diff --git a/benchmark/control_service.py b/benchmark/control_service.py index b81bc78fbe..525f802294 100644 --- a/benchmark/control_service.py +++ b/benchmark/control_service.py @@ -64,7 +64,7 @@ def finalize_measured_run( request.job_id ) observation_path = ZMQAuxiliaryExecutionParams.from_transport( - completed.submission.config_params + completed.request.config_params ).runtime_observation_export_path if observation_path is None: raise ValueError("Completed job has no runtime observation export.") @@ -91,12 +91,12 @@ def finalize_measured_run( seconds=execution_seconds, ) return retain_measured_openhcs_completion( - submission=completed.submission, + request=completed.request, execution_id=record.execution_id, results_summary=record.results_summary, endpoint_provenance=measured_endpoint_provenance(completed.endpoint), phase_timing=phase_timing, - compile_artifact_id=completed.submission.compile_artifact_id, + compile_artifact_id=completed.request.compile_control.compile_artifact_id, ).receipt def discover_cases( diff --git a/benchmark/openhcs_measured_run.py b/benchmark/openhcs_measured_run.py index 46db6511a7..8585e9f564 100644 --- a/benchmark/openhcs_measured_run.py +++ b/benchmark/openhcs_measured_run.py @@ -16,7 +16,7 @@ from typing import Any from zmqruntime import DataControlPortPairAuthority -from zmqruntime.messages import ExecutionStatusSnapshot, PongResponse +from zmqruntime.messages import PongResponse from benchmark.contracts.measured_run_receipt import ( MEASURED_PIPELINE_RUN_RECEIPT_SCHEMA_VERSION, @@ -29,8 +29,6 @@ ) from benchmark.contracts.tool_adapter import ToolExecutionError from benchmark.file_digest import sha256_file -from openhcs.core.config import GlobalPipelineConfig -from openhcs.core.config_document import ConfigDocumentAuthority from openhcs.core.execution_state import ExecutionOutputPlateSummary from openhcs.core.runtime_execution_validation import ( RuntimeArtifactExecutionObservation, @@ -38,6 +36,7 @@ from openhcs.runtime.zmq_application import OPENHCS_ENDPOINT_APPLICATION from openhcs.runtime.zmq_config import OPENHCS_ZMQ_CONFIG from openhcs.runtime.zmq_execution_client import ( + ZMQExecutionRequestBuilder, OpenHCSExecutionSubmission, ZMQExecutionClient, ZMQPipelineRunPhase, @@ -230,25 +229,6 @@ def progress_description(self) -> str: return f"{self.last_progress_phase}/{self.last_progress_status}" -def _completed_server_job_seconds( - client: ZMQExecutionClient, execution_id: str -) -> float: - """Read an ordinary completed job's authoritative server time bounds.""" - - snapshot = ExecutionStatusSnapshot.from_dict(client.poll_status(execution_id)) - record = snapshot.execution - if record is None: - raise ToolExecutionError( - f"Completed OpenHCS job {execution_id!r} has no valid server time bounds." - ) - try: - return completed_server_execution_seconds( - record, expected_execution_id=execution_id - ) - except ValueError as exc: - raise ToolExecutionError(str(exc)) from exc - - def _require_measured_submission( submission: OpenHCSExecutionSubmission, expected_axis_count: int | None, @@ -342,18 +322,25 @@ def execute_measured_openhcs_pipeline_on_client( ) except RuntimeError as exc: raise ToolExecutionError(str(exc)) from exc - phase_timing.record( - BenchmarkPhase.SERVER_COMPILATION_JOB, - seconds=_completed_server_job_seconds(client, run.compile_artifact_id), - ) - phase_timing.record( - BenchmarkPhase.SERVER_PIPELINE_JOB, - seconds=_completed_server_job_seconds(client, run.execution_id), - ) + try: + phase_timing.record( + BenchmarkPhase.SERVER_COMPILATION_JOB, + seconds=completed_server_execution_seconds( + run.compile_record, expected_execution_id=run.compile_artifact_id + ), + ) + phase_timing.record( + BenchmarkPhase.SERVER_PIPELINE_JOB, + seconds=completed_server_execution_seconds( + run.execution_record, expected_execution_id=run.execution_id + ), + ) + except ValueError as exc: + raise ToolExecutionError(str(exc)) from exc timing_observer.record_phase_timings(phase_timing) return ( retain_measured_openhcs_completion( - submission=submission, + request=run.request, execution_id=run.execution_id, results_summary=run.results_summary, endpoint_provenance=endpoint_provenance, @@ -361,13 +348,13 @@ def execute_measured_openhcs_pipeline_on_client( compile_artifact_id=run.compile_artifact_id, expected_axis_count=expected_axis_count, ), - submission.pipeline_code(), + run.request.pipeline_code, ) def retain_measured_openhcs_completion( *, - submission: OpenHCSExecutionSubmission, + request: ZMQExecutionRequestBuilder, execution_id: str, results_summary: Mapping[str, Any], endpoint_provenance: MeasuredEndpointProvenance, @@ -380,7 +367,7 @@ def retain_measured_openhcs_completion( if expected_axis_count is not None and expected_axis_count < 1: raise ValueError("Expected axis count must be positive when declared.") auxiliary_params = ZMQAuxiliaryExecutionParams.from_transport( - submission.config_params + request.config_params ) observation_export_path = auxiliary_params.runtime_observation_export_path if observation_export_path is None: @@ -443,11 +430,8 @@ def retain_measured_openhcs_completion( ) artifact_root = observation_export_path.parent output_roots = tuple(Path(root) for root in observation_export.output_roots) - pipeline_source = submission.pipeline_code() - global_config_source = ConfigDocumentAuthority.render( - submission.global_pipeline_config, - expected_config_type=GlobalPipelineConfig, - ) + pipeline_source = request.pipeline_code + global_config_source = request.global_config_code results_summary_path = MeasuredPipelineRunArtifact.RESULTS_SUMMARY.path_in( artifact_root ) @@ -465,9 +449,9 @@ def retain_measured_openhcs_completion( schema_version=MEASURED_PIPELINE_RUN_RECEIPT_SCHEMA_VERSION, run_id=phase_timing.run_id, pipeline_name=phase_timing.pipeline_name, - plate_id=submission.plate_id, - execution_plate_id=submission.execution_plate_id, - selected_pipeline_path=submission.selected_pipeline_path, + plate_id=request.identity.plate_id, + execution_plate_id=request.identity.execution_plate_id, + selected_pipeline_path=request.identity.selected_pipeline_path, execution_id=execution_id, pipeline_source_sha256=hashlib.sha256( pipeline_source.encode("utf-8") diff --git a/benchmark/reports/cppipe_figures.py b/benchmark/reports/cppipe_figures.py index 02eb7781b5..7ea906b70f 100644 --- a/benchmark/reports/cppipe_figures.py +++ b/benchmark/reports/cppipe_figures.py @@ -1192,7 +1192,7 @@ def _plot_average_speedup_points( alpha=0.86, ) axis.annotate( - "4x target", + f"{SPEEDUP_TARGET:g}x target", xy=(0.995, SPEEDUP_TARGET), xycoords=("axes fraction", "data"), xytext=(-2, 3), @@ -1423,7 +1423,7 @@ def plot_cdf(self, *, log_x: bool) -> tuple[Path, ...]: alpha=0.86, ) axis.annotate( - "4x target", + f"{SPEEDUP_TARGET:g}x target", xy=(SPEEDUP_TARGET, 99.0), xycoords=("data", "data"), xytext=(3, -2), @@ -1626,7 +1626,10 @@ def _draw_reference_lines(axis, *, metric: FigureMetricSpec, log_y: bool) -> Non linestyle="--", alpha=0.86, ) - label = "4x target" if metric.key == SPEEDUP_METRIC_KEY else "target" + label = ( + f"{metric.target_line:g}x target" + if metric.key == SPEEDUP_METRIC_KEY else "target" + ) axis.annotate( label, xy=(0.995, metric.target_line), @@ -1689,7 +1692,7 @@ def _write_benchmark_figure_index(path: Path, outputs: Sequence[Path]) -> None: "- `cppipe_accuracy_zoom.*`: broken-axis parity view for tiny numeric drift near 100%.", "- `cppipe_raw_seconds.*`: single-thread execution runtime in seconds.", "- `cppipe_raw_seconds_log.*`: runtime on a log scale for mixed short and long pipelines.", - "- `cppipe_speedup.*`: execution speedup versus native CellProfiler with the 4x target line.", + f"- `cppipe_speedup.*`: execution speedup versus native CellProfiler with the {SPEEDUP_TARGET:g}x target line.", "- `cppipe_speedup_log.*`: speedup on a log scale for wide dynamic range.", "- `cppipe_speedup_summary_statistics.*`: min, max, median, and mean speedup tables.", "- `cppipe_speedup_cumulative_distribution.*`: percent of datasets at or above each speedup threshold.", diff --git a/benchmark/results/perf_canonical_output_policy_paired_20261003/README.md b/benchmark/results/perf_canonical_output_policy_paired_20261003/README.md new file mode 100644 index 0000000000..8af72cfe58 --- /dev/null +++ b/benchmark/results/perf_canonical_output_policy_paired_20261003/README.md @@ -0,0 +1,10 @@ +The output-policy correctness fix is merged in [PR #531](https://github.com/OpenHCSDev/openhcs/pull/531), closing #530. These fresh observations use performance source `ee8f97552b349499655bb3f961860b34dc784071`, synced with main `ba7b26b82`. Existing environments and the public ordinary/native drivers were reused; both repetitions are retained. Full strict saved-output comparisons pass for all eight ordinary/native pairings, including exact 3D images. + +| Pipeline | Compile | OH execution | OH total | Native CP invocation | Execution speedup | Total speedup | +| --- | ---: | ---: | ---: | ---: | ---: | ---: | +| 3D Monolayer | 1.176 s | 8.994 s | 10.974 s | 14.317 s | 1.592× | 1.305× | +| Speckles | 0.498 s | 1.261 s | 2.091 s | 2.081 s | 1.650× | 0.995× | + +Means use both measured observations. Ordinary 3D execution spans 8.562–9.425 s; the earlier qualified mean was 9.127 s. These separate two-repeat observations do not establish a causal speedup. The remaining 2× execution gap is 1.835 s, so the larger generic source/context/publication work remains necessary. Seven corrected CP groups preserve their input instead of producing anonymous image replacements; this is an architectural dependency, not completion of the performance target. + +Server startup, mandatory library/kernel readiness, shutdown and native imports/JVM/loading/full warmup precede or follow pipeline clocks. Ordinary total includes compilation and default OUTCOMES/RSS completion. This is a two-case preview; full30 and scaling figures remain unfinished. Figures use the existing `benchmark.reports.cppipe_figures` owner with a 2× reference. `timing_summary.json`, raw CSVs, native reports, strict science and `qualification.json` retain determining evidence. diff --git a/benchmark/results/perf_canonical_output_policy_paired_20261003/matched_runtime.png b/benchmark/results/perf_canonical_output_policy_paired_20261003/matched_runtime.png new file mode 100644 index 0000000000..6f2c78a216 Binary files /dev/null and b/benchmark/results/perf_canonical_output_policy_paired_20261003/matched_runtime.png differ diff --git a/benchmark/results/perf_canonical_output_policy_paired_20261003/matched_runtime.svg b/benchmark/results/perf_canonical_output_policy_paired_20261003/matched_runtime.svg new file mode 100644 index 0000000000..d5f4127026 --- /dev/null +++ b/benchmark/results/perf_canonical_output_policy_paired_20261003/matched_runtime.svg @@ -0,0 +1,1615 @@ + + + + + + + + 2026-10-03T08:23:14.895814 + image/svg+xml + + + Matplotlib v3.11.2, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/benchmark/results/perf_canonical_output_policy_paired_20261003/matched_speedup.png b/benchmark/results/perf_canonical_output_policy_paired_20261003/matched_speedup.png new file mode 100644 index 0000000000..c3a5e28898 Binary files /dev/null and b/benchmark/results/perf_canonical_output_policy_paired_20261003/matched_speedup.png differ diff --git a/benchmark/results/perf_canonical_output_policy_paired_20261003/matched_speedup.svg b/benchmark/results/perf_canonical_output_policy_paired_20261003/matched_speedup.svg new file mode 100644 index 0000000000..ac83fa03f4 --- /dev/null +++ b/benchmark/results/perf_canonical_output_policy_paired_20261003/matched_speedup.svg @@ -0,0 +1,1683 @@ + + + + + + + + 2026-10-03T08:23:15.216782 + image/svg+xml + + + Matplotlib v3.11.2, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/benchmark/results/perf_canonical_output_policy_paired_20261003/metrics.csv b/benchmark/results/perf_canonical_output_policy_paired_20261003/metrics.csv new file mode 100644 index 0000000000..abe4cc44c0 --- /dev/null +++ b/benchmark/results/perf_canonical_output_policy_paired_20261003/metrics.csv @@ -0,0 +1,7 @@ +pipeline_name,method,assay_category,module_category,accuracy_fraction,raw_seconds,speedup,peak_memory_mb +ExampleSpeckles,CellProfiler,,,1.0,2.0807363979984075,1.0, +ExampleSpeckles,OH execution,,,1.0,1.2607016563415527,1.6504590023594676, +ExampleSpeckles,OH total,,,1.0,2.0908219020348042,0.9951762969258254, +cp_tutorial_3d_monolayer,CellProfiler,,,1.0,14.316878200042993,1.0, +cp_tutorial_3d_monolayer,OH execution,,,1.0,8.993741154670715,1.59187127512646, +cp_tutorial_3d_monolayer,OH total,,,1.0,10.973736244486645,1.304649381129056, diff --git a/benchmark/results/perf_canonical_output_policy_paired_20261003/native-3d.json b/benchmark/results/perf_canonical_output_policy_paired_20261003/native-3d.json new file mode 100644 index 0000000000..93f685e587 --- /dev/null +++ b/benchmark/results/perf_canonical_output_policy_paired_20261003/native-3d.json @@ -0,0 +1,61 @@ +{ + "startup_seconds": 0.9386979886330664, + "environment": { + "python_executable": "/home/ts/code/projects/openhcs/.venv-cellprofiler39/bin/python", + "python_version": "3.9.25", + "cellprofiler_version": "4.2.8.1", + "cellprofiler_core_version": "4.2.8.1", + "numpy_version": "1.24.4", + "scipy_version": "1.9.0", + "temporary_root": "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/native/cp_tutorial_3d_monolayer/native_tmp" + }, + "request": { + "pipeline_path": "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/native/cp_tutorial_3d_monolayer/preparation/native_cellprofiler_headless/3d_monolayer_final.cppipe", + "input_dir": "/home/ts/.cache/openhcs/benchmark_datasets/CellProfiler_tutorials/data/3d_monolayer/images", + "output_root": "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/native/cp_tutorial_3d_monolayer/outputs", + "expected_image_sets": 1, + "repetitions": 2, + "file_list_path": "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/native/cp_tutorial_3d_monolayer/preparation/native_cellprofiler_file_list.txt", + "first_image_set": 1, + "last_image_set": null, + "report_path": "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/native/cp_tutorial_3d_monolayer/native_report.json", + "start_barrier_root": null, + "start_barrier_job_count": 1, + "start_barrier_job_index": 0 + }, + "observations": [ + { + "repetition": -1, + "output_root": "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/native/cp_tutorial_3d_monolayer/outputs/-1", + "image_set_count": 1, + "invocation_seconds": 17.944316200912, + "pre_first_module_seconds": 0.4406569520942867, + "first_module_through_post_run_seconds": 17.503659248817712, + "invocation_started_monotonic_seconds": 3824476.422337898, + "first_module_started_monotonic_seconds": 3824476.86299485, + "completed_monotonic_seconds": 3824494.366654099 + }, + { + "repetition": 0, + "output_root": "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/native/cp_tutorial_3d_monolayer/outputs/0", + "image_set_count": 1, + "invocation_seconds": 14.412360650952905, + "pre_first_module_seconds": 0.13050647964701056, + "first_module_through_post_run_seconds": 14.281854171305895, + "invocation_started_monotonic_seconds": 3824494.366666422, + "first_module_started_monotonic_seconds": 3824494.497172902, + "completed_monotonic_seconds": 3824508.779027073 + }, + { + "repetition": 1, + "output_root": "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/native/cp_tutorial_3d_monolayer/outputs/1", + "image_set_count": 1, + "invocation_seconds": 14.22139574913308, + "pre_first_module_seconds": 0.1260765721090138, + "first_module_through_post_run_seconds": 14.095319177024066, + "invocation_started_monotonic_seconds": 3824508.779039567, + "first_module_started_monotonic_seconds": 3824508.905116139, + "completed_monotonic_seconds": 3824523.000435316 + } + ] +} \ No newline at end of file diff --git a/benchmark/results/perf_canonical_output_policy_paired_20261003/native-speckles.json b/benchmark/results/perf_canonical_output_policy_paired_20261003/native-speckles.json new file mode 100644 index 0000000000..73edb31d11 --- /dev/null +++ b/benchmark/results/perf_canonical_output_policy_paired_20261003/native-speckles.json @@ -0,0 +1,61 @@ +{ + "startup_seconds": 0.8837718777358532, + "environment": { + "python_executable": "/home/ts/code/projects/openhcs/.venv-cellprofiler39/bin/python", + "python_version": "3.9.25", + "cellprofiler_version": "4.2.8.1", + "cellprofiler_core_version": "4.2.8.1", + "numpy_version": "1.24.4", + "scipy_version": "1.9.0", + "temporary_root": "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/native/ExampleSpeckles/native_tmp" + }, + "request": { + "pipeline_path": "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/native/ExampleSpeckles/preparation/native_cellprofiler_headless/ExampleSpeckles.cppipe", + "input_dir": "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleSpeckles/images", + "output_root": "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/native/ExampleSpeckles/outputs", + "expected_image_sets": 1, + "repetitions": 2, + "file_list_path": "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/native/ExampleSpeckles/preparation/native_cellprofiler_file_list.txt", + "first_image_set": 1, + "last_image_set": null, + "report_path": "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/native/ExampleSpeckles/native_report.json", + "start_barrier_root": null, + "start_barrier_job_count": 1, + "start_barrier_job_index": 0 + }, + "observations": [ + { + "repetition": -1, + "output_root": "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/native/ExampleSpeckles/outputs/-1", + "image_set_count": 1, + "invocation_seconds": 3.3815025235526264, + "pre_first_module_seconds": 0.3202133346349001, + "first_module_through_post_run_seconds": 3.0612891889177263, + "invocation_started_monotonic_seconds": 3824531.358826258, + "first_module_started_monotonic_seconds": 3824531.679039593, + "completed_monotonic_seconds": 3824534.740328782 + }, + { + "repetition": 0, + "output_root": "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/native/ExampleSpeckles/outputs/0", + "image_set_count": 1, + "invocation_seconds": 2.0799103030003607, + "pre_first_module_seconds": 0.09814976202324033, + "first_module_through_post_run_seconds": 1.9817605409771204, + "invocation_started_monotonic_seconds": 3824534.740341355, + "first_module_started_monotonic_seconds": 3824534.838491117, + "completed_monotonic_seconds": 3824536.820251658 + }, + { + "repetition": 1, + "output_root": "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/native/ExampleSpeckles/outputs/1", + "image_set_count": 1, + "invocation_seconds": 2.0815624929964542, + "pre_first_module_seconds": 0.08911933470517397, + "first_module_through_post_run_seconds": 1.9924431582912803, + "invocation_started_monotonic_seconds": 3824536.820261787, + "first_module_started_monotonic_seconds": 3824536.909381122, + "completed_monotonic_seconds": 3824538.90182428 + } + ] +} \ No newline at end of file diff --git a/benchmark/results/perf_canonical_output_policy_paired_20261003/ordinary-0.csv b/benchmark/results/perf_canonical_output_policy_paired_20261003/ordinary-0.csv new file mode 100644 index 0000000000..fffd9799b5 --- /dev/null +++ b/benchmark/results/perf_canonical_output_policy_paired_20261003/ordinary-0.csv @@ -0,0 +1,3 @@ +case_name,mode_name,worker_count,well_count,compile_seconds,prepare_seconds,execute_seconds,total_seconds,wells_per_second,successful_wells,native_single_sample_execution_seconds,projected_native_execution_seconds,projected_execution_speedup,peak_memory_mb,status,memory_limit_mb,error_message,execution_route,server_lifecycle,run_input_sha256 +ExampleSpeckles,1w_1t,1,1,0.49239587783813477,0.0,1.2073335647583008,2.052078391890973,0.8282715143434222,1,,,,1127.01953125,success,,,ordinary-zmq-outcomes-v1,reused-per-sweep,792cfd9b4ac0e6ac65e68c15b2b94f814e085c26535b1db92b2201e640aa2b3c +cp_tutorial_3d_monolayer,1w_1t,1,1,1.1534233093261719,0.0,8.562227010726929,10.547500064130872,0.11679204472705292,1,,,,1699.5234375,success,,,ordinary-zmq-outcomes-v1,reused-per-sweep,792cfd9b4ac0e6ac65e68c15b2b94f814e085c26535b1db92b2201e640aa2b3c diff --git a/benchmark/results/perf_canonical_output_policy_paired_20261003/ordinary-1.csv b/benchmark/results/perf_canonical_output_policy_paired_20261003/ordinary-1.csv new file mode 100644 index 0000000000..36e4c442c7 --- /dev/null +++ b/benchmark/results/perf_canonical_output_policy_paired_20261003/ordinary-1.csv @@ -0,0 +1,3 @@ +case_name,mode_name,worker_count,well_count,compile_seconds,prepare_seconds,execute_seconds,total_seconds,wells_per_second,successful_wells,native_single_sample_execution_seconds,projected_native_execution_seconds,projected_execution_speedup,peak_memory_mb,status,memory_limit_mb,error_message,execution_route,server_lifecycle,run_input_sha256 +ExampleSpeckles,1w_1t,1,1,0.5033345222473145,0.0,1.3140697479248047,2.1295654121786356,0.7609946135501654,1,,,,1128.2734375,success,,,ordinary-zmq-outcomes-v1,reused-per-sweep,792cfd9b4ac0e6ac65e68c15b2b94f814e085c26535b1db92b2201e640aa2b3c +cp_tutorial_3d_monolayer,1w_1t,1,1,1.1986286640167236,0.0,9.425255298614502,11.399972424842417,0.10609792184058914,1,,,,1696.55859375,success,,,ordinary-zmq-outcomes-v1,reused-per-sweep,792cfd9b4ac0e6ac65e68c15b2b94f814e085c26535b1db92b2201e640aa2b3c diff --git a/benchmark/results/perf_canonical_output_policy_paired_20261003/qualification.json b/benchmark/results/perf_canonical_output_policy_paired_20261003/qualification.json new file mode 100644 index 0000000000..6b82571e1b --- /dev/null +++ b/benchmark/results/perf_canonical_output_policy_paired_20261003/qualification.json @@ -0,0 +1,16 @@ +{ + "source_head": "ee8f97552b349499655bb3f961860b34dc784071", + "main_merge": "ba7b26b82717a7bc4de5c9701b413aa64ba13e35", + "fix_pr": "https://github.com/OpenHCSDev/openhcs/pull/531", + "closed_issue": 530, + "focused_main_tests_passed": 381, + "preexisting_shape_test_failures": 5, + "preexisting_failures_reproduced_on_unmodified_main": "6afc9a32514a204424d74527092ea318bc1cdd5e", + "freeze_path": "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/source-freeze.json", + "freeze_sha256": "1aaf1ce6405470eafe86a07db009d0477d55b8b8e2dbf0e8227b9be4e345ffba", + "nra_census_path": "/tmp/openhcs-source-cohort-5af63/policy-family-current-census-v2.json", + "nra_census_sha256": "91849adb21adacacd055a0c1a52b32c71cd58b4443916639fc38d6e6c4348f9c", + "science": "PASS: eight full ordinary/native comparisons", + "remaining_2x_execution_gap_3d_seconds": 1.835302054649219, + "performance_decision": "No causal gain admitted from two descriptive observations; joined dominant plumbing optimization remains active." +} diff --git a/benchmark/results/perf_canonical_output_policy_paired_20261003/strict-science.json b/benchmark/results/perf_canonical_output_policy_paired_20261003/strict-science.json new file mode 100644 index 0000000000..a69926264a --- /dev/null +++ b/benchmark/results/perf_canonical_output_policy_paired_20261003/strict-science.json @@ -0,0 +1,795 @@ +{ + "status": "PASS", + "comparisons": [ + { + "case": "cp_tutorial_3d_monolayer", + "ordinary_repeat": 0, + "native_repeat": 0, + "measurement_differences": 0, + "image_differences": 0, + "tables": [ + 7, + 6 + ], + "physical_images": [ + 2, + 120 + ], + "logical_images": [ + 2, + 2 + ], + "known_relationship_keys": [ + 3, + 3 + ], + "ordinary_receipt_sha256": "5f5119a8aa87e7e54f904ad9d0975810628363202e3dcbbe6f6bb138ce02fc02", + "output_hashes": { + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/native/cp_tutorial_3d_monolayer/outputs/0/3d_monolayer_erodedDownsizedNuclei.csv": "527a0cce497d2a618478be84d1a0bf174049f58aa2a666e37626a990fdca0116", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/native/cp_tutorial_3d_monolayer/outputs/0/3d_monolayer_xy1_ch2_NucleiLabels.tiff": "340bbd795541e4031749d1fff767fa4fcdcac10f5b97879056b25dac9fd7674b", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/native/cp_tutorial_3d_monolayer/outputs/0/3d_monolayer_Image.csv": "6612d34808f8d9904e801d7da5d5ef480912dc89c024548b48825c1b933f4d48", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/native/cp_tutorial_3d_monolayer/outputs/0/3d_monolayer_downsizedNuclei.csv": "2c66bc7b17de52147d5a875403f9a9746019ac61371c08157979044c6ed818dd", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/native/cp_tutorial_3d_monolayer/outputs/0/3d_monolayer_xy1_ch0_CellsLabels.tiff": "aaed9ed23179a162ee7f5a7e8d1d88f1fa342ca55172b7fccd4cbf67f7841d81", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/native/cp_tutorial_3d_monolayer/outputs/0/3d_monolayer_erodedResizedNuclei.csv": "66a58f78cab0cfdbe907468e8ba383fc59fab49025b84b589855bdfa04854609", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/native/cp_tutorial_3d_monolayer/outputs/0/3d_monolayer_Experiment.csv": "774bdd516b093073e8230071241a5e447a7e1e7ad5354f1d5c79878d07318f9a", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/native/cp_tutorial_3d_monolayer/outputs/0/3d_monolayer_Nuclei.csv": "440c33edc7e8cb5611910a835454db62390301a7af617a542349f60aece57561", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/native/cp_tutorial_3d_monolayer/outputs/0/3d_monolayer_Cells.csv": "cc34681db8a66c38ca77bc47db496b26703f21e4d7c7628dd74e30c33250859f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z041_t001_NucleiLabels.tiff": "744eab7cd170d5af8d2f72ced3893dd939c4e1b0f415afab799a37ded5d046c7", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z014_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z012_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z032_t001_CellsLabels.tiff": "8a2c5774044326ae722e41aae517266197fbebb0e4dd5eab4b22414fbfea309f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z004_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z018_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z019_t001_NucleiLabels.tiff": "250cb56a8054c28cea894bc3d9edaddcdce01f5151a05da78da20157c3c3be9f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z051_t001_CellsLabels.tiff": "73483bd10a0f37990084013ad054768086d6d3c929da6bc7e74f4aee37e9dbf2", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z052_t001_NucleiLabels.tiff": "0daf51526658e23b7c9ab8872e992ebe9322399286f95741d0ccdbd357e5d631", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/results/3d_monolayer_downsizedNuclei.csv": "a7b998c5a524e11747fc5452fd763fc3d9abe16f46e961f62e09e9393b6a8adf", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z043_t001_CellsLabels.tiff": "bd0df007524ea4e555e4d2fdbebe6a274caa03bc360a1cf90d601659155984b2", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z002_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/results/3d_monolayer_Image.csv": "75ac32ff5ef57bc285ec4eae1c9b501c27a35b486bf35435af5d499d856d34a4", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z021_t001_NucleiLabels.tiff": "71a10b0539f3fc4cba600b275b7e948258c6a435ba33ef522faa0869ac085518", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z034_t001_NucleiLabels.tiff": "08af61857cfb97fd95fcb08d1ce18139ce7087b192044c63452bee533c5b1aa4", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z019_t001_CellsLabels.tiff": "ec6ef1d319f2732c47b06f5cf02775c8cd94540f2f30a6c002f0aace1d317955", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z007_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z025_t001_NucleiLabels.tiff": "9cc33676a0177130609ab1331feab1722bbde8d55b2f49031730fd5a2a40029c", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z053_t001_CellsLabels.tiff": "ff17f538baaf179752412026a250bdbee016e3101037bf4e0dbb81199fc4c8ed", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z034_t001_CellsLabels.tiff": "3f6c1d8cdbce20aac8f70e7315bea70b147b7b6a034432845b27eeb6cfba083c", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z005_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z056_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z049_t001_CellsLabels.tiff": "28d83dfbf5bbf7e4da9c3e4806353e9fd0a89680dcdab4b43ca2fd19b80f669c", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z010_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z020_t001_NucleiLabels.tiff": "b0cd031b448d8bd2075e65710bd76c064161b25242f85ee150da7cd139fcc1a8", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z030_t001_CellsLabels.tiff": "b71a2e05d270ae0cd237d6c0d97ea82a63e5ad3633723e7255c35d34e585ec80", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z042_t001_CellsLabels.tiff": "88d2e9964455459499656c4f0a762cd86376c678756635aaa6b6c8d98be01852", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z059_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z013_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z008_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z051_t001_NucleiLabels.tiff": "f0f36ccaf744d42da036948682cfd226e6dd4a3cfb94aed38729b2d25ede5dff", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z050_t001_NucleiLabels.tiff": "565b4f08f7503086c1f2f8e631d19063129e02a5767d2f979c0cec8fdec23601", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z049_t001_NucleiLabels.tiff": "e92e493078672a0e0d90e31409612e215bf8486300d5c765d0e0504ff8888e7a", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/openhcs_metadata.json.lock": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/openhcs_metadata.json": "a0c2ccfa41ea6ec88bdc04143a144355f469b41a83caed2e71288662ff2b17ca", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z052_t001_CellsLabels.tiff": "7bb98f0587062e01b965e486fc687872651d7d90d271a2fdf0d35d67b464b233", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z035_t001_NucleiLabels.tiff": "13e69afc324152bb91329fa758d131d849127e8fd346078d94c6adc25582b3a6", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z009_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z029_t001_CellsLabels.tiff": "b3bdde5f751b8f5d41ca8b5219a3427e450cb1b8795401d0ec638940d1ad7bd9", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z056_t001_NucleiLabels.tiff": "ca0723c8b9764d5b77034719bb75a2940be35da2e04119af4c0e6d3552c08718", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z039_t001_NucleiLabels.tiff": "f93e8293a37886a36844b8748083a1f8e717efab092652755263e797f12f0364", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z013_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z047_t001_NucleiLabels.tiff": "995d5ce77cbf61a9be8590f34987ef3f1dd698ae6ed393cac4d0960bc9e7a66a", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z050_t001_CellsLabels.tiff": "ea7654a6fe1f92ad274a54935420923eec4bec5ad030187afc0ac7af02690af5", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/results/3d_monolayer_erodedResizedNuclei.csv": "cca23f86a85bb3ee7a5c3a1d174c34b5f026ca7f399be98458e1a8c6e12d5c77", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z029_t001_NucleiLabels.tiff": "34bce0f06f674e20667554eed0075fde8d9d33c9c0eaeffd88a1c558499cc432", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z022_t001_CellsLabels.tiff": "7d7ec170ed3652efa99e43d8db546c51b696821dca7727d0ff4d2f2ead7fdbaa", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z007_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z004_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z001_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z012_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z037_t001_CellsLabels.tiff": "aa1f449f1769b27cd9f1076e70f49f0242e2549f288a77984ca159cb07cf6a40", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z046_t001_CellsLabels.tiff": "dc081df050be6cd19b5d5bbfe21c96c350eecf9bc6f10f608dc361a36056632a", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z031_t001_CellsLabels.tiff": "1b14aab71bf3623458ea9373852b0baf28be9727877b32f894407927ecfb6d65", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z044_t001_NucleiLabels.tiff": "a78264f2f5e245a3913a69f89105e94df30048b1aaef4eb80fc5c3235e78b196", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z033_t001_NucleiLabels.tiff": "512a3a0ed8025d14b0556a72ebfc13b173d14f7046817ca09876242ab63b9d6b", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z042_t001_NucleiLabels.tiff": "e07252ca1a55c5195c99666d8d3f0d70db636b4ef4b99e1a0049ca22b182d87a", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/results/3d_monolayer_Nuclei.csv": "17500f5d4321bbf255df31f7a3503339029c2b077045a6c10e4d4f6f0db9ad1e", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z046_t001_NucleiLabels.tiff": "c1250e060d32f2cfc07fc7e1594fdb1d6cbb4d0483fa94a8113efa695397963c", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z032_t001_NucleiLabels.tiff": "97b09fe5444ad439c3c2007d75971dce2766d94c93268eccfee9ae49b8a04aa1", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z028_t001_CellsLabels.tiff": "fef31040e0c54501c3bf965eb98f055cdb1d42c96f91cf1c239033d0a9a06534", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z045_t001_CellsLabels.tiff": "c678f2100c7431e5a43c391af86a79e3436d4cf13f050f98c25f62682e4632fe", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z058_t001_NucleiLabels.tiff": "a37c63c6052e40d73db918a014e6f2a18be4d0cbfbeeef65a9c26096a38a4c09", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z060_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z028_t001_NucleiLabels.tiff": "1676f21bd3b7e105601c83f206890507c32ba2447988be2a75d0e8153d069b65", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z027_t001_CellsLabels.tiff": "ee9056587a19e581f5feb6078b41fa1004d923a5ddf1725aefc4b8b8c5201ad6", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z020_t001_CellsLabels.tiff": "e8105a4f04198ac75de9831247030084d6f65bf98691d7444ead7e178072fa22", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z033_t001_CellsLabels.tiff": "a320b99ee129d97b99f9fac66aabb89fc1652930b3bb8b2b3fbba7b57e994f85", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z055_t001_NucleiLabels.tiff": "44e02416cc94a70528165a4b6c42b9e19b205f9c91528076796272cb1a8504ea", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z059_t001_NucleiLabels.tiff": "76c785cf0f481c73ad3cf34ccb576eaa19dd1bdd9c74f9eaf92adfbde5d44b97", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z024_t001_NucleiLabels.tiff": "9e96a05ed9860cac9c57c618db2f4fe5e4b769a9d235aac6fd1d628486317df0", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/results/3d_monolayer_Cells.csv": "6f6e7431171ed5ea73a01784105147eca0e43a6e3e41f8720df93106353c9c79", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z037_t001_NucleiLabels.tiff": "927d52441c57cb3a4014effaca3e3c23c76275fb264c26e1942a9c58b85ee6d2", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z003_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z023_t001_NucleiLabels.tiff": "ecb7f78c8ca0bad2b9d0495659609b9023781b6a936d6afb0a04653eac176555", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z011_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z040_t001_CellsLabels.tiff": "1635ea20dd80ce99f0e86494666825a52a66645837d598fd3a3fa91f0bb77d53", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z017_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z035_t001_CellsLabels.tiff": "eedeb489b46abf1eafbd9c81491cb3f85ce1cb3ce877844ad22e72547fc3c438", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z027_t001_NucleiLabels.tiff": "8c8f402d3a7c65c04e7f1575dd34de0427eeeb433ff2956d20e07d06eb48fb8d", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z016_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z002_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z023_t001_CellsLabels.tiff": "2f06989618050934c73473f9342c2fe3410fd834a0ddb976cf602fe6198db7a6", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z001_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z060_t001_NucleiLabels.tiff": "7cc3c6c6a22f558e62194277090bdea2deb79475dd91fe7d0e49eac3c0187388", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z026_t001_NucleiLabels.tiff": "ad22809ff3f43d15c838f697061c263070dbf1da1031da39900681cdfbf9d54c", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z045_t001_NucleiLabels.tiff": "94bd6a65795ad6395cc18a4fd63dc591354bef612ee49fffd2d9f63e4ed9db84", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z038_t001_CellsLabels.tiff": "6ac8fd9c95acc1f261e96a8fb9332e5d6a403548842f9b85ecb977e6213b4c9b", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z055_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z025_t001_CellsLabels.tiff": "03aabe5528198cfd6ec23a058dab540fb8be0870207c6dc94a62d9b621d1f2f9", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z038_t001_NucleiLabels.tiff": "e2852ea83c62ab30d77681b4e39f88d3cee74ae052f1c948675ae3581c9fc28a", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z015_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z031_t001_NucleiLabels.tiff": "247490c261fecc26c7379ab2eebaa01e4bea523218b3cc5491d2fe2b9aadfe11", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z036_t001_CellsLabels.tiff": "28b68d1300cf7b08e21dbcd4858447862520dded5c27f2d84cf223513a119eed", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z017_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z009_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/results/3d_monolayer_erodedDownsizedNuclei.csv": "ee507fb9c2387f86fc768184baf2596ebe1f8e40f7fc5eb24f252345fee63ae6", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z026_t001_CellsLabels.tiff": "5b433d931fa6637fc793b23880199c01000ef6d9e610903bb38bb8cea5574563", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z048_t001_CellsLabels.tiff": "133a58f6fac8b07f79bfed9634867ccb5428b83e63682031a1def16c6a694568", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z006_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z039_t001_CellsLabels.tiff": "22fa79a76e64013f10373be2ca2af98a2173275c5d43c9cad33135acdc376d14", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z016_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z058_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z018_t001_NucleiLabels.tiff": "03ba7a4d6ae53e6c84aab5926ae1e2592b5f8ca24a839a256c82f08544df4270", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z030_t001_NucleiLabels.tiff": "c54c8b98a5c38a47e0cf9391a1afab09b4c8c58e06294cdb650a15add4a32b58", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z047_t001_CellsLabels.tiff": "b926aa64e1fa8aa52279a69d91dc23cf14bf0ae76107f9b360c7ae77bdf53719", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z054_t001_NucleiLabels.tiff": "b841c5d901c65a6138d9ff2b0ec4aa04f00765b1dd21bcd6fc9f8dc974c6035d", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z044_t001_CellsLabels.tiff": "e03946d94c789ee787cc29a3c8f5e5d9c56b37a0044b297ba8f403abc98eb55e", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z043_t001_NucleiLabels.tiff": "81a705d05b0a5bfa8783df28990c1d70634c1f4aa2bca23e02cfa8a4bc861b86", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z010_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z057_t001_NucleiLabels.tiff": "695517641e9fe4b8421d4a7db56b24c755b6957c98ce32bb24ad5b25f52661eb", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z053_t001_NucleiLabels.tiff": "b8613192175a4615b58aed607474657668429cb6ac635cd012569b19667f2d3d", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z057_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z022_t001_NucleiLabels.tiff": "50aef20e28a2f9e18ca2e28eabf6d87ec2ad20c79898e56f8d63a959ba5bb507", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z005_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z015_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z014_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z021_t001_CellsLabels.tiff": "daa31cb1e537e5c32b1936ab7647c5690741d2bc1d0e15c60b59ba1310a8c0ce", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z040_t001_NucleiLabels.tiff": "e0bd66b166e9f92120dbee183973849eda0afbbe6fed9d03fc4cfd2c56a96280", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z041_t001_CellsLabels.tiff": "be7762756eb65f08cb337904165c6f43b5351f39405461f65ad28669abfe3899", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z008_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z011_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z024_t001_CellsLabels.tiff": "39899adabca74b10b9950d1f97e8b0b3bbaf136d75e7a46ef4a6e86896e3119f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z048_t001_NucleiLabels.tiff": "325478230529e94ba372f38f0bf512292f131d337b6ac09ce5a91b0266724e02", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z036_t001_NucleiLabels.tiff": "4fa967c78709aa400246a50528a36b24ca366e825dd0e64561643369e814906b", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z003_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z054_t001_CellsLabels.tiff": "25ff2ec586a568e42286f73713d64aab1208c38c016099299211f04368ac49c8", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z006_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f" + } + }, + { + "case": "cp_tutorial_3d_monolayer", + "ordinary_repeat": 0, + "native_repeat": 1, + "measurement_differences": 0, + "image_differences": 0, + "tables": [ + 7, + 6 + ], + "physical_images": [ + 2, + 120 + ], + "logical_images": [ + 2, + 2 + ], + "known_relationship_keys": [ + 3, + 3 + ], + "ordinary_receipt_sha256": "5f5119a8aa87e7e54f904ad9d0975810628363202e3dcbbe6f6bb138ce02fc02", + "output_hashes": { + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/native/cp_tutorial_3d_monolayer/outputs/1/3d_monolayer_erodedResizedNuclei.csv": "66a58f78cab0cfdbe907468e8ba383fc59fab49025b84b589855bdfa04854609", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/native/cp_tutorial_3d_monolayer/outputs/1/3d_monolayer_xy1_ch0_CellsLabels.tiff": "aaed9ed23179a162ee7f5a7e8d1d88f1fa342ca55172b7fccd4cbf67f7841d81", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/native/cp_tutorial_3d_monolayer/outputs/1/3d_monolayer_Image.csv": "d775f1b475e2d5f725d30e736f5074301f8f17a1ee72824ad38a659f61d0a184", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/native/cp_tutorial_3d_monolayer/outputs/1/3d_monolayer_Cells.csv": "cc34681db8a66c38ca77bc47db496b26703f21e4d7c7628dd74e30c33250859f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/native/cp_tutorial_3d_monolayer/outputs/1/3d_monolayer_Experiment.csv": "f6b57eaed8c47bd7dfd14bcbaab24b1c2dbd760daaea7fbb9622ec1b1b79307d", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/native/cp_tutorial_3d_monolayer/outputs/1/3d_monolayer_Nuclei.csv": "440c33edc7e8cb5611910a835454db62390301a7af617a542349f60aece57561", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/native/cp_tutorial_3d_monolayer/outputs/1/3d_monolayer_xy1_ch2_NucleiLabels.tiff": "340bbd795541e4031749d1fff767fa4fcdcac10f5b97879056b25dac9fd7674b", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/native/cp_tutorial_3d_monolayer/outputs/1/3d_monolayer_erodedDownsizedNuclei.csv": "527a0cce497d2a618478be84d1a0bf174049f58aa2a666e37626a990fdca0116", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/native/cp_tutorial_3d_monolayer/outputs/1/3d_monolayer_downsizedNuclei.csv": "2c66bc7b17de52147d5a875403f9a9746019ac61371c08157979044c6ed818dd", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z041_t001_NucleiLabels.tiff": "744eab7cd170d5af8d2f72ced3893dd939c4e1b0f415afab799a37ded5d046c7", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z014_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z012_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z032_t001_CellsLabels.tiff": "8a2c5774044326ae722e41aae517266197fbebb0e4dd5eab4b22414fbfea309f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z004_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z018_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z019_t001_NucleiLabels.tiff": "250cb56a8054c28cea894bc3d9edaddcdce01f5151a05da78da20157c3c3be9f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z051_t001_CellsLabels.tiff": "73483bd10a0f37990084013ad054768086d6d3c929da6bc7e74f4aee37e9dbf2", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z052_t001_NucleiLabels.tiff": "0daf51526658e23b7c9ab8872e992ebe9322399286f95741d0ccdbd357e5d631", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/results/3d_monolayer_downsizedNuclei.csv": "a7b998c5a524e11747fc5452fd763fc3d9abe16f46e961f62e09e9393b6a8adf", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z043_t001_CellsLabels.tiff": "bd0df007524ea4e555e4d2fdbebe6a274caa03bc360a1cf90d601659155984b2", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z002_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/results/3d_monolayer_Image.csv": "75ac32ff5ef57bc285ec4eae1c9b501c27a35b486bf35435af5d499d856d34a4", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z021_t001_NucleiLabels.tiff": "71a10b0539f3fc4cba600b275b7e948258c6a435ba33ef522faa0869ac085518", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z034_t001_NucleiLabels.tiff": "08af61857cfb97fd95fcb08d1ce18139ce7087b192044c63452bee533c5b1aa4", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z019_t001_CellsLabels.tiff": "ec6ef1d319f2732c47b06f5cf02775c8cd94540f2f30a6c002f0aace1d317955", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z007_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z025_t001_NucleiLabels.tiff": "9cc33676a0177130609ab1331feab1722bbde8d55b2f49031730fd5a2a40029c", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z053_t001_CellsLabels.tiff": "ff17f538baaf179752412026a250bdbee016e3101037bf4e0dbb81199fc4c8ed", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z034_t001_CellsLabels.tiff": "3f6c1d8cdbce20aac8f70e7315bea70b147b7b6a034432845b27eeb6cfba083c", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z005_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z056_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z049_t001_CellsLabels.tiff": "28d83dfbf5bbf7e4da9c3e4806353e9fd0a89680dcdab4b43ca2fd19b80f669c", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z010_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z020_t001_NucleiLabels.tiff": "b0cd031b448d8bd2075e65710bd76c064161b25242f85ee150da7cd139fcc1a8", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z030_t001_CellsLabels.tiff": "b71a2e05d270ae0cd237d6c0d97ea82a63e5ad3633723e7255c35d34e585ec80", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z042_t001_CellsLabels.tiff": "88d2e9964455459499656c4f0a762cd86376c678756635aaa6b6c8d98be01852", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z059_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z013_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z008_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z051_t001_NucleiLabels.tiff": "f0f36ccaf744d42da036948682cfd226e6dd4a3cfb94aed38729b2d25ede5dff", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z050_t001_NucleiLabels.tiff": "565b4f08f7503086c1f2f8e631d19063129e02a5767d2f979c0cec8fdec23601", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z049_t001_NucleiLabels.tiff": "e92e493078672a0e0d90e31409612e215bf8486300d5c765d0e0504ff8888e7a", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/openhcs_metadata.json.lock": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/openhcs_metadata.json": "a0c2ccfa41ea6ec88bdc04143a144355f469b41a83caed2e71288662ff2b17ca", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z052_t001_CellsLabels.tiff": "7bb98f0587062e01b965e486fc687872651d7d90d271a2fdf0d35d67b464b233", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z035_t001_NucleiLabels.tiff": "13e69afc324152bb91329fa758d131d849127e8fd346078d94c6adc25582b3a6", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z009_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z029_t001_CellsLabels.tiff": "b3bdde5f751b8f5d41ca8b5219a3427e450cb1b8795401d0ec638940d1ad7bd9", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z056_t001_NucleiLabels.tiff": "ca0723c8b9764d5b77034719bb75a2940be35da2e04119af4c0e6d3552c08718", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z039_t001_NucleiLabels.tiff": "f93e8293a37886a36844b8748083a1f8e717efab092652755263e797f12f0364", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z013_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z047_t001_NucleiLabels.tiff": "995d5ce77cbf61a9be8590f34987ef3f1dd698ae6ed393cac4d0960bc9e7a66a", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z050_t001_CellsLabels.tiff": "ea7654a6fe1f92ad274a54935420923eec4bec5ad030187afc0ac7af02690af5", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/results/3d_monolayer_erodedResizedNuclei.csv": "cca23f86a85bb3ee7a5c3a1d174c34b5f026ca7f399be98458e1a8c6e12d5c77", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z029_t001_NucleiLabels.tiff": "34bce0f06f674e20667554eed0075fde8d9d33c9c0eaeffd88a1c558499cc432", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z022_t001_CellsLabels.tiff": "7d7ec170ed3652efa99e43d8db546c51b696821dca7727d0ff4d2f2ead7fdbaa", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z007_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z004_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z001_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z012_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z037_t001_CellsLabels.tiff": "aa1f449f1769b27cd9f1076e70f49f0242e2549f288a77984ca159cb07cf6a40", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z046_t001_CellsLabels.tiff": "dc081df050be6cd19b5d5bbfe21c96c350eecf9bc6f10f608dc361a36056632a", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z031_t001_CellsLabels.tiff": "1b14aab71bf3623458ea9373852b0baf28be9727877b32f894407927ecfb6d65", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z044_t001_NucleiLabels.tiff": "a78264f2f5e245a3913a69f89105e94df30048b1aaef4eb80fc5c3235e78b196", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z033_t001_NucleiLabels.tiff": "512a3a0ed8025d14b0556a72ebfc13b173d14f7046817ca09876242ab63b9d6b", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z042_t001_NucleiLabels.tiff": "e07252ca1a55c5195c99666d8d3f0d70db636b4ef4b99e1a0049ca22b182d87a", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/results/3d_monolayer_Nuclei.csv": "17500f5d4321bbf255df31f7a3503339029c2b077045a6c10e4d4f6f0db9ad1e", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z046_t001_NucleiLabels.tiff": "c1250e060d32f2cfc07fc7e1594fdb1d6cbb4d0483fa94a8113efa695397963c", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z032_t001_NucleiLabels.tiff": "97b09fe5444ad439c3c2007d75971dce2766d94c93268eccfee9ae49b8a04aa1", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z028_t001_CellsLabels.tiff": "fef31040e0c54501c3bf965eb98f055cdb1d42c96f91cf1c239033d0a9a06534", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z045_t001_CellsLabels.tiff": "c678f2100c7431e5a43c391af86a79e3436d4cf13f050f98c25f62682e4632fe", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z058_t001_NucleiLabels.tiff": "a37c63c6052e40d73db918a014e6f2a18be4d0cbfbeeef65a9c26096a38a4c09", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z060_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z028_t001_NucleiLabels.tiff": "1676f21bd3b7e105601c83f206890507c32ba2447988be2a75d0e8153d069b65", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z027_t001_CellsLabels.tiff": "ee9056587a19e581f5feb6078b41fa1004d923a5ddf1725aefc4b8b8c5201ad6", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z020_t001_CellsLabels.tiff": "e8105a4f04198ac75de9831247030084d6f65bf98691d7444ead7e178072fa22", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z033_t001_CellsLabels.tiff": "a320b99ee129d97b99f9fac66aabb89fc1652930b3bb8b2b3fbba7b57e994f85", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z055_t001_NucleiLabels.tiff": "44e02416cc94a70528165a4b6c42b9e19b205f9c91528076796272cb1a8504ea", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z059_t001_NucleiLabels.tiff": "76c785cf0f481c73ad3cf34ccb576eaa19dd1bdd9c74f9eaf92adfbde5d44b97", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z024_t001_NucleiLabels.tiff": "9e96a05ed9860cac9c57c618db2f4fe5e4b769a9d235aac6fd1d628486317df0", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/results/3d_monolayer_Cells.csv": "6f6e7431171ed5ea73a01784105147eca0e43a6e3e41f8720df93106353c9c79", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z037_t001_NucleiLabels.tiff": "927d52441c57cb3a4014effaca3e3c23c76275fb264c26e1942a9c58b85ee6d2", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z003_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z023_t001_NucleiLabels.tiff": "ecb7f78c8ca0bad2b9d0495659609b9023781b6a936d6afb0a04653eac176555", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z011_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z040_t001_CellsLabels.tiff": "1635ea20dd80ce99f0e86494666825a52a66645837d598fd3a3fa91f0bb77d53", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z017_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z035_t001_CellsLabels.tiff": "eedeb489b46abf1eafbd9c81491cb3f85ce1cb3ce877844ad22e72547fc3c438", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z027_t001_NucleiLabels.tiff": "8c8f402d3a7c65c04e7f1575dd34de0427eeeb433ff2956d20e07d06eb48fb8d", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z016_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z002_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z023_t001_CellsLabels.tiff": "2f06989618050934c73473f9342c2fe3410fd834a0ddb976cf602fe6198db7a6", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z001_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z060_t001_NucleiLabels.tiff": "7cc3c6c6a22f558e62194277090bdea2deb79475dd91fe7d0e49eac3c0187388", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z026_t001_NucleiLabels.tiff": "ad22809ff3f43d15c838f697061c263070dbf1da1031da39900681cdfbf9d54c", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z045_t001_NucleiLabels.tiff": "94bd6a65795ad6395cc18a4fd63dc591354bef612ee49fffd2d9f63e4ed9db84", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z038_t001_CellsLabels.tiff": "6ac8fd9c95acc1f261e96a8fb9332e5d6a403548842f9b85ecb977e6213b4c9b", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z055_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z025_t001_CellsLabels.tiff": "03aabe5528198cfd6ec23a058dab540fb8be0870207c6dc94a62d9b621d1f2f9", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z038_t001_NucleiLabels.tiff": "e2852ea83c62ab30d77681b4e39f88d3cee74ae052f1c948675ae3581c9fc28a", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z015_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z031_t001_NucleiLabels.tiff": "247490c261fecc26c7379ab2eebaa01e4bea523218b3cc5491d2fe2b9aadfe11", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z036_t001_CellsLabels.tiff": "28b68d1300cf7b08e21dbcd4858447862520dded5c27f2d84cf223513a119eed", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z017_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z009_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/results/3d_monolayer_erodedDownsizedNuclei.csv": "ee507fb9c2387f86fc768184baf2596ebe1f8e40f7fc5eb24f252345fee63ae6", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z026_t001_CellsLabels.tiff": "5b433d931fa6637fc793b23880199c01000ef6d9e610903bb38bb8cea5574563", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z048_t001_CellsLabels.tiff": "133a58f6fac8b07f79bfed9634867ccb5428b83e63682031a1def16c6a694568", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z006_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z039_t001_CellsLabels.tiff": "22fa79a76e64013f10373be2ca2af98a2173275c5d43c9cad33135acdc376d14", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z016_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z058_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z018_t001_NucleiLabels.tiff": "03ba7a4d6ae53e6c84aab5926ae1e2592b5f8ca24a839a256c82f08544df4270", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z030_t001_NucleiLabels.tiff": "c54c8b98a5c38a47e0cf9391a1afab09b4c8c58e06294cdb650a15add4a32b58", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z047_t001_CellsLabels.tiff": "b926aa64e1fa8aa52279a69d91dc23cf14bf0ae76107f9b360c7ae77bdf53719", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z054_t001_NucleiLabels.tiff": "b841c5d901c65a6138d9ff2b0ec4aa04f00765b1dd21bcd6fc9f8dc974c6035d", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z044_t001_CellsLabels.tiff": "e03946d94c789ee787cc29a3c8f5e5d9c56b37a0044b297ba8f403abc98eb55e", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z043_t001_NucleiLabels.tiff": "81a705d05b0a5bfa8783df28990c1d70634c1f4aa2bca23e02cfa8a4bc861b86", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z010_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z057_t001_NucleiLabels.tiff": "695517641e9fe4b8421d4a7db56b24c755b6957c98ce32bb24ad5b25f52661eb", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z053_t001_NucleiLabels.tiff": "b8613192175a4615b58aed607474657668429cb6ac635cd012569b19667f2d3d", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z057_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z022_t001_NucleiLabels.tiff": "50aef20e28a2f9e18ca2e28eabf6d87ec2ad20c79898e56f8d63a959ba5bb507", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z005_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z015_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z014_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z021_t001_CellsLabels.tiff": "daa31cb1e537e5c32b1936ab7647c5690741d2bc1d0e15c60b59ba1310a8c0ce", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z040_t001_NucleiLabels.tiff": "e0bd66b166e9f92120dbee183973849eda0afbbe6fed9d03fc4cfd2c56a96280", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z041_t001_CellsLabels.tiff": "be7762756eb65f08cb337904165c6f43b5351f39405461f65ad28669abfe3899", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z008_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z011_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z024_t001_CellsLabels.tiff": "39899adabca74b10b9950d1f97e8b0b3bbaf136d75e7a46ef4a6e86896e3119f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z048_t001_NucleiLabels.tiff": "325478230529e94ba372f38f0bf512292f131d337b6ac09ce5a91b0266724e02", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z036_t001_NucleiLabels.tiff": "4fa967c78709aa400246a50528a36b24ca366e825dd0e64561643369e814906b", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z003_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z054_t001_CellsLabels.tiff": "25ff2ec586a568e42286f73713d64aab1208c38c016099299211f04368ac49c8", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z006_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f" + } + }, + { + "case": "ExampleSpeckles", + "ordinary_repeat": 0, + "native_repeat": 0, + "measurement_differences": 0, + "image_differences": 0, + "tables": [ + 3, + 3 + ], + "physical_images": [ + 0, + 0 + ], + "logical_images": [ + 0, + 0 + ], + "known_relationship_keys": [ + 1, + 1 + ], + "ordinary_receipt_sha256": "1ef11d00b7fd5b638b104d9b8be6e03483ed1668465f817fc36905ef2f8b099d", + "output_hashes": { + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/native/ExampleSpeckles/outputs/0/Nuclei.csv": "15af7cac08d651c19b3e3f409b2b0d7fc4f96011c9b53394aa9a35969a8936a6", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/native/ExampleSpeckles/outputs/0/h2ax.csv": "0f54fc72ccdeb7e1a68bab9dc3a8d9d49788cdf81dbbc109ed119e589c09538a", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/native/ExampleSpeckles/outputs/0/Image.csv": "cebe6c0c9ab138ff1f65906b70a130b9e79e3b7d873cc006e88067c596b07a98", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/ExampleSpeckles/wells_1/workers_1/images_ExampleSpeckles_source_workspace_well_throughput/results/Image.csv": "85ef16f24e75f03dc7055215cf2e6cb196b1dc0a0d73713a4c5999f698d4f96e", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/ExampleSpeckles/wells_1/workers_1/images_ExampleSpeckles_source_workspace_well_throughput/results/Nuclei.csv": "e50cb9f8c23f65e9ce8db25132263cf4a4448ed65fc1088d782536abf74c5670", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/ExampleSpeckles/wells_1/workers_1/images_ExampleSpeckles_source_workspace_well_throughput/results/h2ax.csv": "eb453565f3b79ac932eeb5cde8605888b72e58c80f42edbbf0b1ba37f34fd6f8", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/ExampleSpeckles/wells_1/workers_1/images_ExampleSpeckles_source_workspace_well_throughput/openhcs_metadata.json": "71582c62cabb2571ebf8a0de57f92fdf82c55a7ece3dac0bf2a6eca95cad84c9", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/ExampleSpeckles/wells_1/workers_1/images_ExampleSpeckles_source_workspace_well_throughput/openhcs_metadata.json.lock": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + } + }, + { + "case": "ExampleSpeckles", + "ordinary_repeat": 0, + "native_repeat": 1, + "measurement_differences": 0, + "image_differences": 0, + "tables": [ + 3, + 3 + ], + "physical_images": [ + 0, + 0 + ], + "logical_images": [ + 0, + 0 + ], + "known_relationship_keys": [ + 1, + 1 + ], + "ordinary_receipt_sha256": "1ef11d00b7fd5b638b104d9b8be6e03483ed1668465f817fc36905ef2f8b099d", + "output_hashes": { + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/native/ExampleSpeckles/outputs/1/Nuclei.csv": "15af7cac08d651c19b3e3f409b2b0d7fc4f96011c9b53394aa9a35969a8936a6", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/native/ExampleSpeckles/outputs/1/h2ax.csv": "0f54fc72ccdeb7e1a68bab9dc3a8d9d49788cdf81dbbc109ed119e589c09538a", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/native/ExampleSpeckles/outputs/1/Image.csv": "be7bbf5f19c27df330b95c8eb1784e0053a655f84d278d40a9023c1feeb1fbed", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/ExampleSpeckles/wells_1/workers_1/images_ExampleSpeckles_source_workspace_well_throughput/results/Image.csv": "85ef16f24e75f03dc7055215cf2e6cb196b1dc0a0d73713a4c5999f698d4f96e", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/ExampleSpeckles/wells_1/workers_1/images_ExampleSpeckles_source_workspace_well_throughput/results/Nuclei.csv": "e50cb9f8c23f65e9ce8db25132263cf4a4448ed65fc1088d782536abf74c5670", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/ExampleSpeckles/wells_1/workers_1/images_ExampleSpeckles_source_workspace_well_throughput/results/h2ax.csv": "eb453565f3b79ac932eeb5cde8605888b72e58c80f42edbbf0b1ba37f34fd6f8", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/ExampleSpeckles/wells_1/workers_1/images_ExampleSpeckles_source_workspace_well_throughput/openhcs_metadata.json": "71582c62cabb2571ebf8a0de57f92fdf82c55a7ece3dac0bf2a6eca95cad84c9", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-0/ExampleSpeckles/wells_1/workers_1/images_ExampleSpeckles_source_workspace_well_throughput/openhcs_metadata.json.lock": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + } + }, + { + "case": "cp_tutorial_3d_monolayer", + "ordinary_repeat": 1, + "native_repeat": 0, + "measurement_differences": 0, + "image_differences": 0, + "tables": [ + 7, + 6 + ], + "physical_images": [ + 2, + 120 + ], + "logical_images": [ + 2, + 2 + ], + "known_relationship_keys": [ + 3, + 3 + ], + "ordinary_receipt_sha256": "caf9cca665b85734e682f713c153260f8c949fdabd9229f482d6b501964dbac9", + "output_hashes": { + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/native/cp_tutorial_3d_monolayer/outputs/0/3d_monolayer_erodedDownsizedNuclei.csv": "527a0cce497d2a618478be84d1a0bf174049f58aa2a666e37626a990fdca0116", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/native/cp_tutorial_3d_monolayer/outputs/0/3d_monolayer_xy1_ch2_NucleiLabels.tiff": "340bbd795541e4031749d1fff767fa4fcdcac10f5b97879056b25dac9fd7674b", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/native/cp_tutorial_3d_monolayer/outputs/0/3d_monolayer_Image.csv": "6612d34808f8d9904e801d7da5d5ef480912dc89c024548b48825c1b933f4d48", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/native/cp_tutorial_3d_monolayer/outputs/0/3d_monolayer_downsizedNuclei.csv": "2c66bc7b17de52147d5a875403f9a9746019ac61371c08157979044c6ed818dd", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/native/cp_tutorial_3d_monolayer/outputs/0/3d_monolayer_xy1_ch0_CellsLabels.tiff": "aaed9ed23179a162ee7f5a7e8d1d88f1fa342ca55172b7fccd4cbf67f7841d81", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/native/cp_tutorial_3d_monolayer/outputs/0/3d_monolayer_erodedResizedNuclei.csv": "66a58f78cab0cfdbe907468e8ba383fc59fab49025b84b589855bdfa04854609", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/native/cp_tutorial_3d_monolayer/outputs/0/3d_monolayer_Experiment.csv": "774bdd516b093073e8230071241a5e447a7e1e7ad5354f1d5c79878d07318f9a", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/native/cp_tutorial_3d_monolayer/outputs/0/3d_monolayer_Nuclei.csv": "440c33edc7e8cb5611910a835454db62390301a7af617a542349f60aece57561", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/native/cp_tutorial_3d_monolayer/outputs/0/3d_monolayer_Cells.csv": "cc34681db8a66c38ca77bc47db496b26703f21e4d7c7628dd74e30c33250859f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z054_t001_CellsLabels.tiff": "25ff2ec586a568e42286f73713d64aab1208c38c016099299211f04368ac49c8", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z001_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z005_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z013_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z056_t001_NucleiLabels.tiff": "ca0723c8b9764d5b77034719bb75a2940be35da2e04119af4c0e6d3552c08718", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z044_t001_CellsLabels.tiff": "e03946d94c789ee787cc29a3c8f5e5d9c56b37a0044b297ba8f403abc98eb55e", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z002_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z008_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z020_t001_CellsLabels.tiff": "e8105a4f04198ac75de9831247030084d6f65bf98691d7444ead7e178072fa22", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z029_t001_CellsLabels.tiff": "b3bdde5f751b8f5d41ca8b5219a3427e450cb1b8795401d0ec638940d1ad7bd9", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z009_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z014_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z047_t001_CellsLabels.tiff": "b926aa64e1fa8aa52279a69d91dc23cf14bf0ae76107f9b360c7ae77bdf53719", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/results/3d_monolayer_erodedDownsizedNuclei.csv": "ee507fb9c2387f86fc768184baf2596ebe1f8e40f7fc5eb24f252345fee63ae6", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z030_t001_CellsLabels.tiff": "b71a2e05d270ae0cd237d6c0d97ea82a63e5ad3633723e7255c35d34e585ec80", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z040_t001_CellsLabels.tiff": "1635ea20dd80ce99f0e86494666825a52a66645837d598fd3a3fa91f0bb77d53", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z032_t001_NucleiLabels.tiff": "97b09fe5444ad439c3c2007d75971dce2766d94c93268eccfee9ae49b8a04aa1", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z046_t001_NucleiLabels.tiff": "c1250e060d32f2cfc07fc7e1594fdb1d6cbb4d0483fa94a8113efa695397963c", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/results/3d_monolayer_erodedResizedNuclei.csv": "cca23f86a85bb3ee7a5c3a1d174c34b5f026ca7f399be98458e1a8c6e12d5c77", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z044_t001_NucleiLabels.tiff": "a78264f2f5e245a3913a69f89105e94df30048b1aaef4eb80fc5c3235e78b196", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z007_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z045_t001_NucleiLabels.tiff": "94bd6a65795ad6395cc18a4fd63dc591354bef612ee49fffd2d9f63e4ed9db84", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z052_t001_NucleiLabels.tiff": "0daf51526658e23b7c9ab8872e992ebe9322399286f95741d0ccdbd357e5d631", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z043_t001_CellsLabels.tiff": "bd0df007524ea4e555e4d2fdbebe6a274caa03bc360a1cf90d601659155984b2", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z037_t001_NucleiLabels.tiff": "927d52441c57cb3a4014effaca3e3c23c76275fb264c26e1942a9c58b85ee6d2", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z046_t001_CellsLabels.tiff": "dc081df050be6cd19b5d5bbfe21c96c350eecf9bc6f10f608dc361a36056632a", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z055_t001_NucleiLabels.tiff": "44e02416cc94a70528165a4b6c42b9e19b205f9c91528076796272cb1a8504ea", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/results/3d_monolayer_Nuclei.csv": "17500f5d4321bbf255df31f7a3503339029c2b077045a6c10e4d4f6f0db9ad1e", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z048_t001_CellsLabels.tiff": "133a58f6fac8b07f79bfed9634867ccb5428b83e63682031a1def16c6a694568", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z051_t001_CellsLabels.tiff": "73483bd10a0f37990084013ad054768086d6d3c929da6bc7e74f4aee37e9dbf2", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z027_t001_NucleiLabels.tiff": "8c8f402d3a7c65c04e7f1575dd34de0427eeeb433ff2956d20e07d06eb48fb8d", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z055_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z031_t001_NucleiLabels.tiff": "247490c261fecc26c7379ab2eebaa01e4bea523218b3cc5491d2fe2b9aadfe11", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z023_t001_NucleiLabels.tiff": "ecb7f78c8ca0bad2b9d0495659609b9023781b6a936d6afb0a04653eac176555", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z008_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z045_t001_CellsLabels.tiff": "c678f2100c7431e5a43c391af86a79e3436d4cf13f050f98c25f62682e4632fe", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z036_t001_CellsLabels.tiff": "28b68d1300cf7b08e21dbcd4858447862520dded5c27f2d84cf223513a119eed", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z038_t001_NucleiLabels.tiff": "e2852ea83c62ab30d77681b4e39f88d3cee74ae052f1c948675ae3581c9fc28a", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z052_t001_CellsLabels.tiff": "7bb98f0587062e01b965e486fc687872651d7d90d271a2fdf0d35d67b464b233", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z015_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z004_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z001_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z054_t001_NucleiLabels.tiff": "b841c5d901c65a6138d9ff2b0ec4aa04f00765b1dd21bcd6fc9f8dc974c6035d", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z019_t001_NucleiLabels.tiff": "250cb56a8054c28cea894bc3d9edaddcdce01f5151a05da78da20157c3c3be9f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z018_t001_NucleiLabels.tiff": "03ba7a4d6ae53e6c84aab5926ae1e2592b5f8ca24a839a256c82f08544df4270", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z058_t001_NucleiLabels.tiff": "a37c63c6052e40d73db918a014e6f2a18be4d0cbfbeeef65a9c26096a38a4c09", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z057_t001_NucleiLabels.tiff": "695517641e9fe4b8421d4a7db56b24c755b6957c98ce32bb24ad5b25f52661eb", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z032_t001_CellsLabels.tiff": "8a2c5774044326ae722e41aae517266197fbebb0e4dd5eab4b22414fbfea309f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z037_t001_CellsLabels.tiff": "aa1f449f1769b27cd9f1076e70f49f0242e2549f288a77984ca159cb07cf6a40", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z058_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z009_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z053_t001_NucleiLabels.tiff": "b8613192175a4615b58aed607474657668429cb6ac635cd012569b19667f2d3d", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z004_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z031_t001_CellsLabels.tiff": "1b14aab71bf3623458ea9373852b0baf28be9727877b32f894407927ecfb6d65", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z024_t001_CellsLabels.tiff": "39899adabca74b10b9950d1f97e8b0b3bbaf136d75e7a46ef4a6e86896e3119f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z033_t001_CellsLabels.tiff": "a320b99ee129d97b99f9fac66aabb89fc1652930b3bb8b2b3fbba7b57e994f85", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z030_t001_NucleiLabels.tiff": "c54c8b98a5c38a47e0cf9391a1afab09b4c8c58e06294cdb650a15add4a32b58", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z040_t001_NucleiLabels.tiff": "e0bd66b166e9f92120dbee183973849eda0afbbe6fed9d03fc4cfd2c56a96280", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z012_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z035_t001_NucleiLabels.tiff": "13e69afc324152bb91329fa758d131d849127e8fd346078d94c6adc25582b3a6", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z026_t001_CellsLabels.tiff": "5b433d931fa6637fc793b23880199c01000ef6d9e610903bb38bb8cea5574563", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z053_t001_CellsLabels.tiff": "ff17f538baaf179752412026a250bdbee016e3101037bf4e0dbb81199fc4c8ed", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z033_t001_NucleiLabels.tiff": "512a3a0ed8025d14b0556a72ebfc13b173d14f7046817ca09876242ab63b9d6b", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z041_t001_CellsLabels.tiff": "be7762756eb65f08cb337904165c6f43b5351f39405461f65ad28669abfe3899", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z050_t001_CellsLabels.tiff": "ea7654a6fe1f92ad274a54935420923eec4bec5ad030187afc0ac7af02690af5", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z034_t001_NucleiLabels.tiff": "08af61857cfb97fd95fcb08d1ce18139ce7087b192044c63452bee533c5b1aa4", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z026_t001_NucleiLabels.tiff": "ad22809ff3f43d15c838f697061c263070dbf1da1031da39900681cdfbf9d54c", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z016_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z019_t001_CellsLabels.tiff": "ec6ef1d319f2732c47b06f5cf02775c8cd94540f2f30a6c002f0aace1d317955", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z057_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z038_t001_CellsLabels.tiff": "6ac8fd9c95acc1f261e96a8fb9332e5d6a403548842f9b85ecb977e6213b4c9b", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z051_t001_NucleiLabels.tiff": "f0f36ccaf744d42da036948682cfd226e6dd4a3cfb94aed38729b2d25ede5dff", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z022_t001_NucleiLabels.tiff": "50aef20e28a2f9e18ca2e28eabf6d87ec2ad20c79898e56f8d63a959ba5bb507", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z005_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z021_t001_NucleiLabels.tiff": "71a10b0539f3fc4cba600b275b7e948258c6a435ba33ef522faa0869ac085518", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z042_t001_CellsLabels.tiff": "88d2e9964455459499656c4f0a762cd86376c678756635aaa6b6c8d98be01852", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/openhcs_metadata.json.lock": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z059_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z014_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/results/3d_monolayer_Cells.csv": "6f6e7431171ed5ea73a01784105147eca0e43a6e3e41f8720df93106353c9c79", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z048_t001_NucleiLabels.tiff": "325478230529e94ba372f38f0bf512292f131d337b6ac09ce5a91b0266724e02", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z013_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z016_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z020_t001_NucleiLabels.tiff": "b0cd031b448d8bd2075e65710bd76c064161b25242f85ee150da7cd139fcc1a8", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z043_t001_NucleiLabels.tiff": "81a705d05b0a5bfa8783df28990c1d70634c1f4aa2bca23e02cfa8a4bc861b86", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z002_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z010_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z027_t001_CellsLabels.tiff": "ee9056587a19e581f5feb6078b41fa1004d923a5ddf1725aefc4b8b8c5201ad6", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z049_t001_CellsLabels.tiff": "28d83dfbf5bbf7e4da9c3e4806353e9fd0a89680dcdab4b43ca2fd19b80f669c", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z050_t001_NucleiLabels.tiff": "565b4f08f7503086c1f2f8e631d19063129e02a5767d2f979c0cec8fdec23601", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z047_t001_NucleiLabels.tiff": "995d5ce77cbf61a9be8590f34987ef3f1dd698ae6ed393cac4d0960bc9e7a66a", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z010_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z034_t001_CellsLabels.tiff": "3f6c1d8cdbce20aac8f70e7315bea70b147b7b6a034432845b27eeb6cfba083c", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z060_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z028_t001_NucleiLabels.tiff": "1676f21bd3b7e105601c83f206890507c32ba2447988be2a75d0e8153d069b65", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z029_t001_NucleiLabels.tiff": "34bce0f06f674e20667554eed0075fde8d9d33c9c0eaeffd88a1c558499cc432", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/results/3d_monolayer_downsizedNuclei.csv": "a7b998c5a524e11747fc5452fd763fc3d9abe16f46e961f62e09e9393b6a8adf", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z011_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z015_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z021_t001_CellsLabels.tiff": "daa31cb1e537e5c32b1936ab7647c5690741d2bc1d0e15c60b59ba1310a8c0ce", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z060_t001_NucleiLabels.tiff": "7cc3c6c6a22f558e62194277090bdea2deb79475dd91fe7d0e49eac3c0187388", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z041_t001_NucleiLabels.tiff": "744eab7cd170d5af8d2f72ced3893dd939c4e1b0f415afab799a37ded5d046c7", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z012_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z039_t001_CellsLabels.tiff": "22fa79a76e64013f10373be2ca2af98a2173275c5d43c9cad33135acdc376d14", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z036_t001_NucleiLabels.tiff": "4fa967c78709aa400246a50528a36b24ca366e825dd0e64561643369e814906b", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z025_t001_NucleiLabels.tiff": "9cc33676a0177130609ab1331feab1722bbde8d55b2f49031730fd5a2a40029c", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/openhcs_metadata.json": "43ddc7fb22e14f8b2478e1c057a767169c6ffa396b4347fedea756a539e4500e", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z017_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z028_t001_CellsLabels.tiff": "fef31040e0c54501c3bf965eb98f055cdb1d42c96f91cf1c239033d0a9a06534", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z025_t001_CellsLabels.tiff": "03aabe5528198cfd6ec23a058dab540fb8be0870207c6dc94a62d9b621d1f2f9", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z022_t001_CellsLabels.tiff": "7d7ec170ed3652efa99e43d8db546c51b696821dca7727d0ff4d2f2ead7fdbaa", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z056_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z039_t001_NucleiLabels.tiff": "f93e8293a37886a36844b8748083a1f8e717efab092652755263e797f12f0364", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z007_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z003_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z018_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z042_t001_NucleiLabels.tiff": "e07252ca1a55c5195c99666d8d3f0d70db636b4ef4b99e1a0049ca22b182d87a", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z006_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z003_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/results/3d_monolayer_Image.csv": "75ac32ff5ef57bc285ec4eae1c9b501c27a35b486bf35435af5d499d856d34a4", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z011_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z006_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z024_t001_NucleiLabels.tiff": "9e96a05ed9860cac9c57c618db2f4fe5e4b769a9d235aac6fd1d628486317df0", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z023_t001_CellsLabels.tiff": "2f06989618050934c73473f9342c2fe3410fd834a0ddb976cf602fe6198db7a6", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z017_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z059_t001_NucleiLabels.tiff": "76c785cf0f481c73ad3cf34ccb576eaa19dd1bdd9c74f9eaf92adfbde5d44b97", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z049_t001_NucleiLabels.tiff": "e92e493078672a0e0d90e31409612e215bf8486300d5c765d0e0504ff8888e7a", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z035_t001_CellsLabels.tiff": "eedeb489b46abf1eafbd9c81491cb3f85ce1cb3ce877844ad22e72547fc3c438" + } + }, + { + "case": "cp_tutorial_3d_monolayer", + "ordinary_repeat": 1, + "native_repeat": 1, + "measurement_differences": 0, + "image_differences": 0, + "tables": [ + 7, + 6 + ], + "physical_images": [ + 2, + 120 + ], + "logical_images": [ + 2, + 2 + ], + "known_relationship_keys": [ + 3, + 3 + ], + "ordinary_receipt_sha256": "caf9cca665b85734e682f713c153260f8c949fdabd9229f482d6b501964dbac9", + "output_hashes": { + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/native/cp_tutorial_3d_monolayer/outputs/1/3d_monolayer_erodedResizedNuclei.csv": "66a58f78cab0cfdbe907468e8ba383fc59fab49025b84b589855bdfa04854609", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/native/cp_tutorial_3d_monolayer/outputs/1/3d_monolayer_xy1_ch0_CellsLabels.tiff": "aaed9ed23179a162ee7f5a7e8d1d88f1fa342ca55172b7fccd4cbf67f7841d81", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/native/cp_tutorial_3d_monolayer/outputs/1/3d_monolayer_Image.csv": "d775f1b475e2d5f725d30e736f5074301f8f17a1ee72824ad38a659f61d0a184", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/native/cp_tutorial_3d_monolayer/outputs/1/3d_monolayer_Cells.csv": "cc34681db8a66c38ca77bc47db496b26703f21e4d7c7628dd74e30c33250859f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/native/cp_tutorial_3d_monolayer/outputs/1/3d_monolayer_Experiment.csv": "f6b57eaed8c47bd7dfd14bcbaab24b1c2dbd760daaea7fbb9622ec1b1b79307d", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/native/cp_tutorial_3d_monolayer/outputs/1/3d_monolayer_Nuclei.csv": "440c33edc7e8cb5611910a835454db62390301a7af617a542349f60aece57561", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/native/cp_tutorial_3d_monolayer/outputs/1/3d_monolayer_xy1_ch2_NucleiLabels.tiff": "340bbd795541e4031749d1fff767fa4fcdcac10f5b97879056b25dac9fd7674b", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/native/cp_tutorial_3d_monolayer/outputs/1/3d_monolayer_erodedDownsizedNuclei.csv": "527a0cce497d2a618478be84d1a0bf174049f58aa2a666e37626a990fdca0116", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/native/cp_tutorial_3d_monolayer/outputs/1/3d_monolayer_downsizedNuclei.csv": "2c66bc7b17de52147d5a875403f9a9746019ac61371c08157979044c6ed818dd", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z054_t001_CellsLabels.tiff": "25ff2ec586a568e42286f73713d64aab1208c38c016099299211f04368ac49c8", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z001_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z005_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z013_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z056_t001_NucleiLabels.tiff": "ca0723c8b9764d5b77034719bb75a2940be35da2e04119af4c0e6d3552c08718", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z044_t001_CellsLabels.tiff": "e03946d94c789ee787cc29a3c8f5e5d9c56b37a0044b297ba8f403abc98eb55e", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z002_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z008_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z020_t001_CellsLabels.tiff": "e8105a4f04198ac75de9831247030084d6f65bf98691d7444ead7e178072fa22", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z029_t001_CellsLabels.tiff": "b3bdde5f751b8f5d41ca8b5219a3427e450cb1b8795401d0ec638940d1ad7bd9", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z009_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z014_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z047_t001_CellsLabels.tiff": "b926aa64e1fa8aa52279a69d91dc23cf14bf0ae76107f9b360c7ae77bdf53719", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/results/3d_monolayer_erodedDownsizedNuclei.csv": "ee507fb9c2387f86fc768184baf2596ebe1f8e40f7fc5eb24f252345fee63ae6", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z030_t001_CellsLabels.tiff": "b71a2e05d270ae0cd237d6c0d97ea82a63e5ad3633723e7255c35d34e585ec80", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z040_t001_CellsLabels.tiff": "1635ea20dd80ce99f0e86494666825a52a66645837d598fd3a3fa91f0bb77d53", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z032_t001_NucleiLabels.tiff": "97b09fe5444ad439c3c2007d75971dce2766d94c93268eccfee9ae49b8a04aa1", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z046_t001_NucleiLabels.tiff": "c1250e060d32f2cfc07fc7e1594fdb1d6cbb4d0483fa94a8113efa695397963c", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/results/3d_monolayer_erodedResizedNuclei.csv": "cca23f86a85bb3ee7a5c3a1d174c34b5f026ca7f399be98458e1a8c6e12d5c77", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z044_t001_NucleiLabels.tiff": "a78264f2f5e245a3913a69f89105e94df30048b1aaef4eb80fc5c3235e78b196", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z007_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z045_t001_NucleiLabels.tiff": "94bd6a65795ad6395cc18a4fd63dc591354bef612ee49fffd2d9f63e4ed9db84", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z052_t001_NucleiLabels.tiff": "0daf51526658e23b7c9ab8872e992ebe9322399286f95741d0ccdbd357e5d631", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z043_t001_CellsLabels.tiff": "bd0df007524ea4e555e4d2fdbebe6a274caa03bc360a1cf90d601659155984b2", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z037_t001_NucleiLabels.tiff": "927d52441c57cb3a4014effaca3e3c23c76275fb264c26e1942a9c58b85ee6d2", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z046_t001_CellsLabels.tiff": "dc081df050be6cd19b5d5bbfe21c96c350eecf9bc6f10f608dc361a36056632a", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z055_t001_NucleiLabels.tiff": "44e02416cc94a70528165a4b6c42b9e19b205f9c91528076796272cb1a8504ea", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/results/3d_monolayer_Nuclei.csv": "17500f5d4321bbf255df31f7a3503339029c2b077045a6c10e4d4f6f0db9ad1e", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z048_t001_CellsLabels.tiff": "133a58f6fac8b07f79bfed9634867ccb5428b83e63682031a1def16c6a694568", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z051_t001_CellsLabels.tiff": "73483bd10a0f37990084013ad054768086d6d3c929da6bc7e74f4aee37e9dbf2", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z027_t001_NucleiLabels.tiff": "8c8f402d3a7c65c04e7f1575dd34de0427eeeb433ff2956d20e07d06eb48fb8d", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z055_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z031_t001_NucleiLabels.tiff": "247490c261fecc26c7379ab2eebaa01e4bea523218b3cc5491d2fe2b9aadfe11", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z023_t001_NucleiLabels.tiff": "ecb7f78c8ca0bad2b9d0495659609b9023781b6a936d6afb0a04653eac176555", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z008_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z045_t001_CellsLabels.tiff": "c678f2100c7431e5a43c391af86a79e3436d4cf13f050f98c25f62682e4632fe", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z036_t001_CellsLabels.tiff": "28b68d1300cf7b08e21dbcd4858447862520dded5c27f2d84cf223513a119eed", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z038_t001_NucleiLabels.tiff": "e2852ea83c62ab30d77681b4e39f88d3cee74ae052f1c948675ae3581c9fc28a", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z052_t001_CellsLabels.tiff": "7bb98f0587062e01b965e486fc687872651d7d90d271a2fdf0d35d67b464b233", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z015_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z004_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z001_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z054_t001_NucleiLabels.tiff": "b841c5d901c65a6138d9ff2b0ec4aa04f00765b1dd21bcd6fc9f8dc974c6035d", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z019_t001_NucleiLabels.tiff": "250cb56a8054c28cea894bc3d9edaddcdce01f5151a05da78da20157c3c3be9f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z018_t001_NucleiLabels.tiff": "03ba7a4d6ae53e6c84aab5926ae1e2592b5f8ca24a839a256c82f08544df4270", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z058_t001_NucleiLabels.tiff": "a37c63c6052e40d73db918a014e6f2a18be4d0cbfbeeef65a9c26096a38a4c09", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z057_t001_NucleiLabels.tiff": "695517641e9fe4b8421d4a7db56b24c755b6957c98ce32bb24ad5b25f52661eb", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z032_t001_CellsLabels.tiff": "8a2c5774044326ae722e41aae517266197fbebb0e4dd5eab4b22414fbfea309f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z037_t001_CellsLabels.tiff": "aa1f449f1769b27cd9f1076e70f49f0242e2549f288a77984ca159cb07cf6a40", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z058_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z009_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z053_t001_NucleiLabels.tiff": "b8613192175a4615b58aed607474657668429cb6ac635cd012569b19667f2d3d", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z004_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z031_t001_CellsLabels.tiff": "1b14aab71bf3623458ea9373852b0baf28be9727877b32f894407927ecfb6d65", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z024_t001_CellsLabels.tiff": "39899adabca74b10b9950d1f97e8b0b3bbaf136d75e7a46ef4a6e86896e3119f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z033_t001_CellsLabels.tiff": "a320b99ee129d97b99f9fac66aabb89fc1652930b3bb8b2b3fbba7b57e994f85", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z030_t001_NucleiLabels.tiff": "c54c8b98a5c38a47e0cf9391a1afab09b4c8c58e06294cdb650a15add4a32b58", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z040_t001_NucleiLabels.tiff": "e0bd66b166e9f92120dbee183973849eda0afbbe6fed9d03fc4cfd2c56a96280", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z012_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z035_t001_NucleiLabels.tiff": "13e69afc324152bb91329fa758d131d849127e8fd346078d94c6adc25582b3a6", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z026_t001_CellsLabels.tiff": "5b433d931fa6637fc793b23880199c01000ef6d9e610903bb38bb8cea5574563", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z053_t001_CellsLabels.tiff": "ff17f538baaf179752412026a250bdbee016e3101037bf4e0dbb81199fc4c8ed", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z033_t001_NucleiLabels.tiff": "512a3a0ed8025d14b0556a72ebfc13b173d14f7046817ca09876242ab63b9d6b", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z041_t001_CellsLabels.tiff": "be7762756eb65f08cb337904165c6f43b5351f39405461f65ad28669abfe3899", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z050_t001_CellsLabels.tiff": "ea7654a6fe1f92ad274a54935420923eec4bec5ad030187afc0ac7af02690af5", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z034_t001_NucleiLabels.tiff": "08af61857cfb97fd95fcb08d1ce18139ce7087b192044c63452bee533c5b1aa4", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z026_t001_NucleiLabels.tiff": "ad22809ff3f43d15c838f697061c263070dbf1da1031da39900681cdfbf9d54c", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z016_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z019_t001_CellsLabels.tiff": "ec6ef1d319f2732c47b06f5cf02775c8cd94540f2f30a6c002f0aace1d317955", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z057_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z038_t001_CellsLabels.tiff": "6ac8fd9c95acc1f261e96a8fb9332e5d6a403548842f9b85ecb977e6213b4c9b", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z051_t001_NucleiLabels.tiff": "f0f36ccaf744d42da036948682cfd226e6dd4a3cfb94aed38729b2d25ede5dff", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z022_t001_NucleiLabels.tiff": "50aef20e28a2f9e18ca2e28eabf6d87ec2ad20c79898e56f8d63a959ba5bb507", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z005_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z021_t001_NucleiLabels.tiff": "71a10b0539f3fc4cba600b275b7e948258c6a435ba33ef522faa0869ac085518", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z042_t001_CellsLabels.tiff": "88d2e9964455459499656c4f0a762cd86376c678756635aaa6b6c8d98be01852", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/openhcs_metadata.json.lock": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z059_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z014_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/results/3d_monolayer_Cells.csv": "6f6e7431171ed5ea73a01784105147eca0e43a6e3e41f8720df93106353c9c79", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z048_t001_NucleiLabels.tiff": "325478230529e94ba372f38f0bf512292f131d337b6ac09ce5a91b0266724e02", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z013_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z016_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z020_t001_NucleiLabels.tiff": "b0cd031b448d8bd2075e65710bd76c064161b25242f85ee150da7cd139fcc1a8", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z043_t001_NucleiLabels.tiff": "81a705d05b0a5bfa8783df28990c1d70634c1f4aa2bca23e02cfa8a4bc861b86", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z002_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z010_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z027_t001_CellsLabels.tiff": "ee9056587a19e581f5feb6078b41fa1004d923a5ddf1725aefc4b8b8c5201ad6", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z049_t001_CellsLabels.tiff": "28d83dfbf5bbf7e4da9c3e4806353e9fd0a89680dcdab4b43ca2fd19b80f669c", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z050_t001_NucleiLabels.tiff": "565b4f08f7503086c1f2f8e631d19063129e02a5767d2f979c0cec8fdec23601", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z047_t001_NucleiLabels.tiff": "995d5ce77cbf61a9be8590f34987ef3f1dd698ae6ed393cac4d0960bc9e7a66a", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z010_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z034_t001_CellsLabels.tiff": "3f6c1d8cdbce20aac8f70e7315bea70b147b7b6a034432845b27eeb6cfba083c", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z060_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z028_t001_NucleiLabels.tiff": "1676f21bd3b7e105601c83f206890507c32ba2447988be2a75d0e8153d069b65", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z029_t001_NucleiLabels.tiff": "34bce0f06f674e20667554eed0075fde8d9d33c9c0eaeffd88a1c558499cc432", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/results/3d_monolayer_downsizedNuclei.csv": "a7b998c5a524e11747fc5452fd763fc3d9abe16f46e961f62e09e9393b6a8adf", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z011_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z015_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z021_t001_CellsLabels.tiff": "daa31cb1e537e5c32b1936ab7647c5690741d2bc1d0e15c60b59ba1310a8c0ce", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z060_t001_NucleiLabels.tiff": "7cc3c6c6a22f558e62194277090bdea2deb79475dd91fe7d0e49eac3c0187388", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z041_t001_NucleiLabels.tiff": "744eab7cd170d5af8d2f72ced3893dd939c4e1b0f415afab799a37ded5d046c7", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z012_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z039_t001_CellsLabels.tiff": "22fa79a76e64013f10373be2ca2af98a2173275c5d43c9cad33135acdc376d14", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z036_t001_NucleiLabels.tiff": "4fa967c78709aa400246a50528a36b24ca366e825dd0e64561643369e814906b", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z025_t001_NucleiLabels.tiff": "9cc33676a0177130609ab1331feab1722bbde8d55b2f49031730fd5a2a40029c", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/openhcs_metadata.json": "43ddc7fb22e14f8b2478e1c057a767169c6ffa396b4347fedea756a539e4500e", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z017_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z028_t001_CellsLabels.tiff": "fef31040e0c54501c3bf965eb98f055cdb1d42c96f91cf1c239033d0a9a06534", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z025_t001_CellsLabels.tiff": "03aabe5528198cfd6ec23a058dab540fb8be0870207c6dc94a62d9b621d1f2f9", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z022_t001_CellsLabels.tiff": "7d7ec170ed3652efa99e43d8db546c51b696821dca7727d0ff4d2f2ead7fdbaa", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z056_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z039_t001_NucleiLabels.tiff": "f93e8293a37886a36844b8748083a1f8e717efab092652755263e797f12f0364", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z007_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z003_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z018_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z042_t001_NucleiLabels.tiff": "e07252ca1a55c5195c99666d8d3f0d70db636b4ef4b99e1a0049ca22b182d87a", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z006_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z003_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/results/3d_monolayer_Image.csv": "75ac32ff5ef57bc285ec4eae1c9b501c27a35b486bf35435af5d499d856d34a4", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z011_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z006_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z024_t001_NucleiLabels.tiff": "9e96a05ed9860cac9c57c618db2f4fe5e4b769a9d235aac6fd1d628486317df0", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z023_t001_CellsLabels.tiff": "2f06989618050934c73473f9342c2fe3410fd834a0ddb976cf602fe6198db7a6", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z017_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z059_t001_NucleiLabels.tiff": "76c785cf0f481c73ad3cf34ccb576eaa19dd1bdd9c74f9eaf92adfbde5d44b97", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z049_t001_NucleiLabels.tiff": "e92e493078672a0e0d90e31409612e215bf8486300d5c765d0e0504ff8888e7a", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z035_t001_CellsLabels.tiff": "eedeb489b46abf1eafbd9c81491cb3f85ce1cb3ce877844ad22e72547fc3c438" + } + }, + { + "case": "ExampleSpeckles", + "ordinary_repeat": 1, + "native_repeat": 0, + "measurement_differences": 0, + "image_differences": 0, + "tables": [ + 3, + 3 + ], + "physical_images": [ + 0, + 0 + ], + "logical_images": [ + 0, + 0 + ], + "known_relationship_keys": [ + 1, + 1 + ], + "ordinary_receipt_sha256": "70cfd59c5b7e48d708823be2449bc457cfc86f9a1de56835bbc1b068e6d8c4cf", + "output_hashes": { + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/native/ExampleSpeckles/outputs/0/Nuclei.csv": "15af7cac08d651c19b3e3f409b2b0d7fc4f96011c9b53394aa9a35969a8936a6", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/native/ExampleSpeckles/outputs/0/h2ax.csv": "0f54fc72ccdeb7e1a68bab9dc3a8d9d49788cdf81dbbc109ed119e589c09538a", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/native/ExampleSpeckles/outputs/0/Image.csv": "cebe6c0c9ab138ff1f65906b70a130b9e79e3b7d873cc006e88067c596b07a98", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/ExampleSpeckles/wells_1/workers_1/images_ExampleSpeckles_source_workspace_well_throughput/results/Image.csv": "85ef16f24e75f03dc7055215cf2e6cb196b1dc0a0d73713a4c5999f698d4f96e", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/ExampleSpeckles/wells_1/workers_1/images_ExampleSpeckles_source_workspace_well_throughput/openhcs_metadata.json.lock": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/ExampleSpeckles/wells_1/workers_1/images_ExampleSpeckles_source_workspace_well_throughput/openhcs_metadata.json": "71582c62cabb2571ebf8a0de57f92fdf82c55a7ece3dac0bf2a6eca95cad84c9", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/ExampleSpeckles/wells_1/workers_1/images_ExampleSpeckles_source_workspace_well_throughput/results/Nuclei.csv": "e50cb9f8c23f65e9ce8db25132263cf4a4448ed65fc1088d782536abf74c5670", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/ExampleSpeckles/wells_1/workers_1/images_ExampleSpeckles_source_workspace_well_throughput/results/h2ax.csv": "eb453565f3b79ac932eeb5cde8605888b72e58c80f42edbbf0b1ba37f34fd6f8" + } + }, + { + "case": "ExampleSpeckles", + "ordinary_repeat": 1, + "native_repeat": 1, + "measurement_differences": 0, + "image_differences": 0, + "tables": [ + 3, + 3 + ], + "physical_images": [ + 0, + 0 + ], + "logical_images": [ + 0, + 0 + ], + "known_relationship_keys": [ + 1, + 1 + ], + "ordinary_receipt_sha256": "70cfd59c5b7e48d708823be2449bc457cfc86f9a1de56835bbc1b068e6d8c4cf", + "output_hashes": { + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/native/ExampleSpeckles/outputs/1/Nuclei.csv": "15af7cac08d651c19b3e3f409b2b0d7fc4f96011c9b53394aa9a35969a8936a6", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/native/ExampleSpeckles/outputs/1/h2ax.csv": "0f54fc72ccdeb7e1a68bab9dc3a8d9d49788cdf81dbbc109ed119e589c09538a", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/native/ExampleSpeckles/outputs/1/Image.csv": "be7bbf5f19c27df330b95c8eb1784e0053a655f84d278d40a9023c1feeb1fbed", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/ExampleSpeckles/wells_1/workers_1/images_ExampleSpeckles_source_workspace_well_throughput/results/Image.csv": "85ef16f24e75f03dc7055215cf2e6cb196b1dc0a0d73713a4c5999f698d4f96e", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/ExampleSpeckles/wells_1/workers_1/images_ExampleSpeckles_source_workspace_well_throughput/openhcs_metadata.json.lock": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/ExampleSpeckles/wells_1/workers_1/images_ExampleSpeckles_source_workspace_well_throughput/openhcs_metadata.json": "71582c62cabb2571ebf8a0de57f92fdf82c55a7ece3dac0bf2a6eca95cad84c9", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/ExampleSpeckles/wells_1/workers_1/images_ExampleSpeckles_source_workspace_well_throughput/results/Nuclei.csv": "e50cb9f8c23f65e9ce8db25132263cf4a4448ed65fc1088d782536abf74c5670", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/ordinary-1/ExampleSpeckles/wells_1/workers_1/images_ExampleSpeckles_source_workspace_well_throughput/results/h2ax.csv": "eb453565f3b79ac932eeb5cde8605888b72e58c80f42edbbf0b1ba37f34fd6f8" + } + } + ], + "source_head": "ee8f97552b349499655bb3f961860b34dc784071", + "scope": "Both ordinary observations versus both native measured observations; full strict files/values/correlation policy; descriptive two-repeat clocks, not full30 acceptance." +} diff --git a/benchmark/results/perf_canonical_output_policy_paired_20261003/timing_summary.json b/benchmark/results/perf_canonical_output_policy_paired_20261003/timing_summary.json new file mode 100644 index 0000000000..f303ba74dc --- /dev/null +++ b/benchmark/results/perf_canonical_output_policy_paired_20261003/timing_summary.json @@ -0,0 +1,73 @@ +{ + "source_head": "ee8f97552b349499655bb3f961860b34dc784071", + "cases": { + "ExampleSpeckles": { + "native_invocation_seconds": [ + 2.0799103030003607, + 2.0815624929964542 + ], + "native_mean_seconds": 2.0807363979984075, + "ordinary_samples": { + "compile_seconds": [ + 0.49239587783813477, + 0.5033345222473145 + ], + "execute_seconds": [ + 1.2073335647583008, + 1.3140697479248047 + ], + "total_seconds": [ + 2.052078391890973, + 2.1295654121786356 + ] + }, + "ordinary_means": { + "compile_seconds": 0.4978652000427246, + "execute_seconds": 1.2607016563415527, + "total_seconds": 2.0908219020348042 + }, + "other_total_seconds_mean": 0.3322550456505269, + "execution_speedup_ratio_of_means": 1.6504590023594676, + "total_speedup_ratio_of_means": 0.9951762969258254 + }, + "cp_tutorial_3d_monolayer": { + "native_invocation_seconds": [ + 14.412360650952905, + 14.22139574913308 + ], + "native_mean_seconds": 14.316878200042993, + "ordinary_samples": { + "compile_seconds": [ + 1.1534233093261719, + 1.1986286640167236 + ], + "execute_seconds": [ + 8.562227010726929, + 9.425255298614502 + ], + "total_seconds": [ + 10.547500064130872, + 11.399972424842417 + ] + }, + "ordinary_means": { + "compile_seconds": 1.1760259866714478, + "execute_seconds": 8.993741154670715, + "total_seconds": 10.973736244486645 + }, + "other_total_seconds_mean": 0.8039691031444818, + "execution_speedup_ratio_of_means": 1.59187127512646, + "total_speedup_ratio_of_means": 1.304649381129056 + } + }, + "scope": "Two current cases only; means of both observations, not a causal before/after comparison, confidence interval, or full30/scaling result. Server READY startup/shutdown and native imports/JVM/load/full warmup are excluded. Ordinary total includes compilation and default OUTCOMES/RSS completion.", + "science_sha256": "f63245b5fceca1e1f1a1807294b937f8fe9df483cded7491a2dc7baba3c98318", + "plot_script_sha256": "3503b70048d05ff6867397e1921265d5bd17e145956a6bc27787ed69d504b408", + "artifacts": { + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/figures-v2/metrics.csv": "8569f5075c4f5088e5d73694e0d99b2ca751d7d2d6383326eeeffa660206c2bd", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/figures-v2/matched_runtime.png": "3a9878a285b1472b9523607c2e6eaeeb9ff1c020c3a2c717aac1ca6504603c00", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/figures-v2/matched_runtime.svg": "0c4e958aa88fa545563b9ab13b78e5fcb56a29aadf079223b2b54da66b3b175a", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/figures-v2/matched_speedup.png": "3aeb724b0ef9a51c1d18135f86064edc7e76ccd79d63bcab23737c871377179d", + "/home/ts/.local/state/openhcs-maintenance/20261003/canonical-output-policy-paired-v1/figures-v2/matched_speedup.svg": "57cf838d868692a3b0c2a8bc95bb3f1e55b98ed49d41dcd7380a32f026eed467" + } +} diff --git a/benchmark/results/perf_compile_runtime_ledger_20261003/agent-environment-comparison.json b/benchmark/results/perf_compile_runtime_ledger_20261003/agent-environment-comparison.json new file mode 100644 index 0000000000..108861c831 --- /dev/null +++ b/benchmark/results/perf_compile_runtime_ledger_20261003/agent-environment-comparison.json @@ -0,0 +1,8 @@ +{ + "current_matches_prepared": true, + "current_environment_sha256": "00b7f550f6e584e34d6070f79bdd60d37859cb58c752b866fc95ac7f5293dabd", + "prepared_environment_sha256": "00b7f550f6e584e34d6070f79bdd60d37859cb58c752b866fc95ac7f5293dabd", + "differing_key_names": [ + "CODEX_THREAD_ID" + ] +} diff --git a/benchmark/results/perf_compile_runtime_ledger_20261003/assessment.json b/benchmark/results/perf_compile_runtime_ledger_20261003/assessment.json new file mode 100644 index 0000000000..6368532f34 --- /dev/null +++ b/benchmark/results/perf_compile_runtime_ledger_20261003/assessment.json @@ -0,0 +1,431 @@ +{ + "source_revision": "480aed49b30448de4380af5c9274e48084e67b63", + "diagnostic_only": true, + "production_change": false, + "public_row": { + "case_name": "cp_tutorial_3d_monolayer", + "mode_name": "1w_1t", + "worker_count": "1", + "well_count": "1", + "compile_seconds": "1.495826244354248", + "prepare_seconds": "0.0", + "execute_seconds": "8.396726846694946", + "total_seconds": "10.694032318890095", + "wells_per_second": "0.11909402535746559", + "successful_wells": "1", + "native_single_sample_execution_seconds": "", + "projected_native_execution_seconds": "", + "projected_execution_speedup": "", + "peak_memory_mb": "1658.1875", + "status": "success", + "memory_limit_mb": "", + "error_message": "", + "execution_route": "ordinary-zmq-outcomes-v1", + "server_lifecycle": "reused-per-sweep", + "run_input_sha256": "7f66dd478c9a56033495f056335a0eaadb9fd5facd953b504f0e1f8f7eaa57d5" + }, + "execution_partition": { + "root": 8.383970148861408, + "declared_callable_exclusive": 3.6605217196047306, + "outside_declared_callable": 4.723448429256678, + "outside_fraction": 0.5633904159234333 + }, + "compilation": { + "root": 1.2609371892176569, + "state_owner_exclusive": 0.6710898061282933, + "interpretation": "Sum of nested disjoint exclusive state-owner spans. The ten effective-config reads are a .195838s inclusive subset, not an additional term or a removable .671s cost." + }, + "timing_contract": "Public original 1w_1t driver, CPU5, inline execution, reused-per-sweep server READY/library/kernel preparation before clocks; both profilers off, original OUTCOMES and RSS observer. New41 hook version with inherited24 plus17 nominal compiler/config boundaries. Diagnostic overhead remains; no ordinary gain, regression, statistical significance, or fresh native ratio inferred.", + "parity": "FULL6CSV120TIFF_AND180_PHYSICAL_SOURCE_REFS_PASS", + "native_scope": "TRANSITIVE ONLY: exact current saved science equals retained reference and B764-qualified bytes with actual same3physicalvolume inputs/180orderedrefs. Retained2native repetitions verified; native was NOT rerun for current source/environment. Original native compare API RED retained separately; no current native timing ratio or performance claim.", + "environment": { + "python": "3.12.14 (main, Sep 24 2026, 17:57:43) [Clang 22.1.3 ]", + "versions": { + "openhcs": "0.8.7", + "numpy": "2.5.3", + "scipy": "1.18.1", + "arraybridge": "0.3.6", + "polystore": "0.3.0", + "python-introspect": "0.1.15", + "metaclass-registry": "0.2.2", + "zmqruntime": "0.3.0" + } + }, + "declared_hooks": [ + { + "module": "openhcs.runtime.zmq_execution_server", + "owner": "ZMQExecutionServer", + "method": "_execute_with_orchestrator", + "line": 485, + "descriptor_kind": "function", + "source_relative": "openhcs/runtime/zmq_execution_server.py" + }, + { + "module": "openhcs.runtime.zmq_execution_server", + "owner": "ZMQExecutionServer", + "method": "_initialize_orchestrator", + "line": 592, + "descriptor_kind": "function", + "source_relative": "openhcs/runtime/zmq_execution_server.py" + }, + { + "module": "openhcs.runtime.zmq_execution_server", + "owner": "ZMQExecutionServer", + "method": "_export_runtime_observation", + "line": 741, + "descriptor_kind": "function", + "source_relative": "openhcs/runtime/zmq_execution_server.py" + }, + { + "module": "openhcs.core.orchestrator.worker_execution", + "owner": "", + "method": "execute_worker_lane", + "line": 1064, + "descriptor_kind": "function", + "source_relative": "openhcs/core/orchestrator/worker_execution.py" + }, + { + "module": "openhcs.core.steps.function_runtime", + "owner": "FunctionCoreExecutor", + "method": "execute", + "line": 2075, + "descriptor_kind": "function", + "source_relative": "openhcs/core/steps/function_runtime.py" + }, + { + "module": "openhcs.core.steps.function_runtime", + "owner": "PatternGroupRuntime", + "method": "_load_input_stack", + "line": 2821, + "descriptor_kind": "function", + "source_relative": "openhcs/core/steps/function_runtime.py" + }, + { + "module": "openhcs.core.steps.function_runtime", + "owner": "PatternGroupRuntime", + "method": "_validate_and_unstack", + "line": 3248, + "descriptor_kind": "function", + "source_relative": "openhcs/core/steps/function_runtime.py" + }, + { + "module": "openhcs.core.steps.function_runtime", + "owner": "PatternGroupRuntime", + "method": "_save_outputs", + "line": 3374, + "descriptor_kind": "function", + "source_relative": "openhcs/core/steps/function_runtime.py" + }, + { + "module": "openhcs.processing.backends.lib_registry.unified_registry", + "owner": "RuntimeCallableInvocation", + "method": "call", + "line": 264, + "descriptor_kind": "function", + "source_relative": "openhcs/processing/backends/lib_registry/unified_registry.py" + }, + { + "module": "openhcs.interop.cellprofiler.runtime.module_execution", + "owner": "CellProfilerModuleExecutor", + "method": "__call__", + "line": 251, + "descriptor_kind": "function", + "source_relative": "openhcs/interop/cellprofiler/runtime/module_execution.py" + }, + { + "module": "openhcs.interop.cellprofiler.runtime.module_execution", + "owner": "CellProfilerModuleExecutor", + "method": "_image_request", + "line": 1259, + "descriptor_kind": "function", + "source_relative": "openhcs/interop/cellprofiler/runtime/module_execution.py" + }, + { + "module": "openhcs.interop.cellprofiler.runtime.function_contract_execution", + "owner": "CellProfilerFunctionContractExecutor", + "method": "execute", + "line": 78, + "descriptor_kind": "function", + "source_relative": "openhcs/interop/cellprofiler/runtime/function_contract_execution.py" + }, + { + "module": "openhcs.interop.cellprofiler.runtime.output_recording", + "owner": "CellProfilerOutputRecorder", + "method": "record_module_outputs", + "line": 106, + "descriptor_kind": "classmethod", + "source_relative": "openhcs/interop/cellprofiler/runtime/output_recording.py" + }, + { + "module": "openhcs.interop.cellprofiler.runtime.measurement_execution_support", + "owner": "ObjectMeasurementOutputRecorder", + "method": "record", + "line": 408, + "descriptor_kind": "function", + "source_relative": "openhcs/interop/cellprofiler/runtime/measurement_execution_support.py" + }, + { + "module": "openhcs.core.steps.function_outputs", + "owner": "", + "method": "finalize_function_step_outputs", + "line": 140, + "descriptor_kind": "function", + "source_relative": "openhcs/core/steps/function_outputs.py" + }, + { + "module": "openhcs.core.steps.function_outputs", + "owner": "OpenHCSMetadataWriter", + "method": "finalize_completed_plate", + "line": 1092, + "descriptor_kind": "classmethod", + "source_relative": "openhcs/core/steps/function_outputs.py" + }, + { + "module": "openhcs.core.steps.function_outputs", + "owner": "RuntimeArtifactMetadataTarget", + "method": "reconciliation_targets", + "line": 1217, + "descriptor_kind": "function", + "source_relative": "openhcs/core/steps/function_outputs.py" + }, + { + "module": "openhcs.core.virtual_workspace_metadata", + "owner": "AtomicMetadataWriter", + "method": "publish_source_projection_metadata", + "line": 181, + "descriptor_kind": "function", + "source_relative": "openhcs/core/virtual_workspace_metadata.py" + }, + { + "module": "openhcs.core.runtime_stack_cache", + "owner": "RuntimeImageStackCache", + "method": "get", + "line": 38, + "descriptor_kind": "function", + "source_relative": "openhcs/core/runtime_stack_cache.py" + }, + { + "module": "openhcs.core.runtime_stack_cache", + "owner": "RuntimeImageStackCache", + "method": "store", + "line": 49, + "descriptor_kind": "function", + "source_relative": "openhcs/core/runtime_stack_cache.py" + }, + { + "module": "openhcs.core.aligned_image_payload", + "owner": "", + "method": "stack_image_payload_context", + "line": 400, + "descriptor_kind": "function", + "source_relative": "openhcs/core/aligned_image_payload.py" + }, + { + "module": "openhcs.core.aligned_image_payload", + "owner": "", + "method": "unstack_image_payload_context", + "line": 598, + "descriptor_kind": "function", + "source_relative": "openhcs/core/aligned_image_payload.py" + }, + { + "module": "openhcs.core.orchestrator.analysis_consolidation", + "owner": "", + "method": "consolidate_analysis_outputs", + "line": 109, + "descriptor_kind": "function", + "source_relative": "openhcs/core/orchestrator/analysis_consolidation.py" + }, + { + "module": "openhcs.core.measurement_feature_queries", + "owner": "MeasurementFeatureValueIndex", + "method": "from_columnar_table_by_object", + "line": 1327, + "descriptor_kind": "classmethod", + "source_relative": "openhcs/core/measurement_feature_queries.py" + }, + { + "module": "openhcs.core.pipeline.compiler", + "owner": "PipelineCompiler", + "method": "compile_pipelines", + "line": 1816, + "descriptor_kind": "staticmethod", + "source_relative": "openhcs/core/pipeline/compiler.py" + }, + { + "module": "openhcs.core.pipeline.compiler", + "owner": "PipelineCompiler", + "method": "_register_and_resolve_pipeline_once", + "line": 1061, + "descriptor_kind": "staticmethod", + "source_relative": "openhcs/core/pipeline/compiler.py" + }, + { + "module": "openhcs.core.pipeline.compiler", + "owner": "PipelineCompiler", + "method": "initialize_step_plans_for_context", + "line": 235, + "descriptor_kind": "staticmethod", + "source_relative": "openhcs/core/pipeline/compiler.py" + }, + { + "module": "openhcs.core.pipeline.compiler", + "owner": "PipelineCompiler", + "method": "_capture_pipeline_config", + "line": 1229, + "descriptor_kind": "staticmethod", + "source_relative": "openhcs/core/pipeline/compiler.py" + }, + { + "module": "openhcs.core.pipeline.compiler", + "owner": "PipelineCompiler", + "method": "_resolve_global_step_axis_filters", + "line": 1241, + "descriptor_kind": "staticmethod", + "source_relative": "openhcs/core/pipeline/compiler.py" + }, + { + "module": "openhcs.core.pipeline.compiler", + "owner": "PipelineCompiler", + "method": "_configure_input_conversion_if_needed", + "line": 364, + "descriptor_kind": "staticmethod", + "source_relative": "openhcs/core/pipeline/compiler.py" + }, + { + "module": "openhcs.core.pipeline.compiler", + "owner": "PipelineCompiler", + "method": "declare_zarr_stores", + "line": 590, + "descriptor_kind": "staticmethod", + "source_relative": "openhcs/core/pipeline/compiler.py" + }, + { + "module": "openhcs.core.pipeline.compiler", + "owner": "PipelineCompiler", + "method": "_finalize_compilation", + "line": 1735, + "descriptor_kind": "staticmethod", + "source_relative": "openhcs/core/pipeline/compiler.py" + }, + { + "module": "openhcs.core.pipeline.compiler", + "owner": "PipelineCompiler", + "method": "_axis_values_to_process", + "line": 1023, + "descriptor_kind": "staticmethod", + "source_relative": "openhcs/core/pipeline/compiler.py" + }, + { + "module": "openhcs.core.pipeline.compiler", + "owner": "AxisCompilationRequest", + "method": "context_for", + "line": 205, + "descriptor_kind": "function", + "source_relative": "openhcs/core/pipeline/compiler.py" + }, + { + "module": "openhcs.core.pipeline.compilation_session", + "owner": "CompilationSession", + "method": "from_context", + "line": 182, + "descriptor_kind": "classmethod", + "source_relative": "openhcs/core/pipeline/compilation_session.py" + }, + { + "module": "openhcs.core.orchestrator.orchestrator", + "owner": "PipelineOrchestrator", + "method": "create_context", + "line": 556, + "descriptor_kind": "function", + "source_relative": "openhcs/core/orchestrator/orchestrator.py" + }, + { + "module": "openhcs.core.orchestrator.orchestrator", + "owner": "PipelineOrchestrator", + "method": "get_effective_config", + "line": 1009, + "descriptor_kind": "function", + "source_relative": "openhcs/core/orchestrator/orchestrator.py" + }, + { + "module": "objectstate.object_state", + "owner": "ObjectState", + "method": "__init__", + "line": 144, + "descriptor_kind": "function", + "source_relative": "external/ObjectState/src/objectstate/object_state.py" + }, + { + "module": "objectstate.object_state", + "owner": "ObjectState", + "method": "_compute_resolved_snapshot", + "line": 2111, + "descriptor_kind": "function", + "source_relative": "external/ObjectState/src/objectstate/object_state.py" + }, + { + "module": "objectstate.object_state", + "owner": "ObjectState", + "method": "_reconstruct_from_resolved", + "line": 1245, + "descriptor_kind": "function", + "source_relative": "external/ObjectState/src/objectstate/object_state.py" + }, + { + "module": "objectstate.object_state", + "owner": "ObjectState", + "method": "to_saved_resolved_object", + "line": 470, + "descriptor_kind": "function", + "source_relative": "external/ObjectState/src/objectstate/object_state.py" + } + ], + "freeze": { + "path": "/home/ts/.local/state/openhcs-maintenance/20261003/compiler-config-coarse-ledger-v1/output/source-freeze.json", + "sha256": "0aa8d013c340ed52de584cc006becc832dfa1a9875745213d2d2e4c0904656cf", + "controller_path": "/home/ts/.local/state/openhcs-maintenance/20261003/compiler-config-coarse-ledger-v1/controller.py", + "controller_sha256": "5460564d44ffdc7e70078d63ac1250bb65a4fff2320da8dcb89b06fba999602f", + "site_path": "/home/ts/.local/state/openhcs-maintenance/20261003/compiler-config-coarse-ledger-v1/site/sitecustomize.py", + "site_sha256": "339c145b2c13548589958d12ebfe77672f87a108c82cbb44dbe1fdcc929d024b", + "installed_freeze_sha256": "b7e5bbb9b5171476dfeb1692378419bfa157bb620028e1b91c8969eef2498b41", + "full_environment_sha256": "00b7f550f6e584e34d6070f79bdd60d37859cb58c752b866fc95ac7f5293dabd" + }, + "prelaunch_refusal": "Root exec87291 terminated1 before launching a driver: full environment hash differed only in CODEX_THREAD_ID. Original matching agent environment retained the exact freeze, ran once in session17712 terminal0, and validated science in session51754 terminal0. No gate bypass/freeze rewrite.", + "completed_controls": 15, + "originals": { + "controls.json": { + "path": "/home/ts/.local/state/openhcs-maintenance/20261003/compiler-config-coarse-ledger-v1/controls.json", + "sha256": "9acdee867fb46c959a6ddbab82505cb288e1ac564d439f0e35f713d79a65b122" + }, + "science.json": { + "path": "/home/ts/.local/state/openhcs-maintenance/20261003/compiler-config-coarse-ledger-v1/science.json", + "sha256": "d19e5294a829cf98a0d0730b2729224e8a6947f258641a6f0923dfc6af732d74" + }, + "registration-owner-analysis.json": { + "path": "/home/ts/.local/state/openhcs-maintenance/20261003/compiler-config-coarse-ledger-v1/registration-owner-analysis.json", + "sha256": "45faf15f51d4a293b3e432afe86995274eee00925c159ed2db06856ea821c238" + }, + "agent-environment-comparison.json": { + "path": "/home/ts/.local/state/openhcs-maintenance/20261003/compiler-config-coarse-ledger-v1/agent-environment-comparison.json", + "sha256": "2a62e8d0f8563b8d461a8128676b933d68b89b37e0be947125acc51b7e8fcf61" + }, + "observations.json": { + "path": "/home/ts/.local/state/openhcs-maintenance/20261003/compiler-config-coarse-ledger-v1/output/observations.json", + "sha256": "07c19d9a2b6183d1cbb69691258862f3b89b65149481989557b0d1029bf728e3" + }, + "compile_only-region.json": { + "path": "/home/ts/.local/state/openhcs-maintenance/20261003/compiler-config-coarse-ledger-v1/output/regions/region-1948899-139659153200832-0001.json", + "sha256": "6b604c99652c36aba1ce3eff39b65ccd73b71d17ca827c121a98676b4608c687" + }, + "execution-region.json": { + "path": "/home/ts/.local/state/openhcs-maintenance/20261003/compiler-config-coarse-ledger-v1/output/regions/region-1948899-139659153200832-0002.json", + "sha256": "ea2b9668eb40dc72c8af0ed9a6d55250fcd46721db5c5554fd0ea3c82ff738dd" + }, + "availability-rejection.json": { + "path": "/home/ts/.local/state/openhcs-maintenance/20261003/workspace-availability-replay-v1/decision.json", + "sha256": "91d34dd84e764f3eb45ab1f15b8ddeeabbebf1f7104b3032534b1541d937e78c" + } + }, + "outstanding": "Dominant integrated runtime fix, matched ordinary before/after gain, original branch architectural gates, installed acceptance, full-catalog/scaling/native refresh and figures remain unproved. Goal active." +} diff --git a/benchmark/results/perf_compile_runtime_ledger_20261003/availability-rejection.json b/benchmark/results/perf_compile_runtime_ledger_20261003/availability-rejection.json new file mode 100644 index 0000000000..bd965f7b32 --- /dev/null +++ b/benchmark/results/perf_compile_runtime_ledger_20261003/availability-rejection.json @@ -0,0 +1,33 @@ +{ + "status": "REJECT_ROUTE_AS_DOMINANT_FIX", + "source_revision": "480aed49b30448de4380af5c9274e48084e67b63", + "source_document": "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace/openhcs_metadata.json", + "source_document_sha256": "a42ec413a0ec213d22f4ba96fac785bfbfac167dd5d2da7cbd1acc8cf9c2d862", + "source_pins": { + "/home/ts/code/projects/openhcs-shared-runtime-plumbing/openhcs/core/virtual_workspace_metadata.py": "25987be96327dadefa1ecb63a93b2678a0957ffdf42383822d02ef666282b24a", + "/home/ts/code/projects/openhcs-shared-runtime-plumbing/openhcs/core/source_workspace_projection.py": "1e54affed309fbc0d150bee4a3deedbc127aedf39a83f0c8a0eaf719257922be", + "/home/ts/code/projects/openhcs-shared-runtime-plumbing/external/PolyStore/src/polystore/virtual_workspace.py": "b19fcda85369d812e70bfc1a0efc5d8861ae256f69e94372e2e9515c591d36af" + }, + "original_projection_cache_hit_calls_per_replay": 68, + "original_unprofiled_seconds": [ + 0.024565204977989197, + 0.024529157672077417, + 0.024390146136283875, + 0.02441246807575226, + 0.024447152856737375, + 0.02439353195950389, + 0.024356392212212086, + 0.02441841922700405, + 0.024412577971816063 + ], + "median_seconds": 0.024412577971816063, + "controls": [ + { + "name": "current_invalid_ref_rejected_after_projection_cache_hit", + "passed": true, + "type": "TypeError", + "message": "SourcePixelRef.source_axis_indices must contain nonnegative integers." + } + ], + "interpretation": "This retained real source document replays all 68 availability calls observed in an older worker trace. It measures the complete original cache-hit availability operation with a trivial already-loaded document handler; it does not claim the current ordinary driver has identical call counts or equate the replay clock with an end-to-end saving. Even removing the complete replay operation cannot materially close the qualified 1.916s execution gap. Public mutable document validation is observable and cannot simply be skipped." +} diff --git a/benchmark/results/perf_compile_runtime_ledger_20261003/compile_only-region.json b/benchmark/results/perf_compile_runtime_ledger_20261003/compile_only-region.json new file mode 100644 index 0000000000..302cec62b5 --- /dev/null +++ b/benchmark/results/perf_compile_runtime_ledger_20261003/compile_only-region.json @@ -0,0 +1,416 @@ +{ + "pid": 1948899, + "thread": 139659153200832, + "region": "ZMQExecutionServer._execute_with_orchestrator", + "root_dimensions": "{\"case\": \"3d_monolayer_final\", \"compile_artifact_id\": null, \"execution_id\": \"8aba2e39-4db0-4608-bf23-08568aef528e\", \"kind\": \"compile_only\", \"plate\": \"/home/ts/.cache/openhcs/benchmark_datasets/CellProfiler_tutorials/data/3d_monolayer/images\"}", + "seconds": 1.2609371892176569, + "revision": "480aed49b30448de4380af5c9274e48084e67b63", + "source": "/home/ts/code/projects/openhcs-shared-runtime-plumbing", + "stats": { + "ObjectState._compute_resolved_snapshot": { + "owner": "ObjectState._compute_resolved_snapshot", + "dimensions": "", + "phase": "compiler_config:_compute_resolved_snapshot", + "calls": 88, + "inclusive": 0.4525698209181428, + "exclusive": 0.4525698209181428 + }, + "ObjectState.__init__": { + "owner": "ObjectState.__init__", + "dimensions": "", + "phase": "compiler_config:__init__", + "calls": 44, + "inclusive": 0.6144807459786534, + "exclusive": 0.16191092506051064 + }, + "ObjectState._reconstruct_from_resolved": { + "owner": "ObjectState._reconstruct_from_resolved", + "dimensions": "", + "phase": "compiler_config:_reconstruct_from_resolved", + "calls": 532, + "inclusive": 0.1099232928827405, + "exclusive": 0.05649412330240011 + }, + "ObjectState.to_saved_resolved_object": { + "owner": "ObjectState.to_saved_resolved_object", + "dimensions": "", + "phase": "compiler_config:to_saved_resolved_object", + "calls": 42, + "inclusive": 0.056609060149639845, + "exclusive": 0.00011493684723973274 + }, + "PipelineOrchestrator.get_effective_config": { + "owner": "PipelineOrchestrator.get_effective_config", + "dimensions": "", + "phase": "compiler_config:get_effective_config", + "calls": 10, + "inclusive": 0.19583785673603415, + "exclusive": 8.42963345348835e-05 + }, + "PipelineOrchestrator.create_context": { + "owner": "PipelineOrchestrator.create_context", + "dimensions": "", + "phase": "compiler_config:create_context", + "calls": 3, + "inclusive": 0.04134061839431524, + "exclusive": 0.0006397129036486149 + }, + "ZMQExecutionServer._initialize_orchestrator": { + "owner": "ZMQExecutionServer._initialize_orchestrator", + "dimensions": "", + "phase": "_initialize_orchestrator", + "calls": 1, + "inclusive": 0.1260731448419392, + "exclusive": 0.022322111297398806 + }, + "PipelineCompiler._axis_values_to_process": { + "owner": "PipelineCompiler._axis_values_to_process", + "dimensions": "", + "phase": "compiler_config:_axis_values_to_process", + "calls": 1, + "inclusive": 0.017245036084204912, + "exclusive": 6.654579192399979e-05 + }, + "PipelineCompiler._register_and_resolve_pipeline_once": { + "owner": "PipelineCompiler._register_and_resolve_pipeline_once", + "dimensions": "", + "phase": "compiler_config:_register_and_resolve_pipeline_once", + "calls": 1, + "inclusive": 0.47889699088409543, + "exclusive": 0.005476511083543301 + }, + "PipelineCompiler._capture_pipeline_config": { + "owner": "PipelineCompiler._capture_pipeline_config", + "dimensions": "", + "phase": "compiler_config:_capture_pipeline_config", + "calls": 1, + "inclusive": 0.0019184919074177742, + "exclusive": 2.7259811758995056e-06 + }, + "PipelineCompiler._resolve_global_step_axis_filters": { + "owner": "PipelineCompiler._resolve_global_step_axis_filters", + "dimensions": "", + "phase": "compiler_config:_resolve_global_step_axis_filters", + "calls": 1, + "inclusive": 0.015254999045282602, + "exclusive": 0.001242930069565773 + }, + "AxisCompilationRequest.context_for": { + "owner": "AxisCompilationRequest.context_for", + "dimensions": "", + "phase": "compiler_config:context_for", + "calls": 1, + "inclusive": 0.013713276013731956, + "exclusive": 0.00032007182016968727 + }, + "CompilationSession.from_context": { + "owner": "CompilationSession.from_context", + "dimensions": "", + "phase": "compiler_config:from_context", + "calls": 1, + "inclusive": 2.0298175513744354e-05, + "exclusive": 2.0298175513744354e-05 + }, + "PipelineCompiler._configure_input_conversion_if_needed": { + "owner": "PipelineCompiler._configure_input_conversion_if_needed", + "dimensions": "", + "phase": "compiler_config:_configure_input_conversion_if_needed", + "calls": 1, + "inclusive": 0.013645949773490429, + "exclusive": 5.200039595365524e-06 + }, + "PipelineCompiler.initialize_step_plans_for_context": { + "owner": "PipelineCompiler.initialize_step_plans_for_context", + "dimensions": "", + "phase": "compiler_config:initialize_step_plans_for_context", + "calls": 1, + "inclusive": 0.4779214742593467, + "exclusive": 0.46425522631034255 + }, + "PipelineCompiler.declare_zarr_stores": { + "owner": "PipelineCompiler.declare_zarr_stores", + "dimensions": "", + "phase": "compiler_config:declare_zarr_stores", + "calls": 1, + "inclusive": 0.018639610148966312, + "exclusive": 9.438721463084221e-05 + }, + "PipelineCompiler._finalize_compilation": { + "owner": "PipelineCompiler._finalize_compilation", + "dimensions": "", + "phase": "compiler_config:_finalize_compilation", + "calls": 1, + "inclusive": 0.016232328955084085, + "exclusive": 0.00027552898973226547 + }, + "PipelineCompiler.compile_pipelines": { + "owner": "PipelineCompiler.compile_pipelines", + "dimensions": "", + "phase": "compiler_config:compile_pipelines", + "calls": 1, + "inclusive": 1.094543606042862, + "exclusive": 0.05472139874473214 + }, + "ZMQExecutionServer._execute_with_orchestrator | {\"case\": \"3d_monolayer_final\", \"compile_artifact_id\": null, \"execution_id\": \"8aba2e39-4db0-4608-bf23-08568aef528e\", \"kind\": \"compile_only\", \"plate\": \"/home/ts/.cache/openhcs/benchmark_datasets/CellProfiler_tutorials/data/3d_monolayer/images\"}": { + "owner": "ZMQExecutionServer._execute_with_orchestrator", + "dimensions": "{\"case\": \"3d_monolayer_final\", \"compile_artifact_id\": null, \"execution_id\": \"8aba2e39-4db0-4608-bf23-08568aef528e\", \"kind\": \"compile_only\", \"plate\": \"/home/ts/.cache/openhcs/benchmark_datasets/CellProfiler_tutorials/data/3d_monolayer/images\"}", + "phase": "_execute_with_orchestrator", + "calls": 1, + "inclusive": 1.2609371892176569, + "exclusive": 0.0403204383328557 + } + }, + "hooks_installed": [ + { + "module": "objectstate.object_state", + "owner": "ObjectState", + "method": "__init__", + "descriptor_kind": "function" + }, + { + "module": "objectstate.object_state", + "owner": "ObjectState", + "method": "_compute_resolved_snapshot", + "descriptor_kind": "function" + }, + { + "module": "objectstate.object_state", + "owner": "ObjectState", + "method": "_reconstruct_from_resolved", + "descriptor_kind": "function" + }, + { + "module": "objectstate.object_state", + "owner": "ObjectState", + "method": "to_saved_resolved_object", + "descriptor_kind": "function" + }, + { + "module": "openhcs.core.aligned_image_payload", + "owner": "", + "method": "stack_image_payload_context", + "descriptor_kind": "function" + }, + { + "module": "openhcs.core.aligned_image_payload", + "owner": "", + "method": "unstack_image_payload_context", + "descriptor_kind": "function" + }, + { + "module": "openhcs.core.measurement_feature_queries", + "owner": "MeasurementFeatureValueIndex", + "method": "from_columnar_table_by_object", + "descriptor_kind": "classmethod" + }, + { + "module": "openhcs.core.virtual_workspace_metadata", + "owner": "AtomicMetadataWriter", + "method": "publish_source_projection_metadata", + "descriptor_kind": "function" + }, + { + "module": "openhcs.core.runtime_stack_cache", + "owner": "RuntimeImageStackCache", + "method": "get", + "descriptor_kind": "function" + }, + { + "module": "openhcs.core.runtime_stack_cache", + "owner": "RuntimeImageStackCache", + "method": "store", + "descriptor_kind": "function" + }, + { + "module": "openhcs.core.steps.function_outputs", + "owner": "", + "method": "finalize_function_step_outputs", + "descriptor_kind": "function" + }, + { + "module": "openhcs.core.steps.function_outputs", + "owner": "OpenHCSMetadataWriter", + "method": "finalize_completed_plate", + "descriptor_kind": "classmethod" + }, + { + "module": "openhcs.core.steps.function_outputs", + "owner": "RuntimeArtifactMetadataTarget", + "method": "reconciliation_targets", + "descriptor_kind": "function" + }, + { + "module": "openhcs.core.steps.function_runtime", + "owner": "FunctionCoreExecutor", + "method": "execute", + "descriptor_kind": "function" + }, + { + "module": "openhcs.core.steps.function_runtime", + "owner": "PatternGroupRuntime", + "method": "_load_input_stack", + "descriptor_kind": "function" + }, + { + "module": "openhcs.core.steps.function_runtime", + "owner": "PatternGroupRuntime", + "method": "_validate_and_unstack", + "descriptor_kind": "function" + }, + { + "module": "openhcs.core.steps.function_runtime", + "owner": "PatternGroupRuntime", + "method": "_save_outputs", + "descriptor_kind": "function" + }, + { + "module": "openhcs.core.pipeline.compilation_session", + "owner": "CompilationSession", + "method": "from_context", + "descriptor_kind": "classmethod" + }, + { + "module": "openhcs.core.pipeline.compiler", + "owner": "PipelineCompiler", + "method": "compile_pipelines", + "descriptor_kind": "staticmethod" + }, + { + "module": "openhcs.core.pipeline.compiler", + "owner": "PipelineCompiler", + "method": "_register_and_resolve_pipeline_once", + "descriptor_kind": "staticmethod" + }, + { + "module": "openhcs.core.pipeline.compiler", + "owner": "PipelineCompiler", + "method": "initialize_step_plans_for_context", + "descriptor_kind": "staticmethod" + }, + { + "module": "openhcs.core.pipeline.compiler", + "owner": "PipelineCompiler", + "method": "_capture_pipeline_config", + "descriptor_kind": "staticmethod" + }, + { + "module": "openhcs.core.pipeline.compiler", + "owner": "PipelineCompiler", + "method": "_resolve_global_step_axis_filters", + "descriptor_kind": "staticmethod" + }, + { + "module": "openhcs.core.pipeline.compiler", + "owner": "PipelineCompiler", + "method": "_configure_input_conversion_if_needed", + "descriptor_kind": "staticmethod" + }, + { + "module": "openhcs.core.pipeline.compiler", + "owner": "PipelineCompiler", + "method": "declare_zarr_stores", + "descriptor_kind": "staticmethod" + }, + { + "module": "openhcs.core.pipeline.compiler", + "owner": "PipelineCompiler", + "method": "_finalize_compilation", + "descriptor_kind": "staticmethod" + }, + { + "module": "openhcs.core.pipeline.compiler", + "owner": "PipelineCompiler", + "method": "_axis_values_to_process", + "descriptor_kind": "staticmethod" + }, + { + "module": "openhcs.core.pipeline.compiler", + "owner": "AxisCompilationRequest", + "method": "context_for", + "descriptor_kind": "function" + }, + { + "module": "openhcs.processing.backends.lib_registry.unified_registry", + "owner": "RuntimeCallableInvocation", + "method": "call", + "descriptor_kind": "function" + }, + { + "module": "openhcs.core.orchestrator.analysis_consolidation", + "owner": "", + "method": "consolidate_analysis_outputs", + "descriptor_kind": "function" + }, + { + "module": "openhcs.core.orchestrator.worker_execution", + "owner": "", + "method": "execute_worker_lane", + "descriptor_kind": "function" + }, + { + "module": "openhcs.core.orchestrator.orchestrator", + "owner": "PipelineOrchestrator", + "method": "create_context", + "descriptor_kind": "function" + }, + { + "module": "openhcs.core.orchestrator.orchestrator", + "owner": "PipelineOrchestrator", + "method": "get_effective_config", + "descriptor_kind": "function" + }, + { + "module": "openhcs.runtime.zmq_execution_server", + "owner": "ZMQExecutionServer", + "method": "_execute_with_orchestrator", + "descriptor_kind": "function" + }, + { + "module": "openhcs.runtime.zmq_execution_server", + "owner": "ZMQExecutionServer", + "method": "_initialize_orchestrator", + "descriptor_kind": "function" + }, + { + "module": "openhcs.runtime.zmq_execution_server", + "owner": "ZMQExecutionServer", + "method": "_export_runtime_observation", + "descriptor_kind": "function" + }, + { + "module": "openhcs.interop.cellprofiler.runtime.function_contract_execution", + "owner": "CellProfilerFunctionContractExecutor", + "method": "execute", + "descriptor_kind": "function" + }, + { + "module": "openhcs.interop.cellprofiler.runtime.measurement_execution_support", + "owner": "ObjectMeasurementOutputRecorder", + "method": "record", + "descriptor_kind": "function" + }, + { + "module": "openhcs.interop.cellprofiler.runtime.output_recording", + "owner": "CellProfilerOutputRecorder", + "method": "record_module_outputs", + "descriptor_kind": "classmethod" + }, + { + "module": "openhcs.interop.cellprofiler.runtime.module_execution", + "owner": "CellProfilerModuleExecutor", + "method": "__call__", + "descriptor_kind": "function" + }, + { + "module": "openhcs.interop.cellprofiler.runtime.module_execution", + "owner": "CellProfilerModuleExecutor", + "method": "_image_request", + "descriptor_kind": "function" + } + ], + "profiling_enabled": false, + "runtime_profiling_enabled": false, + "diagnostic_errors": [], + "captures": false, + "scope": "coarse same-run nested exclusive timing partition on the exact source revision recorded in this region. Diagnostic wrappers, no scientific or memory-observer substitutions. Not accepted performance comparison. Declared callable boundary includes filtering/decorated processing/metadata; not pure numerical kernels. Both existing profilers are disabled. These wrappers still add diagnostic overhead; no scaling to uninstrumented clocks or causal performance claims. Compiler/state boundaries and query boundary are nested under actual parents and excluded from parent-exclusive elapsed. This is a NEW 41-hook diagnostic version; inherited 24 boundary labels remain, site bytes are changed. ObjectState is verified against the actual source dependency path, not assumed inside the OpenHCS package." +} diff --git a/benchmark/results/perf_compile_runtime_ledger_20261003/controls.json b/benchmark/results/perf_compile_runtime_ledger_20261003/controls.json new file mode 100644 index 0000000000..2205f1cc27 --- /dev/null +++ b/benchmark/results/perf_compile_runtime_ledger_20261003/controls.json @@ -0,0 +1,24 @@ +{ + "status": "PASS", + "controls": [ + "original_called_once", + "argument_mutation_and_result_identity", + "signature_wrapped_code", + "nested_exclusive_conservation", + "error_identity_and_mutation", + "finally_restores_nested_state", + "root_namespace_no_overwrite", + "outside_root_ready_passthrough", + "fork_tls_reset", + "source_loader_real_declaring_path", + "instance_descriptor", + "classmethod_descriptor", + "staticmethod_descriptor", + "source_hash_drift_refusal", + "unchanged_storage_caps_and_41_hook_roster" + ], + "count": 15, + "site_sha256": "339c145b2c13548589958d12ebfe77672f87a108c82cbb44dbe1fdcc929d024b", + "controller_sha256": "5460564d44ffdc7e70078d63ac1250bb65a4fff2320da8dcb89b06fba999602f", + "scope": "Temporary test-owned source only, original result/error/mutation and descriptor/path/hash laws; no candidate pipeline import, compile, execution, profiler, snapshot or processing callback invocation." +} diff --git a/benchmark/results/perf_compile_runtime_ledger_20261003/execution-region.json b/benchmark/results/perf_compile_runtime_ledger_20261003/execution-region.json new file mode 100644 index 0000000000..5aa3f135dc --- /dev/null +++ b/benchmark/results/perf_compile_runtime_ledger_20261003/execution-region.json @@ -0,0 +1,864 @@ +{ + "pid": 1948899, + "thread": 139659153200832, + "region": "ZMQExecutionServer._execute_with_orchestrator", + "root_dimensions": "{\"case\": \"3d_monolayer_final\", \"compile_artifact_id\": \"8aba2e39-4db0-4608-bf23-08568aef528e\", \"execution_id\": \"37e4bb4a-7f5d-463a-a17f-ff8ff7dee0f9\", \"kind\": \"execution\", \"plate\": \"/home/ts/.cache/openhcs/benchmark_datasets/CellProfiler_tutorials/data/3d_monolayer/images\"}", + "seconds": 8.383970148861408, + "revision": "480aed49b30448de4380af5c9274e48084e67b63", + "source": "/home/ts/code/projects/openhcs-shared-runtime-plumbing", + "stats": { + "ObjectState._compute_resolved_snapshot": { + "owner": "ObjectState._compute_resolved_snapshot", + "dimensions": "", + "phase": "compiler_config:_compute_resolved_snapshot", + "calls": 8, + "inclusive": 0.04228230891749263, + "exclusive": 0.04228230891749263 + }, + "ObjectState.__init__": { + "owner": "ObjectState.__init__", + "dimensions": "", + "phase": "compiler_config:__init__", + "calls": 4, + "inclusive": 0.05480403359979391, + "exclusive": 0.012521724682301283 + }, + "ObjectState._reconstruct_from_resolved": { + "owner": "ObjectState._reconstruct_from_resolved", + "dimensions": "", + "phase": "compiler_config:_reconstruct_from_resolved", + "calls": 92, + "inclusive": 0.013641910627484322, + "exclusive": 0.007105355150997639 + }, + "ObjectState.to_saved_resolved_object": { + "owner": "ObjectState.to_saved_resolved_object", + "dimensions": "", + "phase": "compiler_config:to_saved_resolved_object", + "calls": 4, + "inclusive": 0.007119361776858568, + "exclusive": 1.4006625860929489e-05 + }, + "PipelineOrchestrator.get_effective_config": { + "owner": "PipelineOrchestrator.get_effective_config", + "dimensions": "", + "phase": "compiler_config:get_effective_config", + "calls": 4, + "inclusive": 0.06195876281708479, + "exclusive": 3.5367440432310104e-05 + }, + "PipelineOrchestrator.create_context": { + "owner": "PipelineOrchestrator.create_context", + "dimensions": "", + "phase": "compiler_config:create_context", + "calls": 1, + "inclusive": 0.014066982083022594, + "exclusive": 6.845779716968536e-05 + }, + "ZMQExecutionServer._initialize_orchestrator": { + "owner": "ZMQExecutionServer._initialize_orchestrator", + "dimensions": "", + "phase": "_initialize_orchestrator", + "calls": 1, + "inclusive": 0.08127375598996878, + "exclusive": 0.019246535375714302 + }, + "RuntimeImageStackCache.get": { + "owner": "RuntimeImageStackCache.get", + "dimensions": "", + "phase": "get", + "calls": 32, + "inclusive": 0.00039217015728354454, + "exclusive": 0.00039217015728354454 + }, + "stack_image_payload_context": { + "owner": "stack_image_payload_context", + "dimensions": "", + "phase": "stack_image_payload_context", + "calls": 28, + "inclusive": 0.04806605773046613, + "exclusive": 0.04806605773046613 + }, + "PatternGroupRuntime._load_input_stack": { + "owner": "PatternGroupRuntime._load_input_stack", + "dimensions": "", + "phase": "_load_input_stack", + "calls": 32, + "inclusive": 0.7971800449304283, + "exclusive": 0.7817966351285577 + }, + "CellProfilerModuleExecutor._image_request": { + "owner": "CellProfilerModuleExecutor._image_request", + "dimensions": "", + "phase": "_image_request", + "calls": 30, + "inclusive": 0.315012420527637, + "exclusive": 0.315012420527637 + }, + "RuntimeCallableInvocation.call | function=openhcs.processing.backends.cellprofiler.intensity.rescale_intensity;view=1": { + "owner": "RuntimeCallableInvocation.call", + "dimensions": "function=openhcs.processing.backends.cellprofiler.intensity.rescale_intensity;view=1", + "phase": "declared_callable_boundary", + "calls": 2, + "inclusive": 0.019795356784015894, + "exclusive": 0.019795356784015894 + }, + "CellProfilerFunctionContractExecutor.execute | function=openhcs.processing.backends.cellprofiler.intensity.rescale_intensity": { + "owner": "CellProfilerFunctionContractExecutor.execute", + "dimensions": "function=openhcs.processing.backends.cellprofiler.intensity.rescale_intensity", + "phase": "execute", + "calls": 2, + "inclusive": 0.02052792627364397, + "exclusive": 0.0007325694896280766 + }, + "CellProfilerOutputRecorder.record_module_outputs": { + "owner": "CellProfilerOutputRecorder.record_module_outputs", + "dimensions": "", + "phase": "record_module_outputs", + "calls": 26, + "inclusive": 0.3821194381453097, + "exclusive": 0.3821194381453097 + }, + "CellProfilerModuleExecutor.__call__": { + "owner": "CellProfilerModuleExecutor.__call__", + "dimensions": "", + "phase": "__call__", + "calls": 32, + "inclusive": 4.5760794640518725, + "exclusive": 0.17213439382612705 + }, + "FunctionCoreExecutor.execute | function=rescale_intensity": { + "owner": "FunctionCoreExecutor.execute", + "dimensions": "function=rescale_intensity", + "phase": "execute", + "calls": 2, + "inclusive": 0.15594422025606036, + "exclusive": 0.00037235114723443985 + }, + "PatternGroupRuntime._validate_and_unstack": { + "owner": "PatternGroupRuntime._validate_and_unstack", + "dimensions": "", + "phase": "_validate_and_unstack", + "calls": 28, + "inclusive": 0.22986850701272488, + "exclusive": 0.1967936889268458 + }, + "RuntimeImageStackCache.store": { + "owner": "RuntimeImageStackCache.store", + "dimensions": "", + "phase": "store", + "calls": 28, + "inclusive": 0.00023420248180627823, + "exclusive": 0.00023420248180627823 + }, + "PatternGroupRuntime._save_outputs": { + "owner": "PatternGroupRuntime._save_outputs", + "dimensions": "", + "phase": "_save_outputs", + "calls": 28, + "inclusive": 0.6679928456433117, + "exclusive": 0.6677586431615055 + }, + "finalize_function_step_outputs": { + "owner": "finalize_function_step_outputs", + "dimensions": "", + "phase": "finalize_function_step_outputs", + "calls": 30, + "inclusive": 0.7330579869449139, + "exclusive": 0.462262537330389 + }, + "RuntimeCallableInvocation.call | function=openhcs.processing.backends.cellprofiler.image_geometry.resize_volumetric;view=1": { + "owner": "RuntimeCallableInvocation.call", + "dimensions": "function=openhcs.processing.backends.cellprofiler.image_geometry.resize_volumetric;view=1", + "phase": "declared_callable_boundary", + "calls": 3, + "inclusive": 0.12900878163054585, + "exclusive": 0.12900878163054585 + }, + "CellProfilerFunctionContractExecutor.execute | function=openhcs.processing.backends.cellprofiler.image_geometry.resize_volumetric": { + "owner": "CellProfilerFunctionContractExecutor.execute", + "dimensions": "function=openhcs.processing.backends.cellprofiler.image_geometry.resize_volumetric", + "phase": "execute", + "calls": 3, + "inclusive": 0.12965055974200368, + "exclusive": 0.0006417781114578247 + }, + "FunctionCoreExecutor.execute | function=resize_volumetric": { + "owner": "FunctionCoreExecutor.execute", + "dimensions": "function=resize_volumetric", + "phase": "execute", + "calls": 3, + "inclusive": 0.19211693992838264, + "exclusive": 0.0007436810992658138 + }, + "RuntimeCallableInvocation.call | function=openhcs.processing.backends.cellprofiler.median_filter.medianfilter;view=1": { + "owner": "RuntimeCallableInvocation.call", + "dimensions": "function=openhcs.processing.backends.cellprofiler.median_filter.medianfilter;view=1", + "phase": "declared_callable_boundary", + "calls": 1, + "inclusive": 0.4724126742221415, + "exclusive": 0.4724126742221415 + }, + "CellProfilerFunctionContractExecutor.execute | function=openhcs.processing.backends.cellprofiler.median_filter.medianfilter": { + "owner": "CellProfilerFunctionContractExecutor.execute", + "dimensions": "function=openhcs.processing.backends.cellprofiler.median_filter.medianfilter", + "phase": "execute", + "calls": 1, + "inclusive": 0.47297679586336017, + "exclusive": 0.0005641216412186623 + }, + "FunctionCoreExecutor.execute | function=medianfilter": { + "owner": "FunctionCoreExecutor.execute", + "dimensions": "function=medianfilter", + "phase": "execute", + "calls": 1, + "inclusive": 0.4928359529003501, + "exclusive": 0.000936092808842659 + }, + "RuntimeCallableInvocation.call | function=openhcs.processing.backends.cellprofiler.thresholding.threshold;view=1": { + "owner": "RuntimeCallableInvocation.call", + "dimensions": "function=openhcs.processing.backends.cellprofiler.thresholding.threshold;view=1", + "phase": "declared_callable_boundary", + "calls": 3, + "inclusive": 0.4487679689191282, + "exclusive": 0.4487679689191282 + }, + "CellProfilerFunctionContractExecutor.execute | function=openhcs.processing.backends.cellprofiler.thresholding.threshold": { + "owner": "CellProfilerFunctionContractExecutor.execute", + "dimensions": "function=openhcs.processing.backends.cellprofiler.thresholding.threshold", + "phase": "execute", + "calls": 3, + "inclusive": 0.44994965521618724, + "exclusive": 0.0011816862970590591 + }, + "FunctionCoreExecutor.execute | function=threshold": { + "owner": "FunctionCoreExecutor.execute", + "dimensions": "function=threshold", + "phase": "execute", + "calls": 3, + "inclusive": 0.5471520069986582, + "exclusive": 0.0035848570987582207 + }, + "RuntimeCallableInvocation.call | function=openhcs.processing.backends.cellprofiler.morphology.remove_holes_3d;view=1": { + "owner": "RuntimeCallableInvocation.call", + "dimensions": "function=openhcs.processing.backends.cellprofiler.morphology.remove_holes_3d;view=1", + "phase": "declared_callable_boundary", + "calls": 2, + "inclusive": 0.09644329408183694, + "exclusive": 0.09644329408183694 + }, + "CellProfilerFunctionContractExecutor.execute | function=openhcs.processing.backends.cellprofiler.morphology.remove_holes_3d": { + "owner": "CellProfilerFunctionContractExecutor.execute", + "dimensions": "function=openhcs.processing.backends.cellprofiler.morphology.remove_holes_3d", + "phase": "execute", + "calls": 2, + "inclusive": 0.09670406440272927, + "exclusive": 0.000260770320892334 + }, + "FunctionCoreExecutor.execute | function=remove_holes_3d": { + "owner": "FunctionCoreExecutor.execute", + "dimensions": "function=remove_holes_3d", + "phase": "execute", + "calls": 2, + "inclusive": 0.10615720180794597, + "exclusive": 0.0004928689450025558 + }, + "RuntimeCallableInvocation.call | function=openhcs.processing.backends.cellprofiler.watershed.watershed_cellprofiler4;view=1": { + "owner": "RuntimeCallableInvocation.call", + "dimensions": "function=openhcs.processing.backends.cellprofiler.watershed.watershed_cellprofiler4;view=1", + "phase": "declared_callable_boundary", + "calls": 2, + "inclusive": 0.49590820586308837, + "exclusive": 0.49590820586308837 + }, + "CellProfilerFunctionContractExecutor.execute | function=openhcs.processing.backends.cellprofiler.watershed.watershed_cellprofiler4": { + "owner": "CellProfilerFunctionContractExecutor.execute", + "dimensions": "function=openhcs.processing.backends.cellprofiler.watershed.watershed_cellprofiler4", + "phase": "execute", + "calls": 2, + "inclusive": 0.49647813895717263, + "exclusive": 0.0005699330940842628 + }, + "FunctionCoreExecutor.execute | function=watershed_cellprofiler4": { + "owner": "FunctionCoreExecutor.execute", + "dimensions": "function=watershed_cellprofiler4", + "phase": "execute", + "calls": 2, + "inclusive": 0.5379135445691645, + "exclusive": 0.002366554457694292 + }, + "RuntimeCallableInvocation.call | function=openhcs.processing.backends.cellprofiler.morphology.resize_objects_3d;view=1": { + "owner": "RuntimeCallableInvocation.call", + "dimensions": "function=openhcs.processing.backends.cellprofiler.morphology.resize_objects_3d;view=1", + "phase": "declared_callable_boundary", + "calls": 2, + "inclusive": 0.07325948867946863, + "exclusive": 0.07325948867946863 + }, + "CellProfilerFunctionContractExecutor.execute | function=openhcs.processing.backends.cellprofiler.morphology.resize_objects_3d": { + "owner": "CellProfilerFunctionContractExecutor.execute", + "dimensions": "function=openhcs.processing.backends.cellprofiler.morphology.resize_objects_3d", + "phase": "execute", + "calls": 2, + "inclusive": 0.07387770200148225, + "exclusive": 0.0006182133220136166 + }, + "FunctionCoreExecutor.execute | function=resize_objects_3d": { + "owner": "FunctionCoreExecutor.execute", + "dimensions": "function=resize_objects_3d", + "phase": "execute", + "calls": 2, + "inclusive": 0.10657328553497791, + "exclusive": 0.0009544077329337597 + }, + "RuntimeCallableInvocation.call | function=openhcs.processing.backends.cellprofiler.morphology.erode_objects;view=1": { + "owner": "RuntimeCallableInvocation.call", + "dimensions": "function=openhcs.processing.backends.cellprofiler.morphology.erode_objects;view=1", + "phase": "declared_callable_boundary", + "calls": 1, + "inclusive": 0.04853436117991805, + "exclusive": 0.04853436117991805 + }, + "CellProfilerFunctionContractExecutor.execute | function=openhcs.processing.backends.cellprofiler.morphology.erode_objects": { + "owner": "CellProfilerFunctionContractExecutor.execute", + "dimensions": "function=openhcs.processing.backends.cellprofiler.morphology.erode_objects", + "phase": "execute", + "calls": 1, + "inclusive": 0.04904478183016181, + "exclusive": 0.0005104206502437592 + }, + "FunctionCoreExecutor.execute | function=erode_objects": { + "owner": "FunctionCoreExecutor.execute", + "dimensions": "function=erode_objects", + "phase": "execute", + "calls": 1, + "inclusive": 0.058804776053875685, + "exclusive": 0.00045938510447740555 + }, + "RuntimeCallableInvocation.call | function=openhcs.processing.backends.cellprofiler.object_images.convert_objects_to_image;view=1": { + "owner": "RuntimeCallableInvocation.call", + "dimensions": "function=openhcs.processing.backends.cellprofiler.object_images.convert_objects_to_image;view=1", + "phase": "declared_callable_boundary", + "calls": 3, + "inclusive": 0.007222956977784634, + "exclusive": 0.007222956977784634 + }, + "CellProfilerFunctionContractExecutor.execute | function=openhcs.processing.backends.cellprofiler.object_images.convert_objects_to_image": { + "owner": "CellProfilerFunctionContractExecutor.execute", + "dimensions": "function=openhcs.processing.backends.cellprofiler.object_images.convert_objects_to_image", + "phase": "execute", + "calls": 3, + "inclusive": 0.007992795202881098, + "exclusive": 0.0007698382250964642 + }, + "FunctionCoreExecutor.execute | function=convert_objects_to_image": { + "owner": "FunctionCoreExecutor.execute", + "dimensions": "function=convert_objects_to_image", + "phase": "execute", + "calls": 3, + "inclusive": 0.05049174604937434, + "exclusive": 0.001049565151333809 + }, + "RuntimeCallableInvocation.call | function=openhcs.processing.backends.cellprofiler.image_math.image_math;view=1": { + "owner": "RuntimeCallableInvocation.call", + "dimensions": "function=openhcs.processing.backends.cellprofiler.image_math.image_math;view=1", + "phase": "declared_callable_boundary", + "calls": 120, + "inclusive": 0.05379005940631032, + "exclusive": 0.05379005940631032 + }, + "CellProfilerFunctionContractExecutor.execute | function=openhcs.processing.backends.cellprofiler.image_math.image_math": { + "owner": "CellProfilerFunctionContractExecutor.execute", + "dimensions": "function=openhcs.processing.backends.cellprofiler.image_math.image_math", + "phase": "execute", + "calls": 2, + "inclusive": 0.07124726008623838, + "exclusive": 0.017457200679928064 + }, + "FunctionCoreExecutor.execute | function=image_math": { + "owner": "FunctionCoreExecutor.execute", + "dimensions": "function=image_math", + "phase": "execute", + "calls": 2, + "inclusive": 0.30010355403646827, + "exclusive": 0.0004685823805630207 + }, + "RuntimeCallableInvocation.call | function=openhcs.processing.backends.cellprofiler.morphology.closing;view=1": { + "owner": "RuntimeCallableInvocation.call", + "dimensions": "function=openhcs.processing.backends.cellprofiler.morphology.closing;view=1", + "phase": "declared_callable_boundary", + "calls": 1, + "inclusive": 0.2624981193803251, + "exclusive": 0.2624981193803251 + }, + "CellProfilerFunctionContractExecutor.execute | function=openhcs.processing.backends.cellprofiler.morphology.closing": { + "owner": "CellProfilerFunctionContractExecutor.execute", + "dimensions": "function=openhcs.processing.backends.cellprofiler.morphology.closing", + "phase": "execute", + "calls": 1, + "inclusive": 0.2625978058204055, + "exclusive": 9.968644008040428e-05 + }, + "FunctionCoreExecutor.execute | function=closing": { + "owner": "FunctionCoreExecutor.execute", + "dimensions": "function=closing", + "phase": "execute", + "calls": 1, + "inclusive": 0.2876937221735716, + "exclusive": 0.00026171188801527023 + }, + "RuntimeCallableInvocation.call | function=openhcs.processing.backends.cellprofiler.image_geometry.mask_image;view=1": { + "owner": "RuntimeCallableInvocation.call", + "dimensions": "function=openhcs.processing.backends.cellprofiler.image_geometry.mask_image;view=1", + "phase": "declared_callable_boundary", + "calls": 60, + "inclusive": 0.015584377571940422, + "exclusive": 0.015584377571940422 + }, + "CellProfilerFunctionContractExecutor.execute | function=openhcs.processing.backends.cellprofiler.image_geometry.mask_image": { + "owner": "CellProfilerFunctionContractExecutor.execute", + "dimensions": "function=openhcs.processing.backends.cellprofiler.image_geometry.mask_image", + "phase": "execute", + "calls": 1, + "inclusive": 0.03287788573652506, + "exclusive": 0.017293508164584637 + }, + "FunctionCoreExecutor.execute | function=mask_image": { + "owner": "FunctionCoreExecutor.execute", + "dimensions": "function=mask_image", + "phase": "execute", + "calls": 1, + "inclusive": 0.05533677665516734, + "exclusive": 0.0003833817318081856 + }, + "RuntimeCallableInvocation.call | function=openhcs.processing.backends.cellprofiler.morphology.erode_image;view=1": { + "owner": "RuntimeCallableInvocation.call", + "dimensions": "function=openhcs.processing.backends.cellprofiler.morphology.erode_image;view=1", + "phase": "declared_callable_boundary", + "calls": 1, + "inclusive": 0.03985383827239275, + "exclusive": 0.03985383827239275 + }, + "CellProfilerFunctionContractExecutor.execute | function=openhcs.processing.backends.cellprofiler.morphology.erode_image": { + "owner": "CellProfilerFunctionContractExecutor.execute", + "dimensions": "function=openhcs.processing.backends.cellprofiler.morphology.erode_image", + "phase": "execute", + "calls": 1, + "inclusive": 0.03997136000543833, + "exclusive": 0.000117521733045578 + }, + "FunctionCoreExecutor.execute | function=erode_image": { + "owner": "FunctionCoreExecutor.execute", + "dimensions": "function=erode_image", + "phase": "execute", + "calls": 1, + "inclusive": 0.044346907176077366, + "exclusive": 0.00028765155002474785 + }, + "RuntimeCallableInvocation.call | function=openhcs.processing.backends.cellprofiler.intensity.measure_object_intensity;view=1": { + "owner": "RuntimeCallableInvocation.call", + "dimensions": "function=openhcs.processing.backends.cellprofiler.intensity.measure_object_intensity;view=1", + "phase": "declared_callable_boundary", + "calls": 4, + "inclusive": 0.7575583099387586, + "exclusive": 0.7575583099387586 + }, + "CellProfilerFunctionContractExecutor.execute | function=openhcs.processing.backends.cellprofiler.intensity.measure_object_intensity": { + "owner": "CellProfilerFunctionContractExecutor.execute", + "dimensions": "function=openhcs.processing.backends.cellprofiler.intensity.measure_object_intensity", + "phase": "execute", + "calls": 4, + "inclusive": 0.7582870102487504, + "exclusive": 0.0007287003099918365 + }, + "ObjectMeasurementOutputRecorder.record": { + "owner": "ObjectMeasurementOutputRecorder.record", + "dimensions": "", + "phase": "record", + "calls": 6, + "inclusive": 0.0037890542298555374, + "exclusive": 0.0037890542298555374 + }, + "FunctionCoreExecutor.execute | function=measure_object_intensity": { + "owner": "FunctionCoreExecutor.execute", + "dimensions": "function=measure_object_intensity", + "phase": "execute", + "calls": 4, + "inclusive": 0.8959525804966688, + "exclusive": 0.003980354871600866 + }, + "RuntimeCallableInvocation.call | function=openhcs.processing.backends.cellprofiler.shape.measure_object_size_shape;view=1": { + "owner": "RuntimeCallableInvocation.call", + "dimensions": "function=openhcs.processing.backends.cellprofiler.shape.measure_object_size_shape;view=1", + "phase": "declared_callable_boundary", + "calls": 2, + "inclusive": 0.5079499268904328, + "exclusive": 0.5079499268904328 + }, + "CellProfilerFunctionContractExecutor.execute | function=openhcs.processing.backends.cellprofiler.shape.measure_object_size_shape": { + "owner": "CellProfilerFunctionContractExecutor.execute", + "dimensions": "function=openhcs.processing.backends.cellprofiler.shape.measure_object_size_shape", + "phase": "execute", + "calls": 2, + "inclusive": 0.5088439187966287, + "exclusive": 0.000893991906195879 + }, + "FunctionCoreExecutor.execute | function=measure_object_size_shape": { + "owner": "FunctionCoreExecutor.execute", + "dimensions": "function=measure_object_size_shape", + "phase": "execute", + "calls": 2, + "inclusive": 0.5192161961458623, + "exclusive": 0.0021115639247000217 + }, + "RuntimeCallableInvocation.call | function=openhcs.processing.backends.cellprofiler.outlines.overlay_objects;view=1": { + "owner": "RuntimeCallableInvocation.call", + "dimensions": "function=openhcs.processing.backends.cellprofiler.outlines.overlay_objects;view=1", + "phase": "declared_callable_boundary", + "calls": 2, + "inclusive": 0.2317779059521854, + "exclusive": 0.2317779059521854 + }, + "CellProfilerFunctionContractExecutor.execute | function=openhcs.processing.backends.cellprofiler.outlines.overlay_objects": { + "owner": "CellProfilerFunctionContractExecutor.execute", + "dimensions": "function=openhcs.processing.backends.cellprofiler.outlines.overlay_objects", + "phase": "execute", + "calls": 2, + "inclusive": 0.23199649713933468, + "exclusive": 0.00021859118714928627 + }, + "FunctionCoreExecutor.execute | function=overlay_objects": { + "owner": "FunctionCoreExecutor.execute", + "dimensions": "function=overlay_objects", + "phase": "execute", + "calls": 2, + "inclusive": 0.2562795919366181, + "exclusive": 0.01238652877509594 + }, + "RuntimeCallableInvocation.call | function=openhcs.processing.backends.cellprofiler.save_images.save_images;view=1": { + "owner": "RuntimeCallableInvocation.call", + "dimensions": "function=openhcs.processing.backends.cellprofiler.save_images.save_images;view=1", + "phase": "declared_callable_boundary", + "calls": 2, + "inclusive": 0.00015609385445713997, + "exclusive": 0.00015609385445713997 + }, + "FunctionCoreExecutor.execute | function=save_images": { + "owner": "FunctionCoreExecutor.execute", + "dimensions": "function=save_images", + "phase": "execute", + "calls": 2, + "inclusive": 0.17327799275517464, + "exclusive": 0.1731218989007175 + }, + "AtomicMetadataWriter.publish_source_projection_metadata": { + "owner": "AtomicMetadataWriter.publish_source_projection_metadata", + "dimensions": "", + "phase": "publish_source_projection_metadata", + "calls": 5, + "inclusive": 0.5022010854445398, + "exclusive": 0.5022010854445398 + }, + "execute_worker_lane | {\"execution_id\": \"37e4bb4a-7f5d-463a-a17f-ff8ff7dee0f9\", \"kind\": \"worker_lane\", \"plate\": \"/home/ts/.cache/openhcs/benchmark_datasets/CellProfiler_tutorials/data/3d_monolayer/images\", \"worker_slot\": \"worker_0\"}": { + "owner": "execute_worker_lane", + "dimensions": "{\"execution_id\": \"37e4bb4a-7f5d-463a-a17f-ff8ff7dee0f9\", \"kind\": \"worker_lane\", \"plate\": \"/home/ts/.cache/openhcs/benchmark_datasets/CellProfiler_tutorials/data/3d_monolayer/images\", \"worker_slot\": \"worker_0\"}", + "phase": "execute_worker_lane", + "calls": 1, + "inclusive": 7.710202364251018, + "exclusive": 0.5019059842452407 + }, + "consolidate_analysis_outputs": { + "owner": "consolidate_analysis_outputs", + "dimensions": "", + "phase": "consolidate_analysis_outputs", + "calls": 1, + "inclusive": 1.0580290108919144e-05, + "exclusive": 1.0580290108919144e-05 + }, + "RuntimeArtifactMetadataTarget.reconciliation_targets": { + "owner": "RuntimeArtifactMetadataTarget.reconciliation_targets", + "dimensions": "", + "phase": "reconciliation_targets", + "calls": 1, + "inclusive": 0.29502451280131936, + "exclusive": 0.29502451280131936 + }, + "OpenHCSMetadataWriter.finalize_completed_plate": { + "owner": "OpenHCSMetadataWriter.finalize_completed_plate", + "dimensions": "", + "phase": "finalize_completed_plate", + "calls": 1, + "inclusive": 0.5092654940672219, + "exclusive": 0.008654322475194931 + }, + "ZMQExecutionServer._export_runtime_observation": { + "owner": "ZMQExecutionServer._export_runtime_observation", + "dimensions": "", + "phase": "_export_runtime_observation", + "calls": 1, + "inclusive": 0.012431904673576355, + "exclusive": 0.012431904673576355 + }, + "ZMQExecutionServer._execute_with_orchestrator | {\"case\": \"3d_monolayer_final\", \"compile_artifact_id\": \"8aba2e39-4db0-4608-bf23-08568aef528e\", \"execution_id\": \"37e4bb4a-7f5d-463a-a17f-ff8ff7dee0f9\", \"kind\": \"execution\", \"plate\": \"/home/ts/.cache/openhcs/benchmark_datasets/CellProfiler_tutorials/data/3d_monolayer/images\"}": { + "owner": "ZMQExecutionServer._execute_with_orchestrator", + "dimensions": "{\"case\": \"3d_monolayer_final\", \"compile_artifact_id\": \"8aba2e39-4db0-4608-bf23-08568aef528e\", \"execution_id\": \"37e4bb4a-7f5d-463a-a17f-ff8ff7dee0f9\", \"kind\": \"execution\", \"plate\": \"/home/ts/.cache/openhcs/benchmark_datasets/CellProfiler_tutorials/data/3d_monolayer/images\"}", + "phase": "_execute_with_orchestrator", + "calls": 1, + "inclusive": 8.383970148861408, + "exclusive": 0.044967072550207376 + } + }, + "hooks_installed": [ + { + "module": "objectstate.object_state", + "owner": "ObjectState", + "method": "__init__", + "descriptor_kind": "function" + }, + { + "module": "objectstate.object_state", + "owner": "ObjectState", + "method": "_compute_resolved_snapshot", + "descriptor_kind": "function" + }, + { + "module": "objectstate.object_state", + "owner": "ObjectState", + "method": "_reconstruct_from_resolved", + "descriptor_kind": "function" + }, + { + "module": "objectstate.object_state", + "owner": "ObjectState", + "method": "to_saved_resolved_object", + "descriptor_kind": "function" + }, + { + "module": "openhcs.core.aligned_image_payload", + "owner": "", + "method": "stack_image_payload_context", + "descriptor_kind": "function" + }, + { + "module": "openhcs.core.aligned_image_payload", + "owner": "", + "method": "unstack_image_payload_context", + "descriptor_kind": "function" + }, + { + "module": "openhcs.core.measurement_feature_queries", + "owner": "MeasurementFeatureValueIndex", + "method": "from_columnar_table_by_object", + "descriptor_kind": "classmethod" + }, + { + "module": "openhcs.core.virtual_workspace_metadata", + "owner": "AtomicMetadataWriter", + "method": "publish_source_projection_metadata", + "descriptor_kind": "function" + }, + { + "module": "openhcs.core.runtime_stack_cache", + "owner": "RuntimeImageStackCache", + "method": "get", + "descriptor_kind": "function" + }, + { + "module": "openhcs.core.runtime_stack_cache", + "owner": "RuntimeImageStackCache", + "method": "store", + "descriptor_kind": "function" + }, + { + "module": "openhcs.core.steps.function_outputs", + "owner": "", + "method": "finalize_function_step_outputs", + "descriptor_kind": "function" + }, + { + "module": "openhcs.core.steps.function_outputs", + "owner": "OpenHCSMetadataWriter", + "method": "finalize_completed_plate", + "descriptor_kind": "classmethod" + }, + { + "module": "openhcs.core.steps.function_outputs", + "owner": "RuntimeArtifactMetadataTarget", + "method": "reconciliation_targets", + "descriptor_kind": "function" + }, + { + "module": "openhcs.core.steps.function_runtime", + "owner": "FunctionCoreExecutor", + "method": "execute", + "descriptor_kind": "function" + }, + { + "module": "openhcs.core.steps.function_runtime", + "owner": "PatternGroupRuntime", + "method": "_load_input_stack", + "descriptor_kind": "function" + }, + { + "module": "openhcs.core.steps.function_runtime", + "owner": "PatternGroupRuntime", + "method": "_validate_and_unstack", + "descriptor_kind": "function" + }, + { + "module": "openhcs.core.steps.function_runtime", + "owner": "PatternGroupRuntime", + "method": "_save_outputs", + "descriptor_kind": "function" + }, + { + "module": "openhcs.core.pipeline.compilation_session", + "owner": "CompilationSession", + "method": "from_context", + "descriptor_kind": "classmethod" + }, + { + "module": "openhcs.core.pipeline.compiler", + "owner": "PipelineCompiler", + "method": "compile_pipelines", + "descriptor_kind": "staticmethod" + }, + { + "module": "openhcs.core.pipeline.compiler", + "owner": "PipelineCompiler", + "method": "_register_and_resolve_pipeline_once", + "descriptor_kind": "staticmethod" + }, + { + "module": "openhcs.core.pipeline.compiler", + "owner": "PipelineCompiler", + "method": "initialize_step_plans_for_context", + "descriptor_kind": "staticmethod" + }, + { + "module": "openhcs.core.pipeline.compiler", + "owner": "PipelineCompiler", + "method": "_capture_pipeline_config", + "descriptor_kind": "staticmethod" + }, + { + "module": "openhcs.core.pipeline.compiler", + "owner": "PipelineCompiler", + "method": "_resolve_global_step_axis_filters", + "descriptor_kind": "staticmethod" + }, + { + "module": "openhcs.core.pipeline.compiler", + "owner": "PipelineCompiler", + "method": "_configure_input_conversion_if_needed", + "descriptor_kind": "staticmethod" + }, + { + "module": "openhcs.core.pipeline.compiler", + "owner": "PipelineCompiler", + "method": "declare_zarr_stores", + "descriptor_kind": "staticmethod" + }, + { + "module": "openhcs.core.pipeline.compiler", + "owner": "PipelineCompiler", + "method": "_finalize_compilation", + "descriptor_kind": "staticmethod" + }, + { + "module": "openhcs.core.pipeline.compiler", + "owner": "PipelineCompiler", + "method": "_axis_values_to_process", + "descriptor_kind": "staticmethod" + }, + { + "module": "openhcs.core.pipeline.compiler", + "owner": "AxisCompilationRequest", + "method": "context_for", + "descriptor_kind": "function" + }, + { + "module": "openhcs.processing.backends.lib_registry.unified_registry", + "owner": "RuntimeCallableInvocation", + "method": "call", + "descriptor_kind": "function" + }, + { + "module": "openhcs.core.orchestrator.analysis_consolidation", + "owner": "", + "method": "consolidate_analysis_outputs", + "descriptor_kind": "function" + }, + { + "module": "openhcs.core.orchestrator.worker_execution", + "owner": "", + "method": "execute_worker_lane", + "descriptor_kind": "function" + }, + { + "module": "openhcs.core.orchestrator.orchestrator", + "owner": "PipelineOrchestrator", + "method": "create_context", + "descriptor_kind": "function" + }, + { + "module": "openhcs.core.orchestrator.orchestrator", + "owner": "PipelineOrchestrator", + "method": "get_effective_config", + "descriptor_kind": "function" + }, + { + "module": "openhcs.runtime.zmq_execution_server", + "owner": "ZMQExecutionServer", + "method": "_execute_with_orchestrator", + "descriptor_kind": "function" + }, + { + "module": "openhcs.runtime.zmq_execution_server", + "owner": "ZMQExecutionServer", + "method": "_initialize_orchestrator", + "descriptor_kind": "function" + }, + { + "module": "openhcs.runtime.zmq_execution_server", + "owner": "ZMQExecutionServer", + "method": "_export_runtime_observation", + "descriptor_kind": "function" + }, + { + "module": "openhcs.interop.cellprofiler.runtime.function_contract_execution", + "owner": "CellProfilerFunctionContractExecutor", + "method": "execute", + "descriptor_kind": "function" + }, + { + "module": "openhcs.interop.cellprofiler.runtime.measurement_execution_support", + "owner": "ObjectMeasurementOutputRecorder", + "method": "record", + "descriptor_kind": "function" + }, + { + "module": "openhcs.interop.cellprofiler.runtime.output_recording", + "owner": "CellProfilerOutputRecorder", + "method": "record_module_outputs", + "descriptor_kind": "classmethod" + }, + { + "module": "openhcs.interop.cellprofiler.runtime.module_execution", + "owner": "CellProfilerModuleExecutor", + "method": "__call__", + "descriptor_kind": "function" + }, + { + "module": "openhcs.interop.cellprofiler.runtime.module_execution", + "owner": "CellProfilerModuleExecutor", + "method": "_image_request", + "descriptor_kind": "function" + } + ], + "profiling_enabled": false, + "runtime_profiling_enabled": false, + "diagnostic_errors": [], + "captures": false, + "scope": "coarse same-run nested exclusive timing partition on the exact source revision recorded in this region. Diagnostic wrappers, no scientific or memory-observer substitutions. Not accepted performance comparison. Declared callable boundary includes filtering/decorated processing/metadata; not pure numerical kernels. Both existing profilers are disabled. These wrappers still add diagnostic overhead; no scaling to uninstrumented clocks or causal performance claims. Compiler/state boundaries and query boundary are nested under actual parents and excluded from parent-exclusive elapsed. This is a NEW 41-hook diagnostic version; inherited 24 boundary labels remain, site bytes are changed. ObjectState is verified against the actual source dependency path, not assumed inside the OpenHCS package." +} diff --git a/benchmark/results/perf_compile_runtime_ledger_20261003/observations.json b/benchmark/results/perf_compile_runtime_ledger_20261003/observations.json new file mode 100644 index 0000000000..5cb4bc8ef7 --- /dev/null +++ b/benchmark/results/perf_compile_runtime_ledger_20261003/observations.json @@ -0,0 +1,63 @@ +{ + "returncode": 0, + "diagnostic_admission": true, + "public_rows": [ + { + "case_name": "cp_tutorial_3d_monolayer", + "mode_name": "1w_1t", + "worker_count": "1", + "well_count": "1", + "compile_seconds": "1.495826244354248", + "prepare_seconds": "0.0", + "execute_seconds": "8.396726846694946", + "total_seconds": "10.694032318890095", + "wells_per_second": "0.11909402535746559", + "successful_wells": "1", + "native_single_sample_execution_seconds": "", + "projected_native_execution_seconds": "", + "projected_execution_speedup": "", + "peak_memory_mb": "1658.1875", + "status": "success", + "memory_limit_mb": "", + "error_message": "", + "execution_route": "ordinary-zmq-outcomes-v1", + "server_lifecycle": "reused-per-sweep", + "run_input_sha256": "7f66dd478c9a56033495f056335a0eaadb9fd5facd953b504f0e1f8f7eaa57d5" + } + ], + "regions": [ + { + "path": "/home/ts/.local/state/openhcs-maintenance/20261003/compiler-config-coarse-ledger-v1/output/regions/region-1948899-139659153200832-0001.json", + "sha256": "6b604c99652c36aba1ce3eff39b65ccd73b71d17ca827c121a98676b4608c687" + }, + { + "path": "/home/ts/.local/state/openhcs-maintenance/20261003/compiler-config-coarse-ledger-v1/output/regions/region-1948899-139659153200832-0002.json", + "sha256": "ea2b9668eb40dc72c8af0ed9a6d55250fcd46721db5c5554fd0ea3c82ff738dd" + } + ], + "root_sequence_complete": true, + "actual_index_calls": 0, + "actual_declared_calls": 211, + "compile_only_actual_calls": { + "PipelineCompiler.compile_pipelines": 1, + "PipelineCompiler._register_and_resolve_pipeline_once": 1, + "PipelineCompiler._capture_pipeline_config": 1, + "AxisCompilationRequest.context_for": 1, + "CompilationSession.from_context": 1, + "PipelineOrchestrator.create_context": 3, + "PipelineOrchestrator.get_effective_config": 10, + "ObjectState.__init__": 44, + "ObjectState._compute_resolved_snapshot": 88, + "ObjectState._reconstruct_from_resolved": 532, + "ObjectState.to_saved_resolved_object": 42 + }, + "all_required_compiler_boundaries_reached": true, + "all41_hooks_installed": true, + "retained_json_bytes": 51356, + "generated_output_bytes": 18189886, + "public_log_bytes": 541, + "profiler_artifacts_absent": true, + "source_env_native_input_freeze": "PASS", + "science": "NOT_RUN: original full saved-output126file/schema/discrete/numerical/nativeinput witness separate gate. No exclusions or missing outputs waived.", + "scope": "One source-pinned ordinary3D Monolayer1w1t compiler/config diagnostic with NEW41 coarse nominal hooks: inherited24 plus17 compiler/state boundaries. Site is versioned/changed, not byte-identical. cProfile and runtime profiler OFF, no captures/percell hooks. Existing defaultOUTCOMES/memory observers/READY clocks unchanged. Same-thread nested exclusive clocks exclude query from its real ancestors; worker independent roots are not added to parent waits. Nearordinary diagnostic only; wrapper overhead remains, no scale factors/causal performance promotion. Full saved126file (6CSV120TIFF) science/native source witness independently required." +} diff --git a/benchmark/results/perf_compile_runtime_ledger_20261003/registration-owner-analysis.json b/benchmark/results/perf_compile_runtime_ledger_20261003/registration-owner-analysis.json new file mode 100644 index 0000000000..1a22d65121 --- /dev/null +++ b/benchmark/results/perf_compile_runtime_ledger_20261003/registration-owner-analysis.json @@ -0,0 +1,233 @@ +{ + "status": "CURRENT_DIAGNOSTIC_SCIENCE_PASS_READ_ONLY_OWNER_MAP", + "source_revision": "480aed49b30448de4380af5c9274e48084e67b63", + "source_unchanged_against_original_NRA_census": true, + "NRA_census": { + "path": "/home/ts/.local/state/openhcs-maintenance/20261003/compiler-config-transaction-map-v1/census.json", + "sha256": "60541e7bc14f20f6e9d698ac25ea6f094b5503a0670df2f893d83bb5564d3868", + "modules": 731, + "original_classes": 5302, + "selected_families": 67, + "all_source_hashes_revalidated": 731 + }, + "science_receipt": { + "path": "/home/ts/.local/state/openhcs-maintenance/20261003/compiler-config-coarse-ledger-v1/science.json", + "sha256": "d19e5294a829cf98a0d0730b2729224e8a6947f258641a6f0923dfc6af732d74" + }, + "timing": { + "compile_only": { + "root_seconds": 1.2609371892176569, + "owners": { + "ObjectState._compute_resolved_snapshot": { + "owner": "ObjectState._compute_resolved_snapshot", + "dimensions": "", + "phase": "compiler_config:_compute_resolved_snapshot", + "calls": 88, + "inclusive": 0.4525698209181428, + "exclusive": 0.4525698209181428 + }, + "ObjectState.__init__": { + "owner": "ObjectState.__init__", + "dimensions": "", + "phase": "compiler_config:__init__", + "calls": 44, + "inclusive": 0.6144807459786534, + "exclusive": 0.16191092506051064 + }, + "ObjectState._reconstruct_from_resolved": { + "owner": "ObjectState._reconstruct_from_resolved", + "dimensions": "", + "phase": "compiler_config:_reconstruct_from_resolved", + "calls": 532, + "inclusive": 0.1099232928827405, + "exclusive": 0.05649412330240011 + }, + "ObjectState.to_saved_resolved_object": { + "owner": "ObjectState.to_saved_resolved_object", + "dimensions": "", + "phase": "compiler_config:to_saved_resolved_object", + "calls": 42, + "inclusive": 0.056609060149639845, + "exclusive": 0.00011493684723973274 + }, + "PipelineOrchestrator.get_effective_config": { + "owner": "PipelineOrchestrator.get_effective_config", + "dimensions": "", + "phase": "compiler_config:get_effective_config", + "calls": 10, + "inclusive": 0.19583785673603415, + "exclusive": 8.42963345348835e-05 + }, + "PipelineOrchestrator.create_context": { + "owner": "PipelineOrchestrator.create_context", + "dimensions": "", + "phase": "compiler_config:create_context", + "calls": 3, + "inclusive": 0.04134061839431524, + "exclusive": 0.0006397129036486149 + }, + "PipelineCompiler._axis_values_to_process": { + "owner": "PipelineCompiler._axis_values_to_process", + "dimensions": "", + "phase": "compiler_config:_axis_values_to_process", + "calls": 1, + "inclusive": 0.017245036084204912, + "exclusive": 6.654579192399979e-05 + }, + "PipelineCompiler._register_and_resolve_pipeline_once": { + "owner": "PipelineCompiler._register_and_resolve_pipeline_once", + "dimensions": "", + "phase": "compiler_config:_register_and_resolve_pipeline_once", + "calls": 1, + "inclusive": 0.47889699088409543, + "exclusive": 0.005476511083543301 + }, + "PipelineCompiler._capture_pipeline_config": { + "owner": "PipelineCompiler._capture_pipeline_config", + "dimensions": "", + "phase": "compiler_config:_capture_pipeline_config", + "calls": 1, + "inclusive": 0.0019184919074177742, + "exclusive": 2.7259811758995056e-06 + }, + "PipelineCompiler._resolve_global_step_axis_filters": { + "owner": "PipelineCompiler._resolve_global_step_axis_filters", + "dimensions": "", + "phase": "compiler_config:_resolve_global_step_axis_filters", + "calls": 1, + "inclusive": 0.015254999045282602, + "exclusive": 0.001242930069565773 + }, + "AxisCompilationRequest.context_for": { + "owner": "AxisCompilationRequest.context_for", + "dimensions": "", + "phase": "compiler_config:context_for", + "calls": 1, + "inclusive": 0.013713276013731956, + "exclusive": 0.00032007182016968727 + }, + "CompilationSession.from_context": { + "owner": "CompilationSession.from_context", + "dimensions": "", + "phase": "compiler_config:from_context", + "calls": 1, + "inclusive": 2.0298175513744354e-05, + "exclusive": 2.0298175513744354e-05 + }, + "PipelineCompiler._configure_input_conversion_if_needed": { + "owner": "PipelineCompiler._configure_input_conversion_if_needed", + "dimensions": "", + "phase": "compiler_config:_configure_input_conversion_if_needed", + "calls": 1, + "inclusive": 0.013645949773490429, + "exclusive": 5.200039595365524e-06 + }, + "PipelineCompiler.initialize_step_plans_for_context": { + "owner": "PipelineCompiler.initialize_step_plans_for_context", + "dimensions": "", + "phase": "compiler_config:initialize_step_plans_for_context", + "calls": 1, + "inclusive": 0.4779214742593467, + "exclusive": 0.46425522631034255 + }, + "PipelineCompiler.declare_zarr_stores": { + "owner": "PipelineCompiler.declare_zarr_stores", + "dimensions": "", + "phase": "compiler_config:declare_zarr_stores", + "calls": 1, + "inclusive": 0.018639610148966312, + "exclusive": 9.438721463084221e-05 + }, + "PipelineCompiler._finalize_compilation": { + "owner": "PipelineCompiler._finalize_compilation", + "dimensions": "", + "phase": "compiler_config:_finalize_compilation", + "calls": 1, + "inclusive": 0.016232328955084085, + "exclusive": 0.00027552898973226547 + }, + "PipelineCompiler.compile_pipelines": { + "owner": "PipelineCompiler.compile_pipelines", + "dimensions": "", + "phase": "compiler_config:compile_pipelines", + "calls": 1, + "inclusive": 1.094543606042862, + "exclusive": 0.05472139874473214 + } + }, + "state_disjoint_exclusive_seconds": 0.6710898061282933 + }, + "execution": { + "root_seconds": 8.383970148861408, + "owners": { + "ObjectState._compute_resolved_snapshot": { + "owner": "ObjectState._compute_resolved_snapshot", + "dimensions": "", + "phase": "compiler_config:_compute_resolved_snapshot", + "calls": 8, + "inclusive": 0.04228230891749263, + "exclusive": 0.04228230891749263 + }, + "ObjectState.__init__": { + "owner": "ObjectState.__init__", + "dimensions": "", + "phase": "compiler_config:__init__", + "calls": 4, + "inclusive": 0.05480403359979391, + "exclusive": 0.012521724682301283 + }, + "ObjectState._reconstruct_from_resolved": { + "owner": "ObjectState._reconstruct_from_resolved", + "dimensions": "", + "phase": "compiler_config:_reconstruct_from_resolved", + "calls": 92, + "inclusive": 0.013641910627484322, + "exclusive": 0.007105355150997639 + }, + "ObjectState.to_saved_resolved_object": { + "owner": "ObjectState.to_saved_resolved_object", + "dimensions": "", + "phase": "compiler_config:to_saved_resolved_object", + "calls": 4, + "inclusive": 0.007119361776858568, + "exclusive": 1.4006625860929489e-05 + }, + "PipelineOrchestrator.get_effective_config": { + "owner": "PipelineOrchestrator.get_effective_config", + "dimensions": "", + "phase": "compiler_config:get_effective_config", + "calls": 4, + "inclusive": 0.06195876281708479, + "exclusive": 3.5367440432310104e-05 + }, + "PipelineOrchestrator.create_context": { + "owner": "PipelineOrchestrator.create_context", + "dimensions": "", + "phase": "compiler_config:create_context", + "calls": 1, + "inclusive": 0.014066982083022594, + "exclusive": 6.845779716968536e-05 + } + }, + "state_disjoint_exclusive_seconds": 0.06192339537665248 + } + }, + "findings": [ + "44 constructor / 88 snapshots is exactly consistent with constructor initializing independent live and saved baselines; same count is not proof they have equivalent values/effects.", + "Constructor first computes live using current parameters, LIVE global context, and ancestor.to_object; it then detached-copies saved parameters and resolves SAVED global and saved ancestor extraction targets. Initial dirty/provenance/signature sets depend on both.", + "Compiler force_fresh registration is intentional protection from stale UI/post-compile stripped states. Every state is constructed before registry.register fires callbacks; skipping live setup changes observable state at callbacks.", + "Registry ancestral objects include current scope when old state is already registered. force_fresh constructor may therefore observe replaced old registry state before register overwrites it; not assumed empty/no-edits.", + "ObjectState.saved_object synchronizes delegate changes; ancestor live.to_object synchronizes and caches reconstruction; merged context dataclass constructors and validators are real effects. Compiler later uses to_saved_resolved_object but public registered state still has both baseline APIs.", + "Context manager extract_all_configs already owns operation cache per object ID, cleared at context changes. resolver collects layer configs once per single field, with extraction cached during unchanged stack. Do not invent an absent config extraction cache.", + "All10 effective config reads total .195838 inclusive, a subset of ObjectState .671090 disjoint owner work. Late context-only removal cannot claim whole registration lane.", + "Live-versus-saved snapshot split timing is not retained per-argument by41-hook diagnostic; half of .45257 is not an empirical removable bound. Whole snapshot .45257 is an absolute ceiling before mandatory saved resolution and live state laws.", + "Compiler-state work is a total-time opportunity only. Execution state owner work .061924 is separate and cannot bridge execution gap. No production optimization, cache, validation bypass, proxy, subtype switch or constructor mode introduced." + ], + "existing_law_controls": [ + "ObjectState/tests/test_global_config.py:test_dual_config_pattern", + "ObjectState/tests/test_construction_history.py:test_alias_graph_is_detached_and_restored_across_scopes_and_saved_live", + "ObjectState/tests/test_callable_baseline.py:test_initial_values_flatten_nested_dataclass_overrides", + "ObjectState/tests/test_lazy_factory.py:test_patch_lazy_constructors_does_not_hide_default_factory_failure" + ], + "next_admission": "Only if root selects this total-time dependency: a bounded actual registered state snapshot replay must compare both saved/live outputs, provenance/dirty states, independent mutable aliases, registration callbacks, stale same-scope state replacement, delegated object sync, exception/factory/validation ordering. Existing diagnostic does not authorize collapsing live/saved snapshots." +} diff --git a/benchmark/results/perf_compile_runtime_ledger_20261003/report.rst b/benchmark/results/perf_compile_runtime_ledger_20261003/report.rst new file mode 100644 index 0000000000..307be67079 --- /dev/null +++ b/benchmark/results/perf_compile_runtime_ledger_20261003/report.rst @@ -0,0 +1,119 @@ +Current compiler and runtime owner ledger +========================================= + +This checkpoint supports PR #394 and issue #496. It measures unchanged +production source at ``480aed49b30448de4380af5c9274e48084e67b63``; it implements +no optimization. Main #526 was subsequently merged at ``5d62bd52c`` and changes +viewer documentation, knowledge projection and its test only. All measured +production Python bytes remain unchanged. + +The original public 3D Monolayer driver runs one worker and one CPU thread, +with inline execution, default OUTCOMES completion and the normal RSS observer. +The server is reused per sweep. Server startup, mandatory library/registry/kernel +preparation and shutdown remain outside pipeline clocks. Both profilers are +disabled. This diagnostic adds 17 compiler/configuration boundaries to the +retained 24 nominal boundaries; its wrappers introduce observation overhead. +It is not a before/after ordinary performance comparison. + +The public clocks are compilation **1.495826s**, execution **8.396727s**, and +total **10.694032s**. The execution root partitions **8.383970s** into +**3.660522s** at 211 declared callable boundaries and **4.723448s** outside them +(56.34 percent). Those callable boundaries include conversion, filtering and +metadata behavior; they are not pure numerical kernel clocks. + +Selected disjoint execution-exclusive costs: + +.. list-table:: Seconds within the original execution root + :header-rows: 1 + + * - Owner + - Calls + - Seconds + * - Stack loading + - 32 + - 0.781797 + * - In-memory output saving + - 28 + - 0.667759 + * - Worker residual + - 1 + - 0.501906 + * - Metadata publication + - 5 + - 0.502201 + * - Step finalization + - 30 + - 0.462263 + * - CellProfiler output recording + - 26 + - 0.382119 + * - CellProfiler image-request construction + - 30 + - 0.315012 + * - Artifact metadata reconciliation + - 1 + - 0.295025 + * - Validation and unstacking + - 28 + - 0.196794 + +Publication and finalization attribution differs from the previous diagnostic +on the same production bytes. This does not establish a code regression or an +optimization. GC and other stalls overlap owner clocks; they cannot be added +as independent costs. In-memory saving is not final TIFF export. + +The compile-only root is **1.260937s**. Its nested, disjoint ObjectState owners +total **0.671090s**: constructor-exclusive 0.161911s, resolved snapshots +0.452570s, reconstruction 0.056494s, and saved-object forwarding 0.000115s. +There are 44 constructors, 88 snapshots, 532 recursive reconstructions and +42 saved-object reads. All ten ``get_effective_config`` calls total only +**0.195838s inclusive**, a subset of those state costs. Context creation cannot +claim the entire 0.671090s as removable work. + +The two snapshots have distinct consumers. Live resolution observes current +parameters, live ancestor objects and live global context. Saved resolution +observes detached local parameters and saved ancestors/global context. Registry +callbacks receive their completed dirty/provenance baselines. Fresh compiler +registration also avoids stripped or independently edited UI states. These +facts reject unconditional snapshot collapse or existing-state reuse. The +source audit revalidates all 731 modules in the existing NRA census, covering +5,302 original classes; lexical source evidence is not a proof of callback +purity. Execution configuration state accounts for only about 0.062s. + +An original replay of the retained 180-reference input document independently +rules out another route: 68 complete projection-cache-hit availability checks +take **0.024413s median** across nine unprofiled repetitions. Current invalid +source indices are still rejected after projection caching. A cache-before- +validation shortcut would lose that error. This is a replay ceiling with an +already-loaded document handler, not a current end-to-end saving. + +Validation and custody +---------------------- + +All 15 descriptor, argument/result/error identity, call-once, nested clock, +fork-reset and source-drift controls pass. The 41 hooks install from verified +actual declaring files, including ObjectState's dependency source. Original +source, all eight actual dependencies, native binaries, environment and physical +inputs are checked before and after the run. + +The first root launch stops before starting a driver because its full +environment fingerprint differs from the prepared agent environment only in +``CODEX_THREAD_ID``. The original matching environment runs the unchanged +controller once and validates science; no fingerprint bypass or freeze rewrite +is used. Driver session 17712 and science session 51754 terminate successfully. + +The independent original scientific comparison, exact inventory and physical +source gates pass: six CSVs, 120 TIFFs, three input volumes and 180 ordered source +references. Retained native output witnesses are verified transitively; native +CellProfiler is not rerun here and no new native timing ratio is claimed. + +``assessment.json`` joins the full execution/compile ledgers, scientific gate, +control and registration receipts to immutable original paths and hashes. +The full source freeze and recipes remain in the referenced maintenance +directory; the committed evidence totals about 164 KB before this report. +Scientific outputs, saved replay graphs and environments are not copied. + +The multi-second runtime target remains unmet. Dominant integrated runtime +changes, matched ordinary before/after gains, branch architectural acceptance, +installed consumer acceptance, full-catalog/scaling measurements and refreshed +figure packs remain outstanding. The performance goal remains active. diff --git a/benchmark/results/perf_compile_runtime_ledger_20261003/science.json b/benchmark/results/perf_compile_runtime_ledger_20261003/science.json new file mode 100644 index 0000000000..aa75fede4d --- /dev/null +++ b/benchmark/results/perf_compile_runtime_ledger_20261003/science.json @@ -0,0 +1,1085 @@ +{ + "status": "FULL6CSV120TIFF_AND180_PHYSICAL_SOURCE_REFS_PASS", + "validator_sha256": "efc570f4a6026079704335a8be989800427d2c7d9db3afc9379700c1121e998d", + "source_revision": "480aed49b30448de4380af5c9274e48084e67b63", + "diagnostic_gate": "PASS", + "science_does_not_waive_diagnostic_failure": true, + "original_scientific_comparison": { + "reference_root": "/var/tmp/openhcs-owned-metadata-90c30-ordinary-abba-20261002/0-main/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput", + "counts": { + "csv": 6, + "tiff": 120 + }, + "comparisons": [ + { + "name": "images/W001_s001_w0_z001_t001_CellsLabels.tiff", + "actual_sha256": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "reference_sha256": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "exact_scientific_values": true + }, + { + "name": "images/W001_s001_w0_z002_t001_CellsLabels.tiff", + "actual_sha256": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "reference_sha256": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "exact_scientific_values": true + }, + { + "name": "images/W001_s001_w0_z003_t001_CellsLabels.tiff", + "actual_sha256": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "reference_sha256": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "exact_scientific_values": true + }, + { + "name": "images/W001_s001_w0_z004_t001_CellsLabels.tiff", + "actual_sha256": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "reference_sha256": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "exact_scientific_values": true + }, + { + "name": "images/W001_s001_w0_z005_t001_CellsLabels.tiff", + "actual_sha256": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "reference_sha256": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "exact_scientific_values": true + }, + { + "name": "images/W001_s001_w0_z006_t001_CellsLabels.tiff", + "actual_sha256": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "reference_sha256": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "exact_scientific_values": true + }, + { + "name": "images/W001_s001_w0_z007_t001_CellsLabels.tiff", + "actual_sha256": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "reference_sha256": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "exact_scientific_values": true + }, + { + "name": "images/W001_s001_w0_z008_t001_CellsLabels.tiff", + "actual_sha256": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "reference_sha256": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "exact_scientific_values": true + }, + { + "name": "images/W001_s001_w0_z009_t001_CellsLabels.tiff", + "actual_sha256": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "reference_sha256": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "exact_scientific_values": true + }, + { + "name": "images/W001_s001_w0_z010_t001_CellsLabels.tiff", + "actual_sha256": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "reference_sha256": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "exact_scientific_values": true + }, + { + "name": "images/W001_s001_w0_z011_t001_CellsLabels.tiff", + "actual_sha256": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "reference_sha256": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "exact_scientific_values": true + }, + { + "name": "images/W001_s001_w0_z012_t001_CellsLabels.tiff", + "actual_sha256": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "reference_sha256": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "exact_scientific_values": true + }, + { + "name": "images/W001_s001_w0_z013_t001_CellsLabels.tiff", + "actual_sha256": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "reference_sha256": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "exact_scientific_values": true + }, + { + "name": "images/W001_s001_w0_z014_t001_CellsLabels.tiff", + "actual_sha256": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "reference_sha256": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "exact_scientific_values": true + }, + { + "name": "images/W001_s001_w0_z015_t001_CellsLabels.tiff", + "actual_sha256": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "reference_sha256": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "exact_scientific_values": true + }, + { + "name": "images/W001_s001_w0_z016_t001_CellsLabels.tiff", + "actual_sha256": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "reference_sha256": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "exact_scientific_values": true + }, + { + "name": "images/W001_s001_w0_z017_t001_CellsLabels.tiff", + "actual_sha256": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "reference_sha256": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "exact_scientific_values": true + }, + { + "name": "images/W001_s001_w0_z018_t001_CellsLabels.tiff", + "actual_sha256": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "reference_sha256": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "exact_scientific_values": true + }, + { + "name": "images/W001_s001_w0_z019_t001_CellsLabels.tiff", + "actual_sha256": "ec6ef1d319f2732c47b06f5cf02775c8cd94540f2f30a6c002f0aace1d317955", + "reference_sha256": "ec6ef1d319f2732c47b06f5cf02775c8cd94540f2f30a6c002f0aace1d317955", + "exact_scientific_values": true + }, + { + "name": "images/W001_s001_w0_z020_t001_CellsLabels.tiff", + "actual_sha256": "e8105a4f04198ac75de9831247030084d6f65bf98691d7444ead7e178072fa22", + "reference_sha256": "e8105a4f04198ac75de9831247030084d6f65bf98691d7444ead7e178072fa22", + "exact_scientific_values": true + }, + { + "name": "images/W001_s001_w0_z021_t001_CellsLabels.tiff", + "actual_sha256": "daa31cb1e537e5c32b1936ab7647c5690741d2bc1d0e15c60b59ba1310a8c0ce", + "reference_sha256": "daa31cb1e537e5c32b1936ab7647c5690741d2bc1d0e15c60b59ba1310a8c0ce", + "exact_scientific_values": true + }, + { + "name": "images/W001_s001_w0_z022_t001_CellsLabels.tiff", + "actual_sha256": "7d7ec170ed3652efa99e43d8db546c51b696821dca7727d0ff4d2f2ead7fdbaa", + "reference_sha256": "7d7ec170ed3652efa99e43d8db546c51b696821dca7727d0ff4d2f2ead7fdbaa", + "exact_scientific_values": true + }, + { + "name": "images/W001_s001_w0_z023_t001_CellsLabels.tiff", + "actual_sha256": "2f06989618050934c73473f9342c2fe3410fd834a0ddb976cf602fe6198db7a6", + "reference_sha256": "2f06989618050934c73473f9342c2fe3410fd834a0ddb976cf602fe6198db7a6", + "exact_scientific_values": true + }, + { + "name": "images/W001_s001_w0_z024_t001_CellsLabels.tiff", + "actual_sha256": "39899adabca74b10b9950d1f97e8b0b3bbaf136d75e7a46ef4a6e86896e3119f", + "reference_sha256": "39899adabca74b10b9950d1f97e8b0b3bbaf136d75e7a46ef4a6e86896e3119f", + "exact_scientific_values": true + }, + { + "name": "images/W001_s001_w0_z025_t001_CellsLabels.tiff", + "actual_sha256": "03aabe5528198cfd6ec23a058dab540fb8be0870207c6dc94a62d9b621d1f2f9", + "reference_sha256": "03aabe5528198cfd6ec23a058dab540fb8be0870207c6dc94a62d9b621d1f2f9", + "exact_scientific_values": true + }, + { + "name": "images/W001_s001_w0_z026_t001_CellsLabels.tiff", + "actual_sha256": "5b433d931fa6637fc793b23880199c01000ef6d9e610903bb38bb8cea5574563", + "reference_sha256": "5b433d931fa6637fc793b23880199c01000ef6d9e610903bb38bb8cea5574563", + "exact_scientific_values": true + }, + { + "name": "images/W001_s001_w0_z027_t001_CellsLabels.tiff", + "actual_sha256": "ee9056587a19e581f5feb6078b41fa1004d923a5ddf1725aefc4b8b8c5201ad6", + "reference_sha256": "ee9056587a19e581f5feb6078b41fa1004d923a5ddf1725aefc4b8b8c5201ad6", + "exact_scientific_values": true + }, + { + "name": "images/W001_s001_w0_z028_t001_CellsLabels.tiff", + "actual_sha256": "fef31040e0c54501c3bf965eb98f055cdb1d42c96f91cf1c239033d0a9a06534", + "reference_sha256": "fef31040e0c54501c3bf965eb98f055cdb1d42c96f91cf1c239033d0a9a06534", + "exact_scientific_values": true + }, + { + "name": "images/W001_s001_w0_z029_t001_CellsLabels.tiff", + "actual_sha256": "b3bdde5f751b8f5d41ca8b5219a3427e450cb1b8795401d0ec638940d1ad7bd9", + "reference_sha256": "b3bdde5f751b8f5d41ca8b5219a3427e450cb1b8795401d0ec638940d1ad7bd9", + "exact_scientific_values": true + }, + { + "name": "images/W001_s001_w0_z030_t001_CellsLabels.tiff", + "actual_sha256": "b71a2e05d270ae0cd237d6c0d97ea82a63e5ad3633723e7255c35d34e585ec80", + "reference_sha256": "b71a2e05d270ae0cd237d6c0d97ea82a63e5ad3633723e7255c35d34e585ec80", + "exact_scientific_values": true + }, + { + "name": "images/W001_s001_w0_z031_t001_CellsLabels.tiff", + "actual_sha256": "1b14aab71bf3623458ea9373852b0baf28be9727877b32f894407927ecfb6d65", + "reference_sha256": "1b14aab71bf3623458ea9373852b0baf28be9727877b32f894407927ecfb6d65", + "exact_scientific_values": true + }, + { + "name": "images/W001_s001_w0_z032_t001_CellsLabels.tiff", + "actual_sha256": "8a2c5774044326ae722e41aae517266197fbebb0e4dd5eab4b22414fbfea309f", + "reference_sha256": "8a2c5774044326ae722e41aae517266197fbebb0e4dd5eab4b22414fbfea309f", + "exact_scientific_values": true + }, + { + "name": "images/W001_s001_w0_z033_t001_CellsLabels.tiff", + "actual_sha256": "a320b99ee129d97b99f9fac66aabb89fc1652930b3bb8b2b3fbba7b57e994f85", + "reference_sha256": "a320b99ee129d97b99f9fac66aabb89fc1652930b3bb8b2b3fbba7b57e994f85", + "exact_scientific_values": true + }, + { + "name": "images/W001_s001_w0_z034_t001_CellsLabels.tiff", + "actual_sha256": "3f6c1d8cdbce20aac8f70e7315bea70b147b7b6a034432845b27eeb6cfba083c", + "reference_sha256": "3f6c1d8cdbce20aac8f70e7315bea70b147b7b6a034432845b27eeb6cfba083c", + "exact_scientific_values": true + }, + { + "name": "images/W001_s001_w0_z035_t001_CellsLabels.tiff", + "actual_sha256": "eedeb489b46abf1eafbd9c81491cb3f85ce1cb3ce877844ad22e72547fc3c438", + "reference_sha256": "eedeb489b46abf1eafbd9c81491cb3f85ce1cb3ce877844ad22e72547fc3c438", + "exact_scientific_values": true + }, + { + "name": "images/W001_s001_w0_z036_t001_CellsLabels.tiff", + "actual_sha256": "28b68d1300cf7b08e21dbcd4858447862520dded5c27f2d84cf223513a119eed", + "reference_sha256": "28b68d1300cf7b08e21dbcd4858447862520dded5c27f2d84cf223513a119eed", + "exact_scientific_values": true + }, + { + "name": "images/W001_s001_w0_z037_t001_CellsLabels.tiff", + "actual_sha256": "aa1f449f1769b27cd9f1076e70f49f0242e2549f288a77984ca159cb07cf6a40", + "reference_sha256": "aa1f449f1769b27cd9f1076e70f49f0242e2549f288a77984ca159cb07cf6a40", + "exact_scientific_values": true + }, + { + "name": "images/W001_s001_w0_z038_t001_CellsLabels.tiff", + "actual_sha256": "6ac8fd9c95acc1f261e96a8fb9332e5d6a403548842f9b85ecb977e6213b4c9b", + "reference_sha256": "6ac8fd9c95acc1f261e96a8fb9332e5d6a403548842f9b85ecb977e6213b4c9b", + "exact_scientific_values": true + }, + { + "name": "images/W001_s001_w0_z039_t001_CellsLabels.tiff", + "actual_sha256": "22fa79a76e64013f10373be2ca2af98a2173275c5d43c9cad33135acdc376d14", + "reference_sha256": "22fa79a76e64013f10373be2ca2af98a2173275c5d43c9cad33135acdc376d14", + "exact_scientific_values": true + }, + { + "name": "images/W001_s001_w0_z040_t001_CellsLabels.tiff", + "actual_sha256": "1635ea20dd80ce99f0e86494666825a52a66645837d598fd3a3fa91f0bb77d53", + "reference_sha256": "1635ea20dd80ce99f0e86494666825a52a66645837d598fd3a3fa91f0bb77d53", + "exact_scientific_values": true + }, + { + "name": "images/W001_s001_w0_z041_t001_CellsLabels.tiff", + "actual_sha256": "be7762756eb65f08cb337904165c6f43b5351f39405461f65ad28669abfe3899", + "reference_sha256": "be7762756eb65f08cb337904165c6f43b5351f39405461f65ad28669abfe3899", + "exact_scientific_values": true + }, + { + "name": "images/W001_s001_w0_z042_t001_CellsLabels.tiff", + "actual_sha256": "88d2e9964455459499656c4f0a762cd86376c678756635aaa6b6c8d98be01852", + "reference_sha256": "88d2e9964455459499656c4f0a762cd86376c678756635aaa6b6c8d98be01852", + "exact_scientific_values": true + }, + { + "name": "images/W001_s001_w0_z043_t001_CellsLabels.tiff", + "actual_sha256": "bd0df007524ea4e555e4d2fdbebe6a274caa03bc360a1cf90d601659155984b2", + "reference_sha256": "bd0df007524ea4e555e4d2fdbebe6a274caa03bc360a1cf90d601659155984b2", + "exact_scientific_values": true + }, + { + "name": "images/W001_s001_w0_z044_t001_CellsLabels.tiff", + "actual_sha256": "e03946d94c789ee787cc29a3c8f5e5d9c56b37a0044b297ba8f403abc98eb55e", + "reference_sha256": "e03946d94c789ee787cc29a3c8f5e5d9c56b37a0044b297ba8f403abc98eb55e", + "exact_scientific_values": true + }, + { + "name": "images/W001_s001_w0_z045_t001_CellsLabels.tiff", + "actual_sha256": "c678f2100c7431e5a43c391af86a79e3436d4cf13f050f98c25f62682e4632fe", + "reference_sha256": "c678f2100c7431e5a43c391af86a79e3436d4cf13f050f98c25f62682e4632fe", + "exact_scientific_values": true + }, + { + "name": "images/W001_s001_w0_z046_t001_CellsLabels.tiff", + "actual_sha256": "dc081df050be6cd19b5d5bbfe21c96c350eecf9bc6f10f608dc361a36056632a", + "reference_sha256": "dc081df050be6cd19b5d5bbfe21c96c350eecf9bc6f10f608dc361a36056632a", + "exact_scientific_values": true + }, + { + "name": "images/W001_s001_w0_z047_t001_CellsLabels.tiff", + "actual_sha256": "b926aa64e1fa8aa52279a69d91dc23cf14bf0ae76107f9b360c7ae77bdf53719", + "reference_sha256": "b926aa64e1fa8aa52279a69d91dc23cf14bf0ae76107f9b360c7ae77bdf53719", + "exact_scientific_values": true + }, + { + "name": "images/W001_s001_w0_z048_t001_CellsLabels.tiff", + "actual_sha256": "133a58f6fac8b07f79bfed9634867ccb5428b83e63682031a1def16c6a694568", + "reference_sha256": "133a58f6fac8b07f79bfed9634867ccb5428b83e63682031a1def16c6a694568", + "exact_scientific_values": true + }, + { + "name": "images/W001_s001_w0_z049_t001_CellsLabels.tiff", + "actual_sha256": "28d83dfbf5bbf7e4da9c3e4806353e9fd0a89680dcdab4b43ca2fd19b80f669c", + "reference_sha256": "28d83dfbf5bbf7e4da9c3e4806353e9fd0a89680dcdab4b43ca2fd19b80f669c", + "exact_scientific_values": true + }, + { + "name": "images/W001_s001_w0_z050_t001_CellsLabels.tiff", + "actual_sha256": "ea7654a6fe1f92ad274a54935420923eec4bec5ad030187afc0ac7af02690af5", + "reference_sha256": "ea7654a6fe1f92ad274a54935420923eec4bec5ad030187afc0ac7af02690af5", + "exact_scientific_values": true + }, + { + "name": "images/W001_s001_w0_z051_t001_CellsLabels.tiff", + "actual_sha256": "73483bd10a0f37990084013ad054768086d6d3c929da6bc7e74f4aee37e9dbf2", + "reference_sha256": "73483bd10a0f37990084013ad054768086d6d3c929da6bc7e74f4aee37e9dbf2", + "exact_scientific_values": true + }, + { + "name": "images/W001_s001_w0_z052_t001_CellsLabels.tiff", + "actual_sha256": "7bb98f0587062e01b965e486fc687872651d7d90d271a2fdf0d35d67b464b233", + "reference_sha256": "7bb98f0587062e01b965e486fc687872651d7d90d271a2fdf0d35d67b464b233", + "exact_scientific_values": true + }, + { + "name": "images/W001_s001_w0_z053_t001_CellsLabels.tiff", + "actual_sha256": "ff17f538baaf179752412026a250bdbee016e3101037bf4e0dbb81199fc4c8ed", + "reference_sha256": "ff17f538baaf179752412026a250bdbee016e3101037bf4e0dbb81199fc4c8ed", + "exact_scientific_values": true + }, + { + "name": "images/W001_s001_w0_z054_t001_CellsLabels.tiff", + "actual_sha256": "25ff2ec586a568e42286f73713d64aab1208c38c016099299211f04368ac49c8", + "reference_sha256": "25ff2ec586a568e42286f73713d64aab1208c38c016099299211f04368ac49c8", + "exact_scientific_values": true + }, + { + "name": "images/W001_s001_w0_z055_t001_CellsLabels.tiff", + "actual_sha256": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "reference_sha256": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "exact_scientific_values": true + }, + { + "name": "images/W001_s001_w0_z056_t001_CellsLabels.tiff", + "actual_sha256": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "reference_sha256": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "exact_scientific_values": true + }, + { + "name": "images/W001_s001_w0_z057_t001_CellsLabels.tiff", + "actual_sha256": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "reference_sha256": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "exact_scientific_values": true + }, + { + "name": "images/W001_s001_w0_z058_t001_CellsLabels.tiff", + "actual_sha256": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "reference_sha256": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "exact_scientific_values": true + }, + { + "name": "images/W001_s001_w0_z059_t001_CellsLabels.tiff", + "actual_sha256": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "reference_sha256": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "exact_scientific_values": true + }, + { + "name": "images/W001_s001_w0_z060_t001_CellsLabels.tiff", + "actual_sha256": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "reference_sha256": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "exact_scientific_values": true + }, + { + "name": "images/W001_s001_w2_z001_t001_NucleiLabels.tiff", + "actual_sha256": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "reference_sha256": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "exact_scientific_values": true + }, + { + "name": "images/W001_s001_w2_z002_t001_NucleiLabels.tiff", + "actual_sha256": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "reference_sha256": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "exact_scientific_values": true + }, + { + "name": "images/W001_s001_w2_z003_t001_NucleiLabels.tiff", + "actual_sha256": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "reference_sha256": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "exact_scientific_values": true + }, + { + "name": "images/W001_s001_w2_z004_t001_NucleiLabels.tiff", + "actual_sha256": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "reference_sha256": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "exact_scientific_values": true + }, + { + "name": "images/W001_s001_w2_z005_t001_NucleiLabels.tiff", + "actual_sha256": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "reference_sha256": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "exact_scientific_values": true + }, + { + "name": "images/W001_s001_w2_z006_t001_NucleiLabels.tiff", + "actual_sha256": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "reference_sha256": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "exact_scientific_values": true + }, + { + "name": "images/W001_s001_w2_z007_t001_NucleiLabels.tiff", + "actual_sha256": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "reference_sha256": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "exact_scientific_values": true + }, + { + "name": "images/W001_s001_w2_z008_t001_NucleiLabels.tiff", + "actual_sha256": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "reference_sha256": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "exact_scientific_values": true + }, + { + "name": "images/W001_s001_w2_z009_t001_NucleiLabels.tiff", + "actual_sha256": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "reference_sha256": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "exact_scientific_values": true + }, + { + "name": "images/W001_s001_w2_z010_t001_NucleiLabels.tiff", + "actual_sha256": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "reference_sha256": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "exact_scientific_values": true + }, + { + "name": "images/W001_s001_w2_z011_t001_NucleiLabels.tiff", + "actual_sha256": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "reference_sha256": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "exact_scientific_values": true + }, + { + "name": "images/W001_s001_w2_z012_t001_NucleiLabels.tiff", + "actual_sha256": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "reference_sha256": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "exact_scientific_values": true + }, + { + "name": "images/W001_s001_w2_z013_t001_NucleiLabels.tiff", + "actual_sha256": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "reference_sha256": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "exact_scientific_values": true + }, + { + "name": "images/W001_s001_w2_z014_t001_NucleiLabels.tiff", + "actual_sha256": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "reference_sha256": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "exact_scientific_values": true + }, + { + "name": "images/W001_s001_w2_z015_t001_NucleiLabels.tiff", + "actual_sha256": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "reference_sha256": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "exact_scientific_values": true + }, + { + "name": "images/W001_s001_w2_z016_t001_NucleiLabels.tiff", + "actual_sha256": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "reference_sha256": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "exact_scientific_values": true + }, + { + "name": "images/W001_s001_w2_z017_t001_NucleiLabels.tiff", + "actual_sha256": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "reference_sha256": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "exact_scientific_values": true + }, + { + "name": "images/W001_s001_w2_z018_t001_NucleiLabels.tiff", + "actual_sha256": "03ba7a4d6ae53e6c84aab5926ae1e2592b5f8ca24a839a256c82f08544df4270", + "reference_sha256": "03ba7a4d6ae53e6c84aab5926ae1e2592b5f8ca24a839a256c82f08544df4270", + "exact_scientific_values": true + }, + { + "name": "images/W001_s001_w2_z019_t001_NucleiLabels.tiff", + "actual_sha256": "250cb56a8054c28cea894bc3d9edaddcdce01f5151a05da78da20157c3c3be9f", + "reference_sha256": "250cb56a8054c28cea894bc3d9edaddcdce01f5151a05da78da20157c3c3be9f", + "exact_scientific_values": true + }, + { + "name": "images/W001_s001_w2_z020_t001_NucleiLabels.tiff", + "actual_sha256": "b0cd031b448d8bd2075e65710bd76c064161b25242f85ee150da7cd139fcc1a8", + "reference_sha256": "b0cd031b448d8bd2075e65710bd76c064161b25242f85ee150da7cd139fcc1a8", + "exact_scientific_values": true + }, + { + "name": "images/W001_s001_w2_z021_t001_NucleiLabels.tiff", + "actual_sha256": "71a10b0539f3fc4cba600b275b7e948258c6a435ba33ef522faa0869ac085518", + "reference_sha256": "71a10b0539f3fc4cba600b275b7e948258c6a435ba33ef522faa0869ac085518", + "exact_scientific_values": true + }, + { + "name": "images/W001_s001_w2_z022_t001_NucleiLabels.tiff", + "actual_sha256": "50aef20e28a2f9e18ca2e28eabf6d87ec2ad20c79898e56f8d63a959ba5bb507", + "reference_sha256": "50aef20e28a2f9e18ca2e28eabf6d87ec2ad20c79898e56f8d63a959ba5bb507", + "exact_scientific_values": true + }, + { + "name": "images/W001_s001_w2_z023_t001_NucleiLabels.tiff", + "actual_sha256": "ecb7f78c8ca0bad2b9d0495659609b9023781b6a936d6afb0a04653eac176555", + "reference_sha256": "ecb7f78c8ca0bad2b9d0495659609b9023781b6a936d6afb0a04653eac176555", + "exact_scientific_values": true + }, + { + "name": "images/W001_s001_w2_z024_t001_NucleiLabels.tiff", + "actual_sha256": "9e96a05ed9860cac9c57c618db2f4fe5e4b769a9d235aac6fd1d628486317df0", + "reference_sha256": "9e96a05ed9860cac9c57c618db2f4fe5e4b769a9d235aac6fd1d628486317df0", + "exact_scientific_values": true + }, + { + "name": "images/W001_s001_w2_z025_t001_NucleiLabels.tiff", + "actual_sha256": "9cc33676a0177130609ab1331feab1722bbde8d55b2f49031730fd5a2a40029c", + "reference_sha256": "9cc33676a0177130609ab1331feab1722bbde8d55b2f49031730fd5a2a40029c", + "exact_scientific_values": true + }, + { + "name": "images/W001_s001_w2_z026_t001_NucleiLabels.tiff", + "actual_sha256": "ad22809ff3f43d15c838f697061c263070dbf1da1031da39900681cdfbf9d54c", + "reference_sha256": "ad22809ff3f43d15c838f697061c263070dbf1da1031da39900681cdfbf9d54c", + "exact_scientific_values": true + }, + { + "name": "images/W001_s001_w2_z027_t001_NucleiLabels.tiff", + "actual_sha256": "8c8f402d3a7c65c04e7f1575dd34de0427eeeb433ff2956d20e07d06eb48fb8d", + "reference_sha256": "8c8f402d3a7c65c04e7f1575dd34de0427eeeb433ff2956d20e07d06eb48fb8d", + "exact_scientific_values": true + }, + { + "name": "images/W001_s001_w2_z028_t001_NucleiLabels.tiff", + "actual_sha256": "1676f21bd3b7e105601c83f206890507c32ba2447988be2a75d0e8153d069b65", + "reference_sha256": "1676f21bd3b7e105601c83f206890507c32ba2447988be2a75d0e8153d069b65", + "exact_scientific_values": true + }, + { + "name": "images/W001_s001_w2_z029_t001_NucleiLabels.tiff", + "actual_sha256": "34bce0f06f674e20667554eed0075fde8d9d33c9c0eaeffd88a1c558499cc432", + "reference_sha256": "34bce0f06f674e20667554eed0075fde8d9d33c9c0eaeffd88a1c558499cc432", + "exact_scientific_values": true + }, + { + "name": "images/W001_s001_w2_z030_t001_NucleiLabels.tiff", + "actual_sha256": "c54c8b98a5c38a47e0cf9391a1afab09b4c8c58e06294cdb650a15add4a32b58", + "reference_sha256": "c54c8b98a5c38a47e0cf9391a1afab09b4c8c58e06294cdb650a15add4a32b58", + "exact_scientific_values": true + }, + { + "name": "images/W001_s001_w2_z031_t001_NucleiLabels.tiff", + "actual_sha256": "247490c261fecc26c7379ab2eebaa01e4bea523218b3cc5491d2fe2b9aadfe11", + "reference_sha256": "247490c261fecc26c7379ab2eebaa01e4bea523218b3cc5491d2fe2b9aadfe11", + "exact_scientific_values": true + }, + { + "name": "images/W001_s001_w2_z032_t001_NucleiLabels.tiff", + "actual_sha256": "97b09fe5444ad439c3c2007d75971dce2766d94c93268eccfee9ae49b8a04aa1", + "reference_sha256": "97b09fe5444ad439c3c2007d75971dce2766d94c93268eccfee9ae49b8a04aa1", + "exact_scientific_values": true + }, + { + "name": "images/W001_s001_w2_z033_t001_NucleiLabels.tiff", + "actual_sha256": "512a3a0ed8025d14b0556a72ebfc13b173d14f7046817ca09876242ab63b9d6b", + "reference_sha256": "512a3a0ed8025d14b0556a72ebfc13b173d14f7046817ca09876242ab63b9d6b", + "exact_scientific_values": true + }, + { + "name": "images/W001_s001_w2_z034_t001_NucleiLabels.tiff", + "actual_sha256": "08af61857cfb97fd95fcb08d1ce18139ce7087b192044c63452bee533c5b1aa4", + "reference_sha256": "08af61857cfb97fd95fcb08d1ce18139ce7087b192044c63452bee533c5b1aa4", + "exact_scientific_values": true + }, + { + "name": "images/W001_s001_w2_z035_t001_NucleiLabels.tiff", + "actual_sha256": "13e69afc324152bb91329fa758d131d849127e8fd346078d94c6adc25582b3a6", + "reference_sha256": "13e69afc324152bb91329fa758d131d849127e8fd346078d94c6adc25582b3a6", + "exact_scientific_values": true + }, + { + "name": "images/W001_s001_w2_z036_t001_NucleiLabels.tiff", + "actual_sha256": "4fa967c78709aa400246a50528a36b24ca366e825dd0e64561643369e814906b", + "reference_sha256": "4fa967c78709aa400246a50528a36b24ca366e825dd0e64561643369e814906b", + "exact_scientific_values": true + }, + { + "name": "images/W001_s001_w2_z037_t001_NucleiLabels.tiff", + "actual_sha256": "927d52441c57cb3a4014effaca3e3c23c76275fb264c26e1942a9c58b85ee6d2", + "reference_sha256": "927d52441c57cb3a4014effaca3e3c23c76275fb264c26e1942a9c58b85ee6d2", + "exact_scientific_values": true + }, + { + "name": "images/W001_s001_w2_z038_t001_NucleiLabels.tiff", + "actual_sha256": "e2852ea83c62ab30d77681b4e39f88d3cee74ae052f1c948675ae3581c9fc28a", + "reference_sha256": "e2852ea83c62ab30d77681b4e39f88d3cee74ae052f1c948675ae3581c9fc28a", + "exact_scientific_values": true + }, + { + "name": "images/W001_s001_w2_z039_t001_NucleiLabels.tiff", + "actual_sha256": "f93e8293a37886a36844b8748083a1f8e717efab092652755263e797f12f0364", + "reference_sha256": "f93e8293a37886a36844b8748083a1f8e717efab092652755263e797f12f0364", + "exact_scientific_values": true + }, + { + "name": "images/W001_s001_w2_z040_t001_NucleiLabels.tiff", + "actual_sha256": "e0bd66b166e9f92120dbee183973849eda0afbbe6fed9d03fc4cfd2c56a96280", + "reference_sha256": "e0bd66b166e9f92120dbee183973849eda0afbbe6fed9d03fc4cfd2c56a96280", + "exact_scientific_values": true + }, + { + "name": "images/W001_s001_w2_z041_t001_NucleiLabels.tiff", + "actual_sha256": "744eab7cd170d5af8d2f72ced3893dd939c4e1b0f415afab799a37ded5d046c7", + "reference_sha256": "744eab7cd170d5af8d2f72ced3893dd939c4e1b0f415afab799a37ded5d046c7", + "exact_scientific_values": true + }, + { + "name": "images/W001_s001_w2_z042_t001_NucleiLabels.tiff", + "actual_sha256": "e07252ca1a55c5195c99666d8d3f0d70db636b4ef4b99e1a0049ca22b182d87a", + "reference_sha256": "e07252ca1a55c5195c99666d8d3f0d70db636b4ef4b99e1a0049ca22b182d87a", + "exact_scientific_values": true + }, + { + "name": "images/W001_s001_w2_z043_t001_NucleiLabels.tiff", + "actual_sha256": "81a705d05b0a5bfa8783df28990c1d70634c1f4aa2bca23e02cfa8a4bc861b86", + "reference_sha256": "81a705d05b0a5bfa8783df28990c1d70634c1f4aa2bca23e02cfa8a4bc861b86", + "exact_scientific_values": true + }, + { + "name": "images/W001_s001_w2_z044_t001_NucleiLabels.tiff", + "actual_sha256": "a78264f2f5e245a3913a69f89105e94df30048b1aaef4eb80fc5c3235e78b196", + "reference_sha256": "a78264f2f5e245a3913a69f89105e94df30048b1aaef4eb80fc5c3235e78b196", + "exact_scientific_values": true + }, + { + "name": "images/W001_s001_w2_z045_t001_NucleiLabels.tiff", + "actual_sha256": "94bd6a65795ad6395cc18a4fd63dc591354bef612ee49fffd2d9f63e4ed9db84", + "reference_sha256": "94bd6a65795ad6395cc18a4fd63dc591354bef612ee49fffd2d9f63e4ed9db84", + "exact_scientific_values": true + }, + { + "name": "images/W001_s001_w2_z046_t001_NucleiLabels.tiff", + "actual_sha256": "c1250e060d32f2cfc07fc7e1594fdb1d6cbb4d0483fa94a8113efa695397963c", + "reference_sha256": "c1250e060d32f2cfc07fc7e1594fdb1d6cbb4d0483fa94a8113efa695397963c", + "exact_scientific_values": true + }, + { + "name": "images/W001_s001_w2_z047_t001_NucleiLabels.tiff", + "actual_sha256": "995d5ce77cbf61a9be8590f34987ef3f1dd698ae6ed393cac4d0960bc9e7a66a", + "reference_sha256": "995d5ce77cbf61a9be8590f34987ef3f1dd698ae6ed393cac4d0960bc9e7a66a", + "exact_scientific_values": true + }, + { + "name": "images/W001_s001_w2_z048_t001_NucleiLabels.tiff", + "actual_sha256": "325478230529e94ba372f38f0bf512292f131d337b6ac09ce5a91b0266724e02", + "reference_sha256": "325478230529e94ba372f38f0bf512292f131d337b6ac09ce5a91b0266724e02", + "exact_scientific_values": true + }, + { + "name": "images/W001_s001_w2_z049_t001_NucleiLabels.tiff", + "actual_sha256": "e92e493078672a0e0d90e31409612e215bf8486300d5c765d0e0504ff8888e7a", + "reference_sha256": "e92e493078672a0e0d90e31409612e215bf8486300d5c765d0e0504ff8888e7a", + "exact_scientific_values": true + }, + { + "name": "images/W001_s001_w2_z050_t001_NucleiLabels.tiff", + "actual_sha256": "565b4f08f7503086c1f2f8e631d19063129e02a5767d2f979c0cec8fdec23601", + "reference_sha256": "565b4f08f7503086c1f2f8e631d19063129e02a5767d2f979c0cec8fdec23601", + "exact_scientific_values": true + }, + { + "name": "images/W001_s001_w2_z051_t001_NucleiLabels.tiff", + "actual_sha256": "f0f36ccaf744d42da036948682cfd226e6dd4a3cfb94aed38729b2d25ede5dff", + "reference_sha256": "f0f36ccaf744d42da036948682cfd226e6dd4a3cfb94aed38729b2d25ede5dff", + "exact_scientific_values": true + }, + { + "name": "images/W001_s001_w2_z052_t001_NucleiLabels.tiff", + "actual_sha256": "0daf51526658e23b7c9ab8872e992ebe9322399286f95741d0ccdbd357e5d631", + "reference_sha256": "0daf51526658e23b7c9ab8872e992ebe9322399286f95741d0ccdbd357e5d631", + "exact_scientific_values": true + }, + { + "name": "images/W001_s001_w2_z053_t001_NucleiLabels.tiff", + "actual_sha256": "b8613192175a4615b58aed607474657668429cb6ac635cd012569b19667f2d3d", + "reference_sha256": "b8613192175a4615b58aed607474657668429cb6ac635cd012569b19667f2d3d", + "exact_scientific_values": true + }, + { + "name": "images/W001_s001_w2_z054_t001_NucleiLabels.tiff", + "actual_sha256": "b841c5d901c65a6138d9ff2b0ec4aa04f00765b1dd21bcd6fc9f8dc974c6035d", + "reference_sha256": "b841c5d901c65a6138d9ff2b0ec4aa04f00765b1dd21bcd6fc9f8dc974c6035d", + "exact_scientific_values": true + }, + { + "name": "images/W001_s001_w2_z055_t001_NucleiLabels.tiff", + "actual_sha256": "44e02416cc94a70528165a4b6c42b9e19b205f9c91528076796272cb1a8504ea", + "reference_sha256": "44e02416cc94a70528165a4b6c42b9e19b205f9c91528076796272cb1a8504ea", + "exact_scientific_values": true + }, + { + "name": "images/W001_s001_w2_z056_t001_NucleiLabels.tiff", + "actual_sha256": "ca0723c8b9764d5b77034719bb75a2940be35da2e04119af4c0e6d3552c08718", + "reference_sha256": "ca0723c8b9764d5b77034719bb75a2940be35da2e04119af4c0e6d3552c08718", + "exact_scientific_values": true + }, + { + "name": "images/W001_s001_w2_z057_t001_NucleiLabels.tiff", + "actual_sha256": "695517641e9fe4b8421d4a7db56b24c755b6957c98ce32bb24ad5b25f52661eb", + "reference_sha256": "695517641e9fe4b8421d4a7db56b24c755b6957c98ce32bb24ad5b25f52661eb", + "exact_scientific_values": true + }, + { + "name": "images/W001_s001_w2_z058_t001_NucleiLabels.tiff", + "actual_sha256": "a37c63c6052e40d73db918a014e6f2a18be4d0cbfbeeef65a9c26096a38a4c09", + "reference_sha256": "a37c63c6052e40d73db918a014e6f2a18be4d0cbfbeeef65a9c26096a38a4c09", + "exact_scientific_values": true + }, + { + "name": "images/W001_s001_w2_z059_t001_NucleiLabels.tiff", + "actual_sha256": "76c785cf0f481c73ad3cf34ccb576eaa19dd1bdd9c74f9eaf92adfbde5d44b97", + "reference_sha256": "76c785cf0f481c73ad3cf34ccb576eaa19dd1bdd9c74f9eaf92adfbde5d44b97", + "exact_scientific_values": true + }, + { + "name": "images/W001_s001_w2_z060_t001_NucleiLabels.tiff", + "actual_sha256": "7cc3c6c6a22f558e62194277090bdea2deb79475dd91fe7d0e49eac3c0187388", + "reference_sha256": "7cc3c6c6a22f558e62194277090bdea2deb79475dd91fe7d0e49eac3c0187388", + "exact_scientific_values": true + }, + { + "name": "results/3d_monolayer_Cells.csv", + "actual_sha256": "6f6e7431171ed5ea73a01784105147eca0e43a6e3e41f8720df93106353c9c79", + "reference_sha256": "6f6e7431171ed5ea73a01784105147eca0e43a6e3e41f8720df93106353c9c79", + "exact_scientific_values": true + }, + { + "name": "results/3d_monolayer_Image.csv", + "actual_sha256": "75ac32ff5ef57bc285ec4eae1c9b501c27a35b486bf35435af5d499d856d34a4", + "reference_sha256": "75ac32ff5ef57bc285ec4eae1c9b501c27a35b486bf35435af5d499d856d34a4", + "exact_scientific_values": true + }, + { + "name": "results/3d_monolayer_Nuclei.csv", + "actual_sha256": "17500f5d4321bbf255df31f7a3503339029c2b077045a6c10e4d4f6f0db9ad1e", + "reference_sha256": "17500f5d4321bbf255df31f7a3503339029c2b077045a6c10e4d4f6f0db9ad1e", + "exact_scientific_values": true + }, + { + "name": "results/3d_monolayer_downsizedNuclei.csv", + "actual_sha256": "a7b998c5a524e11747fc5452fd763fc3d9abe16f46e961f62e09e9393b6a8adf", + "reference_sha256": "a7b998c5a524e11747fc5452fd763fc3d9abe16f46e961f62e09e9393b6a8adf", + "exact_scientific_values": true + }, + { + "name": "results/3d_monolayer_erodedDownsizedNuclei.csv", + "actual_sha256": "ee507fb9c2387f86fc768184baf2596ebe1f8e40f7fc5eb24f252345fee63ae6", + "reference_sha256": "ee507fb9c2387f86fc768184baf2596ebe1f8e40f7fc5eb24f252345fee63ae6", + "exact_scientific_values": true + }, + { + "name": "results/3d_monolayer_erodedResizedNuclei.csv", + "actual_sha256": "cca23f86a85bb3ee7a5c3a1d174c34b5f026ca7f399be98458e1a8c6e12d5c77", + "reference_sha256": "cca23f86a85bb3ee7a5c3a1d174c34b5f026ca7f399be98458e1a8c6e12d5c77", + "exact_scientific_values": true + } + ], + "scope": "Exact saved CSV cells and TIFF dtype/shape/pixels against specified retained ordinary output. Not a current native ratio or new paired timing." + }, + "complete_inventory": { + "scientific_hashes": { + "images/W001_s001_w0_z001_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "images/W001_s001_w0_z002_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "images/W001_s001_w0_z003_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "images/W001_s001_w0_z004_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "images/W001_s001_w0_z005_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "images/W001_s001_w0_z006_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "images/W001_s001_w0_z007_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "images/W001_s001_w0_z008_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "images/W001_s001_w0_z009_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "images/W001_s001_w0_z010_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "images/W001_s001_w0_z011_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "images/W001_s001_w0_z012_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "images/W001_s001_w0_z013_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "images/W001_s001_w0_z014_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "images/W001_s001_w0_z015_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "images/W001_s001_w0_z016_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "images/W001_s001_w0_z017_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "images/W001_s001_w0_z018_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "images/W001_s001_w0_z019_t001_CellsLabels.tiff": "ec6ef1d319f2732c47b06f5cf02775c8cd94540f2f30a6c002f0aace1d317955", + "images/W001_s001_w0_z020_t001_CellsLabels.tiff": "e8105a4f04198ac75de9831247030084d6f65bf98691d7444ead7e178072fa22", + "images/W001_s001_w0_z021_t001_CellsLabels.tiff": "daa31cb1e537e5c32b1936ab7647c5690741d2bc1d0e15c60b59ba1310a8c0ce", + "images/W001_s001_w0_z022_t001_CellsLabels.tiff": "7d7ec170ed3652efa99e43d8db546c51b696821dca7727d0ff4d2f2ead7fdbaa", + "images/W001_s001_w0_z023_t001_CellsLabels.tiff": "2f06989618050934c73473f9342c2fe3410fd834a0ddb976cf602fe6198db7a6", + "images/W001_s001_w0_z024_t001_CellsLabels.tiff": "39899adabca74b10b9950d1f97e8b0b3bbaf136d75e7a46ef4a6e86896e3119f", + "images/W001_s001_w0_z025_t001_CellsLabels.tiff": "03aabe5528198cfd6ec23a058dab540fb8be0870207c6dc94a62d9b621d1f2f9", + "images/W001_s001_w0_z026_t001_CellsLabels.tiff": "5b433d931fa6637fc793b23880199c01000ef6d9e610903bb38bb8cea5574563", + "images/W001_s001_w0_z027_t001_CellsLabels.tiff": "ee9056587a19e581f5feb6078b41fa1004d923a5ddf1725aefc4b8b8c5201ad6", + "images/W001_s001_w0_z028_t001_CellsLabels.tiff": "fef31040e0c54501c3bf965eb98f055cdb1d42c96f91cf1c239033d0a9a06534", + "images/W001_s001_w0_z029_t001_CellsLabels.tiff": "b3bdde5f751b8f5d41ca8b5219a3427e450cb1b8795401d0ec638940d1ad7bd9", + "images/W001_s001_w0_z030_t001_CellsLabels.tiff": "b71a2e05d270ae0cd237d6c0d97ea82a63e5ad3633723e7255c35d34e585ec80", + "images/W001_s001_w0_z031_t001_CellsLabels.tiff": "1b14aab71bf3623458ea9373852b0baf28be9727877b32f894407927ecfb6d65", + "images/W001_s001_w0_z032_t001_CellsLabels.tiff": "8a2c5774044326ae722e41aae517266197fbebb0e4dd5eab4b22414fbfea309f", + "images/W001_s001_w0_z033_t001_CellsLabels.tiff": "a320b99ee129d97b99f9fac66aabb89fc1652930b3bb8b2b3fbba7b57e994f85", + "images/W001_s001_w0_z034_t001_CellsLabels.tiff": "3f6c1d8cdbce20aac8f70e7315bea70b147b7b6a034432845b27eeb6cfba083c", + "images/W001_s001_w0_z035_t001_CellsLabels.tiff": "eedeb489b46abf1eafbd9c81491cb3f85ce1cb3ce877844ad22e72547fc3c438", + "images/W001_s001_w0_z036_t001_CellsLabels.tiff": "28b68d1300cf7b08e21dbcd4858447862520dded5c27f2d84cf223513a119eed", + "images/W001_s001_w0_z037_t001_CellsLabels.tiff": "aa1f449f1769b27cd9f1076e70f49f0242e2549f288a77984ca159cb07cf6a40", + "images/W001_s001_w0_z038_t001_CellsLabels.tiff": "6ac8fd9c95acc1f261e96a8fb9332e5d6a403548842f9b85ecb977e6213b4c9b", + "images/W001_s001_w0_z039_t001_CellsLabels.tiff": "22fa79a76e64013f10373be2ca2af98a2173275c5d43c9cad33135acdc376d14", + "images/W001_s001_w0_z040_t001_CellsLabels.tiff": "1635ea20dd80ce99f0e86494666825a52a66645837d598fd3a3fa91f0bb77d53", + "images/W001_s001_w0_z041_t001_CellsLabels.tiff": "be7762756eb65f08cb337904165c6f43b5351f39405461f65ad28669abfe3899", + "images/W001_s001_w0_z042_t001_CellsLabels.tiff": "88d2e9964455459499656c4f0a762cd86376c678756635aaa6b6c8d98be01852", + "images/W001_s001_w0_z043_t001_CellsLabels.tiff": "bd0df007524ea4e555e4d2fdbebe6a274caa03bc360a1cf90d601659155984b2", + "images/W001_s001_w0_z044_t001_CellsLabels.tiff": "e03946d94c789ee787cc29a3c8f5e5d9c56b37a0044b297ba8f403abc98eb55e", + "images/W001_s001_w0_z045_t001_CellsLabels.tiff": "c678f2100c7431e5a43c391af86a79e3436d4cf13f050f98c25f62682e4632fe", + "images/W001_s001_w0_z046_t001_CellsLabels.tiff": "dc081df050be6cd19b5d5bbfe21c96c350eecf9bc6f10f608dc361a36056632a", + "images/W001_s001_w0_z047_t001_CellsLabels.tiff": "b926aa64e1fa8aa52279a69d91dc23cf14bf0ae76107f9b360c7ae77bdf53719", + "images/W001_s001_w0_z048_t001_CellsLabels.tiff": "133a58f6fac8b07f79bfed9634867ccb5428b83e63682031a1def16c6a694568", + "images/W001_s001_w0_z049_t001_CellsLabels.tiff": "28d83dfbf5bbf7e4da9c3e4806353e9fd0a89680dcdab4b43ca2fd19b80f669c", + "images/W001_s001_w0_z050_t001_CellsLabels.tiff": "ea7654a6fe1f92ad274a54935420923eec4bec5ad030187afc0ac7af02690af5", + "images/W001_s001_w0_z051_t001_CellsLabels.tiff": "73483bd10a0f37990084013ad054768086d6d3c929da6bc7e74f4aee37e9dbf2", + "images/W001_s001_w0_z052_t001_CellsLabels.tiff": "7bb98f0587062e01b965e486fc687872651d7d90d271a2fdf0d35d67b464b233", + "images/W001_s001_w0_z053_t001_CellsLabels.tiff": "ff17f538baaf179752412026a250bdbee016e3101037bf4e0dbb81199fc4c8ed", + "images/W001_s001_w0_z054_t001_CellsLabels.tiff": "25ff2ec586a568e42286f73713d64aab1208c38c016099299211f04368ac49c8", + "images/W001_s001_w0_z055_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "images/W001_s001_w0_z056_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "images/W001_s001_w0_z057_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "images/W001_s001_w0_z058_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "images/W001_s001_w0_z059_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "images/W001_s001_w0_z060_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "images/W001_s001_w2_z001_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "images/W001_s001_w2_z002_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "images/W001_s001_w2_z003_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "images/W001_s001_w2_z004_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "images/W001_s001_w2_z005_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "images/W001_s001_w2_z006_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "images/W001_s001_w2_z007_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "images/W001_s001_w2_z008_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "images/W001_s001_w2_z009_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "images/W001_s001_w2_z010_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "images/W001_s001_w2_z011_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "images/W001_s001_w2_z012_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "images/W001_s001_w2_z013_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "images/W001_s001_w2_z014_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "images/W001_s001_w2_z015_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "images/W001_s001_w2_z016_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "images/W001_s001_w2_z017_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "images/W001_s001_w2_z018_t001_NucleiLabels.tiff": "03ba7a4d6ae53e6c84aab5926ae1e2592b5f8ca24a839a256c82f08544df4270", + "images/W001_s001_w2_z019_t001_NucleiLabels.tiff": "250cb56a8054c28cea894bc3d9edaddcdce01f5151a05da78da20157c3c3be9f", + "images/W001_s001_w2_z020_t001_NucleiLabels.tiff": "b0cd031b448d8bd2075e65710bd76c064161b25242f85ee150da7cd139fcc1a8", + "images/W001_s001_w2_z021_t001_NucleiLabels.tiff": "71a10b0539f3fc4cba600b275b7e948258c6a435ba33ef522faa0869ac085518", + "images/W001_s001_w2_z022_t001_NucleiLabels.tiff": "50aef20e28a2f9e18ca2e28eabf6d87ec2ad20c79898e56f8d63a959ba5bb507", + "images/W001_s001_w2_z023_t001_NucleiLabels.tiff": "ecb7f78c8ca0bad2b9d0495659609b9023781b6a936d6afb0a04653eac176555", + "images/W001_s001_w2_z024_t001_NucleiLabels.tiff": "9e96a05ed9860cac9c57c618db2f4fe5e4b769a9d235aac6fd1d628486317df0", + "images/W001_s001_w2_z025_t001_NucleiLabels.tiff": "9cc33676a0177130609ab1331feab1722bbde8d55b2f49031730fd5a2a40029c", + "images/W001_s001_w2_z026_t001_NucleiLabels.tiff": "ad22809ff3f43d15c838f697061c263070dbf1da1031da39900681cdfbf9d54c", + "images/W001_s001_w2_z027_t001_NucleiLabels.tiff": "8c8f402d3a7c65c04e7f1575dd34de0427eeeb433ff2956d20e07d06eb48fb8d", + "images/W001_s001_w2_z028_t001_NucleiLabels.tiff": "1676f21bd3b7e105601c83f206890507c32ba2447988be2a75d0e8153d069b65", + "images/W001_s001_w2_z029_t001_NucleiLabels.tiff": "34bce0f06f674e20667554eed0075fde8d9d33c9c0eaeffd88a1c558499cc432", + "images/W001_s001_w2_z030_t001_NucleiLabels.tiff": "c54c8b98a5c38a47e0cf9391a1afab09b4c8c58e06294cdb650a15add4a32b58", + "images/W001_s001_w2_z031_t001_NucleiLabels.tiff": "247490c261fecc26c7379ab2eebaa01e4bea523218b3cc5491d2fe2b9aadfe11", + "images/W001_s001_w2_z032_t001_NucleiLabels.tiff": "97b09fe5444ad439c3c2007d75971dce2766d94c93268eccfee9ae49b8a04aa1", + "images/W001_s001_w2_z033_t001_NucleiLabels.tiff": "512a3a0ed8025d14b0556a72ebfc13b173d14f7046817ca09876242ab63b9d6b", + "images/W001_s001_w2_z034_t001_NucleiLabels.tiff": "08af61857cfb97fd95fcb08d1ce18139ce7087b192044c63452bee533c5b1aa4", + "images/W001_s001_w2_z035_t001_NucleiLabels.tiff": "13e69afc324152bb91329fa758d131d849127e8fd346078d94c6adc25582b3a6", + "images/W001_s001_w2_z036_t001_NucleiLabels.tiff": "4fa967c78709aa400246a50528a36b24ca366e825dd0e64561643369e814906b", + "images/W001_s001_w2_z037_t001_NucleiLabels.tiff": "927d52441c57cb3a4014effaca3e3c23c76275fb264c26e1942a9c58b85ee6d2", + "images/W001_s001_w2_z038_t001_NucleiLabels.tiff": "e2852ea83c62ab30d77681b4e39f88d3cee74ae052f1c948675ae3581c9fc28a", + "images/W001_s001_w2_z039_t001_NucleiLabels.tiff": "f93e8293a37886a36844b8748083a1f8e717efab092652755263e797f12f0364", + "images/W001_s001_w2_z040_t001_NucleiLabels.tiff": "e0bd66b166e9f92120dbee183973849eda0afbbe6fed9d03fc4cfd2c56a96280", + "images/W001_s001_w2_z041_t001_NucleiLabels.tiff": "744eab7cd170d5af8d2f72ced3893dd939c4e1b0f415afab799a37ded5d046c7", + "images/W001_s001_w2_z042_t001_NucleiLabels.tiff": "e07252ca1a55c5195c99666d8d3f0d70db636b4ef4b99e1a0049ca22b182d87a", + "images/W001_s001_w2_z043_t001_NucleiLabels.tiff": "81a705d05b0a5bfa8783df28990c1d70634c1f4aa2bca23e02cfa8a4bc861b86", + "images/W001_s001_w2_z044_t001_NucleiLabels.tiff": "a78264f2f5e245a3913a69f89105e94df30048b1aaef4eb80fc5c3235e78b196", + "images/W001_s001_w2_z045_t001_NucleiLabels.tiff": "94bd6a65795ad6395cc18a4fd63dc591354bef612ee49fffd2d9f63e4ed9db84", + "images/W001_s001_w2_z046_t001_NucleiLabels.tiff": "c1250e060d32f2cfc07fc7e1594fdb1d6cbb4d0483fa94a8113efa695397963c", + "images/W001_s001_w2_z047_t001_NucleiLabels.tiff": "995d5ce77cbf61a9be8590f34987ef3f1dd698ae6ed393cac4d0960bc9e7a66a", + "images/W001_s001_w2_z048_t001_NucleiLabels.tiff": "325478230529e94ba372f38f0bf512292f131d337b6ac09ce5a91b0266724e02", + "images/W001_s001_w2_z049_t001_NucleiLabels.tiff": "e92e493078672a0e0d90e31409612e215bf8486300d5c765d0e0504ff8888e7a", + "images/W001_s001_w2_z050_t001_NucleiLabels.tiff": "565b4f08f7503086c1f2f8e631d19063129e02a5767d2f979c0cec8fdec23601", + "images/W001_s001_w2_z051_t001_NucleiLabels.tiff": "f0f36ccaf744d42da036948682cfd226e6dd4a3cfb94aed38729b2d25ede5dff", + "images/W001_s001_w2_z052_t001_NucleiLabels.tiff": "0daf51526658e23b7c9ab8872e992ebe9322399286f95741d0ccdbd357e5d631", + "images/W001_s001_w2_z053_t001_NucleiLabels.tiff": "b8613192175a4615b58aed607474657668429cb6ac635cd012569b19667f2d3d", + "images/W001_s001_w2_z054_t001_NucleiLabels.tiff": "b841c5d901c65a6138d9ff2b0ec4aa04f00765b1dd21bcd6fc9f8dc974c6035d", + "images/W001_s001_w2_z055_t001_NucleiLabels.tiff": "44e02416cc94a70528165a4b6c42b9e19b205f9c91528076796272cb1a8504ea", + "images/W001_s001_w2_z056_t001_NucleiLabels.tiff": "ca0723c8b9764d5b77034719bb75a2940be35da2e04119af4c0e6d3552c08718", + "images/W001_s001_w2_z057_t001_NucleiLabels.tiff": "695517641e9fe4b8421d4a7db56b24c755b6957c98ce32bb24ad5b25f52661eb", + "images/W001_s001_w2_z058_t001_NucleiLabels.tiff": "a37c63c6052e40d73db918a014e6f2a18be4d0cbfbeeef65a9c26096a38a4c09", + "images/W001_s001_w2_z059_t001_NucleiLabels.tiff": "76c785cf0f481c73ad3cf34ccb576eaa19dd1bdd9c74f9eaf92adfbde5d44b97", + "images/W001_s001_w2_z060_t001_NucleiLabels.tiff": "7cc3c6c6a22f558e62194277090bdea2deb79475dd91fe7d0e49eac3c0187388", + "results/3d_monolayer_Cells.csv": "6f6e7431171ed5ea73a01784105147eca0e43a6e3e41f8720df93106353c9c79", + "results/3d_monolayer_Image.csv": "75ac32ff5ef57bc285ec4eae1c9b501c27a35b486bf35435af5d499d856d34a4", + "results/3d_monolayer_Nuclei.csv": "17500f5d4321bbf255df31f7a3503339029c2b077045a6c10e4d4f6f0db9ad1e", + "results/3d_monolayer_downsizedNuclei.csv": "a7b998c5a524e11747fc5452fd763fc3d9abe16f46e961f62e09e9393b6a8adf", + "results/3d_monolayer_erodedDownsizedNuclei.csv": "ee507fb9c2387f86fc768184baf2596ebe1f8e40f7fc5eb24f252345fee63ae6", + "results/3d_monolayer_erodedResizedNuclei.csv": "cca23f86a85bb3ee7a5c3a1d174c34b5f026ca7f399be98458e1a8c6e12d5c77" + }, + "complete_inventory": { + "images/W001_s001_w0_z001_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "images/W001_s001_w0_z002_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "images/W001_s001_w0_z003_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "images/W001_s001_w0_z004_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "images/W001_s001_w0_z005_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "images/W001_s001_w0_z006_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "images/W001_s001_w0_z007_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "images/W001_s001_w0_z008_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "images/W001_s001_w0_z009_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "images/W001_s001_w0_z010_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "images/W001_s001_w0_z011_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "images/W001_s001_w0_z012_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "images/W001_s001_w0_z013_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "images/W001_s001_w0_z014_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "images/W001_s001_w0_z015_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "images/W001_s001_w0_z016_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "images/W001_s001_w0_z017_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "images/W001_s001_w0_z018_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "images/W001_s001_w0_z019_t001_CellsLabels.tiff": "ec6ef1d319f2732c47b06f5cf02775c8cd94540f2f30a6c002f0aace1d317955", + "images/W001_s001_w0_z020_t001_CellsLabels.tiff": "e8105a4f04198ac75de9831247030084d6f65bf98691d7444ead7e178072fa22", + "images/W001_s001_w0_z021_t001_CellsLabels.tiff": "daa31cb1e537e5c32b1936ab7647c5690741d2bc1d0e15c60b59ba1310a8c0ce", + "images/W001_s001_w0_z022_t001_CellsLabels.tiff": "7d7ec170ed3652efa99e43d8db546c51b696821dca7727d0ff4d2f2ead7fdbaa", + "images/W001_s001_w0_z023_t001_CellsLabels.tiff": "2f06989618050934c73473f9342c2fe3410fd834a0ddb976cf602fe6198db7a6", + "images/W001_s001_w0_z024_t001_CellsLabels.tiff": "39899adabca74b10b9950d1f97e8b0b3bbaf136d75e7a46ef4a6e86896e3119f", + "images/W001_s001_w0_z025_t001_CellsLabels.tiff": "03aabe5528198cfd6ec23a058dab540fb8be0870207c6dc94a62d9b621d1f2f9", + "images/W001_s001_w0_z026_t001_CellsLabels.tiff": "5b433d931fa6637fc793b23880199c01000ef6d9e610903bb38bb8cea5574563", + "images/W001_s001_w0_z027_t001_CellsLabels.tiff": "ee9056587a19e581f5feb6078b41fa1004d923a5ddf1725aefc4b8b8c5201ad6", + "images/W001_s001_w0_z028_t001_CellsLabels.tiff": "fef31040e0c54501c3bf965eb98f055cdb1d42c96f91cf1c239033d0a9a06534", + "images/W001_s001_w0_z029_t001_CellsLabels.tiff": "b3bdde5f751b8f5d41ca8b5219a3427e450cb1b8795401d0ec638940d1ad7bd9", + "images/W001_s001_w0_z030_t001_CellsLabels.tiff": "b71a2e05d270ae0cd237d6c0d97ea82a63e5ad3633723e7255c35d34e585ec80", + "images/W001_s001_w0_z031_t001_CellsLabels.tiff": "1b14aab71bf3623458ea9373852b0baf28be9727877b32f894407927ecfb6d65", + "images/W001_s001_w0_z032_t001_CellsLabels.tiff": "8a2c5774044326ae722e41aae517266197fbebb0e4dd5eab4b22414fbfea309f", + "images/W001_s001_w0_z033_t001_CellsLabels.tiff": "a320b99ee129d97b99f9fac66aabb89fc1652930b3bb8b2b3fbba7b57e994f85", + "images/W001_s001_w0_z034_t001_CellsLabels.tiff": "3f6c1d8cdbce20aac8f70e7315bea70b147b7b6a034432845b27eeb6cfba083c", + "images/W001_s001_w0_z035_t001_CellsLabels.tiff": "eedeb489b46abf1eafbd9c81491cb3f85ce1cb3ce877844ad22e72547fc3c438", + "images/W001_s001_w0_z036_t001_CellsLabels.tiff": "28b68d1300cf7b08e21dbcd4858447862520dded5c27f2d84cf223513a119eed", + "images/W001_s001_w0_z037_t001_CellsLabels.tiff": "aa1f449f1769b27cd9f1076e70f49f0242e2549f288a77984ca159cb07cf6a40", + "images/W001_s001_w0_z038_t001_CellsLabels.tiff": "6ac8fd9c95acc1f261e96a8fb9332e5d6a403548842f9b85ecb977e6213b4c9b", + "images/W001_s001_w0_z039_t001_CellsLabels.tiff": "22fa79a76e64013f10373be2ca2af98a2173275c5d43c9cad33135acdc376d14", + "images/W001_s001_w0_z040_t001_CellsLabels.tiff": "1635ea20dd80ce99f0e86494666825a52a66645837d598fd3a3fa91f0bb77d53", + "images/W001_s001_w0_z041_t001_CellsLabels.tiff": "be7762756eb65f08cb337904165c6f43b5351f39405461f65ad28669abfe3899", + "images/W001_s001_w0_z042_t001_CellsLabels.tiff": "88d2e9964455459499656c4f0a762cd86376c678756635aaa6b6c8d98be01852", + "images/W001_s001_w0_z043_t001_CellsLabels.tiff": "bd0df007524ea4e555e4d2fdbebe6a274caa03bc360a1cf90d601659155984b2", + "images/W001_s001_w0_z044_t001_CellsLabels.tiff": "e03946d94c789ee787cc29a3c8f5e5d9c56b37a0044b297ba8f403abc98eb55e", + "images/W001_s001_w0_z045_t001_CellsLabels.tiff": "c678f2100c7431e5a43c391af86a79e3436d4cf13f050f98c25f62682e4632fe", + "images/W001_s001_w0_z046_t001_CellsLabels.tiff": "dc081df050be6cd19b5d5bbfe21c96c350eecf9bc6f10f608dc361a36056632a", + "images/W001_s001_w0_z047_t001_CellsLabels.tiff": "b926aa64e1fa8aa52279a69d91dc23cf14bf0ae76107f9b360c7ae77bdf53719", + "images/W001_s001_w0_z048_t001_CellsLabels.tiff": "133a58f6fac8b07f79bfed9634867ccb5428b83e63682031a1def16c6a694568", + "images/W001_s001_w0_z049_t001_CellsLabels.tiff": "28d83dfbf5bbf7e4da9c3e4806353e9fd0a89680dcdab4b43ca2fd19b80f669c", + "images/W001_s001_w0_z050_t001_CellsLabels.tiff": "ea7654a6fe1f92ad274a54935420923eec4bec5ad030187afc0ac7af02690af5", + "images/W001_s001_w0_z051_t001_CellsLabels.tiff": "73483bd10a0f37990084013ad054768086d6d3c929da6bc7e74f4aee37e9dbf2", + "images/W001_s001_w0_z052_t001_CellsLabels.tiff": "7bb98f0587062e01b965e486fc687872651d7d90d271a2fdf0d35d67b464b233", + "images/W001_s001_w0_z053_t001_CellsLabels.tiff": "ff17f538baaf179752412026a250bdbee016e3101037bf4e0dbb81199fc4c8ed", + "images/W001_s001_w0_z054_t001_CellsLabels.tiff": "25ff2ec586a568e42286f73713d64aab1208c38c016099299211f04368ac49c8", + "images/W001_s001_w0_z055_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "images/W001_s001_w0_z056_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "images/W001_s001_w0_z057_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "images/W001_s001_w0_z058_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "images/W001_s001_w0_z059_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "images/W001_s001_w0_z060_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "images/W001_s001_w2_z001_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "images/W001_s001_w2_z002_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "images/W001_s001_w2_z003_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "images/W001_s001_w2_z004_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "images/W001_s001_w2_z005_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "images/W001_s001_w2_z006_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "images/W001_s001_w2_z007_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "images/W001_s001_w2_z008_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "images/W001_s001_w2_z009_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "images/W001_s001_w2_z010_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "images/W001_s001_w2_z011_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "images/W001_s001_w2_z012_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "images/W001_s001_w2_z013_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "images/W001_s001_w2_z014_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "images/W001_s001_w2_z015_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "images/W001_s001_w2_z016_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "images/W001_s001_w2_z017_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "images/W001_s001_w2_z018_t001_NucleiLabels.tiff": "03ba7a4d6ae53e6c84aab5926ae1e2592b5f8ca24a839a256c82f08544df4270", + "images/W001_s001_w2_z019_t001_NucleiLabels.tiff": "250cb56a8054c28cea894bc3d9edaddcdce01f5151a05da78da20157c3c3be9f", + "images/W001_s001_w2_z020_t001_NucleiLabels.tiff": "b0cd031b448d8bd2075e65710bd76c064161b25242f85ee150da7cd139fcc1a8", + "images/W001_s001_w2_z021_t001_NucleiLabels.tiff": "71a10b0539f3fc4cba600b275b7e948258c6a435ba33ef522faa0869ac085518", + "images/W001_s001_w2_z022_t001_NucleiLabels.tiff": "50aef20e28a2f9e18ca2e28eabf6d87ec2ad20c79898e56f8d63a959ba5bb507", + "images/W001_s001_w2_z023_t001_NucleiLabels.tiff": "ecb7f78c8ca0bad2b9d0495659609b9023781b6a936d6afb0a04653eac176555", + "images/W001_s001_w2_z024_t001_NucleiLabels.tiff": "9e96a05ed9860cac9c57c618db2f4fe5e4b769a9d235aac6fd1d628486317df0", + "images/W001_s001_w2_z025_t001_NucleiLabels.tiff": "9cc33676a0177130609ab1331feab1722bbde8d55b2f49031730fd5a2a40029c", + "images/W001_s001_w2_z026_t001_NucleiLabels.tiff": "ad22809ff3f43d15c838f697061c263070dbf1da1031da39900681cdfbf9d54c", + "images/W001_s001_w2_z027_t001_NucleiLabels.tiff": "8c8f402d3a7c65c04e7f1575dd34de0427eeeb433ff2956d20e07d06eb48fb8d", + "images/W001_s001_w2_z028_t001_NucleiLabels.tiff": "1676f21bd3b7e105601c83f206890507c32ba2447988be2a75d0e8153d069b65", + "images/W001_s001_w2_z029_t001_NucleiLabels.tiff": "34bce0f06f674e20667554eed0075fde8d9d33c9c0eaeffd88a1c558499cc432", + "images/W001_s001_w2_z030_t001_NucleiLabels.tiff": "c54c8b98a5c38a47e0cf9391a1afab09b4c8c58e06294cdb650a15add4a32b58", + "images/W001_s001_w2_z031_t001_NucleiLabels.tiff": "247490c261fecc26c7379ab2eebaa01e4bea523218b3cc5491d2fe2b9aadfe11", + "images/W001_s001_w2_z032_t001_NucleiLabels.tiff": "97b09fe5444ad439c3c2007d75971dce2766d94c93268eccfee9ae49b8a04aa1", + "images/W001_s001_w2_z033_t001_NucleiLabels.tiff": "512a3a0ed8025d14b0556a72ebfc13b173d14f7046817ca09876242ab63b9d6b", + "images/W001_s001_w2_z034_t001_NucleiLabels.tiff": "08af61857cfb97fd95fcb08d1ce18139ce7087b192044c63452bee533c5b1aa4", + "images/W001_s001_w2_z035_t001_NucleiLabels.tiff": "13e69afc324152bb91329fa758d131d849127e8fd346078d94c6adc25582b3a6", + "images/W001_s001_w2_z036_t001_NucleiLabels.tiff": "4fa967c78709aa400246a50528a36b24ca366e825dd0e64561643369e814906b", + "images/W001_s001_w2_z037_t001_NucleiLabels.tiff": "927d52441c57cb3a4014effaca3e3c23c76275fb264c26e1942a9c58b85ee6d2", + "images/W001_s001_w2_z038_t001_NucleiLabels.tiff": "e2852ea83c62ab30d77681b4e39f88d3cee74ae052f1c948675ae3581c9fc28a", + "images/W001_s001_w2_z039_t001_NucleiLabels.tiff": "f93e8293a37886a36844b8748083a1f8e717efab092652755263e797f12f0364", + "images/W001_s001_w2_z040_t001_NucleiLabels.tiff": "e0bd66b166e9f92120dbee183973849eda0afbbe6fed9d03fc4cfd2c56a96280", + "images/W001_s001_w2_z041_t001_NucleiLabels.tiff": "744eab7cd170d5af8d2f72ced3893dd939c4e1b0f415afab799a37ded5d046c7", + "images/W001_s001_w2_z042_t001_NucleiLabels.tiff": "e07252ca1a55c5195c99666d8d3f0d70db636b4ef4b99e1a0049ca22b182d87a", + "images/W001_s001_w2_z043_t001_NucleiLabels.tiff": "81a705d05b0a5bfa8783df28990c1d70634c1f4aa2bca23e02cfa8a4bc861b86", + "images/W001_s001_w2_z044_t001_NucleiLabels.tiff": "a78264f2f5e245a3913a69f89105e94df30048b1aaef4eb80fc5c3235e78b196", + "images/W001_s001_w2_z045_t001_NucleiLabels.tiff": "94bd6a65795ad6395cc18a4fd63dc591354bef612ee49fffd2d9f63e4ed9db84", + "images/W001_s001_w2_z046_t001_NucleiLabels.tiff": "c1250e060d32f2cfc07fc7e1594fdb1d6cbb4d0483fa94a8113efa695397963c", + "images/W001_s001_w2_z047_t001_NucleiLabels.tiff": "995d5ce77cbf61a9be8590f34987ef3f1dd698ae6ed393cac4d0960bc9e7a66a", + "images/W001_s001_w2_z048_t001_NucleiLabels.tiff": "325478230529e94ba372f38f0bf512292f131d337b6ac09ce5a91b0266724e02", + "images/W001_s001_w2_z049_t001_NucleiLabels.tiff": "e92e493078672a0e0d90e31409612e215bf8486300d5c765d0e0504ff8888e7a", + "images/W001_s001_w2_z050_t001_NucleiLabels.tiff": "565b4f08f7503086c1f2f8e631d19063129e02a5767d2f979c0cec8fdec23601", + "images/W001_s001_w2_z051_t001_NucleiLabels.tiff": "f0f36ccaf744d42da036948682cfd226e6dd4a3cfb94aed38729b2d25ede5dff", + "images/W001_s001_w2_z052_t001_NucleiLabels.tiff": "0daf51526658e23b7c9ab8872e992ebe9322399286f95741d0ccdbd357e5d631", + "images/W001_s001_w2_z053_t001_NucleiLabels.tiff": "b8613192175a4615b58aed607474657668429cb6ac635cd012569b19667f2d3d", + "images/W001_s001_w2_z054_t001_NucleiLabels.tiff": "b841c5d901c65a6138d9ff2b0ec4aa04f00765b1dd21bcd6fc9f8dc974c6035d", + "images/W001_s001_w2_z055_t001_NucleiLabels.tiff": "44e02416cc94a70528165a4b6c42b9e19b205f9c91528076796272cb1a8504ea", + "images/W001_s001_w2_z056_t001_NucleiLabels.tiff": "ca0723c8b9764d5b77034719bb75a2940be35da2e04119af4c0e6d3552c08718", + "images/W001_s001_w2_z057_t001_NucleiLabels.tiff": "695517641e9fe4b8421d4a7db56b24c755b6957c98ce32bb24ad5b25f52661eb", + "images/W001_s001_w2_z058_t001_NucleiLabels.tiff": "a37c63c6052e40d73db918a014e6f2a18be4d0cbfbeeef65a9c26096a38a4c09", + "images/W001_s001_w2_z059_t001_NucleiLabels.tiff": "76c785cf0f481c73ad3cf34ccb576eaa19dd1bdd9c74f9eaf92adfbde5d44b97", + "images/W001_s001_w2_z060_t001_NucleiLabels.tiff": "7cc3c6c6a22f558e62194277090bdea2deb79475dd91fe7d0e49eac3c0187388", + "openhcs_metadata.json": "d0cc10b9362796e0894c240460684bd8dbbaa423069032e8ac8efb9ffdbe2e1e", + "openhcs_metadata.json.lock": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "results/3d_monolayer_Cells.csv": "6f6e7431171ed5ea73a01784105147eca0e43a6e3e41f8720df93106353c9c79", + "results/3d_monolayer_Image.csv": "75ac32ff5ef57bc285ec4eae1c9b501c27a35b486bf35435af5d499d856d34a4", + "results/3d_monolayer_Nuclei.csv": "17500f5d4321bbf255df31f7a3503339029c2b077045a6c10e4d4f6f0db9ad1e", + "results/3d_monolayer_downsizedNuclei.csv": "a7b998c5a524e11747fc5452fd763fc3d9abe16f46e961f62e09e9393b6a8adf", + "results/3d_monolayer_erodedDownsizedNuclei.csv": "ee507fb9c2387f86fc768184baf2596ebe1f8e40f7fc5eb24f252345fee63ae6", + "results/3d_monolayer_erodedResizedNuclei.csv": "cca23f86a85bb3ee7a5c3a1d174c34b5f026ca7f399be98458e1a8c6e12d5c77" + }, + "managed_metadata": { + "openhcs_metadata.json": { + "baseline_sha256": "0af41a148e9dd6ff40febf786b819d84cb689cfeff93500f6aa7f5c8912219ec", + "actual_sha256": "d0cc10b9362796e0894c240460684bd8dbbaa423069032e8ac8efb9ffdbe2e1e", + "changed": true + }, + "openhcs_metadata.json.lock": { + "baseline_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "actual_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "changed": false + } + }, + "unknown_exclusions": [] + }, + "completion": { + "observation_export": { + "path": "/home/ts/.local/state/openhcs-maintenance/20261003/compiler-config-coarse-ledger-v1/output/public/cp_tutorial_3d_monolayer/wells_1/workers_1/ordinary_run_evidence/cp_tutorial_3d_monolayer-1w_1t-1791020555970061852/runtime_outcomes.pkl.gz", + "sha256": "51f80d2dab3f0abcdad31b7c8bb77a58a2fa4c0f0d315f68c503d7c669a6e4fa", + "bytes": 5435 + }, + "results_summary": { + "path": "/home/ts/.local/state/openhcs-maintenance/20261003/compiler-config-coarse-ledger-v1/output/public/cp_tutorial_3d_monolayer/wells_1/workers_1/ordinary_run_evidence/cp_tutorial_3d_monolayer-1w_1t-1791020555970061852/zmq_results_summary.json", + "sha256": "14228fa5cdc6f005e3605f5b5a4c9bf76271a139068139375b8da5f78713a6d6", + "bytes": 655 + } + }, + "actual_receipt": "/home/ts/.local/state/openhcs-maintenance/20261003/compiler-config-coarse-ledger-v1/output/public/cp_tutorial_3d_monolayer/wells_1/workers_1/ordinary_run_evidence/cp_tutorial_3d_monolayer-1w_1t-1791020555970061852/measured_pipeline_receipt.json", + "actual_receipt_sha256": "4a9bbba130e8175a3d3a0d27530e802eb347f0b665fef2b58a089a32fef630c0", + "source_freeze_sha256": "0aa8d013c340ed52de584cc006becc832dfa1a9875745213d2d2e4c0904656cf", + "observations_sha256": "07c19d9a2b6183d1cbb69691258862f3b89b65149481989557b0d1029bf728e3", + "controller_source_env_native_input_freeze": "Original root controller passed actual before/after gate; source/deps/native/input/helper freeze independently revalidated here.", + "original_root_effective_environment_sha256": "00b7f550f6e584e34d6070f79bdd60d37859cb58c752b866fc95ac7f5293dabd", + "validator_environment_scope": "Separate CPU3 read-only process; original controller full effective environment also revalidated from the authenticated original agent environment. Root session-specific CODEX_THREAD_ID prelaunch refusal preserved separately.", + "physical_resources": { + "/home/ts/.cache/openhcs/benchmark_datasets/CellProfiler_tutorials/data/3d_monolayer/images/3d_monolayer_xy1_ch2.tif": "191754bc7f43856223180483e2737ea93bab4d0cf98b1b2a4c27425e9908147d", + "/home/ts/.cache/openhcs/benchmark_datasets/CellProfiler_tutorials/data/3d_monolayer/images/3d_monolayer_xy1_ch1.tif": "a7d9abf632850875c22613c4b740fc01153cf60e9773c16d4a670a97b46e5751", + "/home/ts/.cache/openhcs/benchmark_datasets/CellProfiler_tutorials/data/3d_monolayer/images/3d_monolayer_xy1_ch0.tif": "63114f614fec95664f718a39cddac58449f0edb5cc31b57584e4ba5b1f4994c7" + }, + "ordered_source_ref_count": 180, + "per_volume_ordered_source_refs": 60, + "source_metadata_path": "/home/ts/.local/state/openhcs-maintenance/20261003/compiler-config-coarse-ledger-v1/output/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace/openhcs_metadata.json", + "source_metadata_sha256": "a42ec413a0ec213d22f4ba96fac785bfbfac167dd5d2da7cbd1acc8cf9c2d862", + "input_reference_output_bytes_unchanged_after_validation": true, + "qualified_prior_evidence": { + "/var/tmp/openhcs-current-3d-gc-ledger-v1-scientific-byte-gate-20261003.json": "d0b8d6af1b8a1777b03624cf6435d67b04746e9477a5cefbc7a962feaa2d667d", + "/var/tmp/openhcs-3d-b764-abba-science-clocks-20261002.json": "49c088e2e257f094c7e205caf9743882d41e7574a0733cd190e9edbc0a2e3f76", + "/var/tmp/openhcs-spatial-plane-sourceborn-resize-aba4-diagnostic-20261002/source-freeze.json": "c6d26196dc23e330fcd2614d68a33e35b454223d65b4e9c66a5e0ae021113ace", + "/var/tmp/run_spatial_plane_sourceborn_diagnostic_v2_20261002.py": "d11f91b71129862f623bc62dd4909643f1f589128122c08c7559cb5c12b6c5a4", + "/var/tmp/validate_current_3d_runtime_ledger_scientific_bytes_v1_20261003.py": "f86bcb1c440714e6e5b7d9c2d9a62cc813de7985fb586a59a3edba6cf9f081d0", + "/var/tmp/openhcs-native-3d-aba4-qualification-20261002/source-environment-input-witness.json": "e0fd1afeb2d4a9c73c2aa9c6f43f71055e9b93c7211a45d096789d42633d1120", + "/var/tmp/openhcs-native-3d-aba4-qualification-20261002/fresh-native-scientific-comparison-supplemental.json": "002cd9b5aa5beb22d10621da971d63ad2fa18af009d3bd93072d9a9957cab6c4" + }, + "native_scope": "TRANSITIVE ONLY: exact current saved science equals retained reference and B764-qualified bytes with actual same3physicalvolume inputs/180orderedrefs. Retained2native repetitions verified; native was NOT rerun for current source/environment. Original native compare API RED retained separately; no current native timing ratio or performance claim." +} diff --git a/benchmark/results/perf_current_cohort_v10_20261003/qualification.json b/benchmark/results/perf_current_cohort_v10_20261003/qualification.json new file mode 100644 index 0000000000..7d5ec179f9 --- /dev/null +++ b/benchmark/results/perf_current_cohort_v10_20261003/qualification.json @@ -0,0 +1,198 @@ +{ + "status": "BOUNDED_CURRENT_ORIGINAL_WARM_PRODUCER_AND_LOADER_REPLAY_FULL_GATES_PASS", + "issue": 510, + "source_revision": "4c636a281de4da7341f4f9f6bb8f718c75644a1d", + "protocol": { + "hash_seed": 0, + "actual_outer_cwd": "/home/ts/code/projects/openhcs", + "outer_taskset_cpu": 4, + "public_child_cpu": 5, + "public_child_cwd": "/home/ts/.local/state/openhcs-maintenance/20261003/current-cohort-capture-v10/output/tmp", + "actual_command": "PYTHONDONTWRITEBYTECODE=1 taskset -c 4 /home/ts/code/projects/openhcs/.venv/bin/python /home/ts/.local/state/openhcs-maintenance/20261003/current-cohort-capture-v10/controller.py --run --revision 4c636a281de4da7341f4f9f6bb8f718c75644a1d", + "actual_public_handle": 16238, + "actual_public_terminal": 0, + "failed_preflight_handle": 93559, + "failed_preflight_started_driver": false, + "effective_environment_sha256": "15a56d8163d7c2b38db7398210ec6e1c700da84184031a6460333193909fd375", + "no_environment_field_exclusions_or_reseal": true + }, + "capture": { + "graphs": 4, + "bytes": 1027681056, + "remaining_combined_cap_bytes": 46060768, + "per_item_cap": 402653184, + "total_cap": 1073741824, + "node_cap": 150000, + "errors": [], + "graphs_scope": [ + { + "key": "13-PatternGroupRuntime-_validate_and_unstack-before", + "bytes": 272201079, + "sha256": "3c49c2ebc3050c4bd9e62052d7a6e9acd6c095f23849f80f86a115041c544519", + "sidecar_sha256": "3ca071d05e7516eda02f3d0cbb6f6f77d6d3defee63991af3f147247eef5bd0b", + "owners": 1054, + "nonempty_views": 677, + "view_entries": 4286 + }, + { + "key": "13-save-oracle", + "bytes": 194819278, + "sha256": "c9ed3ce36c322a5d32aeb03f65b1d8d2697775e61231a6d433dae66e7d290542", + "sidecar_sha256": "dec76667df2aa673785cc176e23d309ca3fc6a552adbdd67ce957d4e0194e8c0", + "owners": 1112, + "nonempty_views": 735, + "view_entries": 4400 + }, + { + "key": "14-PatternGroupRuntime-_load_input_stack-before", + "bytes": 280297985, + "sha256": "2a48c08fdf3eecfdd5af13b0052ce985a21469dbbe5e5c4f97be69682a933780", + "sidecar_sha256": "8b6f277dc8d1765e3d6b68f816a91b0b762df72f3128b3294de0f5b513455d26", + "owners": 1115, + "nonempty_views": 738, + "view_entries": 4408 + }, + { + "key": "14-load-oracle", + "bytes": 280362714, + "sha256": "20c4d2721789d5c9dfdce4e6ff789cbcfb59d49e87ba53e042deb75be5c3bde7", + "sidecar_sha256": "67f9015dde0043870494880620dabbb8e5ea17feb08a1da1ad21398b032228b6", + "owners": 1116, + "nonempty_views": 738, + "view_entries": 4408 + } + ] + }, + "original_producer": { + "status": "PASS", + "results": [ + { + "kind": "producer13", + "status": "PASS", + "original_call_started": true, + "original_nested_owner_count": 1054, + "original_nonempty_views": 677, + "nested_exact_capture_refs_restored": true, + "captured_external_manifest_available": true, + "input_fixture": "/home/ts/.local/state/openhcs-maintenance/20261003/current-cohort-capture-v10/output/saved-inputs/root-813175-139641010583232-0002/cohort-13-PatternGroupRuntime-_validate_and_unstack-before.pkl", + "transport": { + "root_type": null, + "array_count": 1184, + "strict_snapshot_restore": true + }, + "original_declaring_method_counts": {}, + "records": 60, + "unstack_seconds": 0.007623694837093353, + "save_seconds": 0.021458042785525322, + "full_outputdata_records_planes_named_whole_equal": true, + "complete_array_alias_graph": true, + "array_roles": 123 + } + ], + "scope": "V10 original saved receiver, fresh graph each repetition; snapshots remain immutable. Exact gates retained. Diagnostic only: graph-owned captured warm fields restored by declared exact references; globalLRU/privateepoch not guessed. No end-to-end performance claim." + }, + "original_loader": { + "status": "PASS", + "results": [ + { + "kind": "loader14", + "status": "PASS", + "original_call_started": true, + "original_nested_owner_count": 1115, + "original_nonempty_views": 738, + "nested_exact_capture_refs_restored": true, + "captured_external_manifest_available": true, + "input_fixture": "/home/ts/.local/state/openhcs-maintenance/20261003/current-cohort-capture-v10/output/saved-inputs/root-813175-139641010583232-0002/cohort-14-PatternGroupRuntime-_load_input_stack-before.pkl", + "transport": { + "root_type": null, + "array_count": 1244, + "strict_snapshot_restore": true + }, + "original_declaring_method_counts": {}, + "load_seconds": 0.009833849966526031, + "full_loaded_metadata_store_cache_equal": true, + "complete_array_alias_graph": true, + "array_roles": 104 + } + ], + "scope": "V10 original saved receiver, fresh graph each repetition; snapshots remain immutable. Exact gates retained. Diagnostic only: graph-owned captured warm fields restored by declared exact references; globalLRU/privateepoch not guessed. No end-to-end performance claim." + }, + "immediate_producer_effects": { + "status": "IMMEDIATE_RETAINED_OWNER_EFFECTS_PASS", + "kind": "producer13", + "before_owners": 1054, + "before_nonempty_views": 677, + "before_view_entries": 4286, + "immediate_after_owners": 1115, + "after_nonempty_views": 738, + "after_view_entries": 4408, + "original_shared_owners_exactly_unchanged": 1050, + "original_outside_after_scope": 4, + "replay_changed_before_owners": 0, + "replay_new_reachable_owners": 61, + "outside_original_after_observation_changes": [], + "snapshot_sha256": "3c49c2ebc3050c4bd9e62052d7a6e9acd6c095f23849f80f86a115041c544519", + "scope": "Observed immediately after original calls, before afteroracle/equality/property checks. Mapping is original before witness path->captured samegraph owner ref->actual restored owner; original after IDs only select observed retained sourceowners, never identify objects across independent processes. Newly reached owners are separate. No candidate/globalLRU/performanceclaim.", + "script_sha256": "66848b5c5f5dcf0ccf7552420754aaab2005dc1a2c563961c6b6bc8d49748728" + }, + "immediate_loader_effects": { + "status": "IMMEDIATE_RETAINED_OWNER_EFFECTS_PASS", + "kind": "loader14", + "before_owners": 1115, + "before_nonempty_views": 738, + "before_view_entries": 4408, + "immediate_after_owners": 1116, + "after_nonempty_views": 738, + "after_view_entries": 4408, + "original_shared_owners_exactly_unchanged": 1115, + "original_outside_after_scope": 0, + "replay_changed_before_owners": 0, + "replay_new_reachable_owners": 1, + "outside_original_after_observation_changes": [], + "snapshot_sha256": "2a48c08fdf3eecfdd5af13b0052ce985a21469dbbe5e5c4f97be69682a933780", + "scope": "Observed immediately after original calls, before afteroracle/equality/property checks. Mapping is original before witness path->captured samegraph owner ref->actual restored owner; original after IDs only select observed retained sourceowners, never identify objects across independent processes. Newly reached owners are separate. No candidate/globalLRU/performanceclaim.", + "script_sha256": "66848b5c5f5dcf0ccf7552420754aaab2005dc1a2c563961c6b6bc8d49748728" + }, + "full_nested_after_oracles": "Corrected actual save oracle restores all1112anchored owners after nominal parser/FileManager/backend alias registration; full loader after-oracle restores all1116owners through original captured receiver/context. No disconnected-owner exclusion or graph union. Exact rows/reference/presence/order checks from retained adapters complete before output equality.", + "science": { + "status": "FULL6CSV120TIFF_AND180_PHYSICAL_SOURCE_REFS_PASS", + "csv": 6, + "tiff": 120, + "ordered_source_refs": 180, + "physical_volumes": 3, + "native_scope": "TRANSITIVE ONLY: exact current saved science equals retained reference and B764-qualified bytes with actual same3physicalvolume inputs/180orderedrefs. Retained2native repetitions verified; native was NOT rerun for current source/environment. Original native compare API RED retained separately; no current native timing ratio or performance claim." + }, + "all_handles_terminal": true, + "large_graphs_released_and_temp_encodings_disposed": true, + "source_clean": true, + "limits": [ + "Four current original occurrences only: producer13 and loader14, independent actual before/after graphs. Not whole-pipeline heap replay.", + "All captured graph-owned declared cache fields and exact presence/absence retained; process-global functools LRU caches explicitly outside scope.", + "Diagnostic constructor/call durations are not ordinary pipeline timings or optimization gains.", + "Original V7/V8/V9 failures and incomplete original save oracle remain immutable; V10 does not reinterpret their source pins or silently repair them." + ], + "evidence_hashes": { + "controller.py": "4d96ff2362e93d8d0bbe7fe66929d4b88e8791ae2710bbfd3636713a384a358e", + "original_replay_v10.py": "7001af6479a05e0dd1afc52a1509a44fed45ce1d0c1151dee3b832dc7a96a74a", + "immediate_original_effects_v10.py": "66848b5c5f5dcf0ccf7552420754aaab2005dc1a2c563961c6b6bc8d49748728", + "science_validator.py": "3483bec5d1f3f0d12e5a09b63e233db9fed1b11f9d201f8cc37d5ae391a0c599", + "output/source-freeze.json": "6d4f4a59e62acbebbd6e21fcff66fa5806f45d99778264e7f5399b666bb3171f", + "output/observations.json": "1559ae44e06fed622816b1518132fd738f56e0355faadf9e15cdd2159052f491", + "science.json": "6f1a8078dfaa74ea840f398b5e5f5b4c0b7d370a436fc1829e4ad5d90f597b6a", + "launch.log": "7d0d52ffcd64337698061f0c4654c66f17a6f6b5b8a8931102a0003f9f6ac9a1", + "launch-v2.log": "8e4a5f55bea98fc6a40613ff182af4172800ec8a009ba5bdb3b7ef746994a2d8", + "launch-environment-diagnosis-v1.json": "d9d74e533a776d8729b9a97941dc94c1a74edc513e12c750fcc8d0dc336d6219", + "launch-environment-diagnosis-v2.json": "032936f8dc7aa279cb468e703ffa04906cfd4b4cda1fb1e44531e697a4c7a071", + "producer-original-replay-v10.log": "74091052623a193539dab4a1f11b21640099824a173abfa33ab99fb444853c53", + "loader-original-replay-v10.log": "34a4c1394fe4435ccb4d21208fd3385623e9905e965c79055e4ac564fdee46a5", + "immediate-original-effects-producer13-v1.json": "d1358af67a0163b223663811dc56f0c5ba5cdf2144d82909b578ae3c943f52a4", + "immediate-original-effects-loader14-v1.json": "fee1fb6458bcc5427fb51b748db16202957205d6f25b1a07626e38a3172c6091", + "site/nested_cache_retention.py": "7e6d9ca3e7dce0da18a603610576cc9eea2d8038ad936fe2599e5b87d94bf3b1", + "site/nested_cache_witness.py": "f8c23b439ea301b761c7329a7273ff66ff2d9a865ff7d377d82d5766432e1055", + "site/openhcs_cohort_ownership_v8_20261003.py": "89abcd4587135989c4fb5ff9a7990f6983ad428c9c403390c770c3b9330ee0ee", + "site/openhcs_cohort_snapshot_transport_v6_20261002.py": "a8b11cf6401aa0f80617e6734ae67bbbffcecc74ad4f7a59041523e42b850763", + "site/openhcs_current_cohort_capture_v10_20261003.py": "ec9af29df043c9f465ba410c7317b6668d903fca3d3308f70716a350e096c98a", + "site/ordered_array_role_oracle.py": "cf6b799a8ade0dbf82185fdc2a80f242111b784e1e643f4e91ea3456a6c5718b", + "site/sitecustomize.py": "60b213d69117b57d7c5340071db6499ff4b923d6e1baf68b05d8d1f69d8fca59" + } +} diff --git a/benchmark/results/perf_current_native_paired_20261003/README.md b/benchmark/results/perf_current_native_paired_20261003/README.md new file mode 100644 index 0000000000..1f52a1f9ea --- /dev/null +++ b/benchmark/results/perf_current_native_paired_20261003/README.md @@ -0,0 +1,20 @@ +# Current paired native comparison + +The ordinary public driver and unchanged warm native worker were run on clean source `60b2ac9b4d4fd91558f68aac85ae39b55e575fc8`, including main `f7de9efad` and the qualified ObjectState 1.1.9 / python-introspect 0.1.15 source update. CPU 5, one worker inline, one native thread, default OUTCOMES and process-tree RSS. All startup, mandatory registry/library/kernel preparation and shutdown precede/follow pipeline clocks. Native imports/JVM/pipeline loading and complete warmup -1 are outside its measured invocation. + +| Case | OH compile mean | OH execute mean | OH total mean | Native invocation mean | Execution speedup | Total speedup | +| --- | ---: | ---: | ---: | ---: | ---: | ---: | +| 3D monolayer | 1.212512 s | 9.127215 s | 11.153507 s | 14.422177 s | 1.58013x | 1.29306x | +| Speckles | 0.663492 s | 1.231350 s | 2.246087 s | 1.954230 s | 1.58706x | 0.87006x | + +Both observations are retained; ranges and exact ratios are in `qualification.json`. These descriptive two-observation means are not a causal optimization experiment or statistical significance. Reaching 2x execution still requires 1.916127 s for 3D and 0.254235 s for Speckles. The source/environment differs from historical evidence, so no source change is blamed for the observed spread. + +Every OH repetition passed against both fresh native repetitions: eight complete strict comparisons, measurements within the existing 1e-6 policy, exact 3D uint16 image values, known relationship correlations, and complete physical output inventories. OH 3D has six authored CSVs and 120 TIFFs (128 total physical files); native has two logical label volumes. Speckles has three CSVs (five total files). The existing comparator owns the native-only experiment table and managed metadata rules; no new exclusions were introduced. The selected source domains are exactly 180 refs / one volumetric image set and two refs / one image set. Root independently verified all 11 linked qualification artifacts and all 290 unique scientific physical output paths. + +The figures use the existing `benchmark.reports.cppipe_figures` owner, means from all four ordinary rows and all four native measured observations, and the 2x reference. They are a two-case preview; full30 and scaling figures remain unfinished. Figure generator evidence and raw sample custody are in `timing_summary.json`; `metrics.csv` retains the declared figure rows. + +The external immutable controllers remain at `/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-preparation-v2/controller.py` (SHA256 `b772d231196eaf23d9a150ffa491f95426cb6e074470ac3febd508afd1d3ad18`) and `/home/ts/.local/state/openhcs-maintenance/20261003/plot_current_paired_timings_v2.py`; their recipes use existing public execution and scientific comparison owners. These are local custody references, not a portable launcher. Original sparse-preparation failure and the exact-current-Git supplement are retained separately. + +Qualification SHA256: `3db0f60d3ef04aa0ce846eaef70e746031442422cc693ba943bf78ac8db1ab32`. Science SHA256: `77ab1a1e88d52502c633b646efe0d032ad87f117fc403298cb8b5742a0510190`. + +This evidence does not admit the whole PR394 R0/R1 guards, finish full-catalog parity, or establish a new performance improvement. The generic runtime plumbing goal remains active. diff --git a/benchmark/results/perf_current_native_paired_20261003/matched_runtime.png b/benchmark/results/perf_current_native_paired_20261003/matched_runtime.png new file mode 100644 index 0000000000..34bd139c92 Binary files /dev/null and b/benchmark/results/perf_current_native_paired_20261003/matched_runtime.png differ diff --git a/benchmark/results/perf_current_native_paired_20261003/matched_runtime.svg b/benchmark/results/perf_current_native_paired_20261003/matched_runtime.svg new file mode 100644 index 0000000000..24bf1032e3 --- /dev/null +++ b/benchmark/results/perf_current_native_paired_20261003/matched_runtime.svg @@ -0,0 +1,1615 @@ + + + + + + + + 2026-10-03T02:56:54.133761 + image/svg+xml + + + Matplotlib v3.11.2, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/benchmark/results/perf_current_native_paired_20261003/matched_speedup.png b/benchmark/results/perf_current_native_paired_20261003/matched_speedup.png new file mode 100644 index 0000000000..684d7d7f68 Binary files /dev/null and b/benchmark/results/perf_current_native_paired_20261003/matched_speedup.png differ diff --git a/benchmark/results/perf_current_native_paired_20261003/matched_speedup.svg b/benchmark/results/perf_current_native_paired_20261003/matched_speedup.svg new file mode 100644 index 0000000000..99ac7b2b8d --- /dev/null +++ b/benchmark/results/perf_current_native_paired_20261003/matched_speedup.svg @@ -0,0 +1,1683 @@ + + + + + + + + 2026-10-03T02:56:54.463573 + image/svg+xml + + + Matplotlib v3.11.2, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/benchmark/results/perf_current_native_paired_20261003/metrics.csv b/benchmark/results/perf_current_native_paired_20261003/metrics.csv new file mode 100644 index 0000000000..596cf18e87 --- /dev/null +++ b/benchmark/results/perf_current_native_paired_20261003/metrics.csv @@ -0,0 +1,7 @@ +pipeline_name,method,assay_category,module_category,accuracy_fraction,raw_seconds,speedup,peak_memory_mb +ExampleSpeckles,CellProfiler,,,1.0,1.9542299311142415,1.0, +ExampleSpeckles,OH execution,,,1.0,1.2313504219055176,1.5870623799276133, +ExampleSpeckles,OH total,,,1.0,2.2460867043118924,0.870059881198102, +cp_tutorial_3d_monolayer,CellProfiler,,,1.0,14.422176547115669,1.0, +cp_tutorial_3d_monolayer,OH execution,,,1.0,9.127214908599854,1.580128954071936, +cp_tutorial_3d_monolayer,OH total,,,1.0,11.153506982140243,1.2930620449881318, diff --git a/benchmark/results/perf_current_native_paired_20261003/native-3d.json b/benchmark/results/perf_current_native_paired_20261003/native-3d.json new file mode 100644 index 0000000000..01f5ea843a --- /dev/null +++ b/benchmark/results/perf_current_native_paired_20261003/native-3d.json @@ -0,0 +1,61 @@ +{ + "startup_seconds": 0.9434431060217321, + "environment": { + "python_executable": "/home/ts/code/projects/openhcs/.venv-cellprofiler39/bin/python", + "python_version": "3.9.25", + "cellprofiler_version": "4.2.8.1", + "cellprofiler_core_version": "4.2.8.1", + "numpy_version": "1.24.4", + "scipy_version": "1.9.0", + "temporary_root": "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/native/cp_tutorial_3d_monolayer/native_tmp" + }, + "request": { + "pipeline_path": "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/native/cp_tutorial_3d_monolayer/preparation/native_cellprofiler_headless/3d_monolayer_final.cppipe", + "input_dir": "/home/ts/.cache/openhcs/benchmark_datasets/CellProfiler_tutorials/data/3d_monolayer/images", + "output_root": "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/native/cp_tutorial_3d_monolayer/outputs", + "expected_image_sets": 1, + "repetitions": 2, + "file_list_path": "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/native/cp_tutorial_3d_monolayer/preparation/native_cellprofiler_file_list.txt", + "first_image_set": 1, + "last_image_set": null, + "report_path": "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/native/cp_tutorial_3d_monolayer/native_report.json", + "start_barrier_root": null, + "start_barrier_job_count": 1, + "start_barrier_job_index": 0 + }, + "observations": [ + { + "repetition": -1, + "output_root": "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/native/cp_tutorial_3d_monolayer/outputs/-1", + "image_set_count": 1, + "invocation_seconds": 15.945333322975785, + "pre_first_module_seconds": 0.4420607606880367, + "first_module_through_post_run_seconds": 15.503272562287748, + "invocation_started_monotonic_seconds": 3804735.20616804, + "first_module_started_monotonic_seconds": 3804735.648228801, + "completed_monotonic_seconds": 3804751.151501363 + }, + { + "repetition": 0, + "output_root": "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/native/cp_tutorial_3d_monolayer/outputs/0", + "image_set_count": 1, + "invocation_seconds": 14.286907745990902, + "pre_first_module_seconds": 0.1336168795824051, + "first_module_through_post_run_seconds": 14.153290866408497, + "invocation_started_monotonic_seconds": 3804751.151514428, + "first_module_started_monotonic_seconds": 3804751.285131308, + "completed_monotonic_seconds": 3804765.438422174 + }, + { + "repetition": 1, + "output_root": "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/native/cp_tutorial_3d_monolayer/outputs/1", + "image_set_count": 1, + "invocation_seconds": 14.557445348240435, + "pre_first_module_seconds": 0.13210490392521024, + "first_module_through_post_run_seconds": 14.425340444315225, + "invocation_started_monotonic_seconds": 3804765.438434918, + "first_module_started_monotonic_seconds": 3804765.570539822, + "completed_monotonic_seconds": 3804779.995880266 + } + ] +} \ No newline at end of file diff --git a/benchmark/results/perf_current_native_paired_20261003/native-speckles.json b/benchmark/results/perf_current_native_paired_20261003/native-speckles.json new file mode 100644 index 0000000000..132c17ac31 --- /dev/null +++ b/benchmark/results/perf_current_native_paired_20261003/native-speckles.json @@ -0,0 +1,61 @@ +{ + "startup_seconds": 0.807538575027138, + "environment": { + "python_executable": "/home/ts/code/projects/openhcs/.venv-cellprofiler39/bin/python", + "python_version": "3.9.25", + "cellprofiler_version": "4.2.8.1", + "cellprofiler_core_version": "4.2.8.1", + "numpy_version": "1.24.4", + "scipy_version": "1.9.0", + "temporary_root": "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/native/ExampleSpeckles/native_tmp" + }, + "request": { + "pipeline_path": "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/native/ExampleSpeckles/preparation/native_cellprofiler_headless/ExampleSpeckles.cppipe", + "input_dir": "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleSpeckles/images", + "output_root": "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/native/ExampleSpeckles/outputs", + "expected_image_sets": 1, + "repetitions": 2, + "file_list_path": "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/native/ExampleSpeckles/preparation/native_cellprofiler_file_list.txt", + "first_image_set": 1, + "last_image_set": null, + "report_path": "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/native/ExampleSpeckles/native_report.json", + "start_barrier_root": null, + "start_barrier_job_count": 1, + "start_barrier_job_index": 0 + }, + "observations": [ + { + "repetition": -1, + "output_root": "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/native/ExampleSpeckles/outputs/-1", + "image_set_count": 1, + "invocation_seconds": 3.0011698277667165, + "pre_first_module_seconds": 0.301135023124516, + "first_module_through_post_run_seconds": 2.7000348046422005, + "invocation_started_monotonic_seconds": 3804788.163755448, + "first_module_started_monotonic_seconds": 3804788.464890471, + "completed_monotonic_seconds": 3804791.164925276 + }, + { + "repetition": 0, + "output_root": "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/native/ExampleSpeckles/outputs/0", + "image_set_count": 1, + "invocation_seconds": 1.9962371489964426, + "pre_first_module_seconds": 0.10309637477621436, + "first_module_through_post_run_seconds": 1.8931407742202282, + "invocation_started_monotonic_seconds": 3804791.164935265, + "first_module_started_monotonic_seconds": 3804791.26803164, + "completed_monotonic_seconds": 3804793.161172414 + }, + { + "repetition": 1, + "output_root": "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/native/ExampleSpeckles/outputs/1", + "image_set_count": 1, + "invocation_seconds": 1.9122227132320404, + "pre_first_module_seconds": 0.07363771507516503, + "first_module_through_post_run_seconds": 1.8385849981568754, + "invocation_started_monotonic_seconds": 3804793.161182433, + "first_module_started_monotonic_seconds": 3804793.234820148, + "completed_monotonic_seconds": 3804795.073405146 + } + ] +} \ No newline at end of file diff --git a/benchmark/results/perf_current_native_paired_20261003/ordinary-0.csv b/benchmark/results/perf_current_native_paired_20261003/ordinary-0.csv new file mode 100644 index 0000000000..bb3efe6808 --- /dev/null +++ b/benchmark/results/perf_current_native_paired_20261003/ordinary-0.csv @@ -0,0 +1,3 @@ +case_name,mode_name,worker_count,well_count,compile_seconds,prepare_seconds,execute_seconds,total_seconds,wells_per_second,successful_wells,native_single_sample_execution_seconds,projected_native_execution_seconds,projected_execution_speedup,peak_memory_mb,status,memory_limit_mb,error_message,execution_route,server_lifecycle,run_input_sha256 +ExampleSpeckles,1w_1t,1,1,0.7714827060699463,0.0,1.0937919616699219,2.189194314647466,0.91425063910076,1,,,,1225.88671875,success,,,ordinary-zmq-outcomes-v1,reused-per-sweep,1a86dbcc3b37bc80fe8cc7f2605b43d0cef1fdc7d075a3b7172fe4c67ce94eb4 +cp_tutorial_3d_monolayer,1w_1t,1,1,1.1917080879211426,0.0,8.670458555221558,10.651790381409228,0.11533415373951313,1,,,,1891.54296875,success,,,ordinary-zmq-outcomes-v1,reused-per-sweep,1a86dbcc3b37bc80fe8cc7f2605b43d0cef1fdc7d075a3b7172fe4c67ce94eb4 diff --git a/benchmark/results/perf_current_native_paired_20261003/ordinary-1.csv b/benchmark/results/perf_current_native_paired_20261003/ordinary-1.csv new file mode 100644 index 0000000000..94bf2fd3ac --- /dev/null +++ b/benchmark/results/perf_current_native_paired_20261003/ordinary-1.csv @@ -0,0 +1,3 @@ +case_name,mode_name,worker_count,well_count,compile_seconds,prepare_seconds,execute_seconds,total_seconds,wells_per_second,successful_wells,native_single_sample_execution_seconds,projected_native_execution_seconds,projected_execution_speedup,peak_memory_mb,status,memory_limit_mb,error_message,execution_route,server_lifecycle,run_input_sha256 +ExampleSpeckles,1w_1t,1,1,0.5555016994476318,0.0,1.3689088821411133,2.302979093976319,0.7305088111020931,1,,,,1176.95703125,success,,,ordinary-zmq-outcomes-v1,reused-per-sweep,1a86dbcc3b37bc80fe8cc7f2605b43d0cef1fdc7d075a3b7172fe4c67ce94eb4 +cp_tutorial_3d_monolayer,1w_1t,1,1,1.23331618309021,0.0,9.58397126197815,11.655223582871258,0.10434088048314934,1,,,,1783.82421875,success,,,ordinary-zmq-outcomes-v1,reused-per-sweep,1a86dbcc3b37bc80fe8cc7f2605b43d0cef1fdc7d075a3b7172fe4c67ce94eb4 diff --git a/benchmark/results/perf_current_native_paired_20261003/qualification.json b/benchmark/results/perf_current_native_paired_20261003/qualification.json new file mode 100644 index 0000000000..251ebad0a1 --- /dev/null +++ b/benchmark/results/perf_current_native_paired_20261003/qualification.json @@ -0,0 +1,640 @@ +{ + "status": "TWO_CASE_FRESH_PAIRED_SCIENCE_PASS", + "source_head": "60b2ac9b4d4fd91558f68aac85ae39b55e575fc8", + "cases": { + "cp_tutorial_3d_monolayer": { + "ordinary_execution_seconds": [ + 8.670458555221558, + 9.58397126197815 + ], + "ordinary_total_seconds": [ + 10.651790381409228, + 11.655223582871258 + ], + "native_invocation_seconds": [ + 14.286907745990902, + 14.557445348240435 + ], + "means_seconds": { + "openhcs_execute": 9.127214908599854, + "openhcs_total": 11.153506982140243, + "openhcs_compile": 1.2125121355056763, + "native_invocation": 14.422176547115669 + }, + "descriptive_native_over_openhcs_execute": 1.580128954071936, + "descriptive_native_over_openhcs_total": 1.2930620449881318, + "remaining_seconds_to_2x_execution": 1.9161266350420192, + "remaining_seconds_to_2x_total": 3.9424187085824087, + "actual_source_refs": 180, + "actual_native_image_sets": 1, + "native_environment": { + "python_executable": "/home/ts/code/projects/openhcs/.venv-cellprofiler39/bin/python", + "python_version": "3.9.25", + "cellprofiler_version": "4.2.8.1", + "cellprofiler_core_version": "4.2.8.1", + "numpy_version": "1.24.4", + "scipy_version": "1.9.0", + "temporary_root": "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/native/cp_tutorial_3d_monolayer/native_tmp" + }, + "science_comparisons": [ + { + "ordinary_repeat": 0, + "native_repeat": 0, + "tables": [ + 7, + 6 + ], + "physical_images": [ + 2, + 120 + ], + "logical_images": [ + 2, + 2 + ], + "known_relationship_keys": [ + 3, + 3 + ] + }, + { + "ordinary_repeat": 0, + "native_repeat": 1, + "tables": [ + 7, + 6 + ], + "physical_images": [ + 2, + 120 + ], + "logical_images": [ + 2, + 2 + ], + "known_relationship_keys": [ + 3, + 3 + ] + }, + { + "ordinary_repeat": 1, + "native_repeat": 0, + "tables": [ + 7, + 6 + ], + "physical_images": [ + 2, + 120 + ], + "logical_images": [ + 2, + 2 + ], + "known_relationship_keys": [ + 3, + 3 + ] + }, + { + "ordinary_repeat": 1, + "native_repeat": 1, + "tables": [ + 7, + 6 + ], + "physical_images": [ + 2, + 120 + ], + "logical_images": [ + 2, + 2 + ], + "known_relationship_keys": [ + 3, + 3 + ] + } + ], + "raw_range_seconds": { + "native": [ + 14.286907745990902, + 14.557445348240435 + ], + "openhcs_execute": [ + 8.670458555221558, + 9.58397126197815 + ], + "openhcs_total": [ + 10.651790381409228, + 11.655223582871258 + ] + }, + "descriptive_ratio_range": { + "native_over_execute": [ + 1.490708533598217, + 1.6789706398485225 + ], + "native_over_total": [ + 1.2257943954835167, + 1.3666665252489216 + ] + }, + "complete_ordinary_physical_inventories": [ + { + "repeat": 0, + "output_roots": [ + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput" + ], + "file_count": 128, + "file_sha256": { + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/openhcs_metadata.json": "df996ea7347162652903028922a9ac2206dd2d6dbecbf9fb6da05a7e65ece370", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/openhcs_metadata.json.lock": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/results/3d_monolayer_erodedResizedNuclei.csv": "cca23f86a85bb3ee7a5c3a1d174c34b5f026ca7f399be98458e1a8c6e12d5c77", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/results/3d_monolayer_Cells.csv": "6f6e7431171ed5ea73a01784105147eca0e43a6e3e41f8720df93106353c9c79", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/results/3d_monolayer_downsizedNuclei.csv": "a7b998c5a524e11747fc5452fd763fc3d9abe16f46e961f62e09e9393b6a8adf", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/results/3d_monolayer_Nuclei.csv": "17500f5d4321bbf255df31f7a3503339029c2b077045a6c10e4d4f6f0db9ad1e", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/results/3d_monolayer_Image.csv": "75ac32ff5ef57bc285ec4eae1c9b501c27a35b486bf35435af5d499d856d34a4", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/results/3d_monolayer_erodedDownsizedNuclei.csv": "ee507fb9c2387f86fc768184baf2596ebe1f8e40f7fc5eb24f252345fee63ae6", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z052_t001_NucleiLabels.tiff": "0daf51526658e23b7c9ab8872e992ebe9322399286f95741d0ccdbd357e5d631", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z008_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z060_t001_NucleiLabels.tiff": "7cc3c6c6a22f558e62194277090bdea2deb79475dd91fe7d0e49eac3c0187388", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z015_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z057_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z021_t001_CellsLabels.tiff": "daa31cb1e537e5c32b1936ab7647c5690741d2bc1d0e15c60b59ba1310a8c0ce", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z047_t001_CellsLabels.tiff": "b926aa64e1fa8aa52279a69d91dc23cf14bf0ae76107f9b360c7ae77bdf53719", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z022_t001_NucleiLabels.tiff": "50aef20e28a2f9e18ca2e28eabf6d87ec2ad20c79898e56f8d63a959ba5bb507", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z027_t001_CellsLabels.tiff": "ee9056587a19e581f5feb6078b41fa1004d923a5ddf1725aefc4b8b8c5201ad6", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z029_t001_NucleiLabels.tiff": "34bce0f06f674e20667554eed0075fde8d9d33c9c0eaeffd88a1c558499cc432", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z007_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z018_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z047_t001_NucleiLabels.tiff": "995d5ce77cbf61a9be8590f34987ef3f1dd698ae6ed393cac4d0960bc9e7a66a", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z046_t001_CellsLabels.tiff": "dc081df050be6cd19b5d5bbfe21c96c350eecf9bc6f10f608dc361a36056632a", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z042_t001_CellsLabels.tiff": "88d2e9964455459499656c4f0a762cd86376c678756635aaa6b6c8d98be01852", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z024_t001_NucleiLabels.tiff": "9e96a05ed9860cac9c57c618db2f4fe5e4b769a9d235aac6fd1d628486317df0", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z035_t001_NucleiLabels.tiff": "13e69afc324152bb91329fa758d131d849127e8fd346078d94c6adc25582b3a6", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z055_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z050_t001_CellsLabels.tiff": "ea7654a6fe1f92ad274a54935420923eec4bec5ad030187afc0ac7af02690af5", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z014_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z031_t001_NucleiLabels.tiff": "247490c261fecc26c7379ab2eebaa01e4bea523218b3cc5491d2fe2b9aadfe11", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z020_t001_NucleiLabels.tiff": "b0cd031b448d8bd2075e65710bd76c064161b25242f85ee150da7cd139fcc1a8", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z051_t001_CellsLabels.tiff": "73483bd10a0f37990084013ad054768086d6d3c929da6bc7e74f4aee37e9dbf2", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z028_t001_CellsLabels.tiff": "fef31040e0c54501c3bf965eb98f055cdb1d42c96f91cf1c239033d0a9a06534", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z022_t001_CellsLabels.tiff": "7d7ec170ed3652efa99e43d8db546c51b696821dca7727d0ff4d2f2ead7fdbaa", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z033_t001_CellsLabels.tiff": "a320b99ee129d97b99f9fac66aabb89fc1652930b3bb8b2b3fbba7b57e994f85", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z038_t001_CellsLabels.tiff": "6ac8fd9c95acc1f261e96a8fb9332e5d6a403548842f9b85ecb977e6213b4c9b", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z051_t001_NucleiLabels.tiff": "f0f36ccaf744d42da036948682cfd226e6dd4a3cfb94aed38729b2d25ede5dff", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z023_t001_CellsLabels.tiff": "2f06989618050934c73473f9342c2fe3410fd834a0ddb976cf602fe6198db7a6", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z010_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z004_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z046_t001_NucleiLabels.tiff": "c1250e060d32f2cfc07fc7e1594fdb1d6cbb4d0483fa94a8113efa695397963c", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z003_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z026_t001_NucleiLabels.tiff": "ad22809ff3f43d15c838f697061c263070dbf1da1031da39900681cdfbf9d54c", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z054_t001_CellsLabels.tiff": "25ff2ec586a568e42286f73713d64aab1208c38c016099299211f04368ac49c8", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z039_t001_CellsLabels.tiff": "22fa79a76e64013f10373be2ca2af98a2173275c5d43c9cad33135acdc376d14", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z057_t001_NucleiLabels.tiff": "695517641e9fe4b8421d4a7db56b24c755b6957c98ce32bb24ad5b25f52661eb", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z020_t001_CellsLabels.tiff": "e8105a4f04198ac75de9831247030084d6f65bf98691d7444ead7e178072fa22", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z008_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z037_t001_NucleiLabels.tiff": "927d52441c57cb3a4014effaca3e3c23c76275fb264c26e1942a9c58b85ee6d2", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z011_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z043_t001_NucleiLabels.tiff": "81a705d05b0a5bfa8783df28990c1d70634c1f4aa2bca23e02cfa8a4bc861b86", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z015_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z041_t001_NucleiLabels.tiff": "744eab7cd170d5af8d2f72ced3893dd939c4e1b0f415afab799a37ded5d046c7", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z060_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z055_t001_NucleiLabels.tiff": "44e02416cc94a70528165a4b6c42b9e19b205f9c91528076796272cb1a8504ea", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z033_t001_NucleiLabels.tiff": "512a3a0ed8025d14b0556a72ebfc13b173d14f7046817ca09876242ab63b9d6b", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z050_t001_NucleiLabels.tiff": "565b4f08f7503086c1f2f8e631d19063129e02a5767d2f979c0cec8fdec23601", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z009_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z036_t001_CellsLabels.tiff": "28b68d1300cf7b08e21dbcd4858447862520dded5c27f2d84cf223513a119eed", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z049_t001_NucleiLabels.tiff": "e92e493078672a0e0d90e31409612e215bf8486300d5c765d0e0504ff8888e7a", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z040_t001_NucleiLabels.tiff": "e0bd66b166e9f92120dbee183973849eda0afbbe6fed9d03fc4cfd2c56a96280", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z016_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z012_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z001_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z053_t001_NucleiLabels.tiff": "b8613192175a4615b58aed607474657668429cb6ac635cd012569b19667f2d3d", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z017_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z006_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z032_t001_CellsLabels.tiff": "8a2c5774044326ae722e41aae517266197fbebb0e4dd5eab4b22414fbfea309f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z032_t001_NucleiLabels.tiff": "97b09fe5444ad439c3c2007d75971dce2766d94c93268eccfee9ae49b8a04aa1", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z058_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z048_t001_NucleiLabels.tiff": "325478230529e94ba372f38f0bf512292f131d337b6ac09ce5a91b0266724e02", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z006_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z038_t001_NucleiLabels.tiff": "e2852ea83c62ab30d77681b4e39f88d3cee74ae052f1c948675ae3581c9fc28a", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z052_t001_CellsLabels.tiff": "7bb98f0587062e01b965e486fc687872651d7d90d271a2fdf0d35d67b464b233", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z041_t001_CellsLabels.tiff": "be7762756eb65f08cb337904165c6f43b5351f39405461f65ad28669abfe3899", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z005_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z011_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z044_t001_NucleiLabels.tiff": "a78264f2f5e245a3913a69f89105e94df30048b1aaef4eb80fc5c3235e78b196", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z029_t001_CellsLabels.tiff": "b3bdde5f751b8f5d41ca8b5219a3427e450cb1b8795401d0ec638940d1ad7bd9", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z059_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z056_t001_NucleiLabels.tiff": "ca0723c8b9764d5b77034719bb75a2940be35da2e04119af4c0e6d3552c08718", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z019_t001_CellsLabels.tiff": "ec6ef1d319f2732c47b06f5cf02775c8cd94540f2f30a6c002f0aace1d317955", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z002_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z036_t001_NucleiLabels.tiff": "4fa967c78709aa400246a50528a36b24ca366e825dd0e64561643369e814906b", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z039_t001_NucleiLabels.tiff": "f93e8293a37886a36844b8748083a1f8e717efab092652755263e797f12f0364", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z044_t001_CellsLabels.tiff": "e03946d94c789ee787cc29a3c8f5e5d9c56b37a0044b297ba8f403abc98eb55e", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z025_t001_CellsLabels.tiff": "03aabe5528198cfd6ec23a058dab540fb8be0870207c6dc94a62d9b621d1f2f9", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z045_t001_NucleiLabels.tiff": "94bd6a65795ad6395cc18a4fd63dc591354bef612ee49fffd2d9f63e4ed9db84", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z026_t001_CellsLabels.tiff": "5b433d931fa6637fc793b23880199c01000ef6d9e610903bb38bb8cea5574563", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z016_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z027_t001_NucleiLabels.tiff": "8c8f402d3a7c65c04e7f1575dd34de0427eeeb433ff2956d20e07d06eb48fb8d", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z018_t001_NucleiLabels.tiff": "03ba7a4d6ae53e6c84aab5926ae1e2592b5f8ca24a839a256c82f08544df4270", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z010_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z040_t001_CellsLabels.tiff": "1635ea20dd80ce99f0e86494666825a52a66645837d598fd3a3fa91f0bb77d53", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z013_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z003_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z024_t001_CellsLabels.tiff": "39899adabca74b10b9950d1f97e8b0b3bbaf136d75e7a46ef4a6e86896e3119f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z014_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z007_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z002_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z056_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z042_t001_NucleiLabels.tiff": "e07252ca1a55c5195c99666d8d3f0d70db636b4ef4b99e1a0049ca22b182d87a", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z017_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z025_t001_NucleiLabels.tiff": "9cc33676a0177130609ab1331feab1722bbde8d55b2f49031730fd5a2a40029c", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z031_t001_CellsLabels.tiff": "1b14aab71bf3623458ea9373852b0baf28be9727877b32f894407927ecfb6d65", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z035_t001_CellsLabels.tiff": "eedeb489b46abf1eafbd9c81491cb3f85ce1cb3ce877844ad22e72547fc3c438", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z021_t001_NucleiLabels.tiff": "71a10b0539f3fc4cba600b275b7e948258c6a435ba33ef522faa0869ac085518", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z019_t001_NucleiLabels.tiff": "250cb56a8054c28cea894bc3d9edaddcdce01f5151a05da78da20157c3c3be9f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z043_t001_CellsLabels.tiff": "bd0df007524ea4e555e4d2fdbebe6a274caa03bc360a1cf90d601659155984b2", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z001_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z059_t001_NucleiLabels.tiff": "76c785cf0f481c73ad3cf34ccb576eaa19dd1bdd9c74f9eaf92adfbde5d44b97", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z048_t001_CellsLabels.tiff": "133a58f6fac8b07f79bfed9634867ccb5428b83e63682031a1def16c6a694568", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z005_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z058_t001_NucleiLabels.tiff": "a37c63c6052e40d73db918a014e6f2a18be4d0cbfbeeef65a9c26096a38a4c09", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z013_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z037_t001_CellsLabels.tiff": "aa1f449f1769b27cd9f1076e70f49f0242e2549f288a77984ca159cb07cf6a40", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z004_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z030_t001_CellsLabels.tiff": "b71a2e05d270ae0cd237d6c0d97ea82a63e5ad3633723e7255c35d34e585ec80", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z054_t001_NucleiLabels.tiff": "b841c5d901c65a6138d9ff2b0ec4aa04f00765b1dd21bcd6fc9f8dc974c6035d", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z023_t001_NucleiLabels.tiff": "ecb7f78c8ca0bad2b9d0495659609b9023781b6a936d6afb0a04653eac176555", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z053_t001_CellsLabels.tiff": "ff17f538baaf179752412026a250bdbee016e3101037bf4e0dbb81199fc4c8ed", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z034_t001_CellsLabels.tiff": "3f6c1d8cdbce20aac8f70e7315bea70b147b7b6a034432845b27eeb6cfba083c", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z045_t001_CellsLabels.tiff": "c678f2100c7431e5a43c391af86a79e3436d4cf13f050f98c25f62682e4632fe", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z034_t001_NucleiLabels.tiff": "08af61857cfb97fd95fcb08d1ce18139ce7087b192044c63452bee533c5b1aa4", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z009_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z028_t001_NucleiLabels.tiff": "1676f21bd3b7e105601c83f206890507c32ba2447988be2a75d0e8153d069b65", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z012_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z030_t001_NucleiLabels.tiff": "c54c8b98a5c38a47e0cf9391a1afab09b4c8c58e06294cdb650a15add4a32b58", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z049_t001_CellsLabels.tiff": "28d83dfbf5bbf7e4da9c3e4806353e9fd0a89680dcdab4b43ca2fd19b80f669c" + }, + "receipt": "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/ordinary_run_evidence/cp_tutorial_3d_monolayer-1w_1t-1791010195055995834/measured_pipeline_receipt.json", + "receipt_sha256": "4fd3a5d08663ac900fef96a286b12329bf8eac5eb10c0bc1d015cf1b3feb390b" + }, + { + "repeat": 1, + "output_roots": [ + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput" + ], + "file_count": 128, + "file_sha256": { + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/openhcs_metadata.json": "2b1c063d1583e1eacc2c087e956acb68f69b4554cd8d04c0d3e4dd4d641053e4", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/openhcs_metadata.json.lock": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/results/3d_monolayer_erodedResizedNuclei.csv": "cca23f86a85bb3ee7a5c3a1d174c34b5f026ca7f399be98458e1a8c6e12d5c77", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/results/3d_monolayer_Cells.csv": "6f6e7431171ed5ea73a01784105147eca0e43a6e3e41f8720df93106353c9c79", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/results/3d_monolayer_downsizedNuclei.csv": "a7b998c5a524e11747fc5452fd763fc3d9abe16f46e961f62e09e9393b6a8adf", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/results/3d_monolayer_Nuclei.csv": "17500f5d4321bbf255df31f7a3503339029c2b077045a6c10e4d4f6f0db9ad1e", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/results/3d_monolayer_Image.csv": "75ac32ff5ef57bc285ec4eae1c9b501c27a35b486bf35435af5d499d856d34a4", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/results/3d_monolayer_erodedDownsizedNuclei.csv": "ee507fb9c2387f86fc768184baf2596ebe1f8e40f7fc5eb24f252345fee63ae6", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z052_t001_NucleiLabels.tiff": "0daf51526658e23b7c9ab8872e992ebe9322399286f95741d0ccdbd357e5d631", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z008_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z060_t001_NucleiLabels.tiff": "7cc3c6c6a22f558e62194277090bdea2deb79475dd91fe7d0e49eac3c0187388", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z015_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z057_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z021_t001_CellsLabels.tiff": "daa31cb1e537e5c32b1936ab7647c5690741d2bc1d0e15c60b59ba1310a8c0ce", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z047_t001_CellsLabels.tiff": "b926aa64e1fa8aa52279a69d91dc23cf14bf0ae76107f9b360c7ae77bdf53719", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z022_t001_NucleiLabels.tiff": "50aef20e28a2f9e18ca2e28eabf6d87ec2ad20c79898e56f8d63a959ba5bb507", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z027_t001_CellsLabels.tiff": "ee9056587a19e581f5feb6078b41fa1004d923a5ddf1725aefc4b8b8c5201ad6", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z029_t001_NucleiLabels.tiff": "34bce0f06f674e20667554eed0075fde8d9d33c9c0eaeffd88a1c558499cc432", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z007_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z018_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z047_t001_NucleiLabels.tiff": "995d5ce77cbf61a9be8590f34987ef3f1dd698ae6ed393cac4d0960bc9e7a66a", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z046_t001_CellsLabels.tiff": "dc081df050be6cd19b5d5bbfe21c96c350eecf9bc6f10f608dc361a36056632a", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z042_t001_CellsLabels.tiff": "88d2e9964455459499656c4f0a762cd86376c678756635aaa6b6c8d98be01852", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z024_t001_NucleiLabels.tiff": "9e96a05ed9860cac9c57c618db2f4fe5e4b769a9d235aac6fd1d628486317df0", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z035_t001_NucleiLabels.tiff": "13e69afc324152bb91329fa758d131d849127e8fd346078d94c6adc25582b3a6", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z055_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z050_t001_CellsLabels.tiff": "ea7654a6fe1f92ad274a54935420923eec4bec5ad030187afc0ac7af02690af5", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z014_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z031_t001_NucleiLabels.tiff": "247490c261fecc26c7379ab2eebaa01e4bea523218b3cc5491d2fe2b9aadfe11", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z020_t001_NucleiLabels.tiff": "b0cd031b448d8bd2075e65710bd76c064161b25242f85ee150da7cd139fcc1a8", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z051_t001_CellsLabels.tiff": "73483bd10a0f37990084013ad054768086d6d3c929da6bc7e74f4aee37e9dbf2", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z028_t001_CellsLabels.tiff": "fef31040e0c54501c3bf965eb98f055cdb1d42c96f91cf1c239033d0a9a06534", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z022_t001_CellsLabels.tiff": "7d7ec170ed3652efa99e43d8db546c51b696821dca7727d0ff4d2f2ead7fdbaa", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z033_t001_CellsLabels.tiff": "a320b99ee129d97b99f9fac66aabb89fc1652930b3bb8b2b3fbba7b57e994f85", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z038_t001_CellsLabels.tiff": "6ac8fd9c95acc1f261e96a8fb9332e5d6a403548842f9b85ecb977e6213b4c9b", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z051_t001_NucleiLabels.tiff": "f0f36ccaf744d42da036948682cfd226e6dd4a3cfb94aed38729b2d25ede5dff", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z023_t001_CellsLabels.tiff": "2f06989618050934c73473f9342c2fe3410fd834a0ddb976cf602fe6198db7a6", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z010_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z004_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z046_t001_NucleiLabels.tiff": "c1250e060d32f2cfc07fc7e1594fdb1d6cbb4d0483fa94a8113efa695397963c", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z003_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z026_t001_NucleiLabels.tiff": "ad22809ff3f43d15c838f697061c263070dbf1da1031da39900681cdfbf9d54c", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z054_t001_CellsLabels.tiff": "25ff2ec586a568e42286f73713d64aab1208c38c016099299211f04368ac49c8", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z039_t001_CellsLabels.tiff": "22fa79a76e64013f10373be2ca2af98a2173275c5d43c9cad33135acdc376d14", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z057_t001_NucleiLabels.tiff": "695517641e9fe4b8421d4a7db56b24c755b6957c98ce32bb24ad5b25f52661eb", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z020_t001_CellsLabels.tiff": "e8105a4f04198ac75de9831247030084d6f65bf98691d7444ead7e178072fa22", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z008_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z037_t001_NucleiLabels.tiff": "927d52441c57cb3a4014effaca3e3c23c76275fb264c26e1942a9c58b85ee6d2", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z011_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z043_t001_NucleiLabels.tiff": "81a705d05b0a5bfa8783df28990c1d70634c1f4aa2bca23e02cfa8a4bc861b86", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z015_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z041_t001_NucleiLabels.tiff": "744eab7cd170d5af8d2f72ced3893dd939c4e1b0f415afab799a37ded5d046c7", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z060_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z055_t001_NucleiLabels.tiff": "44e02416cc94a70528165a4b6c42b9e19b205f9c91528076796272cb1a8504ea", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z033_t001_NucleiLabels.tiff": "512a3a0ed8025d14b0556a72ebfc13b173d14f7046817ca09876242ab63b9d6b", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z050_t001_NucleiLabels.tiff": "565b4f08f7503086c1f2f8e631d19063129e02a5767d2f979c0cec8fdec23601", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z009_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z036_t001_CellsLabels.tiff": "28b68d1300cf7b08e21dbcd4858447862520dded5c27f2d84cf223513a119eed", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z049_t001_NucleiLabels.tiff": "e92e493078672a0e0d90e31409612e215bf8486300d5c765d0e0504ff8888e7a", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z040_t001_NucleiLabels.tiff": "e0bd66b166e9f92120dbee183973849eda0afbbe6fed9d03fc4cfd2c56a96280", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z016_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z012_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z001_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z053_t001_NucleiLabels.tiff": "b8613192175a4615b58aed607474657668429cb6ac635cd012569b19667f2d3d", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z017_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z006_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z032_t001_CellsLabels.tiff": "8a2c5774044326ae722e41aae517266197fbebb0e4dd5eab4b22414fbfea309f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z032_t001_NucleiLabels.tiff": "97b09fe5444ad439c3c2007d75971dce2766d94c93268eccfee9ae49b8a04aa1", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z058_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z048_t001_NucleiLabels.tiff": "325478230529e94ba372f38f0bf512292f131d337b6ac09ce5a91b0266724e02", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z006_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z038_t001_NucleiLabels.tiff": "e2852ea83c62ab30d77681b4e39f88d3cee74ae052f1c948675ae3581c9fc28a", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z052_t001_CellsLabels.tiff": "7bb98f0587062e01b965e486fc687872651d7d90d271a2fdf0d35d67b464b233", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z041_t001_CellsLabels.tiff": "be7762756eb65f08cb337904165c6f43b5351f39405461f65ad28669abfe3899", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z005_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z011_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z044_t001_NucleiLabels.tiff": "a78264f2f5e245a3913a69f89105e94df30048b1aaef4eb80fc5c3235e78b196", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z029_t001_CellsLabels.tiff": "b3bdde5f751b8f5d41ca8b5219a3427e450cb1b8795401d0ec638940d1ad7bd9", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z059_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z056_t001_NucleiLabels.tiff": "ca0723c8b9764d5b77034719bb75a2940be35da2e04119af4c0e6d3552c08718", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z019_t001_CellsLabels.tiff": "ec6ef1d319f2732c47b06f5cf02775c8cd94540f2f30a6c002f0aace1d317955", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z002_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z036_t001_NucleiLabels.tiff": "4fa967c78709aa400246a50528a36b24ca366e825dd0e64561643369e814906b", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z039_t001_NucleiLabels.tiff": "f93e8293a37886a36844b8748083a1f8e717efab092652755263e797f12f0364", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z044_t001_CellsLabels.tiff": "e03946d94c789ee787cc29a3c8f5e5d9c56b37a0044b297ba8f403abc98eb55e", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z025_t001_CellsLabels.tiff": "03aabe5528198cfd6ec23a058dab540fb8be0870207c6dc94a62d9b621d1f2f9", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z045_t001_NucleiLabels.tiff": "94bd6a65795ad6395cc18a4fd63dc591354bef612ee49fffd2d9f63e4ed9db84", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z026_t001_CellsLabels.tiff": "5b433d931fa6637fc793b23880199c01000ef6d9e610903bb38bb8cea5574563", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z016_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z027_t001_NucleiLabels.tiff": "8c8f402d3a7c65c04e7f1575dd34de0427eeeb433ff2956d20e07d06eb48fb8d", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z018_t001_NucleiLabels.tiff": "03ba7a4d6ae53e6c84aab5926ae1e2592b5f8ca24a839a256c82f08544df4270", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z010_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z040_t001_CellsLabels.tiff": "1635ea20dd80ce99f0e86494666825a52a66645837d598fd3a3fa91f0bb77d53", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z013_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z003_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z024_t001_CellsLabels.tiff": "39899adabca74b10b9950d1f97e8b0b3bbaf136d75e7a46ef4a6e86896e3119f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z014_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z007_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z002_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z056_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z042_t001_NucleiLabels.tiff": "e07252ca1a55c5195c99666d8d3f0d70db636b4ef4b99e1a0049ca22b182d87a", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z017_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z025_t001_NucleiLabels.tiff": "9cc33676a0177130609ab1331feab1722bbde8d55b2f49031730fd5a2a40029c", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z031_t001_CellsLabels.tiff": "1b14aab71bf3623458ea9373852b0baf28be9727877b32f894407927ecfb6d65", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z035_t001_CellsLabels.tiff": "eedeb489b46abf1eafbd9c81491cb3f85ce1cb3ce877844ad22e72547fc3c438", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z021_t001_NucleiLabels.tiff": "71a10b0539f3fc4cba600b275b7e948258c6a435ba33ef522faa0869ac085518", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z019_t001_NucleiLabels.tiff": "250cb56a8054c28cea894bc3d9edaddcdce01f5151a05da78da20157c3c3be9f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z043_t001_CellsLabels.tiff": "bd0df007524ea4e555e4d2fdbebe6a274caa03bc360a1cf90d601659155984b2", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z001_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z059_t001_NucleiLabels.tiff": "76c785cf0f481c73ad3cf34ccb576eaa19dd1bdd9c74f9eaf92adfbde5d44b97", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z048_t001_CellsLabels.tiff": "133a58f6fac8b07f79bfed9634867ccb5428b83e63682031a1def16c6a694568", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z005_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z058_t001_NucleiLabels.tiff": "a37c63c6052e40d73db918a014e6f2a18be4d0cbfbeeef65a9c26096a38a4c09", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z013_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z037_t001_CellsLabels.tiff": "aa1f449f1769b27cd9f1076e70f49f0242e2549f288a77984ca159cb07cf6a40", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z004_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z030_t001_CellsLabels.tiff": "b71a2e05d270ae0cd237d6c0d97ea82a63e5ad3633723e7255c35d34e585ec80", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z054_t001_NucleiLabels.tiff": "b841c5d901c65a6138d9ff2b0ec4aa04f00765b1dd21bcd6fc9f8dc974c6035d", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z023_t001_NucleiLabels.tiff": "ecb7f78c8ca0bad2b9d0495659609b9023781b6a936d6afb0a04653eac176555", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z053_t001_CellsLabels.tiff": "ff17f538baaf179752412026a250bdbee016e3101037bf4e0dbb81199fc4c8ed", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z034_t001_CellsLabels.tiff": "3f6c1d8cdbce20aac8f70e7315bea70b147b7b6a034432845b27eeb6cfba083c", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z045_t001_CellsLabels.tiff": "c678f2100c7431e5a43c391af86a79e3436d4cf13f050f98c25f62682e4632fe", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z034_t001_NucleiLabels.tiff": "08af61857cfb97fd95fcb08d1ce18139ce7087b192044c63452bee533c5b1aa4", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z009_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z028_t001_NucleiLabels.tiff": "1676f21bd3b7e105601c83f206890507c32ba2447988be2a75d0e8153d069b65", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z012_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z030_t001_NucleiLabels.tiff": "c54c8b98a5c38a47e0cf9391a1afab09b4c8c58e06294cdb650a15add4a32b58", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z049_t001_CellsLabels.tiff": "28d83dfbf5bbf7e4da9c3e4806353e9fd0a89680dcdab4b43ca2fd19b80f669c" + }, + "receipt": "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/ordinary_run_evidence/cp_tutorial_3d_monolayer-1w_1t-1791010233174646417/measured_pipeline_receipt.json", + "receipt_sha256": "f2f35969c4e153c03e7b921da2503929020c1ecce2d64bbaa49c04033fe1494a" + } + ] + }, + "ExampleSpeckles": { + "ordinary_execution_seconds": [ + 1.0937919616699219, + 1.3689088821411133 + ], + "ordinary_total_seconds": [ + 2.189194314647466, + 2.302979093976319 + ], + "native_invocation_seconds": [ + 1.9962371489964426, + 1.9122227132320404 + ], + "means_seconds": { + "openhcs_execute": 1.2313504219055176, + "openhcs_total": 2.2460867043118924, + "openhcs_compile": 0.6634922027587891, + "native_invocation": 1.9542299311142415 + }, + "descriptive_native_over_openhcs_execute": 1.5870623799276133, + "descriptive_native_over_openhcs_total": 0.870059881198102, + "remaining_seconds_to_2x_execution": 0.25423545634839684, + "remaining_seconds_to_2x_total": 1.2689717387547716, + "actual_source_refs": 2, + "actual_native_image_sets": 1, + "native_environment": { + "python_executable": "/home/ts/code/projects/openhcs/.venv-cellprofiler39/bin/python", + "python_version": "3.9.25", + "cellprofiler_version": "4.2.8.1", + "cellprofiler_core_version": "4.2.8.1", + "numpy_version": "1.24.4", + "scipy_version": "1.9.0", + "temporary_root": "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/native/ExampleSpeckles/native_tmp" + }, + "science_comparisons": [ + { + "ordinary_repeat": 0, + "native_repeat": 0, + "tables": [ + 3, + 3 + ], + "physical_images": [ + 0, + 0 + ], + "logical_images": [ + 0, + 0 + ], + "known_relationship_keys": [ + 1, + 1 + ] + }, + { + "ordinary_repeat": 0, + "native_repeat": 1, + "tables": [ + 3, + 3 + ], + "physical_images": [ + 0, + 0 + ], + "logical_images": [ + 0, + 0 + ], + "known_relationship_keys": [ + 1, + 1 + ] + }, + { + "ordinary_repeat": 1, + "native_repeat": 0, + "tables": [ + 3, + 3 + ], + "physical_images": [ + 0, + 0 + ], + "logical_images": [ + 0, + 0 + ], + "known_relationship_keys": [ + 1, + 1 + ] + }, + { + "ordinary_repeat": 1, + "native_repeat": 1, + "tables": [ + 3, + 3 + ], + "physical_images": [ + 0, + 0 + ], + "logical_images": [ + 0, + 0 + ], + "known_relationship_keys": [ + 1, + 1 + ] + } + ], + "raw_range_seconds": { + "native": [ + 1.9122227132320404, + 1.9962371489964426 + ], + "openhcs_execute": [ + 1.0937919616699219, + 1.3689088821411133 + ], + "openhcs_total": [ + 2.189194314647466, + 2.302979093976319 + ] + }, + "descriptive_ratio_range": { + "native_over_execute": [ + 1.3968955408055566, + 1.8250610892666765 + ], + "native_over_total": [ + 0.8303256934609861, + 0.9118592788406287 + ] + }, + "complete_ordinary_physical_inventories": [ + { + "repeat": 0, + "output_roots": [ + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/ExampleSpeckles/wells_1/workers_1/images_ExampleSpeckles_source_workspace_well_throughput" + ], + "file_count": 5, + "file_sha256": { + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/ExampleSpeckles/wells_1/workers_1/images_ExampleSpeckles_source_workspace_well_throughput/openhcs_metadata.json": "71582c62cabb2571ebf8a0de57f92fdf82c55a7ece3dac0bf2a6eca95cad84c9", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/ExampleSpeckles/wells_1/workers_1/images_ExampleSpeckles_source_workspace_well_throughput/openhcs_metadata.json.lock": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/ExampleSpeckles/wells_1/workers_1/images_ExampleSpeckles_source_workspace_well_throughput/results/Nuclei.csv": "e50cb9f8c23f65e9ce8db25132263cf4a4448ed65fc1088d782536abf74c5670", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/ExampleSpeckles/wells_1/workers_1/images_ExampleSpeckles_source_workspace_well_throughput/results/h2ax.csv": "eb453565f3b79ac932eeb5cde8605888b72e58c80f42edbbf0b1ba37f34fd6f8", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/ExampleSpeckles/wells_1/workers_1/images_ExampleSpeckles_source_workspace_well_throughput/results/Image.csv": "85ef16f24e75f03dc7055215cf2e6cb196b1dc0a0d73713a4c5999f698d4f96e" + }, + "receipt": "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/ExampleSpeckles/wells_1/workers_1/ordinary_run_evidence/ExampleSpeckles-1w_1t-1791010191010518862/measured_pipeline_receipt.json", + "receipt_sha256": "cda421a4fe86662f7be512585425e834739b510b6e0b31e8396f28ed2e123c16" + }, + { + "repeat": 1, + "output_roots": [ + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/ExampleSpeckles/wells_1/workers_1/images_ExampleSpeckles_source_workspace_well_throughput" + ], + "file_count": 5, + "file_sha256": { + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/ExampleSpeckles/wells_1/workers_1/images_ExampleSpeckles_source_workspace_well_throughput/openhcs_metadata.json": "71582c62cabb2571ebf8a0de57f92fdf82c55a7ece3dac0bf2a6eca95cad84c9", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/ExampleSpeckles/wells_1/workers_1/images_ExampleSpeckles_source_workspace_well_throughput/openhcs_metadata.json.lock": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/ExampleSpeckles/wells_1/workers_1/images_ExampleSpeckles_source_workspace_well_throughput/results/Nuclei.csv": "e50cb9f8c23f65e9ce8db25132263cf4a4448ed65fc1088d782536abf74c5670", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/ExampleSpeckles/wells_1/workers_1/images_ExampleSpeckles_source_workspace_well_throughput/results/h2ax.csv": "eb453565f3b79ac932eeb5cde8605888b72e58c80f42edbbf0b1ba37f34fd6f8", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/ExampleSpeckles/wells_1/workers_1/images_ExampleSpeckles_source_workspace_well_throughput/results/Image.csv": "85ef16f24e75f03dc7055215cf2e6cb196b1dc0a0d73713a4c5999f698d4f96e" + }, + "receipt": "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/ExampleSpeckles/wells_1/workers_1/ordinary_run_evidence/ExampleSpeckles-1w_1t-1791010228935841467/measured_pipeline_receipt.json", + "receipt_sha256": "52bfa7d40c01a6f5405d57bb6d3d6652c4c592746a50b35677cdec241045e868" + } + ] + } + }, + "source_env_native_input_sparse_freeze": "PASS before and after all original actions; original V1 missing-new-sparse-doc failure retained. V2 exact new Git-blob supplement with unchanged inventory validator.", + "science": "8 complete comparisons; strict1e-6 measurement/float policy, exact3Duint16 image policy, known cross-output relationship correlations and full scientific physical inventory; no exclusions, aliases or fallback.", + "clocks": "Existing ordinary public driver/defaultOUTCOMES/defaultRSS; READY startup and shutdown outside OH clocks. Unchanged native warm batch excludes interpreter/import/JVM/load and warmup-1, invocation includes prepare/modules/post_run/close. CPU5 native thread1; prepare/readersCPU3.", + "limits": "Two observations per workload are descriptive, not statistical significance or a causal code gain. Current branch/shared dependencies differ from earlier evidence; no attribution of changes. This is not full30 acceptance or broad R0/R1 waiver.", + "generated_files_bytes": 37827386, + "generated_budget_bytes": 157286400, + "artifact_sha256": { + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/source-freeze.json": "72e1b4f14c8c7bf03517c8d99329a1a49182fefa4b128d87326abd5b3ed829b8", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/strict-science.json": "77ab1a1e88d52502c633b646efe0d032ad87f117fc403298cb8b5742a0510190", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-preparation-v2/controller.py": "b772d231196eaf23d9a150ffa491f95426cb6e074470ac3febd508afd1d3ad18", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-preparation-v2/prepare.log": "33eba2651dcf37602dc55b42146f8beff10526831b86583b96b9ddf26d4f67d3", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-preparation-v2/ordinary.log": "20e43f8c2295b7d987c18fefee0d628817bfc47828f643148dc659d99dbeeed3", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-preparation-v2/native.log": "db94eaf7177b9367684a661ccfc6a801348054bfa3505a20ee01b22c030108d7", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-preparation-v2/compare.log": "36f725536f8eae4e5c286d5763031fbafdf2bf880b73557248cfb03692c98b97", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/well_throughput.csv": "43680d83b0df5de1391448655370b1bd013a5b70581741689bc2b3d6cac9db3f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/well_throughput.csv": "54d24ecc9904bafc59405692862769ccbc11b663eae8420d24e2e77886d0bac3", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/native/cp_tutorial_3d_monolayer/native_report.json": "f1f5804eaef6af43b73f0608071ff57c62691bbd9172b33fa45ca633a4593654", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/native/ExampleSpeckles/native_report.json": "25f17f873f96555efb451ecbd39ce03545fb722aaca66a27b64a199fc8e67beb" + }, + "handles": { + "prepare12999": "TERMINAL0", + "ordinary24312": "TERMINAL0", + "native96389": "TERMINAL0", + "compare44367": "TERMINAL0" + }, + "source_state_unchanged": true, + "home_free_bytes": 75883118592, + "var_tmp_free_bytes": 537546752, + "source_freeze_sha256": "72e1b4f14c8c7bf03517c8d99329a1a49182fefa4b128d87326abd5b3ed829b8", + "strict_science_sha256": "77ab1a1e88d52502c633b646efe0d032ad87f117fc403298cb8b5742a0510190", + "parent_custody_paths": { + "source_env_inputs_helpers": "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/source-freeze.json", + "all_compared_output_hashes": "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/strict-science.json", + "original_sparse_prepare_failure": "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-preparation-v1/prepare.log", + "new_current_docs_exact_Git_custody": "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-preparation-v2/sparse-supplement/preservation.json" + }, + "release": "All four owned action handles terminal0; no resident graph or benchmark/reader process remains. Source/environment/helper freeze released now. All generated scientific outputs retained immutable; no further benchmark/capture authorized by this completed protocol.", + "figures": "Separate parent-owned existing generator preview pending; no figure hashes yet. Full30/scaling qualification unfinished." +} diff --git a/benchmark/results/perf_current_native_paired_20261003/strict-science.json b/benchmark/results/perf_current_native_paired_20261003/strict-science.json new file mode 100644 index 0000000000..49c5db3d62 --- /dev/null +++ b/benchmark/results/perf_current_native_paired_20261003/strict-science.json @@ -0,0 +1,795 @@ +{ + "status": "PASS", + "comparisons": [ + { + "case": "cp_tutorial_3d_monolayer", + "ordinary_repeat": 0, + "native_repeat": 0, + "measurement_differences": 0, + "image_differences": 0, + "tables": [ + 7, + 6 + ], + "physical_images": [ + 2, + 120 + ], + "logical_images": [ + 2, + 2 + ], + "known_relationship_keys": [ + 3, + 3 + ], + "ordinary_receipt_sha256": "4fd3a5d08663ac900fef96a286b12329bf8eac5eb10c0bc1d015cf1b3feb390b", + "output_hashes": { + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/native/cp_tutorial_3d_monolayer/outputs/0/3d_monolayer_xy1_ch2_NucleiLabels.tiff": "340bbd795541e4031749d1fff767fa4fcdcac10f5b97879056b25dac9fd7674b", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/native/cp_tutorial_3d_monolayer/outputs/0/3d_monolayer_erodedResizedNuclei.csv": "66a58f78cab0cfdbe907468e8ba383fc59fab49025b84b589855bdfa04854609", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/native/cp_tutorial_3d_monolayer/outputs/0/3d_monolayer_Experiment.csv": "c05f0a11f43a5bda943e9f739ff257216f8ab3f65d8988a0d3d0c612c1db6997", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/native/cp_tutorial_3d_monolayer/outputs/0/3d_monolayer_downsizedNuclei.csv": "2c66bc7b17de52147d5a875403f9a9746019ac61371c08157979044c6ed818dd", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/native/cp_tutorial_3d_monolayer/outputs/0/3d_monolayer_Cells.csv": "cc34681db8a66c38ca77bc47db496b26703f21e4d7c7628dd74e30c33250859f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/native/cp_tutorial_3d_monolayer/outputs/0/3d_monolayer_Nuclei.csv": "440c33edc7e8cb5611910a835454db62390301a7af617a542349f60aece57561", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/native/cp_tutorial_3d_monolayer/outputs/0/3d_monolayer_erodedDownsizedNuclei.csv": "527a0cce497d2a618478be84d1a0bf174049f58aa2a666e37626a990fdca0116", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/native/cp_tutorial_3d_monolayer/outputs/0/3d_monolayer_Image.csv": "1f3dec653b6909c8a81ac109ce1faf91380886ac9a18e56fafc91102d419904e", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/native/cp_tutorial_3d_monolayer/outputs/0/3d_monolayer_xy1_ch0_CellsLabels.tiff": "aaed9ed23179a162ee7f5a7e8d1d88f1fa342ca55172b7fccd4cbf67f7841d81", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z015_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z048_t001_NucleiLabels.tiff": "325478230529e94ba372f38f0bf512292f131d337b6ac09ce5a91b0266724e02", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z011_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z042_t001_NucleiLabels.tiff": "e07252ca1a55c5195c99666d8d3f0d70db636b4ef4b99e1a0049ca22b182d87a", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/results/3d_monolayer_Nuclei.csv": "17500f5d4321bbf255df31f7a3503339029c2b077045a6c10e4d4f6f0db9ad1e", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z048_t001_CellsLabels.tiff": "133a58f6fac8b07f79bfed9634867ccb5428b83e63682031a1def16c6a694568", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z046_t001_NucleiLabels.tiff": "c1250e060d32f2cfc07fc7e1594fdb1d6cbb4d0483fa94a8113efa695397963c", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z029_t001_CellsLabels.tiff": "b3bdde5f751b8f5d41ca8b5219a3427e450cb1b8795401d0ec638940d1ad7bd9", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z017_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z010_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z003_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z037_t001_NucleiLabels.tiff": "927d52441c57cb3a4014effaca3e3c23c76275fb264c26e1942a9c58b85ee6d2", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z031_t001_NucleiLabels.tiff": "247490c261fecc26c7379ab2eebaa01e4bea523218b3cc5491d2fe2b9aadfe11", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z049_t001_NucleiLabels.tiff": "e92e493078672a0e0d90e31409612e215bf8486300d5c765d0e0504ff8888e7a", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z052_t001_NucleiLabels.tiff": "0daf51526658e23b7c9ab8872e992ebe9322399286f95741d0ccdbd357e5d631", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z038_t001_NucleiLabels.tiff": "e2852ea83c62ab30d77681b4e39f88d3cee74ae052f1c948675ae3581c9fc28a", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z047_t001_NucleiLabels.tiff": "995d5ce77cbf61a9be8590f34987ef3f1dd698ae6ed393cac4d0960bc9e7a66a", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z021_t001_CellsLabels.tiff": "daa31cb1e537e5c32b1936ab7647c5690741d2bc1d0e15c60b59ba1310a8c0ce", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z022_t001_NucleiLabels.tiff": "50aef20e28a2f9e18ca2e28eabf6d87ec2ad20c79898e56f8d63a959ba5bb507", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z012_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z005_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z059_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z028_t001_CellsLabels.tiff": "fef31040e0c54501c3bf965eb98f055cdb1d42c96f91cf1c239033d0a9a06534", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z008_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z009_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z019_t001_CellsLabels.tiff": "ec6ef1d319f2732c47b06f5cf02775c8cd94540f2f30a6c002f0aace1d317955", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z054_t001_NucleiLabels.tiff": "b841c5d901c65a6138d9ff2b0ec4aa04f00765b1dd21bcd6fc9f8dc974c6035d", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z035_t001_CellsLabels.tiff": "eedeb489b46abf1eafbd9c81491cb3f85ce1cb3ce877844ad22e72547fc3c438", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z024_t001_NucleiLabels.tiff": "9e96a05ed9860cac9c57c618db2f4fe5e4b769a9d235aac6fd1d628486317df0", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z026_t001_NucleiLabels.tiff": "ad22809ff3f43d15c838f697061c263070dbf1da1031da39900681cdfbf9d54c", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z050_t001_NucleiLabels.tiff": "565b4f08f7503086c1f2f8e631d19063129e02a5767d2f979c0cec8fdec23601", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z045_t001_CellsLabels.tiff": "c678f2100c7431e5a43c391af86a79e3436d4cf13f050f98c25f62682e4632fe", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z012_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z040_t001_CellsLabels.tiff": "1635ea20dd80ce99f0e86494666825a52a66645837d598fd3a3fa91f0bb77d53", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z023_t001_NucleiLabels.tiff": "ecb7f78c8ca0bad2b9d0495659609b9023781b6a936d6afb0a04653eac176555", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z035_t001_NucleiLabels.tiff": "13e69afc324152bb91329fa758d131d849127e8fd346078d94c6adc25582b3a6", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z011_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z002_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z018_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z007_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z034_t001_CellsLabels.tiff": "3f6c1d8cdbce20aac8f70e7315bea70b147b7b6a034432845b27eeb6cfba083c", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z039_t001_CellsLabels.tiff": "22fa79a76e64013f10373be2ca2af98a2173275c5d43c9cad33135acdc376d14", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z059_t001_NucleiLabels.tiff": "76c785cf0f481c73ad3cf34ccb576eaa19dd1bdd9c74f9eaf92adfbde5d44b97", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z029_t001_NucleiLabels.tiff": "34bce0f06f674e20667554eed0075fde8d9d33c9c0eaeffd88a1c558499cc432", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z044_t001_NucleiLabels.tiff": "a78264f2f5e245a3913a69f89105e94df30048b1aaef4eb80fc5c3235e78b196", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z046_t001_CellsLabels.tiff": "dc081df050be6cd19b5d5bbfe21c96c350eecf9bc6f10f608dc361a36056632a", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z034_t001_NucleiLabels.tiff": "08af61857cfb97fd95fcb08d1ce18139ce7087b192044c63452bee533c5b1aa4", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/results/3d_monolayer_Image.csv": "75ac32ff5ef57bc285ec4eae1c9b501c27a35b486bf35435af5d499d856d34a4", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z015_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/openhcs_metadata.json": "df996ea7347162652903028922a9ac2206dd2d6dbecbf9fb6da05a7e65ece370", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z057_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z045_t001_NucleiLabels.tiff": "94bd6a65795ad6395cc18a4fd63dc591354bef612ee49fffd2d9f63e4ed9db84", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z055_t001_NucleiLabels.tiff": "44e02416cc94a70528165a4b6c42b9e19b205f9c91528076796272cb1a8504ea", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/results/3d_monolayer_erodedResizedNuclei.csv": "cca23f86a85bb3ee7a5c3a1d174c34b5f026ca7f399be98458e1a8c6e12d5c77", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z005_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z028_t001_NucleiLabels.tiff": "1676f21bd3b7e105601c83f206890507c32ba2447988be2a75d0e8153d069b65", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z051_t001_CellsLabels.tiff": "73483bd10a0f37990084013ad054768086d6d3c929da6bc7e74f4aee37e9dbf2", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z043_t001_NucleiLabels.tiff": "81a705d05b0a5bfa8783df28990c1d70634c1f4aa2bca23e02cfa8a4bc861b86", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z027_t001_NucleiLabels.tiff": "8c8f402d3a7c65c04e7f1575dd34de0427eeeb433ff2956d20e07d06eb48fb8d", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z042_t001_CellsLabels.tiff": "88d2e9964455459499656c4f0a762cd86376c678756635aaa6b6c8d98be01852", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z003_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z025_t001_NucleiLabels.tiff": "9cc33676a0177130609ab1331feab1722bbde8d55b2f49031730fd5a2a40029c", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/openhcs_metadata.json.lock": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z033_t001_CellsLabels.tiff": "a320b99ee129d97b99f9fac66aabb89fc1652930b3bb8b2b3fbba7b57e994f85", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z057_t001_NucleiLabels.tiff": "695517641e9fe4b8421d4a7db56b24c755b6957c98ce32bb24ad5b25f52661eb", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z006_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z038_t001_CellsLabels.tiff": "6ac8fd9c95acc1f261e96a8fb9332e5d6a403548842f9b85ecb977e6213b4c9b", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z044_t001_CellsLabels.tiff": "e03946d94c789ee787cc29a3c8f5e5d9c56b37a0044b297ba8f403abc98eb55e", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z014_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z041_t001_NucleiLabels.tiff": "744eab7cd170d5af8d2f72ced3893dd939c4e1b0f415afab799a37ded5d046c7", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z007_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z054_t001_CellsLabels.tiff": "25ff2ec586a568e42286f73713d64aab1208c38c016099299211f04368ac49c8", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z013_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z053_t001_NucleiLabels.tiff": "b8613192175a4615b58aed607474657668429cb6ac635cd012569b19667f2d3d", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z051_t001_NucleiLabels.tiff": "f0f36ccaf744d42da036948682cfd226e6dd4a3cfb94aed38729b2d25ede5dff", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z036_t001_NucleiLabels.tiff": "4fa967c78709aa400246a50528a36b24ca366e825dd0e64561643369e814906b", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z016_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z055_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z027_t001_CellsLabels.tiff": "ee9056587a19e581f5feb6078b41fa1004d923a5ddf1725aefc4b8b8c5201ad6", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z024_t001_CellsLabels.tiff": "39899adabca74b10b9950d1f97e8b0b3bbaf136d75e7a46ef4a6e86896e3119f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z013_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z039_t001_NucleiLabels.tiff": "f93e8293a37886a36844b8748083a1f8e717efab092652755263e797f12f0364", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/results/3d_monolayer_downsizedNuclei.csv": "a7b998c5a524e11747fc5452fd763fc3d9abe16f46e961f62e09e9393b6a8adf", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z010_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/results/3d_monolayer_erodedDownsizedNuclei.csv": "ee507fb9c2387f86fc768184baf2596ebe1f8e40f7fc5eb24f252345fee63ae6", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z004_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z040_t001_NucleiLabels.tiff": "e0bd66b166e9f92120dbee183973849eda0afbbe6fed9d03fc4cfd2c56a96280", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z056_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z058_t001_NucleiLabels.tiff": "a37c63c6052e40d73db918a014e6f2a18be4d0cbfbeeef65a9c26096a38a4c09", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z004_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z018_t001_NucleiLabels.tiff": "03ba7a4d6ae53e6c84aab5926ae1e2592b5f8ca24a839a256c82f08544df4270", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z001_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z049_t001_CellsLabels.tiff": "28d83dfbf5bbf7e4da9c3e4806353e9fd0a89680dcdab4b43ca2fd19b80f669c", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z043_t001_CellsLabels.tiff": "bd0df007524ea4e555e4d2fdbebe6a274caa03bc360a1cf90d601659155984b2", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z031_t001_CellsLabels.tiff": "1b14aab71bf3623458ea9373852b0baf28be9727877b32f894407927ecfb6d65", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z033_t001_NucleiLabels.tiff": "512a3a0ed8025d14b0556a72ebfc13b173d14f7046817ca09876242ab63b9d6b", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z052_t001_CellsLabels.tiff": "7bb98f0587062e01b965e486fc687872651d7d90d271a2fdf0d35d67b464b233", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z016_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z022_t001_CellsLabels.tiff": "7d7ec170ed3652efa99e43d8db546c51b696821dca7727d0ff4d2f2ead7fdbaa", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z041_t001_CellsLabels.tiff": "be7762756eb65f08cb337904165c6f43b5351f39405461f65ad28669abfe3899", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z056_t001_NucleiLabels.tiff": "ca0723c8b9764d5b77034719bb75a2940be35da2e04119af4c0e6d3552c08718", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z032_t001_NucleiLabels.tiff": "97b09fe5444ad439c3c2007d75971dce2766d94c93268eccfee9ae49b8a04aa1", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z014_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z060_t001_NucleiLabels.tiff": "7cc3c6c6a22f558e62194277090bdea2deb79475dd91fe7d0e49eac3c0187388", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z037_t001_CellsLabels.tiff": "aa1f449f1769b27cd9f1076e70f49f0242e2549f288a77984ca159cb07cf6a40", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z001_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/results/3d_monolayer_Cells.csv": "6f6e7431171ed5ea73a01784105147eca0e43a6e3e41f8720df93106353c9c79", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z047_t001_CellsLabels.tiff": "b926aa64e1fa8aa52279a69d91dc23cf14bf0ae76107f9b360c7ae77bdf53719", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z025_t001_CellsLabels.tiff": "03aabe5528198cfd6ec23a058dab540fb8be0870207c6dc94a62d9b621d1f2f9", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z026_t001_CellsLabels.tiff": "5b433d931fa6637fc793b23880199c01000ef6d9e610903bb38bb8cea5574563", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z032_t001_CellsLabels.tiff": "8a2c5774044326ae722e41aae517266197fbebb0e4dd5eab4b22414fbfea309f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z053_t001_CellsLabels.tiff": "ff17f538baaf179752412026a250bdbee016e3101037bf4e0dbb81199fc4c8ed", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z020_t001_NucleiLabels.tiff": "b0cd031b448d8bd2075e65710bd76c064161b25242f85ee150da7cd139fcc1a8", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z050_t001_CellsLabels.tiff": "ea7654a6fe1f92ad274a54935420923eec4bec5ad030187afc0ac7af02690af5", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z036_t001_CellsLabels.tiff": "28b68d1300cf7b08e21dbcd4858447862520dded5c27f2d84cf223513a119eed", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z020_t001_CellsLabels.tiff": "e8105a4f04198ac75de9831247030084d6f65bf98691d7444ead7e178072fa22", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z030_t001_NucleiLabels.tiff": "c54c8b98a5c38a47e0cf9391a1afab09b4c8c58e06294cdb650a15add4a32b58", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z060_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z023_t001_CellsLabels.tiff": "2f06989618050934c73473f9342c2fe3410fd834a0ddb976cf602fe6198db7a6", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z030_t001_CellsLabels.tiff": "b71a2e05d270ae0cd237d6c0d97ea82a63e5ad3633723e7255c35d34e585ec80", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z009_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z002_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z006_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z019_t001_NucleiLabels.tiff": "250cb56a8054c28cea894bc3d9edaddcdce01f5151a05da78da20157c3c3be9f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z021_t001_NucleiLabels.tiff": "71a10b0539f3fc4cba600b275b7e948258c6a435ba33ef522faa0869ac085518", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z008_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z058_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z017_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f" + } + }, + { + "case": "cp_tutorial_3d_monolayer", + "ordinary_repeat": 0, + "native_repeat": 1, + "measurement_differences": 0, + "image_differences": 0, + "tables": [ + 7, + 6 + ], + "physical_images": [ + 2, + 120 + ], + "logical_images": [ + 2, + 2 + ], + "known_relationship_keys": [ + 3, + 3 + ], + "ordinary_receipt_sha256": "4fd3a5d08663ac900fef96a286b12329bf8eac5eb10c0bc1d015cf1b3feb390b", + "output_hashes": { + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/native/cp_tutorial_3d_monolayer/outputs/1/3d_monolayer_xy1_ch2_NucleiLabels.tiff": "340bbd795541e4031749d1fff767fa4fcdcac10f5b97879056b25dac9fd7674b", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/native/cp_tutorial_3d_monolayer/outputs/1/3d_monolayer_Cells.csv": "cc34681db8a66c38ca77bc47db496b26703f21e4d7c7628dd74e30c33250859f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/native/cp_tutorial_3d_monolayer/outputs/1/3d_monolayer_erodedDownsizedNuclei.csv": "527a0cce497d2a618478be84d1a0bf174049f58aa2a666e37626a990fdca0116", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/native/cp_tutorial_3d_monolayer/outputs/1/3d_monolayer_Image.csv": "4cde74a38ef73b892dd9012708a3ac7d71fab206a7903f525b39e84493dcfe17", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/native/cp_tutorial_3d_monolayer/outputs/1/3d_monolayer_Experiment.csv": "65f1f124e99f13ddc73b71d01732262cd353f24f0bd4697a776b274a39eaecc5", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/native/cp_tutorial_3d_monolayer/outputs/1/3d_monolayer_Nuclei.csv": "440c33edc7e8cb5611910a835454db62390301a7af617a542349f60aece57561", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/native/cp_tutorial_3d_monolayer/outputs/1/3d_monolayer_erodedResizedNuclei.csv": "66a58f78cab0cfdbe907468e8ba383fc59fab49025b84b589855bdfa04854609", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/native/cp_tutorial_3d_monolayer/outputs/1/3d_monolayer_xy1_ch0_CellsLabels.tiff": "aaed9ed23179a162ee7f5a7e8d1d88f1fa342ca55172b7fccd4cbf67f7841d81", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/native/cp_tutorial_3d_monolayer/outputs/1/3d_monolayer_downsizedNuclei.csv": "2c66bc7b17de52147d5a875403f9a9746019ac61371c08157979044c6ed818dd", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z015_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z048_t001_NucleiLabels.tiff": "325478230529e94ba372f38f0bf512292f131d337b6ac09ce5a91b0266724e02", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z011_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z042_t001_NucleiLabels.tiff": "e07252ca1a55c5195c99666d8d3f0d70db636b4ef4b99e1a0049ca22b182d87a", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/results/3d_monolayer_Nuclei.csv": "17500f5d4321bbf255df31f7a3503339029c2b077045a6c10e4d4f6f0db9ad1e", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z048_t001_CellsLabels.tiff": "133a58f6fac8b07f79bfed9634867ccb5428b83e63682031a1def16c6a694568", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z046_t001_NucleiLabels.tiff": "c1250e060d32f2cfc07fc7e1594fdb1d6cbb4d0483fa94a8113efa695397963c", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z029_t001_CellsLabels.tiff": "b3bdde5f751b8f5d41ca8b5219a3427e450cb1b8795401d0ec638940d1ad7bd9", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z017_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z010_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z003_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z037_t001_NucleiLabels.tiff": "927d52441c57cb3a4014effaca3e3c23c76275fb264c26e1942a9c58b85ee6d2", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z031_t001_NucleiLabels.tiff": "247490c261fecc26c7379ab2eebaa01e4bea523218b3cc5491d2fe2b9aadfe11", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z049_t001_NucleiLabels.tiff": "e92e493078672a0e0d90e31409612e215bf8486300d5c765d0e0504ff8888e7a", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z052_t001_NucleiLabels.tiff": "0daf51526658e23b7c9ab8872e992ebe9322399286f95741d0ccdbd357e5d631", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z038_t001_NucleiLabels.tiff": "e2852ea83c62ab30d77681b4e39f88d3cee74ae052f1c948675ae3581c9fc28a", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z047_t001_NucleiLabels.tiff": "995d5ce77cbf61a9be8590f34987ef3f1dd698ae6ed393cac4d0960bc9e7a66a", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z021_t001_CellsLabels.tiff": "daa31cb1e537e5c32b1936ab7647c5690741d2bc1d0e15c60b59ba1310a8c0ce", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z022_t001_NucleiLabels.tiff": "50aef20e28a2f9e18ca2e28eabf6d87ec2ad20c79898e56f8d63a959ba5bb507", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z012_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z005_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z059_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z028_t001_CellsLabels.tiff": "fef31040e0c54501c3bf965eb98f055cdb1d42c96f91cf1c239033d0a9a06534", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z008_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z009_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z019_t001_CellsLabels.tiff": "ec6ef1d319f2732c47b06f5cf02775c8cd94540f2f30a6c002f0aace1d317955", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z054_t001_NucleiLabels.tiff": "b841c5d901c65a6138d9ff2b0ec4aa04f00765b1dd21bcd6fc9f8dc974c6035d", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z035_t001_CellsLabels.tiff": "eedeb489b46abf1eafbd9c81491cb3f85ce1cb3ce877844ad22e72547fc3c438", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z024_t001_NucleiLabels.tiff": "9e96a05ed9860cac9c57c618db2f4fe5e4b769a9d235aac6fd1d628486317df0", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z026_t001_NucleiLabels.tiff": "ad22809ff3f43d15c838f697061c263070dbf1da1031da39900681cdfbf9d54c", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z050_t001_NucleiLabels.tiff": "565b4f08f7503086c1f2f8e631d19063129e02a5767d2f979c0cec8fdec23601", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z045_t001_CellsLabels.tiff": "c678f2100c7431e5a43c391af86a79e3436d4cf13f050f98c25f62682e4632fe", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z012_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z040_t001_CellsLabels.tiff": "1635ea20dd80ce99f0e86494666825a52a66645837d598fd3a3fa91f0bb77d53", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z023_t001_NucleiLabels.tiff": "ecb7f78c8ca0bad2b9d0495659609b9023781b6a936d6afb0a04653eac176555", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z035_t001_NucleiLabels.tiff": "13e69afc324152bb91329fa758d131d849127e8fd346078d94c6adc25582b3a6", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z011_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z002_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z018_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z007_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z034_t001_CellsLabels.tiff": "3f6c1d8cdbce20aac8f70e7315bea70b147b7b6a034432845b27eeb6cfba083c", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z039_t001_CellsLabels.tiff": "22fa79a76e64013f10373be2ca2af98a2173275c5d43c9cad33135acdc376d14", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z059_t001_NucleiLabels.tiff": "76c785cf0f481c73ad3cf34ccb576eaa19dd1bdd9c74f9eaf92adfbde5d44b97", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z029_t001_NucleiLabels.tiff": "34bce0f06f674e20667554eed0075fde8d9d33c9c0eaeffd88a1c558499cc432", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z044_t001_NucleiLabels.tiff": "a78264f2f5e245a3913a69f89105e94df30048b1aaef4eb80fc5c3235e78b196", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z046_t001_CellsLabels.tiff": "dc081df050be6cd19b5d5bbfe21c96c350eecf9bc6f10f608dc361a36056632a", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z034_t001_NucleiLabels.tiff": "08af61857cfb97fd95fcb08d1ce18139ce7087b192044c63452bee533c5b1aa4", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/results/3d_monolayer_Image.csv": "75ac32ff5ef57bc285ec4eae1c9b501c27a35b486bf35435af5d499d856d34a4", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z015_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/openhcs_metadata.json": "df996ea7347162652903028922a9ac2206dd2d6dbecbf9fb6da05a7e65ece370", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z057_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z045_t001_NucleiLabels.tiff": "94bd6a65795ad6395cc18a4fd63dc591354bef612ee49fffd2d9f63e4ed9db84", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z055_t001_NucleiLabels.tiff": "44e02416cc94a70528165a4b6c42b9e19b205f9c91528076796272cb1a8504ea", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/results/3d_monolayer_erodedResizedNuclei.csv": "cca23f86a85bb3ee7a5c3a1d174c34b5f026ca7f399be98458e1a8c6e12d5c77", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z005_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z028_t001_NucleiLabels.tiff": "1676f21bd3b7e105601c83f206890507c32ba2447988be2a75d0e8153d069b65", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z051_t001_CellsLabels.tiff": "73483bd10a0f37990084013ad054768086d6d3c929da6bc7e74f4aee37e9dbf2", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z043_t001_NucleiLabels.tiff": "81a705d05b0a5bfa8783df28990c1d70634c1f4aa2bca23e02cfa8a4bc861b86", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z027_t001_NucleiLabels.tiff": "8c8f402d3a7c65c04e7f1575dd34de0427eeeb433ff2956d20e07d06eb48fb8d", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z042_t001_CellsLabels.tiff": "88d2e9964455459499656c4f0a762cd86376c678756635aaa6b6c8d98be01852", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z003_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z025_t001_NucleiLabels.tiff": "9cc33676a0177130609ab1331feab1722bbde8d55b2f49031730fd5a2a40029c", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/openhcs_metadata.json.lock": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z033_t001_CellsLabels.tiff": "a320b99ee129d97b99f9fac66aabb89fc1652930b3bb8b2b3fbba7b57e994f85", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z057_t001_NucleiLabels.tiff": "695517641e9fe4b8421d4a7db56b24c755b6957c98ce32bb24ad5b25f52661eb", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z006_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z038_t001_CellsLabels.tiff": "6ac8fd9c95acc1f261e96a8fb9332e5d6a403548842f9b85ecb977e6213b4c9b", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z044_t001_CellsLabels.tiff": "e03946d94c789ee787cc29a3c8f5e5d9c56b37a0044b297ba8f403abc98eb55e", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z014_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z041_t001_NucleiLabels.tiff": "744eab7cd170d5af8d2f72ced3893dd939c4e1b0f415afab799a37ded5d046c7", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z007_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z054_t001_CellsLabels.tiff": "25ff2ec586a568e42286f73713d64aab1208c38c016099299211f04368ac49c8", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z013_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z053_t001_NucleiLabels.tiff": "b8613192175a4615b58aed607474657668429cb6ac635cd012569b19667f2d3d", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z051_t001_NucleiLabels.tiff": "f0f36ccaf744d42da036948682cfd226e6dd4a3cfb94aed38729b2d25ede5dff", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z036_t001_NucleiLabels.tiff": "4fa967c78709aa400246a50528a36b24ca366e825dd0e64561643369e814906b", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z016_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z055_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z027_t001_CellsLabels.tiff": "ee9056587a19e581f5feb6078b41fa1004d923a5ddf1725aefc4b8b8c5201ad6", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z024_t001_CellsLabels.tiff": "39899adabca74b10b9950d1f97e8b0b3bbaf136d75e7a46ef4a6e86896e3119f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z013_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z039_t001_NucleiLabels.tiff": "f93e8293a37886a36844b8748083a1f8e717efab092652755263e797f12f0364", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/results/3d_monolayer_downsizedNuclei.csv": "a7b998c5a524e11747fc5452fd763fc3d9abe16f46e961f62e09e9393b6a8adf", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z010_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/results/3d_monolayer_erodedDownsizedNuclei.csv": "ee507fb9c2387f86fc768184baf2596ebe1f8e40f7fc5eb24f252345fee63ae6", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z004_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z040_t001_NucleiLabels.tiff": "e0bd66b166e9f92120dbee183973849eda0afbbe6fed9d03fc4cfd2c56a96280", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z056_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z058_t001_NucleiLabels.tiff": "a37c63c6052e40d73db918a014e6f2a18be4d0cbfbeeef65a9c26096a38a4c09", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z004_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z018_t001_NucleiLabels.tiff": "03ba7a4d6ae53e6c84aab5926ae1e2592b5f8ca24a839a256c82f08544df4270", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z001_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z049_t001_CellsLabels.tiff": "28d83dfbf5bbf7e4da9c3e4806353e9fd0a89680dcdab4b43ca2fd19b80f669c", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z043_t001_CellsLabels.tiff": "bd0df007524ea4e555e4d2fdbebe6a274caa03bc360a1cf90d601659155984b2", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z031_t001_CellsLabels.tiff": "1b14aab71bf3623458ea9373852b0baf28be9727877b32f894407927ecfb6d65", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z033_t001_NucleiLabels.tiff": "512a3a0ed8025d14b0556a72ebfc13b173d14f7046817ca09876242ab63b9d6b", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z052_t001_CellsLabels.tiff": "7bb98f0587062e01b965e486fc687872651d7d90d271a2fdf0d35d67b464b233", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z016_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z022_t001_CellsLabels.tiff": "7d7ec170ed3652efa99e43d8db546c51b696821dca7727d0ff4d2f2ead7fdbaa", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z041_t001_CellsLabels.tiff": "be7762756eb65f08cb337904165c6f43b5351f39405461f65ad28669abfe3899", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z056_t001_NucleiLabels.tiff": "ca0723c8b9764d5b77034719bb75a2940be35da2e04119af4c0e6d3552c08718", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z032_t001_NucleiLabels.tiff": "97b09fe5444ad439c3c2007d75971dce2766d94c93268eccfee9ae49b8a04aa1", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z014_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z060_t001_NucleiLabels.tiff": "7cc3c6c6a22f558e62194277090bdea2deb79475dd91fe7d0e49eac3c0187388", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z037_t001_CellsLabels.tiff": "aa1f449f1769b27cd9f1076e70f49f0242e2549f288a77984ca159cb07cf6a40", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z001_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/results/3d_monolayer_Cells.csv": "6f6e7431171ed5ea73a01784105147eca0e43a6e3e41f8720df93106353c9c79", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z047_t001_CellsLabels.tiff": "b926aa64e1fa8aa52279a69d91dc23cf14bf0ae76107f9b360c7ae77bdf53719", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z025_t001_CellsLabels.tiff": "03aabe5528198cfd6ec23a058dab540fb8be0870207c6dc94a62d9b621d1f2f9", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z026_t001_CellsLabels.tiff": "5b433d931fa6637fc793b23880199c01000ef6d9e610903bb38bb8cea5574563", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z032_t001_CellsLabels.tiff": "8a2c5774044326ae722e41aae517266197fbebb0e4dd5eab4b22414fbfea309f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z053_t001_CellsLabels.tiff": "ff17f538baaf179752412026a250bdbee016e3101037bf4e0dbb81199fc4c8ed", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z020_t001_NucleiLabels.tiff": "b0cd031b448d8bd2075e65710bd76c064161b25242f85ee150da7cd139fcc1a8", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z050_t001_CellsLabels.tiff": "ea7654a6fe1f92ad274a54935420923eec4bec5ad030187afc0ac7af02690af5", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z036_t001_CellsLabels.tiff": "28b68d1300cf7b08e21dbcd4858447862520dded5c27f2d84cf223513a119eed", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z020_t001_CellsLabels.tiff": "e8105a4f04198ac75de9831247030084d6f65bf98691d7444ead7e178072fa22", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z030_t001_NucleiLabels.tiff": "c54c8b98a5c38a47e0cf9391a1afab09b4c8c58e06294cdb650a15add4a32b58", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z060_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z023_t001_CellsLabels.tiff": "2f06989618050934c73473f9342c2fe3410fd834a0ddb976cf602fe6198db7a6", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z030_t001_CellsLabels.tiff": "b71a2e05d270ae0cd237d6c0d97ea82a63e5ad3633723e7255c35d34e585ec80", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z009_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z002_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z006_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z019_t001_NucleiLabels.tiff": "250cb56a8054c28cea894bc3d9edaddcdce01f5151a05da78da20157c3c3be9f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z021_t001_NucleiLabels.tiff": "71a10b0539f3fc4cba600b275b7e948258c6a435ba33ef522faa0869ac085518", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z008_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z058_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z017_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f" + } + }, + { + "case": "ExampleSpeckles", + "ordinary_repeat": 0, + "native_repeat": 0, + "measurement_differences": 0, + "image_differences": 0, + "tables": [ + 3, + 3 + ], + "physical_images": [ + 0, + 0 + ], + "logical_images": [ + 0, + 0 + ], + "known_relationship_keys": [ + 1, + 1 + ], + "ordinary_receipt_sha256": "cda421a4fe86662f7be512585425e834739b510b6e0b31e8396f28ed2e123c16", + "output_hashes": { + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/native/ExampleSpeckles/outputs/0/Image.csv": "55cdc9117d38d5a9a96b603052b9ca323824897be4962f285934973af03d73bb", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/native/ExampleSpeckles/outputs/0/h2ax.csv": "0f54fc72ccdeb7e1a68bab9dc3a8d9d49788cdf81dbbc109ed119e589c09538a", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/native/ExampleSpeckles/outputs/0/Nuclei.csv": "15af7cac08d651c19b3e3f409b2b0d7fc4f96011c9b53394aa9a35969a8936a6", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/ExampleSpeckles/wells_1/workers_1/images_ExampleSpeckles_source_workspace_well_throughput/results/Image.csv": "85ef16f24e75f03dc7055215cf2e6cb196b1dc0a0d73713a4c5999f698d4f96e", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/ExampleSpeckles/wells_1/workers_1/images_ExampleSpeckles_source_workspace_well_throughput/results/h2ax.csv": "eb453565f3b79ac932eeb5cde8605888b72e58c80f42edbbf0b1ba37f34fd6f8", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/ExampleSpeckles/wells_1/workers_1/images_ExampleSpeckles_source_workspace_well_throughput/openhcs_metadata.json.lock": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/ExampleSpeckles/wells_1/workers_1/images_ExampleSpeckles_source_workspace_well_throughput/openhcs_metadata.json": "71582c62cabb2571ebf8a0de57f92fdf82c55a7ece3dac0bf2a6eca95cad84c9", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/ExampleSpeckles/wells_1/workers_1/images_ExampleSpeckles_source_workspace_well_throughput/results/Nuclei.csv": "e50cb9f8c23f65e9ce8db25132263cf4a4448ed65fc1088d782536abf74c5670" + } + }, + { + "case": "ExampleSpeckles", + "ordinary_repeat": 0, + "native_repeat": 1, + "measurement_differences": 0, + "image_differences": 0, + "tables": [ + 3, + 3 + ], + "physical_images": [ + 0, + 0 + ], + "logical_images": [ + 0, + 0 + ], + "known_relationship_keys": [ + 1, + 1 + ], + "ordinary_receipt_sha256": "cda421a4fe86662f7be512585425e834739b510b6e0b31e8396f28ed2e123c16", + "output_hashes": { + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/native/ExampleSpeckles/outputs/1/Nuclei.csv": "15af7cac08d651c19b3e3f409b2b0d7fc4f96011c9b53394aa9a35969a8936a6", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/native/ExampleSpeckles/outputs/1/h2ax.csv": "0f54fc72ccdeb7e1a68bab9dc3a8d9d49788cdf81dbbc109ed119e589c09538a", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/native/ExampleSpeckles/outputs/1/Image.csv": "1d2f3cbff7ee2608efb670186878d4588a8a438ef74aded60e7052f4d2f243ac", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/ExampleSpeckles/wells_1/workers_1/images_ExampleSpeckles_source_workspace_well_throughput/results/Image.csv": "85ef16f24e75f03dc7055215cf2e6cb196b1dc0a0d73713a4c5999f698d4f96e", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/ExampleSpeckles/wells_1/workers_1/images_ExampleSpeckles_source_workspace_well_throughput/results/h2ax.csv": "eb453565f3b79ac932eeb5cde8605888b72e58c80f42edbbf0b1ba37f34fd6f8", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/ExampleSpeckles/wells_1/workers_1/images_ExampleSpeckles_source_workspace_well_throughput/openhcs_metadata.json.lock": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/ExampleSpeckles/wells_1/workers_1/images_ExampleSpeckles_source_workspace_well_throughput/openhcs_metadata.json": "71582c62cabb2571ebf8a0de57f92fdf82c55a7ece3dac0bf2a6eca95cad84c9", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-0/ExampleSpeckles/wells_1/workers_1/images_ExampleSpeckles_source_workspace_well_throughput/results/Nuclei.csv": "e50cb9f8c23f65e9ce8db25132263cf4a4448ed65fc1088d782536abf74c5670" + } + }, + { + "case": "cp_tutorial_3d_monolayer", + "ordinary_repeat": 1, + "native_repeat": 0, + "measurement_differences": 0, + "image_differences": 0, + "tables": [ + 7, + 6 + ], + "physical_images": [ + 2, + 120 + ], + "logical_images": [ + 2, + 2 + ], + "known_relationship_keys": [ + 3, + 3 + ], + "ordinary_receipt_sha256": "f2f35969c4e153c03e7b921da2503929020c1ecce2d64bbaa49c04033fe1494a", + "output_hashes": { + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/native/cp_tutorial_3d_monolayer/outputs/0/3d_monolayer_xy1_ch2_NucleiLabels.tiff": "340bbd795541e4031749d1fff767fa4fcdcac10f5b97879056b25dac9fd7674b", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/native/cp_tutorial_3d_monolayer/outputs/0/3d_monolayer_erodedResizedNuclei.csv": "66a58f78cab0cfdbe907468e8ba383fc59fab49025b84b589855bdfa04854609", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/native/cp_tutorial_3d_monolayer/outputs/0/3d_monolayer_Experiment.csv": "c05f0a11f43a5bda943e9f739ff257216f8ab3f65d8988a0d3d0c612c1db6997", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/native/cp_tutorial_3d_monolayer/outputs/0/3d_monolayer_downsizedNuclei.csv": "2c66bc7b17de52147d5a875403f9a9746019ac61371c08157979044c6ed818dd", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/native/cp_tutorial_3d_monolayer/outputs/0/3d_monolayer_Cells.csv": "cc34681db8a66c38ca77bc47db496b26703f21e4d7c7628dd74e30c33250859f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/native/cp_tutorial_3d_monolayer/outputs/0/3d_monolayer_Nuclei.csv": "440c33edc7e8cb5611910a835454db62390301a7af617a542349f60aece57561", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/native/cp_tutorial_3d_monolayer/outputs/0/3d_monolayer_erodedDownsizedNuclei.csv": "527a0cce497d2a618478be84d1a0bf174049f58aa2a666e37626a990fdca0116", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/native/cp_tutorial_3d_monolayer/outputs/0/3d_monolayer_Image.csv": "1f3dec653b6909c8a81ac109ce1faf91380886ac9a18e56fafc91102d419904e", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/native/cp_tutorial_3d_monolayer/outputs/0/3d_monolayer_xy1_ch0_CellsLabels.tiff": "aaed9ed23179a162ee7f5a7e8d1d88f1fa342ca55172b7fccd4cbf67f7841d81", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z010_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z044_t001_NucleiLabels.tiff": "a78264f2f5e245a3913a69f89105e94df30048b1aaef4eb80fc5c3235e78b196", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z012_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z020_t001_CellsLabels.tiff": "e8105a4f04198ac75de9831247030084d6f65bf98691d7444ead7e178072fa22", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z006_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z016_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z024_t001_NucleiLabels.tiff": "9e96a05ed9860cac9c57c618db2f4fe5e4b769a9d235aac6fd1d628486317df0", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z032_t001_CellsLabels.tiff": "8a2c5774044326ae722e41aae517266197fbebb0e4dd5eab4b22414fbfea309f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z014_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z021_t001_NucleiLabels.tiff": "71a10b0539f3fc4cba600b275b7e948258c6a435ba33ef522faa0869ac085518", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z034_t001_CellsLabels.tiff": "3f6c1d8cdbce20aac8f70e7315bea70b147b7b6a034432845b27eeb6cfba083c", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z018_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z007_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z052_t001_CellsLabels.tiff": "7bb98f0587062e01b965e486fc687872651d7d90d271a2fdf0d35d67b464b233", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z042_t001_CellsLabels.tiff": "88d2e9964455459499656c4f0a762cd86376c678756635aaa6b6c8d98be01852", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/openhcs_metadata.json": "2b1c063d1583e1eacc2c087e956acb68f69b4554cd8d04c0d3e4dd4d641053e4", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z043_t001_NucleiLabels.tiff": "81a705d05b0a5bfa8783df28990c1d70634c1f4aa2bca23e02cfa8a4bc861b86", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z040_t001_NucleiLabels.tiff": "e0bd66b166e9f92120dbee183973849eda0afbbe6fed9d03fc4cfd2c56a96280", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/results/3d_monolayer_erodedResizedNuclei.csv": "cca23f86a85bb3ee7a5c3a1d174c34b5f026ca7f399be98458e1a8c6e12d5c77", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z016_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z048_t001_NucleiLabels.tiff": "325478230529e94ba372f38f0bf512292f131d337b6ac09ce5a91b0266724e02", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z054_t001_NucleiLabels.tiff": "b841c5d901c65a6138d9ff2b0ec4aa04f00765b1dd21bcd6fc9f8dc974c6035d", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z050_t001_NucleiLabels.tiff": "565b4f08f7503086c1f2f8e631d19063129e02a5767d2f979c0cec8fdec23601", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z058_t001_NucleiLabels.tiff": "a37c63c6052e40d73db918a014e6f2a18be4d0cbfbeeef65a9c26096a38a4c09", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z054_t001_CellsLabels.tiff": "25ff2ec586a568e42286f73713d64aab1208c38c016099299211f04368ac49c8", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z002_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z031_t001_CellsLabels.tiff": "1b14aab71bf3623458ea9373852b0baf28be9727877b32f894407927ecfb6d65", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z005_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z055_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z028_t001_CellsLabels.tiff": "fef31040e0c54501c3bf965eb98f055cdb1d42c96f91cf1c239033d0a9a06534", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z006_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/openhcs_metadata.json.lock": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z050_t001_CellsLabels.tiff": "ea7654a6fe1f92ad274a54935420923eec4bec5ad030187afc0ac7af02690af5", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/results/3d_monolayer_Image.csv": "75ac32ff5ef57bc285ec4eae1c9b501c27a35b486bf35435af5d499d856d34a4", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z019_t001_CellsLabels.tiff": "ec6ef1d319f2732c47b06f5cf02775c8cd94540f2f30a6c002f0aace1d317955", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z023_t001_CellsLabels.tiff": "2f06989618050934c73473f9342c2fe3410fd834a0ddb976cf602fe6198db7a6", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z017_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z014_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z039_t001_CellsLabels.tiff": "22fa79a76e64013f10373be2ca2af98a2173275c5d43c9cad33135acdc376d14", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z043_t001_CellsLabels.tiff": "bd0df007524ea4e555e4d2fdbebe6a274caa03bc360a1cf90d601659155984b2", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z038_t001_CellsLabels.tiff": "6ac8fd9c95acc1f261e96a8fb9332e5d6a403548842f9b85ecb977e6213b4c9b", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z002_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z009_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z011_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z036_t001_NucleiLabels.tiff": "4fa967c78709aa400246a50528a36b24ca366e825dd0e64561643369e814906b", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z060_t001_NucleiLabels.tiff": "7cc3c6c6a22f558e62194277090bdea2deb79475dd91fe7d0e49eac3c0187388", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z029_t001_CellsLabels.tiff": "b3bdde5f751b8f5d41ca8b5219a3427e450cb1b8795401d0ec638940d1ad7bd9", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z013_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z004_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z033_t001_NucleiLabels.tiff": "512a3a0ed8025d14b0556a72ebfc13b173d14f7046817ca09876242ab63b9d6b", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z046_t001_CellsLabels.tiff": "dc081df050be6cd19b5d5bbfe21c96c350eecf9bc6f10f608dc361a36056632a", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z051_t001_NucleiLabels.tiff": "f0f36ccaf744d42da036948682cfd226e6dd4a3cfb94aed38729b2d25ede5dff", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/results/3d_monolayer_Cells.csv": "6f6e7431171ed5ea73a01784105147eca0e43a6e3e41f8720df93106353c9c79", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z049_t001_NucleiLabels.tiff": "e92e493078672a0e0d90e31409612e215bf8486300d5c765d0e0504ff8888e7a", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z007_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z052_t001_NucleiLabels.tiff": "0daf51526658e23b7c9ab8872e992ebe9322399286f95741d0ccdbd357e5d631", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z009_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z049_t001_CellsLabels.tiff": "28d83dfbf5bbf7e4da9c3e4806353e9fd0a89680dcdab4b43ca2fd19b80f669c", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z022_t001_CellsLabels.tiff": "7d7ec170ed3652efa99e43d8db546c51b696821dca7727d0ff4d2f2ead7fdbaa", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z057_t001_NucleiLabels.tiff": "695517641e9fe4b8421d4a7db56b24c755b6957c98ce32bb24ad5b25f52661eb", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z027_t001_CellsLabels.tiff": "ee9056587a19e581f5feb6078b41fa1004d923a5ddf1725aefc4b8b8c5201ad6", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z013_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z041_t001_CellsLabels.tiff": "be7762756eb65f08cb337904165c6f43b5351f39405461f65ad28669abfe3899", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z015_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/results/3d_monolayer_downsizedNuclei.csv": "a7b998c5a524e11747fc5452fd763fc3d9abe16f46e961f62e09e9393b6a8adf", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z041_t001_NucleiLabels.tiff": "744eab7cd170d5af8d2f72ced3893dd939c4e1b0f415afab799a37ded5d046c7", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z036_t001_CellsLabels.tiff": "28b68d1300cf7b08e21dbcd4858447862520dded5c27f2d84cf223513a119eed", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z042_t001_NucleiLabels.tiff": "e07252ca1a55c5195c99666d8d3f0d70db636b4ef4b99e1a0049ca22b182d87a", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z037_t001_NucleiLabels.tiff": "927d52441c57cb3a4014effaca3e3c23c76275fb264c26e1942a9c58b85ee6d2", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z029_t001_NucleiLabels.tiff": "34bce0f06f674e20667554eed0075fde8d9d33c9c0eaeffd88a1c558499cc432", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z047_t001_NucleiLabels.tiff": "995d5ce77cbf61a9be8590f34987ef3f1dd698ae6ed393cac4d0960bc9e7a66a", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z020_t001_NucleiLabels.tiff": "b0cd031b448d8bd2075e65710bd76c064161b25242f85ee150da7cd139fcc1a8", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z055_t001_NucleiLabels.tiff": "44e02416cc94a70528165a4b6c42b9e19b205f9c91528076796272cb1a8504ea", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z001_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z051_t001_CellsLabels.tiff": "73483bd10a0f37990084013ad054768086d6d3c929da6bc7e74f4aee37e9dbf2", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z056_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z011_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z008_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z003_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z030_t001_CellsLabels.tiff": "b71a2e05d270ae0cd237d6c0d97ea82a63e5ad3633723e7255c35d34e585ec80", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z004_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z048_t001_CellsLabels.tiff": "133a58f6fac8b07f79bfed9634867ccb5428b83e63682031a1def16c6a694568", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z031_t001_NucleiLabels.tiff": "247490c261fecc26c7379ab2eebaa01e4bea523218b3cc5491d2fe2b9aadfe11", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z003_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z008_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z059_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z018_t001_NucleiLabels.tiff": "03ba7a4d6ae53e6c84aab5926ae1e2592b5f8ca24a839a256c82f08544df4270", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z047_t001_CellsLabels.tiff": "b926aa64e1fa8aa52279a69d91dc23cf14bf0ae76107f9b360c7ae77bdf53719", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z026_t001_CellsLabels.tiff": "5b433d931fa6637fc793b23880199c01000ef6d9e610903bb38bb8cea5574563", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z035_t001_NucleiLabels.tiff": "13e69afc324152bb91329fa758d131d849127e8fd346078d94c6adc25582b3a6", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z026_t001_NucleiLabels.tiff": "ad22809ff3f43d15c838f697061c263070dbf1da1031da39900681cdfbf9d54c", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z039_t001_NucleiLabels.tiff": "f93e8293a37886a36844b8748083a1f8e717efab092652755263e797f12f0364", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z012_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z056_t001_NucleiLabels.tiff": "ca0723c8b9764d5b77034719bb75a2940be35da2e04119af4c0e6d3552c08718", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z024_t001_CellsLabels.tiff": "39899adabca74b10b9950d1f97e8b0b3bbaf136d75e7a46ef4a6e86896e3119f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z059_t001_NucleiLabels.tiff": "76c785cf0f481c73ad3cf34ccb576eaa19dd1bdd9c74f9eaf92adfbde5d44b97", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z028_t001_NucleiLabels.tiff": "1676f21bd3b7e105601c83f206890507c32ba2447988be2a75d0e8153d069b65", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z045_t001_NucleiLabels.tiff": "94bd6a65795ad6395cc18a4fd63dc591354bef612ee49fffd2d9f63e4ed9db84", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z019_t001_NucleiLabels.tiff": "250cb56a8054c28cea894bc3d9edaddcdce01f5151a05da78da20157c3c3be9f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z057_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z060_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z017_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z025_t001_NucleiLabels.tiff": "9cc33676a0177130609ab1331feab1722bbde8d55b2f49031730fd5a2a40029c", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z021_t001_CellsLabels.tiff": "daa31cb1e537e5c32b1936ab7647c5690741d2bc1d0e15c60b59ba1310a8c0ce", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z040_t001_CellsLabels.tiff": "1635ea20dd80ce99f0e86494666825a52a66645837d598fd3a3fa91f0bb77d53", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z053_t001_CellsLabels.tiff": "ff17f538baaf179752412026a250bdbee016e3101037bf4e0dbb81199fc4c8ed", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z034_t001_NucleiLabels.tiff": "08af61857cfb97fd95fcb08d1ce18139ce7087b192044c63452bee533c5b1aa4", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/results/3d_monolayer_Nuclei.csv": "17500f5d4321bbf255df31f7a3503339029c2b077045a6c10e4d4f6f0db9ad1e", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z027_t001_NucleiLabels.tiff": "8c8f402d3a7c65c04e7f1575dd34de0427eeeb433ff2956d20e07d06eb48fb8d", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z005_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z038_t001_NucleiLabels.tiff": "e2852ea83c62ab30d77681b4e39f88d3cee74ae052f1c948675ae3581c9fc28a", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z025_t001_CellsLabels.tiff": "03aabe5528198cfd6ec23a058dab540fb8be0870207c6dc94a62d9b621d1f2f9", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z023_t001_NucleiLabels.tiff": "ecb7f78c8ca0bad2b9d0495659609b9023781b6a936d6afb0a04653eac176555", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z058_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z035_t001_CellsLabels.tiff": "eedeb489b46abf1eafbd9c81491cb3f85ce1cb3ce877844ad22e72547fc3c438", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z033_t001_CellsLabels.tiff": "a320b99ee129d97b99f9fac66aabb89fc1652930b3bb8b2b3fbba7b57e994f85", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z030_t001_NucleiLabels.tiff": "c54c8b98a5c38a47e0cf9391a1afab09b4c8c58e06294cdb650a15add4a32b58", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z010_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z032_t001_NucleiLabels.tiff": "97b09fe5444ad439c3c2007d75971dce2766d94c93268eccfee9ae49b8a04aa1", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/results/3d_monolayer_erodedDownsizedNuclei.csv": "ee507fb9c2387f86fc768184baf2596ebe1f8e40f7fc5eb24f252345fee63ae6", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z044_t001_CellsLabels.tiff": "e03946d94c789ee787cc29a3c8f5e5d9c56b37a0044b297ba8f403abc98eb55e", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z037_t001_CellsLabels.tiff": "aa1f449f1769b27cd9f1076e70f49f0242e2549f288a77984ca159cb07cf6a40", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z001_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z046_t001_NucleiLabels.tiff": "c1250e060d32f2cfc07fc7e1594fdb1d6cbb4d0483fa94a8113efa695397963c", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z015_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z045_t001_CellsLabels.tiff": "c678f2100c7431e5a43c391af86a79e3436d4cf13f050f98c25f62682e4632fe", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z022_t001_NucleiLabels.tiff": "50aef20e28a2f9e18ca2e28eabf6d87ec2ad20c79898e56f8d63a959ba5bb507", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z053_t001_NucleiLabels.tiff": "b8613192175a4615b58aed607474657668429cb6ac635cd012569b19667f2d3d" + } + }, + { + "case": "cp_tutorial_3d_monolayer", + "ordinary_repeat": 1, + "native_repeat": 1, + "measurement_differences": 0, + "image_differences": 0, + "tables": [ + 7, + 6 + ], + "physical_images": [ + 2, + 120 + ], + "logical_images": [ + 2, + 2 + ], + "known_relationship_keys": [ + 3, + 3 + ], + "ordinary_receipt_sha256": "f2f35969c4e153c03e7b921da2503929020c1ecce2d64bbaa49c04033fe1494a", + "output_hashes": { + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/native/cp_tutorial_3d_monolayer/outputs/1/3d_monolayer_xy1_ch2_NucleiLabels.tiff": "340bbd795541e4031749d1fff767fa4fcdcac10f5b97879056b25dac9fd7674b", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/native/cp_tutorial_3d_monolayer/outputs/1/3d_monolayer_Cells.csv": "cc34681db8a66c38ca77bc47db496b26703f21e4d7c7628dd74e30c33250859f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/native/cp_tutorial_3d_monolayer/outputs/1/3d_monolayer_erodedDownsizedNuclei.csv": "527a0cce497d2a618478be84d1a0bf174049f58aa2a666e37626a990fdca0116", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/native/cp_tutorial_3d_monolayer/outputs/1/3d_monolayer_Image.csv": "4cde74a38ef73b892dd9012708a3ac7d71fab206a7903f525b39e84493dcfe17", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/native/cp_tutorial_3d_monolayer/outputs/1/3d_monolayer_Experiment.csv": "65f1f124e99f13ddc73b71d01732262cd353f24f0bd4697a776b274a39eaecc5", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/native/cp_tutorial_3d_monolayer/outputs/1/3d_monolayer_Nuclei.csv": "440c33edc7e8cb5611910a835454db62390301a7af617a542349f60aece57561", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/native/cp_tutorial_3d_monolayer/outputs/1/3d_monolayer_erodedResizedNuclei.csv": "66a58f78cab0cfdbe907468e8ba383fc59fab49025b84b589855bdfa04854609", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/native/cp_tutorial_3d_monolayer/outputs/1/3d_monolayer_xy1_ch0_CellsLabels.tiff": "aaed9ed23179a162ee7f5a7e8d1d88f1fa342ca55172b7fccd4cbf67f7841d81", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/native/cp_tutorial_3d_monolayer/outputs/1/3d_monolayer_downsizedNuclei.csv": "2c66bc7b17de52147d5a875403f9a9746019ac61371c08157979044c6ed818dd", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z010_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z044_t001_NucleiLabels.tiff": "a78264f2f5e245a3913a69f89105e94df30048b1aaef4eb80fc5c3235e78b196", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z012_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z020_t001_CellsLabels.tiff": "e8105a4f04198ac75de9831247030084d6f65bf98691d7444ead7e178072fa22", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z006_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z016_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z024_t001_NucleiLabels.tiff": "9e96a05ed9860cac9c57c618db2f4fe5e4b769a9d235aac6fd1d628486317df0", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z032_t001_CellsLabels.tiff": "8a2c5774044326ae722e41aae517266197fbebb0e4dd5eab4b22414fbfea309f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z014_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z021_t001_NucleiLabels.tiff": "71a10b0539f3fc4cba600b275b7e948258c6a435ba33ef522faa0869ac085518", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z034_t001_CellsLabels.tiff": "3f6c1d8cdbce20aac8f70e7315bea70b147b7b6a034432845b27eeb6cfba083c", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z018_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z007_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z052_t001_CellsLabels.tiff": "7bb98f0587062e01b965e486fc687872651d7d90d271a2fdf0d35d67b464b233", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z042_t001_CellsLabels.tiff": "88d2e9964455459499656c4f0a762cd86376c678756635aaa6b6c8d98be01852", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/openhcs_metadata.json": "2b1c063d1583e1eacc2c087e956acb68f69b4554cd8d04c0d3e4dd4d641053e4", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z043_t001_NucleiLabels.tiff": "81a705d05b0a5bfa8783df28990c1d70634c1f4aa2bca23e02cfa8a4bc861b86", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z040_t001_NucleiLabels.tiff": "e0bd66b166e9f92120dbee183973849eda0afbbe6fed9d03fc4cfd2c56a96280", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/results/3d_monolayer_erodedResizedNuclei.csv": "cca23f86a85bb3ee7a5c3a1d174c34b5f026ca7f399be98458e1a8c6e12d5c77", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z016_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z048_t001_NucleiLabels.tiff": "325478230529e94ba372f38f0bf512292f131d337b6ac09ce5a91b0266724e02", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z054_t001_NucleiLabels.tiff": "b841c5d901c65a6138d9ff2b0ec4aa04f00765b1dd21bcd6fc9f8dc974c6035d", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z050_t001_NucleiLabels.tiff": "565b4f08f7503086c1f2f8e631d19063129e02a5767d2f979c0cec8fdec23601", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z058_t001_NucleiLabels.tiff": "a37c63c6052e40d73db918a014e6f2a18be4d0cbfbeeef65a9c26096a38a4c09", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z054_t001_CellsLabels.tiff": "25ff2ec586a568e42286f73713d64aab1208c38c016099299211f04368ac49c8", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z002_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z031_t001_CellsLabels.tiff": "1b14aab71bf3623458ea9373852b0baf28be9727877b32f894407927ecfb6d65", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z005_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z055_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z028_t001_CellsLabels.tiff": "fef31040e0c54501c3bf965eb98f055cdb1d42c96f91cf1c239033d0a9a06534", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z006_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/openhcs_metadata.json.lock": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z050_t001_CellsLabels.tiff": "ea7654a6fe1f92ad274a54935420923eec4bec5ad030187afc0ac7af02690af5", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/results/3d_monolayer_Image.csv": "75ac32ff5ef57bc285ec4eae1c9b501c27a35b486bf35435af5d499d856d34a4", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z019_t001_CellsLabels.tiff": "ec6ef1d319f2732c47b06f5cf02775c8cd94540f2f30a6c002f0aace1d317955", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z023_t001_CellsLabels.tiff": "2f06989618050934c73473f9342c2fe3410fd834a0ddb976cf602fe6198db7a6", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z017_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z014_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z039_t001_CellsLabels.tiff": "22fa79a76e64013f10373be2ca2af98a2173275c5d43c9cad33135acdc376d14", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z043_t001_CellsLabels.tiff": "bd0df007524ea4e555e4d2fdbebe6a274caa03bc360a1cf90d601659155984b2", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z038_t001_CellsLabels.tiff": "6ac8fd9c95acc1f261e96a8fb9332e5d6a403548842f9b85ecb977e6213b4c9b", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z002_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z009_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z011_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z036_t001_NucleiLabels.tiff": "4fa967c78709aa400246a50528a36b24ca366e825dd0e64561643369e814906b", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z060_t001_NucleiLabels.tiff": "7cc3c6c6a22f558e62194277090bdea2deb79475dd91fe7d0e49eac3c0187388", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z029_t001_CellsLabels.tiff": "b3bdde5f751b8f5d41ca8b5219a3427e450cb1b8795401d0ec638940d1ad7bd9", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z013_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z004_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z033_t001_NucleiLabels.tiff": "512a3a0ed8025d14b0556a72ebfc13b173d14f7046817ca09876242ab63b9d6b", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z046_t001_CellsLabels.tiff": "dc081df050be6cd19b5d5bbfe21c96c350eecf9bc6f10f608dc361a36056632a", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z051_t001_NucleiLabels.tiff": "f0f36ccaf744d42da036948682cfd226e6dd4a3cfb94aed38729b2d25ede5dff", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/results/3d_monolayer_Cells.csv": "6f6e7431171ed5ea73a01784105147eca0e43a6e3e41f8720df93106353c9c79", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z049_t001_NucleiLabels.tiff": "e92e493078672a0e0d90e31409612e215bf8486300d5c765d0e0504ff8888e7a", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z007_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z052_t001_NucleiLabels.tiff": "0daf51526658e23b7c9ab8872e992ebe9322399286f95741d0ccdbd357e5d631", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z009_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z049_t001_CellsLabels.tiff": "28d83dfbf5bbf7e4da9c3e4806353e9fd0a89680dcdab4b43ca2fd19b80f669c", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z022_t001_CellsLabels.tiff": "7d7ec170ed3652efa99e43d8db546c51b696821dca7727d0ff4d2f2ead7fdbaa", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z057_t001_NucleiLabels.tiff": "695517641e9fe4b8421d4a7db56b24c755b6957c98ce32bb24ad5b25f52661eb", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z027_t001_CellsLabels.tiff": "ee9056587a19e581f5feb6078b41fa1004d923a5ddf1725aefc4b8b8c5201ad6", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z013_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z041_t001_CellsLabels.tiff": "be7762756eb65f08cb337904165c6f43b5351f39405461f65ad28669abfe3899", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z015_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/results/3d_monolayer_downsizedNuclei.csv": "a7b998c5a524e11747fc5452fd763fc3d9abe16f46e961f62e09e9393b6a8adf", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z041_t001_NucleiLabels.tiff": "744eab7cd170d5af8d2f72ced3893dd939c4e1b0f415afab799a37ded5d046c7", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z036_t001_CellsLabels.tiff": "28b68d1300cf7b08e21dbcd4858447862520dded5c27f2d84cf223513a119eed", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z042_t001_NucleiLabels.tiff": "e07252ca1a55c5195c99666d8d3f0d70db636b4ef4b99e1a0049ca22b182d87a", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z037_t001_NucleiLabels.tiff": "927d52441c57cb3a4014effaca3e3c23c76275fb264c26e1942a9c58b85ee6d2", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z029_t001_NucleiLabels.tiff": "34bce0f06f674e20667554eed0075fde8d9d33c9c0eaeffd88a1c558499cc432", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z047_t001_NucleiLabels.tiff": "995d5ce77cbf61a9be8590f34987ef3f1dd698ae6ed393cac4d0960bc9e7a66a", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z020_t001_NucleiLabels.tiff": "b0cd031b448d8bd2075e65710bd76c064161b25242f85ee150da7cd139fcc1a8", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z055_t001_NucleiLabels.tiff": "44e02416cc94a70528165a4b6c42b9e19b205f9c91528076796272cb1a8504ea", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z001_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z051_t001_CellsLabels.tiff": "73483bd10a0f37990084013ad054768086d6d3c929da6bc7e74f4aee37e9dbf2", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z056_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z011_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z008_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z003_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z030_t001_CellsLabels.tiff": "b71a2e05d270ae0cd237d6c0d97ea82a63e5ad3633723e7255c35d34e585ec80", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z004_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z048_t001_CellsLabels.tiff": "133a58f6fac8b07f79bfed9634867ccb5428b83e63682031a1def16c6a694568", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z031_t001_NucleiLabels.tiff": "247490c261fecc26c7379ab2eebaa01e4bea523218b3cc5491d2fe2b9aadfe11", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z003_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z008_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z059_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z018_t001_NucleiLabels.tiff": "03ba7a4d6ae53e6c84aab5926ae1e2592b5f8ca24a839a256c82f08544df4270", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z047_t001_CellsLabels.tiff": "b926aa64e1fa8aa52279a69d91dc23cf14bf0ae76107f9b360c7ae77bdf53719", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z026_t001_CellsLabels.tiff": "5b433d931fa6637fc793b23880199c01000ef6d9e610903bb38bb8cea5574563", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z035_t001_NucleiLabels.tiff": "13e69afc324152bb91329fa758d131d849127e8fd346078d94c6adc25582b3a6", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z026_t001_NucleiLabels.tiff": "ad22809ff3f43d15c838f697061c263070dbf1da1031da39900681cdfbf9d54c", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z039_t001_NucleiLabels.tiff": "f93e8293a37886a36844b8748083a1f8e717efab092652755263e797f12f0364", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z012_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z056_t001_NucleiLabels.tiff": "ca0723c8b9764d5b77034719bb75a2940be35da2e04119af4c0e6d3552c08718", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z024_t001_CellsLabels.tiff": "39899adabca74b10b9950d1f97e8b0b3bbaf136d75e7a46ef4a6e86896e3119f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z059_t001_NucleiLabels.tiff": "76c785cf0f481c73ad3cf34ccb576eaa19dd1bdd9c74f9eaf92adfbde5d44b97", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z028_t001_NucleiLabels.tiff": "1676f21bd3b7e105601c83f206890507c32ba2447988be2a75d0e8153d069b65", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z045_t001_NucleiLabels.tiff": "94bd6a65795ad6395cc18a4fd63dc591354bef612ee49fffd2d9f63e4ed9db84", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z019_t001_NucleiLabels.tiff": "250cb56a8054c28cea894bc3d9edaddcdce01f5151a05da78da20157c3c3be9f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z057_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z060_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z017_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z025_t001_NucleiLabels.tiff": "9cc33676a0177130609ab1331feab1722bbde8d55b2f49031730fd5a2a40029c", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z021_t001_CellsLabels.tiff": "daa31cb1e537e5c32b1936ab7647c5690741d2bc1d0e15c60b59ba1310a8c0ce", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z040_t001_CellsLabels.tiff": "1635ea20dd80ce99f0e86494666825a52a66645837d598fd3a3fa91f0bb77d53", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z053_t001_CellsLabels.tiff": "ff17f538baaf179752412026a250bdbee016e3101037bf4e0dbb81199fc4c8ed", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z034_t001_NucleiLabels.tiff": "08af61857cfb97fd95fcb08d1ce18139ce7087b192044c63452bee533c5b1aa4", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/results/3d_monolayer_Nuclei.csv": "17500f5d4321bbf255df31f7a3503339029c2b077045a6c10e4d4f6f0db9ad1e", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z027_t001_NucleiLabels.tiff": "8c8f402d3a7c65c04e7f1575dd34de0427eeeb433ff2956d20e07d06eb48fb8d", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z005_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z038_t001_NucleiLabels.tiff": "e2852ea83c62ab30d77681b4e39f88d3cee74ae052f1c948675ae3581c9fc28a", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z025_t001_CellsLabels.tiff": "03aabe5528198cfd6ec23a058dab540fb8be0870207c6dc94a62d9b621d1f2f9", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z023_t001_NucleiLabels.tiff": "ecb7f78c8ca0bad2b9d0495659609b9023781b6a936d6afb0a04653eac176555", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z058_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z035_t001_CellsLabels.tiff": "eedeb489b46abf1eafbd9c81491cb3f85ce1cb3ce877844ad22e72547fc3c438", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z033_t001_CellsLabels.tiff": "a320b99ee129d97b99f9fac66aabb89fc1652930b3bb8b2b3fbba7b57e994f85", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z030_t001_NucleiLabels.tiff": "c54c8b98a5c38a47e0cf9391a1afab09b4c8c58e06294cdb650a15add4a32b58", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z010_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z032_t001_NucleiLabels.tiff": "97b09fe5444ad439c3c2007d75971dce2766d94c93268eccfee9ae49b8a04aa1", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/results/3d_monolayer_erodedDownsizedNuclei.csv": "ee507fb9c2387f86fc768184baf2596ebe1f8e40f7fc5eb24f252345fee63ae6", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z044_t001_CellsLabels.tiff": "e03946d94c789ee787cc29a3c8f5e5d9c56b37a0044b297ba8f403abc98eb55e", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z037_t001_CellsLabels.tiff": "aa1f449f1769b27cd9f1076e70f49f0242e2549f288a77984ca159cb07cf6a40", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z001_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z046_t001_NucleiLabels.tiff": "c1250e060d32f2cfc07fc7e1594fdb1d6cbb4d0483fa94a8113efa695397963c", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z015_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z045_t001_CellsLabels.tiff": "c678f2100c7431e5a43c391af86a79e3436d4cf13f050f98c25f62682e4632fe", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z022_t001_NucleiLabels.tiff": "50aef20e28a2f9e18ca2e28eabf6d87ec2ad20c79898e56f8d63a959ba5bb507", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z053_t001_NucleiLabels.tiff": "b8613192175a4615b58aed607474657668429cb6ac635cd012569b19667f2d3d" + } + }, + { + "case": "ExampleSpeckles", + "ordinary_repeat": 1, + "native_repeat": 0, + "measurement_differences": 0, + "image_differences": 0, + "tables": [ + 3, + 3 + ], + "physical_images": [ + 0, + 0 + ], + "logical_images": [ + 0, + 0 + ], + "known_relationship_keys": [ + 1, + 1 + ], + "ordinary_receipt_sha256": "52bfa7d40c01a6f5405d57bb6d3d6652c4c592746a50b35677cdec241045e868", + "output_hashes": { + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/native/ExampleSpeckles/outputs/0/Image.csv": "55cdc9117d38d5a9a96b603052b9ca323824897be4962f285934973af03d73bb", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/native/ExampleSpeckles/outputs/0/h2ax.csv": "0f54fc72ccdeb7e1a68bab9dc3a8d9d49788cdf81dbbc109ed119e589c09538a", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/native/ExampleSpeckles/outputs/0/Nuclei.csv": "15af7cac08d651c19b3e3f409b2b0d7fc4f96011c9b53394aa9a35969a8936a6", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/ExampleSpeckles/wells_1/workers_1/images_ExampleSpeckles_source_workspace_well_throughput/results/h2ax.csv": "eb453565f3b79ac932eeb5cde8605888b72e58c80f42edbbf0b1ba37f34fd6f8", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/ExampleSpeckles/wells_1/workers_1/images_ExampleSpeckles_source_workspace_well_throughput/openhcs_metadata.json.lock": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/ExampleSpeckles/wells_1/workers_1/images_ExampleSpeckles_source_workspace_well_throughput/openhcs_metadata.json": "71582c62cabb2571ebf8a0de57f92fdf82c55a7ece3dac0bf2a6eca95cad84c9", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/ExampleSpeckles/wells_1/workers_1/images_ExampleSpeckles_source_workspace_well_throughput/results/Image.csv": "85ef16f24e75f03dc7055215cf2e6cb196b1dc0a0d73713a4c5999f698d4f96e", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/ExampleSpeckles/wells_1/workers_1/images_ExampleSpeckles_source_workspace_well_throughput/results/Nuclei.csv": "e50cb9f8c23f65e9ce8db25132263cf4a4448ed65fc1088d782536abf74c5670" + } + }, + { + "case": "ExampleSpeckles", + "ordinary_repeat": 1, + "native_repeat": 1, + "measurement_differences": 0, + "image_differences": 0, + "tables": [ + 3, + 3 + ], + "physical_images": [ + 0, + 0 + ], + "logical_images": [ + 0, + 0 + ], + "known_relationship_keys": [ + 1, + 1 + ], + "ordinary_receipt_sha256": "52bfa7d40c01a6f5405d57bb6d3d6652c4c592746a50b35677cdec241045e868", + "output_hashes": { + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/native/ExampleSpeckles/outputs/1/Nuclei.csv": "15af7cac08d651c19b3e3f409b2b0d7fc4f96011c9b53394aa9a35969a8936a6", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/native/ExampleSpeckles/outputs/1/h2ax.csv": "0f54fc72ccdeb7e1a68bab9dc3a8d9d49788cdf81dbbc109ed119e589c09538a", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/native/ExampleSpeckles/outputs/1/Image.csv": "1d2f3cbff7ee2608efb670186878d4588a8a438ef74aded60e7052f4d2f243ac", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/ExampleSpeckles/wells_1/workers_1/images_ExampleSpeckles_source_workspace_well_throughput/results/h2ax.csv": "eb453565f3b79ac932eeb5cde8605888b72e58c80f42edbbf0b1ba37f34fd6f8", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/ExampleSpeckles/wells_1/workers_1/images_ExampleSpeckles_source_workspace_well_throughput/openhcs_metadata.json.lock": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/ExampleSpeckles/wells_1/workers_1/images_ExampleSpeckles_source_workspace_well_throughput/openhcs_metadata.json": "71582c62cabb2571ebf8a0de57f92fdf82c55a7ece3dac0bf2a6eca95cad84c9", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/ExampleSpeckles/wells_1/workers_1/images_ExampleSpeckles_source_workspace_well_throughput/results/Image.csv": "85ef16f24e75f03dc7055215cf2e6cb196b1dc0a0d73713a4c5999f698d4f96e", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/ordinary-1/ExampleSpeckles/wells_1/workers_1/images_ExampleSpeckles_source_workspace_well_throughput/results/Nuclei.csv": "e50cb9f8c23f65e9ce8db25132263cf4a4448ed65fc1088d782536abf74c5670" + } + } + ], + "source_head": "60b2ac9b4d4fd91558f68aac85ae39b55e575fc8", + "scope": "Both ordinary observations versus both native measured observations; full strict files/values/correlation policy; descriptive two-repeat clocks, not full30 acceptance." +} diff --git a/benchmark/results/perf_current_native_paired_20261003/timing_summary.json b/benchmark/results/perf_current_native_paired_20261003/timing_summary.json new file mode 100644 index 0000000000..348ffb1661 --- /dev/null +++ b/benchmark/results/perf_current_native_paired_20261003/timing_summary.json @@ -0,0 +1,73 @@ +{ + "source_head": "60b2ac9b4d4fd91558f68aac85ae39b55e575fc8", + "cases": { + "ExampleSpeckles": { + "native_invocation_seconds": [ + 1.9962371489964426, + 1.9122227132320404 + ], + "native_mean_seconds": 1.9542299311142415, + "ordinary_samples": { + "compile_seconds": [ + 0.7714827060699463, + 0.5555016994476318 + ], + "execute_seconds": [ + 1.0937919616699219, + 1.3689088821411133 + ], + "total_seconds": [ + 2.189194314647466, + 2.302979093976319 + ] + }, + "ordinary_means": { + "compile_seconds": 0.6634922027587891, + "execute_seconds": 1.2313504219055176, + "total_seconds": 2.2460867043118924 + }, + "other_total_seconds_mean": 0.35124407964758575, + "execution_speedup_ratio_of_means": 1.5870623799276133, + "total_speedup_ratio_of_means": 0.870059881198102 + }, + "cp_tutorial_3d_monolayer": { + "native_invocation_seconds": [ + 14.286907745990902, + 14.557445348240435 + ], + "native_mean_seconds": 14.422176547115669, + "ordinary_samples": { + "compile_seconds": [ + 1.1917080879211426, + 1.23331618309021 + ], + "execute_seconds": [ + 8.670458555221558, + 9.58397126197815 + ], + "total_seconds": [ + 10.651790381409228, + 11.655223582871258 + ] + }, + "ordinary_means": { + "compile_seconds": 1.2125121355056763, + "execute_seconds": 9.127214908599854, + "total_seconds": 11.153506982140243 + }, + "other_total_seconds_mean": 0.8137799380347133, + "execution_speedup_ratio_of_means": 1.580128954071936, + "total_speedup_ratio_of_means": 1.2930620449881318 + } + }, + "scope": "Two current cases only; means of both observations, not a causal before/after comparison, confidence interval, or full30/scaling result. Server READY startup/shutdown and native imports/JVM/load/full warmup are excluded. Ordinary total includes compilation and default OUTCOMES/RSS completion.", + "science_sha256": "77ab1a1e88d52502c633b646efe0d032ad87f117fc403298cb8b5742a0510190", + "plot_script_sha256": "a85cbed7174f3e9cd00577e7ec2031d4b11e014042d2246bf4ad4b6927826c40", + "artifacts": { + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/figures-v2/metrics.csv": "906273de1e1fe146a7cf53a41892d203aa80fa96da9e7288ec619e6c828ad999", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/figures-v2/matched_runtime.png": "867a94f34c5cbe1b6d4fe86917a4e42ab335e486d8c321dd745a353c95dad72d", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/figures-v2/matched_runtime.svg": "9a5377c6ad8609f5a59ae2e9757ec5089d7d5dc77615839ac756fdbbb654e9f7", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/figures-v2/matched_speedup.png": "c8a789edb4dda3ae82fbb708a0d2c9a459f0ee0d7ea7732c266703622839e1ee", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/figures-v2/matched_speedup.svg": "d2e121af82f0a08e23f47cfa00b306ac60f8b580e72dad63cde72f6809ca8a2c" + } +} diff --git a/benchmark/results/perf_current_wound_illum3_paired_20261003/README.md b/benchmark/results/perf_current_wound_illum3_paired_20261003/README.md new file mode 100644 index 0000000000..d768c954f1 --- /dev/null +++ b/benchmark/results/perf_current_wound_illum3_paired_20261003/README.md @@ -0,0 +1,18 @@ +# Fresh paired WoundHealing and Illumination Example 3 comparison + +The ordinary public driver ran on clean source `293e04acb53156a0dd9ae71476703e24f66b196c`, containing main `f7de9efad393bce83a3756a271f0cd4383783ea9` and qualified ObjectState 1.1.9 / python-introspect 0.1.15 sources. This is baseline qualification; it does not measure a new performance improvement. CPU 5, one worker executing inline, one native thread, ordinary OUTCOMES export and process-tree RSS. Mandatory server/library/registry/kernel preparation is before pipeline clocks; startup and shutdown are excluded. Native imports, JVM, loading and complete warmup -1 are also outside the measured clocks. + +| Case | OH compilation | OH execution | OH total | Native execution | Native invocation | Execution speedup | Total speedup | +| --- | ---: | ---: | ---: | ---: | ---: | ---: | ---: | +| Illumination Example 3 | 0.594438 s | 0.535986 s | 1.539587 s | 0.626957 s | 0.695522 s | 1.16973x | 0.407224x | +| WoundHealing | 0.345184 s | 3.000829 s | 3.621918 s | 4.253330 s | 4.332074 s | 1.41738x | 1.17433x | + +Speedup means native execution divided by the corresponding OH clock, matching the existing figure policy. Native execution runs from the first module through post_run/close; invocation is recorded separately. Wound covers both selected image sets on each side: its native observation is not divided by two. Both ordinary and native observations are retained with ranges in the raw files. These two-observation means are descriptive, not statistical or causal evidence. Illum OH execution spans 0.385–0.687 s; that dispersion has not been attributed. + +Illum is the weakest total-time case in this new pair. Compilation plus work outside the server compilation/execution clocks consumes 1.003600 s of its 1.539587 s total. Its 2x-native total target leaves a 1.226108 s gap; execution-only work cannot bridge that total gap. Wound's execution and total 2x gaps are 0.874164 s and 1.495253 s. The unassigned completion remainder is not assumed to be entirely avoidable runtime work. + +Every ordinary observation passed against both fresh native observations: eight unchanged full scientific comparisons, declared output inventories and source projections. Illum has two float32 [463,461] image outputs, 213443 pixels per declared comparison; PolynomialCorrected has maximum absolute difference 2.9802322387695312e-08 and no pixels outside the existing 1e-6 policy, while ConvexHullCorrWorm pixels match exactly. Wound has one Image CSV with two rows and no authored image exports. All input/helper/native binary hashes and saved physical output hashes were independently verified. No new comparator exclusions or tolerances were introduced. + +Figures are generated by the existing `benchmark.reports.cppipe_figures` owner and retain the 2x reference. They complement the separate 3D/Speckles qualification; full30, scaling, and broader PR394 acceptance remain unfinished. The qualification source pin is immutable; it does not assert that subsequent live source/environment remains at that pin. + +Raw scientific files and the bounded controller remain in `/home/ts/.local/state/openhcs-maintenance/20261003/current-wound-illum3-paired-v1` and `current-wound-illum3-paired-preparation-v1/controller.py` (SHA256 `0b7abed65ecc3d61761533a3a9a69e9b9a8acb220049175ff46fb5f004ade4aa`). These are local custody locations, not a portable launcher. The compact committed pack retains every timing observation, exact qualification and full comparison receipt without copying scientific pixels. diff --git a/benchmark/results/perf_current_wound_illum3_paired_20261003/freeze-release.json b/benchmark/results/perf_current_wound_illum3_paired_20261003/freeze-release.json new file mode 100644 index 0000000000..7e4153fce3 --- /dev/null +++ b/benchmark/results/perf_current_wound_illum3_paired_20261003/freeze-release.json @@ -0,0 +1,15 @@ +{ + "status": "RELEASED_AFTER_ALL_ACTIONS_TERMINAL", + "source_head": "293e04acb53156a0dd9ae71476703e24f66b196c", + "strict_science_sha256": "3d89dc4daaceb34535ceaab05100b80b88487e32e67180a99595035b66c67236", + "action_handles": { + "prepare": 65780, + "ordinary": 31694, + "native": 10409, + "compare": 44398 + }, + "all_action_exit_codes": 0, + "source_clean_at_release": true, + "main_based_fix_pr": 523, + "output_bytes": 10031981 +} diff --git a/benchmark/results/perf_current_wound_illum3_paired_20261003/matched_runtime.png b/benchmark/results/perf_current_wound_illum3_paired_20261003/matched_runtime.png new file mode 100644 index 0000000000..19ca99020a Binary files /dev/null and b/benchmark/results/perf_current_wound_illum3_paired_20261003/matched_runtime.png differ diff --git a/benchmark/results/perf_current_wound_illum3_paired_20261003/matched_runtime.svg b/benchmark/results/perf_current_wound_illum3_paired_20261003/matched_runtime.svg new file mode 100644 index 0000000000..8f16558dde --- /dev/null +++ b/benchmark/results/perf_current_wound_illum3_paired_20261003/matched_runtime.svg @@ -0,0 +1,1614 @@ + + + + + + + + 2026-10-03T03:59:18.091894 + image/svg+xml + + + Matplotlib v3.11.2, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/benchmark/results/perf_current_wound_illum3_paired_20261003/matched_speedup.png b/benchmark/results/perf_current_wound_illum3_paired_20261003/matched_speedup.png new file mode 100644 index 0000000000..629f47cbd8 Binary files /dev/null and b/benchmark/results/perf_current_wound_illum3_paired_20261003/matched_speedup.png differ diff --git a/benchmark/results/perf_current_wound_illum3_paired_20261003/matched_speedup.svg b/benchmark/results/perf_current_wound_illum3_paired_20261003/matched_speedup.svg new file mode 100644 index 0000000000..3f4b7b878c --- /dev/null +++ b/benchmark/results/perf_current_wound_illum3_paired_20261003/matched_speedup.svg @@ -0,0 +1,1586 @@ + + + + + + + + 2026-10-03T03:59:18.419344 + image/svg+xml + + + Matplotlib v3.11.2, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/benchmark/results/perf_current_wound_illum3_paired_20261003/metrics.csv b/benchmark/results/perf_current_wound_illum3_paired_20261003/metrics.csv new file mode 100644 index 0000000000..d8d026b071 --- /dev/null +++ b/benchmark/results/perf_current_wound_illum3_paired_20261003/metrics.csv @@ -0,0 +1,7 @@ +pipeline_name,method,assay_category,module_category,accuracy_fraction,raw_seconds,speedup,peak_memory_mb +ExampleIlluminationCorrection_Example3,Native CP execution,,,1.0,0.6269565154798329,1.0, +ExampleIlluminationCorrection_Example3,OH execution,,,1.0,0.5359861850738525,1.1697251401982418, +ExampleIlluminationCorrection_Example3,OH total,,,1.0,1.5395865004975349,0.4072239625881526, +ExampleWoundHealing,Native CP execution,,,1.0,4.253329693106934,1.0, +ExampleWoundHealing,OH execution,,,1.0,3.0008292198181152,1.4173847898497653, +ExampleWoundHealing,OH total,,,1.0,3.6219175045844167,1.174330913866291, diff --git a/benchmark/results/perf_current_wound_illum3_paired_20261003/native-illum3.json b/benchmark/results/perf_current_wound_illum3_paired_20261003/native-illum3.json new file mode 100644 index 0000000000..b77b0d762b --- /dev/null +++ b/benchmark/results/perf_current_wound_illum3_paired_20261003/native-illum3.json @@ -0,0 +1,61 @@ +{ + "startup_seconds": 0.9386949227191508, + "environment": { + "python_executable": "/home/ts/code/projects/openhcs/.venv-cellprofiler39/bin/python", + "python_version": "3.9.25", + "cellprofiler_version": "4.2.8.1", + "cellprofiler_core_version": "4.2.8.1", + "numpy_version": "1.24.4", + "scipy_version": "1.9.0", + "temporary_root": "/home/ts/.local/state/openhcs-maintenance/20261003/current-wound-illum3-paired-v1/native/ExampleIlluminationCorrection_Example3/native_tmp" + }, + "request": { + "pipeline_path": "/home/ts/.local/state/openhcs-maintenance/20261003/current-wound-illum3-paired-v1/native/ExampleIlluminationCorrection_Example3/preparation/native_cellprofiler_headless/ExampleIlluminationCorrection_Example3.cppipe", + "input_dir": "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images", + "output_root": "/home/ts/.local/state/openhcs-maintenance/20261003/current-wound-illum3-paired-v1/native/ExampleIlluminationCorrection_Example3/outputs", + "expected_image_sets": 1, + "repetitions": 2, + "file_list_path": "/home/ts/.local/state/openhcs-maintenance/20261003/current-wound-illum3-paired-v1/native/ExampleIlluminationCorrection_Example3/preparation/native_cellprofiler_file_list.txt", + "first_image_set": 1, + "last_image_set": null, + "report_path": "/home/ts/.local/state/openhcs-maintenance/20261003/current-wound-illum3-paired-v1/native/ExampleIlluminationCorrection_Example3/native_report.json", + "start_barrier_root": null, + "start_barrier_job_count": 1, + "start_barrier_job_index": 0 + }, + "observations": [ + { + "repetition": -1, + "output_root": "/home/ts/.local/state/openhcs-maintenance/20261003/current-wound-illum3-paired-v1/native/ExampleIlluminationCorrection_Example3/outputs/-1", + "image_set_count": 1, + "invocation_seconds": 1.3667851807549596, + "pre_first_module_seconds": 0.2952348357066512, + "first_module_through_post_run_seconds": 1.0715503450483084, + "invocation_started_monotonic_seconds": 3808405.732912145, + "first_module_started_monotonic_seconds": 3808406.028146981, + "completed_monotonic_seconds": 3808407.099697326 + }, + { + "repetition": 0, + "output_root": "/home/ts/.local/state/openhcs-maintenance/20261003/current-wound-illum3-paired-v1/native/ExampleIlluminationCorrection_Example3/outputs/0", + "image_set_count": 1, + "invocation_seconds": 0.6704615103080869, + "pre_first_module_seconds": 0.07343892008066177, + "first_module_through_post_run_seconds": 0.5970225902274251, + "invocation_started_monotonic_seconds": 3808407.099707816, + "first_module_started_monotonic_seconds": 3808407.173146736, + "completed_monotonic_seconds": 3808407.770169326 + }, + { + "repetition": 1, + "output_root": "/home/ts/.local/state/openhcs-maintenance/20261003/current-wound-illum3-paired-v1/native/ExampleIlluminationCorrection_Example3/outputs/1", + "image_set_count": 1, + "invocation_seconds": 0.7205826421268284, + "pre_first_module_seconds": 0.06369220139458776, + "first_module_through_post_run_seconds": 0.6568904407322407, + "invocation_started_monotonic_seconds": 3808407.770178504, + "first_module_started_monotonic_seconds": 3808407.833870705, + "completed_monotonic_seconds": 3808408.490761146 + } + ] +} \ No newline at end of file diff --git a/benchmark/results/perf_current_wound_illum3_paired_20261003/native-wound.json b/benchmark/results/perf_current_wound_illum3_paired_20261003/native-wound.json new file mode 100644 index 0000000000..13b0a47072 --- /dev/null +++ b/benchmark/results/perf_current_wound_illum3_paired_20261003/native-wound.json @@ -0,0 +1,61 @@ +{ + "startup_seconds": 0.8074899800121784, + "environment": { + "python_executable": "/home/ts/code/projects/openhcs/.venv-cellprofiler39/bin/python", + "python_version": "3.9.25", + "cellprofiler_version": "4.2.8.1", + "cellprofiler_core_version": "4.2.8.1", + "numpy_version": "1.24.4", + "scipy_version": "1.9.0", + "temporary_root": "/home/ts/.local/state/openhcs-maintenance/20261003/current-wound-illum3-paired-v1/native/ExampleWoundHealing/native_tmp" + }, + "request": { + "pipeline_path": "/home/ts/.local/state/openhcs-maintenance/20261003/current-wound-illum3-paired-v1/native/ExampleWoundHealing/preparation/native_cellprofiler_headless/ExampleWoundHealing.cppipe", + "input_dir": "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleWoundHealing/images", + "output_root": "/home/ts/.local/state/openhcs-maintenance/20261003/current-wound-illum3-paired-v1/native/ExampleWoundHealing/outputs", + "expected_image_sets": 2, + "repetitions": 2, + "file_list_path": "/home/ts/.local/state/openhcs-maintenance/20261003/current-wound-illum3-paired-v1/native/ExampleWoundHealing/preparation/native_cellprofiler_file_list.txt", + "first_image_set": 1, + "last_image_set": null, + "report_path": "/home/ts/.local/state/openhcs-maintenance/20261003/current-wound-illum3-paired-v1/native/ExampleWoundHealing/native_report.json", + "start_barrier_root": null, + "start_barrier_job_count": 1, + "start_barrier_job_index": 0 + }, + "observations": [ + { + "repetition": -1, + "output_root": "/home/ts/.local/state/openhcs-maintenance/20261003/current-wound-illum3-paired-v1/native/ExampleWoundHealing/outputs/-1", + "image_set_count": 2, + "invocation_seconds": 5.988651636987925, + "pre_first_module_seconds": 0.3156425580382347, + "first_module_through_post_run_seconds": 5.67300907894969, + "invocation_started_monotonic_seconds": 3808416.643831191, + "first_module_started_monotonic_seconds": 3808416.959473749, + "completed_monotonic_seconds": 3808422.632482828 + }, + { + "repetition": 0, + "output_root": "/home/ts/.local/state/openhcs-maintenance/20261003/current-wound-illum3-paired-v1/native/ExampleWoundHealing/outputs/0", + "image_set_count": 2, + "invocation_seconds": 4.462228200864047, + "pre_first_module_seconds": 0.08501017466187477, + "first_module_through_post_run_seconds": 4.377218026202172, + "invocation_started_monotonic_seconds": 3808422.632492666, + "first_module_started_monotonic_seconds": 3808422.717502841, + "completed_monotonic_seconds": 3808427.094720867 + }, + { + "repetition": 1, + "output_root": "/home/ts/.local/state/openhcs-maintenance/20261003/current-wound-illum3-paired-v1/native/ExampleWoundHealing/outputs/1", + "image_set_count": 2, + "invocation_seconds": 4.201918839942664, + "pre_first_module_seconds": 0.07247747993096709, + "first_module_through_post_run_seconds": 4.129441360011697, + "invocation_started_monotonic_seconds": 3808427.094730606, + "first_module_started_monotonic_seconds": 3808427.167208086, + "completed_monotonic_seconds": 3808431.296649446 + } + ] +} \ No newline at end of file diff --git a/benchmark/results/perf_current_wound_illum3_paired_20261003/ordinary-0.csv b/benchmark/results/perf_current_wound_illum3_paired_20261003/ordinary-0.csv new file mode 100644 index 0000000000..84f26f5306 --- /dev/null +++ b/benchmark/results/perf_current_wound_illum3_paired_20261003/ordinary-0.csv @@ -0,0 +1,3 @@ +case_name,mode_name,worker_count,well_count,compile_seconds,prepare_seconds,execute_seconds,total_seconds,wells_per_second,successful_wells,native_single_sample_execution_seconds,projected_native_execution_seconds,projected_execution_speedup,peak_memory_mb,status,memory_limit_mb,error_message,execution_route,server_lifecycle,run_input_sha256 +ExampleIlluminationCorrection_Example3,1w_1t,1,1,0.5973958969116211,0.0,0.6867749691009521,1.7173079238273203,1.4560810236125619,1,,,,1266.88671875,success,,,ordinary-zmq-outcomes-v1,reused-per-sweep,7b9e90e243383cc67d48359b943511e18cedb23e386c92cd2bea0d2257f35d50 +ExampleWoundHealing,1w_1t,1,1,0.34695887565612793,0.0,2.856407642364502,3.471247054170817,0.3500900869919993,1,,,,1893.171875,success,,,ordinary-zmq-outcomes-v1,reused-per-sweep,7b9e90e243383cc67d48359b943511e18cedb23e386c92cd2bea0d2257f35d50 diff --git a/benchmark/results/perf_current_wound_illum3_paired_20261003/ordinary-1.csv b/benchmark/results/perf_current_wound_illum3_paired_20261003/ordinary-1.csv new file mode 100644 index 0000000000..9cc7a096b9 --- /dev/null +++ b/benchmark/results/perf_current_wound_illum3_paired_20261003/ordinary-1.csv @@ -0,0 +1,3 @@ +case_name,mode_name,worker_count,well_count,compile_seconds,prepare_seconds,execute_seconds,total_seconds,wells_per_second,successful_wells,native_single_sample_execution_seconds,projected_native_execution_seconds,projected_execution_speedup,peak_memory_mb,status,memory_limit_mb,error_message,execution_route,server_lifecycle,run_input_sha256 +ExampleIlluminationCorrection_Example3,1w_1t,1,1,0.5914797782897949,0.0,0.38519740104675293,1.3618650771677494,2.596071513677285,1,,,,1025.0546875,success,,,ordinary-zmq-outcomes-v1,reused-per-sweep,7b9e90e243383cc67d48359b943511e18cedb23e386c92cd2bea0d2257f35d50 +ExampleWoundHealing,1w_1t,1,1,0.34340977668762207,0.0,3.1452507972717285,3.7725879549980164,0.3179396698245576,1,,,,1664.71484375,success,,,ordinary-zmq-outcomes-v1,reused-per-sweep,7b9e90e243383cc67d48359b943511e18cedb23e386c92cd2bea0d2257f35d50 diff --git a/benchmark/results/perf_current_wound_illum3_paired_20261003/qualification.json b/benchmark/results/perf_current_wound_illum3_paired_20261003/qualification.json new file mode 100644 index 0000000000..b80759f54b --- /dev/null +++ b/benchmark/results/perf_current_wound_illum3_paired_20261003/qualification.json @@ -0,0 +1,231 @@ +{ + "status": "SAVED_HASHES_AND_NONVACUITY_VERIFIED_FULL_SCIENCE_JOIN_PASS", + "source_head": "293e04acb53156a0dd9ae71476703e24f66b196c", + "source_freeze_sha256": "7719484a567283a9427cd9a3742b8ca4f25b26c0678f2d8858073d5666adb284", + "source_environment_scope": "Authoritative before/after controller freeze and terminal release joined; live checkout/env after release not asserted identical.", + "environment_sha256": "18b33cab3a61c45a940312d5ea4e1e108bc5d57261a520f3d9c5058db3ef3776", + "source_input_hashes": { + "/home/ts/code/projects/openhcs/benchmark/reference_exports/official30_value_completion_20260914/ExampleIlluminationCorrection_Example3.cppipe": "f7ec9eb561730cc567986e6a50504a69f23a3ca78a1a033faba0b2fea52759fb", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/--W00001--P00001--Z00000--T00000--cherry.tif": "f073bc8f8102f05e6443226fcb986e7d30b3f9f0d7cd77d25c7c9f82ee11b782", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/ADSAStaphInfection2_A01_w2247376DD-6ADD-442D-AE47-F54A05F3EA94.tif": "5a57b7557bb0da5e241b48851b82d936c7ec36ede7aaca5e77b28ac4bfebf502", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O01f00d2.TIF": "5bfdeeb9e1dba87dc55220f71168af3d9949f38b8d59ba741b546619c2a49fd3", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O01f01d2.TIF": "8ddf231a2727fe0dd5e80d1747a968ecc67438def175dd2b4a5850bf54699c2b", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O01f02d2.TIF": "5a7bf7ff3504baaf787f004e2137059ea2ca890a37842df5360a035b78e49940", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O02f00d2.TIF": "57f0a36092341c746441c837c78b103f35ef6460a71df77f5ae9ee74cd82ad4e", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O02f01d2.TIF": "d1b6057f138d897c3dba0d055e90e17ca5239523264c138c863bd2c4c7e453fa", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O02f02d2.TIF": "4b52dc59a87b5230d2e8701971d42df4f0e96966cf1308ce6eb7dc4865c1000e", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O03f00d2.TIF": "269e5ab417a616ef55679321f56ee99e870abe4e519c5c24c911b39b1527e7fd", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O03f01d2.TIF": "0e95bb9ab0feeab2d0ddd1a5cc877475b5c8001ae4873b9ebcaaa44107acec78", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O03f02d2.TIF": "a26dbf0381c2404bb0f495e9c68d7f2ec8fa87eae6edc7c95b5a3fc55f548a97", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O04f00d2.TIF": "fce63090cdf6281b51ac538d7af3840610f2e275af45d1cf8dd59ee2bf92377a", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O04f01d2.TIF": "e27fd485ee359490f13efa73bf7bbaef2c6743ecadba05d21a22d156ed9b892e", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O04f02d2.TIF": "fa078664928f35b7b0d1a3a971e39602bbb775f78e9001c3dcd81e392c570bf5", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O05f00d2.TIF": "cb80c657237e9cbdadba93d49d9a10cf35531ea2cb7246c5cf15d6cac1a30651", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O05f01d2.TIF": "6035bce54914bc2ce236dd1c37eda3dbeb83752ad6c3c3746e57ae13041ec868", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O05f02d2.TIF": "64e64f69f7b6abd5ed2db49b1a39dcf4036706a2a7cebef48a5188c41e0598e2", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O06f00d2.TIF": "076a52b3f4e257d18f45b01a61bfeeac112531fb5036890f2f2aa44f2ea36fdf", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O06f01d2.TIF": "72e69058831189fb1e799209c6d8bfd90d52e2736d96352ecca08735238c8384", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O06f02d2.TIF": "3c1a864005429908707a07a7f26debc838b9fff9328953a2838b7b629b305d85", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O07f00d2.TIF": "e4adc0b64624c1e83deca015415473d77f323ed7d6cad0322472874cb32b2aa3", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O07f01d2.TIF": "ce3310b92a870a24abc9e81319d319fef07a6fe6a99961c174b1bc06bb65fc47", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O07f02d2.TIF": "0ada0de31dec60745bece90d3d67c5ca5dbec6fa0532d61afe621602eef95543", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O08f00d2.TIF": "ff903c458dbfdbdd076952533aa1f3b17aa71d6b2add8cb79ead0f1649d8a189", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O08f01d2.TIF": "0f3c0748ed5ec06b7e95e411a7744571e3338e3c37ff5b0336d707db997e939c", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O08f02d2.TIF": "97f926715e7ee9743e7b382808486de24a0b386db6712cf9b38a012fcb5b3e0e", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O09f00d2.TIF": "c60dd32928613a0905306b3697279138828520bc8a9420e662dbe79799cba89c", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O09f01d2.TIF": "917e37b5cd8d60c9e2caa89472246fb94d1c51f1a350554556cf826fae276437", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O09f02d2.TIF": "7f3750dd2ea324983f4ab1fcac59183a410267d1f8221f2963f7e74d19646450", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O10f00d2.TIF": "fe52a74223e5a46d3d2b434d7dacc3d2517f2c5b10f0d04b7a3cbf7fbf41e63d", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O10f01d2.TIF": "fc325b8baff83f25402f8398760df8b2bb72425a98077ede74fa05446b22ac88", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O10f02d2.TIF": "b763c7dc7a8a539f2eaa52517c60c39b0673b9777c4642555ba86b5774d6b0fd", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O11f00d2.TIF": "3f05a9e77c8cdf6c5c29c0af26a147bcc63c110bf0bc438abc27497501cfeda6", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O11f01d2.TIF": "93e08b9408c31d4317b2ef2db997c4df3efa7ae8d8d32738cb0ec0c5c9ec1d1f", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O11f02d2.TIF": "25304455c0b64544bcf09aed892c61cd37c3f6535db2447741f0fd0f08eea27c", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O12f00d2.TIF": "6876b895933a84d9dbe7d94e0db1862fdc19ae006a9be1ed76c0e1ec390a95cb", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O12f01d2.TIF": "b29ea362fcf4f1276977f5e09804b3caeca1dba4c030fa285ce69fb7f26b6044", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O12f02d2.TIF": "e086c6b414fa5345577bb9d1cbcfcfdbd183e639e9039b50f1c08b5b67a00f36", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O13f00d2.TIF": "cae644c4b99556fccddbab42098f8dbdaa723996c521557f3b59caf3430b82d7", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O13f01d2.TIF": "17e88f342e33075b08338cb191df919c85eb3a5fa8efb3ddfcae57e69e776be3", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O13f02d2.TIF": "7bfe66d604eeb2b996e368f6a0e36891f2dd0d6ba5d819b4104614d0f0236bd2", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O14f00d2.TIF": "844889a709a3326137fd67171c0b8ec018b397fe1ede836a9b7e5809e075f58d", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O14f01d2.TIF": "968ea530f2a3aab735664fff7936ebc4e406a7112fd84b89d92431ba27178c96", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O14f02d2.TIF": "5193e9ba72e56eaaff791c214c6be34766522b6aaab383ad8e9893f0734e60c3", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O15f00d2.TIF": "488149e5f50630d794c6c57340df6271a693035bbfa46142ed6422cbfa64c8ae", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O15f01d2.TIF": "3278f9402a8110bb622b2a8c62b8087d19b35736ae9a9e6361e675af67ecc13f", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O15f02d2.TIF": "25a40d29b3e2525c976b2288013bdbeb0a2eee7026f172d100586ff9a51ce348", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O16f00d2.TIF": "16fe3c9674e55150497d1d573ccc262419314ae62acb1c76dca858c40f72f744", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O16f01d2.TIF": "69133d455b367c919d5f2bcde19ab2c6223ef57b06d2c3011393e8c9f1a709c9", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O16f02d2.TIF": "b0c7dbcf259ad76e9fccb6de614b5d15f542317bb95c97a85233fbdcb73c9de3", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O17f00d2.TIF": "d049efceda2aea79923d4b8df69de9144ba104c77a06bf168184830cc30f30d4", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O17f01d2.TIF": "bae6ec7694d0868c74c079f5cd24534542f2835d4cab41ed8d82586c662ce4d1", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O17f02d2.TIF": "c991d219a21e6f1274b01bb6f370c4fb44addb122c1e292c36acd33def0787e2", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O18f00d2.TIF": "15e3dde0bdcd792bde186c6576cbb45d64723fb50b5d4c1841ad9ce3c6386f2d", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O18f01d2.TIF": "cf8e231352f5bf3f0b63aa29cf72a21c90a15ad2233e8495068a778399a056d0", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O18f02d2.TIF": "f67d7dba8a06dea16da609d350a98647d181c7b175109b940c74627e4c7fc4fd", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O19f00d2.TIF": "c370003080a53449570d1d780b9dd84626bd3cfa49c80c6db0ccdb493cbf6a63", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O19f01d2.TIF": "1a5b7ad836b7f86e187c52eb4e9f76dbc71b2057bf6ab8ff57d676314811a930", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O19f02d2.TIF": "e8e3774e2ad39eeb9dcfb25cb92d7c75c022f86de5fab772a36e60a332cc7cf1", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O20f00d2.TIF": "99cf977fccdc4cbdb1ba8a1a2992dbf4d1c26b7f6d822a18d0db323e842ace8e", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O20f01d2.TIF": "6847c82a3ea55a29c1f55c7dcf251e5b8a776eb207107f41aaabf3978a855c58", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O20f02d2.TIF": "2e0059c518aa222960520be791721a52837a948d22bf1d2fb4000b37ec89e881", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O21f00d2.TIF": "26fb12cc1228982b372da290eabe06897521db386800aca9518535fead716870", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O21f01d2.TIF": "1c59f7447309b5854ebcac27ed3cd10c564894b4cdb6510865b447bca4029c95", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O21f02d2.TIF": "9c0d1062e13d193427eb146b882e19c54ccbbba531df786d797e7d13756198b0", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O22f00d2.TIF": "fafa8607d475c46e645433036df14b58ec9ba7c850ef5ff37b8253bd8ea67f05", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O22f01d2.TIF": "2183fc92523891136905acf96fc2bdad04e00657f8070911ac3d4c1950ebf822", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O22f02d2.TIF": "5684cec26114f2813f41d4c42ba2bbe982b01bdcad78d80d73cfb78e07f9c790", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O23f00d2.TIF": "7e2420883575733a3d759752d633df10eec665b9d0575173063365366320a8b7", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O23f01d2.TIF": "f61467aadaf8e4c92cab7daff2cf5cf99b87783d5a055f69d9043c8b9b958554", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O23f02d2.TIF": "0a0839f901f76e8f11e85c94af74e0c8f1df302cc7fd88cd7429e83e694329c7", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O24f00d2.TIF": "ecd17866fa382365023790c9c874255e9248ce77fa374abfaec73a62f7cb898d", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O24f01d2.TIF": "8ac212dcc8b92fb953bd4a17f2b6a49a9b824c521b5c0fb62bfafacadd03a44d", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O24f02d2.TIF": "adf56aa932a3e04f19e5eb2b0f5d85a15b52fa2ffa0a0e57b6754c6de818eee0", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleWoundHealing/ExampleWoundHealing.cppipe": "61da2bdd29daec73813645fef978fe237ecd92229433106d80e9bb0c65a3c8e6", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleWoundHealing/images/DMSO_B5_t0.JPG": "1d91c175dd7aa433e63d218b9d352e6065c5c5c888631366f6d0716fa384f642", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleWoundHealing/images/DMSO_B5_t24.JPG": "fc83c19de66538f1619728cd52930b867fb87bbcfa39d85ab9838eae7e097198" + }, + "helpers": { + "/home/ts/.local/state/openhcs-maintenance/20261003/current-wound-illum3-paired-preparation-v1/controller.py": "0b7abed65ecc3d61761533a3a9a69e9b9a8acb220049175ff46fb5f004ade4aa", + "/var/tmp/run_narrow450_runtime_phase_probe_20261002.py": "93a4b1720d3d2c64e77b722c91597be42c7c9968bad42a4503e5588fc7fc4a55", + "/var/tmp/openhcs_measurement_sparse_inventory_v2_20261003.py": "481d6ee99045090e6dac0e1d287a70cd33698575e06375780c123c66ed0bf52b", + "/tmp/run_integrated_fields_ordinary_abba_20261002.py": "8a41db448a722d231777a90a3ae23091617c8ac1ba72cefcb91f72b2c7975554" + }, + "native_binaries": { + "openhcs/core/_tabular_native.abi3.so": "2ce348417de70ad3f614962c82aed9c4977c32b3ba00e13531ecafb8c10d8d1d", + "openhcs/processing/backends/cellprofiler/_granularity_native.abi3.so": "6e45987a50d5c0588a8fb0b09a2232a63e72c122d6a3d583ae4d62830e3b4096" + }, + "strict_science_sha256": "3d89dc4daaceb34535ceaab05100b80b88487e32e67180a99595035b66c67236", + "release_sha256": "718c3806e7d77bc7762268033e1fae6e5491db177f43bc29ff0e314b5b8e50f5", + "all_handles_terminal": { + "prepare": 65780, + "ordinary": 31694, + "native": 10409, + "compare": 44398 + }, + "retained_scientific_comparisons": 8, + "nonvacuity": [ + { + "case": "ExampleIlluminationCorrection_Example3", + "ordinary_repeat": 0, + "native_repeat": 0, + "declared_image_count": 2, + "pixels_per_declared_comparison": [ + 213443, + 213443 + ] + }, + { + "case": "ExampleIlluminationCorrection_Example3", + "ordinary_repeat": 0, + "native_repeat": 1, + "declared_image_count": 2, + "pixels_per_declared_comparison": [ + 213443, + 213443 + ] + }, + { + "case": "ExampleWoundHealing", + "ordinary_repeat": 0, + "native_repeat": 0, + "participating_tables_per_side": 1 + }, + { + "case": "ExampleWoundHealing", + "ordinary_repeat": 0, + "native_repeat": 1, + "participating_tables_per_side": 1 + }, + { + "case": "ExampleIlluminationCorrection_Example3", + "ordinary_repeat": 1, + "native_repeat": 0, + "declared_image_count": 2, + "pixels_per_declared_comparison": [ + 213443, + 213443 + ] + }, + { + "case": "ExampleIlluminationCorrection_Example3", + "ordinary_repeat": 1, + "native_repeat": 1, + "declared_image_count": 2, + "pixels_per_declared_comparison": [ + 213443, + 213443 + ] + }, + { + "case": "ExampleWoundHealing", + "ordinary_repeat": 1, + "native_repeat": 0, + "participating_tables_per_side": 1 + }, + { + "case": "ExampleWoundHealing", + "ordinary_repeat": 1, + "native_repeat": 1, + "participating_tables_per_side": 1 + } + ], + "output_role_hashes": { + "ExampleIlluminationCorrection_Example3/ordinary0": { + "/home/ts/.local/state/openhcs-maintenance/20261003/current-wound-illum3-paired-v1/ordinary-0/ExampleIlluminationCorrection_Example3/wells_1/workers_1/images_ExampleIlluminationCorrection_Example3_source_workspace_well_throughput/openhcs_metadata.json": "579ac084b396dff5f7fbaa844139bf952c2576b6cb0242772c925ba9839c2267", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-wound-illum3-paired-v1/ordinary-0/ExampleIlluminationCorrection_Example3/wells_1/workers_1/images_ExampleIlluminationCorrection_Example3_source_workspace_well_throughput/openhcs_metadata.json.lock": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-wound-illum3-paired-v1/ordinary-0/ExampleIlluminationCorrection_Example3/wells_1/workers_1/images_ExampleIlluminationCorrection_Example3_source_workspace_well_throughput/results/reference_image__ConvexHullCorrWorm.npy": "9ba1259e4ca007c06f14be6946e32a86307ec2dfb9952b73fa2cc253ccae8b3a", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-wound-illum3-paired-v1/ordinary-0/ExampleIlluminationCorrection_Example3/wells_1/workers_1/images_ExampleIlluminationCorrection_Example3_source_workspace_well_throughput/results/reference_image__PolynomialCorrected.npy": "8875da63a072c8f2de4f5cb707d779a064b663bf69aa0f304fe6fa74d4ff57a6" + }, + "ExampleIlluminationCorrection_Example3/ordinary1": { + "/home/ts/.local/state/openhcs-maintenance/20261003/current-wound-illum3-paired-v1/ordinary-1/ExampleIlluminationCorrection_Example3/wells_1/workers_1/images_ExampleIlluminationCorrection_Example3_source_workspace_well_throughput/openhcs_metadata.json": "579ac084b396dff5f7fbaa844139bf952c2576b6cb0242772c925ba9839c2267", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-wound-illum3-paired-v1/ordinary-1/ExampleIlluminationCorrection_Example3/wells_1/workers_1/images_ExampleIlluminationCorrection_Example3_source_workspace_well_throughput/openhcs_metadata.json.lock": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-wound-illum3-paired-v1/ordinary-1/ExampleIlluminationCorrection_Example3/wells_1/workers_1/images_ExampleIlluminationCorrection_Example3_source_workspace_well_throughput/results/reference_image__ConvexHullCorrWorm.npy": "9ba1259e4ca007c06f14be6946e32a86307ec2dfb9952b73fa2cc253ccae8b3a", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-wound-illum3-paired-v1/ordinary-1/ExampleIlluminationCorrection_Example3/wells_1/workers_1/images_ExampleIlluminationCorrection_Example3_source_workspace_well_throughput/results/reference_image__PolynomialCorrected.npy": "8875da63a072c8f2de4f5cb707d779a064b663bf69aa0f304fe6fa74d4ff57a6" + }, + "ExampleIlluminationCorrection_Example3/native-1": { + "/home/ts/.local/state/openhcs-maintenance/20261003/current-wound-illum3-paired-v1/native/ExampleIlluminationCorrection_Example3/outputs/-1/reference_image__ConvexHullCorrWorm.npy": "9ba1259e4ca007c06f14be6946e32a86307ec2dfb9952b73fa2cc253ccae8b3a", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-wound-illum3-paired-v1/native/ExampleIlluminationCorrection_Example3/outputs/-1/reference_image__PolynomialCorrected.npy": "588e6f9951aa7ad220678dbb0053e98fb6d324e71aab089d1d828d891ee32f54" + }, + "ExampleIlluminationCorrection_Example3/native0": { + "/home/ts/.local/state/openhcs-maintenance/20261003/current-wound-illum3-paired-v1/native/ExampleIlluminationCorrection_Example3/outputs/0/reference_image__ConvexHullCorrWorm.npy": "9ba1259e4ca007c06f14be6946e32a86307ec2dfb9952b73fa2cc253ccae8b3a", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-wound-illum3-paired-v1/native/ExampleIlluminationCorrection_Example3/outputs/0/reference_image__PolynomialCorrected.npy": "588e6f9951aa7ad220678dbb0053e98fb6d324e71aab089d1d828d891ee32f54" + }, + "ExampleIlluminationCorrection_Example3/native1": { + "/home/ts/.local/state/openhcs-maintenance/20261003/current-wound-illum3-paired-v1/native/ExampleIlluminationCorrection_Example3/outputs/1/reference_image__ConvexHullCorrWorm.npy": "9ba1259e4ca007c06f14be6946e32a86307ec2dfb9952b73fa2cc253ccae8b3a", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-wound-illum3-paired-v1/native/ExampleIlluminationCorrection_Example3/outputs/1/reference_image__PolynomialCorrected.npy": "588e6f9951aa7ad220678dbb0053e98fb6d324e71aab089d1d828d891ee32f54" + }, + "ExampleWoundHealing/ordinary0": { + "/home/ts/.local/state/openhcs-maintenance/20261003/current-wound-illum3-paired-v1/ordinary-0/ExampleWoundHealing/wells_1/workers_1/images_ExampleWoundHealing_source_workspace_well_throughput/openhcs_metadata.json": "71582c62cabb2571ebf8a0de57f92fdf82c55a7ece3dac0bf2a6eca95cad84c9", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-wound-illum3-paired-v1/ordinary-0/ExampleWoundHealing/wells_1/workers_1/images_ExampleWoundHealing_source_workspace_well_throughput/openhcs_metadata.json.lock": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-wound-illum3-paired-v1/ordinary-0/ExampleWoundHealing/wells_1/workers_1/images_ExampleWoundHealing_source_workspace_well_throughput/results/Image.csv": "939735fa17a067137fea2adc77d57f9ce1df24bfcb6588c49023de1cc3998677" + }, + "ExampleWoundHealing/ordinary1": { + "/home/ts/.local/state/openhcs-maintenance/20261003/current-wound-illum3-paired-v1/ordinary-1/ExampleWoundHealing/wells_1/workers_1/images_ExampleWoundHealing_source_workspace_well_throughput/openhcs_metadata.json": "71582c62cabb2571ebf8a0de57f92fdf82c55a7ece3dac0bf2a6eca95cad84c9", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-wound-illum3-paired-v1/ordinary-1/ExampleWoundHealing/wells_1/workers_1/images_ExampleWoundHealing_source_workspace_well_throughput/openhcs_metadata.json.lock": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-wound-illum3-paired-v1/ordinary-1/ExampleWoundHealing/wells_1/workers_1/images_ExampleWoundHealing_source_workspace_well_throughput/results/Image.csv": "939735fa17a067137fea2adc77d57f9ce1df24bfcb6588c49023de1cc3998677" + }, + "ExampleWoundHealing/native-1": { + "/home/ts/.local/state/openhcs-maintenance/20261003/current-wound-illum3-paired-v1/native/ExampleWoundHealing/outputs/-1/Image.csv": "368b4c00672ff296d0a72ee7b2dc6ff4da56f35da3bed14ec62afba78f9c6c9b" + }, + "ExampleWoundHealing/native0": { + "/home/ts/.local/state/openhcs-maintenance/20261003/current-wound-illum3-paired-v1/native/ExampleWoundHealing/outputs/0/Image.csv": "497700eb62ed0a557b902968c0fdb444eca8b748a772d8234f241c84f5dfad87" + }, + "ExampleWoundHealing/native1": { + "/home/ts/.local/state/openhcs-maintenance/20261003/current-wound-illum3-paired-v1/native/ExampleWoundHealing/outputs/1/Image.csv": "373f02427a4758051bfdd80efd7071774d8adcae60a2928c6d3bb67ad993155c" + } + }, + "original_matched_output_hash_count": 20, + "figure_owner_sha256": "bf4132cabafca6f7e1d277d73ac8cbfd4f30141dcb1b6981bc5fc451da43725e", + "plot_script_sha256": "7972986db6f16f48094d078be56b5fc89e0b020b2bda9b65a14bb267f9045b2b", + "figure_artifacts_sha256": { + "/home/ts/.local/state/openhcs-maintenance/20261003/current-wound-illum3-paired-v1/figures-v1/README.md": "c6eff275dab63534b4b555904f82098ea1e343486f7f5bc422b9743e0898b204", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-wound-illum3-paired-v1/figures-v1/matched_speedup.png": "73b72fa7e2aebec57029f421d081a47261fd7eadf18f6f40705aa4668e136d90", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-wound-illum3-paired-v1/figures-v1/metrics.csv": "df153bc46af1b2e9c1c8e56e18a8a6f48032eecda90000413536eab92e0e99b5", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-wound-illum3-paired-v1/figures-v1/matched_speedup.svg": "6fe3c9f639515d615ff2feb0acf4bd184f54911e273c2cd68ce5f2c34d23d426", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-wound-illum3-paired-v1/figures-v1/matched_runtime.svg": "a65fe6ba36b2b120e5dd919ce9e154226469171a85ea156b95eae78448c932cc", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-wound-illum3-paired-v1/figures-v1/timing_summary.json": "0cc2fa4e4331e97026d46217cc7fa470773cae20784169355a0459398d81662e", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-wound-illum3-paired-v1/figures-v1/matched_runtime.png": "2289b2d27c7c044da4057afc0cd15297377be5526e83e539603847262321ea91", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-wound-illum3-paired-v1/figures-v1/raw-observations.csv": "04f92f2af7a45ab8838868d1460b1d2332bcb325b8f1d2c7b3ac46bdb34db889" + }, + "scope": "Independent saved file/input/helper/native hash and nonvacuity verification; original numerical/full-inventory/correlation comparison results retained unchanged, not a new comparator run. Warmup files hash-preserved but not counted as measured science comparisons. No pipeline/source/env edits. No Wound per-image division." +} diff --git a/benchmark/results/perf_current_wound_illum3_paired_20261003/raw-observations.csv b/benchmark/results/perf_current_wound_illum3_paired_20261003/raw-observations.csv new file mode 100644 index 0000000000..30788dcb9d --- /dev/null +++ b/benchmark/results/perf_current_wound_illum3_paired_20261003/raw-observations.csv @@ -0,0 +1,9 @@ +case,method,repeat,compile_seconds,execute_seconds,total_seconds,native_invocation_seconds,image_sets +ExampleIlluminationCorrection_Example3,OpenHCS,0,0.5973958969116211,0.6867749691009521,1.7173079238273203,,1 +ExampleIlluminationCorrection_Example3,OpenHCS,1,0.5914797782897949,0.38519740104675293,1.3618650771677494,,1 +ExampleIlluminationCorrection_Example3,Native CP,0,,0.5970225902274251,,0.6704615103080869,1 +ExampleIlluminationCorrection_Example3,Native CP,1,,0.6568904407322407,,0.7205826421268284,1 +ExampleWoundHealing,OpenHCS,0,0.34695887565612793,2.856407642364502,3.471247054170817,,2 +ExampleWoundHealing,OpenHCS,1,0.34340977668762207,3.1452507972717285,3.7725879549980164,,2 +ExampleWoundHealing,Native CP,0,,4.377218026202172,,4.462228200864047,2 +ExampleWoundHealing,Native CP,1,,4.129441360011697,,4.201918839942664,2 diff --git a/benchmark/results/perf_current_wound_illum3_paired_20261003/source-freeze.json b/benchmark/results/perf_current_wound_illum3_paired_20261003/source-freeze.json new file mode 100644 index 0000000000..fea7d563c6 --- /dev/null +++ b/benchmark/results/perf_current_wound_illum3_paired_20261003/source-freeze.json @@ -0,0 +1,8607 @@ +{ + "source_state": { + "head": "293e04acb53156a0dd9ae71476703e24f66b196c", + "status": "", + "origin_main": "f7de9efad393bce83a3756a271f0cd4383783ea9", + "tracked": { + ".coveragerc": "5c9dbf297df8f44b2a4750224108ca116f67fc0ce1d6fa6ca51674b4928a3dd4", + ".github/dependabot.yml": "34790e08d06d30f3f06cf2f071fcb2430df398c0a70bf1d99b5cca71d69080ef", + ".github/pull_request_template.md": "fe05b94ba8fa1d566e4463a32fe938c0af6a20c50c373bf77e93fca8a77b905a", + ".github/tests/test_refactor_guardrails.py": "7d9b663b1801754fe934b76ae5c740c5355b34ec7bfa8ebac55762b236ee118e", + ".github/workflows/coverage-pages.yml": "1bc15d59c10cd3dc40c9d803facf81a4ac6c5bc9de2634a94f0ceef97d3314a9", + ".github/workflows/docs.yml": "b36d0a763034b127e99ba1bdd3061e833e933b861e2c81ec34098db0a17c19c7", + ".github/workflows/integration-tests.yml": "a85b32502b58df220e5f7c42cf6e876b6d970c2c5beb419b8d88bb3977d45b6d", + ".github/workflows/publish.yml": "03cda04e49ecc3ab34014e4c440e3f376b13df4b53e6952887fa05b7d69d705b", + ".github/workflows/published-release-canary.yml": "b5b377bf774fd8c19045e7708279d062b3e8da1738b809a8adb79c79a33c1cf0", + ".github/workflows/refactor-guardrails.yml": "47f3eabe448382c8529fb3920a06b07ec6cec90e485a8bb1c29c1f99ee87a3d2", + ".github/workflows/website-pages.yml": "94fd5634ace8d7f138446a120acb49de27d0ea7230b09b1e958ef8b8fcd85b37", + ".gitignore": "13c945f83cd74fbb6205745658ccba4c3bd559c080795a45ffb73851e02f6f75", + ".gitmodules": "b70034bf0b9661f2528f002e08c03042d6cece29de79bd96c11d2d5a943684bd", + ".readthedocs.yaml": "bd5346a882747235c8202c2de4ecfc8c9902accc1cf1534a55d1d1c7a93c373c", + ".vscode/settings.json": "3e7bf4823a1a681cc4162d6f78c91e0d36b2472ddbcda3417750c29b0023a853", + "CHANGELOG.md": "855d7bc59dcd8ef0cb352c33c88710f03c12c833af10867411a14c6ea45d571e", + "LICENSE": "1fe81c33f0cdfbcea8ce2fa4bf5cc98604be54a954ff7c59cea0ff02e3c15741", + "MANIFEST.in": "f54ae206d1d86e914964233d7d3ae1535a4740861257ca9413c24615d4cc5fa2", + "Makefile": "a5b8e41d8bc34948a87649ea12bb1f89c683fafb53a109da6a3f6394d77c7155", + "README.md": "1a600010deb7ddc3fe141b5efe3528bbe4a4e119846157e935e56784628445ed", + "THIRD_PARTY_LICENSES/human-eval-bia-MIT.txt": "d9835c14c2464401664c33f9458254b23fe3ee650e6a54b954338466518b8708", + "THIRD_PARTY_LICENSES/napari-roi-manager-LICENSE": "b6f986100ba22febd16871abdc9af7d0e7b3ae730131bb14fb9589c2acc9caa6", + "benchmark/__init__.py": "802082be754468008c44f86a8a4df7de65eb44280919daace363d04519e45f93", + "benchmark/adapters/__init__.py": "aa93075a5770d135a44c207807cc75c4309e630101bc3d13ef7a75a915151157", + "benchmark/adapters/cellprofiler.py": "6bcbbf744efa539bce2323d484085282fbfb823878ed7e47e7f1250d0d110c01", + "benchmark/adapters/cellprofiler_installation.py": "36ea8b73a88666621430f02dcabd38a502ab202062b667c9c70dd4a2baa1860a", + "benchmark/adapters/cppipe_source.py": "59a317cf302d859445fecb63c39fe5ef5d0ffbac6f849127759967c264ce9316", + "benchmark/adapters/openhcs.py": "21a49c342047a8d8afe7e6937c7dafb97a42fe3038b207a9e67e4459e688a2cc", + "benchmark/agent_validation/OPERATOR_GUIDE.md": "2b2ef7d0dd070e03f8a33bfd8bc0257087e3090c5de02477deef2ebee8d2401f", + "benchmark/agent_validation/__init__.py": "835f7c1cd162b17c5c0095fefb52ff0f7dc696f6d4cd0978b7b08b03e9768db0", + "benchmark/agent_validation/__main__.py": "00e80d3634fe279798b64066c486e9bad165f235c10d2b45646e9e29b32f8d5a", + "benchmark/agent_validation/challenge_functions.py": "3ad0e8ae25f569889e2978738716de50f6cc37b812b0f186c97de62ef7c15540", + "benchmark/agent_validation/contracts.py": "2fb3fa8af1a5ee3f5869791980bb63bbe3e811c721bd85227bfd04f5fbd122c9", + "benchmark/agent_validation/corpus.py": "40695857621b64985221408d93a260bd2c2adbd51233d673138faddc9c1f97ba", + "benchmark/agent_validation/declarations.py": "005a26a7315ae16d1b0dce4983b06377cf351043089bef3ff43b9d1da6034b1b", + "benchmark/agent_validation/journal.py": "486c8f85c86864f5e3d36acf5b5f5c70f752942b16d395ec51a87613e8671300", + "benchmark/agent_validation/mcp_attempt_recorder.py": "b34d8b5da45d3bce7d2144295cd3dfe176a2f626f19f083c10bf2484d85567da", + "benchmark/agent_validation/perturbations.py": "f092af99eff3f40a87c92ca99fb52e690c83839a41c649fad6a5b7af919150d3", + "benchmark/agent_validation/provenance.py": "9925b8ca8d51f191c0c9f75ef50c4f129173d7a89d00efa3afa44bf6376a5d6a", + "benchmark/agent_validation/scoring.py": "5fc0aecd11283f921c0511346c15d5f7a1fb9e892ef1562045e8d6eca87e4baa", + "benchmark/agent_validation/tasks.py": "7579bc6a4e775d1041e331143854dce4f8f8aa76780d9cd25bf3c30fc8a5a921", + "benchmark/annotated_validation.py": "1db72c805e35c6a1328cf1b890bc2af55cc39c159524961187b7f8d81d6820cc", + "benchmark/annotated_validation_20260915.md": "7e7c44be5477f8356b9b93b677270d32277150ec47490803a5d035015616595b", + "benchmark/bioformats_hcs_validation.py": "5114788070a955ae099a26d81127f3f637ac50a1724008e84a1701bfcba8838f", + "benchmark/cellprofiler_benchmark_cli.py": "39272e9d32cf758dfb6e2183f899562d6fab9af3a4d8f5fbc81a434d21f464a1", + "benchmark/cellprofiler_comparison.py": "5ca39ae6db8d43c7c293cd4c5a83508cde59b06e210d1633eaf7dc79aae7f3b2", + "benchmark/cellprofiler_export_equivalence.py": "21bbb55fae8f6ddcf8fdbacba54619b79b410cbf1afda05312949797f548b31d", + "benchmark/cellprofiler_pipelines/BBBC021_analysis.cppipe": "fdb0b710daa900db417b0032b00a18aabf664aedf95a939fc2ac60aaa9097062", + "benchmark/cellprofiler_pipelines/BBBC021_illum.cppipe": "09b73e9a7eca196d0d5056a1e9a39ea21c6b5dca1e2781f767e4b45aec3b45c2", + "benchmark/cellprofiler_pipelines/ExampleFly.cppipe": "8793ac307cda12e66b1d31928894ae2f82b94477b88ba7530d786f35e43bac17", + "benchmark/cellprofiler_pipelines/ExampleHuman.cppipe": "3fc7ace9921e5591f6455ee04ba4cff3754ea70a9f8035ce5cd8eeffe74bce3f", + "benchmark/cellprofiler_reference_exports.py": "604f9a95f94eeb10365437b875a0ff3d558dbb2fda13e7e951242d417a69b49c", + "benchmark/cellprofiler_semantics/__init__.py": "a201adc7d67fd72225be4b5ef9a662380b84d6bbf222a703e41d6b7b589f478c", + "benchmark/contracts/comparison_manifest.py": "17cd75bd2d4c39bd168bed65e94b705b1899e05c606a7e660e10148f7fd18cfd", + "benchmark/contracts/control.py": "0bce24c29ea9dfb7b50c88937b616118078505db6f497312fff87766397e5ce9", + "benchmark/contracts/dataset.py": "99b3bc0456918befd92d9ac65a61fe5315fbda8b688bbe5162b67aabf298bf6f", + "benchmark/contracts/manifest_acquisition.py": "8a09c47497c234fabe526114ba7ed5ea672e6e3dde3c2d8c3911b8a29656446e", + "benchmark/contracts/measured_run_receipt.py": "67c71873d050e05c0e4a1e231c46b700a765c12cade51269553cc7a5cb96989e", + "benchmark/contracts/metric.py": "cb7f9e7afc0b8c9eed8b9770266c4554e21b8f8bffcf9a612ba23c3dd2447cc0", + "benchmark/contracts/pipeline.py": "54857ee11404bdc510478e53873b359d05f4a1a103d915626c27acfb4884946c", + "benchmark/contracts/run_artifacts.py": "e11f0d5cf699529bf2356d43628e06394cdf702119a4d303640aaae783c86f32", + "benchmark/contracts/run_receipt.py": "1704e1ab47411d25d382b95871c96c1e60c94db14b8ffd55f4dc6c8a917758b9", + "benchmark/contracts/tool_adapter.py": "6ff5923c8f7ba171e525ad56029cb28daf989dd87006d01d1b5b5b2ee46a5a58", + "benchmark/contracts/validation.py": "f23637d184c8d9722a61dd4bd8c34d2d11dbabfd3227cf02b9636e29240cc286", + "benchmark/contracts/values.py": "5bd8863dc06d1f7220412cf8db46a8d3f5a15c6d71e33d37b30f6fcecafb3969", + "benchmark/control.py": "4706078a8fbeb516a52bc51600751ae86c39c3ef7e397a2f8cf13d49204db941", + "benchmark/control_service.py": "bf2b39696a49d8c87cf74d39770d63013972b9c8cf884863c467ccdf46eb12d3", + "benchmark/converter/__init__.py": "8f439af8eced6b234ff5501b22f7633ac781cfe427518df5c108846c8834f10b", + "benchmark/converter/compatibility_matrix.py": "ba1f09a2e44e38763a6e316de80f9bda4f82a488b88343505dd9dc3e4b327361", + "benchmark/converter/convert.py": "db93f95345a3d1519415c8016df6b16975872ffb91bc52fef5e2e70a8fe6d2f0", + "benchmark/converter/cppipe_corpus.py": "aa0ffd01ca4980117c3ee18e6a7d36c7e8bc6c88f9e19a53921aaa2278c3e2e1", + "benchmark/datasets/__init__.py": "e8fa7845da316edf641ad8cda3356c0ec8619f20161a7185d932a82c45fbea56", + "benchmark/datasets/acquire.py": "d1d7f66bd78a0a5b6dd5891e47e8a324121b064be77cdbd07a93b5cbf39f6632", + "benchmark/datasets/bioformats_hcs.py": "2d45347a8f84f6908539e8fde85f1890d9fdd3c1264d868c4f6f04741aab5963", + "benchmark/datasets/cache.py": "6c5b12280dcd7cfb41c54ac5f385c6b9936628ec0e59e7c169230a0903bf6bbc", + "benchmark/datasets/cppipe_case_catalog.py": "83bd92a621a386a4e3ead9b9649a74746d3cb90678dc8a9081e9fc7303577c12", + "benchmark/datasets/manifest.py": "f3ab9ca4152d54bb29a7659a96ecf5762c08844b0f0caaf0f491807c2d924802", + "benchmark/datasets/registry.py": "b8ce320322c5d15d210ed677b9ad622fa3bb3acc01924b30937fce36ef692778", + "benchmark/datasets/visible_source.py": "c412d522c4e2a4e820497952013d246ebde73167916175bce4d77e46bf541d2c", + "benchmark/demos/__init__.py": "572160cfa8694cc155ad375b2a3a593ad9b28dbf7c88e235426dd5417ac938dd", + "benchmark/demos/official30_lab_meeting.py": "45b9391e6e0d8561770d6e7fd3ff3e85db11f24dd5bedf643875d09a8d4bacfd", + "benchmark/file_digest.py": "c0628cda351b085ab2487eec761e42fa3e38e32169d1e412a3578e68958d14a8", + "benchmark/fragmented_roi_profile.py": "556fafcab934dded426c1a85427345c0478e9d1fdcb16e086e10d3d786bd8525", + "benchmark/manifests/README.md": "c9db6e2d207001d9a6315689ae874c7c0624077b570ca2b8179876f7ce6b9482", + "benchmark/manifests/annotated_validation_20260915_preparation.json": "5a52361e4856e52aa7f634ec6a0b26d0d835949c829f3b235efaa080ae659d9e", + "benchmark/manifests/cp_tutorial_translocation_start_axis1.json": "270a20636ce740c37f5cdbb27209774bc195cf479dd57b7016aa9ee2e4199f1c", + "benchmark/manifests/extra_provided_not_in_23_axis1.json": "97faf7af8082279c733ed5f77235356f9aaf2188c5dae9ab13179fb47aed3004", + "benchmark/manifests/official23_plus_extra6_axis1.json": "5affa65ff1ec582f7bda22f35c480fb9fcb8d75cd433796874281c5433181f34", + "benchmark/manifests/official23_plus_extra7_axis1.json": "971e1ccf2ffdbffee1c6d3ffd095aa456bf76a77a859f974bb5c5f8470778928", + "benchmark/manifests/official23_plus_monolayer.json": "19af816b2736ee6d4bc9a2650a461ade1db995b057e62062548056805b0c5a03", + "benchmark/manifests/official30_existing_image_refresh_20260914.json": "938167a89704e8a195bd8cbd69e23beb5e643894cad762cd7627e70c2bce4e61", + "benchmark/manifests/official30_portable_axis1.json": "4c302e136b427cb9968eef82d7ede4a6c5b65cbcb4f8e5490fd5125c2e7ab2a8", + "benchmark/manifests/official30_value_completion_20260914.json": "39dd742855c97e49eb653ef8d410f97fb421b993b5df6911585daca7fa39af1c", + "benchmark/matched_cellprofiler_batch.py": "101114f4be7e93bbcdac86f88f39a17ab5b39533a082cebb3f5759c0dd03f3b1", + "benchmark/mcp_extension.py": "14a03b06491b011eb4a965284267cf2b825f82bb3917510348d9d402d90f542b", + "benchmark/metrics/__init__.py": "3eaba4b2c099085ded379020a6a919e75fa25774982aeb0044fa897a3f3ec952", + "benchmark/metrics/memory.py": "bc049ff424564b876b82d79f5a34f49a3d5dc7f374804b23d53eed1dd729e25e", + "benchmark/metrics/time.py": "fb1a4facd5f7a93cefd43219bc7a884d9b8cdb334c4208f8f56f71c323bd38c6", + "benchmark/napari_roi_streaming.py": "8d94caaa494e5ab33b9acf7d653183c392c772d5a57bb7158bf5c7b39c8e8ba8", + "benchmark/native_batch_barrier.py": "74ac18df75dae90c702b0c3f8f0baa1703de20d2b257b01db8507f250ec40c4e", + "benchmark/native_cellprofiler_batch_worker.py": "b377740417fbb9b78839ec792b634246a168de16736224a5991e8fb1ae70be76", + "benchmark/native_refs/README.md": "00c40407653d3a00b47f9746c13dfc7859a06768c619ce5494648ef2359f8062", + "benchmark/native_refs/official30_existing_image_refresh_20260914/CellProfiler_tutorials_cp_tutorial_translocation_final_wells_include_first1/TranslocationData_cp_tutorial_translocation_final_native_cellprofiler/.cellprofiler_benchmark_reference.json": "930c22f3c57c3ea5d2c9e1e4bf37c33217fbb74f53b4e53809aefd58e83bd2de", + "benchmark/native_refs/official30_existing_image_refresh_20260914/CellProfiler_tutorials_cp_tutorial_translocation_final_wells_include_first1/TranslocationData_cp_tutorial_translocation_final_native_cellprofiler/BBBC013_A01_s1_w1_Overlay.tiff": "a8dd29f39f592308c65f5dd20e27fdcf56292fda62a0b09ed6b4a253f3a7429e", + "benchmark/native_refs/official30_existing_image_refresh_20260914/CellProfiler_tutorials_cp_tutorial_translocation_final_wells_include_first1/TranslocationData_cp_tutorial_translocation_final_native_cellprofiler/DefaultDB.db": "ad7882394007e7413189d8e659d1f69548befad832161d58574981f6208f3573", + "benchmark/native_refs/official30_existing_image_refresh_20260914/CellProfiler_tutorials_cp_tutorial_translocation_final_wells_include_first1/TranslocationData_cp_tutorial_translocation_final_native_cellprofiler/DefaultDB.properties": "817353550c5588decd2c07942a187463ef5a802643d7d3e42c45c59fb68cb299", + "benchmark/native_refs/official30_existing_image_refresh_20260914/ExampleIlluminationCorrection_ExampleIlluminationCorrection_Example1_AllMethod_wells_include_first1/images_a015597fb7a8_ExampleIlluminationCorrection_Example1_AllMethod_native_cellprofiler/.cellprofiler_benchmark_reference.json": "4b59286575280b4fb6d7d7da4aff827a29cbecf810c9d5480795f5bfe7b69517", + "benchmark/native_refs/official30_existing_image_refresh_20260914/ExampleIlluminationCorrection_ExampleIlluminationCorrection_Example1_AllMethod_wells_include_first1/images_a015597fb7a8_ExampleIlluminationCorrection_Example1_AllMethod_native_cellprofiler/Illum.npy": "2f8490c4a6a7301d569797a80e3f9f26581fc83cc267aa436e44dc2f06cc346a", + "benchmark/native_refs/official30_scoped_rows/CellProfiler4_benchmark_supplement_cp4_supplement_combine_objects_wells_include_first1/CombineObjects_f4072628fb1a_cp4_supplement_combine_objects_native_cellprofiler/.cellprofiler_benchmark_reference.json": "5adccc651a8610352acb88288c56f2d5de7845be1e0d9813cea1c76b6e87b03a", + "benchmark/native_refs/official30_scoped_rows/CellProfiler4_benchmark_supplement_cp4_supplement_combine_objects_wells_include_first1/CombineObjects_f4072628fb1a_cp4_supplement_combine_objects_native_cellprofiler/reference_labels__CombinedObjects.tiff": "f5a96f1e11f1c9a0a3a86388f100705d99765856bc668aba675c935563e32197", + "benchmark/native_refs/official30_scoped_rows/CellProfiler4_benchmark_supplement_cp4_supplement_combine_objects_wells_include_first1/native_cellprofiler_headless/CombineObjectsDemo.cppipe": "50e67bacad558da3652c27599bbaf2c35a52c974ea9e546b36ac07b014530503", + "benchmark/native_refs/official30_scoped_rows/CellProfiler_tutorials_cp_tutorial_3d_monolayer_samples_first2wells/images_cp_tutorial_3d_monolayer_native_cellprofiler/3d_monolayer_Cells.csv": "cc34681db8a66c38ca77bc47db496b26703f21e4d7c7628dd74e30c33250859f", + "benchmark/native_refs/official30_scoped_rows/CellProfiler_tutorials_cp_tutorial_3d_monolayer_samples_first2wells/images_cp_tutorial_3d_monolayer_native_cellprofiler/3d_monolayer_Experiment.csv": "06c1d8caf3de21a47d79da63fe835857555131e067f5db2d6986d7e0c577362e", + "benchmark/native_refs/official30_scoped_rows/CellProfiler_tutorials_cp_tutorial_3d_monolayer_samples_first2wells/images_cp_tutorial_3d_monolayer_native_cellprofiler/3d_monolayer_Image.csv": "4036d5e7a2699ce804b8bf5edcc5695dc8e79f5ac6c9c12818aa42be0ef6c24b", + "benchmark/native_refs/official30_scoped_rows/CellProfiler_tutorials_cp_tutorial_3d_monolayer_samples_first2wells/images_cp_tutorial_3d_monolayer_native_cellprofiler/3d_monolayer_Nuclei.csv": "440c33edc7e8cb5611910a835454db62390301a7af617a542349f60aece57561", + "benchmark/native_refs/official30_scoped_rows/CellProfiler_tutorials_cp_tutorial_3d_monolayer_samples_first2wells/images_cp_tutorial_3d_monolayer_native_cellprofiler/3d_monolayer_downsizedNuclei.csv": "2c66bc7b17de52147d5a875403f9a9746019ac61371c08157979044c6ed818dd", + "benchmark/native_refs/official30_scoped_rows/CellProfiler_tutorials_cp_tutorial_3d_monolayer_samples_first2wells/images_cp_tutorial_3d_monolayer_native_cellprofiler/3d_monolayer_erodedDownsizedNuclei.csv": "527a0cce497d2a618478be84d1a0bf174049f58aa2a666e37626a990fdca0116", + "benchmark/native_refs/official30_scoped_rows/CellProfiler_tutorials_cp_tutorial_3d_monolayer_samples_first2wells/images_cp_tutorial_3d_monolayer_native_cellprofiler/3d_monolayer_erodedResizedNuclei.csv": "66a58f78cab0cfdbe907468e8ba383fc59fab49025b84b589855bdfa04854609", + "benchmark/native_refs/official30_scoped_rows/CellProfiler_tutorials_cp_tutorial_3d_monolayer_samples_first2wells/images_cp_tutorial_3d_monolayer_native_cellprofiler/3d_monolayer_xy1_ch0_CellsLabels.tiff": "aaed9ed23179a162ee7f5a7e8d1d88f1fa342ca55172b7fccd4cbf67f7841d81", + "benchmark/native_refs/official30_scoped_rows/CellProfiler_tutorials_cp_tutorial_3d_monolayer_samples_first2wells/images_cp_tutorial_3d_monolayer_native_cellprofiler/3d_monolayer_xy1_ch2_NucleiLabels.tiff": "340bbd795541e4031749d1fff767fa4fcdcac10f5b97879056b25dac9fd7674b", + "benchmark/native_refs/official30_scoped_rows/CellProfiler_tutorials_cp_tutorial_3d_monolayer_samples_first2wells/native_cellprofiler_file_list.txt": "556169d5baf25f95b770d2b03ec431cc4217bf3f92008d4c0000b13154d3de5e", + "benchmark/native_refs/official30_scoped_rows/CellProfiler_tutorials_cp_tutorial_3d_monolayer_samples_first2wells/native_cellprofiler_headless/3d_monolayer_final.cppipe": "e31b37a86255d6d62c59d18573b6329513fe194d024421897819e63979c24e09", + "benchmark/native_refs/official30_scoped_rows/CellProfiler_tutorials_cp_tutorial_3d_monolayer_wells_include_first1/images_7a5a13509180_cp_tutorial_3d_monolayer_native_cellprofiler/.cellprofiler_benchmark_reference.json": "4b59286575280b4fb6d7d7da4aff827a29cbecf810c9d5480795f5bfe7b69517", + "benchmark/native_refs/official30_scoped_rows/CellProfiler_tutorials_cp_tutorial_3d_monolayer_wells_include_first1/images_7a5a13509180_cp_tutorial_3d_monolayer_native_cellprofiler/3d_monolayer_Cells.csv": "cc34681db8a66c38ca77bc47db496b26703f21e4d7c7628dd74e30c33250859f", + "benchmark/native_refs/official30_scoped_rows/CellProfiler_tutorials_cp_tutorial_3d_monolayer_wells_include_first1/images_7a5a13509180_cp_tutorial_3d_monolayer_native_cellprofiler/3d_monolayer_Experiment.csv": "1ea3d9b2a556509a56700516857787925f53ad8d51750da1178c15f42cd9a71e", + "benchmark/native_refs/official30_scoped_rows/CellProfiler_tutorials_cp_tutorial_3d_monolayer_wells_include_first1/images_7a5a13509180_cp_tutorial_3d_monolayer_native_cellprofiler/3d_monolayer_Image.csv": "9775dc08d51f1045b42becd671506138c0801db3528b65d250ce306e44e136bd", + "benchmark/native_refs/official30_scoped_rows/CellProfiler_tutorials_cp_tutorial_3d_monolayer_wells_include_first1/images_7a5a13509180_cp_tutorial_3d_monolayer_native_cellprofiler/3d_monolayer_Nuclei.csv": "440c33edc7e8cb5611910a835454db62390301a7af617a542349f60aece57561", + "benchmark/native_refs/official30_scoped_rows/CellProfiler_tutorials_cp_tutorial_3d_monolayer_wells_include_first1/images_7a5a13509180_cp_tutorial_3d_monolayer_native_cellprofiler/3d_monolayer_downsizedNuclei.csv": "2c66bc7b17de52147d5a875403f9a9746019ac61371c08157979044c6ed818dd", + "benchmark/native_refs/official30_scoped_rows/CellProfiler_tutorials_cp_tutorial_3d_monolayer_wells_include_first1/images_7a5a13509180_cp_tutorial_3d_monolayer_native_cellprofiler/3d_monolayer_erodedDownsizedNuclei.csv": "527a0cce497d2a618478be84d1a0bf174049f58aa2a666e37626a990fdca0116", + "benchmark/native_refs/official30_scoped_rows/CellProfiler_tutorials_cp_tutorial_3d_monolayer_wells_include_first1/images_7a5a13509180_cp_tutorial_3d_monolayer_native_cellprofiler/3d_monolayer_erodedResizedNuclei.csv": "66a58f78cab0cfdbe907468e8ba383fc59fab49025b84b589855bdfa04854609", + "benchmark/native_refs/official30_scoped_rows/CellProfiler_tutorials_cp_tutorial_3d_monolayer_wells_include_first1/images_7a5a13509180_cp_tutorial_3d_monolayer_native_cellprofiler/3d_monolayer_xy1_ch0_CellsLabels.tiff": "aaed9ed23179a162ee7f5a7e8d1d88f1fa342ca55172b7fccd4cbf67f7841d81", + "benchmark/native_refs/official30_scoped_rows/CellProfiler_tutorials_cp_tutorial_3d_monolayer_wells_include_first1/images_7a5a13509180_cp_tutorial_3d_monolayer_native_cellprofiler/3d_monolayer_xy1_ch2_NucleiLabels.tiff": "340bbd795541e4031749d1fff767fa4fcdcac10f5b97879056b25dac9fd7674b", + "benchmark/native_refs/official30_scoped_rows/CellProfiler_tutorials_cp_tutorial_3d_monolayer_wells_include_first1/native_cellprofiler_file_list.txt": "556169d5baf25f95b770d2b03ec431cc4217bf3f92008d4c0000b13154d3de5e", + "benchmark/native_refs/official30_scoped_rows/CellProfiler_tutorials_cp_tutorial_3d_monolayer_wells_include_first1/native_cellprofiler_headless/3d_monolayer_final.cppipe": "e31b37a86255d6d62c59d18573b6329513fe194d024421897819e63979c24e09", + "benchmark/native_refs/official30_scoped_rows/CellProfiler_tutorials_cp_tutorial_advanced_segmentation_final_wells_include_first1/BBBC022_20585_AE_cp_tutorial_advanced_segmentation_final_native_cellprofiler/.cellprofiler_benchmark_reference.json": "4b59286575280b4fb6d7d7da4aff827a29cbecf810c9d5480795f5bfe7b69517", + "benchmark/native_refs/official30_scoped_rows/CellProfiler_tutorials_cp_tutorial_advanced_segmentation_final_wells_include_first1/BBBC022_20585_AE_cp_tutorial_advanced_segmentation_final_native_cellprofiler/BBBC022.db": "471dd4621683a2b1bda1f712b4721f7d9a14dbd2ca94fbfd88222733faf58222", + "benchmark/native_refs/official30_scoped_rows/CellProfiler_tutorials_cp_tutorial_advanced_segmentation_final_wells_include_first1/BBBC022_20585_AE_cp_tutorial_advanced_segmentation_final_native_cellprofiler/BBBC022_Cells.properties": "64f308b9481641a9d23b63f8a7420dc8cd5cb260ffb784803c9501531339472b", + "benchmark/native_refs/official30_scoped_rows/CellProfiler_tutorials_cp_tutorial_advanced_segmentation_final_wells_include_first1/BBBC022_20585_AE_cp_tutorial_advanced_segmentation_final_native_cellprofiler/BBBC022_Cytoplasm.properties": "37eab4186b49c760c024559a630d7f0533be381f7bc26252482958d6983bd173", + "benchmark/native_refs/official30_scoped_rows/CellProfiler_tutorials_cp_tutorial_advanced_segmentation_final_wells_include_first1/BBBC022_20585_AE_cp_tutorial_advanced_segmentation_final_native_cellprofiler/BBBC022_Mitochondria.properties": "060c93a8c50e60516083186dfe4cdb2201e355bbd8799a1af55c74db4323533e", + "benchmark/native_refs/official30_scoped_rows/CellProfiler_tutorials_cp_tutorial_advanced_segmentation_final_wells_include_first1/BBBC022_20585_AE_cp_tutorial_advanced_segmentation_final_native_cellprofiler/BBBC022_MitochondriaChildObjects.properties": "3fafb9595c11405691680c4b645270f0d92cc9c5dc471d8a6a7fb7c064866ddb", + "benchmark/native_refs/official30_scoped_rows/CellProfiler_tutorials_cp_tutorial_advanced_segmentation_final_wells_include_first1/BBBC022_20585_AE_cp_tutorial_advanced_segmentation_final_native_cellprofiler/BBBC022_Nuclei.properties": "c53d1e71b1ba9a74730595a8d621cfc43b2f08c90912940b2e301ac336c08d11", + "benchmark/native_refs/official30_scoped_rows/CellProfiler_tutorials_cp_tutorial_advanced_segmentation_final_wells_include_first1/BBBC022_20585_AE_cp_tutorial_advanced_segmentation_final_native_cellprofiler/BBBC022_Nucleoli.properties": "634db019116ec9b9170962c8a09626eefa1b78f91d903267fc277a5e09999a08", + "benchmark/native_refs/official30_scoped_rows/CellProfiler_tutorials_cp_tutorial_advanced_segmentation_final_wells_include_first1/BBBC022_20585_AE_cp_tutorial_advanced_segmentation_final_native_cellprofiler/BBBC022_NucleoliChildObjects.properties": "96a5cff7af576f59d6f140a066928897552a3fbe7854f5a2bac9097a82f12c0c", + "benchmark/native_refs/official30_scoped_rows/CellProfiler_tutorials_cp_tutorial_advanced_segmentation_final_wells_include_first1/native_cellprofiler_headless/BBBC022_Analysis_Final.cppipe": "335b3fa5179860bfd898f09a42ed80388f8bd4bdc4b5bafa30ad769de734c35d", + "benchmark/native_refs/official30_scoped_rows/CellProfiler_tutorials_cp_tutorial_advanced_segmentation_final_wells_include_first1/native_cellprofiler_selected_source_workspace/_source/IllumER/20585_IllumER.npy": "45eda877b52af53e4ff71595751d5e35362ca01f930c0408174ab8337977686d", + "benchmark/native_refs/official30_scoped_rows/CellProfiler_tutorials_cp_tutorial_advanced_segmentation_final_wells_include_first1/native_cellprofiler_selected_source_workspace/_source/IllumHoechst/20585_IllumHoechst.npy": "3bb225213f036c701a8ad04e5233a11ae4acb2eae1f676fcd4391ce945d00200", + "benchmark/native_refs/official30_scoped_rows/CellProfiler_tutorials_cp_tutorial_advanced_segmentation_final_wells_include_first1/native_cellprofiler_selected_source_workspace/_source/IllumMito/20585_IllumMito.npy": "95803eb745543c0f9cd3291afbaca1ffa7d78d0e2a793d5efaac212b737bb918", + "benchmark/native_refs/official30_scoped_rows/CellProfiler_tutorials_cp_tutorial_advanced_segmentation_final_wells_include_first1/native_cellprofiler_selected_source_workspace/_source/IllumPh_golgi/20585_IllumPh_golgi.npy": "a6ee7d393822172428d686353e6c90779f1b3dbe4d32629666d6d1bf735459a1", + "benchmark/native_refs/official30_scoped_rows/CellProfiler_tutorials_cp_tutorial_advanced_segmentation_final_wells_include_first1/native_cellprofiler_selected_source_workspace/_source/IllumSyto/20585_IllumSyto.npy": "3450bf6a25718d45d163138c6774299ef8974e7c84b59dd1e7e6dcdddf7095b5", + "benchmark/native_refs/official30_scoped_rows/CellProfiler_tutorials_cp_tutorial_beginner_segmentation_final_wells_include_first1/images_Illum-corrected_8f3a144edf6a_cp_tutorial_beginner_segmentation_final_native_cellprofiler/.cellprofiler_benchmark_reference.json": "4b59286575280b4fb6d7d7da4aff827a29cbecf810c9d5480795f5bfe7b69517", + "benchmark/native_refs/official30_scoped_rows/CellProfiler_tutorials_cp_tutorial_beginner_segmentation_final_wells_include_first1/images_Illum-corrected_8f3a144edf6a_cp_tutorial_beginner_segmentation_final_native_cellprofiler/MyExpt_Cells.csv": "990c806a68d7f44addfc5294acd50bd42ff6cfcab23fb11b5c39e5f45f9be505", + "benchmark/native_refs/official30_scoped_rows/CellProfiler_tutorials_cp_tutorial_beginner_segmentation_final_wells_include_first1/images_Illum-corrected_8f3a144edf6a_cp_tutorial_beginner_segmentation_final_native_cellprofiler/MyExpt_Cytoplasm.csv": "f918da3280f8e88f70b048249ed10f9815ef04f5381fe0fe016cbc0ed0b19c2f", + "benchmark/native_refs/official30_scoped_rows/CellProfiler_tutorials_cp_tutorial_beginner_segmentation_final_wells_include_first1/images_Illum-corrected_8f3a144edf6a_cp_tutorial_beginner_segmentation_final_native_cellprofiler/MyExpt_Experiment.csv": "1bbfd0c3e6d91c8561fa13d02d1e9e1b09d4c0f366c8ed8b03456af9b01e7fad", + "benchmark/native_refs/official30_scoped_rows/CellProfiler_tutorials_cp_tutorial_beginner_segmentation_final_wells_include_first1/images_Illum-corrected_8f3a144edf6a_cp_tutorial_beginner_segmentation_final_native_cellprofiler/MyExpt_Image.csv": "4ca079358ad8bc84d8bf185be404ecb15f6c3395dbe99ead6e83e4a54206c8a9", + "benchmark/native_refs/official30_scoped_rows/CellProfiler_tutorials_cp_tutorial_beginner_segmentation_final_wells_include_first1/images_Illum-corrected_8f3a144edf6a_cp_tutorial_beginner_segmentation_final_native_cellprofiler/MyExpt_Nuclei.csv": "80496e920f2098aa181c8d6f7efd435c9b9da62cf28780d61e898fa899b62304", + "benchmark/native_refs/official30_scoped_rows/CellProfiler_tutorials_cp_tutorial_beginner_segmentation_final_wells_include_first1/images_Illum-corrected_8f3a144edf6a_cp_tutorial_beginner_segmentation_final_native_cellprofiler/MyExpt_Nucleoli.csv": "6c7ae52b3b3d3dbfa7cbbb8e088cf9cb2aa4d9c14c608867b8a18b29eb783f2a", + "benchmark/native_refs/official30_scoped_rows/CellProfiler_tutorials_cp_tutorial_beginner_segmentation_final_wells_include_first1/images_Illum-corrected_8f3a144edf6a_cp_tutorial_beginner_segmentation_final_native_cellprofiler/MyExpt_NucleoliChildObjects.csv": "bd75ae8a5ae880fa090956729f7826a6242164ab763172084309db29b01b5cb6", + "benchmark/native_refs/official30_scoped_rows/CellProfiler_tutorials_cp_tutorial_beginner_segmentation_final_wells_include_first1/images_Illum-corrected_8f3a144edf6a_cp_tutorial_beginner_segmentation_final_native_cellprofiler/overlay_images/plate1_A14_site1_Ch3_overlay.tiff": "05a85674095f244ab4d85aad6644e04420ac2e8394d01d781ec968ecb5ff59f1", + "benchmark/native_refs/official30_scoped_rows/CellProfiler_tutorials_cp_tutorial_beginner_segmentation_final_wells_include_first1/images_Illum-corrected_8f3a144edf6a_cp_tutorial_beginner_segmentation_final_native_cellprofiler/overlay_images/plate1_A14_site2_Ch3_overlay.tiff": "89888a6d23423bb99118578d423fb5efa13641c1346ddb09547792fd294d6981", + "benchmark/native_refs/official30_scoped_rows/CellProfiler_tutorials_cp_tutorial_beginner_segmentation_final_wells_include_first1/native_cellprofiler_file_list.txt": "8133ba17de0fd35b9a83ba859b9751904b4b58825c137d8575043cd14c16647b", + "benchmark/native_refs/official30_scoped_rows/CellProfiler_tutorials_cp_tutorial_beginner_segmentation_final_wells_include_first1/native_cellprofiler_headless/segmentation_final.cppipe": "f309b3e3065ac3dffe48b2fd4cbd5da7a1436297f9708c70383a9926748b1e89", + "benchmark/native_refs/official30_scoped_rows/CellProfiler_tutorials_cp_tutorial_pixel_based_classification_wells_include_first1/images_d8212f79a2a8_cp_tutorial_pixel_based_classification_native_cellprofiler/.cellprofiler_benchmark_reference.json": "4b59286575280b4fb6d7d7da4aff827a29cbecf810c9d5480795f5bfe7b69517", + "benchmark/native_refs/official30_scoped_rows/CellProfiler_tutorials_cp_tutorial_pixel_based_classification_wells_include_first1/images_d8212f79a2a8_cp_tutorial_pixel_based_classification_native_cellprofiler/cho01_outlines.png": "f79d304a78ee7d881c9e85eca53003e47812d4ce886f4014bfc7c1e7361ce96a", + "benchmark/native_refs/official30_scoped_rows/CellProfiler_tutorials_cp_tutorial_pixel_based_classification_wells_include_first1/images_d8212f79a2a8_cp_tutorial_pixel_based_classification_native_cellprofiler/cho_Cells.csv": "0d04a1adfec9141705ec49660f0e2ec07ae447be28fe86402b5f7c5861883709", + "benchmark/native_refs/official30_scoped_rows/CellProfiler_tutorials_cp_tutorial_pixel_based_classification_wells_include_first1/images_d8212f79a2a8_cp_tutorial_pixel_based_classification_native_cellprofiler/cho_Experiment.csv": "5165adae2b7ead2af3d78bb69ff056159a412dc39ea06ff28bbb56eafbab9e93", + "benchmark/native_refs/official30_scoped_rows/CellProfiler_tutorials_cp_tutorial_pixel_based_classification_wells_include_first1/images_d8212f79a2a8_cp_tutorial_pixel_based_classification_native_cellprofiler/cho_Image.csv": "eabd9cc9c661888ef7e6093ccb9a05cb936454dd0428fb5c95ead99371f8f4f1", + "benchmark/native_refs/official30_scoped_rows/CellProfiler_tutorials_cp_tutorial_pixel_based_classification_wells_include_first1/native_cellprofiler_file_list.txt": "e34bd9281ebffbcff1008132d11d6576cf13901ee324287ed988ba2752fc3f68", + "benchmark/native_refs/official30_scoped_rows/CellProfiler_tutorials_cp_tutorial_pixel_based_classification_wells_include_first1/native_cellprofiler_headless/pixel_based_classification_cho.cppipe": "acea8b966b03cba696d887f37cd28b1b5c4cec267937ef3a49892b0ab5aeead3", + "benchmark/native_refs/official30_scoped_rows/CellProfiler_tutorials_cp_tutorial_quality_control_wells_include_first1/BBBC022_20585_AE_9fb2a83e083c_cp_tutorial_quality_control_native_cellprofiler/.cellprofiler_benchmark_reference.json": "4b59286575280b4fb6d7d7da4aff827a29cbecf810c9d5480795f5bfe7b69517", + "benchmark/native_refs/official30_scoped_rows/CellProfiler_tutorials_cp_tutorial_quality_control_wells_include_first1/BBBC022_20585_AE_9fb2a83e083c_cp_tutorial_quality_control_native_cellprofiler/BBBC022QC.db": "644858dc9862358514b612ba557c9a00234681c910ab4c56f1760630d6bb7f9d", + "benchmark/native_refs/official30_scoped_rows/CellProfiler_tutorials_cp_tutorial_quality_control_wells_include_first1/BBBC022_20585_AE_9fb2a83e083c_cp_tutorial_quality_control_native_cellprofiler/BBBC022QC_BBBC022QC.properties": "5f86bbb4cc181ad933097a5c83abdf2afcd12988ac4b035c57dd39438a37bb1a", + "benchmark/native_refs/official30_scoped_rows/CellProfiler_tutorials_cp_tutorial_quality_control_wells_include_first1/BBBC022_20585_AE_9fb2a83e083c_cp_tutorial_quality_control_native_cellprofiler/BBBC022QC_BBBC022QC.workspace": "884f14365ed643c8dd7050ea77e416a1b7253dca83ff11d2e01aa54a8e07bdc6", + "benchmark/native_refs/official30_scoped_rows/CellProfiler_tutorials_cp_tutorial_quality_control_wells_include_first1/native_cellprofiler_file_list.txt": "d83754368f8b7ae51c8bd367d4714086c398cd5fda8150bfd6de34e73f8e81cc", + "benchmark/native_refs/official30_scoped_rows/CellProfiler_tutorials_cp_tutorial_quality_control_wells_include_first1/native_cellprofiler_headless/BBBC022_QC.cppipe": "8b931f7c0fa2c149af539174bf909477f2c33a06ee1c418bea7d13c729f3ff59", + "benchmark/native_refs/official30_scoped_rows/CellProfiler_tutorials_cp_tutorial_translocation_final_wells_include_first1/TranslocationData_1593ea523b1e_cp_tutorial_translocation_final_native_cellprofiler/.cellprofiler_benchmark_reference.json": "4b59286575280b4fb6d7d7da4aff827a29cbecf810c9d5480795f5bfe7b69517", + "benchmark/native_refs/official30_scoped_rows/CellProfiler_tutorials_cp_tutorial_translocation_final_wells_include_first1/TranslocationData_1593ea523b1e_cp_tutorial_translocation_final_native_cellprofiler/BBBC013_A01_s1_w1_Overlay.tiff": "a8dd29f39f592308c65f5dd20e27fdcf56292fda62a0b09ed6b4a253f3a7429e", + "benchmark/native_refs/official30_scoped_rows/CellProfiler_tutorials_cp_tutorial_translocation_final_wells_include_first1/TranslocationData_1593ea523b1e_cp_tutorial_translocation_final_native_cellprofiler/DefaultDB.db": "6495268ebcd4f7daaaccc34d6707e32578766220f81e9925397a2c3c5ffe1a74", + "benchmark/native_refs/official30_scoped_rows/CellProfiler_tutorials_cp_tutorial_translocation_final_wells_include_first1/TranslocationData_1593ea523b1e_cp_tutorial_translocation_final_native_cellprofiler/DefaultDB.properties": "6ac2716fbd152e7837e0690ab9cc2341ad537c6e09af136ddcab60e2114e0161", + "benchmark/native_refs/official30_scoped_rows/CellProfiler_tutorials_cp_tutorial_translocation_final_wells_include_first1/native_cellprofiler_headless/Translocation_final.cppipe": "6d647905484274fab9aeb8bdcc082dbca46a715bc8a45e91e7bfc7bd0177b163", + "benchmark/native_refs/official30_scoped_rows/CellProfiler_tutorials_cp_tutorial_translocation_start_wells_include_first1/TranslocationData_cp_tutorial_translocation_start_native_cellprofiler/.cellprofiler_benchmark_reference.json": "e5ea45cd8328a430dc4e515c23242dbd2d0970a74493271aacca076278238c8b", + "benchmark/native_refs/official30_scoped_rows/CellProfiler_tutorials_cp_tutorial_translocation_start_wells_include_first1/TranslocationData_cp_tutorial_translocation_start_native_cellprofiler/reference_labels__Nuclei.tiff": "eaa520c6b780dcf61899b0018ae4f1e610b3cdcd9048cd3ec1202669c03ee6e2", + "benchmark/native_refs/official30_scoped_rows/CellProfiler_tutorials_cp_tutorial_translocation_start_wells_include_first1/native_cellprofiler_headless/Translocation_start.cppipe": "19025441307b218f0c2e7023d9cf34ff7016c4ca1cd3356b09586b69034ad2e3", + "benchmark/native_refs/official30_scoped_rows/ExampleColocalization_ExampleColocalization_wells_include_first1/images_48d92a72301c_ExampleColocalization_native_cellprofiler/.cellprofiler_benchmark_reference.json": "4b59286575280b4fb6d7d7da4aff827a29cbecf810c9d5480795f5bfe7b69517", + "benchmark/native_refs/official30_scoped_rows/ExampleColocalization_ExampleColocalization_wells_include_first1/images_48d92a72301c_ExampleColocalization_native_cellprofiler/Image.csv": "5ed9d8130a78f5a03b3823a2e207c74187152c699c83c2dc19ded58d03bfc874", + "benchmark/native_refs/official30_scoped_rows/ExampleColocalization_ExampleColocalization_wells_include_first1/native_cellprofiler_file_list.txt": "22db458de69d10ac4b82c148fd44b96ea72ece88e05e378fe588f0178f708196", + "benchmark/native_refs/official30_scoped_rows/ExampleColocalization_ExampleColocalization_wells_include_first1/native_cellprofiler_headless/ExampleColocalization.cppipe": "839bb2b5efb5b5035c69231ab49be696772017eb2f629a6545d0c7eb9fd38b28", + "benchmark/native_refs/official30_scoped_rows/ExampleCometAssay_ExampleCometAssay_wells_include_first1/images_3112abca6fed_ExampleCometAssay_native_cellprofiler/.cellprofiler_benchmark_reference.json": "4b59286575280b4fb6d7d7da4aff827a29cbecf810c9d5480795f5bfe7b69517", + "benchmark/native_refs/official30_scoped_rows/ExampleCometAssay_ExampleCometAssay_wells_include_first1/images_3112abca6fed_ExampleCometAssay_native_cellprofiler/Comet.csv": "bf3d9b0365d9157e60dfed4c1473b021f69810f4c7592d9dfe7a8b2bd00add6b", + "benchmark/native_refs/official30_scoped_rows/ExampleCometAssay_ExampleCometAssay_wells_include_first1/images_3112abca6fed_ExampleCometAssay_native_cellprofiler/CometHead.csv": "a3505fe5b510a9ad92eb5c58e9ea8a71b17c2f122f272c8649167afcd47ea9a5", + "benchmark/native_refs/official30_scoped_rows/ExampleCometAssay_ExampleCometAssay_wells_include_first1/images_3112abca6fed_ExampleCometAssay_native_cellprofiler/CometTail.csv": "fa3e46fbd2d4272932e236e30a331420443a92368bda32ed00682af6d86cac2c", + "benchmark/native_refs/official30_scoped_rows/ExampleCometAssay_ExampleCometAssay_wells_include_first1/images_3112abca6fed_ExampleCometAssay_native_cellprofiler/CometTails_CometHeadOutline.png": "6c37dc5412968ba29393ab57de0f390a933c0e7cb9df9ec930338de2b34c3684", + "benchmark/native_refs/official30_scoped_rows/ExampleCometAssay_ExampleCometAssay_wells_include_first1/images_3112abca6fed_ExampleCometAssay_native_cellprofiler/Experiment.csv": "9dede520618c58c6b21a2748572ba4f3b230d7ef033535f190fca23f3a95e39a", + "benchmark/native_refs/official30_scoped_rows/ExampleCometAssay_ExampleCometAssay_wells_include_first1/images_3112abca6fed_ExampleCometAssay_native_cellprofiler/Image.csv": "2b9f99f81365c7cc4e7d0b7a702af9370dc4a705a7487054f665936079a11358", + "benchmark/native_refs/official30_scoped_rows/ExampleCometAssay_ExampleCometAssay_wells_include_first1/images_3112abca6fed_ExampleCometAssay_native_cellprofiler/NoTails_CometHeadOutline.png": "c5bd0b0a6bddd22be27240f9d85a6243cc28dc204a7a900d3d698bc89219f03d", + "benchmark/native_refs/official30_scoped_rows/ExampleCometAssay_ExampleCometAssay_wells_include_first1/native_cellprofiler_file_list.txt": "5af4f1dfa994676acef7c7375e7e4db4608cc7ba0cb33434d6a5cd966100a47f", + "benchmark/native_refs/official30_scoped_rows/ExampleCometAssay_ExampleCometAssay_wells_include_first1/native_cellprofiler_headless/ExampleCometAssay.cppipe": "daec62eb90d9457a240bd28dcb3a1002b480db366a5d6aa849a8813f1073f8b6", + "benchmark/native_refs/official30_scoped_rows/ExampleFly_ExampleFlyURL_wells_include_first1/images_2cc1c937754b_ExampleFlyURL_native_cellprofiler/.cellprofiler_benchmark_reference.json": "4b59286575280b4fb6d7d7da4aff827a29cbecf810c9d5480795f5bfe7b69517", + "benchmark/native_refs/official30_scoped_rows/ExampleFly_ExampleFlyURL_wells_include_first1/images_2cc1c937754b_ExampleFlyURL_native_cellprofiler/Cells.csv": "17807e7bd065a66116c99ed9503ec2106c8efdb79ade8a343c6eeb1d4e2419f7", + "benchmark/native_refs/official30_scoped_rows/ExampleFly_ExampleFlyURL_wells_include_first1/images_2cc1c937754b_ExampleFlyURL_native_cellprofiler/CroppedFlyImage0001.tiff": "0f3ae4de1252127bc433873df236cab6dba2b1e39cd24621feb27a61b1d1f257", + "benchmark/native_refs/official30_scoped_rows/ExampleFly_ExampleFlyURL_wells_include_first1/images_2cc1c937754b_ExampleFlyURL_native_cellprofiler/CroppedFlyImage0002.tiff": "0bc3a70d3ec2911d5f6f2517f30856a82c48830c03c2362d5f16df13333c277e", + "benchmark/native_refs/official30_scoped_rows/ExampleFly_ExampleFlyURL_wells_include_first1/images_2cc1c937754b_ExampleFlyURL_native_cellprofiler/CroppedFlyImage0003.tiff": "a52eaa99f86447e92b5c3351fe00af600888c82d137962430d55e741047a1e42", + "benchmark/native_refs/official30_scoped_rows/ExampleFly_ExampleFlyURL_wells_include_first1/images_2cc1c937754b_ExampleFlyURL_native_cellprofiler/Cytoplasm.csv": "421ec8602ceb55446d3360bd61aa272af8954327f0b660cca15512a747018d80", + "benchmark/native_refs/official30_scoped_rows/ExampleFly_ExampleFlyURL_wells_include_first1/images_2cc1c937754b_ExampleFlyURL_native_cellprofiler/Image.csv": "abf8cd393bf12fa90174bc6715fb6b759143bd48a9f7247e3f78dd7878982999", + "benchmark/native_refs/official30_scoped_rows/ExampleFly_ExampleFlyURL_wells_include_first1/images_2cc1c937754b_ExampleFlyURL_native_cellprofiler/Nuclei.csv": "da0c217235d10ff3a28314041a70349c2ab56606f3b34fff276ff67d76d7598f", + "benchmark/native_refs/official30_scoped_rows/ExampleFly_ExampleFlyURL_wells_include_first1/native_cellprofiler_headless/ExampleFlyURL.cppipe": "cc5485857e4392c91736c9f38b81f1dd04295f8d676d524062fa65136a54a2d6", + "benchmark/native_refs/official30_scoped_rows/ExampleFly_ExampleFly_wells_include_first1/images_2cc1c937754b_ExampleFly_native_cellprofiler/.cellprofiler_benchmark_reference.json": "4b59286575280b4fb6d7d7da4aff827a29cbecf810c9d5480795f5bfe7b69517", + "benchmark/native_refs/official30_scoped_rows/ExampleFly_ExampleFly_wells_include_first1/images_2cc1c937754b_ExampleFly_native_cellprofiler/01_POS002_DRGB.tiff": "0f3ae4de1252127bc433873df236cab6dba2b1e39cd24621feb27a61b1d1f257", + "benchmark/native_refs/official30_scoped_rows/ExampleFly_ExampleFly_wells_include_first1/images_2cc1c937754b_ExampleFly_native_cellprofiler/01_POS076_DRGB.tiff": "0bc3a70d3ec2911d5f6f2517f30856a82c48830c03c2362d5f16df13333c277e", + "benchmark/native_refs/official30_scoped_rows/ExampleFly_ExampleFly_wells_include_first1/images_2cc1c937754b_ExampleFly_native_cellprofiler/01_POS218_DRGB.tiff": "a52eaa99f86447e92b5c3351fe00af600888c82d137962430d55e741047a1e42", + "benchmark/native_refs/official30_scoped_rows/ExampleFly_ExampleFly_wells_include_first1/images_2cc1c937754b_ExampleFly_native_cellprofiler/Cells.csv": "a3e229c264bc943aa298de966c101983d4ca3d7e75c9df947311d6656f38021e", + "benchmark/native_refs/official30_scoped_rows/ExampleFly_ExampleFly_wells_include_first1/images_2cc1c937754b_ExampleFly_native_cellprofiler/Cytoplasm.csv": "71120635ce6af4b40f7629a28ee18dfb605b453b57ba24c50af1b659dd160ee9", + "benchmark/native_refs/official30_scoped_rows/ExampleFly_ExampleFly_wells_include_first1/images_2cc1c937754b_ExampleFly_native_cellprofiler/Image.csv": "719bba516b4ec6dc19c97f022d51aecc36dd1f8c1d6df9368577bbb39c950190", + "benchmark/native_refs/official30_scoped_rows/ExampleFly_ExampleFly_wells_include_first1/images_2cc1c937754b_ExampleFly_native_cellprofiler/Nuclei.csv": "51ab042002e91f581ce238fd50f43f8bfa737bb6373c9c5661a67964da919848", + "benchmark/native_refs/official30_scoped_rows/ExampleFly_ExampleFly_wells_include_first1/native_cellprofiler_file_list.txt": "4e4293727a6ee67d4efca00cd5b456727d8faa7b5048c06ba9fff4c82173c1e3", + "benchmark/native_refs/official30_scoped_rows/ExampleFly_ExampleFly_wells_include_first1/native_cellprofiler_headless/ExampleFly.cppipe": "85c799ccbf2a6dd92185b8902da24229a0ca896c51dc7a83fcb124aae47c644a", + "benchmark/native_refs/official30_scoped_rows/ExampleHuman_ExampleHuman_wells_include_first1/images_95e1f0d3695a_ExampleHuman_native_cellprofiler/.cellprofiler_benchmark_reference.json": "c0f6eed26fd477ab9f98af2f19604f1927ce44a40985bdb79bb53b454936fbbc", + "benchmark/native_refs/official30_scoped_rows/ExampleHuman_ExampleHuman_wells_include_first1/images_95e1f0d3695a_ExampleHuman_native_cellprofiler/AS_09125_050116030001_D03f00d0_Overlay.png": "7ab7c2ec53beca87eda3a911213884c5002bf8b456e770304ee88b3f146ba5d0", + "benchmark/native_refs/official30_scoped_rows/ExampleHuman_ExampleHuman_wells_include_first1/images_95e1f0d3695a_ExampleHuman_native_cellprofiler/Cells.csv": "878e54e6c3759b1ce1c12e655d1482eae964d73f5d84b30d870b26d8724495c7", + "benchmark/native_refs/official30_scoped_rows/ExampleHuman_ExampleHuman_wells_include_first1/images_95e1f0d3695a_ExampleHuman_native_cellprofiler/Cytoplasm.csv": "4698593b4ff357656a74385d9f9ffc636bbf0754dc7e5c0ddda44f6d6b3d4ae6", + "benchmark/native_refs/official30_scoped_rows/ExampleHuman_ExampleHuman_wells_include_first1/images_95e1f0d3695a_ExampleHuman_native_cellprofiler/Experiment.csv": "0ef8436b70da872826c39e47c162b490a12d2a9ff0ca1f081361cc38d3107e99", + "benchmark/native_refs/official30_scoped_rows/ExampleHuman_ExampleHuman_wells_include_first1/images_95e1f0d3695a_ExampleHuman_native_cellprofiler/Image.csv": "1be263c6192d6a191884f27a60340a6d578e8ae39d5f740c999fedbcc6820073", + "benchmark/native_refs/official30_scoped_rows/ExampleHuman_ExampleHuman_wells_include_first1/images_95e1f0d3695a_ExampleHuman_native_cellprofiler/Nuclei.csv": "be557c8bedbe19c5d59e083e92f81b526d9ca58098a0568af02950495dc9288c", + "benchmark/native_refs/official30_scoped_rows/ExampleHuman_ExampleHuman_wells_include_first1/images_95e1f0d3695a_ExampleHuman_native_cellprofiler/PH3.csv": "7112907105b44e061918a6581238b0f3199dfabe0faf38e313b45e0b6379ec78", + "benchmark/native_refs/official30_scoped_rows/ExampleHuman_ExampleHuman_wells_include_first1/native_cellprofiler_file_list.txt": "dfeb6768ac6f3608707a401a8644c268d14ea9cf2e565d1743d69643c24853a2", + "benchmark/native_refs/official30_scoped_rows/ExampleHuman_ExampleHuman_wells_include_first1/native_cellprofiler_headless/ExampleHuman.cppipe": "e3c567abdab72455674521234f9183a769c8365b1bbb969312d95cf7482c73bd", + "benchmark/native_refs/official30_scoped_rows/ExampleIlluminationCorrection_ExampleIlluminationCorrection_Example1_AllMethod_wells_include_first1/images_a015597fb7a8_ExampleIlluminationCorrection_Example1_AllMethod_native_cellprofiler/.cellprofiler_benchmark_reference.json": "4b59286575280b4fb6d7d7da4aff827a29cbecf810c9d5480795f5bfe7b69517", + "benchmark/native_refs/official30_scoped_rows/ExampleIlluminationCorrection_ExampleIlluminationCorrection_Example1_AllMethod_wells_include_first1/images_a015597fb7a8_ExampleIlluminationCorrection_Example1_AllMethod_native_cellprofiler/Illum.npy": "2f8490c4a6a7301d569797a80e3f9f26581fc83cc267aa436e44dc2f06cc346a", + "benchmark/native_refs/official30_scoped_rows/ExampleIlluminationCorrection_ExampleIlluminationCorrection_Example1_AllMethod_wells_include_first1/native_cellprofiler_file_list.txt": "9793c1df10fad958514cc6604e0edde27dfb152f8654e9414e3729bd19af61a1", + "benchmark/native_refs/official30_scoped_rows/ExampleIlluminationCorrection_ExampleIlluminationCorrection_Example1_AllMethod_wells_include_first1/native_cellprofiler_headless/ExampleIlluminationCorrection_Example1_AllMethod.cppipe": "e76125ee2402879bf0610135ea02c1bc065120c074d404b6d955fa12523fbb02", + "benchmark/native_refs/official30_scoped_rows/ExampleIlluminationCorrection_ExampleIlluminationCorrection_Example1_EachMethod_wells_include_first1/images_ExampleIlluminationCorrection_Example1_EachMethod_native_cellprofiler/.cellprofiler_benchmark_reference.json": "331429c61ec577b7baec0beb6cc913cd4b6575b323a02a64aa00693918941194", + "benchmark/native_refs/official30_scoped_rows/ExampleIlluminationCorrection_ExampleIlluminationCorrection_Example1_EachMethod_wells_include_first1/images_ExampleIlluminationCorrection_Example1_EachMethod_native_cellprofiler/reference_image__CorrGreen.npy": "3c17148f0fad16738a23af55ac4e41692e6c2906808a7d83823331702b1b4f46", + "benchmark/native_refs/official30_scoped_rows/ExampleIlluminationCorrection_ExampleIlluminationCorrection_Example1_EachMethod_wells_include_first1/native_cellprofiler_file_list.txt": "730871fddd9fd941ae38a6c34109f9818c219179599b65d686c92f7963d06d0f", + "benchmark/native_refs/official30_scoped_rows/ExampleIlluminationCorrection_ExampleIlluminationCorrection_Example1_EachMethod_wells_include_first1/native_cellprofiler_headless/ExampleIlluminationCorrection_Example1_EachMethod.cppipe": "ae7ae773b1479b18b08606c9cd7a5106c5ebba78f58f3ccbd27bc28f684d65b2", + "benchmark/native_refs/official30_scoped_rows/ExampleIlluminationCorrection_ExampleIlluminationCorrection_Example2_wells_include_first1/images_ExampleIlluminationCorrection_Example2_native_cellprofiler/.cellprofiler_benchmark_reference.json": "dd475748fcbfd645efef9e29f6a856e1b68096344ab4614dae2ff597523e95ca", + "benchmark/native_refs/official30_scoped_rows/ExampleIlluminationCorrection_ExampleIlluminationCorrection_Example2_wells_include_first1/images_ExampleIlluminationCorrection_Example2_native_cellprofiler/reference_labels__LargeBlockCorrectedNuclei.tiff": "f1bbed3348ce75d8d4158cad37c08ae4ab30d9e0a5dfbb9e259b906311811e45", + "benchmark/native_refs/official30_scoped_rows/ExampleIlluminationCorrection_ExampleIlluminationCorrection_Example2_wells_include_first1/images_ExampleIlluminationCorrection_Example2_native_cellprofiler/reference_labels__SmallBlockCorrectedNuclei.tiff": "d31aa4bc3e9782e646820b5f3bef6f91f4fbf78bf8ee46b5260cde78e558f700", + "benchmark/native_refs/official30_scoped_rows/ExampleIlluminationCorrection_ExampleIlluminationCorrection_Example2_wells_include_first1/images_ExampleIlluminationCorrection_Example2_native_cellprofiler/reference_labels__UncorrectedNuclei.tiff": "2f54cba8f1482ab54e8a21f71fb2a912ea8a260f8dae2bb5bccfb94994da5a84", + "benchmark/native_refs/official30_scoped_rows/ExampleIlluminationCorrection_ExampleIlluminationCorrection_Example2_wells_include_first1/native_cellprofiler_file_list.txt": "6cdd305e931eab9d08f3020e7417c974c58a57b13128e515a7ee03096bb835aa", + "benchmark/native_refs/official30_scoped_rows/ExampleIlluminationCorrection_ExampleIlluminationCorrection_Example2_wells_include_first1/native_cellprofiler_headless/ExampleIlluminationCorrection_Example2.cppipe": "b6170bcb31668b082deb2fb9be285d0019ba7137a691ce80dc34a141744b9e97", + "benchmark/native_refs/official30_scoped_rows/ExampleIlluminationCorrection_ExampleIlluminationCorrection_Example3_wells_include_first1/images_ExampleIlluminationCorrection_Example3_native_cellprofiler/.cellprofiler_benchmark_reference.json": "37e74838f03ca2fcb0b941ad62f2bcf6ebc4082651dd04c577d7e0b760a03a79", + "benchmark/native_refs/official30_scoped_rows/ExampleIlluminationCorrection_ExampleIlluminationCorrection_Example3_wells_include_first1/images_ExampleIlluminationCorrection_Example3_native_cellprofiler/reference_image__ConvexHullCorrWorm.npy": "9ba1259e4ca007c06f14be6946e32a86307ec2dfb9952b73fa2cc253ccae8b3a", + "benchmark/native_refs/official30_scoped_rows/ExampleIlluminationCorrection_ExampleIlluminationCorrection_Example3_wells_include_first1/images_ExampleIlluminationCorrection_Example3_native_cellprofiler/reference_image__PolynomialCorrected.npy": "588e6f9951aa7ad220678dbb0053e98fb6d324e71aab089d1d828d891ee32f54", + "benchmark/native_refs/official30_scoped_rows/ExampleIlluminationCorrection_ExampleIlluminationCorrection_Example3_wells_include_first1/native_cellprofiler_file_list.txt": "84cdf25570fc4ed34acee7d8b83a456d2dbe7ba5f87d8c2d59f52501e2ff8e1b", + "benchmark/native_refs/official30_scoped_rows/ExampleIlluminationCorrection_ExampleIlluminationCorrection_Example3_wells_include_first1/native_cellprofiler_headless/ExampleIlluminationCorrection_Example3.cppipe": "64c5ad5f41c0c843506c288ffc61b2aed9391e3bc914f770633e57ee5bbada12", + "benchmark/native_refs/official30_scoped_rows/ExampleImagingFlowCytometryObjectsInGrid_ExampleImagingFlowCytometryObjectsInGrid_wells_include_first1/images_febbfcc5c842_ExampleImagingFlowCytometryObjectsInGrid_native_cellprofiler/.cellprofiler_benchmark_reference.json": "c0f6eed26fd477ab9f98af2f19604f1927ce44a40985bdb79bb53b454936fbbc", + "benchmark/native_refs/official30_scoped_rows/ExampleImagingFlowCytometryObjectsInGrid_ExampleImagingFlowCytometryObjectsInGrid_wells_include_first1/images_febbfcc5c842_ExampleImagingFlowCytometryObjectsInGrid_native_cellprofiler/BF_cells_on_grid.csv": "23ca5a36a568fc87405888b130328aeb45e9ecf2853516d35493f8b3b4d769d1", + "benchmark/native_refs/official30_scoped_rows/ExampleImagingFlowCytometryObjectsInGrid_ExampleImagingFlowCytometryObjectsInGrid_wells_include_first1/native_cellprofiler_file_list.txt": "0413a52c486a36ca8534e50a246952c35b44b640c722b00189bd60f2fa575541", + "benchmark/native_refs/official30_scoped_rows/ExampleImagingFlowCytometryObjectsInGrid_ExampleImagingFlowCytometryObjectsInGrid_wells_include_first1/native_cellprofiler_headless/ExampleImagingFlowCytometryObjectsInGrid.cppipe": "391c846497690c51db29ce728383fdf7327aecef9922e9069414ab28c7b9577c", + "benchmark/native_refs/official30_scoped_rows/ExampleNeighbors_ExampleNeighbors_wells_include_first1/images_752e3d1a4a72_ExampleNeighbors_native_cellprofiler/.cellprofiler_benchmark_reference.json": "4b59286575280b4fb6d7d7da4aff827a29cbecf810c9d5480795f5bfe7b69517", + "benchmark/native_refs/official30_scoped_rows/ExampleNeighbors_ExampleNeighbors_wells_include_first1/images_752e3d1a4a72_ExampleNeighbors_native_cellprofiler/Cells.csv": "3ac4cbfaaf7d4cdbe4ea9f0624707ca1776b2b0a65b8c3dfd30cfb3e3a1c908f", + "benchmark/native_refs/official30_scoped_rows/ExampleNeighbors_ExampleNeighbors_wells_include_first1/images_752e3d1a4a72_ExampleNeighbors_native_cellprofiler/Clones1_ColorNeighbors.png": "9c930b44559a4c8b343652b52c42602348b8c9b48d0608f715fce3285198d18b", + "benchmark/native_refs/official30_scoped_rows/ExampleNeighbors_ExampleNeighbors_wells_include_first1/images_752e3d1a4a72_ExampleNeighbors_native_cellprofiler/Clones1_InvertedRed.png": "81efde4802d5cfa71292ffdf78567535b8761ed9dffd10d849b95c9cb2b37b72", + "benchmark/native_refs/official30_scoped_rows/ExampleNeighbors_ExampleNeighbors_wells_include_first1/images_752e3d1a4a72_ExampleNeighbors_native_cellprofiler/Image.csv": "74dacf6d115a893193a0cb890ce679944355519813800295a4662d5a47f01f14", + "benchmark/native_refs/official30_scoped_rows/ExampleNeighbors_ExampleNeighbors_wells_include_first1/native_cellprofiler_file_list.txt": "2a80e5949bc283999e14c575276ffe817b03dab061abf3cf99be28fe5953a7b6", + "benchmark/native_refs/official30_scoped_rows/ExampleNeighbors_ExampleNeighbors_wells_include_first1/native_cellprofiler_headless/ExampleNeighbors.cppipe": "53bd447b6bb96fb63588590838e0b74d9b3514615773b88c0e00437d15f82c64", + "benchmark/native_refs/official30_scoped_rows/ExamplePercentPositive_ExamplePercentPositive_wells_include_first1/images_386eec9eae5f_ExamplePercentPositive_native_cellprofiler/.cellprofiler_benchmark_reference.json": "4b59286575280b4fb6d7d7da4aff827a29cbecf810c9d5480795f5bfe7b69517", + "benchmark/native_refs/official30_scoped_rows/ExamplePercentPositive_ExamplePercentPositive_wells_include_first1/images_386eec9eae5f_ExamplePercentPositive_native_cellprofiler/Experiment.csv": "2a88f16ce5fe41011936191d59c52b23833d3167882abf78209919737eccafac", + "benchmark/native_refs/official30_scoped_rows/ExamplePercentPositive_ExamplePercentPositive_wells_include_first1/images_386eec9eae5f_ExamplePercentPositive_native_cellprofiler/Image.csv": "61318dfb76b44a9665af2a9bc9b7f12c5f7065d04f4dc8f1f769e03b38ce9f41", + "benchmark/native_refs/official30_scoped_rows/ExamplePercentPositive_ExamplePercentPositive_wells_include_first1/images_386eec9eae5f_ExamplePercentPositive_native_cellprofiler/Nuclei.csv": "8784edd1a232864fe18a71bd78eca1214e63fa8ca4b8789926605e0e75cbd7c7", + "benchmark/native_refs/official30_scoped_rows/ExamplePercentPositive_ExamplePercentPositive_wells_include_first1/images_386eec9eae5f_ExamplePercentPositive_native_cellprofiler/PH3.csv": "2396591af9c4bdd277060be915bf096797eb0820887817645cdc60aadbe6bd21", + "benchmark/native_refs/official30_scoped_rows/ExamplePercentPositive_ExamplePercentPositive_wells_include_first1/images_386eec9eae5f_ExamplePercentPositive_native_cellprofiler/PH3PosNuclei.csv": "edb4ffb53dbbb581dacc22bc36eaa1c8da55005972d1d4c923960f6db56754f7", + "benchmark/native_refs/official30_scoped_rows/ExamplePercentPositive_ExamplePercentPositive_wells_include_first1/native_cellprofiler_file_list.txt": "50e6dda932f1f8c22e9ff02529d94df54cb3a254e869fbb781bb2311b4507320", + "benchmark/native_refs/official30_scoped_rows/ExamplePercentPositive_ExamplePercentPositive_wells_include_first1/native_cellprofiler_headless/ExamplePercentPositive.cppipe": "17c5308d3f2ddbb26e3418c9b1f9937dab9b14f4da330d7dcdce08e0aad1c600", + "benchmark/native_refs/official30_scoped_rows/ExampleSpeckles_ExampleSpeckles_wells_include_first1/images_9683227414f2_ExampleSpeckles_native_cellprofiler/.cellprofiler_benchmark_reference.json": "4b59286575280b4fb6d7d7da4aff827a29cbecf810c9d5480795f5bfe7b69517", + "benchmark/native_refs/official30_scoped_rows/ExampleSpeckles_ExampleSpeckles_wells_include_first1/images_9683227414f2_ExampleSpeckles_native_cellprofiler/Image.csv": "8f12b7360d23ca72e8b1aca6ddb23ebde86543421971ce77f36d2ff9734ca847", + "benchmark/native_refs/official30_scoped_rows/ExampleSpeckles_ExampleSpeckles_wells_include_first1/images_9683227414f2_ExampleSpeckles_native_cellprofiler/Nuclei.csv": "15af7cac08d651c19b3e3f409b2b0d7fc4f96011c9b53394aa9a35969a8936a6", + "benchmark/native_refs/official30_scoped_rows/ExampleSpeckles_ExampleSpeckles_wells_include_first1/images_9683227414f2_ExampleSpeckles_native_cellprofiler/h2ax.csv": "0f54fc72ccdeb7e1a68bab9dc3a8d9d49788cdf81dbbc109ed119e589c09538a", + "benchmark/native_refs/official30_scoped_rows/ExampleSpeckles_ExampleSpeckles_wells_include_first1/native_cellprofiler_file_list.txt": "1adc0f16f42239d43fb944773e6b813c3c5596031b0f5977ec6ba241700506f5", + "benchmark/native_refs/official30_scoped_rows/ExampleSpeckles_ExampleSpeckles_wells_include_first1/native_cellprofiler_headless/ExampleSpeckles.cppipe": "2dbe55a93a6356f495c954e4492e2d436d96f11f3b3074d5ed9f8df12f3c240a", + "benchmark/native_refs/official30_scoped_rows/ExampleStraightenWorms_ExampleUntangleAndStraightenWorms_wells_include_first1/images_b2548cae1315_ExampleUntangleAndStraightenWorms_native_cellprofiler/.cellprofiler_benchmark_reference.json": "4b59286575280b4fb6d7d7da4aff827a29cbecf810c9d5480795f5bfe7b69517", + "benchmark/native_refs/official30_scoped_rows/ExampleStraightenWorms_ExampleUntangleAndStraightenWorms_wells_include_first1/images_b2548cae1315_ExampleUntangleAndStraightenWorms_native_cellprofiler/StraightenedWorms.csv": "f5f6b1cf5bc764e7a4779489847508a9945490ef597b2a3178182355d78ab750", + "benchmark/native_refs/official30_scoped_rows/ExampleStraightenWorms_ExampleUntangleAndStraightenWorms_wells_include_first1/native_cellprofiler_file_list.txt": "0427f41525037dcd997d181aaad3025ad96d6feea44f5ce0de4a2f42bea9faba", + "benchmark/native_refs/official30_scoped_rows/ExampleStraightenWorms_ExampleUntangleAndStraightenWorms_wells_include_first1/native_cellprofiler_headless/ExampleUntangleAndStraightenWorms.cppipe": "bf1076e58498cedcec86edcc2154067dc6e84fbdc8cbb3f7622efe301a10a742", + "benchmark/native_refs/official30_scoped_rows/ExampleTrackObjects_ExampleTrackObjects_wells_include_first1/images_45c4bf7d7bb1_ExampleTrackObjects_native_cellprofiler/.cellprofiler_benchmark_reference.json": "4b59286575280b4fb6d7d7da4aff827a29cbecf810c9d5480795f5bfe7b69517", + "benchmark/native_refs/official30_scoped_rows/ExampleTrackObjects_ExampleTrackObjects_wells_include_first1/images_45c4bf7d7bb1_ExampleTrackObjects_native_cellprofiler/Sequence1/DrosophilaEmbryo-0000.png": "ccb27d92a6837e0f2f6f59f0bd67dd6dc776c3779f636a89b82d89fa861de91e", + "benchmark/native_refs/official30_scoped_rows/ExampleTrackObjects_ExampleTrackObjects_wells_include_first1/images_45c4bf7d7bb1_ExampleTrackObjects_native_cellprofiler/Sequence1/DrosophilaEmbryo-0001.png": "df0fbeb62e76d4959516178835bc88a3f6632d32f440fb954d3d7c219e9edcfc", + "benchmark/native_refs/official30_scoped_rows/ExampleTrackObjects_ExampleTrackObjects_wells_include_first1/images_45c4bf7d7bb1_ExampleTrackObjects_native_cellprofiler/Sequence1/DrosophilaEmbryo-0002.png": "e3172e0b3f6c97693e4992c349e499c0392d6c5f15c6fbab1641a5abc0eec34b", + "benchmark/native_refs/official30_scoped_rows/ExampleTrackObjects_ExampleTrackObjects_wells_include_first1/images_45c4bf7d7bb1_ExampleTrackObjects_native_cellprofiler/Sequence1/DrosophilaEmbryo-0003.png": "e3172e0b3f6c97693e4992c349e499c0392d6c5f15c6fbab1641a5abc0eec34b", + "benchmark/native_refs/official30_scoped_rows/ExampleTrackObjects_ExampleTrackObjects_wells_include_first1/images_45c4bf7d7bb1_ExampleTrackObjects_native_cellprofiler/Sequence1/DrosophilaEmbryo-0004.png": "2b4575e3eac35bd306845582f82714f9390f2c5331462bb9e37a62d99e5119d8", + "benchmark/native_refs/official30_scoped_rows/ExampleTrackObjects_ExampleTrackObjects_wells_include_first1/images_45c4bf7d7bb1_ExampleTrackObjects_native_cellprofiler/Sequence1/DrosophilaEmbryo-0005.png": "4392bfaacdf926e1d961bc3945cf7dba716ec338b4ab8579a4082a715e10379a", + "benchmark/native_refs/official30_scoped_rows/ExampleTrackObjects_ExampleTrackObjects_wells_include_first1/images_45c4bf7d7bb1_ExampleTrackObjects_native_cellprofiler/Sequence1/DrosophilaEmbryo-0006.png": "4392bfaacdf926e1d961bc3945cf7dba716ec338b4ab8579a4082a715e10379a", + "benchmark/native_refs/official30_scoped_rows/ExampleTrackObjects_ExampleTrackObjects_wells_include_first1/images_45c4bf7d7bb1_ExampleTrackObjects_native_cellprofiler/Sequence1/DrosophilaEmbryo-0007.png": "42c4b6f5a3f339051c5bce755e9ba61d577013cb21d0d4f9e0428f06e61d8d41", + "benchmark/native_refs/official30_scoped_rows/ExampleTrackObjects_ExampleTrackObjects_wells_include_first1/images_45c4bf7d7bb1_ExampleTrackObjects_native_cellprofiler/Sequence1/DrosophilaEmbryo-0008.png": "a6e057f7ddd09cf602ea442c754190509cbafdcd422ceb735634949928a39cfc", + "benchmark/native_refs/official30_scoped_rows/ExampleTrackObjects_ExampleTrackObjects_wells_include_first1/images_45c4bf7d7bb1_ExampleTrackObjects_native_cellprofiler/Sequence1/DrosophilaEmbryo-0009.png": "a6e057f7ddd09cf602ea442c754190509cbafdcd422ceb735634949928a39cfc", + "benchmark/native_refs/official30_scoped_rows/ExampleTrackObjects_ExampleTrackObjects_wells_include_first1/images_45c4bf7d7bb1_ExampleTrackObjects_native_cellprofiler/Sequence1/DrosophilaEmbryo-0010.png": "09a253d116ff74f9b8a223031a1e01f25367b78aa4bfb7ee8aeee8a865543603", + "benchmark/native_refs/official30_scoped_rows/ExampleTrackObjects_ExampleTrackObjects_wells_include_first1/images_45c4bf7d7bb1_ExampleTrackObjects_native_cellprofiler/Sequence1/DrosophilaEmbryo-0011.png": "1246ed67396f5107d4532bc0d67f5bbebadce77034d451ba7003b39ec458834b", + "benchmark/native_refs/official30_scoped_rows/ExampleTrackObjects_ExampleTrackObjects_wells_include_first1/images_45c4bf7d7bb1_ExampleTrackObjects_native_cellprofiler/Sequence1/DrosophilaEmbryo-0012.png": "1246ed67396f5107d4532bc0d67f5bbebadce77034d451ba7003b39ec458834b", + "benchmark/native_refs/official30_scoped_rows/ExampleTrackObjects_ExampleTrackObjects_wells_include_first1/images_45c4bf7d7bb1_ExampleTrackObjects_native_cellprofiler/Sequence1/DrosophilaEmbryo-0013.png": "fef7b5d3a9064f5a6cdeee821f46a83c1d1cfd02f4dcedf237ef69156965e0c3", + "benchmark/native_refs/official30_scoped_rows/ExampleTrackObjects_ExampleTrackObjects_wells_include_first1/images_45c4bf7d7bb1_ExampleTrackObjects_native_cellprofiler/Sequence1/DrosophilaEmbryo-0014.png": "00c51409c195bd9a22033bb65df6a590088b5b13b54d2cfc7b2f5c249b65020b", + "benchmark/native_refs/official30_scoped_rows/ExampleTrackObjects_ExampleTrackObjects_wells_include_first1/images_45c4bf7d7bb1_ExampleTrackObjects_native_cellprofiler/Sequence1/DrosophilaEmbryo-0015.png": "00c51409c195bd9a22033bb65df6a590088b5b13b54d2cfc7b2f5c249b65020b", + "benchmark/native_refs/official30_scoped_rows/ExampleTrackObjects_ExampleTrackObjects_wells_include_first1/images_45c4bf7d7bb1_ExampleTrackObjects_native_cellprofiler/Sequence1/DrosophilaEmbryo-0016.png": "e0f9c89fdf96d28aa0b4c53d98eac408f4d4f4b02c5e29e847e24b935bf8d636", + "benchmark/native_refs/official30_scoped_rows/ExampleTrackObjects_ExampleTrackObjects_wells_include_first1/images_45c4bf7d7bb1_ExampleTrackObjects_native_cellprofiler/Sequence1/DrosophilaEmbryo-0017.png": "936196086157848b06d961d30d9ff0fcba09731885e9209f13194cf1039bf25d", + "benchmark/native_refs/official30_scoped_rows/ExampleTrackObjects_ExampleTrackObjects_wells_include_first1/images_45c4bf7d7bb1_ExampleTrackObjects_native_cellprofiler/Sequence1/DrosophilaEmbryo-0018.png": "936196086157848b06d961d30d9ff0fcba09731885e9209f13194cf1039bf25d", + "benchmark/native_refs/official30_scoped_rows/ExampleTrackObjects_ExampleTrackObjects_wells_include_first1/images_45c4bf7d7bb1_ExampleTrackObjects_native_cellprofiler/Sequence1/DrosophilaEmbryo-0019.png": "a068c00d5245cae6cabd119892586ccbe32341a31e71857b76d6107a6f9d05c9", + "benchmark/native_refs/official30_scoped_rows/ExampleTrackObjects_ExampleTrackObjects_wells_include_first1/images_45c4bf7d7bb1_ExampleTrackObjects_native_cellprofiler/Sequence1/DrosophilaEmbryo-0020.png": "3f4a3c0d670e75260df0e15bfce911954b285dd3df6c70a9bae62182bd8c106e", + "benchmark/native_refs/official30_scoped_rows/ExampleTrackObjects_ExampleTrackObjects_wells_include_first1/images_45c4bf7d7bb1_ExampleTrackObjects_native_cellprofiler/Sequence1/Embryos.csv": "0d6927a942947e220e91385cd90082c0349391fdeeaa70ee2a95fd4aae8038b8", + "benchmark/native_refs/official30_scoped_rows/ExampleTrackObjects_ExampleTrackObjects_wells_include_first1/images_45c4bf7d7bb1_ExampleTrackObjects_native_cellprofiler/Sequence1/Image.csv": "a1f0c73eaa61e08247160e36b0cb281f1cc1da4afa1b6862c2cec4cac1b5f88d", + "benchmark/native_refs/official30_scoped_rows/ExampleTrackObjects_ExampleTrackObjects_wells_include_first1/native_cellprofiler_file_list.txt": "49759b614a98bdd8000adc32d20b6bf7dbeb17a360b4e6bdae51fb378ba601f6", + "benchmark/native_refs/official30_scoped_rows/ExampleTrackObjects_ExampleTrackObjects_wells_include_first1/native_cellprofiler_headless/ExampleTrackObjects.cppipe": "c3f91a36bb7fef8b078a60e3bfe73fe2f4ea25bc97048c44f8e6d57ecfac0098", + "benchmark/native_refs/official30_scoped_rows/ExampleTumor_ExampleTumor_wells_include_first1/images_9401bbd08d77_ExampleTumor_native_cellprofiler/.cellprofiler_benchmark_reference.json": "c0f6eed26fd477ab9f98af2f19604f1927ce44a40985bdb79bb53b454936fbbc", + "benchmark/native_refs/official30_scoped_rows/ExampleTumor_ExampleTumor_wells_include_first1/images_9401bbd08d77_ExampleTumor_native_cellprofiler/30-2A1f_Tumors.png": "eaa154d347361f8347db3c444d74a0708bd4f77964ec6d60a529438f047d5d6c", + "benchmark/native_refs/official30_scoped_rows/ExampleTumor_ExampleTumor_wells_include_first1/images_9401bbd08d77_ExampleTumor_native_cellprofiler/Experiment.csv": "73ffe748dcfa18b8dd683fab5e7ea53f41a5529f47bfe96ac8479c44c8342df3", + "benchmark/native_refs/official30_scoped_rows/ExampleTumor_ExampleTumor_wells_include_first1/images_9401bbd08d77_ExampleTumor_native_cellprofiler/Image.csv": "0c23c2a135ce9b1d83c739e076ef0b50e3532fed66812b523317926018bd0a1a", + "benchmark/native_refs/official30_scoped_rows/ExampleTumor_ExampleTumor_wells_include_first1/images_9401bbd08d77_ExampleTumor_native_cellprofiler/tumor.csv": "85f033d06783f917ae543cf3ed332e184c0a3b69c7ecd66c1593f06e5390eb0c", + "benchmark/native_refs/official30_scoped_rows/ExampleTumor_ExampleTumor_wells_include_first1/native_cellprofiler_file_list.txt": "234cb63fa27f4086a95a6a1474edcb7fc2fb86c934be683afd753bb79066dd5b", + "benchmark/native_refs/official30_scoped_rows/ExampleTumor_ExampleTumor_wells_include_first1/native_cellprofiler_headless/ExampleTumor.cppipe": "f45ae0a3969cb8f0ab7e1d346c1f7df76ddcda110b081d98835996a6a7c41997", + "benchmark/native_refs/official30_scoped_rows/ExampleUntangleWormsBrightField_ExampleUntangleWormsBrightField_wells_include_first1/images_a61f79afad70_ExampleUntangleWormsBrightField_native_cellprofiler/.cellprofiler_benchmark_reference.json": "4b59286575280b4fb6d7d7da4aff827a29cbecf810c9d5480795f5bfe7b69517", + "benchmark/native_refs/official30_scoped_rows/ExampleUntangleWormsBrightField_ExampleUntangleWormsBrightField_wells_include_first1/images_a61f79afad70_ExampleUntangleWormsBrightField_native_cellprofiler/NonOverlappingWorms.csv": "9ade92229325f64cf9d2f2d404ac8654a04199721b054922f47e05be5028ad2e", + "benchmark/native_refs/official30_scoped_rows/ExampleUntangleWormsBrightField_ExampleUntangleWormsBrightField_wells_include_first1/native_cellprofiler_file_list.txt": "699d439b828ca3e0706a789521015dfc79ae6fd8192e4c37ae9c147b39dd2f85", + "benchmark/native_refs/official30_scoped_rows/ExampleUntangleWormsBrightField_ExampleUntangleWormsBrightField_wells_include_first1/native_cellprofiler_headless/ExampleUntangleWormsBrightField.cppipe": "cffb98c4f763a7656fc149d06edd2533f436416ab84810f8138fd9640fccc6bb", + "benchmark/native_refs/official30_scoped_rows/ExampleUntangleWorms_ExampleUntangleWorms_wells_include_first1/images_886125f8f337_ExampleUntangleWorms_native_cellprofiler/.cellprofiler_benchmark_reference.json": "4b59286575280b4fb6d7d7da4aff827a29cbecf810c9d5480795f5bfe7b69517", + "benchmark/native_refs/official30_scoped_rows/ExampleUntangleWorms_ExampleUntangleWorms_wells_include_first1/images_886125f8f337_ExampleUntangleWorms_native_cellprofiler/1649_1109_0003_Amp5-1_B_20070424_C01_w2_CB2F18CD-EDF0-4BCD-98CF-3A07E5A582FFoutlines.png": "3af795fe333ba75a120324267162f6e647dd48ba938d7f68af9e2a951aaa9cbd", + "benchmark/native_refs/official30_scoped_rows/ExampleUntangleWorms_ExampleUntangleWorms_wells_include_first1/images_886125f8f337_ExampleUntangleWorms_native_cellprofiler/1649_1109_0003_Amp5-1_B_20070424_C20_w2_5F64C597-735E-435D-B49C-2A07B9D6DFC3outlines.png": "5fb364ee092cbb112b0a790067d15814595f8f31e81889f5feaa5f58702556a0", + "benchmark/native_refs/official30_scoped_rows/ExampleUntangleWorms_ExampleUntangleWorms_wells_include_first1/images_886125f8f337_ExampleUntangleWorms_native_cellprofiler/Image.csv": "666590d051a3266922dbb8623b63b8e65efc4b9a87e8337c7628af4ec64376c1", + "benchmark/native_refs/official30_scoped_rows/ExampleUntangleWorms_ExampleUntangleWorms_wells_include_first1/images_886125f8f337_ExampleUntangleWorms_native_cellprofiler/OverlappingWorms.csv": "b3d754b7df1cf265875977067e251ea209e505ee0dcbcf4752fab500ffaf8ed0", + "benchmark/native_refs/official30_scoped_rows/ExampleUntangleWorms_ExampleUntangleWorms_wells_include_first1/native_cellprofiler_file_list.txt": "f9f2a939f212b570addf2e4217842844c5bbe4b646fcb76707705d8bc78d9b02", + "benchmark/native_refs/official30_scoped_rows/ExampleUntangleWorms_ExampleUntangleWorms_wells_include_first1/native_cellprofiler_headless/ExampleUntangleWorms.cppipe": "9fc8c49624dbb6796afa37794a957eb95177f0632891dc48f2ab12d7d2381c17", + "benchmark/native_refs/official30_scoped_rows/ExampleVitraImages_ExampleVitra_wells_include_first1/images_571b7d96aae0_ExampleVitra_native_cellprofiler/.cellprofiler_benchmark_reference.json": "4b59286575280b4fb6d7d7da4aff827a29cbecf810c9d5480795f5bfe7b69517", + "benchmark/native_refs/official30_scoped_rows/ExampleVitraImages_ExampleVitra_wells_include_first1/images_571b7d96aae0_ExampleVitra_native_cellprofiler/Cells.csv": "2ac1308e6bd6c3299ce34217916f3eb1846e1992215bc658658e947ab19d46fc", + "benchmark/native_refs/official30_scoped_rows/ExampleVitraImages_ExampleVitra_wells_include_first1/images_571b7d96aae0_ExampleVitra_native_cellprofiler/Channel 1-01-A-01-00_Outlined.tiff": "4c9caab6edec2642f60376a9b5257ab60d08adac602952b1528b868d0e6ae711", + "benchmark/native_refs/official30_scoped_rows/ExampleVitraImages_ExampleVitra_wells_include_first1/images_571b7d96aae0_ExampleVitra_native_cellprofiler/Cytoplasm.csv": "7c8c1139cea980114efe72dac52cfb2364a4dcc26904c3ef4c68e3297731e5df", + "benchmark/native_refs/official30_scoped_rows/ExampleVitraImages_ExampleVitra_wells_include_first1/images_571b7d96aae0_ExampleVitra_native_cellprofiler/Image.csv": "be1933d1d3df78ef586154cb4a24641b560f9d85755942fc1f905f160bfc9213", + "benchmark/native_refs/official30_scoped_rows/ExampleVitraImages_ExampleVitra_wells_include_first1/images_571b7d96aae0_ExampleVitra_native_cellprofiler/Nuclei.csv": "2201239ff8cf2042dc36ed4812b61a00cdee8311bcbed804b2cd0537ce82666b", + "benchmark/native_refs/official30_scoped_rows/ExampleVitraImages_ExampleVitra_wells_include_first1/native_cellprofiler_selected_source_workspace/_source/IllumDNA/VitraChannel2ILLUM.npy": "f95bcd9ea006a731eac68070808c225584b85834aea703356d61d471a318a075", + "benchmark/native_refs/official30_scoped_rows/ExampleVitraImages_ExampleVitra_wells_include_first1/native_cellprofiler_selected_source_workspace/_source/IllumProtein/VitraChannel1ILLUM.npy": "047d756eb3ccc55c4c850a85c0b9883ac683cc4cc415c0c9f9b41712ad9d650e", + "benchmark/native_refs/official30_scoped_rows/ExampleWoundHealing_ExampleWoundHealing_wells_include_first1/images_ea0a23a93a14_ExampleWoundHealing_native_cellprofiler/.cellprofiler_benchmark_reference.json": "4b59286575280b4fb6d7d7da4aff827a29cbecf810c9d5480795f5bfe7b69517", + "benchmark/native_refs/official30_scoped_rows/ExampleWoundHealing_ExampleWoundHealing_wells_include_first1/images_ea0a23a93a14_ExampleWoundHealing_native_cellprofiler/Image.csv": "5092109ba5104d090b3d6d95683d7fee23ae609de3ea874583d0ee5d59916849", + "benchmark/native_refs/official30_scoped_rows/ExampleWoundHealing_ExampleWoundHealing_wells_include_first1/native_cellprofiler_file_list.txt": "f00beb9e827b95803f59725b3dd7b98817fdb815bd4c0361300daeb8b5e3f2ab", + "benchmark/native_refs/official30_scoped_rows/ExampleWoundHealing_ExampleWoundHealing_wells_include_first1/native_cellprofiler_headless/ExampleWoundHealing.cppipe": "492f8be03ef821ebf56ac43023a956f368fd89f03abfdf9e5ed5cefe3ac790fb", + "benchmark/native_refs/official30_scoped_rows/ExampleYeastColonies_ExampleYeastColonies_wells_include_first1/images_d4157ddaf410_ExampleYeastColonies_native_cellprofiler/.cellprofiler_benchmark_reference.json": "c0f6eed26fd477ab9f98af2f19604f1927ce44a40985bdb79bb53b454936fbbc", + "benchmark/native_refs/official30_scoped_rows/ExampleYeastColonies_ExampleYeastColonies_wells_include_first1/images_d4157ddaf410_ExampleYeastColonies_native_cellprofiler/6-1_outlines.png": "359ecfa9aed57495df2b3896bcaa6d499762314ad8a2525b1ca14a5d7d0d340e", + "benchmark/native_refs/official30_scoped_rows/ExampleYeastColonies_ExampleYeastColonies_wells_include_first1/images_d4157ddaf410_ExampleYeastColonies_native_cellprofiler/Colonies.csv": "0efb44e46b42674c383ffd808cf83f5111826217ddadf5510e3c07ae29bcf9cd", + "benchmark/native_refs/official30_scoped_rows/ExampleYeastColonies_ExampleYeastColonies_wells_include_first1/images_d4157ddaf410_ExampleYeastColonies_native_cellprofiler/Image.csv": "0c65352424f6d5928b130d37b8d69f494faf55224c20ba6f17a98944c9a5b7fa", + "benchmark/native_refs/official30_scoped_rows/ExampleYeastColonies_ExampleYeastColonies_wells_include_first1/native_cellprofiler_file_list.txt": "efc7e3daaa355ae68efebf397620be8f51725929a50f3aed6fb94512cfcf1ef9", + "benchmark/native_refs/official30_scoped_rows/ExampleYeastColonies_ExampleYeastColonies_wells_include_first1/native_cellprofiler_headless/ExampleYeastColonies.cppipe": "dcd88ecaa4109da46752b15596f1caa3f41db96e3f6baa960c693d96c9fae436", + "benchmark/native_refs/official30_scoped_rows/ExampleYeastPatches_ExampleYeastPatches_wells_include_first1/images_5dcdc9c27278_ExampleYeastPatches_native_cellprofiler/.cellprofiler_benchmark_reference.json": "4b59286575280b4fb6d7d7da4aff827a29cbecf810c9d5480795f5bfe7b69517", + "benchmark/native_refs/official30_scoped_rows/ExampleYeastPatches_ExampleYeastPatches_wells_include_first1/images_5dcdc9c27278_ExampleYeastPatches_native_cellprofiler/1832-48hours-gal-1_ForcedOutline.png": "c03031031d98b5e391c77bc8345f07148543d25b60843ad3ce1206bba1e9f8fe", + "benchmark/native_refs/official30_scoped_rows/ExampleYeastPatches_ExampleYeastPatches_wells_include_first1/images_5dcdc9c27278_ExampleYeastPatches_native_cellprofiler/1832-48hours-gal-1_NaturalOutline.png": "d581dc4d03a11a5535ee237459c14603e80ebbbdf22a82abdb6e469769445954", + "benchmark/native_refs/official30_scoped_rows/ExampleYeastPatches_ExampleYeastPatches_wells_include_first1/images_5dcdc9c27278_ExampleYeastPatches_native_cellprofiler/Experiment.csv": "9010befceef019ce48bf8d6a0165269b8a497d7344d2bf21da3f541a191b3d58", + "benchmark/native_refs/official30_scoped_rows/ExampleYeastPatches_ExampleYeastPatches_wells_include_first1/images_5dcdc9c27278_ExampleYeastPatches_native_cellprofiler/FilterObjects.csv": "c096a4758c1816a807f15e5a97e1437953445f5f0637887200f95f6c5d73d09c", + "benchmark/native_refs/official30_scoped_rows/ExampleYeastPatches_ExampleYeastPatches_wells_include_first1/images_5dcdc9c27278_ExampleYeastPatches_native_cellprofiler/ForcedSpots.csv": "ae682b931aac32f5ea6c899953ccd72c4ee826e711153dad97b053a4d0ec3b65", + "benchmark/native_refs/official30_scoped_rows/ExampleYeastPatches_ExampleYeastPatches_wells_include_first1/images_5dcdc9c27278_ExampleYeastPatches_native_cellprofiler/Image.csv": "20e979345f3e0c2c52ce691430b84643070902f1416940c6b36a04cb1bb123ca", + "benchmark/native_refs/official30_scoped_rows/ExampleYeastPatches_ExampleYeastPatches_wells_include_first1/images_5dcdc9c27278_ExampleYeastPatches_native_cellprofiler/NaturalSpots.csv": "87da0ddc6b311e95e9ab11d162d62e85fec437a33eb07a6f01fd2f7cfc2b47d1", + "benchmark/native_refs/official30_scoped_rows/ExampleYeastPatches_ExampleYeastPatches_wells_include_first1/images_5dcdc9c27278_ExampleYeastPatches_native_cellprofiler/Prespots.csv": "d3500afcfb50d95a18eb391371e79897456bbf39489657f2ffa1551ecc7d6c3d", + "benchmark/native_refs/official30_scoped_rows/ExampleYeastPatches_ExampleYeastPatches_wells_include_first1/native_cellprofiler_file_list.txt": "b08566b61f65bfb22c329500259b205fc82e58249f94b27262aca9f079208882", + "benchmark/native_refs/official30_scoped_rows/ExampleYeastPatches_ExampleYeastPatches_wells_include_first1/native_cellprofiler_headless/ExampleYeastPatches.cppipe": "0a44f253afd1ab73ec99c77f3b91cdb09bf5d41b1fe22465ee4b1e46ce720066", + "benchmark/native_refs/official30_value_completion_20260914/CellProfiler4_benchmark_supplement_cp4_supplement_combine_objects_wells_include_first1/CombineObjects_f4072628fb1a_cp4_supplement_combine_objects_native_cellprofiler/.cellprofiler_benchmark_reference.json": "5adccc651a8610352acb88288c56f2d5de7845be1e0d9813cea1c76b6e87b03a", + "benchmark/native_refs/official30_value_completion_20260914/CellProfiler4_benchmark_supplement_cp4_supplement_combine_objects_wells_include_first1/CombineObjects_f4072628fb1a_cp4_supplement_combine_objects_native_cellprofiler/reference_labels__CombinedObjects.tiff": "f5a96f1e11f1c9a0a3a86388f100705d99765856bc668aba675c935563e32197", + "benchmark/native_refs/official30_value_completion_20260914/CellProfiler_tutorials_cp_tutorial_translocation_start_wells_include_first1/TranslocationData_cp_tutorial_translocation_start_native_cellprofiler/.cellprofiler_benchmark_reference.json": "e5ea45cd8328a430dc4e515c23242dbd2d0970a74493271aacca076278238c8b", + "benchmark/native_refs/official30_value_completion_20260914/CellProfiler_tutorials_cp_tutorial_translocation_start_wells_include_first1/TranslocationData_cp_tutorial_translocation_start_native_cellprofiler/reference_labels__Nuclei.tiff": "eaa520c6b780dcf61899b0018ae4f1e610b3cdcd9048cd3ec1202669c03ee6e2", + "benchmark/native_refs/official30_value_completion_20260914/ExampleIlluminationCorrection_ExampleIlluminationCorrection_Example1_EachMethod_wells_include_first1/images_ExampleIlluminationCorrection_Example1_EachMethod_native_cellprofiler/.cellprofiler_benchmark_reference.json": "331429c61ec577b7baec0beb6cc913cd4b6575b323a02a64aa00693918941194", + "benchmark/native_refs/official30_value_completion_20260914/ExampleIlluminationCorrection_ExampleIlluminationCorrection_Example1_EachMethod_wells_include_first1/images_ExampleIlluminationCorrection_Example1_EachMethod_native_cellprofiler/reference_image__CorrGreen.npy": "3c17148f0fad16738a23af55ac4e41692e6c2906808a7d83823331702b1b4f46", + "benchmark/native_refs/official30_value_completion_20260914/ExampleIlluminationCorrection_ExampleIlluminationCorrection_Example2_wells_include_first1/images_ExampleIlluminationCorrection_Example2_native_cellprofiler/.cellprofiler_benchmark_reference.json": "dd475748fcbfd645efef9e29f6a856e1b68096344ab4614dae2ff597523e95ca", + "benchmark/native_refs/official30_value_completion_20260914/ExampleIlluminationCorrection_ExampleIlluminationCorrection_Example2_wells_include_first1/images_ExampleIlluminationCorrection_Example2_native_cellprofiler/reference_labels__LargeBlockCorrectedNuclei.tiff": "f1bbed3348ce75d8d4158cad37c08ae4ab30d9e0a5dfbb9e259b906311811e45", + "benchmark/native_refs/official30_value_completion_20260914/ExampleIlluminationCorrection_ExampleIlluminationCorrection_Example2_wells_include_first1/images_ExampleIlluminationCorrection_Example2_native_cellprofiler/reference_labels__SmallBlockCorrectedNuclei.tiff": "d31aa4bc3e9782e646820b5f3bef6f91f4fbf78bf8ee46b5260cde78e558f700", + "benchmark/native_refs/official30_value_completion_20260914/ExampleIlluminationCorrection_ExampleIlluminationCorrection_Example2_wells_include_first1/images_ExampleIlluminationCorrection_Example2_native_cellprofiler/reference_labels__UncorrectedNuclei.tiff": "2f54cba8f1482ab54e8a21f71fb2a912ea8a260f8dae2bb5bccfb94994da5a84", + "benchmark/native_refs/official30_value_completion_20260914/ExampleIlluminationCorrection_ExampleIlluminationCorrection_Example3_wells_include_first1/images_ExampleIlluminationCorrection_Example3_native_cellprofiler/.cellprofiler_benchmark_reference.json": "37e74838f03ca2fcb0b941ad62f2bcf6ebc4082651dd04c577d7e0b760a03a79", + "benchmark/native_refs/official30_value_completion_20260914/ExampleIlluminationCorrection_ExampleIlluminationCorrection_Example3_wells_include_first1/images_ExampleIlluminationCorrection_Example3_native_cellprofiler/reference_image__ConvexHullCorrWorm.npy": "9ba1259e4ca007c06f14be6946e32a86307ec2dfb9952b73fa2cc253ccae8b3a", + "benchmark/native_refs/official30_value_completion_20260914/ExampleIlluminationCorrection_ExampleIlluminationCorrection_Example3_wells_include_first1/images_ExampleIlluminationCorrection_Example3_native_cellprofiler/reference_image__PolynomialCorrected.npy": "588e6f9951aa7ad220678dbb0053e98fb6d324e71aab089d1d828d891ee32f54", + "benchmark/native_synthetic_well_scaling.py": "de987613fe1ee2c1f8e29be505846595ec8f829f1d2148ca4b3d51e2304b2954", + "benchmark/openhcs_measured_run.py": "1e0cccc518fb6bec9c92ea8057dd7adfc7305b2d90a6da8f152c1b97601878ab", + "benchmark/own_neurite_blind_20260915_preparation.md": "9c4e9a9e1dca543c7a22649693045d94b7cdef41873e8f815de70637ea826df5", + "benchmark/pipelines/__init__.py": "a95462dd83b89a8b11e46ca9c1c0b9eee8d0934773dc55b2bc3ca6125768f8ef", + "benchmark/pipelines/bbbc021_nuclei_segmentation.py": "56166f2dadfdd8d7f1c7fe509129f15ad9ac086bd48ebe5860b3432d66304ea4", + "benchmark/pipelines/bbbc022_nuclei_segmentation.py": "c442e7586fbadc8cc975048fcad9403957d096ce0cfb8b8183ff0486db5498e8", + "benchmark/pipelines/cellprofiler_nuclei.py": "d7bbc254c82381edc2c82f22e0583c783574d36d9ed52819445f64d7d65925fc", + "benchmark/pipelines/cellprofiler_nuclei_cupy.py": "f92d88239172074f3b84f63b4c1faa02f5c10945cee89797214c20c74f727a9d", + "benchmark/pipelines/cellprofiler_nuclei_gpu.py": "780db7199ad37ac957d8688583c86d8cca75aa69ab219fc1b467e96470b065ae", + "benchmark/pipelines/cellprofiler_preprocess.py": "30179b93bd69cf0c8a3fc9b0751b577ec306b776ccee03daac6b229be2a6eef2", + "benchmark/pipelines/registry.py": "d6bb037e43aee45ad6041bb71710066bd6ce9b7e3d5d23d79e5186d9b08a10e0", + "benchmark/prepare_blind_neurite.py": "341587cc14bec627555cb70ddcbd858cce2f209f9bd611aa4045b460fe8e01ea", + "benchmark/progress.py": "d5ffd622416e9d954095a58d8aee816b5875473d87b75c785f91b65ed2cac3a8", + "benchmark/reference_exports/official30_value_completion_20260914/ExampleIlluminationCorrection_Example1_EachMethod.cppipe": "3879f7d442034a3603f4dabe44ba4a542d831156494fff0d4e37b64cbf2161ad", + "benchmark/reference_exports/official30_value_completion_20260914/ExampleIlluminationCorrection_Example1_EachMethod.reference_exports.json": "858fc86b72c13e0e641b971f2b8877a5a07ae4078df2671eff44725ec79b34c5", + "benchmark/reference_exports/official30_value_completion_20260914/ExampleIlluminationCorrection_Example2.cppipe": "fa2966b0cd36932e1fa5a853e3a5f4d272173f20c97b81636cdfeb31d79419a2", + "benchmark/reference_exports/official30_value_completion_20260914/ExampleIlluminationCorrection_Example2.reference_exports.json": "2b6c192627491f6b532e062624b7dcc5832eca2768c3ff10f7dfc5a1f25d3099", + "benchmark/reference_exports/official30_value_completion_20260914/ExampleIlluminationCorrection_Example3.cppipe": "f7ec9eb561730cc567986e6a50504a69f23a3ca78a1a033faba0b2fea52759fb", + "benchmark/reference_exports/official30_value_completion_20260914/ExampleIlluminationCorrection_Example3.reference_exports.json": "23509b73afd617981e8c06a107760dc0233dd5049aae028717de649ae929e80a", + "benchmark/reference_exports/official30_value_completion_20260914/cp4_supplement_combine_objects.cppipe": "25d76709b04f6eaeae234545948e9cb304b5d88a4988631fea0bc60113a71fe3", + "benchmark/reference_exports/official30_value_completion_20260914/cp4_supplement_combine_objects.reference_exports.json": "e2e7e2efd24a396c5bbb6fe5ec3d3a00fc74997d9c84b316459fe00c7bc7f5ac", + "benchmark/reference_exports/official30_value_completion_20260914/cp_tutorial_translocation_start.cppipe": "15d95afa1821526e5b58cc76fc33916ee0107ba5a3123cba33fa91ac319e5708", + "benchmark/reference_exports/official30_value_completion_20260914/cp_tutorial_translocation_start.reference_exports.json": "bae2691f4f71f2297ae85eecd9fe4c209047bd3b8c1b888c2b81a80e4ab456a4", + "benchmark/reports/__init__.py": "5257727a4b7318de6de26d52564a414fa02a93d1f14439b58ed6945344283547", + "benchmark/reports/autonomous_image_analysis_validation_tranche_20260917.md": "2a9ed4eb0417dcf403c7593ece8f217bcb086e44c09d5c460ba2a48071e71d54", + "benchmark/reports/cppipe_figures.py": "bf4132cabafca6f7e1d277d73ac8cbfd4f30141dcb1b6981bc5fc451da43725e", + "benchmark/reports/cppipe_scaling_figures.py": "047ed45f4a73a0cd90afc8a2b221895dec56e104b130b881b57025e995796276", + "benchmark/reports/independent_validation_preparation_20260917.md": "1042a818ee1216550553b5da8ebfed6e2a115027a135a3dc67e048a251764be0", + "benchmark/results/labmeeting_20260505/README.md": "51680197c044a5d5daecbd3ed7e489e1e46058caa08c019ee0bead32cdf5e4e3", + "benchmark/results/labmeeting_20260505/cppipe_cp_vs_openhcs_summary.csv": "25bf28d0bf7587ffa6b59883ae836197370a946974181d26866e2f932c4fba19", + "benchmark/results/labmeeting_20260505/cppipe_figures_20260505_v7/cppipe_accuracy.png": "7b3565fb46c6f7f3da79b45aa868e9b1b38524d8212dea1e20d873dee0f7597b", + "benchmark/results/labmeeting_20260505/cppipe_figures_20260505_v7/cppipe_accuracy.svg": "9ecd4d9c5be0907ec051af8e8beb5e26df1ce674e9ac2bbcef01f4e03b14ccb6", + "benchmark/results/labmeeting_20260505/cppipe_figures_20260505_v7/cppipe_accuracy_zoom.png": "15f2e309e6d3a81b5715a02484d41530f60190e77979054650ccd0c301066108", + "benchmark/results/labmeeting_20260505/cppipe_figures_20260505_v7/cppipe_accuracy_zoom.svg": "661aa6143bbef3966b5f0b5cbe5c3ae89dffccf8a529608174af291c149613cc", + "benchmark/results/labmeeting_20260505/cppipe_figures_20260505_v7/cppipe_comparison_metrics_long.csv": "e298d34a3a8e7f0fdf124059bdf784f13cb7e040a5fb43e9798cb6a2053145b4", + "benchmark/results/labmeeting_20260505/cppipe_figures_20260505_v7/cppipe_raw_seconds.png": "419a52a00adf37f2ad5c1960e12d463cfdc3fe202015f2326f291cfc58537603", + "benchmark/results/labmeeting_20260505/cppipe_figures_20260505_v7/cppipe_raw_seconds.svg": "e3f3184ad6dc2d7ba1965e864ca810403d19edd2861e60c7118383068f99b361", + "benchmark/results/labmeeting_20260505/cppipe_figures_20260505_v7/cppipe_raw_seconds_log.png": "214f215d3d0eb9e5fbc7e62bd99d56c811bf7f0c16f0f54a5b4ed71f13d2a485", + "benchmark/results/labmeeting_20260505/cppipe_figures_20260505_v7/cppipe_raw_seconds_log.svg": "dafdffc0e3c1c29520b01c5bca533a73ce322a8a7e320fa094880e21ff15cd8b", + "benchmark/results/labmeeting_20260505/cppipe_figures_20260505_v7/cppipe_speedup.png": "430ad689c9083ae857f847d7ad98341e7fa3ba834d21a5daa6b40a00365eb86a", + "benchmark/results/labmeeting_20260505/cppipe_figures_20260505_v7/cppipe_speedup.svg": "2f764837cfdef11d7a2a5f66ec65f55a42f12843dc6c6820194bab24b52cd05e", + "benchmark/results/labmeeting_20260505/cppipe_figures_20260505_v7/cppipe_speedup_log.png": "126bde3a80ead1931f2a84e892534cdbe11a1e964ea244eb59fc825fb7696a58", + "benchmark/results/labmeeting_20260505/cppipe_figures_20260505_v7/cppipe_speedup_log.svg": "5c428999f91c6c15c0c56c45b32dad601f6e92d09d34652b7c64b257c357d6a3", + "benchmark/results/labmeeting_20260505/throughput_2v16_samples_1v2_jobs_partial/throughput_batches.csv": "5af6b59ba253f193ac19a7babd5e0bbd9a4f8924e2fb2c954d22318f38173376", + "benchmark/results/labmeeting_20260505/throughput_2v16_samples_1v2_jobs_partial/throughput_jobs.csv": "9836b7b7c06045ae9a7b84808af61ecbcd95efc287b0e164c636793d53664d8a", + "benchmark/results/labmeeting_20260505/throughput_2v16_samples_1v2_jobs_partial/throughput_summary.csv": "fb5309e9a5ce28ca0a53d5c70cfb8e68b73360a0ebc2e0b8752bb55ce84f3898", + "benchmark/results/labmeeting_20260505/well_throughput_native_coloc_24w_1v2v3/ExampleColocalization/wells_24/workers_1/well_throughput_progress_events.csv": "6b2af2df6325a6b7e1238d6979a7cbf040855aab758d0976561b10b12f0c76c6", + "benchmark/results/labmeeting_20260505/well_throughput_native_coloc_24w_1v2v3/ExampleColocalization/wells_24/workers_1/well_throughput_step_timings.csv": "82178ee1eced32201c85ae89ddc75fd0331871da768e5507d45e971c0fa605aa", + "benchmark/results/labmeeting_20260505/well_throughput_native_coloc_24w_1v2v3/ExampleColocalization/wells_24/workers_1/well_throughput_worker_lanes.csv": "b619e13ecafbb80c12018cb18b8b866aeab304c3d6ef1dcb88a2946eebb85357", + "benchmark/results/labmeeting_20260505/well_throughput_native_coloc_24w_1v2v3/ExampleColocalization/wells_24/workers_2/well_throughput_progress_events.csv": "f3219e1e9ccc95f72e82ebc47fd17b47d52add4d315de294c32fd1866938dc58", + "benchmark/results/labmeeting_20260505/well_throughput_native_coloc_24w_1v2v3/ExampleColocalization/wells_24/workers_2/well_throughput_step_timings.csv": "7cd51b935d6aed535e4399a5eec0f8bc6ba0525dd7bc901b723231b274603411", + "benchmark/results/labmeeting_20260505/well_throughput_native_coloc_24w_1v2v3/ExampleColocalization/wells_24/workers_2/well_throughput_worker_lanes.csv": "83208040a6b48cef0296d63bd56e3fe6c06fd96d8ba4ccae072cca4652e612b0", + "benchmark/results/labmeeting_20260505/well_throughput_native_coloc_24w_1v2v3/ExampleColocalization/wells_24/workers_3/well_throughput_progress_events.csv": "e5a6a6a3737c1a4efa6e21f88242a8de8e8d71f07784029943309ff5de77a796", + "benchmark/results/labmeeting_20260505/well_throughput_native_coloc_24w_1v2v3/ExampleColocalization/wells_24/workers_3/well_throughput_step_timings.csv": "37da778817614f39665e1dee26be02b63a32b765f68c89b73baa9a56dcae8596", + "benchmark/results/labmeeting_20260505/well_throughput_native_coloc_24w_1v2v3/ExampleColocalization/wells_24/workers_3/well_throughput_worker_lanes.csv": "ac0d424450cc4b369d36739373e9be33dc9fb654adeeb938c84b7d794959bf85", + "benchmark/results/labmeeting_20260505/well_throughput_native_coloc_24w_1v2v3/well_throughput.csv": "35aeef7992b64abb3ad5aa7b4f2d22a3e135c9a7ce95df07ff5cc6f36c74416c", + "benchmark/results/labmeeting_20260505/well_throughput_native_coloc_2v16/well_throughput.csv": "0854ac349626a7828e87454bcd44248ef395215829b8c6f1a52ebbcb8a22804d", + "benchmark/results/labmeeting_20260513/README.md": "e507c90f0cbc65ef3ad8b33099b770e64fdcba424cba7c55b797c1fd627ac434", + "benchmark/results/labmeeting_20260513/official30_well_throughput/data/core_scaling_well_throughput.csv": "3b799feec3a7c024bf878b2c08c3848b8d5320e50d87387a999eeb34a429d491", + "benchmark/results/labmeeting_20260513/official30_well_throughput/data/single_process_summary.csv": "38747ee2a7a0a8fcd361cc5269f76aaf3150396a6b2ff7988edd11aa12345488", + "benchmark/results/labmeeting_20260513/official30_well_throughput/data/wells_per_core_2c3c4c.csv": "1d6db1948a510855e24d52bb316e36c704fe0176d8623eb99dc1346fa396b6de", + "benchmark/results/labmeeting_20260513/official30_well_throughput/data/wells_per_core_4c_6wpc_8wpc.csv": "5938eefdba5aefa50b55f320120253f1096502e2ba74973ae38d05ecb3f5ab2f", + "benchmark/results/labmeeting_20260513/official30_well_throughput/figures/01_parity_by_pipeline.csv": "2ac591b1865756ac6f54066ad3f978e6ab047bdaf4676c5fbc37811291366969", + "benchmark/results/labmeeting_20260513/official30_well_throughput/figures/01_parity_by_pipeline.png": "c1465fdab74fe6c98beedad84b845e81d39a344c54e2bb5a56b64455263a7fd9", + "benchmark/results/labmeeting_20260513/official30_well_throughput/figures/01_parity_by_pipeline.svg": "605558d1ab275cdd39806f193312807b00a085d75560e45b9a6f91892f483a1d", + "benchmark/results/labmeeting_20260513/official30_well_throughput/figures/02_core_scaling_by_pipeline_plus_average_long.csv": "dac4de8bf11d427030ed1e5069b6bb47d4f8d489fee7f4224ab2d86fca8caf58", + "benchmark/results/labmeeting_20260513/official30_well_throughput/figures/02_core_scaling_by_pipeline_plus_average_speedup.png": "88b4a869f837282280b79ca95d929a556112f276612764adc9f3b0f85b1fba28", + "benchmark/results/labmeeting_20260513/official30_well_throughput/figures/02_core_scaling_by_pipeline_plus_average_speedup.svg": "dc266b7aa72bd230609f09621a5d2dab11c7798e4e53576c7e1942efaa586763", + "benchmark/results/labmeeting_20260513/official30_well_throughput/figures/02_core_scaling_by_pipeline_plus_average_speedup_log.png": "a8f5d3dc4b5f03ce0b5c78f3d9c4a916fee346bf1df809c1bcf506bb2965d8ed", + "benchmark/results/labmeeting_20260513/official30_well_throughput/figures/02_core_scaling_by_pipeline_plus_average_speedup_log.svg": "a55897c712c9ce9fec5eaaa5e2f30290d5e052e10612d855d5024777b2fe1e97", + "benchmark/results/labmeeting_20260513/official30_well_throughput/figures/03_core_scaling_average_with_pipeline_points_speedup.png": "933ea666c623db0b43f1b32505a258fe12ec07c3042797bf2ec5c08fc6fbc7ff", + "benchmark/results/labmeeting_20260513/official30_well_throughput/figures/03_core_scaling_average_with_pipeline_points_speedup.svg": "32837549844ad1422bcdf0b5d700a4c51ac4a330b4615295e2e3474448908650", + "benchmark/results/labmeeting_20260513/official30_well_throughput/figures/03_core_scaling_average_with_pipeline_points_speedup_log.png": "5aff106f3814bdcb4764588819a93efbe856a8262f159c4b814c015fbddb5e58", + "benchmark/results/labmeeting_20260513/official30_well_throughput/figures/03_core_scaling_average_with_pipeline_points_speedup_log.svg": "d987f7a000fb5448c151b90585bb0915827a90550f398352ea37eae59731213d", + "benchmark/results/labmeeting_20260513/official30_well_throughput/figures/04_core_scaling_average_with_pipeline_points_ram.png": "048d50ecb36a6731e65b48fe2c1d9a68a1481dfc37606223874e22b99b6af6e0", + "benchmark/results/labmeeting_20260513/official30_well_throughput/figures/04_core_scaling_average_with_pipeline_points_ram.svg": "433b722561af91dde339705f2a0da040db22e670e38ef9f0c27a9374772984e4", + "benchmark/results/labmeeting_20260513/official30_well_throughput/figures/04_core_scaling_by_pipeline_plus_average_ram.png": "703da7f0d220c0068e4356399c67d19f240129a5a11b23a23c4d451e9f864924", + "benchmark/results/labmeeting_20260513/official30_well_throughput/figures/04_core_scaling_by_pipeline_plus_average_ram.svg": "9f7f74db3afc9e96c7579c3d8e1c40a7327a3f3345ec64abe0a1c79aff3926ad", + "benchmark/results/labmeeting_20260513/official30_well_throughput/figures/04_core_scaling_by_pipeline_plus_average_ram_log.png": "b07a3eb5528229351f20c1a5655888cd78b32c620de1a73590902302eb084426", + "benchmark/results/labmeeting_20260513/official30_well_throughput/figures/04_core_scaling_by_pipeline_plus_average_ram_log.svg": "54604f5c04f69ce0b2fe3093373b2deb8ed26cc2dcaa0cdacbbd2373ea391182", + "benchmark/results/labmeeting_20260513/official30_well_throughput/figures/05_speedup_by_core_and_wells_per_core_summary.csv": "63473a7219d7a42b2f48f0f872dde98c943c1416ab1a9403852fe39ab7a7cef3", + "benchmark/results/labmeeting_20260513/official30_well_throughput/figures/05_speedup_by_core_and_wells_per_core_summary.md": "027d5b2ee710b087a415e353b63e43a13dc345f932d1493985482988e1d41118", + "benchmark/results/labmeeting_20260513/official30_well_throughput/figures/05_speedup_summary_by_core_and_wells_per_core.png": "338c1ec72020fd12809289fe997e30e9bac41edf4aa120a076fb27c68a57457d", + "benchmark/results/labmeeting_20260513/official30_well_throughput/figures/05_speedup_summary_by_core_and_wells_per_core.svg": "f37d086ca32e7aa13b16ed72e088bfdb21fe2a295f543215c4f788db6d5ddf84", + "benchmark/results/labmeeting_20260513/official30_well_throughput/figures/05_speedup_summary_by_core_and_wells_per_core_log.png": "141da994ec06ec12b44dbf1f8d0b44b8efc7d6842443c4c75682c7d05e0e7e52", + "benchmark/results/labmeeting_20260513/official30_well_throughput/figures/05_speedup_summary_by_core_and_wells_per_core_log.svg": "e4c2993bf24d292717b6ba2e7feaa1f27b592e5bcbafc90b499a0cf854aef6f6", + "benchmark/results/labmeeting_20260513/official30_well_throughput/figures/06_module_coverage_by_abstraction.png": "9300f12f6317d99d0e8fb144550a9a6a5575869f68ad1570f8f660323fc7b875", + "benchmark/results/labmeeting_20260513/official30_well_throughput/figures/06_module_coverage_by_abstraction.svg": "f46e1b5876b1eca9398359f8d1354f2126db507c5ad525f71a44d3b02bce24be", + "benchmark/results/labmeeting_20260513/official30_well_throughput/figures/06_module_coverage_by_abstraction_modules.csv": "9091dbd94ff3b2233085a1644e0db87bb105c1896d8c266ee2e6fec55505abbe", + "benchmark/results/labmeeting_20260513/official30_well_throughput/figures/06_module_coverage_by_abstraction_modules.md": "b35f2a1f1ba2dc7c7bd8e49ebb2e08283c8e977e80566abb45e13a9840ed93c2", + "benchmark/results/labmeeting_20260513/official30_well_throughput/figures/module_coverage_absorbed_modules.csv": "fbc5be2c4e93fa853739b4f8b312735a52e70d2e7064c07807070f1a8861f7a6", + "benchmark/results/labmeeting_20260513/official30_well_throughput/figures/module_coverage_cppipe_modules.csv": "2b0e620a3a040af285b4947e3e16b0afea90443f5c4fef15c51c61a7a6601c6d", + "benchmark/results/labmeeting_20260513/official30_well_throughput/figures/module_coverage_cppipe_settings.csv": "12fa844a0682baee44cc16b5a87a192a5f9c2173e54fa02c823d18c30283f087", + "benchmark/results/labmeeting_20260513/official30_well_throughput/figures/module_coverage_semantic_families.csv": "5b65b12926b490571339ef72df7270a179c72f5c9821a644958856d43be78b0c", + "benchmark/results/labmeeting_20260513/official30_well_throughput/figures/presentation_figure_index.md": "6c285b83ca84ab132bec1622f43a93db7653541a072a16562230f5cd97f62959", + "benchmark/results/matched_batch_concurrency_20260923/README.md": "60b8fe63b52a2d10de8a87cbf4d0d9cbe49212e747b0a6814240181f2cd67ae6", + "benchmark/results/matched_batch_concurrency_20260923/candidate_evidence/-1/measured_pipeline_receipt.json": "9866c2429dc84a9bf6eac52d1ef7f442ba2498f1d5c08bb2cc0d30cf759dae2f", + "benchmark/results/matched_batch_concurrency_20260923/candidate_evidence/-1/submitted_global_config.py.txt": "bc1af8635d4850ed123463438c15c7eb9b0c44cdc031f81e3932c9ebc6759006", + "benchmark/results/matched_batch_concurrency_20260923/candidate_evidence/-1/submitted_pipeline.py.txt": "c2eaa0a5de13dc877d51d9f6c1ad39199f4dfb1a658ae3013b8bb832393e75af", + "benchmark/results/matched_batch_concurrency_20260923/candidate_evidence/-1/zmq_results_summary.json": "c63b27185b82823f97e24b91f9dfecf20c1e0a803b5a39a5ed78c38e863af1ae", + "benchmark/results/matched_batch_concurrency_20260923/candidate_evidence/0/measured_pipeline_receipt.json": "2401ce5a473af0746c9f9c74c39153d8fa5be8071f3dd51d44d301b4fbb6011e", + "benchmark/results/matched_batch_concurrency_20260923/candidate_evidence/0/observation.pkl": "5a9bcb31f2fd33a5c91611af7da99c161317aba890442383831f2cde9e0c8f97", + "benchmark/results/matched_batch_concurrency_20260923/candidate_evidence/0/submitted_global_config.py.txt": "3e25715a0ff1de90782d8006eea3c3e90b6abcf2b7481b363b1ed722eb69e0f6", + "benchmark/results/matched_batch_concurrency_20260923/candidate_evidence/0/submitted_pipeline.py.txt": "adce89e9fab8e4267da3b242ccd33085d45d7c63630fe898a3966fcb015e3626", + "benchmark/results/matched_batch_concurrency_20260923/candidate_evidence/0/zmq_results_summary.json": "d0fe961c00a9f1d666159d8d96ac5eae6f9f36b6e308833281cab96232273955", + "benchmark/results/matched_batch_concurrency_20260923/candidate_evidence/1/measured_pipeline_receipt.json": "6af567d895f43ea2ff27712d9ade92db08b51b638f7eb1c05dd5713e71f03d8a", + "benchmark/results/matched_batch_concurrency_20260923/candidate_evidence/1/observation.pkl": "c863f9586ac64a0e582da98eb9e39cf16bfcafc081c7c85eed5a0abcdf2f8ba8", + "benchmark/results/matched_batch_concurrency_20260923/candidate_evidence/1/submitted_global_config.py.txt": "cb907e38b4a1a4ef993c1039603d30446bc30cb6e34da91ccf5d9c44628f1cf5", + "benchmark/results/matched_batch_concurrency_20260923/candidate_evidence/1/submitted_pipeline.py.txt": "bc5d590f7cb47967d8ac5ca80eedd164a4e915685ba027b8fed279f36112aabe", + "benchmark/results/matched_batch_concurrency_20260923/candidate_evidence/1/zmq_results_summary.json": "9ed64039ba39df1c66689b556a472a157bbc8096e8fd6c276d721532488ec3b3", + "benchmark/results/matched_batch_concurrency_20260923/candidate_evidence/2/measured_pipeline_receipt.json": "e65ff346a549f15d45c19544bb5e0d69f9070bd338609c300068853b89d341cd", + "benchmark/results/matched_batch_concurrency_20260923/candidate_evidence/2/observation.pkl": "0dc5d4edd08bc2c6c85fba1b30ba9f4c47da8c4f423cf8cda0e25b59c3f4ee62", + "benchmark/results/matched_batch_concurrency_20260923/candidate_evidence/2/submitted_global_config.py.txt": "e19f897158809ec122e39cac05398fba1b65ba328a8ff48f47bd77795f383e31", + "benchmark/results/matched_batch_concurrency_20260923/candidate_evidence/2/submitted_pipeline.py.txt": "56ef5e650382b307d1e695b3db41e7827050751b895cd91fba55834355725837", + "benchmark/results/matched_batch_concurrency_20260923/candidate_evidence/2/zmq_results_summary.json": "542822f3bd0fd93411fe42edfa382a11e72ffa9b81a365c168ae9524f09a5955", + "benchmark/results/matched_batch_concurrency_20260923/candidate_report.json": "ee971d5c0b16d518a7b5019689235542df9cdf0a11037be51e341934f8ad4d54", + "benchmark/results/matched_batch_concurrency_20260923/equivalence_policy.json": "00a8c59aa435ef235aee9e5a05cbfc32f03f0ca9f6fd0aff89085d91118b49bf", + "benchmark/results/matched_batch_concurrency_20260923/imported_pipeline.py.txt": "5f3129bfa97e5f542e6d56912e965f04ba9f96ca6ea0707800a62606d095f412", + "benchmark/results/matched_batch_concurrency_20260923/input_inventory.json": "76d136a7abca37e1543b521e15e31f2ba8ebf5964608f65e1c470cdaa7c76f83", + "benchmark/results/matched_batch_concurrency_20260923/native_preparation/native_cellprofiler_headless/Translocation_final.cppipe": "3992ce36c9d5b6c42c7b6b6d5e1fcef59563d9e244d38613b257c848a4e10090", + "benchmark/results/matched_batch_concurrency_20260923/native_report.json": "5fd212d18255a77ff0263d77cae015ada81845b835ff6b7bc6fdb38ddd93ffd9", + "benchmark/results/matched_batch_concurrency_20260923/native_request.json": "7ba2ee85e6732acb1cf15d06d83e3e4131cd21b8971377a25aa2bc3b58cb1d51", + "benchmark/results/matched_batch_concurrency_20260923/native_shards/0_stderr.log": "1bfef94ea190e1c68ffc1d9320e86bcdec847795d6b9cd408097422784d581fc", + "benchmark/results/matched_batch_concurrency_20260923/native_shards/1_stderr.log": "0f18fce288e4880a1051025ce1b28631b0f68befe8c4d1300bae5f9c988dfab6", + "benchmark/results/matched_batch_concurrency_20260923/native_shards/equivalence.json": "e47c16d8ec7ea8f1376d729e775c37f4b2c06645064a3a340ea20970dd226c78", + "benchmark/results/matched_batch_concurrency_20260923/native_shards/reports.json": "32a2c15221059d81ca23dfd86b7d8443aefa8210b4334fdb28b830cfbf255bac", + "benchmark/results/matched_batch_concurrency_20260923/native_shards/request_0.json": "178e897c0b5dcd68d7d70e0aeff0f475b35c85034646e8b54fab27f61ecfb1ac", + "benchmark/results/matched_batch_concurrency_20260923/native_shards/request_1.json": "8d02d9255123c21aa0ec40b9f8fde70ff2a7f16bd95d1828286b8c60e0d470c0", + "benchmark/results/matched_batch_concurrency_20260923/native_stderr.log": "1bfef94ea190e1c68ffc1d9320e86bcdec847795d6b9cd408097422784d581fc", + "benchmark/results/matched_batch_concurrency_20260923/pilot_provenance.json": "895cb585b20dddbe9f6448fc022c01c309dbc98d0fdd0b208a929197ae89d08b", + "benchmark/results/matched_batch_concurrency_20260923/report.json": "5da28c0be5a78866488411333f0cd06bfd9d1152a822a23e04ce2c1949c9fb8e", + "benchmark/results/matched_batch_concurrency_fork_20260923/README.md": "bb846d0cff0071644dde0978285005d4acbaedf3d9ccbd86c5fa0fe47aa9ed42", + "benchmark/results/matched_batch_concurrency_fork_20260923/candidate_evidence/-1/measured_pipeline_receipt.json": "0083fac025224c4a82a8606e0cb9bf8c8b6eb479898ddc9aee3b183f99fac451", + "benchmark/results/matched_batch_concurrency_fork_20260923/candidate_evidence/-1/submitted_global_config.py.txt": "dcdc73cbfed64fd31f961b9a4fdc92ee821aca10ad4cdaacc3e8e07e901a740b", + "benchmark/results/matched_batch_concurrency_fork_20260923/candidate_evidence/-1/submitted_pipeline.py.txt": "cc3158f25ee58d716faa1c10c67ef49d2a7afd8b9e36b6bd657aa4dc15d5504d", + "benchmark/results/matched_batch_concurrency_fork_20260923/candidate_evidence/-1/well_throughput_progress_events.csv": "fd6d55f4b93b648a57948cd629ef53e0783a173ac5ae8ba78f1c021ba0fc2807", + "benchmark/results/matched_batch_concurrency_fork_20260923/candidate_evidence/-1/well_throughput_step_timings.csv": "544336b987f2c64bdcec61d88dff40f1fbfb628a9ac07d93391ce07a3a1ebc2e", + "benchmark/results/matched_batch_concurrency_fork_20260923/candidate_evidence/-1/well_throughput_worker_lanes.csv": "26ef335eba0a99c12c0e3e5951be4ce18d3a2d551c6b698203d1cb9653f72dd9", + "benchmark/results/matched_batch_concurrency_fork_20260923/candidate_evidence/-1/zmq_results_summary.json": "76a9512d8e528d325c426e719651684cdf9c71a571524d6fecd82a897552b95e", + "benchmark/results/matched_batch_concurrency_fork_20260923/candidate_evidence/0/measured_pipeline_receipt.json": "7bd5af04aa29740ef6af81474e8b00009c61abb0c1540e53b2c942783ee6bc58", + "benchmark/results/matched_batch_concurrency_fork_20260923/candidate_evidence/0/runtime_outcomes.pkl.gz": "4fcebaa56d982fb0462e82a237dc2a08771343ac2f3706dc637948f7b0cf2c61", + "benchmark/results/matched_batch_concurrency_fork_20260923/candidate_evidence/0/submitted_global_config.py.txt": "a23c1ad757b04d053a7e93672431bad46eeab38cac4cd0b8ce4fabec1ce9ff53", + "benchmark/results/matched_batch_concurrency_fork_20260923/candidate_evidence/0/submitted_pipeline.py.txt": "c9308c39f21ec04ab7687264cf22d962691cd888298813658f48277c9e5b2fa3", + "benchmark/results/matched_batch_concurrency_fork_20260923/candidate_evidence/0/well_throughput_progress_events.csv": "ee3e23732629f8287ba47a9dd74b6e67f8919c5ce70f4fbb08610092614e2954", + "benchmark/results/matched_batch_concurrency_fork_20260923/candidate_evidence/0/well_throughput_step_timings.csv": "904007268550dd212f560e856c7766751048a601d784766f8691341a1d31cdc0", + "benchmark/results/matched_batch_concurrency_fork_20260923/candidate_evidence/0/well_throughput_worker_lanes.csv": "6461af40c8430e4bbbc6aee48635a6752914908a9d12cffd4d08d494bc6c22cd", + "benchmark/results/matched_batch_concurrency_fork_20260923/candidate_evidence/0/zmq_results_summary.json": "8334e761e1f3913f02051d86f39174225ab8825910d3170a138b9052e7519255", + "benchmark/results/matched_batch_concurrency_fork_20260923/candidate_evidence/1/measured_pipeline_receipt.json": "4470b9200832aa5a681f5269a299fb3af4772afefee0e49c8e6ab988a0daaa7a", + "benchmark/results/matched_batch_concurrency_fork_20260923/candidate_evidence/1/runtime_outcomes.pkl.gz": "4c21fc7629036cf7e5e24f5b77a32ae2a07426b32beb01cf7d1c25fee57f9699", + "benchmark/results/matched_batch_concurrency_fork_20260923/candidate_evidence/1/submitted_global_config.py.txt": "1c855b0e7d1e26ae42d6fa0fb85cdb073f5a86359b6a224dbd5d25701acc1910", + "benchmark/results/matched_batch_concurrency_fork_20260923/candidate_evidence/1/submitted_pipeline.py.txt": "e896b861d9fb3b90485f8d66e7a3f27cac9610e35c96ef78567e04b707710a23", + "benchmark/results/matched_batch_concurrency_fork_20260923/candidate_evidence/1/well_throughput_progress_events.csv": "55b111df9d55a1007eb5e119a5c1eba89119c21b4c77e17b7618bb3013e7d1f1", + "benchmark/results/matched_batch_concurrency_fork_20260923/candidate_evidence/1/well_throughput_step_timings.csv": "8a50bb8297975d2724808670d8982230a672c0f6608c741ba3179dc28580ff9a", + "benchmark/results/matched_batch_concurrency_fork_20260923/candidate_evidence/1/well_throughput_worker_lanes.csv": "9c5f7fe1c61a52526f2e523dd844d39a9d9fe25035cf6743ac3aefe6d497877c", + "benchmark/results/matched_batch_concurrency_fork_20260923/candidate_evidence/1/zmq_results_summary.json": "f8cf711bad9840c4239394c640f53aeb9a810e998d954e4e43d5be06518b5b06", + "benchmark/results/matched_batch_concurrency_fork_20260923/candidate_evidence/2/measured_pipeline_receipt.json": "8d3f002dbc32484d64e970d8656455396bba49384f16a1d8813f1e0a8f3bce19", + "benchmark/results/matched_batch_concurrency_fork_20260923/candidate_evidence/2/runtime_outcomes.pkl.gz": "df29c72f4d4a012aa8beb25f4af1c06fd34b64dd0ec3cd88777b7f6ea549fefc", + "benchmark/results/matched_batch_concurrency_fork_20260923/candidate_evidence/2/submitted_global_config.py.txt": "8e3ec609e6d94a7c3c30922b1a65a50acb25f34428bcd2cff78135560ed78f86", + "benchmark/results/matched_batch_concurrency_fork_20260923/candidate_evidence/2/submitted_pipeline.py.txt": "62de8041a654ffd823020783c47124e58b16753e45c2959f7046dda9cd6a2847", + "benchmark/results/matched_batch_concurrency_fork_20260923/candidate_evidence/2/well_throughput_progress_events.csv": "5ea8e78db6513305d9d8e91e122224385ae321b74b8215bd68acae02e54bd55a", + "benchmark/results/matched_batch_concurrency_fork_20260923/candidate_evidence/2/well_throughput_step_timings.csv": "001cb532bc19c5ada6ffb94a922d5ad3beab71cb1871beb203bf43cd8cf4ee1e", + "benchmark/results/matched_batch_concurrency_fork_20260923/candidate_evidence/2/well_throughput_worker_lanes.csv": "34e98ec0bd5dc30a1b09d4c1bb1aeba85191f4b2c85270ff9669329d1baf9b0b", + "benchmark/results/matched_batch_concurrency_fork_20260923/candidate_evidence/2/zmq_results_summary.json": "6e3aa985ddbd3c70687559cd927772f100acd6e93da4b453da5d674634a32ac0", + "benchmark/results/matched_batch_concurrency_fork_20260923/candidate_report.json": "5c47c4d0c8b81b5d548b49ec474c22e585f44ef0781424ab508850d7b425e04e", + "benchmark/results/matched_batch_concurrency_fork_20260923/equivalence_policy.json": "00a8c59aa435ef235aee9e5a05cbfc32f03f0ca9f6fd0aff89085d91118b49bf", + "benchmark/results/matched_batch_concurrency_fork_20260923/imported_pipeline.py.txt": "5f3129bfa97e5f542e6d56912e965f04ba9f96ca6ea0707800a62606d095f412", + "benchmark/results/matched_batch_concurrency_fork_20260923/native_execution.cppipe": "3992ce36c9d5b6c42c7b6b6d5e1fcef59563d9e244d38613b257c848a4e10090", + "benchmark/results/matched_batch_concurrency_fork_20260923/native_report.json": "f51d1ba3f09a308c8548347178cc3e5b9641327d21d74aaf7b4a0defa08ab6bf", + "benchmark/results/matched_batch_concurrency_fork_20260923/native_request.json": "c08455531b719b407b976417fbfa2b9ebdfb686ee888c9e8d17fd847f56652ec", + "benchmark/results/matched_batch_concurrency_fork_20260923/native_shards/0_stderr.log": "1bfef94ea190e1c68ffc1d9320e86bcdec847795d6b9cd408097422784d581fc", + "benchmark/results/matched_batch_concurrency_fork_20260923/native_shards/1_stderr.log": "0f18fce288e4880a1051025ce1b28631b0f68befe8c4d1300bae5f9c988dfab6", + "benchmark/results/matched_batch_concurrency_fork_20260923/native_shards/equivalence.json": "852ec06a3d52c267733cfc94b5f9915ea18730a2ba0dae9d8731c146a342d9ba", + "benchmark/results/matched_batch_concurrency_fork_20260923/native_shards/reports.json": "fd3a3e44d14295352b4c2877d53d6addc1b6ad97d847bdd36acf26b301fafdf1", + "benchmark/results/matched_batch_concurrency_fork_20260923/native_shards/request_0.json": "f891535796d897329a337d43a249cdba513642fc12d3b1f163f9a96716062b3b", + "benchmark/results/matched_batch_concurrency_fork_20260923/native_shards/request_1.json": "f63a333884c76ffcbd241fadd19826c49b816b1a68b50cb092b549cebf72c826", + "benchmark/results/matched_batch_concurrency_fork_20260923/native_stderr.log": "1bfef94ea190e1c68ffc1d9320e86bcdec847795d6b9cd408097422784d581fc", + "benchmark/results/matched_batch_concurrency_fork_20260923/pilot_provenance.json": "4ad80909a00a32dd67bdb919293800a02c015d1437aec2bc4c5bd81c419b6583", + "benchmark/results/matched_batch_concurrency_fork_20260923/report.json": "6dc6375fe8284b8171cab9af7dba3c65637ebef64f30056acd7610a752e3b172", + "benchmark/results/matched_batch_concurrency_fork_20260923/source_workspace_metadata.json": "aff9aa0b2d88404a3a6c38c1c1949ba0d1504753bf2b7a93d14f88142602b9fb", + "benchmark/results/matched_batch_pilot_20260915/README.md": "a166608b61e1809b6cd3e80a3dc0f5bd1f7eac87e65fc66ea1cb6c8d544e472f", + "benchmark/results/matched_batch_pilot_20260915/candidate_probe.json": "b8876f6f986f15a3e727b08b134a6545b7fb4bfadab98b231c6edde7bb21141f", + "benchmark/results/matched_batch_pilot_20260915/design.md": "9aa0ae40df73c80c3af94af43ad3f13568d4d56313b04e17057142405974b75f", + "benchmark/results/matched_batch_pilot_20260915/native_report.json": "bd6bacda979f7c1502565471d4fbcc449dfd27294d57b660ee5d77d357a93c14", + "benchmark/results/matched_batch_pilot_20260915/native_request.json": "134ed45e59f38120e3811cadfce6edbb2e24cd17c07a7e12dcf5cc6b8bc44c56", + "benchmark/results/matched_batch_pilot_20260915/pilot_driver.py": "3e96ef4275a25e72fee905b73fcd91c859ec878e26d3d9f51fcde72ca93028f6", + "benchmark/results/matched_batch_pilot_20260915/receipt.json": "e92e3ecbc1c0ea0db2a393d7ce1e5c2141df82ebd96b75916b842686439a00d9", + "benchmark/results/matched_batch_pilot_v2_20260923/README.md": "27e71b9cf67eca46790ad262d016f6d523d3d885d320f7518702ddf5e2629c00", + "benchmark/results/matched_batch_pilot_v2_20260923/candidate_evidence/-1/measured_pipeline_receipt.json": "c86ba66f43f194472ff28f49ce97559ce5182fe26061d72c4898ad90d92784b2", + "benchmark/results/matched_batch_pilot_v2_20260923/candidate_evidence/-1/submitted_global_config.py.txt": "c36e49f1fbf34cbbe4b4cfbb6ccd50b93d785c37b01c4a2c0aea91adb2179e51", + "benchmark/results/matched_batch_pilot_v2_20260923/candidate_evidence/-1/submitted_pipeline.py.txt": "580f0bb142048d758eee1bb88fdb18ea45a45e36328cf36253dce8e5c077006b", + "benchmark/results/matched_batch_pilot_v2_20260923/candidate_evidence/-1/zmq_results_summary.json": "59b17135e44da0a99c73680f5f0d495308441c641f609018401cbdc73f82b2d5", + "benchmark/results/matched_batch_pilot_v2_20260923/candidate_evidence/0/measured_pipeline_receipt.json": "789af27f2c388f6a4104655ce933ac6ee23892fcaa05fd8d5ca269a5a8e3ce18", + "benchmark/results/matched_batch_pilot_v2_20260923/candidate_evidence/0/submitted_global_config.py.txt": "82448464297c2ef2ca6701aeb032daaf29a5e0a73bcf98bcc23b5c63bb333b3a", + "benchmark/results/matched_batch_pilot_v2_20260923/candidate_evidence/0/submitted_pipeline.py.txt": "5417d3ef4ceb4dd0be9d1b6d6a051bf3449dbeff59549fb302f38e627b0fd81b", + "benchmark/results/matched_batch_pilot_v2_20260923/candidate_evidence/0/zmq_results_summary.json": "36b533a4e4145f93b7d037fd5f5863d82ce0fc40c1ce5996efe49bc67442ac9d", + "benchmark/results/matched_batch_pilot_v2_20260923/candidate_evidence/1/measured_pipeline_receipt.json": "5fa320171d0373bb188340f0768a3559bb711f7b792f993bd50e31f3d52b9853", + "benchmark/results/matched_batch_pilot_v2_20260923/candidate_evidence/1/submitted_global_config.py.txt": "36a7537d372cbfd7e50f11563379dc58fbcf5b35f9dbed3b1ed66be9e6758bfd", + "benchmark/results/matched_batch_pilot_v2_20260923/candidate_evidence/1/submitted_pipeline.py.txt": "69831b8ed1dc5921a0c3045e7e62ab676807e3ccf663a9113134189e14b1e09f", + "benchmark/results/matched_batch_pilot_v2_20260923/candidate_evidence/1/zmq_results_summary.json": "ca4f221cbcf2323271f5a6c73e489d4db34f740d4cceca79aa5bb6cfc003ab05", + "benchmark/results/matched_batch_pilot_v2_20260923/candidate_evidence/2/measured_pipeline_receipt.json": "d76e3a25787775b48f759232a530083026edc5191f48e2e49814d80c68505c90", + "benchmark/results/matched_batch_pilot_v2_20260923/candidate_evidence/2/submitted_global_config.py.txt": "83036fe3f0210e750d891202897bbf235e65c8b3db0599f7f83cc4d8303cb632", + "benchmark/results/matched_batch_pilot_v2_20260923/candidate_evidence/2/submitted_pipeline.py.txt": "daa78c85f51b44204a9ff04b6f2fe17a19f72c724e36c4bf79026eb56e49007b", + "benchmark/results/matched_batch_pilot_v2_20260923/candidate_evidence/2/zmq_results_summary.json": "8a96218334240be93d4ec7772eab9d50bda1c32c30e6bd7686fa27f77a5f39ee", + "benchmark/results/matched_batch_pilot_v2_20260923/candidate_report.json": "22fdb17e9d60f0a905f858fa9aac3c053b859a09acd141259fa7a592c4702796", + "benchmark/results/matched_batch_pilot_v2_20260923/native_pipeline.cppipe": "3992ce36c9d5b6c42c7b6b6d5e1fcef59563d9e244d38613b257c848a4e10090", + "benchmark/results/matched_batch_pilot_v2_20260923/native_report.json": "bfbfac3c0a07816baa507336c7795195737eb668ec0c966ba39f19ca53d2d8a3", + "benchmark/results/matched_batch_pilot_v2_20260923/native_request.json": "2f1f8fa389ab1b8a9f45a95b6decce809dbf31b57353d16d9a97b2f0d5862914", + "benchmark/results/matched_batch_pilot_v2_20260923/pilot_provenance.json": "edc1fc18ea0a58b852c0ae0969fc27cae27f75f618afef8deccbb26b4a79026b", + "benchmark/results/matched_batch_pilot_v2_20260923/report.json": "fbd7c078690dd0a0db12ca21b68fe724e90cd0a881c8a27ef2b0c507e2080416", + "benchmark/results/matched_batch_pilot_v2_20260923/strict_confirmation/candidate_evidence/-1/measured_pipeline_receipt.json": "ed4cc36936157639c5372f7db3970612fd81af9163df907eb8d53143ea00ff9b", + "benchmark/results/matched_batch_pilot_v2_20260923/strict_confirmation/candidate_evidence/-1/submitted_global_config.py.txt": "4e8121fddf7db72432b7715ef8e205406b02f86ad0a827da87b9c7f62039ef2f", + "benchmark/results/matched_batch_pilot_v2_20260923/strict_confirmation/candidate_evidence/-1/submitted_pipeline.py.txt": "8196fb569bf5bf67545ac4495eb49ae9307689f2ad75544f14b8ade84869ed86", + "benchmark/results/matched_batch_pilot_v2_20260923/strict_confirmation/candidate_evidence/-1/zmq_results_summary.json": "f8957c2160eca3f40d7a42f73c3985647e921c8f070a169686eb25c65011831c", + "benchmark/results/matched_batch_pilot_v2_20260923/strict_confirmation/candidate_evidence/0/measured_pipeline_receipt.json": "1d38731b138dd0fb27055a0a5eeebf8fb1c27b78bc2f3bc04ab23d57ee9cca56", + "benchmark/results/matched_batch_pilot_v2_20260923/strict_confirmation/candidate_evidence/0/submitted_global_config.py.txt": "d9f27b5a6c2413e0f4ad3eda849a7713d42bf1de6d9b63fcc65ba48abcf6509a", + "benchmark/results/matched_batch_pilot_v2_20260923/strict_confirmation/candidate_evidence/0/submitted_pipeline.py.txt": "51de99b51ff19707ef852264b37ebd7520db77e1620fdeb930de9eefe1a65784", + "benchmark/results/matched_batch_pilot_v2_20260923/strict_confirmation/candidate_evidence/0/zmq_results_summary.json": "4d56fd2b5591e14fca632b199f0ff65b95927c92b4b8b3487cf2930ec8c5ea8d", + "benchmark/results/matched_batch_pilot_v2_20260923/strict_confirmation/candidate_report.json": "7e2bad5c1d555b8f552ea2e408b05c7f7d4fd190ad560e1d09d97bd8a9d1dd04", + "benchmark/results/matched_batch_pilot_v2_20260923/strict_confirmation/equivalence_policy.json": "00a8c59aa435ef235aee9e5a05cbfc32f03f0ca9f6fd0aff89085d91118b49bf", + "benchmark/results/matched_batch_pilot_v2_20260923/strict_confirmation/native_report.json": "b48874f78a4d1efe8135a3106ddef8325a9bf5fcc9ed67a87faf26c3014dd07d", + "benchmark/results/matched_batch_pilot_v2_20260923/strict_confirmation/native_request.json": "df651776f933dd547a9cfdfeb389889161527450732da06f89f1bf74c018e932", + "benchmark/results/matched_batch_pilot_v2_20260923/strict_confirmation/pilot_provenance.json": "563ea0c75d2437b7e9af622f67a86e36425f0cc9f2a0dfe2bed099b6cf47fa99", + "benchmark/results/matched_batch_pilot_v2_20260923/strict_confirmation/report.json": "e83e3001d29b87e36188154aabffd3a697a0b7a0c10b142d2932d07a76452ae4", + "benchmark/results/matched_bbbc022_20260923_rc5/README.md": "507c79f3ed2b1aec29d283df51b95bdf847b762111ef09ab5105d5baf9f42a28", + "benchmark/results/matched_bbbc022_20260923_rc5/candidate_evidence/-1/measured_pipeline_receipt.json": "e1e5a944b9d82cc6073755945abfd8b80233b227b745c07c3cdad7d7a25602aa", + "benchmark/results/matched_bbbc022_20260923_rc5/candidate_evidence/-1/observation.pkl": "90ca7dde3cbf832403fa86d8e2020439e041f03402bf8f82365dfae5a453474a", + "benchmark/results/matched_bbbc022_20260923_rc5/candidate_evidence/-1/submitted_global_config.py.txt": "b139a9640a8a2be14d9782a21b14ef71fc8762375c4a5fe0afd3185bbdccbb7a", + "benchmark/results/matched_bbbc022_20260923_rc5/candidate_evidence/-1/submitted_pipeline.py.txt": "5df03db5eb47c5f714b1163c1d325fa2a62a38cb396ddc8779200dd2db8a9eb2", + "benchmark/results/matched_bbbc022_20260923_rc5/candidate_evidence/-1/well_throughput_progress_events.csv": "e770d6fc773589f897db479a1299ef93c1f1e070834d509b0af62eb77a034ce2", + "benchmark/results/matched_bbbc022_20260923_rc5/candidate_evidence/-1/well_throughput_step_timings.csv": "10fe559789de7d288f580ce82aceb73c2402a204279c12228e6f9ecc64768bfe", + "benchmark/results/matched_bbbc022_20260923_rc5/candidate_evidence/-1/well_throughput_worker_lanes.csv": "0812d86c57c5d70e779f3e2192ba7105fefe0d2fc2d6b826dbc95b3eb51608ec", + "benchmark/results/matched_bbbc022_20260923_rc5/candidate_evidence/-1/zmq_results_summary.json": "92b21d78830abb6e82acd72f3c906d7b2af64c2b15501381e63e7f531886c778", + "benchmark/results/matched_bbbc022_20260923_rc5/candidate_evidence/0/measured_pipeline_receipt.json": "f4017ece68a2289232deafc4fd30d6c6b32e43ba681fb9812e6ed069ce5bf8ec", + "benchmark/results/matched_bbbc022_20260923_rc5/candidate_evidence/0/observation.pkl": "68c10b08756f0038c705e1f71e0b6c402144794209ff01602bb471b610f6c199", + "benchmark/results/matched_bbbc022_20260923_rc5/candidate_evidence/0/submitted_global_config.py.txt": "2487e2067157ae5087f31adffed7a11233f95ae1428ba37a64b2ee596729f6df", + "benchmark/results/matched_bbbc022_20260923_rc5/candidate_evidence/0/submitted_pipeline.py.txt": "cbbeaaacf8460718694703346ec04572ee998da456997a5fcf3cab413bc857b5", + "benchmark/results/matched_bbbc022_20260923_rc5/candidate_evidence/0/well_throughput_progress_events.csv": "e68e5101956a7f25bb9b080b5193f1a5f82435051500a8a208e0db260bb29c22", + "benchmark/results/matched_bbbc022_20260923_rc5/candidate_evidence/0/well_throughput_step_timings.csv": "bf42e9fe69d20b7b768d2256488f624ce496d1af72566902066d2c1c4114b308", + "benchmark/results/matched_bbbc022_20260923_rc5/candidate_evidence/0/well_throughput_worker_lanes.csv": "5e7a191aaab21f15bb38d00ce3e32951c71e62838cc420db08d25d4006cd8352", + "benchmark/results/matched_bbbc022_20260923_rc5/candidate_evidence/0/zmq_results_summary.json": "2adf72fe2b7866af28aa1bc1f16f958040f30f26bedf4778883795ea3be15e44", + "benchmark/results/matched_bbbc022_20260923_rc5/candidate_report.json": "1761878cf8f03b7e27abd968f4216b40a9ffb5aef4cf35f3cbdd39623f5befc1", + "benchmark/results/matched_bbbc022_20260923_rc5/equivalence_policy.json": "00a8c59aa435ef235aee9e5a05cbfc32f03f0ca9f6fd0aff89085d91118b49bf", + "benchmark/results/matched_bbbc022_20260923_rc5/imported_pipeline.py.txt": "0e4c0714de41ce665725a63bf47385ce71f135b61b9c8503b40db5256862fad4", + "benchmark/results/matched_bbbc022_20260923_rc5/native_preparation/native_cellprofiler_headless/BBBC022_Analysis_Final.cppipe": "cf77de35d244d264a64e87b37bd5da3871c64b227c8f297b2be39d87d315f582", + "benchmark/results/matched_bbbc022_20260923_rc5/native_report.json": "b1bfa2bf2e24d6ffbd8801626392fd31bf609ebdf9e6d83209c4b872de5ec3a1", + "benchmark/results/matched_bbbc022_20260923_rc5/native_request.json": "4266132b87bfed663c84aecb9744e43543a3f6b534b909c36db46a5613c4174f", + "benchmark/results/matched_bbbc022_20260923_rc5/native_shards/0_stderr.log": "1ff3a3b82ae3762e019bd3f796a6b3374850e4dea9dd4f31503df16204f6da5f", + "benchmark/results/matched_bbbc022_20260923_rc5/native_shards/0_stdout.log": "a3565fdcda5edfcc323bef428d5352d535a184f23b9c66c24763c53a879385f4", + "benchmark/results/matched_bbbc022_20260923_rc5/native_shards/1_stderr.log": "622dfab87d0b78fbb8d6ae056e550b141713c4fd3ede992b6489abb0deb04ae5", + "benchmark/results/matched_bbbc022_20260923_rc5/native_shards/1_stdout.log": "33de2d6b0d07eabc330206edbc19c5b5f1069708be2e3908f993765c03b94e62", + "benchmark/results/matched_bbbc022_20260923_rc5/native_shards/equivalence.json": "d68e9727efe1662a7a8048728e80cae706ce14bb85b820ae666fe9633f8112c1", + "benchmark/results/matched_bbbc022_20260923_rc5/native_shards/reports.json": "cf2049d58327afb9a3abc92e1021d54d64ce9c85ee1df0e1f7e995cabf79fd35", + "benchmark/results/matched_bbbc022_20260923_rc5/native_shards/request_0.json": "619c39740e931dfeeb2d5c6690484f74dde442e78ce6fb59177e28cb7e7df099", + "benchmark/results/matched_bbbc022_20260923_rc5/native_shards/request_1.json": "d63562c5134ff475c63d0c5adcf87f6cf202516a2d843d4b5047359da584948a", + "benchmark/results/matched_bbbc022_20260923_rc5/native_stderr.log": "1ff3a3b82ae3762e019bd3f796a6b3374850e4dea9dd4f31503df16204f6da5f", + "benchmark/results/matched_bbbc022_20260923_rc5/native_stdout.log": "2ed77a8b1bdd5a30e52e480afb048e534cb7568d1620a271204e022773ed2c2f", + "benchmark/results/matched_bbbc022_20260923_rc5/pilot_provenance.json": "1ca278b4992268fa139fc092b18a8763a766faede15d49a736daa8739dbe292f", + "benchmark/results/matched_bbbc022_20260923_rc5/report.json": "1ee3f66fe77009574b6faadf4dfb98232b41fdfd83a2714bcfafb9d7a9170958", + "benchmark/results/official30_existing_image_refresh_20260914/current_endpoint_run/candidate_outputs/ExampleIlluminationCorrection_Example1_AllMethod/Illum.npy": "1e3255fc4af5a6fa45b4efbd656ae5187b8ec8c55c3a71c99766ebd351d6bd4f", + "benchmark/results/official30_existing_image_refresh_20260914/current_endpoint_run/candidate_outputs/cp_tutorial_translocation_final/A01_s001_w1_z001_t001_Overlay.tiff": "4bdc8e3891c6b1212388ec6b16bd2e132079c6237ed1b19498708f43e1447b1f", + "benchmark/results/official30_existing_image_refresh_20260914/current_endpoint_run/endpoint_logs/openhcs_zmq_server_port_23844_1789406886652996.log": "b2eb329a7596a5ac246d81fe4ea79ea6a6b70ba151ee98e9acf3244709cd6bd8", + "benchmark/results/official30_existing_image_refresh_20260914/current_endpoint_run/endpoint_logs/openhcs_zmq_server_port_23844_1789406920299344.log": "3ce30abd164706b959a1f3985dc033a9f93f603de092527453ffee5ef2b712d8", + "benchmark/results/official30_existing_image_refresh_20260914/current_endpoint_run/image_comparisons.csv": "3de4a7119f16164d2a951aa086d2bd5bb3a28df8eb459bc4d3c5e4bb92708956", + "benchmark/results/official30_existing_image_refresh_20260914/current_endpoint_run/observations.csv": "22f1b74a3351d0ae5401421c4f9bf9cdcb0345e02e48467f8c7bba85d43152c9", + "benchmark/results/official30_existing_image_refresh_20260914/current_endpoint_run/observations.jsonl": "41c395c5efc6c36665251add6a5fd1d8928b273313d6694e31dddfae887bfa5b", + "benchmark/results/official30_existing_image_refresh_20260914/current_endpoint_run/phase_timing.csv": "5f66956c197b3042aaf0d6324d1db43ec15695054a89bca7bd9687761b39a0c8", + "benchmark/results/official30_existing_image_refresh_20260914/current_endpoint_run/run_environment.json": "8f46ea996b6d17edad8ee593ff2a52b73ae1bc5cd79487a6b2af1bb64ebb244e", + "benchmark/results/official30_existing_image_refresh_20260914/current_endpoint_run/suite_metadata.json": "08602c90d5e4feae9686bdb5b763af8702e4ca7e35167572a990b468a9c161ef", + "benchmark/results/official30_existing_image_refresh_20260914/current_endpoint_run/summary.csv": "f3253c93ffb565eaf39e0471743187cbc2df15881f0816d873fe4292109d4554", + "benchmark/results/official30_existing_image_refresh_20260914/native_markers/cp_tutorial_advanced_segmentation_final.cellprofiler_benchmark_reference.json": "064541e52c452470cdec69dbac694aacad0aa9f6fbe1c43e5d815a792fb8405e", + "benchmark/results/official30_existing_image_refresh_20260914/native_markers/cp_tutorial_translocation_final.cellprofiler_benchmark_reference.json": "930c22f3c57c3ea5d2c9e1e4bf37c33217fbb74f53b4e53809aefd58e83bd2de", + "benchmark/results/official30_existing_image_refresh_20260914/stale_endpoint_run/fresh_pair/observations.csv": "270d5cf592b653465e1279e0045f5fa0eb0d5fee8b630cb990f9ec874deb076f", + "benchmark/results/official30_existing_image_refresh_20260914/stale_endpoint_run/fresh_pair/observations.jsonl": "c182b0b2a81fd5677ea46c63ec7421b688ad5dd40516c200ba7be86ea3b4fce9", + "benchmark/results/official30_existing_image_refresh_20260914/stale_endpoint_run/fresh_pair/phase_timing.csv": "216efe6ef84d275944949a047646653eb3f23b0cd0ef1cd54bb90847affe73d1", + "benchmark/results/official30_existing_image_refresh_20260914/stale_endpoint_run/fresh_pair/suite_metadata.json": "b3e26ab55c44b76a163f4c28a79cb7d16dc3ba2e2f5a8267dd165bb64d76e96c", + "benchmark/results/official30_existing_image_refresh_20260914/stale_endpoint_run/fresh_pair/summary.csv": "6bd827ac8f0a1ebbb75f42f0976f23fe929bb2452a46fbb23f24114235bd85b4", + "benchmark/results/official30_existing_image_refresh_20260914/stale_endpoint_run/image_comparisons.csv": "4902d565323bc979fb3a7391b57c7db7722e682ab52100774e8bfe737d909e2e", + "benchmark/results/official30_existing_image_refresh_20260914/stale_endpoint_run/retained_allmethod/observations.csv": "b12340ded2ea449b9ab4490f3af3cc20d876820891aa2fd50841836593c82e07", + "benchmark/results/official30_existing_image_refresh_20260914/stale_endpoint_run/retained_allmethod/observations.jsonl": "f160d2a571d0aaca792f2c926a4e4c79f3713104f485d2cf4a7d160fb1df9d15", + "benchmark/results/official30_existing_image_refresh_20260914/stale_endpoint_run/retained_allmethod/phase_timing.csv": "ba42b5806c07cceb3bd29974bd461e946a958dd32dbb81183337c2913a3f8c00", + "benchmark/results/official30_existing_image_refresh_20260914/stale_endpoint_run/retained_allmethod/suite_metadata.json": "6b32d1ca251e8276901f5dcabfc27fa24496d424b70fe8bcb590b4bc04f7969b", + "benchmark/results/official30_existing_image_refresh_20260914/stale_endpoint_run/retained_allmethod/summary.csv": "79f391269dc8b02c43d64334a463bfc3978ca2dd18eff2b50d256daba5503d6a", + "benchmark/results/official30_grid_shrink_regression_20260914/ExampleImagingFlowCytometryObjectsInGrid_openhcs.py.txt": "ba0a589e4eccff9a5fd9bd6de634890584921feb18720a0a4e2fbc66f25101cf", + "benchmark/results/official30_grid_shrink_regression_20260914/candidate_output/BF_cells_on_grid.csv": "9017cea6750607d456f73aa733024c91347502f27fc19cb5041455b0eaec174f", + "benchmark/results/official30_grid_shrink_regression_20260914/endpoint_logs/openhcs_zmq_server_port_23951_1789412266964266.log": "21d16c5557208c4d8a1881c04690ca3caaeb555fd42837eed41977786f4018ce", + "benchmark/results/official30_grid_shrink_regression_20260914/observations.csv": "e9241b436259a2d9a505fa1da592348caa51062ebddcff08d7e1f00012a3af40", + "benchmark/results/official30_grid_shrink_regression_20260914/observations.jsonl": "a0937dc5a01f22bb43dfee67944fc3ff47e505acf1004f524c74a28650b01c38", + "benchmark/results/official30_grid_shrink_regression_20260914/phase_timing.csv": "cf782533e09b73e75dbef961234a4775ea24cda8bebf8327f80508f1329344c5", + "benchmark/results/official30_grid_shrink_regression_20260914/run_environment.json": "02126009a3a96d6e975dcb01fb5eb3fe7a3c697608d714fd52381c63a2e3c745", + "benchmark/results/official30_grid_shrink_regression_20260914/suite_metadata.json": "e2ad92513dae6e44ffac91257ef23bac70ab5ba8f01e00aaab863afafaaf1a1b", + "benchmark/results/official30_grid_shrink_regression_20260914/summary.csv": "e504a8498d89f2ea88b1e955a992e630436352b7bc33b9324acf99d427a9b6be", + "benchmark/results/official30_reference_root_audit_20260914/reference_inventory.csv": "d17005e72abf61e803d0045e10448d743fd33c16e7dd1dfba7d0524326a2c68f", + "benchmark/results/official30_unified_value_comparison_20260916/README.md": "833ef86fc39e6adbb5ef7ea53217e735ae4154fc01ef96a6832ddc65f9fe27d8", + "benchmark/results/official30_unified_value_comparison_20260916/observations.csv": "b09fa5fd6926afa093e7eef47b26950458eab8afc31b6e029246a61ec6a41677", + "benchmark/results/official30_unified_value_comparison_20260916/observations.jsonl": "ee7f6862e1713ee55630d62226343d1162285b39975d98a68608b73d5e50e451", + "benchmark/results/official30_unified_value_comparison_20260916/phase_timing.csv": "bd2cec4749ac63e1bfd0a046ff9166ee2ca8e79c659dcadf15aaf19645c52f66", + "benchmark/results/official30_unified_value_comparison_20260916/reference_inventory.csv": "42c4001b156733d62a5936142263c9b1db169b30a2064e1e0bebfa9236f581ac", + "benchmark/results/official30_unified_value_comparison_20260916/summary.csv": "8858fd821172a13ff3914f3ee78451f32451472ba2c185df54712cc62ab33226", + "benchmark/results/official30_value_completion_20260914/committed_fixed_endpoint_run/artifact_comparisons.csv": "a2673a9edbe6193455aa760a90c6220b8c5ec50314e13a536bca99dc1f359dd4", + "benchmark/results/official30_value_completion_20260914/committed_fixed_endpoint_run/candidate_outputs/ExampleIlluminationCorrection_Example1_EachMethod/reference_image__CorrGreen.npy": "3c17148f0fad16738a23af55ac4e41692e6c2906808a7d83823331702b1b4f46", + "benchmark/results/official30_value_completion_20260914/committed_fixed_endpoint_run/candidate_outputs/ExampleIlluminationCorrection_Example2/reference_labels__LargeBlockCorrectedNuclei.tiff": "48e0ff1c313ce3e7154453d5b8ec53db9fcb6fb3ec8321f6eb5958c77e4b201f", + "benchmark/results/official30_value_completion_20260914/committed_fixed_endpoint_run/candidate_outputs/ExampleIlluminationCorrection_Example2/reference_labels__SmallBlockCorrectedNuclei.tiff": "0b3270a092b0882d2c34effdd28d62edb9cd0f594dda592fe0e05845c5abba09", + "benchmark/results/official30_value_completion_20260914/committed_fixed_endpoint_run/candidate_outputs/ExampleIlluminationCorrection_Example2/reference_labels__UncorrectedNuclei.tiff": "4543f3afec804f201126e640bae070fd4e44700ac7b0de99dec13e038b42377a", + "benchmark/results/official30_value_completion_20260914/committed_fixed_endpoint_run/candidate_outputs/ExampleIlluminationCorrection_Example3/reference_image__ConvexHullCorrWorm.npy": "9ba1259e4ca007c06f14be6946e32a86307ec2dfb9952b73fa2cc253ccae8b3a", + "benchmark/results/official30_value_completion_20260914/committed_fixed_endpoint_run/candidate_outputs/ExampleIlluminationCorrection_Example3/reference_image__PolynomialCorrected.npy": "8875da63a072c8f2de4f5cb707d779a064b663bf69aa0f304fe6fa74d4ff57a6", + "benchmark/results/official30_value_completion_20260914/committed_fixed_endpoint_run/candidate_outputs/cp4_supplement_combine_objects/reference_labels__CombinedObjects.tiff": "2d1994f6d02100c4f5e77fc3c077d14d873bad8b5a48023966bdbb6a06bb83e4", + "benchmark/results/official30_value_completion_20260914/committed_fixed_endpoint_run/candidate_outputs/cp_tutorial_translocation_start/reference_labels__Nuclei.tiff": "7cbac0da81e073728ee86f7265b960d1d90b75ece750b92c1bdfcbad99ffbdfd", + "benchmark/results/official30_value_completion_20260914/committed_fixed_endpoint_run/endpoint_logs/openhcs_zmq_server_port_23850_1789409446631210.log": "d0bd0975b748ed28d245db48d50150b83930b75f20347333671f7308cdc7fd8e", + "benchmark/results/official30_value_completion_20260914/committed_fixed_endpoint_run/endpoint_logs/openhcs_zmq_server_port_23850_1789409479132474.log": "2f7c6cd5eeb193fe97b7a067687896f2e0172cb9f41ebf8674f4a4e0137d366f", + "benchmark/results/official30_value_completion_20260914/committed_fixed_endpoint_run/endpoint_logs/openhcs_zmq_server_port_23850_1789409505323215.log": "61ee37213ec0a08fd21e4daabc9d171f9fd63ae1475b0e0305360c0788d693b7", + "benchmark/results/official30_value_completion_20260914/committed_fixed_endpoint_run/endpoint_logs/openhcs_zmq_server_port_23850_1789409525315168.log": "34a387c0d0fd5eba460ae8500a1623ea9c5b16a73b170034e301a88ea86c3dfc", + "benchmark/results/official30_value_completion_20260914/committed_fixed_endpoint_run/endpoint_logs/openhcs_zmq_server_port_23850_1789409543626042.log": "70d5337711f93a6e153fba48dabd46d92f356508627cf02bb6f15f716bdeb59a", + "benchmark/results/official30_value_completion_20260914/committed_fixed_endpoint_run/module_coverage_absorbed_modules.csv": "2acf6a4e7385137fceafad7a3591e93d3302ebc85fec14057d5be8af334e9f1e", + "benchmark/results/official30_value_completion_20260914/committed_fixed_endpoint_run/module_coverage_cppipe_modules.csv": "9294a9c694d85f1f2676cb33f41431d66a4986cfb7f07432d3a2015423521c1e", + "benchmark/results/official30_value_completion_20260914/committed_fixed_endpoint_run/module_coverage_cppipe_settings.csv": "02764a949ea6b3bb7037a65091a3dff2d715adbeffe998dcda43f78ac226c05f", + "benchmark/results/official30_value_completion_20260914/committed_fixed_endpoint_run/module_coverage_summary.json": "acdc4005dfc26d8a51b943a8bb43a6378cc667d68ebf60c7124c2d23dbca24b6", + "benchmark/results/official30_value_completion_20260914/committed_fixed_endpoint_run/observations.csv": "f6d6d0781c3afd330fb0bb9b4590f4ac4f3d3db2ef6a14b727f06c580e8cd8a3", + "benchmark/results/official30_value_completion_20260914/committed_fixed_endpoint_run/observations.jsonl": "7c3cbaac6e201995ef124a175e77538061a486b73810f3172ae1ec7fbb6b1179", + "benchmark/results/official30_value_completion_20260914/committed_fixed_endpoint_run/phase_timing.csv": "b2b4c193576e46200c238c0943c1343b67c740a51aa78f08205a7da8e5243325", + "benchmark/results/official30_value_completion_20260914/committed_fixed_endpoint_run/run_environment.json": "d361b9ee4345447ded8ad908cd7766351ff1ce61a5203e00e15e53dab8622541", + "benchmark/results/official30_value_completion_20260914/committed_fixed_endpoint_run/suite_metadata.json": "26b1bddf9a3e9c61b00784e81e55f7d3d55536d300eeb8c3ffa74bf91dc79e56", + "benchmark/results/official30_value_completion_20260914/committed_fixed_endpoint_run/summary.csv": "3b5f444d8f830e38effbe204d648039defea05dfffca8e83e300c396b460ce36", + "benchmark/results/official30_value_completion_20260914/current_endpoint_run/artifact_comparisons.csv": "85cc6483ceae8e7b7ff950209f298d33de9320eabe05a7e128764beb5fbb1568", + "benchmark/results/official30_value_completion_20260914/current_endpoint_run/candidate_outputs/ExampleIlluminationCorrection_Example1_EachMethod/reference_image__CorrGreen.npy": "3c17148f0fad16738a23af55ac4e41692e6c2906808a7d83823331702b1b4f46", + "benchmark/results/official30_value_completion_20260914/current_endpoint_run/candidate_outputs/ExampleIlluminationCorrection_Example2/reference_labels__LargeBlockCorrectedNuclei.tiff": "48e0ff1c313ce3e7154453d5b8ec53db9fcb6fb3ec8321f6eb5958c77e4b201f", + "benchmark/results/official30_value_completion_20260914/current_endpoint_run/candidate_outputs/ExampleIlluminationCorrection_Example2/reference_labels__SmallBlockCorrectedNuclei.tiff": "0b3270a092b0882d2c34effdd28d62edb9cd0f594dda592fe0e05845c5abba09", + "benchmark/results/official30_value_completion_20260914/current_endpoint_run/candidate_outputs/ExampleIlluminationCorrection_Example2/reference_labels__UncorrectedNuclei.tiff": "ca7d7941ef6beb2695c941c2274412650e393f380141fca70dfb242f5e4109e6", + "benchmark/results/official30_value_completion_20260914/current_endpoint_run/candidate_outputs/ExampleIlluminationCorrection_Example3/reference_image__ConvexHullCorrWorm.npy": "fb4a60bdedfb1164a12a7fcaab6a8d951bd6be35b8816f5cabb35d372df80ee7", + "benchmark/results/official30_value_completion_20260914/current_endpoint_run/candidate_outputs/ExampleIlluminationCorrection_Example3/reference_image__PolynomialCorrected.npy": "35f818f06250b6bd4b747027526cf8cd6b96eb56ae3df8e89471294843caa61a", + "benchmark/results/official30_value_completion_20260914/current_endpoint_run/candidate_outputs/cp4_supplement_combine_objects/reference_labels__CombinedObjects.tiff": "a42fdaebb6358e22d1089869c8ca19933acd0f5288d8f7643b0cefdd3683570b", + "benchmark/results/official30_value_completion_20260914/current_endpoint_run/candidate_outputs/cp_tutorial_translocation_start/reference_labels__Nuclei.tiff": "357890970564fc2750467ddece6ab9e7ef45977cc0b10ced3033624313681e75", + "benchmark/results/official30_value_completion_20260914/current_endpoint_run/endpoint_logs/openhcs_zmq_server_port_23843_1789406516482568.log": "86fd2e0ce55635c12f33ebc85f4d492aa2001c93d6adcb16e48345554820ac8c", + "benchmark/results/official30_value_completion_20260914/current_endpoint_run/endpoint_logs/openhcs_zmq_server_port_23843_1789406538957050.log": "5ce8af41470538bb4cdc8add5ef3788672ac8e75b0bd0c28e2281840bb21fe0e", + "benchmark/results/official30_value_completion_20260914/current_endpoint_run/endpoint_logs/openhcs_zmq_server_port_23843_1789406563469953.log": "d211d41c61fa4db6d9dab768537b91dbe628fe00e4448e54a9d20442704f55d8", + "benchmark/results/official30_value_completion_20260914/current_endpoint_run/endpoint_logs/openhcs_zmq_server_port_23843_1789406582510098.log": "e496703016e3a09513855b550caa3244d574a3724291f49f8a5d54dc504900e3", + "benchmark/results/official30_value_completion_20260914/current_endpoint_run/endpoint_logs/openhcs_zmq_server_port_23843_1789406600832518.log": "b8e1ae6c47158f6d76ae19733a1e6110debba60a5f0a53ce1ee22f36491774f6", + "benchmark/results/official30_value_completion_20260914/current_endpoint_run/observations.csv": "0cb87c3b785c01f0e1d9f11b5053269db2b2d570e2e20f987e7f5e065d5acdcf", + "benchmark/results/official30_value_completion_20260914/current_endpoint_run/observations.jsonl": "ba798d976b0031a46d18f2948240d553e7134cec355ff11450c9565bbcc1af24", + "benchmark/results/official30_value_completion_20260914/current_endpoint_run/phase_timing.csv": "00d1fd2f4c471f3ff3d05a2a03fffc72f98cbad47940320619c449fc6d53cbaf", + "benchmark/results/official30_value_completion_20260914/current_endpoint_run/run_environment.json": "1802aba67ee4820c548f050745d368b297652e182a8ecd05bec46949a9096385", + "benchmark/results/official30_value_completion_20260914/current_endpoint_run/suite_metadata.json": "45e5680f1d7033cc0e865f286cfffa4b0b3c43de9c51b0e6bf479ea8642df39b", + "benchmark/results/official30_value_completion_20260914/current_endpoint_run/summary.csv": "26a9200f34b97f78cd2b3ef82feab3f3c86eab8403b0d289b36463347f8a424f", + "benchmark/results/official30_value_completion_20260914/example3_intermediate_diagnostic/artifact_comparisons.csv": "b52085641deb680bda7daea3e3d5513224d8fb66e2556dfc8e12f210ea17cebc", + "benchmark/results/official30_value_completion_20260914/example3_intermediate_diagnostic/candidate_outputs/reference_image__ConvexHullCorrWorm.npy": "9ba1259e4ca007c06f14be6946e32a86307ec2dfb9952b73fa2cc253ccae8b3a", + "benchmark/results/official30_value_completion_20260914/example3_intermediate_diagnostic/candidate_outputs/reference_image__ConvexHullIllumWorm.npy": "1890f573e1ca6ea4f16c6a533db1a429f86090f5ea52851dab4a151ca01c8614", + "benchmark/results/official30_value_completion_20260914/example3_intermediate_diagnostic/candidate_outputs/reference_image__InvertedWorms.npy": "0c35c2ceb36b064a8f9e9879ce0339f545bed0637b66a6cc36c5bde0d2734f31", + "benchmark/results/official30_value_completion_20260914/example3_intermediate_diagnostic/candidate_outputs/reference_image__MaskedInvertedWorms.npy": "45c1ae2ca8acf6a4b45931f670d0f5ff0db96b35de49ee054e407f04f6436f83", + "benchmark/results/official30_value_completion_20260914/example3_intermediate_diagnostic/candidate_outputs/reference_image__MaskedOrigWorms.npy": "1e45f21c32f98b5969705e54c4a2d5c5261cb1de1bb9abfb544ec1e57a9948d7", + "benchmark/results/official30_value_completion_20260914/example3_intermediate_diagnostic/candidate_outputs/reference_image__PolynomialCorrected.npy": "8875da63a072c8f2de4f5cb707d779a064b663bf69aa0f304fe6fa74d4ff57a6", + "benchmark/results/official30_value_completion_20260914/example3_intermediate_diagnostic/candidate_outputs/reference_image__PolynomialIllum.npy": "86f02928457324b3dc9b59dae1d858c8e10376a6cde16f1dc4e46bf7b8fae456", + "benchmark/results/official30_value_completion_20260914/example3_intermediate_diagnostic/candidate_outputs/reference_labels__ShrunkenWell.tiff": "debdfd00e7ce8d5c14f0de9c95c16ad26526f2e9fec2fd46e99b566077f614d1", + "benchmark/results/official30_value_completion_20260914/example3_intermediate_diagnostic/candidate_outputs/reference_labels__Well.tiff": "9f059bedc38992b8c83908028a213f232722d582667fbd7f4d9c3fc373830915", + "benchmark/results/official30_value_completion_20260914/example3_intermediate_diagnostic/endpoint_logs/openhcs_zmq_server_port_23848_1789408615215817.log": "f618dc60b84bb708781c8b2df087f4277d0f3da41fb448c7fda8e4e726ccd4ad", + "benchmark/results/official30_value_completion_20260914/example3_intermediate_diagnostic/native_outputs/.cellprofiler_benchmark_reference.json": "8b7661079f0da1c0f1a64e2471baf8afa22e4bb4725a8b7d622e8cb12352a341", + "benchmark/results/official30_value_completion_20260914/example3_intermediate_diagnostic/native_outputs/reference_image__ConvexHullCorrWorm.npy": "9ba1259e4ca007c06f14be6946e32a86307ec2dfb9952b73fa2cc253ccae8b3a", + "benchmark/results/official30_value_completion_20260914/example3_intermediate_diagnostic/native_outputs/reference_image__ConvexHullIllumWorm.npy": "1890f573e1ca6ea4f16c6a533db1a429f86090f5ea52851dab4a151ca01c8614", + "benchmark/results/official30_value_completion_20260914/example3_intermediate_diagnostic/native_outputs/reference_image__InvertedWorms.npy": "0c35c2ceb36b064a8f9e9879ce0339f545bed0637b66a6cc36c5bde0d2734f31", + "benchmark/results/official30_value_completion_20260914/example3_intermediate_diagnostic/native_outputs/reference_image__MaskedInvertedWorms.npy": "45c1ae2ca8acf6a4b45931f670d0f5ff0db96b35de49ee054e407f04f6436f83", + "benchmark/results/official30_value_completion_20260914/example3_intermediate_diagnostic/native_outputs/reference_image__MaskedOrigWorms.npy": "1e45f21c32f98b5969705e54c4a2d5c5261cb1de1bb9abfb544ec1e57a9948d7", + "benchmark/results/official30_value_completion_20260914/example3_intermediate_diagnostic/native_outputs/reference_image__PolynomialCorrected.npy": "588e6f9951aa7ad220678dbb0053e98fb6d324e71aab089d1d828d891ee32f54", + "benchmark/results/official30_value_completion_20260914/example3_intermediate_diagnostic/native_outputs/reference_image__PolynomialIllum.npy": "c3a44c530753120d1224d5c4abcd21225508fd63bc19c7dd3bd2a49eac0d31c7", + "benchmark/results/official30_value_completion_20260914/example3_intermediate_diagnostic/native_outputs/reference_labels__ShrunkenWell.tiff": "b1fcb0e9d83d8c2bcfcbe618aac6b2f153cf5971fe2b812229aa1c865dc05653", + "benchmark/results/official30_value_completion_20260914/example3_intermediate_diagnostic/native_outputs/reference_labels__Well.tiff": "31ba2ed9039c7b7fc37310a2b1e0f784a4c5aca5d09bd1fcaa606bc40548a060", + "benchmark/results/official30_value_completion_20260914/example3_intermediate_diagnostic/observations.csv": "1945f4cc68fa327fe9638d31bcf995bba342dca6a4f3dc8d68f58bea88709c99", + "benchmark/results/official30_value_completion_20260914/example3_intermediate_diagnostic/observations.jsonl": "002d7cf28a1dae4a864798c563cfca957872e24695facc22d173c7c33ac70e9f", + "benchmark/results/official30_value_completion_20260914/example3_intermediate_diagnostic/phase_timing.csv": "e38aaa8f5e16698c7b3a2d1669d66c43112977d9cd6ff3d9783e141a352b156c", + "benchmark/results/official30_value_completion_20260914/example3_intermediate_diagnostic/pipeline/ExampleIlluminationCorrection_Example3.cppipe": "8e93c5dca4aa4abd722b69c036e05c4ccd1c337e386e3cc7716def363d9df792", + "benchmark/results/official30_value_completion_20260914/example3_intermediate_diagnostic/pipeline/ExampleIlluminationCorrection_Example3.reference_exports.json": "725a929078405268ae450679e2061eae0332a2b9428f950a1ace504e161bc913", + "benchmark/results/official30_value_completion_20260914/example3_intermediate_diagnostic/pipeline/manifest.json": "8b288b7b155bbe8b54259eb0791d04da0add142bd3315de5cf628843637fdaec", + "benchmark/results/official30_value_completion_20260914/example3_intermediate_diagnostic/run_environment.json": "ac9f2201e7ebcf85d4fcea749045c692f4f8a5340a129304e7a84bd8b8d05144", + "benchmark/results/official30_value_completion_20260914/example3_intermediate_diagnostic/suite_metadata.json": "d170891869d30b1eaf90b6d2ee96796a3b0e269914c3dc12faa110226d03b547", + "benchmark/results/official30_value_completion_20260914/example3_intermediate_diagnostic/summary.csv": "ed34ecdbbc9eec25ac0eb19bd634b50a139f4ea0e65d67e3af2ca6b0617d2022", + "benchmark/results/official30_value_completion_20260914/invalid_suppressed_image_run/observations.csv": "53c0b56a7cc156e6a443d02954b308e9ee0c7407ea2ce3c0ba4dcca23756ea5c", + "benchmark/results/official30_value_completion_20260914/invalid_suppressed_image_run/observations.jsonl": "adce8264063f7182a53e76d30fe8256d73143b5ef93ed577a82f88013ef3b822", + "benchmark/results/official30_value_completion_20260914/invalid_suppressed_image_run/suite_metadata.json": "395d4bfdd7641b74458a756f43240acefed0af46baa1a034bb7200cae07cc090", + "benchmark/results/official30_value_completion_20260914/invalid_suppressed_image_run/summary.csv": "ba32869b4aa83f7d17d998fb48b7cb6d53568ede82ff3a8d0839d924136b6cd2", + "benchmark/results/official30_value_completion_20260914/label_aware_exact_commit_run/artifact_comparisons.csv": "6769bb47a485e4cc942a535265d6f93cad530d7672ea6d0303c7c5b20101f5bb", + "benchmark/results/official30_value_completion_20260914/label_aware_exact_commit_run/candidate_outputs/ExampleIlluminationCorrection_Example1_EachMethod/reference_image__CorrGreen.npy": "3c17148f0fad16738a23af55ac4e41692e6c2906808a7d83823331702b1b4f46", + "benchmark/results/official30_value_completion_20260914/label_aware_exact_commit_run/candidate_outputs/ExampleIlluminationCorrection_Example2/reference_labels__LargeBlockCorrectedNuclei.tiff": "48e0ff1c313ce3e7154453d5b8ec53db9fcb6fb3ec8321f6eb5958c77e4b201f", + "benchmark/results/official30_value_completion_20260914/label_aware_exact_commit_run/candidate_outputs/ExampleIlluminationCorrection_Example2/reference_labels__SmallBlockCorrectedNuclei.tiff": "0b3270a092b0882d2c34effdd28d62edb9cd0f594dda592fe0e05845c5abba09", + "benchmark/results/official30_value_completion_20260914/label_aware_exact_commit_run/candidate_outputs/ExampleIlluminationCorrection_Example2/reference_labels__UncorrectedNuclei.tiff": "4543f3afec804f201126e640bae070fd4e44700ac7b0de99dec13e038b42377a", + "benchmark/results/official30_value_completion_20260914/label_aware_exact_commit_run/candidate_outputs/ExampleIlluminationCorrection_Example3/reference_image__ConvexHullCorrWorm.npy": "9ba1259e4ca007c06f14be6946e32a86307ec2dfb9952b73fa2cc253ccae8b3a", + "benchmark/results/official30_value_completion_20260914/label_aware_exact_commit_run/candidate_outputs/ExampleIlluminationCorrection_Example3/reference_image__PolynomialCorrected.npy": "8875da63a072c8f2de4f5cb707d779a064b663bf69aa0f304fe6fa74d4ff57a6", + "benchmark/results/official30_value_completion_20260914/label_aware_exact_commit_run/candidate_outputs/cp4_supplement_combine_objects/reference_labels__CombinedObjects.tiff": "2d1994f6d02100c4f5e77fc3c077d14d873bad8b5a48023966bdbb6a06bb83e4", + "benchmark/results/official30_value_completion_20260914/label_aware_exact_commit_run/candidate_outputs/cp_tutorial_translocation_start/reference_labels__Nuclei.tiff": "7cbac0da81e073728ee86f7265b960d1d90b75ece750b92c1bdfcbad99ffbdfd", + "benchmark/results/official30_value_completion_20260914/label_aware_exact_commit_run/endpoint_logs/openhcs_zmq_server_port_23952_1789412557483684.log": "21468a74bd0bf30c9ff06c434fc6673479ee6250a2cedf17c50f3f2b975e065d", + "benchmark/results/official30_value_completion_20260914/label_aware_exact_commit_run/endpoint_logs/openhcs_zmq_server_port_23952_1789412579144257.log": "9c138abe3ae085f701fc1d4dd28778686c138732b7eb8597964cc72b72f9e04d", + "benchmark/results/official30_value_completion_20260914/label_aware_exact_commit_run/endpoint_logs/openhcs_zmq_server_port_23952_1789412604000694.log": "b7ab91fd34917b424ab5ac363f268cf84de6e2f7c390d0bbc208db4f657e0cce", + "benchmark/results/official30_value_completion_20260914/label_aware_exact_commit_run/endpoint_logs/openhcs_zmq_server_port_23952_1789412623395869.log": "1abfc359c124f6d6e0a838f2764f59075a559231f3ea5c0674c42b60c2fd228c", + "benchmark/results/official30_value_completion_20260914/label_aware_exact_commit_run/endpoint_logs/openhcs_zmq_server_port_23952_1789412642098045.log": "94d8e09536f0066d85dc6cf23422a77f97fefc2d3d91a663e4afc8c53c904a55", + "benchmark/results/official30_value_completion_20260914/label_aware_exact_commit_run/module_coverage_absorbed_modules.csv": "2acf6a4e7385137fceafad7a3591e93d3302ebc85fec14057d5be8af334e9f1e", + "benchmark/results/official30_value_completion_20260914/label_aware_exact_commit_run/module_coverage_cppipe_modules.csv": "9294a9c694d85f1f2676cb33f41431d66a4986cfb7f07432d3a2015423521c1e", + "benchmark/results/official30_value_completion_20260914/label_aware_exact_commit_run/module_coverage_cppipe_settings.csv": "02764a949ea6b3bb7037a65091a3dff2d715adbeffe998dcda43f78ac226c05f", + "benchmark/results/official30_value_completion_20260914/label_aware_exact_commit_run/module_coverage_summary.json": "acdc4005dfc26d8a51b943a8bb43a6378cc667d68ebf60c7124c2d23dbca24b6", + "benchmark/results/official30_value_completion_20260914/label_aware_exact_commit_run/observations.csv": "a1f84b3baef6c0a41c37f1c6ce613bd8a7b7a64402a4b26067add4366a731d9f", + "benchmark/results/official30_value_completion_20260914/label_aware_exact_commit_run/observations.jsonl": "4b27671215b174655fcfe0878b0be1e82a91c45e25cbd8977c1affc7db04ea76", + "benchmark/results/official30_value_completion_20260914/label_aware_exact_commit_run/phase_timing.csv": "9cf38c07b4fa8b02a02a4d68c7fcd9028e2e466b97ff835e3a3c7a2d0f9ff4ff", + "benchmark/results/official30_value_completion_20260914/label_aware_exact_commit_run/run_environment.json": "1657aa024b80da323b37cd62ea4a585bfeae50b1774649d6f9a9733c36d5d6f6", + "benchmark/results/official30_value_completion_20260914/label_aware_exact_commit_run/suite_metadata.json": "27173378623b3f7fb9753dc453b839a7d8a4484dbc7ddbee65a34efec137ed10", + "benchmark/results/official30_value_completion_20260914/label_aware_exact_commit_run/summary.csv": "699f4238d29a277d33749959f1f23f4e2b4bdd2b5cade914420f2bc238b2d347", + "benchmark/results/official30_value_completion_20260914/stale_endpoint_run/artifact_comparisons.csv": "64b5ed21e64b2ea62d4a92de290e17fc5f51f7b608df77ad89d33e0aff107ade", + "benchmark/results/official30_value_completion_20260914/stale_endpoint_run/observations.csv": "6575e5497a75f2341269980182749314b9fc207397a350ef9236b85f8cfeba46", + "benchmark/results/official30_value_completion_20260914/stale_endpoint_run/observations.jsonl": "4ab94c30460ce9d6da5df5a72600ca2f0c65179abd4a10d0fc9b4d39a54dc89d", + "benchmark/results/official30_value_completion_20260914/stale_endpoint_run/phase_timing.csv": "c68b045a8d00c63da60849aad9ea1d10ca1a7b89fa1b234eb0935d4ce22d77d3", + "benchmark/results/official30_value_completion_20260914/stale_endpoint_run/run_environment.json": "4a6cdbf676791877e6e8cc1a6f13c1a1365b092f1a2c125022b741cfa6d0c78c", + "benchmark/results/official30_value_completion_20260914/stale_endpoint_run/suite_metadata.json": "b403d0dac8413a58671431e42eb2b4915dd451d3cf0d8f4bfb3d44cbe0a3b391", + "benchmark/results/official30_value_completion_20260914/stale_endpoint_run/summary.csv": "fe1ecdecede51b92181b85ba661330534f6e3cfd7186379a7708e532b699facf", + "benchmark/results/paper_config_new_api_probe_20260923/8w_1c.csv": "9830d4add0020e24995190e5e603b7bfdba2c4799010ff0da67a553ba9d7f381", + "benchmark/results/paper_config_new_api_probe_20260923/8w_1c_outcomes.pkl.gz": "ff6daf5d45b817ac616e9af41dd53cff1b1ae5c41d2d12f974f2ea797acc6e34", + "benchmark/results/paper_config_new_api_probe_20260923/8w_1c_receipt.json": "3027c94773d6e55bfb2f65d18b7083a0e7924093ee5ebfea64ed94feff4864a3", + "benchmark/results/paper_config_new_api_probe_20260923/8w_2c.csv": "638dcfd5fed0e2ff2377e36c4a0c0d66e9768ac2c8741d97a23f2c7196ee05b3", + "benchmark/results/paper_config_new_api_probe_20260923/8w_2c_declared_outputs.csv": "e6ccd858434c95bababfcc28c04b3684ee270a992f34b27d18bbf87b81ca69dd", + "benchmark/results/paper_config_new_api_probe_20260923/8w_2c_declared_outputs_outcomes.pkl.gz": "b29ff7bb0c747604f993ad392f7c3368de8453f199f48c5ed27da0cad120b53e", + "benchmark/results/paper_config_new_api_probe_20260923/8w_2c_declared_outputs_receipt.json": "deb11a85bf2e101d5836cfc962d1aa2b1d8322320cc9b01fe7e528a8116c3ade", + "benchmark/results/paper_config_new_api_probe_20260923/8w_2c_outcomes.pkl.gz": "859be309417596501880a8a4d43118d6cfdbea4fce70c73ab8924e546de329c1", + "benchmark/results/paper_config_new_api_probe_20260923/8w_2c_receipt.json": "032c248f67bd279574f4ec4c67e1fac796206e68fcfbaaa31f146e44f23592ab", + "benchmark/results/paper_config_new_api_probe_20260923/8w_2c_verified_2pid/measured_pipeline_receipt.json": "b8fd0422d90e248ac5bb70840a142414caf9e9dad007dce39ffdfb907e11724c", + "benchmark/results/paper_config_new_api_probe_20260923/8w_2c_verified_2pid/runtime_outcomes.pkl.gz": "bdcf6a36243367658625132f87bd60b85a939cc4df1c8cf3acf10e6c3d1fa3a3", + "benchmark/results/paper_config_new_api_probe_20260923/8w_2c_verified_2pid/submitted_global_config.py.txt": "11e089b9f329088028498a66fc39a51833624cd8eb29562002c5e807512c5740", + "benchmark/results/paper_config_new_api_probe_20260923/8w_2c_verified_2pid/submitted_pipeline.py.txt": "e6ebb8608d2a22a5ea5ee40059f0dbf7583876bd6245387c24cf0ed6ab7345bd", + "benchmark/results/paper_config_new_api_probe_20260923/8w_2c_verified_2pid/well_throughput.csv": "08c44e894b2ee7130cb7005bb1fe486ad79dc406302179707c35c950fd0b5bab", + "benchmark/results/paper_config_new_api_probe_20260923/8w_2c_verified_2pid/well_throughput_progress_events.csv": "705fd02774f61bc2f905a21f0362a5cc49a80452cbc6bab3ac3c4be58b8a186e", + "benchmark/results/paper_config_new_api_probe_20260923/8w_2c_verified_2pid/well_throughput_step_timings.csv": "1b30e7b61e160e8d97231b29af988095e7ff1f441185b3c9868929ab89abf32a", + "benchmark/results/paper_config_new_api_probe_20260923/8w_2c_verified_2pid/well_throughput_worker_lanes.csv": "e688af596ca7a4e54bd71df0221bed792f98f0bf6e70f7a8d738df740778080f", + "benchmark/results/paper_config_new_api_probe_20260923/8w_2c_verified_2pid/zmq_results_summary.json": "22a3ceacbbbae85e3e4f193cf9c247ac2d9fbe09ae8b1a17be339695353ca8a4", + "benchmark/results/paper_config_new_api_probe_20260923/README.md": "f74483f8e75346851ff9c0a9751200c4c3ed5f5115d7d8bbaa4521ab065d78fd", + "benchmark/results/paper_config_new_api_probe_20260923/translocation_four_modes_fork/12w_3c/measured_pipeline_receipt.json": "ee1fee7401b8b8dcfe17dc053824d35bfe66f439783626be44ddfd3838083f37", + "benchmark/results/paper_config_new_api_probe_20260923/translocation_four_modes_fork/12w_3c/progress_events.csv": "32aa3f571d0cc1c36cd9b9ededd72979b88760062155c2cd8902c22c8b168d12", + "benchmark/results/paper_config_new_api_probe_20260923/translocation_four_modes_fork/12w_3c/runtime_outcomes.pkl.gz": "adc1dd9c98eb04c85ea5c2e5b098da43de6b3d082848947ba728a645c172cbbb", + "benchmark/results/paper_config_new_api_probe_20260923/translocation_four_modes_fork/12w_3c/step_timings.csv": "7dc918c5dd8378cfdd5a245d0828e0b242181359c581d80c3dc3504851c30805", + "benchmark/results/paper_config_new_api_probe_20260923/translocation_four_modes_fork/12w_3c/submitted_global_config.py.txt": "5b02ba65228c46b1eb52b79d6f6d7e4d87c1b8feb4b72d916a29064ab5b071be", + "benchmark/results/paper_config_new_api_probe_20260923/translocation_four_modes_fork/12w_3c/submitted_pipeline.py.txt": "f6176b7c207fdc44a89729ed336225c3b56d7c0c7bc96cbb5a4e73aab2320377", + "benchmark/results/paper_config_new_api_probe_20260923/translocation_four_modes_fork/12w_3c/worker_lanes.csv": "2ac06c1beec3c379fbf9b13a22674e303c68414a459c75a9da8e6b4783652451", + "benchmark/results/paper_config_new_api_probe_20260923/translocation_four_modes_fork/12w_3c/zmq_results_summary.json": "9aa7300757cd96bfcba6775adfe811fab88d0415b9aa1db053283de743ee0df7", + "benchmark/results/paper_config_new_api_probe_20260923/translocation_four_modes_fork/16w_4c/measured_pipeline_receipt.json": "e34bcc76ccf26058ba36fd18ec7f690dcc26a4c6a17759381a7b4392ec5217fe", + "benchmark/results/paper_config_new_api_probe_20260923/translocation_four_modes_fork/16w_4c/progress_events.csv": "bb5d4d68a48d6dc850b884482513d309dbc62a121f3aee2588afc74c4dcbcad2", + "benchmark/results/paper_config_new_api_probe_20260923/translocation_four_modes_fork/16w_4c/runtime_outcomes.pkl.gz": "dba0a261f50186cf097b1c6df874186d5e6063b1a2aa74a1b7ffd406f6ea2d7d", + "benchmark/results/paper_config_new_api_probe_20260923/translocation_four_modes_fork/16w_4c/step_timings.csv": "16f04f753226989c6f4ca66e949e8a9f637034f5a476a54f8a1bf66b91053bcf", + "benchmark/results/paper_config_new_api_probe_20260923/translocation_four_modes_fork/16w_4c/submitted_global_config.py.txt": "80a34af100ced928482f27c647571274798d2748e66ed1d244f70ebe5d573097", + "benchmark/results/paper_config_new_api_probe_20260923/translocation_four_modes_fork/16w_4c/submitted_pipeline.py.txt": "cd1ce5cd2e75d10ce50bba191f3d946ec383888686a4185a1199a997d72ba2c4", + "benchmark/results/paper_config_new_api_probe_20260923/translocation_four_modes_fork/16w_4c/worker_lanes.csv": "5a70fe4c631d40b79e982d6364887d4417f7a803f335438477993b2e24d3d3b1", + "benchmark/results/paper_config_new_api_probe_20260923/translocation_four_modes_fork/16w_4c/zmq_results_summary.json": "3ec94ab3c15f17c015a2e8d3bf8c8d31532c400cccce505d8d053ee5587fd208", + "benchmark/results/paper_config_new_api_probe_20260923/translocation_four_modes_fork/1w_1t/measured_pipeline_receipt.json": "a09cc0bcef1c8c6bee3521505d1d84bad5ac5eca26a265d998da84c79e1c9575", + "benchmark/results/paper_config_new_api_probe_20260923/translocation_four_modes_fork/1w_1t/progress_events.csv": "a1dca6aae9555f9dc97ab031f5208024497f702110fa6970d52419844381f9f3", + "benchmark/results/paper_config_new_api_probe_20260923/translocation_four_modes_fork/1w_1t/runtime_outcomes.pkl.gz": "0dc6e0f703cd192e73898546dac5730e44a9e5494f0c385fdc75fc760056973d", + "benchmark/results/paper_config_new_api_probe_20260923/translocation_four_modes_fork/1w_1t/step_timings.csv": "b03de853c21350719a48a7f2cd33ce4f4b210c513c568ab3715a79d5a0eca5a8", + "benchmark/results/paper_config_new_api_probe_20260923/translocation_four_modes_fork/1w_1t/submitted_global_config.py.txt": "2e2cf95d87a9465d20ecbb8c88629ce615b64de6e5843319f9b51599f343c1c3", + "benchmark/results/paper_config_new_api_probe_20260923/translocation_four_modes_fork/1w_1t/submitted_pipeline.py.txt": "48c6b13776fc8312baf76308a1016c9faca1c61db154434344a869cd183530c3", + "benchmark/results/paper_config_new_api_probe_20260923/translocation_four_modes_fork/1w_1t/worker_lanes.csv": "aa76fbc3919a68a5fe6fce8b158e8d94a695bbb5267bfdc1865a60a1c1349037", + "benchmark/results/paper_config_new_api_probe_20260923/translocation_four_modes_fork/1w_1t/zmq_results_summary.json": "527db04cd5ab7ac04b23eedb5db8113bfb0073445431403a1327c2a32ddc361a", + "benchmark/results/paper_config_new_api_probe_20260923/translocation_four_modes_fork/8w_2c/measured_pipeline_receipt.json": "edc8c152c3ab6f662af7d50ae9cdc96e9d9d10168e2cd30ad5be27d520d5b043", + "benchmark/results/paper_config_new_api_probe_20260923/translocation_four_modes_fork/8w_2c/progress_events.csv": "b3433d039d3ee84ba05185b59e4b0b594ebd1892c734344e2ae4f39bf756be95", + "benchmark/results/paper_config_new_api_probe_20260923/translocation_four_modes_fork/8w_2c/runtime_outcomes.pkl.gz": "04b1b1b87f74d04692c0df45a505bd6c7242d8227ffc7ad68e96a05765576f94", + "benchmark/results/paper_config_new_api_probe_20260923/translocation_four_modes_fork/8w_2c/step_timings.csv": "9bac75d5f6550c3a299707651a26f8120281b958d821d98526e8b0877507a693", + "benchmark/results/paper_config_new_api_probe_20260923/translocation_four_modes_fork/8w_2c/submitted_global_config.py.txt": "11e089b9f329088028498a66fc39a51833624cd8eb29562002c5e807512c5740", + "benchmark/results/paper_config_new_api_probe_20260923/translocation_four_modes_fork/8w_2c/submitted_pipeline.py.txt": "ab20fcab6f0b07a3a7029b68eb3b20ac4cd95efef78e47ac82ffbde141cd6475", + "benchmark/results/paper_config_new_api_probe_20260923/translocation_four_modes_fork/8w_2c/worker_lanes.csv": "9398bab30364fa71e31276030f470b84e89cec863ec5e244a8bb14898b8eb96b", + "benchmark/results/paper_config_new_api_probe_20260923/translocation_four_modes_fork/8w_2c/zmq_results_summary.json": "116db1296535c341894ccb67a3b1ca1bed0eecfc4a2e8d82b2dd386bd6e09c7c", + "benchmark/results/paper_config_new_api_probe_20260923/translocation_four_modes_fork/README.md": "353cb4ce359532168d2467cb0196f4cb15ec1398dc54371a7265a04303e29c71", + "benchmark/results/paper_config_new_api_probe_20260923/translocation_four_modes_fork/well_throughput.csv": "c92b7cfb06e17a7a312bb3abb93d6a06b39d1bf7983f266409c964059f1fa263", + "benchmark/results/perf_coloc_step_cache_20260929/README.md": "aa888a93071515ae296a2a5e615d57ba043708a2676d4faf81442c14f963056f", + "benchmark/results/perf_coloc_step_cache_20260929/abba_1_control.csv": "ecbaae1ddb7c931cc7cd76e2b68fee261426330ae9b7ac853ff85ee1aec4a2b5", + "benchmark/results/perf_coloc_step_cache_20260929/abba_2_candidate.csv": "a49b0f06696f192073bb9aa4786c148d6969e6e9c22b17c1d924331a41faf38d", + "benchmark/results/perf_coloc_step_cache_20260929/abba_3_candidate.csv": "cffcc08fb7c3acbf673f12db48ffd838a6ed646e574ba85aeb063760d20a56f1", + "benchmark/results/perf_coloc_step_cache_20260929/abba_4_control.csv": "765727623360319a134023bccdc1fb10a25697981c046eb25818384327c91326", + "benchmark/results/perf_coloc_step_cache_20260929/affected_case_execution.png": "f90ff514a2191b0a42b9a75d867744be6d10abce8455366e05b5a37496e7b9d3", + "benchmark/results/perf_coloc_step_cache_20260929/full_first_candidate.csv": "406e67b3d1b9a5f2b257caebfdfe211bcc4744363d2a1c75c7c0e95b25efc7bf", + "benchmark/results/perf_coloc_step_cache_20260929/full_first_control.csv": "1dceecbae5cb6858914b0a241cab4fa362da784ca699eaccca46b0c9e37ad775", + "benchmark/results/perf_coloc_step_cache_20260929/full_suite_execution_delta.png": "d48e224d6fe6cfa570cb6512693db00a8d4bae4ca82f1987d51308ca10eb0cc4", + "benchmark/results/perf_coloc_step_cache_20260929/full_warm_candidate.csv": "77ad4113fdc086c9412ea0aab24e19a8db93cf960e749b2fb4a2ac92394455dd", + "benchmark/results/perf_coloc_step_cache_20260929/full_warm_control.csv": "f7effe7ac56c5547fa0a3769dbaac4062744baac3cc0d42eec98c400217d8a24", + "benchmark/results/perf_coloc_step_cache_20260929/plot.py": "c96b55e25f5e145a0531d88bf77d09026f1a66e3caab110db609eb4d8767ff60", + "benchmark/results/perf_compiled_radial_20260929/README.md": "4de88c4978800932097c9e9f89382a05de1acbbdec1b9e5a17c4c3d33288050f", + "benchmark/results/perf_compiled_radial_20260929/analysis.json": "ba90d0586f8ac9252dfe0f4a68da0fb2d13b8d386a0b911f9e616d61745d75d5", + "benchmark/results/perf_compiled_radial_20260929/analyze.py": "8d5af51b4768f1448de23b1cfd128195dc0892710642502776c237a57de14f11", + "benchmark/results/perf_compiled_radial_20260929/architecture.md": "7193e21aedf6e49089f5a0a082040c6cf2e6ed19125c958c65f9da58ebdf1b75", + "benchmark/results/perf_compiled_radial_20260929/census_summary.json": "8efc5b9337c9fdc85139fdbec4050735b659c0fb2d3ed3a8f0e763cfa33c80e2", + "benchmark/results/perf_compiled_radial_20260929/check_export_parity.py": "5b73605782f75598c76925966fe31d363c28c474de6f3f3735cc5fedea10c525", + "benchmark/results/perf_compiled_radial_20260929/consumer_tests.log": "9559c2c2107217a19bae92dfe8a0a66c26dd60d0d90e9ca0e09443a9d0d16c20", + "benchmark/results/perf_compiled_radial_20260929/export_parity_16w.json": "1972a155234a4921d2466f905085a11cb09ffeed09a47a6d4ac7dbddd5d69712", + "benchmark/results/perf_compiled_radial_20260929/export_parity_1w.json": "7baf12caa4ef5a280383d19c93842b3c1385ed06552455188d3d3c164eec91e8", + "benchmark/results/perf_compiled_radial_20260929/focused_tests.log": "51c5f4493731fc4516821d0446564ad5d8fb45d83f46e1e675e59c5b39d28154", + "benchmark/results/perf_compiled_radial_20260929/input_digest_checks.json": "73ba5709841fd20f52f0bc34254fa251044648b54bedc0fd66f9770f03a199c1", + "benchmark/results/perf_compiled_radial_20260929/measured_radial_scaling.png": "fb3f31b15e45b9bf9ab55f54ad2228335466a785a2fcee13412d2b2d258e94c2", + "benchmark/results/perf_compiled_radial_20260929/measured_radial_scaling.svg": "1ebdfe437f1e677e8514cccaa7d8d456df6350a5e12a27524d75fcb1fc1ae45f", + "benchmark/results/perf_compiled_radial_20260929/observations_16w.jsonl": "06307852309a4ab5ad8fdbcf426ae228c66d3c7ed89a6917e1c4ff4c51c2c641", + "benchmark/results/perf_compiled_radial_20260929/observations_1w.jsonl": "69a82bbb6bf4e3a3c0c4a309a17274dd0a05aced8af2fe65d97a69e8a41dd09f", + "benchmark/results/perf_compiled_radial_20260929/plot.py": "abe70858d4debec9fef7d9e2eb83db20e56313a74879950fe9eca003276645b6", + "benchmark/results/perf_compiled_radial_20260929/provenance.json": "1c7fb6b859ed5f9ffe7063e7653460689dd86015820da57496ca1b6d55905652", + "benchmark/results/perf_compiled_radial_20260929/radial_probe_observations.json": "0a73c10c81e96f2cd66f89f15efe5a79bd8e0df9e5bc248fff522b4b4d351e56", + "benchmark/results/perf_compiled_radial_20260929/recipes/01_select_compiled_default.py": "61521b77d0e5cb7a3986d134b17d821502b293006652ad7f11afa52235ae8339", + "benchmark/results/perf_compiled_radial_20260929/recipes/02_share_request_boundary.py": "f07bb95b6bbcc39e09cd090a2c0d8c3069fbe685d2e76f3d9eb5040a2cc7d39b", + "benchmark/results/perf_compiled_radial_20260929/recipes/03_share_compiled_normalization.py": "976f78897800d801538d0d1a72415df3b248677b6966f4ab05bc2fffca5bfe94", + "benchmark/results/perf_compiled_radial_20260929/recipes/perf-compiled-radial-nra-projected-20260929.diff": "4340b6d4998dac35a2a527127be79d28d6de0f1e9eb00b6d7cabeb8dcc7d7e73", + "benchmark/results/perf_compiled_radial_20260929/recipes/perf-radial-normalization-nra-projected-20260929.diff": "26d23401861d9509560247e943cd7699d9be03dc55675670da1e5603d75a19bf", + "benchmark/results/perf_compiled_radial_20260929/recipes/perf-radial-request-boundary-nra-projected-20260929.diff": "13f23a3810750714f751796fb6f32efb2ce3ed24c71a9e4cdeb56e0e5f137b9c", + "benchmark/results/perf_compiled_radial_20260929/replay_saved_requests.py": "dd97cb2afba7ea2da38378c83a120e0a51e9c5a285a6a45295668ab64c395896", + "benchmark/results/perf_compiled_radial_20260929/run_pairs.py": "b6e9da11b530c855759e95084582c2e5be91a44e91d23492937774bc6433a85f", + "benchmark/results/perf_compiled_radial_20260929/runs/16w/candidate_1/lanes.csv": "6b26eb412a9e61dda5fbc0e4a29403f86a772bb22392b9f781235e0be597c4df", + "benchmark/results/perf_compiled_radial_20260929/runs/16w/candidate_1/observation.csv": "4b4b5249ec0c7ad7da4b3418c0025773c5e84649b8dfe539e0d9634e103559d9", + "benchmark/results/perf_compiled_radial_20260929/runs/16w/candidate_1/receipt.json": "4313e6d7db3534e8776137926d95d7955407ffbf74fcf4b8b0ff2b9c21c54be9", + "benchmark/results/perf_compiled_radial_20260929/runs/16w/candidate_1/steps.csv": "433aa409929a6cfb0650c28c393fb0ef9ca5451069c071ced3b798b800ac2b0b", + "benchmark/results/perf_compiled_radial_20260929/runs/16w/candidate_1/warm.log": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "benchmark/results/perf_compiled_radial_20260929/runs/16w/candidate_2/lanes.csv": "06e34d1ff26f4f00d32044f8a1219fadfac6ce48364fb0fc93dbe583e61b54ff", + "benchmark/results/perf_compiled_radial_20260929/runs/16w/candidate_2/observation.csv": "e523b5e543cee1eaf0071c564225e6f52dae130fd726eeb0c39c51d24e8cd292", + "benchmark/results/perf_compiled_radial_20260929/runs/16w/candidate_2/receipt.json": "fa5da6355824e2056e2bfb2eed97f02d367abaf7a53d0f30c6b6d580ae0b0bf2", + "benchmark/results/perf_compiled_radial_20260929/runs/16w/candidate_2/steps.csv": "af8b2b8d50405f276805a6175c750ab5ae973dc50cbd6f21d3981366ba7addb5", + "benchmark/results/perf_compiled_radial_20260929/runs/16w/candidate_2/warm.log": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "benchmark/results/perf_compiled_radial_20260929/runs/16w/control_1/lanes.csv": "f8dc5f00bf00eca1848aac546d288e835d390aea0bc89db7ba77ed9bc9afec47", + "benchmark/results/perf_compiled_radial_20260929/runs/16w/control_1/observation.csv": "6e33a531e8576ccfc726550021ebf466bae26cc917f500170b997a8ebdf21002", + "benchmark/results/perf_compiled_radial_20260929/runs/16w/control_1/receipt.json": "ad55269d27c9e544b0350b764c61326fb9126da8492291fb73aefcd504ac50f6", + "benchmark/results/perf_compiled_radial_20260929/runs/16w/control_1/steps.csv": "b7e8de743c24e9ae6b77ce29823d7226ac7d670196e46a4f0aa1810a39f46457", + "benchmark/results/perf_compiled_radial_20260929/runs/16w/control_1/warm.log": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "benchmark/results/perf_compiled_radial_20260929/runs/16w/control_2/lanes.csv": "2dc771537fff91b16f682b6e76e5270a2c33d2f6a72837983839715b5ad7bb40", + "benchmark/results/perf_compiled_radial_20260929/runs/16w/control_2/observation.csv": "17a37ad58ef2a7834379e4859b8fba25de8860dce3ca5f9917dbb773a64b2a0d", + "benchmark/results/perf_compiled_radial_20260929/runs/16w/control_2/receipt.json": "c51ba471fc40524c41c9e74da089c15ea550faa09ad28c2398ae8b06fcdd0ee5", + "benchmark/results/perf_compiled_radial_20260929/runs/16w/control_2/steps.csv": "495f7e6274b1e630428058c8c408904a0b34c6b14b5603b2a0b486cac8f321ca", + "benchmark/results/perf_compiled_radial_20260929/runs/16w/control_2/warm.log": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "benchmark/results/perf_compiled_radial_20260929/runs/1w/candidate_1/lanes.csv": "7a826c444e88849408b94523d01ac04ee59ddcade186a523766dc06b81c7fb28", + "benchmark/results/perf_compiled_radial_20260929/runs/1w/candidate_1/observation.csv": "e21d6605d0e670c0aba253502edf6ff56f3bf7e038a9cc6bd61f8819cf47ee0b", + "benchmark/results/perf_compiled_radial_20260929/runs/1w/candidate_1/receipt.json": "b72dc79054ed1228332651ea35b638a86c85184d4c5d38b67931151d5126364c", + "benchmark/results/perf_compiled_radial_20260929/runs/1w/candidate_1/steps.csv": "1d8fbffb3b5bb8179211cdffdc28fb566e0f57fae49543d24f357964a6668a36", + "benchmark/results/perf_compiled_radial_20260929/runs/1w/candidate_1/warm.log": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "benchmark/results/perf_compiled_radial_20260929/runs/1w/candidate_2/lanes.csv": "fc52a4f6af56dc266abf76c5e7edb0819f8aa98e2b3fdc299e06a4a7bc79145b", + "benchmark/results/perf_compiled_radial_20260929/runs/1w/candidate_2/observation.csv": "9dce42b0c959dd5e53e725ddd07bb88d350b1bb572135addbaaa749ac524183b", + "benchmark/results/perf_compiled_radial_20260929/runs/1w/candidate_2/receipt.json": "d54090a75a601224778bf1f6a3ed7aae3d2dc588403af439d39aab84daca1fc4", + "benchmark/results/perf_compiled_radial_20260929/runs/1w/candidate_2/steps.csv": "c8cb71b1e10c39d9683dc48f73faafe8d86908321e4efe7752a076901eb1d322", + "benchmark/results/perf_compiled_radial_20260929/runs/1w/candidate_2/warm.log": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "benchmark/results/perf_compiled_radial_20260929/runs/1w/control_1/lanes.csv": "6cafb7ad213c7c9d13afa340cd2064ea4d7318ed100f060dfb851236e214ee01", + "benchmark/results/perf_compiled_radial_20260929/runs/1w/control_1/observation.csv": "2f843f6da5b2dc56beb567fe686c2cb41378a695d74b1aef83a97365b71491e1", + "benchmark/results/perf_compiled_radial_20260929/runs/1w/control_1/receipt.json": "194cff54fc1159fee7dd0f2b6eee7d9f11d7d3d32c5c9409010daf37d0b2726a", + "benchmark/results/perf_compiled_radial_20260929/runs/1w/control_1/steps.csv": "7a7265a6a85fe4d4411b476d1951818ca8d48050b1fe4b089a05570346e6b1f4", + "benchmark/results/perf_compiled_radial_20260929/runs/1w/control_1/warm.log": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "benchmark/results/perf_compiled_radial_20260929/runs/1w/control_2/lanes.csv": "144f10255b0e693ee56c7a4aeb0bd804c2a4fb3570e7ddcf7597042d7f327b3a", + "benchmark/results/perf_compiled_radial_20260929/runs/1w/control_2/observation.csv": "7bc6f2c3262dd5354a02b5c6240076d576a60f0758c444294a7e30396cc79ff9", + "benchmark/results/perf_compiled_radial_20260929/runs/1w/control_2/receipt.json": "d35e75707f248910835abf1f006ab859ec0e854d5352f2cf98bae1a1399f2f59", + "benchmark/results/perf_compiled_radial_20260929/runs/1w/control_2/steps.csv": "eb9e85450dd20eb1cb530fb4936b9ce882dd96516283d035746842a7dae6a4d6", + "benchmark/results/perf_compiled_radial_20260929/runs/1w/control_2/warm.log": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "benchmark/results/perf_compiled_radial_20260929/saved_request_replay.json": "425db6a6ba66e31d64356d4e7e107eebb78499f14220d0682209b9fc06ac811d", + "benchmark/results/perf_compiled_radial_20260929/scope_16w.json": "ed2a5ac206df30462f524e4c7b78ef88bb6738b827b2703049819f7f9b625d90", + "benchmark/results/perf_compiled_radial_20260929/scope_1w.json": "ed2a5ac206df30462f524e4c7b78ef88bb6738b827b2703049819f7f9b625d90", + "benchmark/results/perf_compiled_radial_20260929/spawn_cache/populate.log": "0397ac9f4204f8eae9072d741a6b28fb49e5943bb78893ae113deea6a3f07d4a", + "benchmark/results/perf_compiled_radial_20260929/spawn_cache/spawn_0.log": "49499ae034f18cbc70d39dfec1fbed98cf807de2922f36f240b6d03ddc032727", + "benchmark/results/perf_compiled_radial_20260929/spawn_cache/spawn_1.log": "49499ae034f18cbc70d39dfec1fbed98cf807de2922f36f240b6d03ddc032727", + "benchmark/results/perf_compiled_radial_20260929/spawn_cache_summary.json": "46a49bc1bec06c6017bb6e4d05429e01958955d8b7855460c5f057e56740e611", + "benchmark/results/perf_current_cohort_v10_20261003/qualification.json": "17bb47f609d95ca6044f92810dbbf1c5f31e066ef330955aab264a5d8d7e6273", + "benchmark/results/perf_current_native_paired_20261003/README.md": "41990bd207602a7b72a486dff057c7903f66fae43e7355501468c0b3ffaabac5", + "benchmark/results/perf_current_native_paired_20261003/matched_runtime.png": "867a94f34c5cbe1b6d4fe86917a4e42ab335e486d8c321dd745a353c95dad72d", + "benchmark/results/perf_current_native_paired_20261003/matched_runtime.svg": "9a5377c6ad8609f5a59ae2e9757ec5089d7d5dc77615839ac756fdbbb654e9f7", + "benchmark/results/perf_current_native_paired_20261003/matched_speedup.png": "c8a789edb4dda3ae82fbb708a0d2c9a459f0ee0d7ea7732c266703622839e1ee", + "benchmark/results/perf_current_native_paired_20261003/matched_speedup.svg": "d2e121af82f0a08e23f47cfa00b306ac60f8b580e72dad63cde72f6809ca8a2c", + "benchmark/results/perf_current_native_paired_20261003/metrics.csv": "906273de1e1fe146a7cf53a41892d203aa80fa96da9e7288ec619e6c828ad999", + "benchmark/results/perf_current_native_paired_20261003/native-3d.json": "f1f5804eaef6af43b73f0608071ff57c62691bbd9172b33fa45ca633a4593654", + "benchmark/results/perf_current_native_paired_20261003/native-speckles.json": "25f17f873f96555efb451ecbd39ce03545fb722aaca66a27b64a199fc8e67beb", + "benchmark/results/perf_current_native_paired_20261003/ordinary-0.csv": "43680d83b0df5de1391448655370b1bd013a5b70581741689bc2b3d6cac9db3f", + "benchmark/results/perf_current_native_paired_20261003/ordinary-1.csv": "54d24ecc9904bafc59405692862769ccbc11b663eae8420d24e2e77886d0bac3", + "benchmark/results/perf_current_native_paired_20261003/qualification.json": "3db0f60d3ef04aa0ce846eaef70e746031442422cc693ba943bf78ac8db1ab32", + "benchmark/results/perf_current_native_paired_20261003/strict-science.json": "77ab1a1e88d52502c633b646efe0d032ad87f117fc403298cb8b5742a0510190", + "benchmark/results/perf_current_native_paired_20261003/timing_summary.json": "c3a2afbb04f59b1c7de4d001d9ce42577fe778d15d46bae81362f0d0ec73f24a", + "benchmark/results/perf_declared_callable_kernels_20260930/README.md": "3577c991ddfa0d412fc242c38e284fbfae92692866dcf180c702ec885a6a3d84", + "benchmark/results/perf_declared_callable_kernels_20260930/analysis.json": "a745a031ec8f0b179c454cebaf92241dda5e890c0655f4f168cf0f181f64a27f", + "benchmark/results/perf_declared_callable_kernels_20260930/architecture.md": "ca63c13968ecdb26bfa970f39fc65bc9e3bc54c5433e120520debec12cc566d2", + "benchmark/results/perf_declared_callable_kernels_20260930/cold_observations.jsonl": "5b4351dc6e84221cd91a6f1c31b732ff65457770afa5d7811eeb6cdeb35861db", + "benchmark/results/perf_declared_callable_kernels_20260930/cold_scope.json": "c2748dfc40a186a4ef21218ff114dada404d5b62b05b05c52b9198b45c76019a", + "benchmark/results/perf_declared_callable_kernels_20260930/input_digest_checks.json": "51c2835d516f08e6292595393dbeac3493c2fcdb90e1d748fc4beeb22c54f7b7", + "benchmark/results/perf_declared_callable_kernels_20260930/installed_scope.json": "bfd11e13721d0e21c763da80cf7e6944bdd2c710b8421a31757dcfa68d5f8441", + "benchmark/results/perf_declared_callable_kernels_20260930/installed_throughput.csv": "c40c49bee53d694c5350a3b8890a9b1cd22c33ee041a47d415867474e4e912c8", + "benchmark/results/perf_declared_callable_kernels_20260930/measured_kernel_preparation_scaling.png": "a468bc28adce19c28b50af534cd5ccd345dbff6ad09da4af9b7e79a49806a92d", + "benchmark/results/perf_declared_callable_kernels_20260930/measured_kernel_preparation_scaling.svg": "2bb4930d358a60723adb8f080b38cae3ccbb8df7a90b25d038c0b4d2e29d4741", + "benchmark/results/perf_declared_callable_kernels_20260930/runs/cold/candidate_1/steps.csv": "a2504974ba0b0e0146357f9fca97dfcea6fcd93334d96ae2e6bdce92e1754bb1", + "benchmark/results/perf_declared_callable_kernels_20260930/runs/cold/candidate_1/throughput.csv": "88e3aa8d61048342a1827db268d9cdf785c70c9ecf3b8f0520d0644afbf7a657", + "benchmark/results/perf_declared_callable_kernels_20260930/runs/cold/candidate_1/worker_lanes.csv": "2549c53d3150bec98c378157edf583d1ab5525ce4c63c3f7e42b30017a3bc458", + "benchmark/results/perf_declared_callable_kernels_20260930/runs/cold/candidate_2/steps.csv": "fb5420342770c3ebff3d5aceaa848b15daa6b5b84bb000bac1579b36725ef9d1", + "benchmark/results/perf_declared_callable_kernels_20260930/runs/cold/candidate_2/throughput.csv": "a0c64337b88770b4f92ae891e854301c9d4aec9874983a8ac284ec98b1cf504a", + "benchmark/results/perf_declared_callable_kernels_20260930/runs/cold/candidate_2/worker_lanes.csv": "0dcb070d4d97fb44f955ac13eaa4db562ba81d01f9c36b10fb6c07062766c8c6", + "benchmark/results/perf_declared_callable_kernels_20260930/runs/cold/control_1/steps.csv": "b9ece8ba640d5c3ddbba092d232eb29dea6d634dc64088871c76da4287509202", + "benchmark/results/perf_declared_callable_kernels_20260930/runs/cold/control_1/throughput.csv": "b12dc7a024cff6c5e5045883575fbedd9dfb1b20d0a2e49962feceb1a5421dc7", + "benchmark/results/perf_declared_callable_kernels_20260930/runs/cold/control_1/worker_lanes.csv": "1a4b144a84767fc63cf67a63c36af29e343647c2bf778764a06bcff460e13287", + "benchmark/results/perf_declared_callable_kernels_20260930/runs/cold/control_2/steps.csv": "3cc1861af1d82b40e94a87da0f9fecc77d93df0a7f5bcd60cd585d7b881e6c91", + "benchmark/results/perf_declared_callable_kernels_20260930/runs/cold/control_2/throughput.csv": "3582178c5c102e40c160c01374fcead2f8c832b8be823cda5f435307a681137c", + "benchmark/results/perf_declared_callable_kernels_20260930/runs/cold/control_2/worker_lanes.csv": "78ad314a4c6d3c3f9a0d3d52f40eb97ab82a87ff225b119bafa9414d06ecaccc", + "benchmark/results/perf_declared_callable_kernels_20260930/runs/warm-16w/candidate_1/steps.csv": "d7d7ba3480b8a0fcac8c09527f60601c3bb7e3736835a3f43451e482f67f4e80", + "benchmark/results/perf_declared_callable_kernels_20260930/runs/warm-16w/candidate_1/throughput.csv": "d366dcdd3cac7ca6842311403fecc9c70970a7d4c96e0ecb077c4dab8608c6b5", + "benchmark/results/perf_declared_callable_kernels_20260930/runs/warm-16w/candidate_1/worker_lanes.csv": "148ee1bf9957576adbe2bd3f2427d2242c0b91ff307e266d9beeffe37516472b", + "benchmark/results/perf_declared_callable_kernels_20260930/runs/warm-16w/control_1/steps.csv": "ea341d3daf794c519763fdb6607eb2a8e87f359e6c59efcfe59e00768b086184", + "benchmark/results/perf_declared_callable_kernels_20260930/runs/warm-16w/control_1/throughput.csv": "d5b45e0ffef673d95041faeaaabd5f88f41e9a3ccfefd5be30e420259cf1e20c", + "benchmark/results/perf_declared_callable_kernels_20260930/runs/warm-16w/control_1/worker_lanes.csv": "091ed4bb6af0d2a3d0c1f306817facfdf22bda98b8ec4292f40600f32124ebc5", + "benchmark/results/perf_declared_callable_kernels_20260930/runs/warm-1w/candidate_1/steps.csv": "5ce7beec847c7a168c0b1f631c67f2f96eff78a3755a21dac43cc696ed020cbd", + "benchmark/results/perf_declared_callable_kernels_20260930/runs/warm-1w/candidate_1/throughput.csv": "3f1d5cd5efcef7d785bfc4db1008f9b216dd874e12ba57eea45880d9031c9027", + "benchmark/results/perf_declared_callable_kernels_20260930/runs/warm-1w/candidate_1/worker_lanes.csv": "8987e467e3c0be3478ad9cd8f267f83eaf1275646b4b959d96dd37dfbbe59b1a", + "benchmark/results/perf_declared_callable_kernels_20260930/runs/warm-1w/candidate_2/steps.csv": "c9726b7074d6b156c860f530cb2843346be8c9152b3d4207238c7f0c52756b4f", + "benchmark/results/perf_declared_callable_kernels_20260930/runs/warm-1w/candidate_2/throughput.csv": "1e80b0042c48df962741e15939a78ebd847be5f1ffdffa0f3f58ecd5a1966de0", + "benchmark/results/perf_declared_callable_kernels_20260930/runs/warm-1w/candidate_2/worker_lanes.csv": "22d22dfdaa9a2d3e94492be83368684f0bb520e9c1a0a83e2e0ddd429ddae7ab", + "benchmark/results/perf_declared_callable_kernels_20260930/runs/warm-1w/control_1/steps.csv": "1bdc5f3cd5ee7025d036860d335c84b66a949fb580c342debc796cbcd287415a", + "benchmark/results/perf_declared_callable_kernels_20260930/runs/warm-1w/control_1/throughput.csv": "8e5923e1ff827aad55af177cbc277d18bbdf29766eb470c2e08bd2a9764a540b", + "benchmark/results/perf_declared_callable_kernels_20260930/runs/warm-1w/control_1/worker_lanes.csv": "0d38295275d9bfa8bf47fd27c9da052cab626348ca7af2ef9b3dd797d08c1565", + "benchmark/results/perf_declared_callable_kernels_20260930/runs/warm-1w/control_2/steps.csv": "28e55cfe9ebef2d2d9d7c1360bdf42687e2280b47107345f7ea6115beaf67f7d", + "benchmark/results/perf_declared_callable_kernels_20260930/runs/warm-1w/control_2/throughput.csv": "58d0e53aa0c5afc7ca6d26b4797efe3c6bbc76333528351514f6089f2c92df88", + "benchmark/results/perf_declared_callable_kernels_20260930/runs/warm-1w/control_2/worker_lanes.csv": "c58b38fccc6e83c7141d4917d60b531743e0c1f0b3f91b014755a7b86e5d2186", + "benchmark/results/perf_declared_callable_kernels_20260930/validation/census_after_full.json.gz": "f075c3731639cc5ebaa5f323eb5935d91a4d870dbb2e6ea96db70b6d778b00c4", + "benchmark/results/perf_declared_callable_kernels_20260930/validation/census_before_full.json.gz": "5f3e07267d88d49c0c88e01384604b594ef97922c4bb4e5697208296cc7bcfc4", + "benchmark/results/perf_declared_callable_kernels_20260930/validation/perf-declared-kernel-capture-order-original-regression-20260930.log": "12702fd1022a4d4db576b983c658e19115ff108e0db5ebfdfcb76946745d893b", + "benchmark/results/perf_declared_callable_kernels_20260930/validation/perf-declared-kernel-inherited-lock-candidate-20260930.log": "3275522a65c60210c9aee3615ac7c007be3d0dd63b9902e872ac3dd10094cc3d", + "benchmark/results/perf_declared_callable_kernels_20260930/validation/perf-declared-kernel-inherited-lock-original-regression-20260930.log": "d1b5f1fef92a34bc053c743801d0728c55774fcee2e98b3b7849b0a13db7271b", + "benchmark/results/perf_declared_callable_kernels_20260930/validation/perf-declared-kernel-integrated-consumer-tests-20260930.log": "62425fa689161103b9b8581498903c11b95a69174fd98534a8a1bdc3de9b0222", + "benchmark/results/perf_declared_callable_kernels_20260930/validation/perf-declared-kernel-integrated-dependency-install-20260930.log": "6a43b60d9aa63d7980745c647c86eca240f1d2abc0245ddbc779ca6f6b042959", + "benchmark/results/perf_declared_callable_kernels_20260930/validation/perf-declared-kernel-integrated-installed-provenance-20260930.json": "edbf9a3458ee6a64f3c57932b331ef78697cbcbe93872f34047918e4fbd76217", + "benchmark/results/perf_declared_callable_kernels_20260930/validation/perf-declared-kernel-integrated-r1-20260930.log": "2b2816ec41fb06232920106b03b9dabbd8f044d8e7e7ed0864489b7d9c298c11", + "benchmark/results/perf_declared_callable_kernels_20260930/validation/perf-declared-kernel-integrated-wheel-build-20260930.log": "6553775a2fe6c5e80dcc3fb402de9cfaf3fbe4de7aab40ddab00fc369e4561a4", + "benchmark/results/perf_declared_callable_kernels_20260930/validation/perf-declared-kernel-integrated-wheel-install-20260930.log": "f265f60af03f420f3549488e30f2eb7783fdba01b42777877a66980b69d0b153", + "benchmark/results/perf_declared_callable_kernels_20260930/validation/perf-declared-kernel-nra-admission-order-20260930.diff": "dc242266c89b1d501e68bea9bf4f30fbc3b527bfa5afa94d7402e37d87800908", + "benchmark/results/perf_declared_callable_kernels_20260930/validation/perf-declared-kernel-nra-cache-projection-20260930.diff": "ab986425bc54dcf18ab1229569732c15eedb7cfd6fd3831a2d4fd6eff089f6be", + "benchmark/results/perf_declared_callable_kernels_20260930/validation/perf-declared-kernel-nra-capture-admission-20260930.diff": "6ccb606252a410c366df37fed4068cdc5a8a1f6cb335d93f641fb8edd608012f", + "benchmark/results/perf_declared_callable_kernels_20260930/validation/perf-declared-kernel-nra-hook-phase-20260930.diff": "09a62d9cc814bd90382f96891f6c3c555e35d14b3bcba8eabb0d5fe93fecd016", + "benchmark/results/perf_declared_callable_kernels_20260930/validation/perf-declared-kernel-nra-source-transaction-20260930.diff": "1eab40f216c91868545ccedeee0792293866d293e9b4d9786e782dfd9e9f2de1", + "benchmark/results/perf_declared_callable_kernels_20260930/validation/ratchet_benchmark_full.json.gz": "3c44f2b26488ffac4c4aaab2ffc91549bab5280586e8ac370b9c815a7c84e549", + "benchmark/results/perf_declared_callable_kernels_20260930/validation/ratchet_openhcs_full.json.gz": "a1f8b10203a6d192a003ae6872197ec985dfe7efa77af14940572599f6546565", + "benchmark/results/perf_declared_callable_kernels_20260930/validation/ratchet_scripts_full.json.gz": "b9c7d20235e8d1cb736e637422a20de5a9d6d7b1e6e7257d8ea3c9aef377ab8a", + "benchmark/results/perf_declared_callable_kernels_20260930/warm-16w_observations.jsonl": "23dc4c804613368e9fc6510241836f5db5e0cf645861dd4a40cfb00370e08262", + "benchmark/results/perf_declared_callable_kernels_20260930/warm-16w_scope.json": "4ca55b6593152f4e32693daa0a0c5e5f68116df069ab6cf6989b18f18bde9326", + "benchmark/results/perf_declared_callable_kernels_20260930/warm-1w_observations.jsonl": "c3e1db27a443061c62a26fd2fb28f740305d50465e268b5b87adc4844c41a322", + "benchmark/results/perf_declared_callable_kernels_20260930/warm-1w_scope.json": "c2748dfc40a186a4ef21218ff114dada404d5b62b05b05c52b9198b45c76019a", + "benchmark/results/perf_dependency_source_readiness_20261003/shared-environment-qualification.json": "8715be9d5e5bcbf1fa1334f67433b22c50e2e2f4d8140d127bddc912db344c48", + "benchmark/results/perf_direct_docstring_20260929/README.md": "bc96703dee346baa7971d5d1ab35cc9f475a75d34514396ed74f0ac8356b4559", + "benchmark/results/perf_direct_docstring_20260929/control_fresh.csv": "65d9a015f07256c5b07e6c4baaf3c14ddbc05cd3bc0c9206f3eabf703cd38cd8", + "benchmark/results/perf_direct_docstring_20260929/direct_fresh.csv": "baeaa02de3efa4c944a435ead533bb963fba62649c1ea0eb5a2381281c804956", + "benchmark/results/perf_direct_docstring_20260929/direct_fresh_native_relative.png": "c0449c5128451e07d2a44d329b1196fc59a68df50852d9ad62994f0af6a9e7c3", + "benchmark/results/perf_direct_docstring_20260929/direct_reused.csv": "b522f2b104075ff815b301e78eae3b5b52b6133ceeba83dc17373b16f01d8973", + "benchmark/results/perf_direct_docstring_20260929/direct_reused_native_relative.png": "ed398949fc43f8cdb4b4b36952d1518096629b2cc8a0db036161a6b2231831b2", + "benchmark/results/perf_direct_docstring_20260929/native_cp_summary.csv": "a14d75cfc762140506f703731d78e99310f72f4eae5374345cb8ec008222558d", + "benchmark/results/perf_fast_poll_20260929/README.md": "6a0f668f0579750259855b4b5138bf1c5752589f6f4a05426ee5248918c6c5f2", + "benchmark/results/perf_fast_poll_20260929/fast_poll_well_throughput.csv": "5043444a0a49f963c95d5efd0b29d5e7712b599a511fd7e9da80ab30369f2b9f", + "benchmark/results/perf_fast_poll_20260929/plot.py": "c730cac645b7684ccf31ff3df04ace779c0c8b443247290145a987aaafe280b7", + "benchmark/results/perf_fast_poll_20260929/polling_total_and_slack.png": "64704ceda22ab313afa9510b7016f4af7792c118c59ac98423b36d902f3a0c5e", + "benchmark/results/perf_fast_poll_20260929/wait_breakdown.csv": "71633d5f6c9521c68b8e7a7c91b841ba1a215046392685e5d4c9b0dc19c5b0fc", + "benchmark/results/perf_fork_compiler_prewarm_20260929/README.md": "d41090fd6c37fbb1253955f0cb79573607f6f1296eb4a96cc021ee7b6d2bbaed", + "benchmark/results/perf_fork_compiler_prewarm_20260929/measured_phases.png": "858610eb6d10a9f6fedcca6981436a3f516056d8fc86861e85ae8cf12a0d9d34", + "benchmark/results/perf_fork_compiler_prewarm_20260929/measured_phases.svg": "979030a49c9a62d9d7f17a6d30af2c1e8f237288e75fd1c14776d1c44362f0ad", + "benchmark/results/perf_fork_compiler_prewarm_20260929/method_probe/fork-cold.json": "4829bc68e88e147c4be1be12f7db0426657c0c1dc416ce5279bdc7aac887ccda", + "benchmark/results/perf_fork_compiler_prewarm_20260929/method_probe/fork-warm.json": "422dd55cb471e417a4a31dd1e836d8a9877a96ddab5a5aa676c0939a3e30a780", + "benchmark/results/perf_fork_compiler_prewarm_20260929/method_probe/serial-cold.json": "b18e0f438fdd8db56718141bd014869fb91e172f1c4f44c0d8552353290c6a4e", + "benchmark/results/perf_fork_compiler_prewarm_20260929/method_probe/serial-warm.json": "7ec6997a89b5878d277eed644e25aa41e089b317cbccaee47e9098dc59905ab9", + "benchmark/results/perf_fork_compiler_prewarm_20260929/observations.csv": "0b4900371140a957121146b55f9014ed353baaa0dc56e9988eb871a577b57277", + "benchmark/results/perf_fork_compiler_prewarm_20260929/output_parity.csv": "d4cceb88faee5a6fb0a2c85feb4f643bb5a5e00d957cba18bfaed015c60b6ded", + "benchmark/results/perf_fork_compiler_prewarm_20260929/plot.py": "e41deef66523bc3e89c4f1a27a73efb2e2473675bbecd7bbbdf710cb4d7ca34b", + "benchmark/results/perf_fork_compiler_prewarm_20260929/provenance.json": "ad70f31ef686909f49ff393c05932fb3a0194cc232586639067bed8eb5707831", + "benchmark/results/perf_fused_haralick_20260929/README.md": "7e76ad808f3956e15618329727a0ebe8f2999338fddcf2783256a525fac1d3ef", + "benchmark/results/perf_fused_haralick_20260929/apply_fused_haralick_20260929.py": "7d729dd9fbc183ae68da8b5e3c75964002c50be3249a46c6b8233bdbcb985a0c", + "benchmark/results/perf_fused_haralick_20260929/check_haralick_export_parity_20260929.py": "92a938d62445a26f20c91fea4f32165ea5e6e93a30048cf8eb190997ff379d14", + "benchmark/results/perf_fused_haralick_20260929/class_roles_after.json": "bc630b2cdddca8a1ec18279d6f86949eb508cb03510d8f8f0ac512985f8e2c59", + "benchmark/results/perf_fused_haralick_20260929/class_roles_before.json": "dde2ffc4555e31cdbe3d877e3a57fc60ba218d91614ab5c28ecaddc01fb61d55", + "benchmark/results/perf_fused_haralick_20260929/main_dependency_sync_tests.log": "983deaad161b346d90a4e59daf3686b5b4fe8aa576f5df8621c56ac3f6ed7762", + "benchmark/results/perf_fused_haralick_20260929/measured_phases.png": "6fa05f0f2f3dd4b2fd7c3806a96aa40207003b9bbbcb9b5a72e85f433bfffaab", + "benchmark/results/perf_fused_haralick_20260929/measured_phases.svg": "7d9107d9f15f825ed9af7ca1347cfb6862d058bf9bd10c9553a870e3ed3f146e", + "benchmark/results/perf_fused_haralick_20260929/medians.json": "df7af7ee2b7622469ba974f66ca6b55b19313b5e66b3f25c9cb29007a5cdbb58", + "benchmark/results/perf_fused_haralick_20260929/observations.csv": "331e30099f88d9033cbed7ddb2329c822e84b2faee4aec9d18167d9b985cd483", + "benchmark/results/perf_fused_haralick_20260929/ownership.md": "2e4ea25eeac128ba73bf3bbf00f517bd191f62309cd6d0a08c31ceb19a3dcf0c", + "benchmark/results/perf_fused_haralick_20260929/paired_prewarmed_haralick_runs_20260929.py": "07f207d22ec54b360c7a63bde26ccccc8b9bab3980c9d4253f0302009895b2b4", + "benchmark/results/perf_fused_haralick_20260929/perf-fused-haralick-nra-projected-20260929.diff": "cfcd7011b8abd4d27efb04595c98d3a2036fcce0778f7122694b91a965500d80", + "benchmark/results/perf_fused_haralick_20260929/perf-fused-haralick-ruff-parity-20260929.json": "103a9e3ac59b9c2fafa1ddc9f198e08ee7f9e8678d785d8aa5532a2428a06150", + "benchmark/results/perf_fused_haralick_20260929/perf-fused-haralick-tests-20260929.log": "e6e523bb5c1c1054c9c2c2352e64bd1d54fb885204c325b8b17784ec82f188d2", + "benchmark/results/perf_fused_haralick_20260929/perf-fused-haralick-tests-fixed-20260929.log": "50074f61feb1f320694ee94760c93e04f68768128b92dc4dd318423deb4ef741", + "benchmark/results/perf_fused_haralick_20260929/perf-haralick-export-parity-20260929.json": "c34424a59ce61c8380ebfccd9a3916fa6870af8d980f97f99053c32437a0a29e", + "benchmark/results/perf_fused_haralick_20260929/perf-haralick-prewarmed-pairs-20260929.log": "e127f456b8b26329323095f6100e3fa9d5fd7cae483175e04fd4e3d6025a5cd0", + "benchmark/results/perf_fused_haralick_20260929/plot.py": "e41ce367959d5eb736ac968b08831d3bcf0366bed8b2599c655666635a0f7e7c", + "benchmark/results/perf_fused_haralick_20260929/replay_production_fused_haralick_20260929.py": "af61aadb42df3ba5a63bcb185be4aa472cd01b71cbd330fbec8b5ee26dc0c21b", + "benchmark/results/perf_fused_haralick_20260929/saved_frontier_replay.json": "db39a89bb2ef2c52fc049a52d849271021e9268b6e830953b23f2e7a98652b02", + "benchmark/results/perf_fused_haralick_20260929/steps.csv": "0495f48c3d61c8b7a82699c3b39976ef7f215905b839eace1277d59bee7f32ff", + "benchmark/results/perf_fused_haralick_scaling_20260929/README.md": "d08dcbf2dbe4ba48c9e01b82d66e799751d3135da6ab54ba3929916ac44b956d", + "benchmark/results/perf_fused_haralick_scaling_20260929/input_digest_checks.json": "73ba5709841fd20f52f0bc34254fa251044648b54bedc0fd66f9770f03a199c1", + "benchmark/results/perf_fused_haralick_scaling_20260929/measured_native_scaling.png": "dffdc3ea829e541384eb111aef4da28943134791d002a69ad9d6c2cf02919658", + "benchmark/results/perf_fused_haralick_scaling_20260929/measured_native_scaling.svg": "5ee1d4c2a69fa7b1678535749d33e77ad9b7b4e3613f113b6a6c1824cc441975", + "benchmark/results/perf_fused_haralick_scaling_20260929/measured_ratios.json": "cf0a3644cf5789ce7f15e28862c832ebb26bcdb3070e574582c9792ca01f6d32", + "benchmark/results/perf_fused_haralick_scaling_20260929/native_16w_provenance.json": "462f5fe8862808815cd1f3a0b5ac9783023ef3a3f962ad6c1b15f5e7a16396f8", + "benchmark/results/perf_fused_haralick_scaling_20260929/native_16w_summary.json": "bb75252582f04b94bb7a32aa56e1dd67c9d036a0ee17aa6707a62fdc1b0b3058", + "benchmark/results/perf_fused_haralick_scaling_20260929/native_1w_provenance.json": "ab996e3a02d6b83992c223a6a2886a9a2d184ca3e7ab5870f4bd7c48340271c1", + "benchmark/results/perf_fused_haralick_scaling_20260929/native_1w_summary.json": "e91e1264b72e4ab06454b8746d2b4d1902c88df48690b79427856f2d83182bf8", + "benchmark/results/perf_fused_haralick_scaling_20260929/openhcs_16w_lanes.csv": "0c77c84e969f26c842d77093adbdac5cdda74b81a7381fe0e2cb28d3c28f305b", + "benchmark/results/perf_fused_haralick_scaling_20260929/openhcs_16w_receipt.json": "64bc0294f0e10c59723efe0764078a73d28a083af271a2a8c68b8f611473021a", + "benchmark/results/perf_fused_haralick_scaling_20260929/openhcs_16w_steps.csv": "66f44fcfad3a5f2ac38c07086c144bc49c554d53449537f302bc50d703efc700", + "benchmark/results/perf_fused_haralick_scaling_20260929/openhcs_1w_lanes.csv": "4cdaedb8f3615d48ac4abc5085f604163cd0b25a8bfb75cb8400a8da84685870", + "benchmark/results/perf_fused_haralick_scaling_20260929/openhcs_1w_receipt.json": "61c71a06d6a84bd33cbd597cd95f77cb2321b5f640f2830eac8793ebec43d751", + "benchmark/results/perf_fused_haralick_scaling_20260929/openhcs_1w_steps.csv": "c872b6a597f12a94545d20aa4dd77e760476e0ea58893e2a2526e502b6d25286", + "benchmark/results/perf_fused_haralick_scaling_20260929/openhcs_observations.csv": "8966df254b818a295778cd3d6cb7ae22a462727e173e599c8ed7012d892a6b5d", + "benchmark/results/perf_fused_haralick_scaling_20260929/output_prefix_check.json": "c25e63b2f86280be762759c7d8dbb08d4c0d0b19be97d71ed1f53fc9104cf457", + "benchmark/results/perf_fused_haralick_scaling_20260929/plot.py": "e0b563e48ec793f1f90c73a571b51f32ce80b5b12c74fb36ebf55aa65e92f6aa", + "benchmark/results/perf_fused_haralick_scaling_20260929/provenance.json": "f4d8294e14b6f248d921b672f2194b3c987477a3b8b3d20cedde2885fd5b7f05", + "benchmark/results/perf_fused_haralick_scaling_20260929/recovery_capture.log": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "benchmark/results/perf_fused_haralick_scaling_20260929/recovery_capture_status.json": "20db60eac2659f3592e99d22549f2903134c4c60d7dc8ad1ba57051d5e56b0c3", + "benchmark/results/perf_granularity_native_sampling_20260930/README.md": "1152f62f7018b2373ad0f889ba58b527b17f0396924dabcab3d151f695742ca7", + "benchmark/results/perf_granularity_native_sampling_20260930/analysis.json": "deb2f60fbf6ef2eedf73815eb7e1d72e11057aeafeb3e3f66b1604fb0eb371b1", + "benchmark/results/perf_granularity_native_sampling_20260930/analyze.py": "a4e35ce573ed5fa0a7f4bb960bf0fe072cf94ae9d9b86cb4fe79286f240192fa", + "benchmark/results/perf_granularity_native_sampling_20260930/architecture.md": "bab2d8d5f853ccc6a639d2b3fbd01368379b58ef77a29d6392e2b01739453e4c", + "benchmark/results/perf_granularity_native_sampling_20260930/census_summary.json": "cd494090302120e5cafddee7d0321f583cfd0fe4039951b76846f99f42551940", + "benchmark/results/perf_granularity_native_sampling_20260930/check_export_parity.py": "5b73605782f75598c76925966fe31d363c28c474de6f3f3735cc5fedea10c525", + "benchmark/results/perf_granularity_native_sampling_20260930/cpp_class_census_after.json": "407f99faf394974eb9477c231f4b10c04b563ee7c3d05c9f089e8d7539075123", + "benchmark/results/perf_granularity_native_sampling_20260930/cpp_class_census_before.json": "e5fab502796c82b18d7c4b68bdff81cc97865ba3fdcca20968795be05b63ac45", + "benchmark/results/perf_granularity_native_sampling_20260930/dtype_replay.json": "1a84c800f307e6cdb8ad90333ee21ed47591310e6d72704798bfc5c1cf77d7fe", + "benchmark/results/perf_granularity_native_sampling_20260930/earlier_observations/perf-granularity-native-paired-1w-20260930/observations.jsonl": "620ff1fe5dd7ce94e220c35e548db7e17119c578f38cefbdb006e9c60381af48", + "benchmark/results/perf_granularity_native_sampling_20260930/earlier_observations/perf-granularity-native-paired-1w-20260930/scope.json": "da112f2162f1517ce4115033d7ec39fac5d669590e8a2432621dc0445b733411", + "benchmark/results/perf_granularity_native_sampling_20260930/earlier_observations/perf-granularity-native-paired-steady-1w-20260930/observations.jsonl": "71746efe6578d8d1ead766c760b6b432eb308fc049e91448a2f08dad60d16105", + "benchmark/results/perf_granularity_native_sampling_20260930/earlier_observations/perf-granularity-native-paired-steady-1w-20260930/scope.json": "da112f2162f1517ce4115033d7ec39fac5d669590e8a2432621dc0445b733411", + "benchmark/results/perf_granularity_native_sampling_20260930/export_parity_16w.json": "7bdc09386d2048f28c5a24de245d89c03c5a57c258685ae5556c01652eee1a61", + "benchmark/results/perf_granularity_native_sampling_20260930/export_parity_1w.json": "690fc2abb40ca286775b54cacf182b89685ee2d07095194b8c01ff67c751e226", + "benchmark/results/perf_granularity_native_sampling_20260930/input_digest_checks.json": "73ba5709841fd20f52f0bc34254fa251044648b54bedc0fd66f9770f03a199c1", + "benchmark/results/perf_granularity_native_sampling_20260930/measured_granularity_scaling.png": "e65054ae2f4cee0278a56ba062d4876b8efa5048af6673d0634054947cc7c071", + "benchmark/results/perf_granularity_native_sampling_20260930/measured_granularity_scaling.svg": "c31994311b1b2c0b0e87c992e8223429927c7be1dd7931c3fc71a8fbcb8daa6f", + "benchmark/results/perf_granularity_native_sampling_20260930/observations_16w.jsonl": "9ee767da07b97e9bafb7182091a0dfde2e6e1b5755916c6a7605a128a8617027", + "benchmark/results/perf_granularity_native_sampling_20260930/observations_1w.jsonl": "245ee0039af090258c4cbf4e0a9b7ab46b3a040115ac0b620cafe790632700bb", + "benchmark/results/perf_granularity_native_sampling_20260930/plot.py": "06ce5513e65947b237fa77d3b287214867da4c5386a9078169e313852f8f7c56", + "benchmark/results/perf_granularity_native_sampling_20260930/recipes/01_own_sampling_grid.py": "a0c0e6b91b58525fe9bd7fe9969f8887858f84dc31b1319c0b1b178b70aacd90", + "benchmark/results/perf_granularity_native_sampling_20260930/recipes/02_migrate_sparse_consumer.py": "4908418793212e2a6d8ae3bf6eac2f23aa8c3c02398c76f02d99aeda0101df00", + "benchmark/results/perf_granularity_native_sampling_20260930/recipes/perf-granularity-grid-nra-projected-20260930.diff": "62971066a48920e339c32b0d6ada7f6865c324d15870bd49b8bed0a288791817", + "benchmark/results/perf_granularity_native_sampling_20260930/recipes/perf-granularity-sparse-grid-nra-projected-20260930.diff": "d69dfa553f880c8e1ad4cb30b58c0907af534b7afb2955a0e0a9eed21ce6f999", + "benchmark/results/perf_granularity_native_sampling_20260930/replay_saved_inputs.py": "b93163d027d07c59def5f959a168b766c035e1a3f0741daee8294fef0543d6eb", + "benchmark/results/perf_granularity_native_sampling_20260930/run_pairs.py": "5d44d85055dfc568b8418e7014db55d32bd6fa3d5bfd97ac5d13241b7a6c8a75", + "benchmark/results/perf_granularity_native_sampling_20260930/runs/16w/candidate_1/lanes.csv": "68fea9b269da9b6043688cf21451bdbae79c19040bb66d8c478ac80aca2da786", + "benchmark/results/perf_granularity_native_sampling_20260930/runs/16w/candidate_1/observation.csv": "a29e960b190d06e3052f32771096bccd9bc1b6941822ba28bbf826470c327250", + "benchmark/results/perf_granularity_native_sampling_20260930/runs/16w/candidate_1/receipt.json": "0edc169e4ca223f7e9159123c472262dceb5adbe9c181e1bf972947c4feb0ccb", + "benchmark/results/perf_granularity_native_sampling_20260930/runs/16w/candidate_1/steps.csv": "91da0c0f94fa8dfa7db52e21d8a8930c14444994d1ea4df0d17590d751deea36", + "benchmark/results/perf_granularity_native_sampling_20260930/runs/16w/candidate_1/warm.log": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "benchmark/results/perf_granularity_native_sampling_20260930/runs/16w/candidate_2/lanes.csv": "6d19d8541b3f1e5536f975b1cf1487ebf7a768f6e537ef6e4d39de1283e71ecb", + "benchmark/results/perf_granularity_native_sampling_20260930/runs/16w/candidate_2/observation.csv": "d2e49cb7c87f9cf5448bea18d2ad2bda42d5849407a1a96c960242f7f5d9b194", + "benchmark/results/perf_granularity_native_sampling_20260930/runs/16w/candidate_2/receipt.json": "1a17c4e7da48c46c45e48bb6f4e43c3d4a4c6e40f9e8acfa420dc2ce1601853c", + "benchmark/results/perf_granularity_native_sampling_20260930/runs/16w/candidate_2/steps.csv": "9157fb7b32d155a5f81706cd781a33153f1fef439221230076fe584f20f02e8e", + "benchmark/results/perf_granularity_native_sampling_20260930/runs/16w/candidate_2/warm.log": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "benchmark/results/perf_granularity_native_sampling_20260930/runs/16w/control_1/lanes.csv": "2de4f611388135bb764f3b54ac5117cd3680a70ae432b2e980627d670bacd04d", + "benchmark/results/perf_granularity_native_sampling_20260930/runs/16w/control_1/observation.csv": "638db8e59ee88885dacc7b17abd8af3942dcfb3fb048ec5b031ff85c0da02f8a", + "benchmark/results/perf_granularity_native_sampling_20260930/runs/16w/control_1/receipt.json": "5743cc94191e009e5357f6c4c41556640549b870870213599e2b72d39e71f9b5", + "benchmark/results/perf_granularity_native_sampling_20260930/runs/16w/control_1/steps.csv": "101563be3b6b0a60d7016c19739ffa68583ff9f3f61f2e08d958c35a8aafde7c", + "benchmark/results/perf_granularity_native_sampling_20260930/runs/16w/control_1/warm.log": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "benchmark/results/perf_granularity_native_sampling_20260930/runs/16w/control_2/lanes.csv": "90f4704a2214ae71623e15f2bb0e91eee9566b7a0ebb4295c115c1eccf6e21c4", + "benchmark/results/perf_granularity_native_sampling_20260930/runs/16w/control_2/observation.csv": "6375cc07b07f03e5b214a183142f74fc9c2e50fd426f73e1271dca8a3832482b", + "benchmark/results/perf_granularity_native_sampling_20260930/runs/16w/control_2/receipt.json": "90a12637dab99a321013e3f4e10dca97b96eaf7b9505b936f38af012a2da4f03", + "benchmark/results/perf_granularity_native_sampling_20260930/runs/16w/control_2/steps.csv": "bae568bf6030c1ffe8ce98fcd9b932cf775cb42c1d029283b2bb1dbf465d65e4", + "benchmark/results/perf_granularity_native_sampling_20260930/runs/16w/control_2/warm.log": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "benchmark/results/perf_granularity_native_sampling_20260930/runs/1w/candidate_1/lanes.csv": "3119508f57e8692012b64074d4efe0cceb4f1a4e2a5f7391c3fec3b3909920aa", + "benchmark/results/perf_granularity_native_sampling_20260930/runs/1w/candidate_1/observation.csv": "aefd9df5b670b4fbf7b0d43eaa4740289d0de17bb9c5c94788fd97233b0638d1", + "benchmark/results/perf_granularity_native_sampling_20260930/runs/1w/candidate_1/receipt.json": "4df5d233714528b408c2f0c200d48f57b1b51f996a036ce1b72617c4194308a8", + "benchmark/results/perf_granularity_native_sampling_20260930/runs/1w/candidate_1/steps.csv": "93c5fd981444a55c373bcb6b5d86c54b623dc132061ed37a6fc0b727ba8f3a76", + "benchmark/results/perf_granularity_native_sampling_20260930/runs/1w/candidate_1/warm.log": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "benchmark/results/perf_granularity_native_sampling_20260930/runs/1w/candidate_2/lanes.csv": "51d665398e0caced3ff6011cf84688c5284bc122d5d343330f340c4ebc7bdcb8", + "benchmark/results/perf_granularity_native_sampling_20260930/runs/1w/candidate_2/observation.csv": "ebb76efb20b4981255ed3afa62a5ce27e10f71c352415da154314be1821ea103", + "benchmark/results/perf_granularity_native_sampling_20260930/runs/1w/candidate_2/receipt.json": "c5167be0a785cc0ac05cd5e583769a592104178aec995148cb7af4fb0090497e", + "benchmark/results/perf_granularity_native_sampling_20260930/runs/1w/candidate_2/steps.csv": "f02fd2969726f3081401c97ae39881972701bf67ff94d442c64b151a87592ca1", + "benchmark/results/perf_granularity_native_sampling_20260930/runs/1w/candidate_2/warm.log": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "benchmark/results/perf_granularity_native_sampling_20260930/runs/1w/control_1/lanes.csv": "c54a086f9a5dfca4c108f1f27d4cb1647fbd434758de6486a3fb2226befce6d1", + "benchmark/results/perf_granularity_native_sampling_20260930/runs/1w/control_1/observation.csv": "a8a6e73d1477493ec7c979ee8a7b6d0df30dab71664649661e5ace31693133ac", + "benchmark/results/perf_granularity_native_sampling_20260930/runs/1w/control_1/receipt.json": "84038f3397c0da6f4f2291e0748f3a38777f60275091805d1d6b785512dd4f88", + "benchmark/results/perf_granularity_native_sampling_20260930/runs/1w/control_1/steps.csv": "80552d2035d0a15666f06955c2e180840926a2225b113eb93ca766e475a9f675", + "benchmark/results/perf_granularity_native_sampling_20260930/runs/1w/control_1/warm.log": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "benchmark/results/perf_granularity_native_sampling_20260930/runs/1w/control_2/lanes.csv": "adab77881db78c11b02c443bca27095885b62893cfece3e0661b71939d008dfe", + "benchmark/results/perf_granularity_native_sampling_20260930/runs/1w/control_2/observation.csv": "a057337107afca793e6426f30bec8b3d4c911219a34ed9a712c1a324d23410a9", + "benchmark/results/perf_granularity_native_sampling_20260930/runs/1w/control_2/receipt.json": "3b77cddd993412eb442c3f39acff7b126e85770bf92633b20fb79392ec9c956a", + "benchmark/results/perf_granularity_native_sampling_20260930/runs/1w/control_2/steps.csv": "a1a6708170695b214dccdaa3c52d9130c9bc6ae70f671cb4f23a1cba379f882e", + "benchmark/results/perf_granularity_native_sampling_20260930/runs/1w/control_2/warm.log": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "benchmark/results/perf_granularity_native_sampling_20260930/saved_input_replay.json": "8736f32e04929928f08e7de507036e80f4c82c9e03771fdfbe8aaf37bcaaeea8", + "benchmark/results/perf_granularity_native_sampling_20260930/scope_16w.json": "dc9c90ba6a6e90e50e763cf4a35ce9e4069e68305bf3c241b0b0c9f612bcbd12", + "benchmark/results/perf_granularity_native_sampling_20260930/scope_1w.json": "2810bbd9100bf34ffd717ef8748e603a3e83670914b2b706d5d3c8766529525a", + "benchmark/results/perf_granularity_native_sampling_20260930/validation/perf-granularity-latest-main-integration-tests-20260930.log": "251044be6f7d4a933a4457fa8a41568d33a37206499e45b72f4654624ff87a73", + "benchmark/results/perf_granularity_native_sampling_20260930/validation/perf-granularity-main-integration-tests-20260930.log": "84afadedbd349b06243f8a97c34d7454f25b13e3faaa60e46018e183bd7a6e89", + "benchmark/results/perf_granularity_native_sampling_20260930/validation/perf-granularity-native-build-20260930.log": "817b0dde474117531a1dfad095033631f976ac15f83cb1cbc65f4134dd7f52e7", + "benchmark/results/perf_granularity_native_sampling_20260930/validation/perf-granularity-native-candidate-1w-r1-20260930.log": "dd3cb00ed5fce5b5de43d07c24d459c2bd99532cb29b60edc50e6dc124f52f06", + "benchmark/results/perf_granularity_native_sampling_20260930/validation/perf-granularity-native-candidate-1w-r2-20260930.log": "306c705d985addf6b7bd8a472b9fa1bbc19605e696bc55dd9bb45ef5b9603da4", + "benchmark/results/perf_granularity_native_sampling_20260930/validation/perf-granularity-native-candidate-main-16w-r1-20260930.log": "e1b58481bbefc3823889c21190bf591f1010ee43001c07a78d4d784a08376a2f", + "benchmark/results/perf_granularity_native_sampling_20260930/validation/perf-granularity-native-candidate-main-16w-r2-20260930.log": "6ba6853435ef66126d38702a49e905518e4576616fb5302405c47691bd433c0c", + "benchmark/results/perf_granularity_native_sampling_20260930/validation/perf-granularity-native-candidate-main-1w-r1-20260930.log": "2194f7f736cacc6aeaf109e596825a19f2687f1e142b492805f69ba98fe48ab9", + "benchmark/results/perf_granularity_native_sampling_20260930/validation/perf-granularity-native-candidate-main-1w-r2-20260930.log": "a3a87051d4fdd1b832204d602ee90ef41528076158a1960f6f0cda504076378d", + "benchmark/results/perf_granularity_native_sampling_20260930/validation/perf-granularity-native-candidate-steady-1w-r1-20260930.log": "11f3ea9c45d4f439b36d9cb09bc44ae3db7d20f4b7cc7a790511fd228c0ad22d", + "benchmark/results/perf_granularity_native_sampling_20260930/validation/perf-granularity-native-candidate-steady-1w-r2-20260930.log": "99a08919e6746613714d874e6fe5dd222768b4bf729156bdcffb0fa305f8c56f", + "benchmark/results/perf_granularity_native_sampling_20260930/validation/perf-granularity-native-control-1w-r1-20260930.log": "aec47865920cbfe92f775aed275c35604a9d8f7d41d490fe03166f89d822bcdb", + "benchmark/results/perf_granularity_native_sampling_20260930/validation/perf-granularity-native-control-1w-r2-20260930.log": "aa9816c08cdf89e12c760a0de974347b84b66c6e7ddf254be13153e3e0016b63", + "benchmark/results/perf_granularity_native_sampling_20260930/validation/perf-granularity-native-control-main-16w-r1-20260930.log": "275dfe2f0f47e4a83dd68415f06786106ced00ce0aebbfd7469aef6b9a5cb683", + "benchmark/results/perf_granularity_native_sampling_20260930/validation/perf-granularity-native-control-main-16w-r2-20260930.log": "52eb6c7cec6da570e47c45173b3f7e99e5d7ee013f63864c42bbed8e22a26155", + "benchmark/results/perf_granularity_native_sampling_20260930/validation/perf-granularity-native-control-main-1w-r1-20260930.log": "87c77149c096d426fb4a4b4263d5e38f580446bbc10e5e17d5e490fa0c66d65c", + "benchmark/results/perf_granularity_native_sampling_20260930/validation/perf-granularity-native-control-main-1w-r2-20260930.log": "2839fa4c7b0174d81059b80b52c386cd962285dfe1f4d39cdc47fa4bc03e656e", + "benchmark/results/perf_granularity_native_sampling_20260930/validation/perf-granularity-native-control-steady-1w-r1-20260930.log": "a3e539f1f97afe81931b3a7edfd3e413f928c314b62630a2a67298bb8c870e8f", + "benchmark/results/perf_granularity_native_sampling_20260930/validation/perf-granularity-native-control-steady-1w-r2-20260930.log": "da98ff540cb8690036024feb0432ddab850ae00c4278c24b568bbb109cfeb6ec", + "benchmark/results/perf_granularity_native_sampling_20260930/validation/perf-granularity-native-edge-tests-20260930.log": "70030fc54b05e8e948122cc7080b8587f3d26dfdbfcd156f2db85382d2449f0e", + "benchmark/results/perf_granularity_native_sampling_20260930/validation/perf-granularity-native-final-production-replays-20260930.log": "8736f32e04929928f08e7de507036e80f4c82c9e03771fdfbe8aaf37bcaaeea8", + "benchmark/results/perf_granularity_native_sampling_20260930/validation/perf-granularity-native-final-tests-20260930.log": "e0a7213e40a57df421c4d50092ef9fa4d8ba933ec2420404125752eb7f757629", + "benchmark/results/perf_granularity_native_sampling_20260930/validation/perf-granularity-native-final-wheel-build-20260930.log": "e584d1dde05604676bdb173cdfa716c574c07c49385e8287cc433c0955e6363f", + "benchmark/results/perf_granularity_native_sampling_20260930/validation/perf-granularity-native-first-tests-20260930.log": "0084d084ab04e8c2df76092e6ffd291a6bac141ad5a57682e4954a4d79fae6db", + "benchmark/results/perf_granularity_native_sampling_20260930/validation/perf-granularity-native-production-replays-20260930.log": "13a7334bcd744f19d7bd229df5d69c804f0b788476f141c253c066915c2a7e6d", + "benchmark/results/perf_granularity_native_sampling_20260930/validation/perf-granularity-native-strict-boundary-tests-20260930.log": "d3cfaa0082aaabf780fa23a4e6749de937f399bf9c2781dd80f42812115786e8", + "benchmark/results/perf_granularity_native_sampling_20260930/validation/perf-granularity-native-wheel-build-20260930.log": "7fe2a48d3508e397da00bf66c4edf570e34a93a1ab3d0491043109f53efc623d", + "benchmark/results/perf_granularity_native_sampling_20260930/validation_manifest.json": "ba0f6f052de666947fb34ac39365620589f7a811a204fcdddb4bb3f4f657d7ee", + "benchmark/results/perf_granularity_native_sampling_20260930/wheel_smoke.json": "8dad3fd78351c72b18e976a85a05447e7a068336eda51f4222b9f1deffa9b088", + "benchmark/results/perf_lazy_catalog_20260929/README.md": "a0383ead1f0009d7c0eb00e228fe3126188f526038f33100731060df76583df6", + "benchmark/results/perf_lazy_catalog_20260929/control_fresh.csv": "baeaa02de3efa4c944a435ead533bb963fba62649c1ea0eb5a2381281c804956", + "benchmark/results/perf_lazy_catalog_20260929/fresh_total_breakdown.png": "7fc23391c879535fca84188c431bc266a4bd59d3268e2f82631a2d89a99cd8e8", + "benchmark/results/perf_lazy_catalog_20260929/fresh_total_breakdown.svg": "f92b21dd7e5505606f04455b33f6c763afe23cdfb514ec878350a10644162995", + "benchmark/results/perf_lazy_catalog_20260929/lazy_fresh.csv": "0a2e7686d78cce4f21be8c51251519d678f5365d296a9d122743661e83281a50", + "benchmark/results/perf_lazy_catalog_20260929/lazy_native_execution_cdf.png": "602339ed2c680e288a11d7f23c0f7b1a1b6d9502459a14cbd150d0c2746931a2", + "benchmark/results/perf_lazy_catalog_20260929/lazy_native_execution_speedup.png": "c6fe70a732afb9b307150ae4b2f1cc0f60bd1c80057f28b92a14cad959d61730", + "benchmark/results/perf_lazy_catalog_20260929/native_cp_summary.csv": "a14d75cfc762140506f703731d78e99310f72f4eae5374345cb8ec008222558d", + "benchmark/results/perf_lazy_cp_registry_20260929/README.md": "17c1d91cfe8716bc1190a936006f8d32c52ead8ba013c28689a9defb2220e10d", + "benchmark/results/perf_lazy_cp_registry_20260929/abba.csv": "7d92d6e50da1037e10ffdb6854f40afa8b54dc56257ec610cc82fa0e515dd5b7", + "benchmark/results/perf_lazy_cp_registry_20260929/candidate.csv": "010c60ea28ac3b831d79eb2708c78debfa98fbccd26094b5cdd5d9fc827e00c7", + "benchmark/results/perf_lazy_cp_registry_20260929/control.csv": "c8a08fc6e9f00a9ce72ef4c60a62ef805ba07ffe168d381930e43de68ba9a344", + "benchmark/results/perf_lazy_cp_registry_20260929/fresh_server_total_breakdown.png": "1c25a11a741a5ed49fb6f7d117528ebdc5a00ac706d79effcc0619dd37499d76", + "benchmark/results/perf_lazy_cp_registry_20260929/lookup_only.csv": "9852b479dd349ecabc95e666e99a351786eba886b748e2135ba35ca17b4d371c", + "benchmark/results/perf_lazy_cp_registry_20260929/per_case_phase_deltas.png": "ded04cda8aeaed7485d5a73732f12544e05e0b960cfb5c7d61c025c8c04002c8", + "benchmark/results/perf_lazy_cp_registry_20260929/plot.py": "2b9927a8159da3887ae6265a2eead3fb85fde53871f2daf0138a25999a67a608", + "benchmark/results/perf_lazy_cp_registry_20260929/scoped.csv": "b7589b2a7dd3cc85b8b4732216f2cdde53d27269beb0b14364099418d26e596e", + "benchmark/results/perf_lazy_ome_zarr_20260929/README.md": "c4f1fd610b6b974cc5a581a1900782e321484f777f57f00caf5dd23359903acb", + "benchmark/results/perf_lazy_ome_zarr_20260929/candidate.csv": "2be45166bf843144544aecbddd0424f06158228025431c659c5b0762943ec50b", + "benchmark/results/perf_lazy_ome_zarr_20260929/control.csv": "77ad4113fdc086c9412ea0aab24e19a8db93cf960e749b2fb4a2ac92394455dd", + "benchmark/results/perf_lazy_ome_zarr_20260929/fresh_server_total_breakdown.png": "557d6ac7c7ec89d5a16a2d49781223573e4626a4cb6e0d01c8ba16e43f29aec1", + "benchmark/results/perf_lazy_ome_zarr_20260929/per_case_nonjob_delta.png": "a36ce9b826d711decfd2ad34f15ae8c4afa9e99910993e9b54cfaeb352debab8", + "benchmark/results/perf_lazy_ome_zarr_20260929/plot.py": "a555b4da51c6597d1b54608ae841cd38d3dcf167d8f3073ba6dfecbd42b8d1a2", + "benchmark/results/perf_long_form_export_20260929/README.md": "7305c2f43d9234eb01e7dd1d8250db11d43de375f91e495890ae7da2e012d1d9", + "benchmark/results/perf_long_form_export_20260929/imagingflow_scaling_vs_native.png": "c4cdc890b3917552efb8f0485e01347de22d99573e12bc049d30029699093e18", + "benchmark/results/perf_long_form_export_20260929/observations.csv": "56bbe1d3eea2e300a972b0e86659ed78defaf1f0d2c40ca0545a0945b1c812ed", + "benchmark/results/perf_long_form_export_20260929/official30_totals.csv": "c92665a1013b0ad22b9e0d476c37a91e7e2ca866d9bb7e6170385a64551a7c2f", + "benchmark/results/perf_long_form_export_20260929/plot.py": "13e0065694fc0b64ff12ec03e4bb34ea472e2dea62e3d565b0ead2ff408a81ea", + "benchmark/results/perf_native_batch_durability_20260929/README.md": "68e7414346907334ae197e388cc349232053a59000b87e2b71200f66766d9bde", + "benchmark/results/perf_native_batch_durability_20260929/authored_nra_transaction.py": "60342b74f0e62d69c90cefdf4676dc3b73edb3e4df26d12a65c05b8b6cddf4c1", + "benchmark/results/perf_native_batch_durability_20260929/class_roles_after.json": "3eba64ae4564c918f79dbc8619ebabf9b154e5a0998ecd409c495126ba4d7bfa", + "benchmark/results/perf_native_batch_durability_20260929/class_roles_before.json": "2425998e665b877af726f7f0e2c819bad1a892fb5d97a14dbb686af79203e5b9", + "benchmark/results/perf_native_batch_durability_20260929/perf-native-batch-durability-nra-projected-20260929.diff": "d59f34de3c253daf9b9dd77fbeb74b31b2006dd6f6f9f6090dbf368149d6709f", + "benchmark/results/perf_native_batch_durability_20260929/perf-native-batch-durability-ruff-parity-20260929.json": "0d9503776ce5fe2a238428d520007feb9699bd33606d72f7a4acb7d8cd24cbe6", + "benchmark/results/perf_native_batch_durability_20260929/perf-native-batch-durability-tests-20260929.log": "91df7ae57684662b410cb4ee37f2f63f6f0a2db89eb8b469c8db1e06a781aa9e", + "benchmark/results/perf_native_synthetic_scaling_20260929/ExampleColocalization_16w_provenance.json": "c199d7b4658e96981e33403e70c194573e47cbc76b5382d0fcad49a310214309", + "benchmark/results/perf_native_synthetic_scaling_20260929/ExampleColocalization_16w_summary.json": "04e596323cb05b7fac40e688a48d18d0daa9c0cd02dc23bc5859dfa0b4d4238c", + "benchmark/results/perf_native_synthetic_scaling_20260929/ExampleColocalization_1w_provenance.json": "344d44603b3b2f7d8e7bbd6127902298a1dea4a8a7a95e9cb1a7f54b375c92d9", + "benchmark/results/perf_native_synthetic_scaling_20260929/ExampleColocalization_1w_summary.json": "6ecda793fe883c638cfe3a876e8ca3cdf7c5eadc51e96e0566496863539cfb9a", + "benchmark/results/perf_native_synthetic_scaling_20260929/ExampleImagingFlowCytometryObjectsInGrid_16w_provenance.json": "4d2d29f71bb837907a484d98347e53c6935d65076c09e5b17dc6627beaf39793", + "benchmark/results/perf_native_synthetic_scaling_20260929/ExampleImagingFlowCytometryObjectsInGrid_16w_summary.json": "2091f9f1ec5763986b3f288f4e4cc0b906787430a12f5e09459b496dba285359", + "benchmark/results/perf_native_synthetic_scaling_20260929/ExampleImagingFlowCytometryObjectsInGrid_1w_provenance.json": "85b19062484e5b2791760e1269a831cd68a2fb9c008972692c4b3195d1ef9bbb", + "benchmark/results/perf_native_synthetic_scaling_20260929/ExampleImagingFlowCytometryObjectsInGrid_1w_summary.json": "4353c55fa9320cda777eb9e220a0e8ef1f0ce1585e12a3d225eb4d3633a1be0b", + "benchmark/results/perf_native_synthetic_scaling_20260929/README.md": "5d9d394d5c8630de888cb11c644c93eab5bc528b48c7f9c169cb883b747018ba", + "benchmark/results/perf_native_synthetic_scaling_20260929/cache_probe_observations.csv": "4d8bb5c4f25b844b3930c17682f699aff99e3c69e41450f9cb534345389830a0", + "benchmark/results/perf_native_synthetic_scaling_20260929/cache_probe_steps.csv": "88de53af149104bbccfe0f7de5d06208ece15dce78262d95a7c6319fe8fd5c65", + "benchmark/results/perf_native_synthetic_scaling_20260929/measured_native_scaling.png": "05562fdc06828c2d5f67e52543eb139a9d27b7762ea0625aef68c96590cbcddc", + "benchmark/results/perf_native_synthetic_scaling_20260929/openhcs_observations.csv": "7f3bc948e162c2a835710be3e42c12c88b42a523cf5c65e6a12b704810b313df", + "benchmark/results/perf_native_synthetic_scaling_20260929/plot.py": "d2127deac41ad1bd91e1794ea541171fbc2e66dc08536b111c39e62f23b4abfa", + "benchmark/results/perf_native_tabular_20260929/README.md": "18e208d5df7cd4cd9e17af6a51c7974b4f5accf9bd3f6a3b94d77b46a963e8e8", + "benchmark/results/perf_native_tabular_20260929/abi_audit.json": "f278609477391c5cf8815372b488b1ba6287f88458efbd74e35be9dd97cedc09", + "benchmark/results/perf_native_tabular_20260929/broad_tests.log": "40f1f288eb85faeaaa394105980a5632ba1fbcbe48603e286067a8ba8cb86e4f", + "benchmark/results/perf_native_tabular_20260929/focused_tests.log": "adf6e9cc742286bb53bb33508c9dc4123a7ffcdd459e678ac7721b844b5464fc", + "benchmark/results/perf_native_tabular_20260929/installed_wheel.json": "3e87d0df974ee052d57375363ea8419eb12d3712818c39d4d498a32bca6d002d", + "benchmark/results/perf_native_tabular_20260929/measured_pipeline_receipt.json": "54bf5ee3ad39545cb474f78f86004adf1a30a216b0a4636735e884fd1b5860bf", + "benchmark/results/perf_native_tabular_20260929/nominal_build_classes.csv": "a87fcc5b0d4b64c62bb372612d906bc574f9deffba401210e5e25ad204cc07cf", + "benchmark/results/perf_native_tabular_20260929/ordinary_run.csv": "c0a1583d7cf56bd34af55e4fb989d8a16efa088c71c5c1eb698090ff4770376a", + "benchmark/results/perf_native_tabular_20260929/ownership.md": "79862819e186a04f5de14ae0cb8c5fe9e0054b926c2c8ff568b50f2dbc96a77b", + "benchmark/results/perf_native_tabular_20260929/provenance.json": "f4360d39eb19357d0ff6acf0cfc4da22631643605eddfcf7b009060edd05ea87", + "benchmark/results/perf_native_tabular_20260929/ruff_baseline.json": "b7c5f1c4c036131be8fae5743ac4046dbe3205e1368c9c2d07a8b1af51810238", + "benchmark/results/perf_native_tabular_20260929/saved_input_replays.json": "4783207b8c40f2727db73cd2c058f01ff2da1d2e92ac2cb52565a8205f6104dd", + "benchmark/results/perf_native_tabular_20260929/step_timings.csv": "dde363d4f0c1c91aad22db7f933024f9c9780ce82365b7dddf439deda0f2b51f", + "benchmark/results/perf_nominal_preparation_20260929/README.md": "4559e5a21d21d3a6792f64fe0e95d8573a5b43b755f8ca341ec0bcc758330c3c", + "benchmark/results/perf_nominal_preparation_20260929/observations.csv": "c06c14948fbf011025820016a0ebdc7248b8ce4c39e24c80799f230253513d01", + "benchmark/results/perf_nominal_preparation_20260929/output_parity.csv": "6d7a4a17ac6720e3844c7f37c6fb49dc9e58a5f026f047714652da4de50f94bd", + "benchmark/results/perf_nominal_preparation_20260929/ownership_decision.md": "010031ebee7614ff83bf6fac9ef38cb35d46f6b7e01534575c0e2bb9dbb8209f", + "benchmark/results/perf_nominal_preparation_20260929/probe_spawn_cache.py": "9ff0b53fa0e4b6665d1ebb21cefccfebc7773de5302c8c308de00bc64ec7e098", + "benchmark/results/perf_nominal_preparation_20260929/provenance.json": "94d6a06c7742a6e6a89697695338ca08a58c5b9b1b328105599ea8a60d081c8b", + "benchmark/results/perf_nominal_preparation_20260929/shared_environment.json": "ceef376ab654d753103c155acdb8437f0e1441f32127131a56111a2411a07149", + "benchmark/results/perf_nominal_preparation_20260929/shared_mcp_health.json": "60bcb5a20f06309ca889a6362c833343d10418648c8b9a719e47eaba345c8ff0", + "benchmark/results/perf_nominal_preparation_20260929/shared_requirements.txt": "fe17c29ad9c9a782fda6dc8c2adcc0134da259435837b4f2621cbc5d42b11c2f", + "benchmark/results/perf_nominal_preparation_20260929/spawn_cache_hits.json": "40235c72fe6121dec137919c9d993e46a7562a2091524cb913e3b12abcd60bdf", + "benchmark/results/perf_owned_label_hulls_20260930/README.md": "926e851555d8d4054b006dc4887e0cb9a94648bf98db0b0e7c71b6f6dd7bb321", + "benchmark/results/perf_owned_label_hulls_20260930/analysis.json": "74381e4d1b7c6af6c828f5f467c0e1afca5ee190017395ad66b9bbe516f0883a", + "benchmark/results/perf_owned_label_hulls_20260930/architecture.md": "42699e2b9798cef4efac48ddb3e065f7b9fc6577067307e98eb7f0dba738bbc9", + "benchmark/results/perf_owned_label_hulls_20260930/architecture_transactions/perf-owned-hull-common-outline-nra-projected-20260930.diff": "366eca170026ef8722ad64d6c78e7e93e30b4d3980a8c4bf0e63c9ec4713e67d", + "benchmark/results/perf_owned_label_hulls_20260930/architecture_transactions/perf-owned-hull-leaf-contracts-nra-projected-20260930.diff": "f64d1fe84dc9a353928bc28c7ba80db001034eeac8ec89d1e255b3e8b546b0af", + "benchmark/results/perf_owned_label_hulls_20260930/architecture_transactions/perf-owned-label-hull-nra-projected-20260930.diff": "e41e5acb98e55395d6b4527e60f272d8a143afd8b90c7c336534a7b90289e493", + "benchmark/results/perf_owned_label_hulls_20260930/captured_circle_frontier.json": "d555f121c808764f521d6a876e54367817dc29695867d50396a0cad53875a9d2", + "benchmark/results/perf_owned_label_hulls_20260930/export_hashes.json": "fc0abbb1e6305f54eb626a9961477d4ad0cbf1928666ea599563ee04c993017c", + "benchmark/results/perf_owned_label_hulls_20260930/input_digest_checks.json": "73ba5709841fd20f52f0bc34254fa251044648b54bedc0fd66f9770f03a199c1", + "benchmark/results/perf_owned_label_hulls_20260930/measured_hull_scaling.png": "c1ce6d371f765ef36f4011052e8b954a668f0e634a5fe62b850f3c0096d20685", + "benchmark/results/perf_owned_label_hulls_20260930/measured_hull_scaling.svg": "a35e6a2992241d14ad15a57e8bcc0b21c493fe66c1a20a886f1842ed0ee85a8e", + "benchmark/results/perf_owned_label_hulls_20260930/observations_16w.jsonl": "cc3e6ff6865888e77693dedf84b2a29cece87323becbd624350beeb33b761255", + "benchmark/results/perf_owned_label_hulls_20260930/observations_1w.jsonl": "2e901b4d20bd7cd7fba55211d31e916e2dc209d13f7a3c8920a2f324a54bcd58", + "benchmark/results/perf_owned_label_hulls_20260930/parity/16w_1.json": "91ce60d66ce48d09137e06d1ae6d4d8bbb951ae7c91879f34fb0a0caa82135c9", + "benchmark/results/perf_owned_label_hulls_20260930/parity/16w_2.json": "91ce60d66ce48d09137e06d1ae6d4d8bbb951ae7c91879f34fb0a0caa82135c9", + "benchmark/results/perf_owned_label_hulls_20260930/parity/1w_1.json": "6db2f7a6b3bc0dc94b6c266ab8c9e8dcf640f28b4d17647d3453cdeaab57afe4", + "benchmark/results/perf_owned_label_hulls_20260930/parity/1w_2.json": "6db2f7a6b3bc0dc94b6c266ab8c9e8dcf640f28b4d17647d3453cdeaab57afe4", + "benchmark/results/perf_owned_label_hulls_20260930/runs/16w/candidate_1/preparation.log": "126e37216097eae16adba6d9b10734088f9aec8869055037ca4cf9cec5cc7e5e", + "benchmark/results/perf_owned_label_hulls_20260930/runs/16w/candidate_1/steps.csv": "77fc2150cf2fc04385c182ec87b3918ae8b47a2b64a008c15cafaa25052825a9", + "benchmark/results/perf_owned_label_hulls_20260930/runs/16w/candidate_1/throughput.csv": "41e95dbf6aae43808e11c45ff4bbc03d416aaf05f93213e1f19c0440a0ffae06", + "benchmark/results/perf_owned_label_hulls_20260930/runs/16w/candidate_1/worker_lanes.csv": "276ffad7083054a9b4ec3ef30edce3132aad70f806a1cd32f9db2f21ac951535", + "benchmark/results/perf_owned_label_hulls_20260930/runs/16w/candidate_2/preparation.log": "126e37216097eae16adba6d9b10734088f9aec8869055037ca4cf9cec5cc7e5e", + "benchmark/results/perf_owned_label_hulls_20260930/runs/16w/candidate_2/steps.csv": "f9a808fe8a66abdf054b0c2af6ba4f25aea836988d8f6751bb42f042ababab91", + "benchmark/results/perf_owned_label_hulls_20260930/runs/16w/candidate_2/throughput.csv": "6e1b1c6ece5753722b07b6461f6da2e3c0151f48113472189e80673fc00e191d", + "benchmark/results/perf_owned_label_hulls_20260930/runs/16w/candidate_2/worker_lanes.csv": "ef6594640d1c822a563aa221a1f240117df469e028f47456777600d02a8f8975", + "benchmark/results/perf_owned_label_hulls_20260930/runs/16w/control_1/preparation.log": "126e37216097eae16adba6d9b10734088f9aec8869055037ca4cf9cec5cc7e5e", + "benchmark/results/perf_owned_label_hulls_20260930/runs/16w/control_1/steps.csv": "169810bf1f2bc5c17bf9f3e780b240de639224cc6b074b7d9e99b6eade848999", + "benchmark/results/perf_owned_label_hulls_20260930/runs/16w/control_1/throughput.csv": "431441321f944a7e28770f05ad0d1cf1e8e98e3b2026ff5c8ee5f7b3bb6ce85f", + "benchmark/results/perf_owned_label_hulls_20260930/runs/16w/control_1/worker_lanes.csv": "cbac9c083d8d1732b8fc8882efe5a04964ec612c5ef7b6205b6659044093d8de", + "benchmark/results/perf_owned_label_hulls_20260930/runs/16w/control_2/preparation.log": "126e37216097eae16adba6d9b10734088f9aec8869055037ca4cf9cec5cc7e5e", + "benchmark/results/perf_owned_label_hulls_20260930/runs/16w/control_2/steps.csv": "c7b3e60b3cf071803d7e4613cf56079336dbfc84f627a96cd0c0493148d5be26", + "benchmark/results/perf_owned_label_hulls_20260930/runs/16w/control_2/throughput.csv": "5a2fdbcb1b4750ddec7ea8bac77ab34012819c735cbd43285bcf04cf71f444c7", + "benchmark/results/perf_owned_label_hulls_20260930/runs/16w/control_2/worker_lanes.csv": "8d50d0606168c00302f13a909a76be1495544336d72eaf29d8f7229eb0cace18", + "benchmark/results/perf_owned_label_hulls_20260930/runs/1w/candidate_1/preparation.log": "126e37216097eae16adba6d9b10734088f9aec8869055037ca4cf9cec5cc7e5e", + "benchmark/results/perf_owned_label_hulls_20260930/runs/1w/candidate_1/steps.csv": "6d32bd6347174ed34e095e223e4412ec2deb26fb773fa188d9fc58e4c17f933c", + "benchmark/results/perf_owned_label_hulls_20260930/runs/1w/candidate_1/throughput.csv": "e91c20c07d487a5b6035b86d2bbe2caafed1face61a2513a861b6d73bace9e09", + "benchmark/results/perf_owned_label_hulls_20260930/runs/1w/candidate_1/worker_lanes.csv": "b11748e48b8f85c93936ede3d5ce5ad35b4d475e96f8c0a15779783227536c65", + "benchmark/results/perf_owned_label_hulls_20260930/runs/1w/candidate_2/preparation.log": "126e37216097eae16adba6d9b10734088f9aec8869055037ca4cf9cec5cc7e5e", + "benchmark/results/perf_owned_label_hulls_20260930/runs/1w/candidate_2/steps.csv": "539b4d3cf19b5ffa71c3a91d36adca014f847c768ec38119e9100eec69ac8180", + "benchmark/results/perf_owned_label_hulls_20260930/runs/1w/candidate_2/throughput.csv": "ad16d0b6fe2f648f33e6adf64d8bfb9ed65b9a9e1d41ce7e97a7049421ff90b9", + "benchmark/results/perf_owned_label_hulls_20260930/runs/1w/candidate_2/worker_lanes.csv": "fba3cc04a96f857f37ec1a87f3dd83a8d5d3feb8c71be54320a8d7f0e9fee49d", + "benchmark/results/perf_owned_label_hulls_20260930/runs/1w/control_1/preparation.log": "126e37216097eae16adba6d9b10734088f9aec8869055037ca4cf9cec5cc7e5e", + "benchmark/results/perf_owned_label_hulls_20260930/runs/1w/control_1/steps.csv": "376cfc51e6bb7ec4ddc754f666a5536dd2f2bddd73e1f44876f209e358325800", + "benchmark/results/perf_owned_label_hulls_20260930/runs/1w/control_1/throughput.csv": "82c9d6d92250a81400dae6533a5bbd6fc6b16e09c037171dd083d5267432c4ca", + "benchmark/results/perf_owned_label_hulls_20260930/runs/1w/control_1/worker_lanes.csv": "0738afe9aaa5e78c60a8b2345bc5212bd583be0bb107370fec8905e76591584d", + "benchmark/results/perf_owned_label_hulls_20260930/runs/1w/control_2/preparation.log": "126e37216097eae16adba6d9b10734088f9aec8869055037ca4cf9cec5cc7e5e", + "benchmark/results/perf_owned_label_hulls_20260930/runs/1w/control_2/steps.csv": "82e29922ddede1697ce200a3de7fca73b7316673bd0e5d27af57adb531bc722c", + "benchmark/results/perf_owned_label_hulls_20260930/runs/1w/control_2/throughput.csv": "c76bf33b3e0857ab1eadd749faf09c075c5335b411b373e0af1aa5084b6ab7bd", + "benchmark/results/perf_owned_label_hulls_20260930/runs/1w/control_2/worker_lanes.csv": "80bd59f9435e34247689d8a60939e929fd19814b0818192ff8d1ceefc3f10dac", + "benchmark/results/perf_owned_label_hulls_20260930/saved_input_replay.json": "a076cce556a2ea924cc56cad62df2a524099c1d6c171a3b64d534a1af0f81f63", + "benchmark/results/perf_owned_label_hulls_20260930/scope_16w.json": "816105a904edb0bbe45c9bb4db23bef8f264f8fa506610fc6a56a2dace2b3111", + "benchmark/results/perf_owned_label_hulls_20260930/scope_1w.json": "fdcee02c23a72b6fa6a8a5346abc001fee7954b5d55f657104595196dd171f79", + "benchmark/results/perf_owned_label_hulls_20260930/validation/global_class_census_after.json.gz": "6791de7cc3cbd45d1d3e7c6b295f02479fc71ab227f663acb842dab4534c4c86", + "benchmark/results/perf_owned_label_hulls_20260930/validation/global_class_census_before.json.gz": "9fcfe58a0a746f1672fe9c26c8d4d19c7e2a682a4de0d4e9e11f5e233bf3c827", + "benchmark/results/perf_owned_label_hulls_20260930/validation/perf-final-production-owned-hull-replay-20260930.log": "612cd322cdf003adc5990b2f61edd4e2fb1000b24785ebd945903cbcdd7ef14b", + "benchmark/results/perf_owned_label_hulls_20260930/validation/perf-owned-hull-baseline-consumer-failure-20260930.log": "66ba009e61dd089a58cdcc2067f84d3a012d304673221908766d5216f59b28dc", + "benchmark/results/perf_owned_label_hulls_20260930/validation/perf-owned-hull-final-consumer-tests-20260930.log": "d416ee8ec5ed87bfc639586cef4020b948ebabd21579c549c6ff9852f8594ded", + "benchmark/results/perf_owned_label_hulls_20260930/validation/perf-owned-hull-installed-acceptance-20260930.json": "f89801fac0cb4571ef748d9938ecda1753117a3aa6f3006986b3744ca85f6b4c", + "benchmark/results/perf_owned_label_hulls_20260930/validation/perf-owned-hull-installed-acceptance-20260930.log": "4045f9e254d63b066fd79dfd76201b58257655ae6bbd48c412e6d509703966cd", + "benchmark/results/perf_owned_label_hulls_20260930/validation/perf-owned-hull-r1-consolidated-20260930.json": "24dc0d3ac06b837e9a64260a3f999ed010a765551b4bfdf69feef9df02c17abe", + "benchmark/results/perf_owned_label_hulls_20260930/validation/perf-owned-hull-r1-consolidated-20260930.log": "a6bf08f1fad7fee274dd0a192d9a5e9b34be7dbc3398a64e7d6a294a5be8d429", + "benchmark/results/perf_owned_label_hulls_20260930/validation/perf-requested-hull-nra-census-after-20260930.log": "09a6d48a9f65847afe1baefc9dcd0b9060b7b4cfe79d36b5e087105ec00e77e5", + "benchmark/results/perf_owned_label_hulls_20260930/validation/perf-requested-hull-nra-census-before-20260930.log": "4e7cf25b2071a6935c7a1b429f801411ca090ccd69edf2c2b59d41ffff070517", + "benchmark/results/perf_owned_label_hulls_20260930/validation/ratchet_benchmark_full.json.gz": "3229c499774ef6f608beab2872b0484ac8acb0ebcbc9e8622f6881ec101a330a", + "benchmark/results/perf_owned_label_hulls_20260930/validation/ratchet_benchmark_summary.json": "933b8b80ce77a470c4f913ab33a4b2e737d204b60f0bfc74bad42b1db3fef25b", + "benchmark/results/perf_owned_label_hulls_20260930/validation/ratchet_openhcs_full.json.gz": "19595554e5f1b811e5796f88da51d5f2a746182f719c311fd1e72891f6e2ced6", + "benchmark/results/perf_owned_label_hulls_20260930/validation/ratchet_openhcs_summary.json": "c97be412e4a76a9bfa37c1665bbf6af204f86d838321eccfb671293f118365eb", + "benchmark/results/perf_owned_label_hulls_20260930/validation/ratchet_scripts_full.json.gz": "c7f1065131bf0ec6be42d3a74abf6c4cb432aa50f3a904bd0651d27378b321e0", + "benchmark/results/perf_owned_label_hulls_20260930/validation/ratchet_scripts_summary.json": "22025f61d889d9b9712334cf9be16caed39378b3ff69e4c984bae58cc626f0f3", + "benchmark/results/perf_owned_label_hulls_20260930/validation_manifest.json": "96de72753b691e5636a2460f5070755d9995b30948ecba94d2ed39d666f09f69", + "benchmark/results/perf_payload_slice_projection_owner_20260930/README.md": "6dbbd8710f8ebfb21361a402672d4fcf1dc21d1ff5226f9ded1de2cc9237cbc5", + "benchmark/results/perf_payload_slice_projection_owner_20260930/recipes/apply_payload_slice_projection_owner_20260930.py": "5a46ad52c50de3534c94163ea049634502dde90de195210d01e398574cdc0bef", + "benchmark/results/perf_payload_slice_projection_owner_20260930/recipes/refine_payload_slice_projection_owner_20260930.py": "5222711472d6adfe5b59ce2c8dd761a09a5a19321acfcc58aa991a127232a6bf", + "benchmark/results/perf_payload_slice_projection_owner_20260930/recipes/replay_payload_slice_projection_owner_20260930.py": "3cf47beef6e1f9d6ff75b3d0d43cc50b9ff55082da59d01a72e5c44a4e9fcba8", + "benchmark/results/perf_payload_slice_projection_owner_20260930/recipes/reproduce_profile_thread_contamination_20260930.py": "4fbbcaa832378b2aa8aabfc9f444d169852db22f1e60014c26fd7bb96a725900", + "benchmark/results/perf_payload_slice_projection_owner_20260930/recipes/retire_unreachable_mask_axis_guard_20260930.py": "e48a42abb553e0e303987a52d737daf50aa8c156e1f0d408326f68f0fe9e44c9", + "benchmark/results/perf_payload_slice_projection_owner_20260930/recipes/run_payload_slice_projection_acceptance_20260930.py": "6d0b09cb8bd3b407d2f044e1b719670557bebb6a1972456b4b364e2516c6b5cb", + "benchmark/results/perf_payload_slice_projection_owner_20260930/recipes/run_runtime_owner_timer_20260930.py": "ad1f3d2aa488a4d22f647355bce8e908ea71cf67a8860a8da0d5ccb8c1226bf6", + "benchmark/results/perf_payload_slice_projection_owner_20260930/recipes/sitecustomize.py": "213412e0a1f845a21261de620c6d67384a266c56d0c9cb9f67f93d2e395f95b8", + "benchmark/results/perf_payload_slice_projection_owner_20260930/recipes/validate_payload_slice_projection_outputs_20260930.py": "4a645c74eadfd0504efd32a2358596c2d01c2050695542900b04fe0c955eb7aa", + "benchmark/results/perf_payload_slice_projection_owner_20260930/validation/perf-payload-slice-projection-consumer-tests-20260930.xml": "8e124e5a78f2bb126f5ff0430f6923aff85e468dbf6bf0c20c3479cf55019111", + "benchmark/results/perf_payload_slice_projection_owner_20260930/validation/perf-payload-slice-projection-diagnostic-parity-20260930.json": "17498c56d8fb5a71d5b1c829a6267d53b9b657741c60ba891c920435440aeb4e", + "benchmark/results/perf_payload_slice_projection_owner_20260930/validation/perf-payload-slice-projection-final-consumer-tests-20260930.xml": "86858a73afe49519d202710808a528970e07ff876dd7acbfa37e24250dcd5597", + "benchmark/results/perf_payload_slice_projection_owner_20260930/validation/perf-payload-slice-projection-integrated-consumer-tests-20260930.xml": "834abbba0957cd1b4f4673d8538345552d31b96f7955dcc0543df08f97e6bb6c", + "benchmark/results/perf_payload_slice_projection_owner_20260930/validation/perf-payload-slice-projection-nra-transaction-20260930.diff": "e0cd07e7373a69ac0cb90e73c09890ff6767969aa1e9907144e839d4caf0f3b1", + "benchmark/results/perf_payload_slice_projection_owner_20260930/validation/perf-payload-slice-projection-owner-refinement-nra-transaction-20260930.diff": "84bda389525389e79c8a934cf4cd0419fe5ec6a57b0096278af5f8bd939192ea", + "benchmark/results/perf_payload_slice_projection_owner_20260930/validation/perf-payload-slice-projection-ownership-20260930.json": "90496956740d56c96f61cd6eb2cfcf587ed5be232f6f62ad3f7ff24812ab1f41", + "benchmark/results/perf_payload_slice_projection_owner_20260930/validation/perf-payload-slice-projection-public-abba-observations-20260930.json": "0ddcde813dae4ec88cc52652236fa811caa5c46f8aa401e3406bc349f9187b5d", + "benchmark/results/perf_payload_slice_projection_owner_20260930/validation/perf-payload-slice-projection-public-comparison-20260930.json": "fd8d4bafdd83b1c2c073e50a49c2cf27c7f38cbbf7649498ac155eaf065df767", + "benchmark/results/perf_payload_slice_projection_owner_20260930/validation/perf-payload-slice-projection-replay-0-main-20260930.json": "268cc484fba7531c44788521d56c7277e45c6a58b35873e65696e7688c041ad1", + "benchmark/results/perf_payload_slice_projection_owner_20260930/validation/perf-payload-slice-projection-replay-1-candidate-20260930.json": "1b07d5f8ebc9c7ad92c85fae783f8518b57b5bd19d5f612797eb3cc102b6e1e7", + "benchmark/results/perf_payload_slice_projection_owner_20260930/validation/perf-payload-slice-projection-replay-2-candidate-20260930.json": "4a1ed61a76b3a3467e64d8a3948c82b785b80ac1718938526abf9baa5b1c9558", + "benchmark/results/perf_payload_slice_projection_owner_20260930/validation/perf-payload-slice-projection-replay-3-main-20260930.json": "fcd4a03e1a903240834f300a54a2d601722c75833b431e6da320657baf00803d", + "benchmark/results/perf_payload_slice_projection_owner_20260930/validation/perf-payload-slice-projection-retire-guard-nra-transaction-20260930.diff": "0619c594bafdee0300a63027c6b401bc7b75ffd35b089b61fc6874f9ce838df6", + "benchmark/results/perf_payload_slice_projection_owner_20260930/validation/perf-profile-thread-contamination-reproduction-20260930.json": "84cc5e7db3e23d38e0b1f28159f12e1b4b5c87eb7d502697e4e13c2a91daa862", + "benchmark/results/perf_payload_slice_projection_owner_20260930/validation/perf-runtime-owner-timer-summary-20260930.json": "5adbf2dc7fdcd01214168a9645f4c10740af2646e0caaae431f1f0bf0353171f", + "benchmark/results/perf_payload_slice_projection_owner_20260930/validation/r0_initial.json": "092714814183bcf602853444bbb2436ae3892978abfe9f550d0e97a50ff339fe", + "benchmark/results/perf_payload_slice_projection_owner_20260930/validation/r1_final.json": "3b09e698b62f9b18d552d481a7ee3206a51ffe54dbfc6b04e3aad70db47827be", + "benchmark/results/perf_payload_slice_projection_owner_20260930/validation/r1_initial.json": "cb501bd75160d68faa662d5882a42ad63f8810ffcb02c86470da38982763304d", + "benchmark/results/perf_payload_slice_projection_owner_20260930/validation/structural_checks.json": "950dba66c69763010f6339512813a2079e0cb2a9d7bd859e6c077874dbfa0566", + "benchmark/results/perf_plate_input_transport_20260929/README.md": "bd1e5be9b4eaed2c839772e362f3ca9c695269bca43c45222a36461081f5d965", + "benchmark/results/perf_plate_input_transport_20260929/multiwell.csv": "0be811e1843c96d083f2745feed9f4410e532ffb962557409d87af44d3dde8ef", + "benchmark/results/perf_plate_input_transport_20260929/multiwell_execution_and_transfer.png": "f4e66b34a7a3ee807f17f4688e6d0792b8efc7e625a988f18a3fdbbe429f49ff", + "benchmark/results/perf_plate_input_transport_20260929/official30_candidate.csv": "12ba219820c4cb8c2a31a7cbb02f1825c7f3e6092952e1baeb78d0aad8fdc41a", + "benchmark/results/perf_plate_input_transport_20260929/official30_control.csv": "8fc6f717372ab664822cb316fdff63189f68fd65ccbb651bea9b04b338c077c2", + "benchmark/results/perf_plate_input_transport_20260929/official30_phase_totals.png": "03714a464b8571f3c7e77a8fce920bebd91ceba65d83e7105388b61ec417ece1", + "benchmark/results/perf_plate_input_transport_20260929/plot.py": "e23738e0650d4f954d2923e223e976d8532b747a75bdbbbf9215f017e4c61135", + "benchmark/results/perf_plate_input_transport_20260929/transport_payload.csv": "36830ae656be98e2e17d9f42167e2948bcd0cc3b7ad0d16c16b23cc68128d20a", + "benchmark/results/perf_radial_geometry_20260929/README.md": "db12abb21784105bbda6078c71b4796e0296650c58af3cdd05773edb732feb04", + "benchmark/results/perf_radial_geometry_20260929/full30_output_parity.csv": "32decced1ac7d073957967e322ed283ad434487ca3f4877d91d4c11518e22b67", + "benchmark/results/perf_radial_geometry_20260929/imagingflow_1w_fresh_runs.csv": "22a018aabd087141e312430d17d18353648ec75814ec11b3e3e16405a1988d31", + "benchmark/results/perf_radial_geometry_20260929/review_base_1w_fresh_runs.csv": "26341010def31263fb47b665b7295cb9d3c6937abf77566fddd465054202b058", + "benchmark/results/perf_refill_preparation_20260930/README.md": "e5c55f80da24f7f07f3b4fcea1ab8cc79d524bf2efd44c272570105802ca3a01", + "benchmark/results/perf_refill_preparation_20260930/analysis.json": "245e4f609b7788bec91533bcd20c2cc7acd5ae1adb2edd6aa16e9d6587f8103e", + "benchmark/results/perf_refill_preparation_20260930/architecture.md": "e1e92f0b4cadc7a82f56dbcc7b9d7c3e9342d7640b5e48f9062a54f0023b7891", + "benchmark/results/perf_refill_preparation_20260930/input_digest_checks.json": "51c2835d516f08e6292595393dbeac3493c2fcdb90e1d748fc4beeb22c54f7b7", + "benchmark/results/perf_refill_preparation_20260930/measured_preparation_scaling.png": "b4b80beec8187317a91790b05fe86730ed5025615d8ece2da83c4f8fd6d7c44c", + "benchmark/results/perf_refill_preparation_20260930/measured_preparation_scaling.svg": "a6cef795e50f0024df5716fbabdcb202723097727f1d90fe5b22557ea3c8a884", + "benchmark/results/perf_refill_preparation_20260930/runs/true_cold/candidate_1/throughput.csv": "afc29e71eadd4ca99e3a34117a096c970363ee69bd77b1305bd7b5da30378758", + "benchmark/results/perf_refill_preparation_20260930/runs/true_cold/candidate_2/throughput.csv": "f6f59e870757f07711c94b75680eecfed4e9b1f9fca3e2c81bec31df0c64e726", + "benchmark/results/perf_refill_preparation_20260930/runs/true_cold/control_1/throughput.csv": "0fb43fc1fff84e2827b22eea5e6b0e93bed8063fdad1e5eb57eec1a990281c34", + "benchmark/results/perf_refill_preparation_20260930/runs/true_cold/control_2/throughput.csv": "3e453ce9789b81991756507a317ac55b352a0869eaedc8f4b94e7a9efe042203", + "benchmark/results/perf_refill_preparation_20260930/runs/warm/16w/candidate_1/steps.csv": "79b3e07d764556e2afa77c6d87d7e7e914e1530937cbac4ecf8249013fdc1144", + "benchmark/results/perf_refill_preparation_20260930/runs/warm/16w/candidate_1/throughput.csv": "f2dac38233d7aa5d3f7d18d252121252134250d5f7aad2db92005210e23f1af6", + "benchmark/results/perf_refill_preparation_20260930/runs/warm/16w/candidate_1/worker_lanes.csv": "8168e486b681f20627e09bfa4a4f126a162d65dd74eac5aa1081ad9071aecc36", + "benchmark/results/perf_refill_preparation_20260930/runs/warm/16w/control_1/steps.csv": "5d1fe480854a5323a8093b061d4b345dc8c3d371646fe291bc4aec77cc6adebe", + "benchmark/results/perf_refill_preparation_20260930/runs/warm/16w/control_1/throughput.csv": "a726ea21123439ce5fe931ae7657fa867b50f7157e7833ec6226d33aa0128669", + "benchmark/results/perf_refill_preparation_20260930/runs/warm/16w/control_1/worker_lanes.csv": "4bae87dd031c0fa7ad743e935144b68226efa8c3e2cf6441c3d77f54402cbe6f", + "benchmark/results/perf_refill_preparation_20260930/runs/warm/1w/candidate_1/steps.csv": "3bf27d6d9a0ea3ac52e7af4787983bebe4ed17766723acb6ba8b9f1fea37f469", + "benchmark/results/perf_refill_preparation_20260930/runs/warm/1w/candidate_1/throughput.csv": "11655fe69222dba206ac80d9e085814ebf642b86f6e0107fc3ab958d60e62006", + "benchmark/results/perf_refill_preparation_20260930/runs/warm/1w/candidate_1/worker_lanes.csv": "e52966c61592070de3524e006b2b63ead2d982fb819941d746bfa276b9dc6704", + "benchmark/results/perf_refill_preparation_20260930/runs/warm/1w/candidate_2/steps.csv": "c9303e2de93e7e58fc6903f3c45313abed0760953bb0cbab9aaffad9f3029b20", + "benchmark/results/perf_refill_preparation_20260930/runs/warm/1w/candidate_2/throughput.csv": "9258ecba3d1bae70ad897575516a781d7e1fd422f1363acd98ae846e5036a84f", + "benchmark/results/perf_refill_preparation_20260930/runs/warm/1w/candidate_2/worker_lanes.csv": "c750fb5c98bfbbd44d3032abe6de6b630d932efdaf63c619d5216ce6fcd6a758", + "benchmark/results/perf_refill_preparation_20260930/runs/warm/1w/control_1/steps.csv": "5f1b0b6075efa27613b102a8e55da6da2a058083ca551e380ff5fdc3638e4742", + "benchmark/results/perf_refill_preparation_20260930/runs/warm/1w/control_1/throughput.csv": "a8c5791a6c4922e3a45b4685b67a5930024d0d17487d2b99cc01c0cc2a07d7dc", + "benchmark/results/perf_refill_preparation_20260930/runs/warm/1w/control_1/worker_lanes.csv": "12fdf31f2cd447b4e6968e266f3831c52383601a09578942baec008defb19260", + "benchmark/results/perf_refill_preparation_20260930/runs/warm/1w/control_2/steps.csv": "af716c8df70bf103e14d264d7a51cba2712c14e20b35f4a22a439618cd40cef3", + "benchmark/results/perf_refill_preparation_20260930/runs/warm/1w/control_2/throughput.csv": "d059cfac08acf27a741aed64d056b7fae11157e504dc564b96554ba1c57e00ad", + "benchmark/results/perf_refill_preparation_20260930/runs/warm/1w/control_2/worker_lanes.csv": "ba9332f75958016e6c4055f9a52d667c41c424004d0add892ec1eedccb843548", + "benchmark/results/perf_refill_preparation_20260930/true_cold_observations.jsonl": "69c038b58f814c1fab2beeb462932a447c9ae5f6afcaba3e7bd5fe1e176abc99", + "benchmark/results/perf_refill_preparation_20260930/validation/class_census_after.json.gz": "b99cc7360b64a39d0894823474656e6a9ce92907b9079d7cadf2f87755e433b1", + "benchmark/results/perf_refill_preparation_20260930/validation/class_census_before.json.gz": "4982a27089ff5a26ce45ae329c31d2cdca8648b57827adc0c1dfc18d878a4dab", + "benchmark/results/perf_refill_preparation_20260930/validation/perf-refill-preparation-completion-loop-tests-20260930.log": "beee2f9bda7fe4ea7187ed0439cc52439b17fcc77f3e926a54b47f043d3f5c97", + "benchmark/results/perf_refill_preparation_20260930/validation/perf-refill-preparation-consumer-tests-20260930.log": "cf85e332a2efdfdfcdd5a6025e96fabe5b7b0acd63b302186ea1254802efaf1f", + "benchmark/results/perf_refill_preparation_20260930/validation/perf-refill-preparation-installed-provenance-20260930.json": "41848c9ab7d1e7ce684dab85c429524dac7e4eece93a0eedb7186c66ecec9cc4", + "benchmark/results/perf_refill_preparation_20260930/validation/perf-refill-preparation-nra-completion-loop-20260930.diff": "6fdf65ecdff8f341e9c8056abc7fa6e924612f4f8a1207340d8be71277a4cb24", + "benchmark/results/perf_refill_preparation_20260930/validation/perf-refill-preparation-nra-source-transaction-20260930.diff": "5739370bd682c72dbec12c4588a591ad8d62141671449ea7b41f36359443164b", + "benchmark/results/perf_refill_preparation_20260930/validation/perf-refill-preparation-original-regression-20260930.log": "2fa14273872348f2f8f071aeef7403075aaaeee820b944959b22266d0ae677ab", + "benchmark/results/perf_refill_preparation_20260930/validation/perf-refill-preparation-r1-20260930.log": "3e69ed79d64187b00a87c8f178f33429990264af8a8002835adc2df052400221", + "benchmark/results/perf_refill_preparation_20260930/validation/perf-refill-preparation-saved-frontier-proxy-20260930.json": "e390e4040085be3f81e167ef5876144a1cae6b46253aa718150e680776fe9030", + "benchmark/results/perf_refill_preparation_20260930/validation/perf-refill-preparation-synced-main-r1-20260930.log": "c5ef13bdd1fb3f780c4c9d37d10cfd259dbb6a5769cd61aaa2f2dcbb5c333d78", + "benchmark/results/perf_refill_preparation_20260930/validation/perf-refill-preparation-synced-main-tests-20260930.log": "147c91f707d5663dd44698ff9111ba9c76da784b45d6d509d39e0f43f041b974", + "benchmark/results/perf_refill_preparation_20260930/validation/ratchet_benchmark_full.json.gz": "7b2a4fdc79de6990151ac06b4d27ef940e3f1dbfa94cdaa541e55e112e57a4ee", + "benchmark/results/perf_refill_preparation_20260930/validation/ratchet_openhcs_full.json.gz": "666b57ef7c6d977606fd5cb02ab8ea0c2b042553e5bf4955f921b032bbf4cabf", + "benchmark/results/perf_refill_preparation_20260930/validation/ratchet_scripts_full.json.gz": "2540f3be53c1ff0acb06043257b93da3cad7aaffc73868f5830f34a5ba7b2c7e", + "benchmark/results/perf_refill_preparation_20260930/warm_observations_16w.jsonl": "305f4b08c7a4f68940244c3771859b53da72f2b0ad910bb26583dea1798de470", + "benchmark/results/perf_refill_preparation_20260930/warm_observations_1w.jsonl": "b276b8c4a85637e5e7e260a6a601f8335c4f78f574c4a11e4122e5581dae8730", + "benchmark/results/perf_refill_preparation_20260930/warm_scope_16w.json": "1c4ad4416e931f7b7f9a4b8b00dc84f3dbd3d566dc340800cfca9764b4d633ed", + "benchmark/results/perf_refill_preparation_20260930/warm_scope_1w.json": "5d35f3e0a919a3bb34358fb7c5c4543a9d0f9e842de7ed5dc15b038dbe51a909", + "benchmark/results/perf_registry_kernel_warming_20260929/README.md": "b0c8e085e8b163c0759230244552737ed95b778e19e201ab128a9491d395cb2a", + "benchmark/results/perf_registry_kernel_warming_20260929/measured_pipeline_receipt.json": "7327fa807c1bf41baca4830a48194615540b5e9ca7a0ec9d674e5c983434a4c0", + "benchmark/results/perf_registry_kernel_warming_20260929/nra_classes.csv": "0f69daf80b9fce4af81db0e4744cb7a3ab2228b32581031cc1ffef97cfe363fb", + "benchmark/results/perf_registry_kernel_warming_20260929/nra_scope.json": "acc0434b98b7455d8fb965b392dca28efdbd341fbf74160ba9cfd3eb66825eb6", + "benchmark/results/perf_registry_kernel_warming_20260929/ordinary_observation.csv": "cb5878c0502da25098b8999db4af9b5578d0b13bf49cb91ea9028e5ffb6ee72d", + "benchmark/results/perf_registry_kernel_warming_20260929/ownership_decision.md": "b2559947546d7acbeea199a5849504ea28ae681a5a8804c3d2fa6e5d77acc516", + "benchmark/results/perf_registry_kernel_warming_20260929/perf-registry-kernel-warming-backend-tests-20260929.log": "15568e162438c46e739b08dbee8d68a0ed08996c174a3db242ae806fb1b8e04e", + "benchmark/results/perf_registry_kernel_warming_20260929/perf-registry-kernel-warming-compiler-tests-20260929.log": "b6eeac8913019addb99b987c35ad33ea56f2fdcbb3ea7640c07db3f68fe726f5", + "benchmark/results/perf_registry_kernel_warming_20260929/perf-registry-kernel-warming-tests-20260929.log": "8cd94ea08d5da414d8b36a236ccdfd0d03a99769bb4bb8d1eb0ade4127bb1c18", + "benchmark/results/perf_registry_kernel_warming_20260929/probe_catalog_warmup.py": "2b9903c5b5508752b7c69f048435de6b6961c19f1a2f3799252e0e7fc945607d", + "benchmark/results/perf_registry_kernel_warming_20260929/probe_spawn_cache.py": "351e6b076ef49e561d88f1350ba53a90e8d2d41ce08900e9964569087d9e9389", + "benchmark/results/perf_registry_kernel_warming_20260929/production_warmup.log": "030312e1ea82edc6919f51806090b76a7947ab25915d8c5906c3830c7e6092c9", + "benchmark/results/perf_registry_kernel_warming_20260929/provenance.json": "90f6c1ee7a94b100497c7faa61a07d4398da5c492f03adf813ebade7a8689dc2", + "benchmark/results/perf_registry_kernel_warming_20260929/spawn_cache_hits.json": "6a553f581b6f54fc82c5df5e993cfbf15242ebe36dbc52b18643d4775a7bf421", + "benchmark/results/perf_reused_server_current_20260929/README.md": "92428e24c53b75fd7e92c70981b5571f713534b8d1514bb9226338763562a23d", + "benchmark/results/perf_reused_server_current_20260929/fresh.csv": "75919572a19f5255def07e7086e818c91f8e0d5f423aa6d8a2858aba8e6086c3", + "benchmark/results/perf_reused_server_current_20260929/fresh_vs_reused_phase_sums.png": "e7f48d279bb2f6448765279705fd47bbda6844e9b546e9be21a993fc5992b7b8", + "benchmark/results/perf_reused_server_current_20260929/plot.py": "1966762d70d1027d632d3a6d06f12fd0a41e98015759d0b8448a1323a450a926", + "benchmark/results/perf_reused_server_current_20260929/reused.csv": "e14be1164d8cb478ccbb84960d65b93d136ad0c061792148706d3d0e18c8a388", + "benchmark/results/perf_reused_server_current_20260929/wall_times.csv": "3da1b9ff342b7496e98226f743ee9eacfe5b0ea8e03074a2e0a8c8d6b8d01019", + "benchmark/results/perf_runtime_image_metadata_admission_20260930/README.md": "4ab32b8d71bfb457d14789d385055ecc33cf44c9b0ec3a49c3dbe322b60a18c4", + "benchmark/results/perf_runtime_image_metadata_admission_20260930/architecture.md": "7f50f88eb9f1f1e75c82dd9532453a1f954fb6d519e423b1b673a530576e7f6d", + "benchmark/results/perf_runtime_image_metadata_admission_20260930/observations/failed_main_profile-clock.json": "c56e5e8360943cd9f568b6656fdc63ed0d30182ef4962d3f6edd6922bf5abc51", + "benchmark/results/perf_runtime_image_metadata_admission_20260930/observations/failed_main_profile.csv": "3ca32d9648fe03307349a8ecf8596d4b827739c7288221d4502d4570f352089c", + "benchmark/results/perf_runtime_image_metadata_admission_20260930/observations/failed_main_traceback.log": "7d92e1d053bf055507d94b3ec4a6bbe63c19276e55caf5a1e30571aed3ffd25a", + "benchmark/results/perf_runtime_image_metadata_admission_20260930/observations/installed_acceptance-clock.json": "9dbb65c4a83878c95d03bc803db4ebb362118603d1482dff036e88498c498a80", + "benchmark/results/perf_runtime_image_metadata_admission_20260930/observations/installed_acceptance.csv": "c8c2d3f417ae0b86f3e2a9486f5e1759b32ed3cca3a65010668ca8989aab6374", + "benchmark/results/perf_runtime_image_metadata_admission_20260930/validation/imagingflow_parity.json": "d4cfe0a97690d8a330b49e6413ff28ef49b437c1265ac93e7938292846be50a6", + "benchmark/results/perf_runtime_image_metadata_admission_20260930/validation/perf-runtime-image-target-consumers-20260930.log": "43234bbdd6bd7fa279d0eba2fd2814fe8dc0edc604d757b465fe0811c09f5d56", + "benchmark/results/perf_runtime_image_metadata_admission_20260930/validation/perf-runtime-image-target-installed-provenance-20260930.json": "7eb6b03ac6b27458e4282a0413b5b69ce0f967f193ae3a00d3485176500397ff", + "benchmark/results/perf_runtime_image_metadata_admission_20260930/validation/perf-runtime-image-target-installed-scientific-parity-20260930.json": "0677ccd33cb9b6a3401f1ae2b0fe0a2e8fef4c091d451512e662455205d0c141", + "benchmark/results/perf_runtime_image_metadata_admission_20260930/validation/perf-runtime-image-target-nra-source-transaction-20260930.diff": "a3598b2a58e89a14f6c1fda90499d1b74087f3e85a14d23fbbe71e8753b0d898", + "benchmark/results/perf_runtime_image_metadata_admission_20260930/validation/perf-runtime-image-target-r1-20260930.log": "c6731798cacf77882a36bcfb0548236c5c35af1ef28a6422c21d0170886d8071", + "benchmark/results/perf_runtime_image_metadata_admission_20260930/validation/perf-runtime-image-target-tests-20260930.log": "f89dd6b69f813d4bcf2fd4342cc9e07821f71e0bc02a9c57b410506284845763", + "benchmark/results/perf_runtime_image_metadata_admission_20260930/validation/perf-runtime-image-target-unchanged-main-regression-tests-20260930.log": "ab3874e8e7407b52c999cc2d3007fee50f9709550ffb42640e8b33a0598c4f43", + "benchmark/results/perf_runtime_image_metadata_admission_20260930/validation/perf-runtime-image-target-wheel-build-20260930.log": "f67ed7fb9b06083b5a700248cacda563b9360f8359adbf81ab395c90ee1e4d1f", + "benchmark/results/perf_runtime_image_metadata_admission_20260930/validation/perf-runtime-image-target-wheel-install-20260930.log": "207bac2efdc91844b03743c8abf48913a0d08403e8400dd342422211894fb33f", + "benchmark/results/perf_runtime_image_metadata_admission_20260930/validation/structural_checks.json": "46670ae71423fce031766c3e63d3d32c5fb21bf1e7f3539e016782cda100a718", + "benchmark/results/perf_runtime_producer_path_index_20260930/README.md": "fb59803d86a785e71200c70588864d08a3238bb5d78373f0845ef5ecf7605688", + "benchmark/results/perf_runtime_producer_path_index_20260930/architecture.md": "c62665137d81719fa243f39c95e6ba26c1403aa1227c2788a51de73eb27755a2", + "benchmark/results/perf_runtime_producer_path_index_20260930/observations/perf-runtime-context-abba-1-main-20260930-clock.json": "6576cc42fe33cf8f7dd9e167e0f75416683e51525488875cf96ff6e04b259c30", + "benchmark/results/perf_runtime_producer_path_index_20260930/observations/perf-runtime-context-abba-1-main-20260930.csv": "a4008a9b335a3ac69a65d7604f4cb45213a80ae3f606be5fe80d40f5f3e6f4dc", + "benchmark/results/perf_runtime_producer_path_index_20260930/observations/perf-runtime-context-abba-2-candidate-20260930-clock.json": "d073aabb15a21ecf016796cd4e076cc8a1e0aa3dc6ed8bbf874f2296c41d40e4", + "benchmark/results/perf_runtime_producer_path_index_20260930/observations/perf-runtime-context-abba-2-candidate-20260930.csv": "9eb645ecff6def59a0778813432ebca7ee9261f147705138a22d5974f17318bf", + "benchmark/results/perf_runtime_producer_path_index_20260930/observations/perf-runtime-context-abba-3-candidate-20260930-clock.json": "cd42645c5513c118603cc0517936133c5296d4c1882a9a3556fbc8cff8ae91ae", + "benchmark/results/perf_runtime_producer_path_index_20260930/observations/perf-runtime-context-abba-3-candidate-20260930.csv": "2cc63812939984df6ccfd984340ea897779b53f6df1852c9f7e843544fe5c215", + "benchmark/results/perf_runtime_producer_path_index_20260930/observations/perf-runtime-context-abba-4-main-20260930-clock.json": "ea551daad24293d88a9a36ef39bae7015d17b4802bcd0b3dc4544f232bd6f323", + "benchmark/results/perf_runtime_producer_path_index_20260930/observations/perf-runtime-context-abba-4-main-20260930.csv": "156f133f799312b00b9a9b0b500937465d9b5588292e1724a13d22ec9b642e2c", + "benchmark/results/perf_runtime_producer_path_index_20260930/observations/perf-runtime-context-abba-observations-20260930.json": "c45a1af67365b92ec68ef620912e32c22f898811e8f4afc2cd08bc0e27907805", + "benchmark/results/perf_runtime_producer_path_index_20260930/observations/perf-runtime-context-fixed-cpu-abba-1-main-20260930-clock.json": "55ac11260fb9f421e640b07accac7ff4240af515d8ae409a14207f3628b4ef67", + "benchmark/results/perf_runtime_producer_path_index_20260930/observations/perf-runtime-context-fixed-cpu-abba-1-main-20260930.csv": "e5effa2f42bd87edde291e6b64bbe9a97edcae1b10c70277935842f424b62cb4", + "benchmark/results/perf_runtime_producer_path_index_20260930/observations/perf-runtime-context-fixed-cpu-abba-2-candidate-20260930-clock.json": "37c5485e89ecd7b7371d3d449a9221f470b3318935924a148b939093e82e6526", + "benchmark/results/perf_runtime_producer_path_index_20260930/observations/perf-runtime-context-fixed-cpu-abba-2-candidate-20260930.csv": "ef421fa28189e15bf738faa8a67ac13097f1486d7405fdd26b0752e91721a64b", + "benchmark/results/perf_runtime_producer_path_index_20260930/observations/perf-runtime-context-fixed-cpu-abba-3-candidate-20260930-clock.json": "e70cf143b3386749f8745519f216efb3f8e8715daa2663f7b555382fa671c95c", + "benchmark/results/perf_runtime_producer_path_index_20260930/observations/perf-runtime-context-fixed-cpu-abba-3-candidate-20260930.csv": "8ff36bb5b2dd019c2b9351e104764c016ca10f34c534926c26d6e6ad9dd426a5", + "benchmark/results/perf_runtime_producer_path_index_20260930/observations/perf-runtime-context-fixed-cpu-abba-4-main-20260930-clock.json": "7b34d8a6a6f4e75ad474ee32e459da449764f9b301bd70e970495bc2228dc995", + "benchmark/results/perf_runtime_producer_path_index_20260930/observations/perf-runtime-context-fixed-cpu-abba-4-main-20260930.csv": "4bc5676c7d5aba251de71c63532e042e07f4c47f44c6b2af596fc3692e890ff9", + "benchmark/results/perf_runtime_producer_path_index_20260930/observations/perf-runtime-context-fixed-cpu-abba-observations-20260930.json": "e10cc39965533356406cc710b1b0385b78afc7f689eb7bea7c429a7a5ff6a0a7", + "benchmark/results/perf_runtime_producer_path_index_20260930/pipeline_comparison.png": "4c815131a00c45bbe9ddbf9e375a38d24efdebe892df7c85c6cc7553b59b00af", + "benchmark/results/perf_runtime_producer_path_index_20260930/pipeline_comparison.svg": "e5c101551f90c8247a0c36670f9b6728c25e398d126db27200f55a8e50631529", + "benchmark/results/perf_runtime_producer_path_index_20260930/timing_summary.json": "ad8b3ab948b28132dd476c1733959508066a4603f932342ab965e693db4810c9", + "benchmark/results/perf_runtime_producer_path_index_20260930/validation/perf-runtime-context-consumer-tests-20260930.log": "bca5c2f553174924417df158b21c7208820afa0d5319c139e7fad639f6b88500", + "benchmark/results/perf_runtime_producer_path_index_20260930/validation/perf-runtime-context-independent-main-baseline-failures-20260930.log": "052defd30a2ec61feb024e01b3b0e4ba1b739effb89e10493cc750635331ea77", + "benchmark/results/perf_runtime_producer_path_index_20260930/validation/perf-runtime-context-installed-provenance-20260930.json": "819a628d56147abe1982a039f5db031aaa300158c82a1a7ae0ddcc14b9b7c8e6", + "benchmark/results/perf_runtime_producer_path_index_20260930/validation/perf-runtime-context-known-baseline-failures-20260930.log": "5b08d68dd2e717cf1cee4538703e3163253ddde538b0afe5beb27045159441e3", + "benchmark/results/perf_runtime_producer_path_index_20260930/validation/perf-runtime-context-nra-source-transaction-20260930.diff": "506f63b47d1e4e621ce8f53432382e178177e1641c0ceac7a7581bbdaa6e056e", + "benchmark/results/perf_runtime_producer_path_index_20260930/validation/perf-runtime-context-r1-20260930.log": "fb8896bd2f4d0a5131002abe782e89f9671e57380e80f072e16f08ad698674b1", + "benchmark/results/perf_runtime_producer_path_index_20260930/validation/perf-runtime-context-representative-replay-20260930.json": "342dc106beda75f7bee10982013013e7067982cc93af194f32af6aed7a0a4009", + "benchmark/results/perf_runtime_producer_path_index_20260930/validation/perf-runtime-context-scientific-parity-20260930.json": "5741c88809d28a4dfb26d0eb8b1d6aec6b7701f5ec7c81c110440281df942b5b", + "benchmark/results/perf_runtime_producer_path_index_20260930/validation/perf-runtime-context-selector-nra-source-transaction-20260930.diff": "611960e442dc4961b2ef237a36875d39024030841a38d8842583667cab3a88d5", + "benchmark/results/perf_runtime_producer_path_index_20260930/validation/perf-runtime-context-wheel-build-20260930.log": "dc5fc22c21b78a5faf1d185aa0606f69136d89fd5bea6d42624ce8129eb44340", + "benchmark/results/perf_runtime_producer_path_index_20260930/validation/perf-runtime-context-wheel-install-corrected-20260930.log": "9348905423857b4f5095fcd91fd41c7bdd3a4415546f8f35a34e5b8ba4af514b", + "benchmark/results/perf_runtime_producer_path_index_20260930/validation/structural_checks.json": "372b657d8a694b8d5f59840117efd9627c9f6d98bfd84a58332b0e1ecfbddb83", + "benchmark/results/perf_runtime_projection_platform_20260930/README.md": "8d98c60202d94db0e2bbffb9ebe3b67acf3cefa5cb4cc8fa14f3c41586b8227c", + "benchmark/results/perf_runtime_projection_platform_20260930/comparison.png": "72f8fc2e077c04c66f33a1579b503eed525684083814482a5a03d9d393208437", + "benchmark/results/perf_runtime_projection_platform_20260930/comparison.svg": "b8491c13e64983c83e398f2cc993bbccfb17292ee33874e70c8965c667eb2036", + "benchmark/results/perf_runtime_projection_platform_20260930/recipes/perf-runtime-projection-fixture-repair-nra-transaction-20260930.diff": "536e6a7c7b047317b082dde827666273f686b25ac41c691fd2c045117d30deb9", + "benchmark/results/perf_runtime_projection_platform_20260930/recipes/perf-runtime-projection-owner-refinement-nra-transaction-20260930.diff": "dbf24baf1bef10376c8c7707a1ffa2ac9ead2a40b7aacd8776c2e565d8daebc9", + "benchmark/results/perf_runtime_projection_platform_20260930/recipes/perf-runtime-projection-ownership-nra-transaction-20260930.diff": "8d57892458162042b4bc682a80831e4403f139e07d4ba65361c5eed2458fe8f0", + "benchmark/results/perf_runtime_projection_platform_20260930/recipes/replay_runtime_output_projection_production_20260930.py": "6fc66b2dbfdfd6124fa22b8d11d9d833f9074555ff7fe2bc59751e42879cf4f2", + "benchmark/results/perf_runtime_projection_platform_20260930/recipes/run_runtime_projection_platform_abba_20260930.py": "570733b0130e6c7bbce1893b8d63c710c65f2292e7c1e0b5d0c00474f92f393e", + "benchmark/results/perf_runtime_projection_platform_20260930/recipes/run_runtime_projection_platform_profile_20260930.py": "0c6df2834cb423bc1c97dba4032bff9664b981a463720af4d343b1d68eea0cfb", + "benchmark/results/perf_runtime_projection_platform_20260930/recipes/sitecustomize.py": "62f575353e857f55682b7efff4797da1117d3bc8be6999ae81cd9c360961facf", + "benchmark/results/perf_runtime_projection_platform_20260930/recipes/validate_runtime_projection_platform_20260930.py": "48528ce69f0fa40ea3cf05a5b28b2a9e08e708d8308c1e8c78af0e768a8d3f9c", + "benchmark/results/perf_runtime_projection_platform_20260930/validation/perf-runtime-output-projection-production-audit-overlap-limits-20260930.json": "7edd9bf09049da12b887dff16b631a743f926e850edb1b8541d61d6c999e6345", + "benchmark/results/perf_runtime_projection_platform_20260930/validation/perf-runtime-output-projection-production-candidate-20260930-audit-overlap.json": "180c639d49f81a63cc128ca5750c81fecb0a403f7ffaaae0f96b6b9e42a9d026", + "benchmark/results/perf_runtime_projection_platform_20260930/validation/perf-runtime-output-projection-production-candidate-20260930.json": "441a07fc3432a9e29a7210a2e8b14b13f9f4d159f0427daa1c634526b476c862", + "benchmark/results/perf_runtime_projection_platform_20260930/validation/perf-runtime-output-projection-production-main-20260930-audit-overlap.json": "0908272e990b373f5a10fd0bd6d08a0ab3f0434ef15a9e55f2c1a1ae059728e5", + "benchmark/results/perf_runtime_projection_platform_20260930/validation/perf-runtime-output-projection-production-main-20260930.json": "29bba554c3400392083f6b28b9795155b036934145c5192e4d5dff6ad18dbf8e", + "benchmark/results/perf_runtime_projection_platform_20260930/validation/perf-runtime-output-projection-prototype-20260930.json": "64777817f1e78d42aa65ca8602b83d720656f88fd8e2583b66fb6cb51ff9b621", + "benchmark/results/perf_runtime_projection_platform_20260930/validation/perf-runtime-projection-current-main-consumer-tests-20260930.log": "c081bb7ff28fa58012474f3370c69f28fa6283fe17335d78ce1fc022a1ed9112", + "benchmark/results/perf_runtime_projection_platform_20260930/validation/perf-runtime-projection-current-main-r1-20260930.log": "b2d2e9dddfb01989907e42c9ede6e44de083324656551fdc4c0dccbd78e883bb", + "benchmark/results/perf_runtime_projection_platform_20260930/validation/perf-runtime-projection-global-cache-declaration-inventory-20260930.json": "198da819fc4ed938f64b6f9996c2c0ff34abbf1c7b30533c5b29d5ff77d7f87d", + "benchmark/results/perf_runtime_projection_platform_20260930/validation/perf-runtime-projection-ownership-consumer-tests-20260930.log": "55ebbc9bb02996c7d203f42345867fde715e103942c3368fc5b729e8c7ade0ff", + "benchmark/results/perf_runtime_projection_platform_20260930/validation/perf-runtime-projection-ownership-decision-20260930.json": "97e45e54cc19254599f7ed5cf4f3a4ac31e19a9597bb9f082bf4830472d371fc", + "benchmark/results/perf_runtime_projection_platform_20260930/validation/perf-runtime-projection-ownership-fixture-repair-tests-20260930.log": "e5402f834a2951686d74ca6279cb56b90782026bcc598d97da26e6b553bc7b5a", + "benchmark/results/perf_runtime_projection_platform_20260930/validation/perf-runtime-projection-ownership-main-fixture-counterexample-20260930.log": "901de316db2fb5975583aa967cef5848719949653478127688fbf19fe0796ce6", + "benchmark/results/perf_runtime_projection_platform_20260930/validation/perf-runtime-projection-platform-abba-1-main-20260930-clock.json": "4550b1c4ca091fc8720a6ef8ef1cee1f9a69e515288fe45d621b7ecf8879e324", + "benchmark/results/perf_runtime_projection_platform_20260930/validation/perf-runtime-projection-platform-abba-2-candidate-20260930-clock.json": "6e18b53ad6b495df3e995b2e1b35f99d46817c1809d3093a6b5d62864bad53dc", + "benchmark/results/perf_runtime_projection_platform_20260930/validation/perf-runtime-projection-platform-abba-3-candidate-20260930-clock.json": "3ec7649fb89915d2a6a883eae989403c1b0575a522e8d6c576426b97531c7fb0", + "benchmark/results/perf_runtime_projection_platform_20260930/validation/perf-runtime-projection-platform-abba-4-main-20260930-clock.json": "9000d11f572610e7c7bd728055479142676a6a179580a94484fd905afce3f2ab", + "benchmark/results/perf_runtime_projection_platform_20260930/validation/perf-runtime-projection-platform-abba-observations-20260930.json": "cef93ac8b59182b5c4769ecc50f88d1125712f132f383c4cd5262513563b1111", + "benchmark/results/perf_runtime_projection_platform_20260930/validation/perf-runtime-projection-platform-comparison-20260930.json": "38a349648c6a363eeacb22efece8373bf03f5b08fe2072b966daae4156ccb376", + "benchmark/results/perf_runtime_projection_platform_20260930/validation/perf-runtime-projection-platform-current-provenance-20260930.json": "e04050a1cb9ab7086120e63af4bb31571844fc2748a31f35c2dbf2211e859a26", + "benchmark/results/perf_runtime_projection_platform_20260930/validation/perf-runtime-projection-platform-phase-comparison-20260930.json": "2358f8296c1f6eb19fb7907fd6288206137b35a440d93781532c9136f7e72aa8", + "benchmark/results/perf_runtime_projection_platform_20260930/validation/perf-runtime-projection-platform-profile-parity-20260930.json": "f23561230710904b03c5a03be677f00dcd46e2eba337e27e3930c4a0dd72468a", + "benchmark/results/perf_runtime_projection_platform_20260930/validation/structural_checks.json": "f89aac49b61d5b8dd50ba4cb2029a4cc066e7a1fbb257ce22649bf5205dadaa1", + "benchmark/results/perf_saveimages_artifact_binding_20260930/README.md": "9ff06c77092d7ea9fd3cd8b9a7322bab6347abba5facece2a0ee75b4dd5dde6c", + "benchmark/results/perf_saveimages_artifact_binding_20260930/analysis.json": "666b030e26de9308507dffedf802a3f2c5503dfafba8e32229b0381e88951699", + "benchmark/results/perf_saveimages_artifact_binding_20260930/architecture.md": "8b923e761b15f79ebc8eecc760e3cbb1594fcf45d0d7068fe684c60cb9f76c14", + "benchmark/results/perf_saveimages_artifact_binding_20260930/observations/ExampleImagingFlowCytometryObjectsInGrid_receipt.json": "dab23bdea8f4ab29e586b4b6ed58d3de453a0c797979424cea28ae529ebd737f", + "benchmark/results/perf_saveimages_artifact_binding_20260930/observations/cp_tutorial_3d_monolayer_receipt.json": "96de5ff58478c3da0b69a95282c634a858470519ff8fee19dfca7567b5cd2103", + "benchmark/results/perf_saveimages_artifact_binding_20260930/observations/installed_frontier.csv": "cc22553adaea736c58e3727aedb1e6250d766916605dc686ba127c39f9978a5b", + "benchmark/results/perf_saveimages_artifact_binding_20260930/observations/installed_frontier_ExampleImagingFlowCytometryObjectsInGrid_steps.csv": "1061b5076abe2623b965c113efdd0332a12516bc4ed779f6ad29c404c9e03b18", + "benchmark/results/perf_saveimages_artifact_binding_20260930/observations/installed_frontier_cp_tutorial_3d_monolayer_steps.csv": "a6704a1dfeb9bfee71b0431fe944932c32c229267b235f2f18209cbbbc706e6a", + "benchmark/results/perf_saveimages_artifact_binding_20260930/observations/main_3d_failure.csv": "fff90aaef255e2122203f535eab2734c8bd37968c086d436b6cfe52ef5c30dd0", + "benchmark/results/perf_saveimages_artifact_binding_20260930/observations/main_3d_failure_cp_tutorial_3d_monolayer_steps.csv": "02cf0d0ba4c92ee65a5b58c7aec0643e4d1123c1482ab27bb852cb1ce182d8c0", + "benchmark/results/perf_saveimages_artifact_binding_20260930/observations/source_prototype.csv": "3e7b4361add2c7ed4ea03d82dba8063e5014b05b3edb33c9fb9d185ed593e7b0", + "benchmark/results/perf_saveimages_artifact_binding_20260930/observations/source_prototype_cp_tutorial_3d_monolayer_steps.csv": "34e2bd8f54c563b23eb5c75a171f26b80ab8c4281057db94801bea567aa2e2ba", + "benchmark/results/perf_saveimages_artifact_binding_20260930/refreshed_single_well_execution.png": "5157714f2cb3ac35531b09357565bedfdbeacb16f6d08c7bab8dcb767f347a03", + "benchmark/results/perf_saveimages_artifact_binding_20260930/refreshed_single_well_execution.svg": "26b5b96f3f2bb9f2107508d710d983a256b06ebdc32765540a31c13f28e00b94", + "benchmark/results/perf_saveimages_artifact_binding_20260930/validation/perf-saveimages-artifact-binding-nra-migration-closure-20260930.diff": "ae8d44f35766a3fde00a1d2de5cabee0ae9076081e389f1f4b083c3337a7d270", + "benchmark/results/perf_saveimages_artifact_binding_20260930/validation/perf-saveimages-artifact-binding-nra-source-transaction-20260930.diff": "414fd983ce456da9eb9a1a478fe32b00024463abc3fa3b3685c7ea3edb38fed3", + "benchmark/results/perf_saveimages_artifact_binding_20260930/validation/perf-saveimages-baseline-fixture-failures-20260930.log": "08a5b57fb10891aaae099ec15812197e429751fe4c890fb1cf415881247a0421", + "benchmark/results/perf_saveimages_artifact_binding_20260930/validation/perf-saveimages-binding-final-consumer-r2-tests-20260930.log": "ad7963af8e4bb55b122cabb5f9af58d9ef09755d8d0977b04691c2b01e5b5701", + "benchmark/results/perf_saveimages_artifact_binding_20260930/validation/perf-saveimages-binding-final-r1-20260930.log": "a0172400e380dc58bd7a9ea6a1a3a9b8d433a292f8ab16ce968268e279efa94b", + "benchmark/results/perf_saveimages_artifact_binding_20260930/validation/perf-saveimages-binding-installed-provenance-20260930.json": "2da33a2f9eca1d68e370cea855c07539c46616be86cdae27560f7d532705e96a", + "benchmark/results/perf_saveimages_artifact_binding_20260930/validation/perf-saveimages-binding-policy-nra-source-transaction-20260930.diff": "2c3219976c127f92007ff4c9aa6f307991e762409138897cdb93b5233b302d7e", + "benchmark/results/perf_saveimages_artifact_binding_20260930/validation/perf-saveimages-binding-wheel-build-20260930.log": "8afb31890af4b5d4925c62786010b2ed90fc83168e202cdae0cd67e3f4b8a973", + "benchmark/results/perf_saveimages_artifact_binding_20260930/validation/perf-saveimages-binding-wheel-install-20260930.log": "3f6771a8343db1c2b7794d15a631926af945952e0ca757ea16c34cb15b2d086a", + "benchmark/results/perf_saveimages_artifact_binding_20260930/validation/perf-saveimages-input-value-nra-source-transaction-20260930.diff": "2f133544c1a47be96a8d7761b142b93a870a87726dceb07b4a1b7c5fe37e5ca0", + "benchmark/results/perf_saveimages_artifact_binding_20260930/validation/perf-saveimages-installed-scientific-parity-20260930.json": "0b2f7575d1f21a43de81a96cce6b3c72a900f73761fdf9e44248966ea148caac", + "benchmark/results/perf_saveimages_artifact_binding_20260930/validation/perf-saveimages-known-failing-supplemental-final-tests-20260930.log": "1b59d7fb22075a84bd5e7e2c7d7a221037c3bf20261a31e4207dc43f2558dbda", + "benchmark/results/perf_saveimages_artifact_binding_20260930/validation/perf-saveimages-runtime-values-baseline-fixture-failures-20260930.log": "6a06c0b66959f29a1fec4b2e8450c3814b1a19d44628e4f4d9be113746a8c7d9", + "benchmark/results/perf_saveimages_artifact_binding_20260930/validation/structural_checks.json": "356441b5b96105110f902ebb7d617fb4031da899e71c836d33a8b1d4b7f6964f", + "benchmark/results/perf_scaling_rise_investigation_20260929/README.md": "1bf288d522c32c756008cba5582f8cef92a388294befb70868d95c7ca10a2e10", + "benchmark/results/perf_scaling_rise_investigation_20260929/analysis.json": "a4d1fd5a7f891135f3abd5e8aff507bbf230905b3cced55dde56c7c72c162342", + "benchmark/results/perf_scaling_rise_investigation_20260929/analyze.py": "f01332b37a27dae1257432ac3fdddc8259b35a6d3fd76111c49ead14d34734c1", + "benchmark/results/perf_scaling_rise_investigation_20260929/audit_overlap_lanes.csv": "477c56ef60a83b3bf4b5775342fbd1eb000cc71e374f27ca64a2e7ceba9cae05", + "benchmark/results/perf_scaling_rise_investigation_20260929/audit_overlap_observation.json": "28bc8a37103c5d461cfa0ed4edd56c5c1709da2e25b0eab499c8ac545521f744", + "benchmark/results/perf_scaling_rise_investigation_20260929/audit_overlap_pressure.jsonl": "42ee04a92068b5fd9059294ccb2f4972bed9c468400d281ad389987a1be5a763", + "benchmark/results/perf_scaling_rise_investigation_20260929/audit_overlap_receipt.json": "113b5bcd1e39935efe3f47dda6eb3c8683d55f1c8c7d0b17f3bb17e5939aca5b", + "benchmark/results/perf_scaling_rise_investigation_20260929/audit_overlap_resources.jsonl": "68570f53f3d97cfd7428f9cd3482b214b9e39bbccca892655360b651529a4f6e", + "benchmark/results/perf_scaling_rise_investigation_20260929/audit_overlap_steps.csv": "7248bf88f04f109cf862c28c4cdf29b92b6894ed51401c8bf06d078669f0632b", + "benchmark/results/perf_scaling_rise_investigation_20260929/audit_processes.jsonl": "491a34cb38232b27af00ffd0c75e3194b44feb1f14b95edafeaecb6c28edea94", + "benchmark/results/perf_scaling_rise_investigation_20260929/check_export_parity.py": "4620186c3a049fb677b9f6c0799fdc3a151f539e9a56885de3668372cb8b4de5", + "benchmark/results/perf_scaling_rise_investigation_20260929/clean_comparison.json": "29cad99db5d0d7f4aacac119c4a6b078cb835f1cd64ca9de6d0bb3caf4aa9e5a", + "benchmark/results/perf_scaling_rise_investigation_20260929/control_1_lanes.csv": "e8c810f898ab57af09e1bd890025e9c2c55178dc91b7618a1bf1e298224b2696", + "benchmark/results/perf_scaling_rise_investigation_20260929/control_1_observation.json": "61c422f74198a6970b6c1038a5e912f814b3b3b6b8d4f0bf7f89471bbb5d8f90", + "benchmark/results/perf_scaling_rise_investigation_20260929/control_1_receipt.json": "0324e4586c3a0d0b990d3b208fec27f7b970d3364e68d6963de78e1c9f96be5c", + "benchmark/results/perf_scaling_rise_investigation_20260929/control_1_resources.jsonl": "8f9556f4c18ac305bc804d9b6c2597b5a85792f1dc3d7766e3ad19eac6f76205", + "benchmark/results/perf_scaling_rise_investigation_20260929/control_1_steps.csv": "32a013d5e18c4ddf47bae5b1f972ad6824d6d4a829938f999bd61d38216fe8e7", + "benchmark/results/perf_scaling_rise_investigation_20260929/control_2_lanes.csv": "3a9a6911b3ad605d2bd6c312cd1e3b15df3e1637e7aef0fd136907cb1dc56045", + "benchmark/results/perf_scaling_rise_investigation_20260929/control_2_observation.json": "ba389668fb78ef25fae78527976e7a02fd4428db769e741fdf37124758c9cbf9", + "benchmark/results/perf_scaling_rise_investigation_20260929/control_2_receipt.json": "862d753d3d98012252cdb231a62cf13fc4a90210522497823c63e9241d36d599", + "benchmark/results/perf_scaling_rise_investigation_20260929/control_2_resources.jsonl": "a48ec2c55507f89120c41033e94e553692fd8bed9f38833fd3c07486f7b89e77", + "benchmark/results/perf_scaling_rise_investigation_20260929/control_2_steps.csv": "a5c6a4439a78e2df6555407a0b118a8c589233ee1be7c7d502bdbcf61caf45ab", + "benchmark/results/perf_scaling_rise_investigation_20260929/export_parity.json": "2604ecab15341d4959d9bd8f2f262c55ec8809251cc572af96a4621d93b90dff", + "benchmark/results/perf_scaling_rise_investigation_20260929/fused_1_lanes.csv": "20da5aa68bf5f6c7352efa5c2b047ac0954333febc7355250dff8416f50cc52f", + "benchmark/results/perf_scaling_rise_investigation_20260929/fused_1_observation.json": "841c92ebee8b468ff2a1a15aa04f46b31c7c50b0c1c6c4654f1b8a3b1e06c4b6", + "benchmark/results/perf_scaling_rise_investigation_20260929/fused_1_receipt.json": "f19e82e711b6baf06c405ef8ff82eb4a9f5b68c99481e2449807d9785e2ab9b6", + "benchmark/results/perf_scaling_rise_investigation_20260929/fused_1_resources.jsonl": "10366f04634d250df292eea320e469ff343823fcd5a0b09a6bb3f87efb8613f3", + "benchmark/results/perf_scaling_rise_investigation_20260929/fused_1_steps.csv": "cda853cc8f06bcc27f603a69161d89252dca4c9ccb209da4ed39b5ccef9e0d9c", + "benchmark/results/perf_scaling_rise_investigation_20260929/fused_2_lanes.csv": "afa016f89bdc5c5de31dd7bad24f6da87c7863d9ccc3953265e1705c49d31d96", + "benchmark/results/perf_scaling_rise_investigation_20260929/fused_2_observation.json": "62a412a1d60684805229850a9d6bd72ceea2b149ff6b43c55bee0dfc846d3e92", + "benchmark/results/perf_scaling_rise_investigation_20260929/fused_2_receipt.json": "cb8e180c5bbfb77b97b591b1584179f3e6aada3b78d7319d93f7b27219a83398", + "benchmark/results/perf_scaling_rise_investigation_20260929/fused_2_resources.jsonl": "aaec729d62128f354d07706f3bfb4670a1dd0a45e4a77889c6ff8cf1b035092f", + "benchmark/results/perf_scaling_rise_investigation_20260929/fused_2_steps.csv": "32bff7c63bdb18e41b5ca01f1abc978caf69d85c500442523539365e1d920bfc", + "benchmark/results/perf_scaling_rise_investigation_20260929/historical_control_lanes.csv": "9c0cea11096b1fa6df8f92bca8721bfc3778c33c452cbc20e312fe080c4fa37e", + "benchmark/results/perf_scaling_rise_investigation_20260929/historical_control_observation.json": "5b30461c7976dca68f937251c1402c753270540fb095ae8e5439d1bbb8ec46be", + "benchmark/results/perf_scaling_rise_investigation_20260929/historical_control_steps.csv": "24029c49adb574e68f8753a38138e93f64d9cb3c928a6813479053e564f43eea", + "benchmark/results/perf_scaling_rise_investigation_20260929/historical_fused_lanes.csv": "0c77c84e969f26c842d77093adbdac5cdda74b81a7381fe0e2cb28d3c28f305b", + "benchmark/results/perf_scaling_rise_investigation_20260929/historical_fused_observation.json": "14a76ef34d2f0e7d5d1711875358c255cc3c750d6be756ac9e9862ca46af2a2a", + "benchmark/results/perf_scaling_rise_investigation_20260929/historical_fused_steps.csv": "66f44fcfad3a5f2ac38c07086c144bc49c554d53449537f302bc50d703efc700", + "benchmark/results/perf_scaling_rise_investigation_20260929/measured_native_scaling.png": "5451ef08907f83ea0580baf23b56154b24c4aeb313561ff120d37623ad58f67f", + "benchmark/results/perf_scaling_rise_investigation_20260929/measured_native_scaling.svg": "897b542be439bd4af2b46888d93d517df41d27a7cffba7bcf2e648207214f526", + "benchmark/results/perf_scaling_rise_investigation_20260929/measured_ratios.json": "2afe22e357217037e8e8eeb03e3d7926f41bf8723070a793df0c89d6ea1e152d", + "benchmark/results/perf_scaling_rise_investigation_20260929/observations.jsonl": "3eb0c48208eeaf7ce9915f8d9aade45f041979018443cca7b9bc0b18c9cadb55", + "benchmark/results/perf_scaling_rise_investigation_20260929/original_audit_completion.json": "05f51d788a3f6a8483c388e625f3ce87fe395a320799381d9ec426cc4e4f7e9e", + "benchmark/results/perf_scaling_rise_investigation_20260929/plot.py": "b374f19611462b2d32c7c3b2f0a31a1a1771254f7e982d01c56d1365e3d0bc00", + "benchmark/results/perf_scaling_rise_investigation_20260929/reproduce_audit_overlap.py": "6d903e96b1617e96527ed52c456c2b7e8fae29d23203711692536323e6ae05e1", + "benchmark/results/perf_scaling_rise_investigation_20260929/reproduced_audit_after.log": "13874b229972cd645f8d848ecc44ba6ae39d7714bff6dc1b58c5f9b9a11a10a3", + "benchmark/results/perf_scaling_rise_investigation_20260929/reproduced_audit_after.py": "7692c8ae0ac9c82e32f5984ad080cfe609436451e3115979b192d67d30596c22", + "benchmark/results/perf_scaling_rise_investigation_20260929/reproduced_audit_before_expanded.log": "b3d881d0ed506f021b19dce00b3b9b89226747847c897ee15d706755d9c1f6b6", + "benchmark/results/perf_scaling_rise_investigation_20260929/reproduced_audit_before_expanded.py": "2d3f39587d0c7a050d54e0bf5ea2652e9da074f0ef4307fdc8e9c02d83ec9695", + "benchmark/results/perf_scaling_rise_investigation_20260929/resource_summary.json": "e4fc06980257cf315ab5f9a8cd158c7ac9747e7ad67411f269faa6e1f920ed30", + "benchmark/results/perf_scaling_rise_investigation_20260929/run_clean_pairs.py": "05e873c327c5c8fb03d875e0967db0a2e3b16051a4d8f1ce6ba9925a50d98ba7", + "benchmark/results/perf_scaling_rise_investigation_20260929/scope.json": "9a2279a99cbd1ac41c8b7ab49a7bff50af0ed2b04febeb0a2dbc8826b71d66f2", + "benchmark/results/perf_schema_source_readiness_20261003/README.rst": "9c21aa47a6824050dbae03d15050a8bf9385d33079f6182096d1d63ebab6382c", + "benchmark/results/perf_schema_source_readiness_20261003/receipt.json": "9baa4230ef299fd3514ab91fc107c5ab1fc241910f5a30cadd40b56c7fd15c79", + "benchmark/results/perf_server_startup_preparation_20260930/README.md": "327c6ae38a8b22943b6b85e2cd9da6c25a8822747ff5282ad0449c2efa0aef7a", + "benchmark/results/perf_server_startup_preparation_20260930/analysis.json": "2acf3132377fced68aa981ec1b70b759a6bbebece273c1c2f56e548399d37c0e", + "benchmark/results/perf_server_startup_preparation_20260930/architecture.md": "25e910fdcaef52a6763c5c587c08493b0db65a9baee079e344710bb4d9687cc9", + "benchmark/results/perf_server_startup_preparation_20260930/observations/cold_server_diagnostic.csv": "3227764653e8041c25148980f5bfc3aed587b716f31b7821776c19122c321f2f", + "benchmark/results/perf_server_startup_preparation_20260930/observations/cold_server_diagnostic_clock.json": "38d84791c399cb705b588a7f93cca3c769eb41ba056c744931bdf02981a148a8", + "benchmark/results/perf_server_startup_preparation_20260930/observations/imagingflow_pipeline_receipt.json": "3ab7c4071e94167a4522a5dfd38b5a7b429f65a2243cd8e72f33bfa5104afe4e", + "benchmark/results/perf_server_startup_preparation_20260930/observations/initial_startup_inactivity_failure.csv": "4b4093e6438e2641c44aefade6cbadd496b605ede4c7024c7e6c94e077e97d56", + "benchmark/results/perf_server_startup_preparation_20260930/observations/main_3d_failure.csv": "fff90aaef255e2122203f535eab2734c8bd37968c086d436b6cfe52ef5c30dd0", + "benchmark/results/perf_server_startup_preparation_20260930/observations/main_3d_failure_clock.json": "fc3a9b94bc0141e4bc346666a5a7fef15f9f05d0732d9ea0f33810f848ddfe80", + "benchmark/results/perf_server_startup_preparation_20260930/observations/ready_pipeline_installed.csv": "4117a32599a08705eecc2dc8e12bff755a7a6854765233c476b1f6437b14a952", + "benchmark/results/perf_server_startup_preparation_20260930/observations/ready_pipeline_installed_clock.json": "b0fcccad7ea0bcf268c789be81ded4e51302cae11f22677f14a24457b9dc55e6", + "benchmark/results/perf_server_startup_preparation_20260930/validation/perf-server-startup-benchmark-boundary-tests-20260930.log": "e62fc5cb412b4aee73d7faa9e997c91974752113442fa892bccac14c5039d602", + "benchmark/results/perf_server_startup_preparation_20260930/validation/perf-server-startup-final-r1-20260930.log": "6d4b85b3fe7af5d48ba1d634b7210e5a43f8a830c450307fc5e9934083bbee43", + "benchmark/results/perf_server_startup_preparation_20260930/validation/perf-server-startup-final-wheel-build-20260930.log": "4990d961752c288dd2eefeb590f06548c40c6bd62bf08e50179966106a2faffb", + "benchmark/results/perf_server_startup_preparation_20260930/validation/perf-server-startup-final-wheel-install-20260930.log": "d84a606fb441a22e113f3548f763c47268795a44f3fe696fbd8a21e55184d6cc", + "benchmark/results/perf_server_startup_preparation_20260930/validation/perf-server-startup-installed-provenance-20260930.json": "60d1776a3fcb534bd0bb640e620c33584c5544af459533541c9b38c272d91838", + "benchmark/results/perf_server_startup_preparation_20260930/validation/perf-server-startup-latest-main-consumer-tests-20260930.log": "383ec7187143430f958308198f1e46ca74fe6e0a79f4c6485b853a448b4094c6", + "benchmark/results/perf_server_startup_preparation_20260930/validation/perf-server-startup-nra-source-transaction-20260930.diff": "f9962b866fc9c7f8e44a6fe6ca2aa4e3854a387e1cc0028fc1c27077f6b3b5e1", + "benchmark/results/perf_server_startup_preparation_20260930/validation/perf-server-startup-progress-nra-source-transaction-20260930.diff": "457503e409cac051aae12f7eb59b407ed955786d0c6ee317b5bdb41c80952b73", + "benchmark/results/perf_server_startup_preparation_20260930/validation/structural_checks.json": "88dac376aa48035531253941ad5b018416c222d87c2357b14e76ac613c8f59eb", + "benchmark/results/perf_single_axis_session_20260929/README.md": "02bdcf8c806adce5d33a76d2a2aa42be7d909b4039760f89d2f7934af8451fdc", + "benchmark/results/perf_single_axis_session_20260929/candidate.csv": "ff56ad8a251369fc73a17e2fff9da7b5a48bca44190a99cc6a324298ec191580", + "benchmark/results/perf_single_axis_session_20260929/control.csv": "b7589b2a7dd3cc85b8b4732216f2cdde53d27269beb0b14364099418d26e596e", + "benchmark/results/perf_single_axis_session_20260929/fresh_server_total_breakdown.png": "5c73efe68bd3524528accdeffdc0a8fffb31bee8256a200db9668d615b01b353", + "benchmark/results/perf_single_axis_session_20260929/multiwell_candidate.csv": "6a377170e3b4678d1dfebc2da0cd2ddd3a701ae65d48dd45e2f70d4bb60f3937", + "benchmark/results/perf_single_axis_session_20260929/multiwell_control.csv": "d9807519e2235be4b5eb7d22a7f47cc86a1f64e790a1951553fdbb374bac5dbc", + "benchmark/results/perf_single_axis_session_20260929/multiwell_control_initial.csv": "4a8320b8eb6e896ac21d0e39dbb03723ebba8041037e1358a7bfd46940022b0c", + "benchmark/results/perf_single_axis_session_20260929/per_case_phase_deltas.png": "a1759dba131493c381f8540314e79cf2ce6147dcb6c94ba3bab2c536ee3b3e29", + "benchmark/results/perf_single_axis_session_20260929/plot.py": "4fa0997a6ce1b859e0afa69b109936d2f68f7d3485b33047ba60bd3c1706c0c9", + "benchmark/results/perf_source_header_reuse_20260930/README.md": "d573cda3f18feacf2606bb4effcb2f22b016b779d9fba7b68d262cf18495093a", + "benchmark/results/perf_source_header_reuse_20260930/comparison.png": "d0b3b41dbc91ba0d90a86b5775f7b7a8f4882178161f0cd81374991d64e1b819", + "benchmark/results/perf_source_header_reuse_20260930/comparison.svg": "bfa2d081246d88c3197043c5c6e371e47822fbe2bcf71d3b33859f34d0a3c32c", + "benchmark/results/perf_source_header_reuse_20260930/observations/current-main-primary-abba-1-main-cli-clock.json": "0b953ae6c5761824617dda39094e69b5d4d23c499177dc8c0040ab41be344dc8", + "benchmark/results/perf_source_header_reuse_20260930/observations/current-main-primary-abba-1-main.csv": "fd63b3bc178bd28c178c3148d0f4160e6649c7654bb0c8a6b3c0c42059b9992a", + "benchmark/results/perf_source_header_reuse_20260930/observations/current-main-primary-abba-2-candidate-cli-clock.json": "4b50df94f0533637a2fb202333a4aa3bcd71206ec2cc19120af8cac27337e2bd", + "benchmark/results/perf_source_header_reuse_20260930/observations/current-main-primary-abba-2-candidate.csv": "58e6e7f741eddb464c156c62e5fd52e669bae3fba90876e09cef0e71ca87abab", + "benchmark/results/perf_source_header_reuse_20260930/observations/current-main-primary-abba-3-candidate-cli-clock.json": "bb08b80b51aae0c7bc95b3aad183df936aea2b5c7da34cae34629372a136c4b8", + "benchmark/results/perf_source_header_reuse_20260930/observations/current-main-primary-abba-3-candidate.csv": "b987377e78c8d1e77068b68ac4b5b77748ab44601a746a8b2ab3c0d890e21d1e", + "benchmark/results/perf_source_header_reuse_20260930/observations/current-main-primary-abba-4-main-cli-clock.json": "c120a272df3a190d89a27fba53016df6c48ad27100d97aad185a999edbb3e3b2", + "benchmark/results/perf_source_header_reuse_20260930/observations/current-main-primary-abba-4-main.csv": "bbe73574f3f153612cc5ffb922be4ce384744a5a3537169c6a93480ddbd0b5ec", + "benchmark/results/perf_source_header_reuse_20260930/observations/fixed-cpu-abba-1-main-cli-clock.json": "c12e2ab163df069033e5615ce95102a2afb7a2d97856234418a282d636bde30b", + "benchmark/results/perf_source_header_reuse_20260930/observations/fixed-cpu-abba-1-main.csv": "63922bfca62a8da3f6a1609909fd909bb3e034ba3fff63d32a80e2eb04e29724", + "benchmark/results/perf_source_header_reuse_20260930/observations/fixed-cpu-abba-2-candidate-cli-clock.json": "5d3bde2043f6d4882229234371d28313d3c38bcf639efd52390d58db1b2f2bd7", + "benchmark/results/perf_source_header_reuse_20260930/observations/fixed-cpu-abba-2-candidate.csv": "77c2194e590099238394aba9644bc9bc5fe942724214f4b4b613210ec31acc98", + "benchmark/results/perf_source_header_reuse_20260930/observations/fixed-cpu-abba-3-candidate-cli-clock.json": "8257bbc798b2e65311c205c6f60277cb36420fbc76bd56ff5ad4cf393f7158f8", + "benchmark/results/perf_source_header_reuse_20260930/observations/fixed-cpu-abba-3-candidate.csv": "31eaa3c2a385d03bc1e628701c4ec7ca307050191b32e3efc051a8343bc2306e", + "benchmark/results/perf_source_header_reuse_20260930/observations/fixed-cpu-abba-4-main-cli-clock.json": "afb99489c8071e9c9171f3043c445539a7e3e72d2c0a7e7472335f42d9af38d7", + "benchmark/results/perf_source_header_reuse_20260930/observations/fixed-cpu-abba-4-main.csv": "2613a0de75f5dfc7fc315dc4f36770e1e0b85a03feda425ed9de82f1618d97b3", + "benchmark/results/perf_source_header_reuse_20260930/observations/perf-source-header-current-main-primary-abba-observations-20260930.json": "0c2bc28205a5e1ca1e8f4ca9ba78f486856b98643b6c4a8b4ea390bb1a1969ca", + "benchmark/results/perf_source_header_reuse_20260930/observations/perf-source-header-fixed-cpu-abba-observations-20260930.json": "9e1d2795b715ee86bb02310150f1d9ecae854704ce4efd91ccb0528d4cbde4d2", + "benchmark/results/perf_source_header_reuse_20260930/observations/perf-source-header-primary-only-abba-observations-20260930.json": "1a07ca770f4b89ad30fc3ec3d7db9d05967d83441b20ce1b49c4e3831032e5dc", + "benchmark/results/perf_source_header_reuse_20260930/observations/primary-only-abba-1-main-cli-clock.json": "4a5ca518ecc32a7e611f3a3325b8d9a86ee9c7b60372864ff8c45520adc51e93", + "benchmark/results/perf_source_header_reuse_20260930/observations/primary-only-abba-1-main.csv": "d6f602114ad0ed3a0bd99e82c1a83e60e634beb2a31fed8c58b637bd90a51aee", + "benchmark/results/perf_source_header_reuse_20260930/observations/primary-only-abba-2-candidate-cli-clock.json": "1e789a7a798e58428496939054fcfd0aec5b75f5ba91010d395bc5ade812acac", + "benchmark/results/perf_source_header_reuse_20260930/observations/primary-only-abba-2-candidate.csv": "3a928779b10f3ab68258da537bd3664bdec8071d1131a1c999f0a79c5b094ebb", + "benchmark/results/perf_source_header_reuse_20260930/observations/primary-only-abba-3-candidate-cli-clock.json": "5fd5e0c9d3c6e584996b53aac9e96f6a7266f16918a8151c5f51f1c447de2f58", + "benchmark/results/perf_source_header_reuse_20260930/observations/primary-only-abba-3-candidate.csv": "9b422231278c42c5f11a3c049b9a0cfc534449976b7843251d9182b9612a1ca7", + "benchmark/results/perf_source_header_reuse_20260930/observations/primary-only-abba-4-main-cli-clock.json": "12500377ab449aff7ff5f8354ee4117d92db768d5a8505f73c1769351ee55e17", + "benchmark/results/perf_source_header_reuse_20260930/observations/primary-only-abba-4-main.csv": "ae0d4ce65a9d02a5fbbd866ad5af4ab417cb9938a79057461b5c81eab88ca4e8", + "benchmark/results/perf_source_header_reuse_20260930/recipes/analyze_source_header_phases_20260930.py": "a56040710dde0fe391263a4b5d231e4374e8222a8807f896c2a225c884bb711b", + "benchmark/results/perf_source_header_reuse_20260930/recipes/replay_production_source_headers_20260930.py": "ca0d6c7d3afe7989ed1c7c3b2b3206fc916b5456ab9c727dc73f6d75b282ea81", + "benchmark/results/perf_source_header_reuse_20260930/recipes/run_source_header_current_main_abba_20260930.py": "21f221d367f41ed16dba7377795e58cc9ae91ff8e6b4789ee7de7b99dce171f5", + "benchmark/results/perf_source_header_reuse_20260930/recipes/run_source_header_preparation_timing_20260930.py": "4bc27ee0c8559dd830d1a58c8476eecf90ee69c0ef1b0a89e92a6d0934698f4f", + "benchmark/results/perf_source_header_reuse_20260930/recipes/validate_source_header_current_main_20260930.py": "5fcc2c2d7e96717fbb0068ffee2c82fdcd21d96b3a4a80cf04511c39fdb9d481", + "benchmark/results/perf_source_header_reuse_20260930/validation/perf-source-header-comparison-20260930.json": "ff41380dad71d23b242a69cfea22eb4515517ba61ce3066af8b3c3af62ad0534", + "benchmark/results/perf_source_header_reuse_20260930/validation/perf-source-header-current-main-comparison-20260930.json": "beea5157067f67b05594d3479dc97967b35ef532e28dcbb5d166dbd546477a20", + "benchmark/results/perf_source_header_reuse_20260930/validation/perf-source-header-current-main-provenance-20260930.json": "9d8bbba5cb8adb80d7474ef1007ccdac890c56f8438601195774b120499ad842", + "benchmark/results/perf_source_header_reuse_20260930/validation/perf-source-header-latest-main-consumer-tests-20260930.log": "cd716188cc66c2cffbdcf62f21534893a8aa4e071587a1760dc59a31df7646cb", + "benchmark/results/perf_source_header_reuse_20260930/validation/perf-source-header-latest-main-r1-20260930.log": "523f8f5bcb9c890938a709831b3f4f9b1452afd2e1e68c4591868f749ce48056", + "benchmark/results/perf_source_header_reuse_20260930/validation/perf-source-header-nra-transaction-20260930.diff": "edfc5f6b197c1de8805ee286322d8032709793cf4097075c47fd8e8332e36f06", + "benchmark/results/perf_source_header_reuse_20260930/validation/perf-source-header-ownership-decision-20260930.json": "3b897eb635cd6bfea106bc847fdbb742a486c89476977350c84b708c3958af37", + "benchmark/results/perf_source_header_reuse_20260930/validation/perf-source-header-phase-comparison-20260930.json": "e0bb44f1cbe9e73103f4db48b0603401f6c5e94c59d104c3cb46fcbb93b56217", + "benchmark/results/perf_source_header_reuse_20260930/validation/perf-source-header-production-replay-candidate-20260930.json": "2ae3fe9f025f5b302e23524ae9c6897e86554bc1978213f690be8a683ee666be", + "benchmark/results/perf_source_header_reuse_20260930/validation/perf-source-header-production-replay-main-20260930.json": "6dab79713afad5e2919b93f35bb38e87308565b843826579a0a259b8676c14a4", + "benchmark/results/perf_source_header_reuse_20260930/validation/perf-source-header-scientific-parity-20260930.json": "a790f1b9f3998f58667b481f9489484cad3ef794ed7c55f381bc6e5c1ca550fb", + "benchmark/results/perf_source_header_reuse_20260930/validation/structural_checks.json": "123a0fb9b9901b6b6fef2d33b1ccf85c11d3b7b4f81dedc08edd0e7edec88f07", + "benchmark/results/perf_source_identity_resolution_20260930/README.md": "6097286b97d21659d43868a7b9089c2e6112ca263c579797fb6a7dc11872a154", + "benchmark/results/perf_source_identity_resolution_20260930/comparison.png": "10e99e9a42d251a2b37b9539d1a11595bc8407fa3bf1cd84448eb25754e42857", + "benchmark/results/perf_source_identity_resolution_20260930/comparison.svg": "9b0ffba4cc2a22eb278d4a36720c3cb1c845fe03d5ec7bc2766e60b3216141e5", + "benchmark/results/perf_source_identity_resolution_20260930/observations/perf-source-identity-comparison-20260930.json": "f8ca190b2c0326700be187c14e466e8997ca9581aeb179e0c35b208fd8086cf8", + "benchmark/results/perf_source_identity_resolution_20260930/observations/perf-source-identity-fixed-cpu-abba-observations-20260930.json": "8a4b8af2e3a0f6ce4fa51d80e58d45b83a801f8eb449a40980407131b6efb5e2", + "benchmark/results/perf_source_identity_resolution_20260930/observations/run-1-main-clock.json": "9c6cc151dca167a9f38930c7fbea2acf35dcef076dd7db7b72556bfc808b30cc", + "benchmark/results/perf_source_identity_resolution_20260930/observations/run-1-main.csv": "180039c73ebd424228568bbba2f5eff049ddcec153605079d31ead81a3016b77", + "benchmark/results/perf_source_identity_resolution_20260930/observations/run-2-candidate-clock.json": "8f25c40ce27f40d382d567547791b053e2a043733fbc9cce365edf46222934df", + "benchmark/results/perf_source_identity_resolution_20260930/observations/run-2-candidate.csv": "b0987e7ee5177ce42e42a88f093acb998ecf30cdc57962c8a65740a427db1eed", + "benchmark/results/perf_source_identity_resolution_20260930/observations/run-3-candidate-clock.json": "3f8c0083f1b98d09e7d8ee62f7fd99e912279fdc54e79bd0ecd42f8ee7311a32", + "benchmark/results/perf_source_identity_resolution_20260930/observations/run-3-candidate.csv": "3e23fa00ce05a00652b53992b25bde86783a1abc05a343a2e0848b4584679c27", + "benchmark/results/perf_source_identity_resolution_20260930/observations/run-4-main-clock.json": "f4b86256ca4fa029bd40b44d653b993c3ce2c6739411b291c4dd11841f239b32", + "benchmark/results/perf_source_identity_resolution_20260930/observations/run-4-main.csv": "2f08ef2f5cd3c9338468ede91afae1088017f609c5ab6efa5b98d421fa73de06", + "benchmark/results/perf_source_identity_resolution_20260930/observations/source-preparation-candidate.jsonl": "794f0411506d014f664a05ebef3b77b21260bc628189989d8771661c4c61d5c9", + "benchmark/results/perf_source_identity_resolution_20260930/observations/source-preparation-main.jsonl": "8b7cd0aa0f8e472f41104fce5f24dee53e85f07fddeff7d9729201804031799a", + "benchmark/results/perf_source_identity_resolution_20260930/validation/perf-source-identity-index-ownership-decision-20260930.json": "38cc2bcd99573a6e0f963ca47f1b6420b9d7b1390dd9f605e4c30873c938b96a", + "benchmark/results/perf_source_identity_resolution_20260930/validation/perf-source-identity-scientific-parity-20260930.json": "b97ba3cbf3f33ddd50c773724d1903f969de92896fe5ae9eb8d10a8626de72a1", + "benchmark/results/perf_source_identity_resolution_20260930/validation/perf-source-member-production-replay-candidate-20260930.json": "c11b3e9e847604145c82dd7ff9cc0f6ea94447dee4712c197bf30f5aea1a556b", + "benchmark/results/perf_source_identity_resolution_20260930/validation/perf-source-member-production-replay-main-20260930.json": "ec042f87dc615e5a39cbcb54b10e1595194c07b1d6a773a3d0dcfa727e61f810", + "benchmark/results/perf_source_identity_resolution_20260930/validation/structural_checks.json": "9ac2fe388d786c9d50e9ab0b44525a3c993fcdf419a1232dcf8d53942ac23337", + "benchmark/results/perf_wide_intensity_distribution_20260929/README.md": "b63a1f555235f93772537dfafca20cf01a9e86ac7009a6f396a37d3b346e6f2b", + "benchmark/results/perf_wide_intensity_distribution_20260929/measured_scaling.png": "b980f672c3f66478b1cd25cd996d2d592c52d5ed936cfaca5db810e6eaa674c7", + "benchmark/results/perf_wide_intensity_distribution_20260929/measured_scaling.svg": "e13b8f55d96b8436ffdb338df7b93d03fcb378ac0cc2a2928751ea457c152630", + "benchmark/results/perf_wide_intensity_distribution_20260929/observations.csv": "9f94923f61028d6b9816ebae75226516171b8e2f2254653edf5d47cc5bbfb675", + "benchmark/results/perf_wide_intensity_distribution_20260929/output_parity.csv": "74435f24bfbe5b0d41b48d2e57cf690b05b20bececb901e737fb1446eb1821b7", + "benchmark/results/perf_wide_intensity_distribution_20260929/plot.py": "a51838fc0ad2804d8974bb41a3e152dd526026703a6465bd176be1fdcdb3c57b", + "benchmark/results/perf_wide_intensity_distribution_20260929/provenance.json": "8bd7f8d239a95c75089e1b441ea5ed92bfd5d60ba74fe845e5a26bca9b975abc", + "benchmark/results/perf_wide_intensity_distribution_20260929/replay_saved_batch.py": "e1edd3ca70d48d2c489e4a038d2150ed6e57c4f2836a29bc334c350744603bdc", + "benchmark/results/perf_wide_intensity_distribution_20260929/saved_batch_probe.json": "d759679a546b5d88ecb784494e5fae0f39e6fc91663cd9cd564439d074b9f64f", + "benchmark/results/perf_wide_intensity_distribution_20260929/step_timings.csv": "165dbac3bee4b7cd76862a082dbeec5a3d4b2b1c1ab59d62eed88845746af2b2", + "benchmark/results/perf_worker_profiling_20260929/README.md": "ff7bd0e2b525d94e9d140c3a7e5badbc60d2dae30198b350b6b00f9113a712a4", + "benchmark/results/perf_worker_profiling_20260929/authored_nra_transaction.py": "ea4a4cd873585a4463968179e5d3927b4fa4c946d59f66db7bdb8167447a565f", + "benchmark/results/perf_worker_profiling_20260929/class_roles_after.json": "c29cbf078dfb11698cab777fe0b491ec2daeb163ff9e9a17628984ee12aa1e91", + "benchmark/results/perf_worker_profiling_20260929/class_roles_before.json": "29bf5cb828343e28579f4982e1b4339e32fcaab9d531d1e8e0bb8a775b617d4b", + "benchmark/results/perf_worker_profiling_20260929/main_sync_tests.log": "b54ba3ec209c2a1a4938cfe31e3778e025657bd349e858ed6ef51935ce963c8b", + "benchmark/results/perf_worker_profiling_20260929/ownership.md": "ab37026e795ade8f356e650c3ecea83f4246673963eb93798766a750b595d9bf", + "benchmark/results/perf_worker_profiling_20260929/perf-worker-profile-baseline-regression-20260929.log": "a16a0e89391babd64abd1878a5fcb49df055e7388652a231e14323d73069392b", + "benchmark/results/perf_worker_profiling_20260929/perf-worker-profile-corrected-top-20260929.log": "57b36807c0f5a0c6923f3acc46620180635772b308e5568ef9791982103bd5ea", + "benchmark/results/perf_worker_profiling_20260929/perf-worker-profile-integration-tests-20260929.log": "ecfea1a16e246ff55aaf411843b17c866c59d8a5ec4c6b7b6e05ebabf08c72e7", + "benchmark/results/perf_worker_profiling_20260929/perf-worker-profile-nra-projected-20260929.diff": "edf4fe82ec7edbc66cab4b33018a1111c60fdee54d3bf88f955047d5ac0188bf", + "benchmark/results/perf_worker_profiling_20260929/perf-worker-profile-production-check-20260929.json": "4438eacd5a28a14ee48343911c8925fd8661cb9b698196667d9984f18c29ce3e", + "benchmark/runner.py": "089f0c3a31496dcf46519aa2c1daea435066a77e82a4e0897f040a39641c9031", + "benchmark/runtime_env.py": "c5661239230be69ebd86559a661940efb8156901aaa1616b7cdcfefa1537439d", + "benchmark/throughput_scaling.py": "0df1d940e84b6ffa246ae795ecaa3d66f5f1cb3fda6523ec7282db8ea9369af2", + "benchmark/timing.py": "b908f648d8e0ef0091da96a33a65fad9203962f17e9a2e6e75695c12d0404ada", + "benchmark/validation/README.md": "e188b7e57b42aca79f2dd1267e18af8986f73d8ce80456febf17b4665d449f36", + "benchmark/validation/__init__.py": "d88b40e492c5aed0f461522dad63bbd4ce1cc1c1f65498adfadf1c64576c316d", + "benchmark/validation/__main__.py": "d093e023493bc368c7ff37d8323028fb40dc17f0c4f09633ed7645e84f5058e0", + "benchmark/validation/corpus.py": "c122842a39b9dc2af7db688519bddb3470339904c347e6e5a039d77cf723c0ae", + "benchmark/validation/layouts.py": "be14d9802251778d5bbf07167ce571651115ce55d7b55a4d2c0ee8ae8a4d563d", + "benchmark/validation/references.py": "d3257c514ae6d4f64f46d513d63dabacfe04cc36bed05373b7a3055438928c90", + "benchmark/validation/scoring.py": "6e9c7a4be22be553f02642ea0375604a890047cf40cea5429b7720804aa75e93", + "benchmark/well_throughput_scaling.py": "bcb58517c9c699be96d87027725a1fe299082874002cf0dc1032c6b267283e35", + "diagnostics/.gitignore": "b26aaf3fa669581280dc2d73f5c65aa4e7f5cdf675415309f7835a2537721095", + "diagnostics/ACQUISITION_SHA256SUMS": "01d1ee74593192823a32051d8ea9aaa76589c97787fc31ad522dc5265ea8b42e", + "diagnostics/NOMINAL_REVIEW_SHA256SUMS": "920243a783c70c5142e83a7bdd4ff4bebcba85159b62b573aefb9d1d66a772d1", + "diagnostics/README.rst": "939b5cfa8c32eb2db38cee2606ffa755be3eaf96fbe3640674f038ced125f5fc", + "diagnostics/SHA256SUMS": "bcfce1e1789f68ed4774f62db87e077d7a409344e6e9a741aba20b81388c5865", + "diagnostics/run_source_tests.py": "2dd04e5005b9cde8b1b9b86f0d17e3b9c45120795e9be0ed9b556787b33ffdf2", + "diagnostics/test_344_engineering_document.py": "9599cb9152d642e834b4056d820856c3dba9593647ea7554c36f0589c72b3798", + "diagnostics/test_344_source_binding_ingress.py": "f398b5db2435208a1317f0e97bf347e7e837e4b64f91ac0887e2e571d6da913c", + "docs/__init__.py": "f2ea2f1e16a5c2f29a8d6f869618ac9b5e70e72368d5ff60fffcf348dbccdaf4", + "docs/announcements/image_sc_openhcs_beta.md": "00488fcd6312b59f9408c69f32173d8b8af057f3080e90587536e428e5e7835e", + "docs/archive/README.md": "930de929bf83de77ec77a2bd992661f56517a8d26ed55027b703a69250d68d67", + "docs/archive/architecture/abstract_manager_widget.rst": "b779175704d10f906a4c1dfd9cb700639deb0e41492cf4ea69c5f8f48c24901d", + "docs/archive/architecture/abstract_table_browser.rst": "74a6dd42c6abe836aa7e58a4c80814a3adba9f8b2396d0aea9f0592342ebb346", + "docs/archive/architecture/cellprofiler_boundary_audit.md": "99e1518dc0aef8f97934af4c320e98a4e6fc39537c019e02bdc3f1395fd6fe38", + "docs/archive/architecture/cellprofiler_openhcs_runtime_unification_plan.md": "7cead27eeffa05cb1e27e35bea920963c843478e5ac707b494430113aac7300e", + "docs/archive/architecture/cellprofiler_runtime_execution_import_dispatch_consolidation_plan.md": "09b50a5f3afc7c743baa1d8ac97c051ad2a6644ece2b776d1fa7d9181a42e53a", + "docs/archive/architecture/cellprofiler_runtime_unification_uncertainty_audit.md": "0b2470532ef7684eb028ff19d13d8da165ace999fb68c634c829cafc60b80e4c", + "docs/archive/architecture/compilation_service.rst": "21e975265889add3ec4c896db0049a8d93f1e7b6c703dc0e3fd8c2c79a59e2c9", + "docs/archive/architecture/compilation_system_detailed.rst": "e5e74c8eededb2c1963acfb6deb84500f7014791f2beb7870083cec52b69e2c7", + "docs/archive/architecture/component_configuration_framework.rst": "f90bd3d76218d7a5a7055653b8abb1c2299cbd7ada32f803fef31e6788a0b726", + "docs/archive/architecture/component_processor_metaprogramming.rst": "fa52a3d58e15c141ba0e9546e3502fbc6340ad07dc31fd81de4f2a237d69d807", + "docs/archive/architecture/configuration_framework.rst": "1b37707e0d88d7f4542c74ddb729123b6a1ae3d128ad9891fb55c3f9af6be310", + "docs/archive/architecture/context_system.rst": "086c59e3331851427d02a0ed1df22eb27ad5ba8bcde4aadd05e72acc25bc0cc9", + "docs/archive/architecture/cross_window_update_optimization.rst": "8169bb105e1090877aa35f5612c6148f2d25d966f0db2f32aede4a455f4f296f", + "docs/archive/architecture/custom_function_registration_system.rst": "7f982f824c9ab6b72a20eb3a887852a01bc1c1cfa89c2b74599fe17b933212a2", + "docs/archive/architecture/declarative_window_system.rst": "d9e9b6cdca53c057fd907d41d80f6280a74016841ca978245ba60fabf1eaccb8", + "docs/archive/architecture/dict_pattern_case_study.rst": "17d3910ab6872065a5617df801473fadea5a1d1fdc842c7ccb9de350f5797420", + "docs/archive/architecture/dynamic_dataclass_factory.rst": "d22d1d24d18e2ac897a12974811ce4bf199cd8c4280350a0082aac04b6aea4eb", + "docs/archive/architecture/ezstitcher_to_openhcs_evolution.rst": "e73fdd71a23282180898eeacc99dc1ff205731981aa16af4b41dfe433e2dbf28", + "docs/archive/architecture/field_change_dispatcher.rst": "16f4ce723be215965b342f7f1a3d1b9895a5042b3b20be41e4d7621f30d1a819", + "docs/archive/architecture/fiji_streaming_system.rst": "4b5640cd5ab59d5978d62ab595e8cae1eaf8b1fdb7ad4d0e9eb5d53e90a394c2", + "docs/archive/architecture/flash_animation_system.rst": "a9021663f826034d0945caafba5acdde5d22a1727609689a94784b30dc578ee3", + "docs/archive/architecture/function_pattern_system.rst": "1511efd73879b31054dafcbdf029193bf597e586ee1b0ea4666e766b7beb2e7d", + "docs/archive/architecture/function_reference_pattern.rst": "f627165e8463192fdfea3f592028edade4123abbd70feb78e769ef1bf76286ea", + "docs/archive/architecture/function_registry_system.rst": "76b426d5ede8d808b22436b32f2f3ae8d1e24e1215bb83c721ee42dc8b49dbf3", + "docs/archive/architecture/gui_performance_patterns.rst": "e56dc6076c5f72d78fb53e402357dbb56c82ea0333dd93e5261b7b7b4300082d", + "docs/archive/architecture/list_item_preview_system.rst": "5f2b4b8a4c7e839ac25dffe2b3aaee50ef5357921d65dce7be9940b1fbeff6b2", + "docs/archive/architecture/memory_type_system.rst": "0d6c338f15792e55392ddefec582539ac2bd7a59292bcd2bbffe6b45fcd38027", + "docs/archive/architecture/napari_integration_architecture.rst": "3d37439e1abf621f4b49411ea6780b41f8ab09672f9bfa8479f348f31ad8927c", + "docs/archive/architecture/napari_streaming_system.rst": "0cabea8dea2d1377557fc3ebec24f259bec8fce57328dccd32507ab914a233c8", + "docs/archive/architecture/omero_backend_system.rst": "e55fc574916a152455105fdf7cecf8888fd76ff417febfe15a51bea994bbd421", + "docs/archive/architecture/parameter_form_lifecycle.rst": "93f59f392b13d333efbc2fc8653c140b6013158a8d1f50c7ae981780d2547339", + "docs/archive/architecture/parameter_form_service_architecture.rst": "1ac8b9651df9d4fbb611511027debb5ed22049f5af0978c71571cb82cae80e12", + "docs/archive/architecture/parametric_widget_creation.rst": "77699972cc6495a84d70214ae92060050426dda0dd7bee53b6ebbe041d0eeaa8", + "docs/archive/architecture/parser_metaprogramming_system.rst": "fd454b4111c68c20aaca5021a5e24d096e652c3d2a1f87f3fa6ccc0c6d20956c", + "docs/archive/architecture/pattern_detection_system.rst": "8428c68070fb999996ed22b25e30872f7f5384efc58537a1172356cbc8ef1e47", + "docs/archive/architecture/plugin_registry_advanced.rst": "95dd6f9be02fd9dbf139bc1da99a2fab22960b9a223ece052abe846d5d1cb040", + "docs/archive/architecture/plugin_registry_system.rst": "0c08d4ba2bb2eb0f070fcacc8240b75396d499ce8ab7519b146076950488d215", + "docs/archive/architecture/quick_start.rst": "bfd16fc9170f9e10a4927cbef9a3c9a43f9b17a10b87f8b441f4c8044554869d", + "docs/archive/architecture/roi_system.rst": "9a1c3f0a082bdece753b6713f409f1d15cd38090ec1267bba4436a6490d0aeec", + "docs/archive/architecture/scope_visual_feedback_system.rst": "3aa092abe420fbe990c880f1f0c17f32390b928ebc2eae1a62de75cc61d2afae", + "docs/archive/architecture/scope_window_factory_system.rst": "101ee2b845448cf7cd55a9fcc93c9e88a7353a0ad292ebbd28fa765eb94a3397", + "docs/archive/architecture/service-layer-architecture.rst": "4a9401ccd609bb0855f8ff63dac60513b8ff5a752f4e658f097e7bce392cd810", + "docs/archive/architecture/service_registry_integration.rst": "dcfe7f19815dc2468fa228bf38e1cccfb06aa0f43ce5ee52fc07b626e37341d4", + "docs/archive/architecture/step-editor-generalization.rst": "01590287d526f179be82e8fc4b14741f63057636016c93c2e3d7a8a46ccc4496", + "docs/archive/architecture/storage_and_memory_system.rst": "47724cfd7fe6408f4981a55677507dd7b7d15ed57b4fe242be27d3f12c28d00b", + "docs/archive/architecture/system_integration.rst": "5803ffb3614d61df3b0dfa9498932bacd1a06fdcab43597b16579323512e8fcd", + "docs/archive/architecture/tui_system.rst": "3ede276228c97bf216cae3f5e9d0e73a53ff9c38a8a6a6cd2cfbaf71b5a4c27d", + "docs/archive/architecture/ui_services_architecture.rst": "29f0b6327889053dad3dd603e52b736be886ee84cfe2cd85e0db6b96163eea52", + "docs/archive/architecture/widget_protocol_system.rst": "662e0caddb44b7cc85851aba9e456021bb7264e7811881a881b95aa7a3adf808", + "docs/archive/architecture/zmq_execution_service_extracted.rst": "74b82a586a657e38c8ec52c494616830dde54a74b9b815181367e0dbb4b6d395", + "docs/archive/development/architectural_refactoring_patterns.rst": "48c16c9ddcdac58eb14dbf8c290ec987d96d3cbe1a1eb5341b07dbcd6cb0ba4c", + "docs/archive/development/ast_refactoring_workflow.rst": "3a1a384e96e03ea0f93b60404cade294c2637b238c822f2e992adba81c724e92", + "docs/archive/development/cellprofiler_semantic_refactor_audit_20260507.md": "b91e8efcdf4ed148294095d960d8314b97444878d5a0ac76d4de5932ed829dfb", + "docs/archive/development/compact_window_patterns.rst": "b649f8ae20629ace06ae6dd7f11c3a4c11e97b9ab21e79a3cc05440591556ed2", + "docs/archive/development/compositional_commit_message_generation.rst": "44c6fe8f7fc325b16979fdd57e7e9817f4301136e0b76208b89798f550675b35", + "docs/archive/development/dry_run_methodology.md": "e716752082ccad04069bce1fb0caa68070f688d2d73ae4f1d4be38cfd12aaa0c", + "docs/archive/development/gui_test_recording.rst": "c32d42f86fbc4c8c92605ea153c4d4c7b5618f6592369ea1c67db177fc765559", + "docs/archive/development/lazy_dataclass_utils.rst": "b29b2f4bb9bb144bd96015496aaedb2920da36ecce832489b65231562bb9ae59", + "docs/archive/development/literal_includes_audit_methodology.rst": "5d9ff1fd3bf453f31142ab53f47982ca3dcdf41eefc5ba5bb39df0dce3fcfd23", + "docs/archive/development/parameter_analysis_audit.rst": "a1b1561e4a62940f72454261bc8c8dde598b049fcb52da8d2fd6d707eaab541f", + "docs/archive/development/placeholder_inheritance_debugging.rst": "3b1deb2b5edd91f2d0ad7ea12428774bd082dfe2fcf84905cc1e6e4bf90a8ea7", + "docs/archive/development/placeholder_refresh_threading.rst": "75097d76ad7c31dd6a9c8d69fbfeb5a656bd1d89b0d3969973eed846029cb23b", + "docs/archive/development/refactoring_principles.rst": "6b04521e7a6cd55b82d64930b3544e4d26782198005cced7a6e2a74717c8150f", + "docs/archive/development/scope_hierarchy_live_context.rst": "544658f0b897bdf99c8f833a8dd691eb720c6a83a87bef79395ce4513e02ed67", + "docs/archive/development/source_inspection_methodology.md": "365ad1d3903219363fbb83d03ec08927fbd3c2c41d989a16ae78e18765d7b4fd", + "docs/archive/development/systematic_refactoring_framework.rst": "0c117c5b780e5499e257d3e08682c0da01d411242fbfa23aa79fa9add70100e0", + "docs/archive/development/ui-patterns.rst": "c19cd470c6fe3f82ed61f467686f670863fe8749109426efc6ab51dc143ab301", + "docs/archive/development/unified_parameter_analyzer_migration.rst": "c08e68fe28309e9533815ace3410330b2a87d0ac73de791f2424848e77d7eaaa", + "docs/archive/development/window_manager_usage.rst": "7c1dab597e236e663f0395da526fe8e712962642f2e1dec5e38efcc4b1da0e45", + "docs/archive/user/research_impact.rst": "3c2303a420fd1e34418e1e23011917928f2e7e8183fd58d744377c3ca2adeaba", + "docs/archive/user_guide/production_examples.rst": "528884f6bf9c1dfc91ff906d11d3c6d3f5d92f412b0919a0431501eb74bb9fbe", + "docs/audits/README.md": "aeb08ec4e4a0e8cc7dd6e0be9d0de9c1dc159793f5643e91aa6c543cac145c4b", + "docs/audits/architecture_a_m.json": "7b8348bff72685427a8bcdde00dd6968cc2cf68125b6d954a653a26646033479", + "docs/audits/architecture_n_z_development.json": "f7bedd2b90bbd95721968e3dedf4d05090bea42df7c68972883683e82c4fecd5", + "docs/audits/authoring_preview_review_20260910.md": "0d48687e89bc855c33ec2fdd3029c8dd969ad2363b05fd6cba9135285ea79e01", + "docs/audits/automatic_materialization_policy_review_20260923.md": "3d5e28add58d44c0d70c35034c407503d2c4ed62eb460a10a10b6d2a07984cc4", + "docs/audits/benchmark_cli_interrupt_review_20260923.md": "96de3efd5b19689627eaa843900991785656ce9d669c91b11739a5c2990e283e", + "docs/audits/benchmark_outcome_scope_review_20260922.md": "225f364c2141c50f5c9f0cf5e6edc43372745816039d3f3f27e38c3f31a44867", + "docs/audits/benchmark_report_and_run_claim_review_20260923.md": "a4f810c130630e7509a2f75acc2d9a4704acb8bdab3aa69931f207caa899c78d", + "docs/audits/benchmark_wrapper_review_20260922.md": "3406437d32bf5cc0187fc6ec308cf6e717022e0fc1369b27467d0b060b255d82", + "docs/audits/gallery_connection_owner_review_20260924.md": "9e34feff8c8c84b78243e682d397b9263b34663b252a2c022e89a8586420b017", + "docs/audits/headless_observation_export_review_20260922.md": "7ce818c3c095b623bda793f00e184e1f90542c68a2355cfcf1f3c70a4ff69de7", + "docs/audits/hosted_ci_repair_20260914.md": "fea7faf803353f42d38f95ee786fbf923e1ef202b276a2151e7bcceef57d2e3e", + "docs/audits/measured_run_inspection_review_20260922.md": "d8bc2a5379196646fef482450af98e959c0b4d756cede8c4ddafd2769c87d072", + "docs/audits/native_volume_comparison_boundary_361_20261002.md": "86c9e06122d5ac8aa1df38b04eca2c76a470ec1965153a1c56b48a27591aea39", + "docs/audits/official30_reference_output_audit.md": "77258d0a4db14d3f4c37d8d8f88e3d5972d52d6693780e4fb177473ee471770e", + "docs/audits/official30_value_completion_20260914.md": "b97c66dfc108770a3172af706f676f500b006dcc2ca2f6573f75fc2d9ca3782c", + "docs/audits/pr126_authority_delta_review_20260922.md": "b8405f5c4462966939d680632301ea0aa3587b42b549a12bad0dd142a540787c", + "docs/audits/pr129_tiff_compression_review_20260924.md": "821a06dec8355362946f0ed91cfc81e42287b1153935d205218ef4e140098961", + "docs/audits/project_surface.json": "5267d115faa41528aaa31ce5cdfd40b4c6abfbeaebf62b79fc6ffcc77333ab86", + "docs/audits/runtime_axis_ownership_review_20260923.md": "7cb53ae20886d412a426113c2fff7a648b7ece95f409d2feb4c5115ad697429c", + "docs/audits/source_object_domain_boundary_428_20261002.md": "5f1dd0abfdaf629e8029ee50a9bc55e8409f619b4ef0625c61461f5cf7356564", + "docs/audits/user_docs.json": "719d0f96842efde3d66042b4962afc98ac566b5159087ff249a9640afacde98b", + "docs/audits/well_throughput_cli_review_20260923.md": "aa659e13bdc3e09c0e16d656d43ff57f89e98e14e58d848c4703bd3589268a27", + "docs/audits/windows_source_path_review_20260923.md": "e3e97bc877cdb0122e98368756bb77e4a15896f9a15483e6cc241e071c57804c", + "docs/cellprofiler_backend_optimization_tracker.md": "2c76b17dd668f4d1993fb6e9edf1adfa7dc3b57d0f4f27671323d7a7bff847be", + "docs/cellprofiler_cppipe_parity_tracker.md": "abd1345c76a0fcb966dac1dc4e249bb9dd219739fe95dd27ae70bba4af52376b", + "docs/cellprofiler_dataset_acquisition.md": "4ff4f204bdbe0a60272b0f4df32e1fbc8eb524f85a930c50aa8771b51ae3647e", + "docs/code_complexity_analysis.md": "c47bb7cc241d25ce5543707da851d97d33ac46c5781d24a05674e3f33bcbe6a5", + "docs/development/CANONICAL-CUSTOM-SOURCE-379-20261001.rst": "908af78872abb85ad1ed2c8928ff0b185f00f54d4c5fad7c5cad1ab3d3a52772", + "docs/development/colocalization_metric_selection_487.md": "c58aa4cb4f902efb50ae5d695511df37ec9bc19d8b17dc9452090eb339f409ab", + "docs/development/colocalization_preparation_491.md": "4de9ff456384c75e44b89f644c362faac41708bd29f8e8fa4e555a3978b095f1", + "docs/development/cpa_workspace_export_480.md": "aa4bc6b49151b9eb200459cf32f9391b076a2fed5314308aab0091d15e9f59ca", + "docs/development_setup.md": "3b524c15a49a9c0f5e5816061a9298def00f72e4a2783a14457ff140e55baf9e", + "docs/lab_meeting_cellprofiler_openhcs_slides.md": "2b56514e08d80a1f6c00eb5de173ead90029673427ed69ce64d55b6399a5eb0c", + "docs/openhcs_cellprofiler_lab_meeting.pptx": "e7db5a7375a708f458e141e26e161fcc4de7dbeb2b70d175665d9b25ca9b7c9c", + "docs/pics/cellprofilershuffle2_1.png": "22766756ee8fda75caa8e485e05e04170338a2a7a95c350b4e14ef84347fe852", + "docs/pics/cp_logo.png": "b4a2c73f83d00e37ee772215168258a7b4a45af54d5b15e69291b30d1a800f1f", + "docs/pics/cp_logo_text.png": "089e089ac4200c57cc06b90f1231a467ae0f51467e414ece8d923b08df0d2acf", + "docs/pics/examples/clones1colorneighbors_1.jpg": "fd9ae59612601b82c8b4d03b203010df0cb5ad8aa399a4aa8f46298f95694b04", + "docs/pics/examples/examplecolocalization_masked_1.png": "e9f1081df7c90a982e62f003b85d81d2cc03114892d6829d6d8f6e0afcbbb652", + "docs/pics/examples/examplecolocalization_orig_1.png": "e9bb26162e3e33c08f88c38561071861764a5f20eed159d44e7979f4276009fa", + "docs/pics/examples/examplecometid_4.png": "de009c6800c298d29056e3dd270dbcd316ff554e866372c3ae8941b7959b2c99", + "docs/pics/examples/examplecometimg_1.png": "f3b429e907a38ef30d4b85473fe02342044cf500b51fa5eb077d6f8e4c75bbee", + "docs/pics/examples/exampleilluminationcorrection_corr_1.png": "e3db3f2847fbbcdfed52b994bcbce8f599ac6b89aaf3a45b3119bf512e6395b1", + "docs/pics/examples/exampleilluminationcorrection_orig_1.png": "f4b63bb13ec6dee8e9f3c46f2aae5a0334d932152a1e7c7ff6545cecd00e31a4", + "docs/pics/examples/examplepercentposid_1.png": "e7c80215d6e63fa52f898dff31be31379d6e29a2608e5df4a01a5fd372ad9d6a", + "docs/pics/examples/examplepercentposimg_1.png": "f99bc40457f792ce3532b4bdb0a7a0e590b204cdaf2dbe3382cbcba099b5878e", + "docs/pics/examples/exampletumorid_1.png": "b956fed52f569e1eec5e3c839fc4a35e4e6cfcd379a36411e112ffd1bc060e31", + "docs/pics/examples/exampletumorimg_5.png": "f1a62dfc9c6e8d034034f267970944f1c2d8329f21ecddaf8cd5914020af5635", + "docs/pics/examples/examplevitraid_1.png": "ef300b99a943b91dc8cd68fdc100a57277de84383343452e3d7ad831d7b27847", + "docs/pics/examples/examplevitraimg_1.png": "fa4d657a4d1aea618e3808548f24dc96aea8b439138c172d6204ac676ec036ee", + "docs/pics/examples/exampleyeastpatch_1.png": "8dc08c4a22264bf6722f5c37eb98dbbb499a86d91b41744c02bed39e47426a1c", + "docs/pics/examples/exampleyeastpatchid_1.png": "95dcf058c54526cda79c4cde415ab19cceb28d2f29d88496f1961bc209ba52fb", + "docs/pics/examples/fruitfly-coded_1.jpg": "3bae3c9479b90f9bdc0ec540326494c95fdcec8ab3fceb8ebb31a726292b44d0", + "docs/pics/examples/fruitflyimg_1.jpg": "9ea6810589dd52a0d750ed903d63959a6d47dadbdc40bfe3263c6d9a84ce6e7f", + "docs/pics/examples/humancolornucleism_2.jpg": "84482408947faae3271184ada529044177bec1b8467d0cc21d41f74a5f2cb938", + "docs/pics/examples/humannuclei_3.jpg": "f61945fc5eb0dd205ee774e5ad9430cc15314ca9012cfb24a03a303df141b8cf", + "docs/pics/examples/imaging_flow_1_1.jpg": "f96f60c7eba45b8157b418e490b3b2915bf7b753c4b2978d4ca9da822d4f347f", + "docs/pics/examples/imaging_flow_2_1.jpg": "4ef0492e8025e407785be0b1dcda4a9775d4f5ce2780912cb3e0626b598d69bc", + "docs/pics/examples/specklesab_1.gif": "8e6b1ac574fb9dc72a15a0cf632cc4716da53be012bcd579db7222402304afb2", + "docs/pics/examples/specklescd_1.gif": "b4490d876040251af57d02354581717a141fee94c24af9c847b2c9a6b2857a58", + "docs/pics/examples/tissueneighbors_1.jpg": "570bac16fc77693064333653cba2b64be2b1b1b17c11d5fbf71841ec7b0e9a5f", + "docs/pics/examples/trackingexampleid_1.gif": "d872ef1c1ec95f9e2a5795b8bc5c93610a69f362c6a1baf346eaf60ae8af427e", + "docs/pics/examples/trackingexampleimg_1.gif": "a0f02997b15d6cdaedcb741099a476a0ddfc658bee444662fb597b864897cfc9", + "docs/pics/examples/worms_untangle_1.gif": "f91acb85e01aac27262cacd62a38af25a574a739e0e6fea95c6fb2807493ad5d", + "docs/pics/examples/worms_untangle_output_1.gif": "979d10e6c0a997d41208019309fe6bd196ad5ec2a0238974e171d456e2f2519e", + "docs/pics/examples/wound-analysis_1.gif": "ffbcd5576fb23d0ada2be70c4d4d02b271b5f8004da852795bc8b12a184053e5", + "docs/pics/examples/wound-img_1.gif": "d0cc8cd65635ac0067b813b11e36d8fdc5e318a7b306f1467b5eb3b3b234ea3a", + "docs/pics/examples/yeastcrop_1.jpg": "6a91a65eb83590d21c4146f2061755571b641876b821d98e5ddeaad0cc6e3fbc", + "docs/pics/examples/yeastcropid_1.jpg": "cc41c154778d4b995d9682dd6cc07a2af3ab9edfb83bddd480b9a0d1b11257c8", + "docs/pics/fiji_logo.png": "93161bc041d929a74427abd2554ef208439733d260d7de8ee0f13bb9ef34ea90", + "docs/pics/images": "d18be4b579b6407304c1ad6ff4011eb3cada6429a9693fc45f35cb7c6442e206", + "docs/pics/napari_logo-300x300-1.png": "c9b448a1c2d580be6f9f08b6d29743b518d263a928af2eb138f010e14c341758", + "docs/pics/omero.svg": "313efbf2fbe9418a9a6e6afcbc21d428889191f14338c19be5a3a83343984722", + "docs/pics/omero_logo.png": "edd5100aab0e5ab431cc2966fdd83b83649347becd8dc5a5f605577cfc8edb51", + "docs/plans/active_non_tui_cleanup_batch_20260518.md": "7805a34ad2b532c46d9d44de85475f88e69c7be0e44796e6eaf07fe1c30d78e9", + "docs/plans/active_pyqt_residual_decomposition_20260518.md": "bc78043fbc7f840e205c478cc61ad6d08c9e2c56269aac61a1571900269b9b5b", + "docs/plans/advisor_guided_adjacent_refactor_overview_20260516.md": "5b61888a20977b9cfb0040217c178f6a3bc12c53bfd225acb3f7aaea40bed202", + "docs/plans/advisor_known_noise.md": "9bc656d255c8a5b25c35d1726fa342a42701ddf515c4844ad5b3b75842e33f81", + "docs/plans/advisor_noise_calibration_20260518.md": "2773cbd2a4f6a3437f05683872032bc6f9997ac0010bc4d300d6763bf4658ad7", + "docs/plans/architectural_debt_refactor_sequence_20260515.md": "679c5935fb1d61ee1f57a40ec3198e8b905bfb52eefd5e4e52b77fc94996ba6b", + "docs/plans/artifact_output_lineage_contract_plan_20260701.md": "9e294b7d9f6bec60fc4cc962fee54ad2a731b801f09ff627b7aad00eed58c438", + "docs/plans/artifact_plan_write_authority_20260929.md": "90de19f98ab1ff217ea1bfb6e3b025265976fd3c96abc728e273715e45376f31", + "docs/plans/backend_dimensional_dispatch_authority_20260518.md": "64799c79e7e814ad4a3617484609e01fca40f7bf55d5bda85b40836ba1e44b28", + "docs/plans/backend_parameter_request_records_refactor_20260518.md": "596bf765654ddbf559692af39b37d56632a2869280158fa82c6322bf57d3e1db", + "docs/plans/benchmark_api_style_refactor_20260630.md": "59c2526819f6e2b738e7f4bf38509d961f59e3373af4987dff23e7e1752524f3", + "docs/plans/benchmark_mcp_control_surface_20260916.md": "5c3db4271016820c296b24fb3600134518fc0d53a7a7117bc121f3f41711910a", + "docs/plans/benchmark_pipeline_wrapper_20260922.md": "e225c040d2f38a23500134e85d8ae25cb5b1cdb4509642fc3d6be79ab6747c8e", + "docs/plans/benchmark_remaining_cleanup_plan_20260701.md": "9e977aa61f6b4b26a0d8613a3f9a305101ac7cd4b86c94cbba0b869c0b24ab3b", + "docs/plans/bioformats_microscope_handler_20260518.md": "a3b08257f7454cf8f69d0ce2d7088d8862670219ef00900e465422fe0d1cdb81", + "docs/plans/callable_reference_lineage_checkpoint_20260930.md": "f389ccc2ab89cc2fa6f4448e2d49134f6f8044e8d2554fbfc43ebf3cc73a930d", + "docs/plans/callable_request_binding_refactor_20260518.md": "fc231fe45dbf3a88b535bf2a2bc046c17e81107274d18fd0ada8147aa51f1aad", + "docs/plans/cellprofiler_analyst_export_integration_20260611.md": "42930bd400a152c133cfaeea56889d0982b24c3ad66895809746489abc805c95", + "docs/plans/cellprofiler_artifact_contract_ssot_refactor_20260520.md": "9f9a90415b24db0c528a8c151d619fba811908329ed8d115614cbf6011abf5fd", + "docs/plans/cellprofiler_backend_authority_cleanup_20260518.md": "8cdfd1484bbac85b0dd2b17c1c2dcbc0083614da6bdbffdc5946c598384e57f1", + "docs/plans/cellprofiler_binding_context_cleanup_20260518.md": "3a2e1ca4a345b3698922b249d6c14d48169d65a6f6238cf569999316ec9b88bb", + "docs/plans/cellprofiler_bioformats_pyqt_binding_ui_20260526.md": "224d270d817e5227ed2fffdd66a3b8de9a3a75e993d6c26d4ce2119545f74562", + "docs/plans/cellprofiler_bioformats_workspace_binding_20260525.md": "eca55b2e5a9e9edef0dcf1c474e6fed897a96d6f4534e56be78cd0e4e56cd279", + "docs/plans/cellprofiler_boilerplate_elimination.md": "4da1e4ad9e55525396da40666394c6639fb19dd453104c9710bd74c3fd40bcf1", + "docs/plans/cellprofiler_community_cppipe_corpus_acquisition_20260719.md": "f621b0d814495019a69a9689162e000ebc9547ec383ae2c75b0bea3a804f4bd5", + "docs/plans/cellprofiler_cross_domain_skeleton_refactor_20260517.md": "9462ad752dd01d024e8952ea5c00d5899e100dbec83d3ff24efa6b690dc35f10", + "docs/plans/cellprofiler_declaration_extraction_shadow_plan_20260626.md": "573e9ed4b0172c5a0e1231a75caa1f888be1c47c23adcfa6cda9d20330c8d431", + "docs/plans/cellprofiler_function_name_variant_registry_20260517.md": "22de8cfa95af85b1e00372aa6c63b0dcd252be43d0041f88dde690dcbc050720", + "docs/plans/cellprofiler_generator_declaration_query_refactor_20260624.md": "0f8f16ca0462e17eec61f279c77acec253d0f6512913a5ee9d9c31e2013be19b", + "docs/plans/cellprofiler_gui_source_bindings.md": "4344005ccb49b1ae4747f4bdda21f0b71f9d159177fc51cf9e615dedfdf04877", + "docs/plans/cellprofiler_like_debug_mode.md": "e2fd45ac437e12a17e7fccf3801b892e70ae5bbf5cf56164d2272da9091e745f", + "docs/plans/cellprofiler_matcher_fanout_refactor_20260517.md": "2939883224d93393888263933aead5c7089afe49c40aa6bf986f7dac337f589a", + "docs/plans/cellprofiler_measurement_semantic_authority_audit_20260703.md": "bd95bb188e1b3de1d2a8685e3364391ed403840d72718dbad8fcc9fbd51f3f40", + "docs/plans/cellprofiler_naming_opt_in_plan_20260718.md": "11408284e3420164cf57c3247491f582126a0b8f9907525dc87c5433039a2fc7", + "docs/plans/cellprofiler_production_boilerplate_inventory_20260626.md": "396f56767f28c6fe8bd855a9f5263aeb40fe417efcccec65ffbb5890e62cc5b1", + "docs/plans/cellprofiler_runtime_boundary_decomposition_20260516.md": "b2081a153297a0cebdf811a2e1e1d952748cb2dbfc7f56a0f6aa3eca4ea67e64", + "docs/plans/cellprofiler_runtime_declaration_semantics_inventory_20260626.md": "eceee6733b34e5f545a060fa2354f91411231085a27f5794c80d6945eb68e1fd", + "docs/plans/cellprofiler_runtime_deep_refactor_remaining_findings.md": "867a10d0a1d082ca242fcee4251534f7eddf1118a93f419a7de3199edeb51d89", + "docs/plans/cellprofiler_runtime_semantic_authority_refactor_20260524.md": "3fe4d9edeb3ed482c28d7cc1b9daddcffb18fd76421df585423d0b3959e96a43", + "docs/plans/cellprofiler_save_images_signature_family_20260517.md": "ffd278253618cb90c07f20bec1b4dceaa373e900787e9e08d4b1c38a41b16074", + "docs/plans/cellprofiler_source_schema_plate_ingestion_20260519.md": "9cbc39f5c812127618001a23cf3b924b5caf26e7e43c2d8f5a81f9b6de9c3995", + "docs/plans/cellprofiler_symbol_table_usage_inventory_20260626.md": "3a688684579dcc4632ec9f3ed086ecfbb33afd5e6dc9ede7b0a0e8f5d93dfd36", + "docs/plans/centrosome_watershed_checkpoint_20260929.md": "6bb66cf354f40efe20233bc32d8e1f2202a96686c5cc70855e1179f209367230", + "docs/plans/centrosome_watershed_issue_20260929.md": "f69a09a8e9e01090a494548d4bc820b2b65ea0c3db8b0e0b9a9b54b7c15d10bc", + "docs/plans/code_mode_paths_and_artifact_tab_plan_20260719.md": "b8058701f1fd320a1f1738e3faef7a282fc009eeac32373edfddd963670ee7db", + "docs/plans/cp_runtime_compatibility_deletion_parity_20260517.md": "032f97808965ba8817cab7872075b7bac969f609121cc9be93c9760e8ecd8561", + "docs/plans/custom_registration_205_coordination.md": "f67fa02b59d93862f056f8d800d67deaff2e724d24ef30bcd35b37e2620fc625", + "docs/plans/custom_registration_admission_20260929.md": "edd93cc6cc106dd8ab80d77203da6a44f199379e0a4f1031c7a7ddd9c3b9fc94", + "docs/plans/custom_registration_source_live_handoff_20260929.md": "25536201923c419eec855d43502afc612d1792821486ec25f84578d9c984ea02", + "docs/plans/custom_source_inspection_20260928.md": "d063f34b60bce65b8743f2305e33ea5557541c1cf6c1d6902290fb5e7c1529aa", + "docs/plans/czi_source_bindings_and_zarr_audit_20260719.md": "ee6ba0ff204669e8b61d6390f138aa158921ad984dfa26e162d607624da42ac7", + "docs/plans/debug_gui_e2e_workflow_tests_20260517.md": "90a915d522a969347805863e8fbde36b07b620f78844c15aaaef8a0f08ec984a", + "docs/plans/debug_mode_gui_worker_integration.md": "ccd33254aa20b86c84fd2e6c62bdfe7f9f0c33df5e876788dc53c2139945b9f7", + "docs/plans/debug_source_binding_followthrough_20260516.md": "4aa3643f98d098e1dbeaa1e2cb7e61d47014586858b63f6e40c41b5956168e02", + "docs/plans/debugger_ide_workbench_plan_20260701.md": "e2a7e49e436eb0020644cede49b6749bd378b49a73ab9d01ae9561b1f066d018", + "docs/plans/debugger_runtime_projection_api_plan_20260701.md": "20a077c49a216acd6a1f9b4e7a828b52c792e0a71eccced0ee3157b98e66ec8b", + "docs/plans/debugger_session_ux_dynamic_menu_plan_20260630.md": "60454e46123644675b03aa4fd901d0736f2d2c141eea6bf434e6b44626342400", + "docs/plans/debugger_session_ux_rework_plan_20260630.md": "13ff039204842e719b1f657525447bf8b75936f10b6215d4dc681c07a0240f1d", + "docs/plans/documentation_overhaul_disposition_20260717.md": "aba9ed6f1de8f6eb2209b790934d89601d9b78c8fefc4407b3637133862727c2", + "docs/plans/domain_extraction/.gitignore": "6a37da5ac2a5ffa7214f044ac64ea315fe20d6f71d6522e6603b85c2e2502479", + "docs/plans/domain_extraction/README.md": "aa551eefa64b0f97497ed3dede5779c2248a4449a86dab6b4292debc51b4cab5", + "docs/plans/domain_extraction/component_inventory.md": "af5e7892f94f8268846d15d51cb2ca55aa7e585c99203d13bce51a33beb46dca", + "docs/plans/domain_extraction/nra_leverage.md": "a870181033f891811bfe6a0a0cc94f1d9f4dd610cf77da4f3b73fc82dfe46b4f", + "docs/plans/domain_extraction/nra_runtime_artifact_location_extraction.json": "b32fb0a3158203d308e8ba348da0336a27e598368d530b20e953620bce35ecc3", + "docs/plans/domain_extraction/nra_scan_evidence.md": "b56382df5dc70b9b9cdfc5411c6ab221adb7be84439b72d4d444880c1666e930", + "docs/plans/domain_extraction/nra_widget_action_models_extraction.json": "c623d4723ed5802dcb9d6019514eb0debe55f905547ed79af319fb86a49f5479", + "docs/plans/domain_extraction/ui_streaming_inventory.md": "555a201eaa98e0a4f38dcc14fb50c7bf10cba8c760fb79ecd7ee6238812484e8", + "docs/plans/dual_editor_config_pyqtreactive_refactor_20260526.md": "9b61fcf197624646942112315a96dc255b5267d73a70ede2dc480c9aa70b4b7f", + "docs/plans/filter_objects_special_input_contract_fix_20260719.md": "bb1a03c1219acad7a91f6393e64337e0858afb2a60af03c2057a7bde6bb55bb9", + "docs/plans/full_repo_advisor_campaign_index_20260518.md": "82d0a3cc9550fb9480787567c173af12bbaeb6b321297f143d08f210a3979eec", + "docs/plans/full_repo_advisor_triage_policy_20260518.md": "94c673d41bd02ce9a2c4dc832613d6297eb2951834983c5a052f3603df1f846c", + "docs/plans/full_repo_orchestration_hubs_refactor_20260518.md": "dc87376e84e29373bc3a1b7c968aff25a968967736d677885f17a49a68fe1bb6", + "docs/plans/full_repo_refactor_master_tracker_20260518.md": "72e914c46ebd77bbb995a1d73e4adf9f07b8343d0a2d877eec17c83204915130", + "docs/plans/global_ui_zmq_config_tabs_plan_20260719.md": "2a48fb164a156c66d710471e5d5118a5a37cc522afd42322ba05fe350d2b355e", + "docs/plans/gui_widget_decomposition_20260517.md": "d15e61f6676c39fe014d69cc0e3e8ce77b414145b716126bee9ae483ce38f6f4", + "docs/plans/h002_query_preparation_diagnosis_20260929.md": "0e0c39ab8878884e79434385b9412c2763677af3b5ee6a2d7c49c569360484b5", + "docs/plans/imagej_cache_progress_checkpoint_20260929.md": "fbf82d8a777df09a203c52d72c8a9a679129f15117a839554bad022fedb30759", + "docs/plans/input_preparation_checkpoint_20260929.md": "794058fade714177303e17ed6d212fc414828242439a036b08719bcc9bb171ff", + "docs/plans/issue133_204_measurement_contract_checkpoint_20260929.md": "ac069c0663b747253e12068bd0dc127795c062a3444c12b7ed26c920a8279906", + "docs/plans/issue135_viewer_bind_implementation_20260929.md": "468632176c9f43b08f43121528e61523344c3008ee6bcdd219ee42b93df004be", + "docs/plans/issue135_viewer_bind_receipt_20260929.md": "74b765fc676593c6dd02bd7372288fcf69a7a8030c439cec81d2d33f60a319fe", + "docs/plans/issue204_catalog_diagnosis_20260929.md": "9ae3d78efef24187aded07c791645decb3a233bcb52dad45dfa13715432fc961", + "docs/plans/issue265_main_flow_lineage_checkpoint_20260930.md": "da15d4acc12eb24bf203dc8968a205368a530bbee37d116a20e92fbb66e36a0c", + "docs/plans/live_measurement_table_20260526.md": "f0e7f0ba02e9bf192398c78608353a19ebfa202c524b16e792b7cad31f8b4327", + "docs/plans/mcp_agent_experience_implementation_dry_run_20260629.md": "8d81b2f6dce348fe5ca7d8838b94c6267ea8d0c6dc1fd0cdc8976b3d49223fef", + "docs/plans/mcp_agent_experience_plan_set_20260629.md": "650ce7677ce387671030e4ac72f143b099002845aa2a2b0a3ce20ab8a9c7c229", + "docs/plans/mcp_agent_service_projection_refactor_20260629.md": "7bfbb90903134b9f3c8adcba00643c4e860f31d3d5e5abdbfc1e177a12d72c37", + "docs/plans/mcp_artifact_source_coverage_plan_20260629.md": "3c4ab4cea73f5b6fafb5a75c5bf49ecdc4bb42a42347fbc074824671deb2ce56", + "docs/plans/mcp_beginner_folder_workflow_plan_20260629.md": "5cd0b68b7e094e5917480e3e7810551343a8306180873fd841a162f8e1c35467", + "docs/plans/mcp_capability_tool_binding_refactor_20260629.md": "37a3827e82b2149079abc10e729af1e9739783d596dd0a4b6c463ddda4339f0c", + "docs/plans/mcp_cellprofiler_example_search_plan_20260629.md": "3137ca8e180dd76c28c9402b179c2112b5e5608a6789b6da272dcb38d9190e55", + "docs/plans/mcp_dev_client_ergonomics_plan_20260629.md": "d5ef694a0f501f9bfcbbe9c8dc138ccd3d021601f83d515d15e8d517e59c86c5", + "docs/plans/mcp_dev_client_schema_derivation_refactor_20260629.md": "2a75d87484062c3644dc13f79155675c44d70fa0e208ead68f576f4a2cb55ed4", + "docs/plans/mcp_frontdoor_core_model_plan_20260629.md": "7f78dab8a80e8230ceb242e9ef16ca585beab40fda156ee03a06fcbafd92ae65", + "docs/plans/mcp_function_contract_axis_semantics_plan_20260629.md": "70a31662a563ca740d4ee3402e4aa3e1f3a54e30d99ba02862ae7265a7af1146", + "docs/plans/mcp_operating_guidance_validation_20260909.md": "a8bf78e21856e70b073d5daee9f055fc4172d9590c9e72c5f1da3f833820d7fd", + "docs/plans/mcp_plate_viewer_projection_refactor_20260629.md": "836dd519a297647e61ae2bb2b28cb838b2a5cf8a7597575507841cbd97009505", + "docs/plans/mcp_public_python_api_projection_plan_20260629.md": "5093fb681089ed77fcd663ea8f11ade514eee8edbdd71c90d3ea89c52254e1c3", + "docs/plans/mcp_release_readiness_20260720.md": "de2de90864f6f035e2eba0fe244589036d62f5b08756c2d0b3458d78670d8946", + "docs/plans/mcp_runtime_sidecar_projection_plan_20260629.md": "dbe33e8074a2dbf561641e213bd19d85b51713260f34b8966af107a036d9fe3d", + "docs/plans/mcp_semantic_authority_audit_20260629.md": "44e738f678eaf5df0281ac0ccab9cfe75ce96c2a0675c309a1abff125e1792a2", + "docs/plans/mcp_source_binding_authoring_guidance_plan_20260629.md": "af3949bbb11f875ae1f38d5b3862b1490bfb120920c1fe7ef6d53cbbc8267207", + "docs/plans/mcp_source_model_projection_plan_20260629.md": "75a79d80d3dd07e69f2f7c87feb5840b83890c97bffe5e57aface4c64edd1f9c", + "docs/plans/mcp_thesis_demo_checklist_20260708.md": "83e04389297a19811fe32076b4a5a7855514ce1ca6d30bf6b3073f73794840d4", + "docs/plans/mcp_tool_surface_grouping_plan_20260629.md": "a78341dfd806d0e40e236101ff4f0ac5cae6011da9c7d7223bf9346c821f42ee", + "docs/plans/mcp_ui_bridge_authority_refactor_20260629.md": "a02618a14dacf625b0cd18364f7b9aaaca9ad5d338799635eb62bf3d836ff1da", + "docs/plans/mcp_ui_current_handoff.md": "a978e3b15c65524d410fec205ee77865a5b908e1e415886ad9d54484770e7af6", + "docs/plans/mcp_vfs_storage_model_plan_20260629.md": "674c1a152303b03b329fd6eb34cd0181561dcbdc6773beb494e264d28b75060e", + "docs/plans/measure_object_intensity_selection_retention_fix_20260719.md": "191cb59fe3bae3508c35a13617bcc6b13c956acb8014cdba89a897df702c5331", + "docs/plans/measurement_group_scope_triage_20260929.md": "21aa1fdfebb2a31c6a16e747078e7f91800b159b11c08660d699bbd5defe7844", + "docs/plans/napari_layer_identity_display_modes_20260611.md": "7e17f5f8667e755d3cd6e2d916912462611b0b13856db7e4431525feb9f55d0b", + "docs/plans/napari_streaming_handler_axis_refactor_20260518.md": "112bd4016dd2f3546b04e15050c0251443e6c47a8672697a1109b9d32fa17325", + "docs/plans/napari_viewer_navigation_authority_20260916.dsl": "ed96623c30a18ae856ad87f580c3313d4e2313a99e3480788bc20cfee757f1d0", + "docs/plans/napari_viewer_server_refactor_20260916.md": "8f0bc4b1c656e2928976d58164c7b5064cc44c4ae40a67f56fcca73072cf249d", + "docs/plans/objectstate_granular_table_semantics_plan.md": "7676177f6bf9021257f4491c4688ec04ee81c73505b1501e438dd60ab6c44b70", + "docs/plans/official30_current_failure_classification_20260719.md": "69b89994e93ae9a52c23938a2fe88cb79cb9ee77e8e53d5fd78c79d3c388b1b2", + "docs/plans/open_issue_surface_index_20260929.md": "bc9d24a5a0a693de9fb8dcc37c4b5e6363539648c9f88c02f65963e8a90e40ba", + "docs/plans/openhcs_mcp_agent_knowledge_base_20260625.md": "7c4b546fafe4d88137e7ace235f925fa8a1083e055ca6544092d8ffd08b7c801", + "docs/plans/openhcs_mcp_api_exposition_investigation_20260616.md": "7c32408f0543eca22cb8e9cfb9f84f5e532b2125fb8d9822f91f990548f24195", + "docs/plans/openhcs_mcp_implementation_blueprint_20260616.md": "4f4ec9c530bbd6c66ad748e6f08aa1d073931b3748fd29e1623a2b377020976a", + "docs/plans/openhcs_mcp_server_plan_20260616.md": "e7ca8942b97b51875811f968dbd138ecb6dbb7db1a3edd9a57b54762068360fc", + "docs/plans/openhcs_mcp_ui_capability_registry_20260617.md": "e02198a285ccd1fbe821f9260559b4773ef4558617b84b5e242df2f2309a3833", + "docs/plans/openhcs_mcp_ui_code_document_bridge_20260617.md": "f7f7341ab0fefe779d8aeb48d76a8c8b5c2d8c3ee30bd99d145621a6e5f2b748", + "docs/plans/orchestrator_stage_split_continuation_20260518.md": "24950935d165662b5f3863f616813baa332f6a2e81b319d406325bbc8d10dc15", + "docs/plans/plan_completion_audit_20260517.md": "127ae7d3c5921ee2780ab166bd198f3f52d98db89bbe27a5db18b4c304712c91", + "docs/plans/preset_pipeline_spec_authority_refactor_20260518.md": "62b31ad5e6db3facdc44d336fdb1c90e2e3b6f0334f5c2096d50bbb58b18c187", + "docs/plans/primary_segmentation_diagnostics_checkpoint_20260929.md": "58442a82f78fde89b99852907b15e7e9aed06d7f5ae68c98db951bae0ba4a081", + "docs/plans/public_api_export_surface_authority_20260518.md": "68e12db08586fcf726440d7267507ad394a5acb7ad824f92b95690d92d59a41d", + "docs/plans/public_internal_boundary_audit_20260518.md": "34bdcb19fa61862402d046025100d92177261d72feadcf21752c4f4aad030f47", + "docs/plans/pyqt_gui_decomposition_refactor_20260518.md": "2fe29afc25593ed89a853d1557d3729485a5e8c5b8039331493617a404c99bbc", + "docs/plans/registry_key_declaration_refactor_20260516.md": "20e190b8ac7e061e0913a6c5825c854efc8629d0c1170b406a853d10241bc72f", + "docs/plans/remaining_advisor_campaign_master_20260518.md": "ee376bcd84ba7f4c4ec4f00622055ea4fe618cd14cc90816a795cd5fcafb1ab8", + "docs/plans/remaining_backend_dispatch_projection_20260518.md": "ede587cfa9c49526c9f74d968b0d9edca134e660fca2bfc8b191a378571e2a41", + "docs/plans/remaining_cellprofiler_backend_authority_20260518.md": "15f3c4bec040b0ae889098b87f4267964a391b444ae81df1f8b316a8d2545fb8", + "docs/plans/remaining_cleanup_noise_calibration_20260518.md": "577e168c3b10950249c41f5710a50df13c8eaf049bf3b9454d280b8b817ff8d7", + "docs/plans/remaining_debt_master_tracker_20260518.md": "36a5efb6e96eda88fe0c398521f76e7c46ef343f4c92d37d1a424c7e095e9325", + "docs/plans/remaining_format_microscope_authority_20260518.md": "b85f883264786654d8b5ebf882f405f739861d0c20985afc65c827425b91d72d", + "docs/plans/remaining_gui_runtime_authority_20260518.md": "3f6b59ad560ac8b676d5b68cb108d4e843b1299c10c7884a5920b2bd01daf1de", + "docs/plans/remaining_public_registry_export_authority_20260518.md": "772fcc91c7ea5278c8ba3108871ca9ccf753538dab8cfafd36cd3db971b087d3", + "docs/plans/robust_streaming_refactor_20260618.md": "f6147f482fbab33e075491bc43d587f3eb350409e3cdca2c24748d0b2373d6a1", + "docs/plans/runtime_artifact_query_axis_refactor_20260518.md": "417d5c35f5e47d84680ca1a6d8ea39432c9dc1b367fd418a28454c0ed90a2c96", + "docs/plans/runtime_artifact_semantics_consolidation_20260516.md": "dffb731602ff85346f447e01d9b86141f3b949d6f5cce3d92447c421aef8308b", + "docs/plans/runtime_plumbing_frontier_20261003.rst": "be801060337c637750cdd766711bee630113c122e5dd6b0898715b810bbd57ef", + "docs/plans/runtime_viewer_protocol_cleanup_20260518.md": "49ad080fc66cbd99fcfc48c9ad7afcbf78ce377cfa6e90a8d7057d24b0ebb70e", + "docs/plans/source_assignment_model_cleanup_20260517.md": "b23a6c908aa890f1f94d6e6c709b6c9438ff615524a0b41dba978175c8fbe02d", + "docs/plans/source_binding_activation_boundary_plan_20260701.md": "b5aa96c12fefc9b281477571615c97cccd719ad849c2ac7ae059b5930e358951", + "docs/plans/source_binding_context_architecture_refactor_20260526.md": "d857b966896db1acbd446ec282abdc9609c69d0ec23787201ef6b3b5b94175f5", + "docs/plans/source_bindings_microscope_handler_20260626.md": "3e920e59a734ad107109da34d2313d43895234a9e27d829a3e9b01dbe435056e", + "docs/plans/source_projection_cross_system_remediation_20260527.md": "e5c69706c0cd76b44d72aa6b6e6fcb9b7f169836e7c9e1a3ae4e4ed03436f9bf", + "docs/plans/source_projection_overhaul_20260527.md": "b4176123d61a1016d419c8e497c4e273a0b502bf6c7ad122af5f34547f89e625", + "docs/plans/source_projection_overhaul_code_audit_20260527.md": "4c640f24c7d86862241fa8a0cd0df18face920c553a0f1a289395ec551acad12", + "docs/plans/typed-3d-point-result-20260929.md": "f5b4de3553d12544dce4b9ab6bb066177a29b7763ab22da12dc06f9166feff51", + "docs/plans/validation_registry_family_refactor_20260518.md": "966703a39700dc4e6b4da8234b633793c3e2117cd3172d8a511fa55f63cf9df2", + "docs/plans/yeast_colonies_source_context_identity_fix_20260719.md": "48fb2ea4b19842901a02e5d68945766ea1e79fec70449b964c4bd3cdcda9c5fc", + "docs/plans/zmq_server_decomposition_20260517.md": "96522ecb9779962661e458795496be97ba76e0af1262a9a379f9cd4b0d95a150", + "docs/refactor/00-RULES.md": "8da82e8348d9f3620558fe75f249380f965cd0367fb99d83c6f440c0b21f5281", + "docs/refactor/01-INDEX.md": "8427c3c0313e1f312950582bb3b0f30090c69bbf560b117aa0f978ac602b4162", + "docs/refactor/344-engineering-acceptance.rst": "0df290b3cb92862b5aba67a27f45558d0d6f10cd53504f9fffab6f6378a9c296", + "docs/refactor/344-installed-native-acceptance.rst": "f798862aa6f3bcef1540c027dc289752b143ddbc8a6e4dc3b0fdf6e9027a5916", + "docs/refactor/345-installed-generated-input-acceptance.rst": "25bfa4666621477855b0cf2bd2c314f3664e81c03e9bf9c3ad82c2425600b143", + "docs/refactor/Canonical-dev-client-decoder-400.rst": "1b6af739b82a65a5e661c75809801e9d2874b8c45700fb47c637939325c1c520", + "docs/refactor/Classification-authoring-runtime-380-381.rst": "5e5c53ebacb1bcd09465f2ac991e0c4c6f6e0af52a550e9b6d4be57fc0ede3da", + "docs/refactor/Classification-measurement-subject-370.rst": "3aba78be9e0c5662c76522c0730d347320a5f41c9960cdb020c24ac5c281149d", + "docs/refactor/Classification-two-vector-authoring-386.rst": "37a7497a8c9b429402fc5bca2964bbd5c042e3307ccc0f392a6ab743e75872fd", + "docs/refactor/L0-experimental-cli-owner.rst": "77adf11dc6623116d38fc01ffe03a01c70fa4336db9dc4b7b4eb7d951dbe58da", + "docs/refactor/L0-pattern-resolver.rst": "c066c5bb9d618a3c591c04d26bb328c656d9e5cd7ca0b719dc8d7dc64e91c223", + "docs/refactor/MCP-authoring-roundtrip-360.rst": "b4fae4f0d03c567d138bd2154ff923bb175e1569ae3621de2953bdc508c159f5", + "docs/refactor/MCP-compile-selector-authoring-360.rst": "e3255ebfb9064713543652192359744a0ed120ce22b14c67a2ef6c3c2126078f", + "docs/refactor/OWNER-OVERRIDES.md": "c7fc3abfa8a3b2912bd443fce0fe110c717791bb5a6793d0c265f01cce1e9d7c", + "docs/refactor/R0-checkpoint-20260930.md": "239d5cdda154b8ad4a7a0a9df7ddfb8f6600c00d39f10031de1fcbc7e72f43c9", + "docs/refactor/R0-empty-report-scope.rst": "439664a890993ad20b28296379f3c119923eeef3e85b3e16c5fd88f5733ac950", + "docs/refactor/R0-stop-the-inflow.md": "a9c94236a30eae4345a4b9004d1e76650c80f94338ab40b0743f0a6a393868ea", + "docs/refactor/R1-two-revision-staging-357.rst": "47171aa139010e2acca35fdd1a28bffb36ec9b3e6281ca46f12a73d78e9c66b3", + "docs/refactor/README.md": "bae436fbae8d4dcc715619e64cfabfd1e6b110678ad58e56f46deea760be3642", + "docs/refactor/S1-config-schema-typed-renderer.rst": "3e664969d49ffb5d523766605a2f1a9d44f10294a32a47add37eedea43e14a78", + "docs/refactor/S1-generated-input-contracts-339.rst": "ae0d6f1342703c9e6d85dfcb21e5831f003c82a8f39536de18e9f0be6d41392d", + "docs/refactor/S1-imagexpress-installed-338.rst": "794ac11af297de5779499b564441eefb91c9d6509c7b2c01eff29b03abecb32e", + "docs/refactor/S1-imagexpress-readonly-inventory-337.rst": "6c2d35d2606df56d7bcf7f65abd45ca580fa0033173d7735c3c9281dd4d37cb7", + "docs/refactor/S1-main-f24-integration-20261001.rst": "42b79a6bafc48f14c6531d2f4627ac283ea5cae7f76716b6aa280b422e1212de", + "docs/refactor/S1-mcp-result-owners.rst": "1073fffb2c583041d6a6eccec670c2264f42987b16413cc90955157480949398", + "docs/refactor/S1-paired-raw-bootstrap-350.rst": "53be6f31b40675028e84551dd857e7aa7e99a5f825a1b2e1ff0babdf7c14d26e", + "docs/refactor/S1-paired-raw-installed-350.rst": "84247349d17dca8f0d372a671232cb11600adfefd7173b6785333ecce42d12e8", + "docs/refactor/S1-ui-action-result-installed-20261001.rst": "2f0dd3e03b897362dabe7f29d8eb816d965c029786aec2a3f0f214d8bf59611b", + "docs/refactor/S1-ui-action-result-ownership.rst": "0ff2b822cd55203b4014e98cb2881cf5105af5cf326717d3038a5969304b2901", + "docs/refactor/centrosome_watershed_integration_20260930.rst": "939b4d1602a6b34ec0e6ab4577c21dcf543bea6876e97d58a4419103c57bc5a4", + "docs/refactor/cleanup-20260929/H002-FRESH-C03-ENDPOINT-RCA-20261002.rst": "4b5d24a5ed8e683b53e2ad2be1b0bc6b9b6a4d3b85de15f25d792471b220f5da", + "docs/refactor/cp-aligned-full-stack-342.rst": "b7493d7e12dafec853e02498f6f65979859c5c041010716bd4cf9f4669318fd4", + "docs/refactor/evidence/cache-reuse-tests-resources.txt": "d89afd03540a141b2dd564a33f6e072d0a50cf7a96fdc88991d872a1533a4877", + "docs/refactor/evidence/cache-reuse-tests.txt": "332d84f320f1f6679439758dd688d7cbdd6381020f5aa7d0780866ad7fdf639a", + "docs/refactor/evidence/config-resource-supervisor-failure.rst": "464f1068973ddc2b4334cddd0d1473a62f29b6f17065dcaa47e368bf3c7887cf", + "docs/refactor/evidence/final-cli-tests.txt": "7703858045bbf0160002fe19390dff1039cb4e896f75de769946be28eec22029", + "docs/refactor/evidence/focused-tests-resources.txt": "ece6e843c060b3107a5d3581157e4e446354cbb608cbbde72afd165d5cd2c16c", + "docs/refactor/evidence/focused-tests.txt": "709d352ce4928ef077981e76e64e7dc9ff4082172c9d4abeccff544a29622ee2", + "docs/refactor/evidence/r1-cache-reuse-checkpoint-resources.txt": "e71dec459a0cec70de0a013733603a0d282495bc1e05b6d961deaf37b2c1d37d", + "docs/refactor/evidence/r1-cache-reuse-checkpoint-time.txt": "dd199b725c8b7f12ac03334ea8e4629aa0ae1dbb4f2f5882d052cfae47b921ea", + "docs/refactor/evidence/r1-cache-reuse-checkpoint.json": "5df03cd49cc726caf0d342dd90bb3c84e7d5695b2551434f4749ef9043ffdead", + "docs/refactor/evidence/r1-corrected-checkpoint-resources.txt": "7484374e6bf73cc0f3ea3867ef2c76bf3c1bb6edbeff211c125c6094d312a5b5", + "docs/refactor/evidence/r1-corrected-checkpoint.json": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "docs/refactor/evidence/r1-real-checkpoint-resources.txt": "880240afd2232ddcc116e8fed028675eb204a69a675f9eb853c6aa9e8ee8e09c", + "docs/refactor/evidence/r1-real-checkpoint.json": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "docs/refactor/evidence/ratchet-benchmark-resources.txt": "4cf9458b9fa70c7d9b72edc2a3dba0d1e71d3c227a8d2cf62be101d1a0808d62", + "docs/refactor/evidence/ratchet-benchmark.json.gz": "33ee215eb47196f1d361da45c1f0ef78418627789a7e29a0681b9611eaf3b415", + "docs/refactor/evidence/ratchet-openhcs-resources.txt": "ba215567deb02b310bcf440509df5545856bc458f62aba5c718ad1fee48f4c0b", + "docs/refactor/evidence/ratchet-openhcs.json.gz": "9fc448a6c5e7388a29b93019417a333bc68b3024a658bcd5f63f0f8e84908a67", + "docs/refactor/evidence/ratchet-reuse-scripts-resources.txt": "fa9e82cf96707d434abdf0f374a93a0745bca28021828ca7e586a03bdd6933ae", + "docs/refactor/evidence/ratchet-reuse-scripts.json.gz": "085041a4b6f41509c297e1d2d1ac4ec9f756ba69f2b7ee14db19f9c39285077f", + "docs/refactor/evidence/ratchet-scripts-resources.txt": "55187d48a956949c8df1c6d358896b61e0b6bf35f6a16bbfda303b4ab19e1a71", + "docs/refactor/evidence/ratchet-scripts.json.gz": "b54471e11432954d42e72b2adfb4f2870091dbeb88553eb36a6f040217d9847d", + "docs/refactor/examples/344-aligned-rescale-engineering.py": "323ab83b8462a9a8f4e8cc873e446eab1de15a114a3f3a07740ea8b682b7666f", + "docs/refactor/receipts/S1-config-schema-typed-renderer-20261001.tar.gz": "f6641d99fb42983763c3bfec0044ec4711e4787223361ddae0b3ce32ab097e68", + "docs/refactor/receipts/S1-generated-input-contracts-339-20261001.tar.gz": "50e19c75e01d8456bdcbb35f910c76254b7a00906d18084f79298dacf6078fb0", + "docs/refactor/receipts/S1-imagexpress-installed-338-20261001.tar.gz": "2afac8c852d194ec1f89e55dd7d63a06bee21efd76fcdcb34c33e5e7a0a2f21b", + "docs/refactor/receipts/S1-imagexpress-readonly-inventory-337-20261001.tar.gz": "bd635440e79af99d1a0b9f285668699ed47ce678bf8c82c0c630e054c524bc64", + "docs/refactor/receipts/S1-main-f24-integration-20261001.tar.gz": "bca2ab8be8aa58ebdfc3502a4115ff12228aa048cd215d2fe0942f7cf062fea7", + "docs/refactor/receipts/S1-pipeline-20261001.tar.gz": "9a4fdd76ba5113c20dc75b34f92c84d3fe86abe3a76acae522daab47d3fa30ed", + "docs/refactor/receipts/canonical-dev-client-decoder-400-source-20261001.tar.gz": "06d9c73a82ae7e1c58eb1213da3398a3e1a349ec939bc69bf1e1992145f4c351", + "docs/refactor/receipts/classification-370-cooperative-hook-review-20261001.tar.gz": "7c26a2c40eefcc8fd71c833cbdf016df0e20f909ab271e29587f914cb5f3ab72", + "docs/refactor/receipts/classification-authoring-runtime-380-381-source-20261001.tar.gz": "4f27a84e986968d421ba4b3011e833f8e78d3ffb1ed61142d89d883a8634589f", + "docs/refactor/receipts/classification-measurement-subject-370-source-20261001.tar.gz": "95aaa8e25c2f35cee817a3391f194733c39d66a74903e19c3f4440304c297c01", + "docs/refactor/receipts/classification-two-vector-authoring-386-source-20261001.tar.gz": "470e435d270548a0cf65ac574bfed5778798af91410484ed78906ee80f87ca96", + "docs/refactor/receipts/classification-two-vector-mode-ownership-386-source-20261001.tar.gz": "2106b6113282fa8652ab1a0c6b3a7aad4ffebf27c5e9798552838adcbe50a682", + "docs/refactor/receipts/classification-two-vector-public-driver-388-preparation-20261001.tar.gz": "3ff0f287ce9fc2022f8556590aa42cb519ac201b8337e5792bebfd3d84f9a22c", + "docs/refactor/receipts/cp-aligned-full-stack-342-20261001.tar.gz": "8bf492e2b9efb309ca071f7b034b8780ff96d5f441acf0da9a12fe55d35150ed", + "docs/refactor/receipts/cp-aligned-full-stack-342-a14-supplement.tar.gz": "34f21c4c7c3ce912d020bacb91c303b00dc9ee55629e96aa7d092c123e1714d7", + "docs/refactor/receipts/cp-aligned-full-stack-342-acquisition.tar.gz": "da7bc60170e6383b9cc2e5dde090294fc4f7dccf9ef9be757c2839c41b2f6852", + "docs/refactor/receipts/cp-stack-installed-native-344-20261001.tar.gz": "d6d53528b2a8508f4004a6d1d6b7adfc411a7dea9a1ed1844bb19736731faad5", + "docs/refactor/receipts/generated-inputs-installed-345-20261001.tar.gz": "e509a5518d575a4fe58dad635c55cceb3a926f78814b834eb1d1b2b233280dd5", + "docs/refactor/receipts/mcp-authoring-360-source-20261001.tar.gz": "366b053daf6483c44adc3d4d4a69f661fcb8fbbdbbee474b6ab698979e9eb91a", + "docs/refactor/receipts/mcp-compile-selectors-360-source-20261001.tar.gz": "dcbc336f43a851ea88743b0d58fbc28f9592be2cf724366c3af778963cd8e888", + "docs/refactor/receipts/paired-main-flow-388-closure-20261001.tar.gz": "f20d2d7798198ace853e8e77333549b29a5d69d4e35d9823659d792b390fe310", + "docs/refactor/receipts/paired-raw-350-census.txt": "1a72c6dd5cbe0baf897bab12966f008611bb82065a64bd4ee890c8e0372be308", + "docs/refactor/receipts/paired-raw-350-collection-failure.txt": "5f6ff263edfc1d56ddd97d0cd14e3adfa5aa0d367bfdf63f3d495f01dfc92acb", + "docs/refactor/receipts/paired-raw-350-full-context-r1-20261001.tar.gz": "6d596f8abef2e4d9eb0c6b72ed1915c1f77186503e722b56387141545147d384", + "docs/refactor/receipts/paired-raw-350-initial-global-audit.txt": "4a83dee9b19d8aedb6e4bafadde38288f1029ca78ae1dda7eed3dc5697aac967", + "docs/refactor/receipts/paired-raw-350-installed-20261001.tar.gz": "d9dc3cf6172a0acca50bbf15886f0582ffd34536fca2af9daab99d9f0f0c225c", + "docs/refactor/receipts/paired-raw-350-original-defects.txt": "b6368e5c9367a216d3f173a9f68b6e69c3529d1ea58c546431d1d8313d1df045", + "docs/refactor/receipts/paired-raw-350-overlay-incomplete.txt": "97f5613f88daacf944f75aabec61b66004a8ac31fe2bff226fe9a2be0574392a", + "docs/refactor/receipts/paired-raw-350-owner-review-fixture-failure.txt": "ce0f5371142d9750633d8065d2fabe7d8707959a18d382188c25f8f36e47d504", + "docs/refactor/receipts/paired-raw-350-owner-review-freeze.txt": "d9bc4d82187956dda1d828a019808e30ac74ee88f0f46205a6f0ea11f78bae0a", + "docs/refactor/receipts/paired-raw-350-owner-review-local-guards.txt": "1116c64232866231a978418a19b09bb778b1bbfdc84deac96e80dbb3408e010c", + "docs/refactor/receipts/paired-raw-350-owner-review-projection.txt": "cc623dc80b72a868b5de960a60ad4ab1d64204a79f0f1eed4dbb042be069512b", + "docs/refactor/receipts/paired-raw-350-owner-review-source.txt": "a5ef378a65443f9db401e22389e2c366ee7d52fd47df54b3e02fddf183c2a319", + "docs/refactor/receipts/paired-raw-350-owner-review-viewer.txt": "c1d277659910c61cac056f695e23fd5b2ba7bec7848c0937fb5c762d014777e7", + "docs/refactor/receipts/paired-raw-350-polymorphism-review.rst": "c80c952a89f2137ea3b82ddabf3923b230ac40263aff8a54f178ab735fe87e9c", + "docs/refactor/receipts/paired-raw-350-r0-unavailable.txt": "ff164f8da87f5fa14b24bc2e2a835b40458a460453d4ba20fa47233cd2227238", + "docs/refactor/receipts/paired-raw-350-r1-incomplete.txt": "f9d688e0c3ce656bf7b759b9b1f850a03f12136d78751a2774ec465869127aca", + "docs/refactor/receipts/paired-raw-350-source-bindings.txt": "ca18cffe286f54ca9f0f33715d1dc9faafc2a1e8345f2e67c58dae129826151c", + "docs/refactor/receipts/paired-raw-350-source-projection.txt": "9476267486a93ee37ab243a1610477dd70c926d5ba6fc0ba81f7f92eb11df0d0", + "docs/refactor/receipts/paired-raw-350-validation-environment.txt": "52323864bff1c2527a9151ebad6f681d19a8cc2918a790f958dae1a3cb3615bb", + "docs/refactor/receipts/paired-raw-350-viewer-projection.txt": "bf8894234b9431616297e73803005e880aea705de2a8c2168f832d013adef153", + "docs/refactor/receipts/public-enum-388-source-20261001.tar.gz": "d0e8e9015987245eb0988926735e257576d55f06f981db3872043b884b2a689e", + "docs/refactor/receipts/r1-357-parent-acceptance-20261001.tar.gz": "575e1fd30ffef1770cdc07b022a31fc6af66b51bcaa9086fe858da59c9b65b31", + "docs/refactor/receipts/r1-357-pinned-r0-20261001.tar.gz": "03c14fb7b8d1c37cf85b88913e09b6d8abd8f6eaaa6312027d33c7e813d947fc", + "docs/refactor/receipts/r1-357-source-20261001.tar.gz": "d41a137fb14f83f471f01a00cb94636520b8f61df70e74e56ca356d648155b2e", + "docs/refactor/receipts/ui-action-result-348-installed-20261001.tar.gz": "f438599170dd46755328a8967bffcca6d3589cd98e744c687811222e9ff55c90", + "docs/refactor/receipts/ui-action-result-348-poll-source-20261001.tar.gz": "ad1bc20fccf597bba6715d2727e7ae5f75e008122f2281afd95353c0217b8c6b", + "docs/refactor/receipts/ui-action-result-348-source-20261001.tar.gz": "bb23a531dd376857f3816c2757f4bbca3194686210221727a35079bac670ff92", + "docs/refactor/render-complete-snapshot-363.rst": "96e1923aaec6aa5dabee74e874d06253eb0f6d2c1a77fa2ed5ef406f23d12081", + "docs/source/_ext/openhcs_config_reference.py": "a45ccbd142745b0e636ea815134d6154c669f84b06a2d087fd76f993ee06aca3", + "docs/source/_ext/openhcs_gallery.py": "825d0e01d331069b93c00469fff157ec44c2febc346b6978b2e556159be7a8e1", + "docs/source/api/index.rst": "68401481faeeb4745afa97a50248df8533cfdb6ca0aa09a94557bae2cc4ef57c", + "docs/source/appendices/glossary.rst": "0d2911da50a8546e893ffbf0091415ae995700bef3f271170cd8eafb7abffb85", + "docs/source/appendices/index.rst": "2da5b38e721f42b2a0f689a47d7919770ba4cbecb2b89840ed46cccb1e75ab90", + "docs/source/appendices/research_impact.rst": "177e054c72fcf87d97b79d4055a33d4125522b1fcbaeaf14e2876808511429c7", + "docs/source/architecture/abstract_manager_widget.rst": "3c51ca0ae7b7ce37ca6bae986330b7b1285b4e3f176d3f61b9ad92ee70e2d9e8", + "docs/source/architecture/abstract_table_browser.rst": "f628d49ec314b8893df96ba0737d52ade78cc63ed997a5563129cc60765284e7", + "docs/source/architecture/abstraction_lattices.rst": "aab6e8a69b89dc4f866cd83a639a4120a9ebbdfa366bd228fe8cda4202ea51b7", + "docs/source/architecture/analysis_consolidation_system.rst": "3f3fa8f3f0ee441d4c2aa42bd79c2da3dc04635f4958b64ce49bcbfc25a618db", + "docs/source/architecture/artifact_contract_system.rst": "eb9380b348a7fccfb4385956bc1997b4dc4bf23aaf1f45abe2fd2fd8c1342d83", + "docs/source/architecture/batch_workflow_service.rst": "5b35c78968bea4782ff67974f90428b37d7f00d79ef00509155f2b6d79917798", + "docs/source/architecture/cellprofiler_interop.rst": "ca51e69ffeb5e594de80ab27c0c71bcb1d78a76fd059ab093afbab9b7a9b0040", + "docs/source/architecture/code_ui_interconversion.rst": "e92fe7d1580b8cbc121dbf13023c64faf85150de3e4bca9a13f99513ef6e2cea", + "docs/source/architecture/compilation_service.rst": "38551baf73cc9010f0dff7af6440a72645ef28d85ae014989831c502cdae2e80", + "docs/source/architecture/compilation_system_detailed.rst": "f6b652564854eafd1e1d6670a2f6290c799d5aea05ddafff3fe6c8e7587af7bb", + "docs/source/architecture/component_configuration_framework.rst": "1334fb249990281c1c8e23c74b3cb2da71aaa1fed73d58ea79b0177dc5e7bfa4", + "docs/source/architecture/component_processor_metaprogramming.rst": "82f7f46e2303d1a78f0cb9d2d2286e230447f8f32daefcbbbc5021b9e9e86561", + "docs/source/architecture/component_system_integration.rst": "5c4c60b9b9a02dfb0dd0f56ecc2bf4528e877314f14f76d0591ec112958e84c8", + "docs/source/architecture/component_validation_system.rst": "c9d15356dc02939a216b2bf7bad60b43b2a244ce30d1eda4e61556c26b80ee02", + "docs/source/architecture/concurrency_model.rst": "db244918e5b7ef7ba93ae17d1855954c630e577b56813f8ded29dafd4e7889bc", + "docs/source/architecture/configuration_framework.rst": "76255a82c6f9d5c2032ba2c31a5c5c8a08442ba463f62f65995b54e26ea74363", + "docs/source/architecture/context_system.rst": "dd532f01302a0aedf0ed9e42a478808557aa7a9b16554e274117e142e3fb57e8", + "docs/source/architecture/cross_window_update_optimization.rst": "c51c33c8b45c265d62061e5b45ae00eb84d250bd050640a623f99911257a323d", + "docs/source/architecture/custom_function_registration_system.rst": "41758478c7609c3506a501d30ee41de17df3f36036587c5b622e3a2fb38d93b9", + "docs/source/architecture/declarative_window_system.rst": "480757c11ae720000f495ecfd073bc695a59f3ccf60a1c4069e0990a28828f96", + "docs/source/architecture/dict_pattern_case_study.rst": "7b7f94d81bd19966988b9971ffbc260f8cbfa35cb6351d11689f660c3b48d3bb", + "docs/source/architecture/dynamic_dataclass_factory.rst": "cf60e0c66a1f0d8a4cc586619de26fcb176b38543c4f807d12f8da7a5053dc26", + "docs/source/architecture/experimental_analysis_system.rst": "9b143aff0b24ea2c3d9dbebe9f4789f764c3e81d1258747ee2fe33eed8e4e943", + "docs/source/architecture/external_foundations.rst": "2c95e2864cf17a5a6195c2fc3c498ac99eb4cf450a841f7a8d2417a94d53f1cb", + "docs/source/architecture/external_integrations_overview.rst": "cd950b20705e1661d76f3c2ba9a66e68a37a88020228083327b77a9e40b688f1", + "docs/source/architecture/field_change_dispatcher.rst": "0f8b6bbb4cae3582c7320d97cdd2834c8d0d03a71d09087a5191dd6c7ba0f76b", + "docs/source/architecture/fiji_streaming_system.rst": "62e265e06150472a480de0827b6c87acca44485731fd1460fcc3a3dd63c44d20", + "docs/source/architecture/flash_animation_system.rst": "64572091cf8f5ab81e3486dfd96254a8e21678ec535d442225013ac122ad1569", + "docs/source/architecture/function_pattern_system.rst": "51d989837a8c3db1e4278c72a9193051d6664719fbe65dd6e8c64c4f107df643", + "docs/source/architecture/function_reference_pattern.rst": "8fc9e57d90916b1b3296caefef94f86ba521aefb6daca2d979ab146b3636129d", + "docs/source/architecture/function_registry_system.rst": "d7b3867ded4005b0c37875b70b972f89e76baf04397ec54554679532cbc0ddf6", + "docs/source/architecture/gpu_resource_management.rst": "998a32e50c5ed6c59b44f3f7b0fc686b19fe619c63b459e0be7b273c555bc637", + "docs/source/architecture/gui_performance_patterns.rst": "11a327ebe1b1a01dd66e41b995fa5ba4af84f903b711d57e4fda58efe727ad9b", + "docs/source/architecture/index.rst": "f4f48fea35485a48919dd048ed8e053b71c8c2c25b6fa8e0f6a60db1b7f3e24d", + "docs/source/architecture/list_item_preview_system.rst": "59ec9b7019bcc8baae04e3cded674beb98cc808c040fd82f47852b253467d5ec", + "docs/source/architecture/mcp_distribution.rst": "11d1d54561689e08a1b6c8ceaedfa1f4de7fd82dfa25e20e1b2ae813528ee0ce", + "docs/source/architecture/measurement_equivalence_system.rst": "f071f7effe7d94ef86cfcfaa24f479249fce185cba690c670ff247597aafa948", + "docs/source/architecture/memory_type_system.rst": "1d921c1987ff8020a9b246e554bf23c89a40026b232aea78e2222253b1aeeefa", + "docs/source/architecture/microscope_handler_integration.rst": "7568ee810dd5ff9f13643ee2434a239e6e79d42d0e3dd57d2690b406d41b254f", + "docs/source/architecture/multiprocessing_coordination_system.rst": "816ae37a0aa964c708bf3b7855583b1e0ce706571a231df60caf1405eecee5ee", + "docs/source/architecture/napari_integration_architecture.rst": "4bbde493663df970ff002dece5777f6150773f266b3e4ecdb5fa1ab00185607d", + "docs/source/architecture/napari_streaming_system.rst": "0627ddfe19a65702fecbf151a17924f1f44bf9ba91886651b5c516384232197d", + "docs/source/architecture/nominal_ownership.rst": "ab2d1a92cb778414fb8624533ef6de74cf92e70ba87c92a495bbe8ae70faf7be", + "docs/source/architecture/omero_backend_system.rst": "c62d31950f0d453ce5d6741f628f37ed758dbae64e45398ca470526f623c6e46", + "docs/source/architecture/orchestrator_cleanup_guarantees.rst": "1fabf4a602e5856b9ac754b390478f7c2859a6bc6e088e7c55a4e5901ccb54a7", + "docs/source/architecture/orchestrator_configuration_management.rst": "1cf4d86ac3a102396af9ad8515466dc6cb55dd81c7c53190503210349b7f6b5b", + "docs/source/architecture/parameter_form_lifecycle.rst": "dd8768b55e6bbacfe6553a718a590d7c05c1fb1a802d3d6cd276c1526036a2f5", + "docs/source/architecture/parameter_form_service_architecture.rst": "ef32a0a776d3062db07cfc53763f43e98b2e860f902a1ae5a962adc01244a52c", + "docs/source/architecture/parametric_widget_creation.rst": "b99e226bc6d9ba392e003c594e4bce691188b93e0b0d34bd41d5a77c5deb4b22", + "docs/source/architecture/parser_metaprogramming_system.rst": "2e5fb290d9e25310c13084ee05ddf0e8c19cee7af435e6d3a16b5c7ca60550c9", + "docs/source/architecture/pattern_detection_system.rst": "2a59466462d8dd7f7439f2d628369bbfab955fc6cc92f82bba81bb896cc2f06d", + "docs/source/architecture/pattern_grouping_and_special_outputs.rst": "42dcebbbb001891b323a38fb786c50ad1def8d13f52ec0b77750fd8b846ab293", + "docs/source/architecture/pipeline_compilation_system.rst": "a8b349cd9e24e5ca683416666c05ce71e9c74fbdddd4f216f20c1b0837ac36a6", + "docs/source/architecture/plate_manager_services.rst": "06abc350333f3c0d51f3418db49de6c51d7eb3f5d27d523e1a113a5b2b2b943d", + "docs/source/architecture/plugin_registry_advanced.rst": "74b621c6e6e85dc47aefc7b971cfdfbd0dbc39eba911f147184dd778c93afda3", + "docs/source/architecture/plugin_registry_system.rst": "1b851cbbceb6ec89d7acb28574bc8d858903b8040f42f65760b96c0b7d3250e4", + "docs/source/architecture/processing_semantics.rst": "9d1a0203f2a4236ea102cacd8e48735a24d93d55d3d5c807ed69a2f30d451278", + "docs/source/architecture/progress_runtime_projection_system.rst": "6cd52fe8420d85bf7429ab128e3ba3a92a42bd158cc35767b9c1673ef51a6441", + "docs/source/architecture/quick_start.rst": "4dcc151050f02da75a6819db0be0053a1dcbefcf236b34998536ad9fbece915d", + "docs/source/architecture/roi_system.rst": "15c214ff7075f5e87c56620dcf2730405fdd6845c83d6c379409caca919dff61", + "docs/source/architecture/runtime_value_system.rst": "130ae142dd1d147f24317d06c900d6701482fd492d580ee819082c8a756f7703", + "docs/source/architecture/scope_visual_feedback_system.rst": "58c708f70f3e1dad618b797f3dfe6e50f69dfbcd089f6acaa7d2f3ab2d845cb9", + "docs/source/architecture/scope_window_factory_system.rst": "02e8e78701a4cd7b149cead277ffc3d52305ed153980307d4818f0949c43fc61", + "docs/source/architecture/serialization_boundaries.rst": "28083415985860019b3ee15d0c69e9c07c903584a3890cd53b7a1676a6718c74", + "docs/source/architecture/service-layer-architecture.rst": "8a2362db7c8da206ea396293f9a90bdbf728740e39cd616d5902910ce296a2b5", + "docs/source/architecture/service_registry_integration.rst": "db7c022ce0ebef1a40baed2b68e3d9e8301811d4947cef3eab6b2dcf7d3d48e6", + "docs/source/architecture/source_model.rst": "ba603eb36228385593c44bec049517320dfd29013ffb49cbdce81bc675ec11e0", + "docs/source/architecture/special_io_system.rst": "e61acca7a6cb7e2c7cf41948d399b850695c9c245c46d0d5c85d1d5b0d0bfaf1", + "docs/source/architecture/step-editor-generalization.rst": "d5e23b3c0ec74c1a0e31b253493e3c777f72f817c87f42bd72818ba0d2f0ecc6", + "docs/source/architecture/storage_and_memory_system.rst": "37be786863142d1762d151ed6a528941c79a47270ba577e93cef27cf0c474428", + "docs/source/architecture/streaming_boundary_and_wrappers.rst": "b4943eeac6a59501b60ebfa16b0b093bc415b5bf8e4124409371b0d3641cbbfd", + "docs/source/architecture/system_integration.rst": "f0756f6700cd6d8e3ed2ceeb6e5d4210ad24ead7561fcc3271fa3c9684d5b664", + "docs/source/architecture/system_overview.rst": "87f6eec65645b2fd4a01de961126c765230ae0eb3480a1e3b4a7b3fb3618b28f", + "docs/source/architecture/tui_system.rst": "da94ee23afc2e0870cfe590a263afd3855d3460a3d34b9579615a3c79246a881", + "docs/source/architecture/ui_services_architecture.rst": "f398733f3501923efcbd7e41fc8da2681c9ffe1e78c2d1997fc65df5e731de3a", + "docs/source/architecture/widget_protocol_system.rst": "930b2684c302fc8a1c60f8c11845ec10168ee29a074d6c04e78ea5ccd68706ec", + "docs/source/architecture/zmq_execution_service_extracted.rst": "dcaf4e63eb604312edadcb3442479ac6e369842231bb5caeb3e5404ecf693155", + "docs/source/architecture/zmq_server_browser_system.rst": "2ceb609f8b720a6862577d5fb1e18658d1040bc7e7507c03642a3b8471a9fa6e", + "docs/source/concepts/building_intuition.rst": "f4eb04f78f1e52241fa1b7f79b39609142f106832a0bf38b953a170592cf8f78", + "docs/source/concepts/component_system_concepts.rst": "e3816c371c55821e36e5012787776092beee9650ea638f0006673808e3e81539", + "docs/source/concepts/core_model.rst": "abf8f245abf9ca3526a63840d54dbc5f9677604422f027c0d838ff2256800830", + "docs/source/concepts/data_dimensions.rst": "09ab2832cfb480cc532867a118850e12242f2fc9951df718f95317bd746ee564", + "docs/source/concepts/domain_fundamentals.rst": "9f4a6f7aa270b5814397a0e8227f44064cc6f5e4cf2219609da187ae7557341e", + "docs/source/concepts/dtype_config_system.rst": "65715bc974d343ac1f219a175a95491a6120667fa46e32a5ea96f6f3e14628e2", + "docs/source/concepts/function_library.rst": "5f283828046aaa3e7c9e57ff0ef34cd77561031f110619b0d41aa9696047a769", + "docs/source/concepts/function_patterns.rst": "2e60a937bc001bdcc961f378c5fb29d1829580351cbf87db4eec9eda02d77411", + "docs/source/concepts/index.rst": "dd54fe9788c8e958696998abe42c55a6b49a31eb7d07211e14de761dfd8c62c2", + "docs/source/concepts/module_structure.rst": "6537ec140390a40a617770c4c4c7691a568133bf9d72b0be41ee3acc7e61c404", + "docs/source/concepts/pipelines_and_steps.rst": "ae82cf8baa401e60948956fd26590ae6d32c0a08db147df5c7a70ab09398eed6", + "docs/source/concepts/storage_system.rst": "6457c0c132bd45f195274e51b255f45713b5efda9ee7ada352de556ac4aa1dde", + "docs/source/conf.py": "37c6c130d75662601d1e0fece5e0f206b7bf366ae04b596ae39aa9f691ad1c94", + "docs/source/development/agent_workflow_validation.rst": "70fc4c26f67598a993788db2f246520836b9fc255fdd4cbb8d7d3999667a3158", + "docs/source/development/ast_refactoring_workflow.rst": "79299114e82cb13d549d24dce90abc381cd249e2c2d4e10c116d2086b73e4686", + "docs/source/development/basicpy_readiness.md": "7ae8ee1dd13f7161a2280d3632802b66c496eee37cbfb6909d6b83d3c22b503c", + "docs/source/development/callable_artifact_authoring.rst": "204bc980bf4eb9b8d388e17ea9510c15baea62dbd42cbce19b71aa59119a0b53", + "docs/source/development/cellprofiler_module_authoring.rst": "21c9257bb7f2f637f3ae4546614a5aa2dc166f770da6144d9292baa4806f5bae", + "docs/source/development/compiler_extension.rst": "4bb46f10ebfdab22de8f3f5b833e7f74b78d4d846ee50c671296e4aad33953ff", + "docs/source/development/documentation_authoring.rst": "26fd82613f2b305850a37ae899dfda4fa1eab2186fcc46cdba639f43b82e2175", + "docs/source/development/extension_workflows.rst": "02e13f4611803605d430da15b4a1fa875a16a708b4b167fa0efc19f03df672eb", + "docs/source/development/git_worktree_testing.rst": "5a2487f59d2befe94a05219b3a382f2c60e2c773054cb90f8ac2bfdde0ab9e63", + "docs/source/development/index.rst": "fd425732b5660df4f8f110174f6e773f070160f73828bb84f7dd641965184fdd", + "docs/source/development/mcp_development.rst": "829194108df1e11d2b8aaae97da3a0ce7cfd6c5a2842e58ef3ab3ad305a88de7", + "docs/source/development/mcp_knowledge_base.rst": "5c80d2a633a6c49ce2301a02d47ca10051ff5289c60e16b1e0e01ce12e7a84fa", + "docs/source/development/mcp_knowledge_base_manifest.json": "1544dfcbba774a3f6192d74975e46d406096609527bc86d0d44dfa153e7ebcdd", + "docs/source/development/mcp_release.rst": "df77e028492fbfa6856545a9eb138959a3ad7535de2878ede2583fa2b39f5ab1", + "docs/source/development/media_gallery_capture.rst": "d6a113e61be593483c1fde8ebf6c7ebc51b67a1ae05ab86e811605793a9db5e7", + "docs/source/development/omero_testing.rst": "2316f94fc1745319e710ea52f48276eac864c7c8070bbb7e0c2f67affabbe595", + "docs/source/development/parameter_analysis_audit.rst": "4e5c25f0c8a05c81d0dbf73f1a2b69e791a3da4c5261865a2fd08de47d49c2c1", + "docs/source/development/pipeline_debugging_guide.rst": "884c4ea25aa9bb02b90962a9500ab981848b143867197068cf585f1abdd5d45d", + "docs/source/development/pyclesperanto_simple_implementation.rst": "5cecda2276f76c744ad6a215f8ecd58c82c2ce6ce4859d6d5990f39ba67ffc3c", + "docs/source/development/recipe_knowledge/official30_examplehuman_nuclei.md": "f6420893f94f1c4ef060f629227f9696d000b46c1ee97f61163a21c2e3185a12", + "docs/source/development/repository_setup.rst": "745235abe25f39764df948357b010f3e973815bd10cf89bbc91ce7d6e7b5070d", + "docs/source/development/respecting_codebase_architecture.rst": "2f9665a3a063e62b401f3d44c24f596baf16d3496d0953efc269e563bda9d48b", + "docs/source/development/runtime_system_assembly_rules.rst": "a2275aad184f08bd2966a26e44463909c92c5151b79936f1ce76f83766fc7164", + "docs/source/development/runtime_value_extension.rst": "eb0f4bdd7eac7fff1ded970acbe29db94f76e06d1bb61d8e25d564f43ea9e249", + "docs/source/development/source_binding_extension.rst": "a1b709b00dca507f7183aa847d208192d6f79f2eba8cf5f452cec37b9510a63d", + "docs/source/examples/experimental_config_example.xlsx": "3333fc392d79c86f80d1f973fa31463b97ad5a1649f1255af2ad460c0e0a4bcb", + "docs/source/getting_started/getting_started.rst": "151b7d49018e4ef31c21bd96729c1ccd3af746a82a5d239bd27bf163474c067c", + "docs/source/guide_for_biologists/basic_interface.rst": "2478a75261b5e9ab12e01f897561485fb004da645f15bf030870fda628162b41", + "docs/source/guide_for_biologists/configuration_reference.rst": "ba3c4ef923c4f643c06accc8641c462b2f63a8e46694ef984dde96ef49a0d9c7", + "docs/source/guide_for_biologists/domain_expert_onboarding.rst": "99af4a6bf51653532d929d7008e20f515bf4ff1303a1eccfec7e7dd79be5ca4d", + "docs/source/guide_for_biologists/glossary.rst": "0f36a6d90e71d79e1b33eafa06f2ef4b0d8193850e6e72a2260fae11360f47e4", + "docs/source/guide_for_biologists/image_sources.rst": "8a4a45c89a263d1da25150009a8fd55af1edeae621b3028878c9f138e40375ed", + "docs/source/guide_for_biologists/index.rst": "36a25412fe848d198b00170d96fe7c4ea1ae8e0ac128354bbc2a94b869bfd4ab", + "docs/source/guide_for_biologists/installation_and_setup.rst": "12516b7e28b02f223b15977b23d94b2396af6a32cb47fc9bc84e0396505aaedb", + "docs/source/guide_for_biologists/intro.rst": "40fac7417c9d8920edb90f3b3dbae55b8e05f333ea58271ef2cce2514717fde4", + "docs/source/guide_for_biologists/intro_stitching.rst": "fde83b50eb661c94d16d4d8986b86f565f6db1bdf7f57668293af7b1612e29d2", + "docs/source/guide_for_biologists/troubleshooting_FAQ.rst": "0c2fb0dbb43ec18efb8d4aeff2a728a35630516a6e506de677de5d070089f428", + "docs/source/guides/complete_examples.rst": "ad07bdc258a85e22c4b67c3d4694c84550dc8e0c1e136998d174e558bc9682d7", + "docs/source/guides/example_corpus_map.rst": "2266d39c952e8d64b2296c524412028606276f9f0ee5883d2e0fa660649373c1", + "docs/source/guides/fiji_viewer_management.rst": "43f0e1f0effa40bf1a1efe18ac3efe8da0a184ad746da086b19f756f06178943", + "docs/source/guides/index.rst": "e4a5b15f4fb1f335477b33bfcb8e6d559b568b4264f68e3dcabf568e89fc2c58", + "docs/source/guides/memory_type_integration.rst": "7890c784379b0de4ecc3871068f1acd13de522077d16a7589436ab94a8019adb", + "docs/source/guides/omero_integration.rst": "b900bea91d2eaecb90d593786b213830c6fd689b6cbc09c25f9b0c7ab2a6183e", + "docs/source/guides/pipeline_compilation_workflow.rst": "051f6d70831eb9939375063651d825604695186de950275b512f5bd8c64a6293", + "docs/source/guides/testing_guide.rst": "82d14d7b3163bd6c7313922d7509cd80325e1021d83e80e50aa8775ac902e59b", + "docs/source/guides/viewer_management.rst": "cf6b38318a5464e6b0d30394f7a5c3bed5b3ca8af1a336486a9d4962bc104996", + "docs/source/index.rst": "708577608c7afb29ce9e3d579bcce3c099348cdad8cb05af63656db66b1c8c72", + "docs/source/installation.rst": "05f5519d47c42adea4d67ef1e70d0eebab7819f0ea4fe66b293a5c78eb34f9ca", + "docs/source/reference/configuration.rst": "526b0bd4f86e96cb888a54f9231abe57d9d6eea06e551e925d9ef6eea18bc678", + "docs/source/reference/dimensionality_and_measurements.rst": "5e76aafecd9d58677c7f0578b9bc461594ef8347cdcfb3a25ec1f563ae0ec808", + "docs/source/reference/experimental_config_syntax.rst": "730244294388f85e5e49fc46d9850cf8f38912fb4039ac45ab89da88d7825051", + "docs/source/reference/index.rst": "23988fccd4033006377ea231c93bafcb2455a6257ac242054123577c927c0e3e", + "docs/source/reference/ui_windows.rst": "f6b96b5e67dba0977de53dd8d76292e1a3577cc43fdddf4959f211f605004c11", + "docs/source/user_guide/analysis_consolidation.rst": "ddb564adfdece91f7ea7223bbd8407b78492175b83fa500c2e4449ae82cfc50a", + "docs/source/user_guide/code_ui_editing.rst": "7617d0594ee253c7a19ad940eee142a931b094171b76428ac83bb74861ad2c17", + "docs/source/user_guide/cpu_only_mode.rst": "f85c3dfdde3dee4e3a2e16ddafd2995d8a18d422477c6800caaa4f94ed5dcfff", + "docs/source/user_guide/custom_function_management.rst": "a543658a18b61b83e0e516d59f13e543090213d904b7503c89ef479eb9a55f87", + "docs/source/user_guide/custom_functions.rst": "6dec340f9cb1eb45e984513bb0ad3cdae229c546fc846df128564a0df0f61398", + "docs/source/user_guide/dtype_conversion.rst": "c95144eee07fe4134768fd2e839cb25dfaa9d61e9794332c8481ccfc39a95d4c", + "docs/source/user_guide/experimental_layouts.rst": "836f6b525b52a32672e7ea18c21e37f037c27ff102a83a762433caa4e04fb31a", + "docs/source/user_guide/index.rst": "27f8a295cf35fafbac99ee4915c653ea5ae63cdfd544b5ebd321564ce61dde36", + "docs/source/user_guide/log_viewer.rst": "fc2c9f40387305d8b2eed47c066d578b99a930a682e7c585319615d539bdfd32", + "docs/source/user_guide/mcp_clients.rst": "f47e4de0a9e8653155f47898627953ad7635c2b72e05805483a72bb6c85f0e26", + "docs/source/user_guide/real_time_visualization.rst": "c269dd225183533dbd30237661eb2f8926c9f42b46082023e457a6c9232f7e3d", + "examples/benchmark_example.py": "bc7ddb98189af17eb0502520ecc259283aab4ae400eccb0b26fcbd31fecdeea6", + "hooks/post-checkout": "f656fcc566be174503d4c3f4700b88f2e1ee71d29f777961b8d3159a3afe89e9", + "hooks/post-merge": "e6bb2b8650ee36f37ec42067ee6cb4a7b5bb3da1c66923a97ea38ca46a88b5e9", + "hooks/report-submodule-status": "776761b57f14e0bdfff14a3b52b9b22bb3440f8c686b171c69a7a40d9b2d90d6", + "napari448-existing-controls.log": "e0fca33c2a8fe4fe33b015c1ed05c7d7aa1ce89b4ef874327b8845842f625f3e", + "napari448-final-controls.log": "ab173c6a68a51f10fbb775cd7f01db8e72e680718f362592c1f4f7d38e8e85e9", + "napari448-first-controls.log": "8fc24071aab28e3b327d28c2217c49dae5901e7f8bd61957c78913722509efe6", + "napari448-original-r0.log": "e44326ccf2424a46ebf8af51dc423dc661ec3f705a5e75c8bb1cf6450d9ebe05", + "napari448-original-red.log": "4f81dad7b8a553755b1223c815dbfd076675ea50763260c16b51ad1e791a531f", + "napari448-source-red.log": "e3506f3dc69016cc0a5bf3a6dda5ded0ac4c957451f82d27889497f067f39744", + "openhcs/__init__.py": "32253e0592653cf555e52f4d4151bbe1002337ad3c459755cbfccb4a91a077b1", + "openhcs/_source_dependencies.py": "63c6f60298b8155b1abc0880cac09ac4d9676461f5198d3f15db676140ec7653", + "openhcs/agent/__init__.py": "3b5283f8384967a128270d2758883a38a7721c5c6a179c8277681c102b74f172", + "openhcs/agent/authoring_contexts.py": "98a2f00ecde98b57e6196aa461573ba84d758e2dddbc7f5944544b7c77018f03", + "openhcs/agent/blind_recipe_audit.py": "131d709b16597dd7978d2d0c98394e1e2531840af7f25063ade2b3575d60fa64", + "openhcs/agent/capabilities.py": "c72eccdfb1a2837dc8227563f1f9f34f62106f8af4533e9e481fc7121dcbd3d8", + "openhcs/agent/dto/__init__.py": "bcaae6fa3303f83e4f9f54ef33a2db2ae609a03a19a440295e0e196178c36bf7", + "openhcs/agent/dto/architecture.py": "19e8596c4bb88a107ad7cecb0fb62aab07738c991937f2ed4d4ca0a26d2d03d2", + "openhcs/agent/dto/authoring.py": "a07683356289012a2ec713fe1b7d21023e4c36880e931c756c7de2d39461afc1", + "openhcs/agent/dto/common.py": "f1f46fdb98446eb5f76e35d299fa5aa44e69617d25dc9eef97c8245b234ae9ed", + "openhcs/agent/dto/config.py": "cee5d664f80346f847186d56cd4efff64b2d6dc72fa7721d2bab02b17a82c9b8", + "openhcs/agent/dto/execution.py": "a1a325d771df05a9cd9c7b91478b1ccb6f9ae745e7aca97366521a6686290748", + "openhcs/agent/dto/execution_connection.py": "1316cd285936def8576f02d14923352e0b96554e7b9675bb1d91c6245c446785", + "openhcs/agent/dto/functions.py": "1a9d2cf4e068c2dc1ed42cafeaa2e7a4a38ef0741895daeeb7333074b5afc801", + "openhcs/agent/dto/knowledge.py": "4826294b7b50f4f1f842ff53cd0c9d9908a6a0620279a49fff2d67c88629bdd2", + "openhcs/agent/dto/mcp.py": "7a6ad911c61b62f339f2615990c3eeea1589ef6efea8941d7d76b745d3406264", + "openhcs/agent/dto/pipeline.py": "ab1f0d5bf70d9d8959ef1e1ead8c2ca1c23f1e6f6557ffcd55ee79ccba4a943b", + "openhcs/agent/dto/plate.py": "1e09656c15ed131bf0185260b8e754e93f57d95331ff51f3064ea37d3f984e4c", + "openhcs/agent/dto/ui_bridge.py": "585b1701b01b92bfce91437a60881afa769e36de9126807c3f4fcaf0ffc006fb", + "openhcs/agent/dto/viewer.py": "c4b976bfd14f83d6d14080e54671c26c507efe636a9d3a68cf660e439a171223", + "openhcs/agent/exceptions.py": "50f91dbd2b6f5ddf029f2d8ddab6b166c85e1226d03cb47efc06944ca94dad92", + "openhcs/agent/image_analysis_qa.py": "3e3b968eaf9b56a0de7177a8557aec80aa95c85dffebdd2a584e9a89f6ce960e", + "openhcs/agent/knowledge_manifest.py": "2689e052a31a075475e48bcc288a5ce6ec43417a607486f67b892f794f61ff44", + "openhcs/agent/knowledge_manifest_schema.py": "0699cb21975a3d783b47e23c0f41399e9b7ad91d58499e0207442d9010f8fea2", + "openhcs/agent/path_policy.py": "73fb2d2f729487a926861bd3919ae26c92da79229db52d9c61e94ca88c7f392d", + "openhcs/agent/resources/__init__.py": "33d4a88d70f2ea443bceaabd3d6ce18bf7617670c2eac4161c9d86ab2e345c17", + "openhcs/agent/runtime_platform.py": "1429f747a77282e9221af6b1ddfbc68d96579558f51bc78abd74607d02d6d79f", + "openhcs/agent/services/__init__.py": "b4c841ea9a2b3c7b14672083ceb2b4569575b3cef1ef9accc05b020118530345", + "openhcs/agent/services/architecture_projection_service.py": "b209098d78c5520fd34d744d17b10c1ef0375a9bc2655449f6f3f9908decce0e", + "openhcs/agent/services/config_reference_service.py": "18b740aad750284c0aeaa4c51e81a31828c8e51e609f4997b6a1a50cabfb4e32", + "openhcs/agent/services/config_service.py": "c4dc3860e1720fe6b383aec8b0ddcb498eb219da74da6ccd6709547205193f22", + "openhcs/agent/services/endpoint_function_catalog_service.py": "91aa713fe1a09b2def1b2748483338a942a0a5ac9c92c45c4d48c2c91c4f4cc0", + "openhcs/agent/services/execution_session_service.py": "40b51d5ce4db6d1e9733d410b78c770963a6f71be922f1ef05484126a9deef52", + "openhcs/agent/services/function_catalog_service.py": "14d16fa47c863f4932fad548e21759ee2499f60ad1153a80af14d22df97aa5b2", + "openhcs/agent/services/knowledge_base_service.py": "c5023d3646fffed2c7b046f068ecba0f2f7375b83b72fddbbadb8842d74c8db3", + "openhcs/agent/services/llm_context_service.py": "6cac4630478f2addcd7e054821eddd7a3243ab156e96f898eb28d2d3873ef72f", + "openhcs/agent/services/object_state_field_help_service.py": "d1f130b63e7b36aaee23b6333048de777b21fb40b7ecd85dcc7687c79dc74ce6", + "openhcs/agent/services/object_state_field_projection.py": "86d56cca7e6ee3ed4d67ca6dfd42145bda09f15114eda4769773803efbce929d", + "openhcs/agent/services/pipeline_authoring_service.py": "c966a51926e980194abc255733fdd7ed44e8de63b29520ca0dac95d72e4a317b", + "openhcs/agent/services/plate_inspection_service.py": "a488e591594195e54153cc80c9901cbe256d5a444232900dbc631de9d05fe2fd", + "openhcs/agent/services/plate_streaming_service.py": "bdb2b1cbaae388783e0c3b4a6e0c9ec143df97504a2570d459878e7788bba93f", + "openhcs/agent/services/runtime_server_service.py": "71f58c8aa17a277c707074a254edeecda61533dc43a8cbb2c89f2a48b4229ce3", + "openhcs/agent/services/selected_plate_service.py": "d4e75a6607fda7004c5363d674315996f2ee8bd4f477c9926a7c029b1be73f97", + "openhcs/agent/services/synthetic_plate_service.py": "2860714a9f1f2e66df403bc72331195d912cb180600889a1b4f4207642cc776b", + "openhcs/agent/services/ui_bridge_service.py": "37015a88828820e7ae98bf804f42c37f1fa26009b1ad28b3c537f65a656e943a", + "openhcs/agent/services/ui_bridge_transport.py": "32e759baf65b34989c99223d8fa9e64800ab566cd05160df2bc125b04dea5953", + "openhcs/agent/services/viewer_endpoint_discovery.py": "27bc74d2964961e80bac607eef383c9aa7353b9d65ad6b4dc3e7b7f76742bed8", + "openhcs/agent/services/viewer_window_service.py": "4748db99a13af087329cf1b140b5ec57727c5e8f60ecd3b4d8520f7af248c020", + "openhcs/agent/skill_bundle.py": "34e99772b73d32642cb5df713156b9d2f4ab49a937034018e9077127124b1547", + "openhcs/agent/skill_sync.py": "e3366bb7fc8c300ab12a8fcfb86b412da45e578fb3c2317394e1efe16dfa18f5", + "openhcs/agent/ui_bridge_actions.py": "28c494cc9335ac84482787f1949d9937fd818864407d56ca23ba585a3b0156a1", + "openhcs/agent/ui_bridge_environment.py": "30f459623ed48c6d653725080453630ef9813f875dd8e63d171147f5e73caacf", + "openhcs/agent/ui_bridge_identities.py": "5913d14b99340174af87b2a7cafa3cdd080a331553c0cf59392ade7d253f1234", + "openhcs/build_utils/__init__.py": "2b28663db4d6ec1638afb92e71a907c275e0c62ba2b1ea69382c51a6bf8f7f9d", + "openhcs/build_utils/zeroc_ice_installer.py": "6922f41c8fc3037b987a2a04ce43d51cd16779a130a039a488f1c5fa9e0849e2", + "openhcs/cli.py": "59025ea51309dbae40416d75fc203287657a109379f65072d77cff41c712e11e", + "openhcs/components/__init__.py": "5d3e9eae8bd7ff36ac4d7d619e1869925fc3e038f69dbf5735587ba0038e8e65", + "openhcs/components/framework.py": "5dc5ff81c9c3fa268e0a7699ae62a99e887e6f86c448ab6d1fc92255c5a9c718", + "openhcs/constants/__init__.py": "7f9ce299ea67a0772b5973e522c3c620505212fd56480bce4fa2fe742f57f236", + "openhcs/constants/constants.py": "4cd6c29abd8b8e3ecc396b424d2b8b61e819a215fc1d770d3f6852b260a0691d", + "openhcs/constants/input_source.py": "fccc1854051fbe47371df2cfb737080bdca14d932825ef7ddc9a0e1ed1cf0dc9", + "openhcs/core/__init__.py": "faa96a3ec6c9a966571aea7696cb4ab0fd81eca3c58f542bc9366a6fdbe3582c", + "openhcs/core/_tabular_native.cpp": "15acc82b8ab64268bd1ea4f83fa7a68f527bf317f002e9f39e15be321e03b28e", + "openhcs/core/alias_property.py": "b7716605fe9b78cd2dfc76627655a70eacdb31f7ef83cb0e09b74f2572bbbe71", + "openhcs/core/aligned_image_payload.py": "3e93fd6cf96da0b6b125055722866c5b6f11ffaf30de464d7fa7d409d8e1886a", + "openhcs/core/artifact_inspection.py": "f0033d6edc3691fb4c7c2d641b6dbdb552e0fc75ee109c6145095a96011b8916", + "openhcs/core/artifact_key_selection.py": "9d4f607483b4b444c0600026a79a2f821eec4ee679a5f662ad059121f05bb35e", + "openhcs/core/artifacts.py": "f67e1a2fe8b794bc37bd17424235d7f1af402bdc1120bb0dc50cc5a963c508af", + "openhcs/core/autoregister_preparation.py": "49762654d81fbe90073930950cb27c94b3552f529e34c5e0afa860ab0d27bdf0", + "openhcs/core/axis_filter.py": "c375f5ccfc5669aadbac035590aca578f9c209a4276d9c6752b96a7461a4214f", + "openhcs/core/callable_contract.py": "a15708ec2bec159cd4c4be2b93d213e8fb9a812e1d6c467dd67e7248898cd6fd", + "openhcs/core/compiled_execution.py": "4d5bc05df24a0874adb974f73eda79a3848d0fc573ed126f3693648bdf2f35df", + "openhcs/core/compiled_step_plan.py": "982ab3b9b79cb78c2aebc905c5acf682d9243abc602ea5ecbeabbb4da993cf04", + "openhcs/core/component_group_scope.py": "d5f1138d21187e7d84213780e3b5961f2daafad4c107f1468b1dce53811743b5", + "openhcs/core/component_set.py": "b3f7dbee802766aab3002256db044025abca8c4ce60be4648f7c1de7b13b41cc", + "openhcs/core/components/__init__.py": "58f0646aeed090cac412be6e4f5357776f7af1a5c5b8989afd09ffb27fdfa2fa", + "openhcs/core/components/component_values.py": "3813d6f7d6d66fc21ea881e3dfcb72f54bd1bfe36212895f00be8f09e59d49dd", + "openhcs/core/components/multiprocessing.py": "d30c624db431f25287d6f5036861139fb8d1ce66838eb9f08d725ae318796719", + "openhcs/core/components/parser_metaprogramming.py": "e916e680993175a78a4db2f9f97976918ddf4bb13617d5b5e2916f912a9939fd", + "openhcs/core/components/validation.py": "21ff922447de83ed3f62e54c25df7966419b4895be23a8a3c5d42a3981df554c", + "openhcs/core/config.py": "47d54358521bd7c7abfea1b3bd2cb4b8c24fd9a85826498437a6970122d59d74", + "openhcs/core/config_cache.py": "51db7f1d5010c0b633a0997b4a587cb2a9a042e0a1b1f291f1c6c8d0d2d90632", + "openhcs/core/config_document.py": "37f66fd971806e059da6194c003e20a7ad08f69066eec4af7ebb11b4b70a08db", + "openhcs/core/context/__init__.py": "309422241c5d942952aeec92d513d9e0e517f91b937fd8aa3eece5bf0a686815", + "openhcs/core/context/processing_context.py": "fa587f726d3baac27f17b064db7230d58162408e4230d426f08acc91568b1c75", + "openhcs/core/debug.py": "072259811bc50bfe71cce9a7cac3e9867bfd853bd34ab5a74b01d9fe14b68f36", + "openhcs/core/debug_session_projection.py": "0a630eb03a83d741a4ed55838adb8ee65dd4fde9be07878aeba5e7a8c86c7378", + "openhcs/core/debug_view_models.py": "1cae1ff9267cd8cbe6324cb25ccd3b50cd0237eafa781e3acffe77e668385df8", + "openhcs/core/debug_views.py": "095ef349e413148e4e49ed221a4822592f66292578d9eaadf76595771dc41996", + "openhcs/core/equivalence/__init__.py": "24516170f37a443d24843686c6d52bf27d6ce73a39f483337144a3bb12740091", + "openhcs/core/equivalence/arrays.py": "6074f4b5183a45b7295f42c6de878affbac49b284ea694aa2533547b8ec3fbfa", + "openhcs/core/equivalence/cells.py": "70785cb4ce8a75f695d97f6c685a1816f715a1b3225382d1f8b4a9a9c707c5be", + "openhcs/core/equivalence/comparison.py": "f8832104aad56c64ad1017c2c0d5ef6a3609384648c5017a394f9900f9ebaf59", + "openhcs/core/equivalence/images.py": "8fbe0bc6620beafee276c887195dab91bdf6f102b246ff63e0ab8f330707b2ad", + "openhcs/core/equivalence/keys.py": "d2b2c2702dd5ad75c7df32905e7abc3ee4bb453c427503387fd210c2631dab5e", + "openhcs/core/equivalence/measurement_facts.py": "ef1fd1f95469d55e670e6b4a874b239fa448fa0c927992723be8c8487aeb9e3c", + "openhcs/core/equivalence/measurement_features.py": "b0e1c3d3073d0af931f7acdede06102b7e493bf1e6825ee9cff41924dd59b021", + "openhcs/core/equivalence/measurement_requirements.py": "c8ae5999e47d7fdc81de1bcf92ab614e517580260188b9e6817f8eeb27d2a8bc", + "openhcs/core/equivalence/measurement_rows.py": "de8b80dc6e73a79e714137f6697ef5e0252f99f9209aac908492386a0f8b4ea7", + "openhcs/core/equivalence/object_label_measurements.py": "b4bfcc56e98dd3558d458894a78037778192aaa9752855dff6e20053eccdc053", + "openhcs/core/equivalence/outputs.py": "be3ffd9364208900a88ea1defdf750de3bd79abdea6bb843900510ed5618176e", + "openhcs/core/equivalence/policy.py": "aaae502d1bb818ba38761374f02d8d4b5cf78a798bb2965f157216eba72cef79", + "openhcs/core/equivalence/relationships.py": "b29521d60b5870f989919a8bc36adc626795264b68851836b90b768588d0468d", + "openhcs/core/equivalence/report.py": "c23d65e113f792e40855dd0843ba0cf16b62cab096fcff96e1a4168a65f187de", + "openhcs/core/equivalence/tables.py": "da6000a86fce224c967195431c86d9d256f3dc216d29a4d889e2e708c9fa60a0", + "openhcs/core/execution_state.py": "4ed84065adb562e6a43230a211cc23f021f4498af546e5eac33d4e7b98082029", + "openhcs/core/execution_visualizer.py": "88d4332fbf10d63107d56675753b16a7afab49d0f16571949ae0bf2eda2be23c", + "openhcs/core/framework_device_resolver.py": "be96430174bc576c0b8083879c579ef3fb9b83c4690234751459c2d7bc5556a8", + "openhcs/core/function_contract_metadata.py": "e3313cc1667719a948913cf819d028f37868b081b69a052795417f4484f872b8", + "openhcs/core/function_patterns.py": "ac438272b3b0b08fed59e1105f7b16d30db27888aab19d8e7baf8b4ac3075e78", + "openhcs/core/function_reference.py": "546a8eb0e315cfe9ff264a4c3f446e05b6c2935f2c6ac1810c196843baf73b3a", + "openhcs/core/function_step_document.py": "9991a14903ca5160e96bc268728943fd524c55896ed2e26825a3639240e0ec2f", + "openhcs/core/function_step_transport.py": "b4c89539ace519926d178eb85a7909b4a7894203bf340213279e4f2a11e1152f", + "openhcs/core/image_file_serialization.py": "85f20b9939ea01b772fd95fd24b4cd82f02d3439f7257b1860f20275a86464cd", + "openhcs/core/image_payload_execution_mode.py": "8fef20a3abe5e2812d5f0b6906ac758ef1307504af282f4ddba54737ef6a6229", + "openhcs/core/image_shapes.py": "42b27a64f00186f337077debe1e9f78c2093380bff878311bc3ec36e55d3cdda", + "openhcs/core/input_workspace.py": "657ecec0cd1bc822ae0f9595616d857e893a5e35757e872ed83356d1e195d5b4", + "openhcs/core/invocation_artifacts.py": "b90ab5bcebbdda757be3c60defaa0b17b738dab1d0f3b691790cef3a50591abb", + "openhcs/core/lazy_gpu_imports.py": "6881f21a00325c457e46b55865e610c8402777a22fa73540a3437cb82136a6db", + "openhcs/core/log_utils.py": "51be2e790b1abd551f9adaef2dab7bec31c34a7bdf78cf9977948eb525783ff8", + "openhcs/core/measurement_feature_queries.py": "e9e2188a7edfc9fe25b08b0ae2cc576d4960169beb0fa053d59d6544cb0f8240", + "openhcs/core/measurement_image_alignment.py": "c97a6e7c8c16cf0b399aa9bcb202c0302dc7f8c726faa0c4323432ca6b188cc9", + "openhcs/core/measurement_lookup_dialect.py": "0c9765ff7f211fe3e766f6c70f22e1e3f3b6a6a6403c3c0685a44ba40d177b46", + "openhcs/core/measurement_row_materialization.py": "2e92a6043937e1eec272b8de1edf5a2d3bd349e3298e432c69a679ee066b8189", + "openhcs/core/memory/__init__.py": "9d5223bda2ace85b6dfb91b0d510fafcbfe6fc19c99f6e2f9c4325dc0d295f47", + "openhcs/core/memory/decorators.py": "d9f9cf0be7593dc0ebfc57f258aebed75bcf9cfa508ed1e942137366d819766a", + "openhcs/core/metadata_cache.py": "e193f1c2737b14c7853bf0d436f0323f1f774d1f941d716dad177ae02dbe9037", + "openhcs/core/native_threading.py": "7f940589bf2ccec524b17081cdc39706b482377d87c114484d731bb59a1bf4aa", + "openhcs/core/orchestrator/__init__.py": "f274cb783cb5b8ce29d7353a80ef7b0ff25577e73b0ff2e328701499e0cd1f9f", + "openhcs/core/orchestrator/analysis_consolidation.py": "3ef9c20c347c1ac724353c84b24f9d7e13513aba7b9c5c01e194171b7e72bb52", + "openhcs/core/orchestrator/cancellation.py": "f825b602fb020a23d602e1f93ed9cecea881eca16e07882fd7a91ab519445244", + "openhcs/core/orchestrator/compiled_plate_execution.py": "ccf1670c632f6bd188881850b09625f1d745b31eade22e7713a13bfedeba44f1", + "openhcs/core/orchestrator/execution_result.py": "21a22fa7aac7f81522d1a391d7faa6f07271c294dc754aa177fe6493c394dc42", + "openhcs/core/orchestrator/orchestrator.py": "ae64fbf28c96f7672fd389b4647b96b11b0b90caccd28e542984692e82e2baf9", + "openhcs/core/orchestrator/worker_execution.py": "2bf7e0b7a1f7df0682939cfdfffdda53825b55bc34bd65269f8c74baeea8b23d", + "openhcs/core/orchestrator/worker_lanes.py": "2e2a17b52e06f692c924554c387ed7aed9d25b3174c60e69d28bed6906f430b0", + "openhcs/core/orchestrator/worker_profiling.py": "c2e51f5a68288bf75c937039d748baebb4402b8bfb5a5f1e2428d7d50a16b7b5", + "openhcs/core/path_cache.py": "59be89822548c957c7b9a22c6232586336e89a847be8ba13adcaa743c1a4b59b", + "openhcs/core/path_pattern_matching.py": "4d3db470c9e55fba2ddc834c145622f3dc88c9f31031c6de8e465563bd7ff8ae", + "openhcs/core/pipeline/__init__.py": "7610df23184cef8c93dcae8f1a2a23cf6370ce00530f78852725052ac478eff9", + "openhcs/core/pipeline/artifact_planning.py": "64dfd5d3e43c2a9b0603b0b19b3aecdcd7f615f8ac6f990ff121dcf7cd2a1b62", + "openhcs/core/pipeline/compilation_session.py": "3c840a89baccc8665d415175458280fd904c1a837b7fd879e303d7dbca129a1c", + "openhcs/core/pipeline/compiler.py": "f9c368f046fd338ae51ee46251ecc24f4b246b00971db423a1f14fb4d8ca4a10", + "openhcs/core/pipeline/framework_device_assignment.py": "f77f3fb2d30c4af8cab6210dbe294f9fb5e246dad0a6bbf88bcaf1e2b58dead7", + "openhcs/core/pipeline/funcstep_contract_validator.py": "73cb5250a5855625903f8b7deada667b83fba594d66de0ed4a68ec76afa3db19", + "openhcs/core/pipeline/function_contracts.py": "5c002873e7626af0376429819a66d2f170b9d8a220ec5c95f085218b668ec997", + "openhcs/core/pipeline/materialization_flag_planner.py": "a492738dd5ee9525b9a9873a2c08f6fe6a103015973a95005a4fb71a5f88ee17", + "openhcs/core/pipeline/path_planner.py": "6a73e774ee8032adea60adf83e74f61cd00380d14eeb113e6bd38e3ca765b316", + "openhcs/core/pipeline/step_attribute_stripper.py": "1aff2f8e6ea87b326c36ef094339e76e4efc784a02ac24f504c712104599a6fe", + "openhcs/core/pipeline/step_snapshot.py": "d81a70b84d5c68fb738603653516d20da882fb51d74d41a6dca238823e3279cb", + "openhcs/core/pipeline_document.py": "0849800b3e6474b8176fe35bc4aaebc63cfa85bd77251000c50da5f4c928b1b2", + "openhcs/core/pipeline_document_fields.py": "81178547c9d6d9a4e78bcb9e5764382ef9961afb09392c1464aa24a9dcd20d14", + "openhcs/core/plate_file_inventory.py": "1402b4f61f756375394409825d9705e996d516f62722998f119a2363f4c8a2c6", + "openhcs/core/plate_image_inventory.py": "49f02284102099abc34649b44934236b80f58148193b32db481b2b7183b9c972", + "openhcs/core/process_local_cache.py": "dcf37435ca47f4ea656e6148ba47713358943a089a927fe1949b6e667c948bea", + "openhcs/core/processing_preparation.py": "6271b4e32e6850ebe2bbafacefae191f64d9be07c34e06599bfb8486995b21e8", + "openhcs/core/progress/__init__.py": "705c78e3d79c50e25e7975f78a17ce663f063cd5752fae8c19b917ab8e9ad31c", + "openhcs/core/progress/debug_projection.py": "8a24e00b68351a1d77898f057ad0790c043e1eeaf12f21b593ab6996b9996902", + "openhcs/core/progress/emitters.py": "632edadc1093d9842d672a91b1e032f560815176ed576221668f91454190aaf8", + "openhcs/core/progress/exceptions.py": "1749f46adf2640e13e8805e32a375415105a4264db16df1e08c68c8a9da83516", + "openhcs/core/progress/live_measurements.py": "59d59c085c61eaf003ae0990d0e6d9cb06e2a37693b4edfb826fcacf0babe485", + "openhcs/core/progress/projection.py": "f07ac1c460d0761c2b70c834aae57f77994ac43bb3ef5cd688e4196ccc5d9fce", + "openhcs/core/progress/registry.py": "1925a97b9cdd6a4928c16e03bad5650b2d233426ec07a913a843c7eb543db709", + "openhcs/core/progress/runtime_artifacts.py": "452f0cd11f29ce5479086bbf81f9eea35b7454ffdcbc231a30d64f3f3ee61468", + "openhcs/core/progress/runtime_tree.py": "ec56720fea831cd358db8bbf54fac1868e9153dd56c332435633a7e2f96b96c9", + "openhcs/core/progress/types.py": "88755f8f54afdfe57288c8fd3924b8f1565cc973d80ee5568730832e1decdfaa", + "openhcs/core/projected_image_output.py": "fb14bc276442873f1a9644a566a8a9423b82438e442cb985b58fce98dbc36fde", + "openhcs/core/public_api.py": "4b98d01316612ccba6735b8edd6130d3da01d6244af51548c5e5e0945dddf54a", + "openhcs/core/python_source_literal.py": "82fea2f1fde28ca9227298c41f8bb10220d07d77ace1613445b5a8708e5476e4", + "openhcs/core/registry_strategies.py": "a41186665abbd308f224d0bb41d6618cd9d89b08acaf54ec2819f2024a6e0804", + "openhcs/core/roi_point_metadata.py": "cbb84911bdf766bda2dc1de1d8fea1c3b328d521c19e0f9a8bd3d2d006b4ad01", + "openhcs/core/roi_source_metadata.py": "aebf51a085874aaf125ad337b268a520382cd21569a278815bf3732d26f83781", + "openhcs/core/runtime_adapters.py": "6e468623ac43282989f0bfcfa31e3391ad677786cea075d6899d32b37583e260", + "openhcs/core/runtime_array_values.py": "52f1fdf015b263affa73ece768e765328a08db81a8d48e2c033c56849d31ad07", + "openhcs/core/runtime_artifact_queries.py": "a7b8e28660b483a457f0dc6e39095f560738aff92533056507e7bff30508424d", + "openhcs/core/runtime_artifact_values.py": "83c8de2f8456ca944306d1019723fb9e90a6add55596cac273415701a6d2af3f", + "openhcs/core/runtime_batch_contracts.py": "146bf643d5232d61a085ef049af1ef982d574d1ad7ea28684c1b955d61e08966", + "openhcs/core/runtime_equivalence.py": "e62f640076e8703195fb4fa5b4196e0958f12e4086515168b7aa3a888c3a42da", + "openhcs/core/runtime_execution_validation.py": "3a485cd9ab033f0cadd718779dc0b7a2efc6749d6bf5e24afaacecc84f4bff95", + "openhcs/core/runtime_exports.py": "568671497b2aeace1593e5908f376df0680992e341292f5bf14fae0cdb957808", + "openhcs/core/runtime_identifier.py": "e558552d0a788707f6e53b7a16fed7028696cde0e61b3fd340a1b4064aceb8cb", + "openhcs/core/runtime_image_loading.py": "4c6e09f3268380ab078a73b8d4c8db4e53583aef9f047c8786edfe1fd3f105d0", + "openhcs/core/runtime_image_values.py": "13f6df2684aceb604e6475850b6dc7dd6455cd36a5e700c55bf25d4b0a271829", + "openhcs/core/runtime_measurements.py": "7e8735b96a0020fd3971282d0e9ffeca76bcb6e8803e8eac8945af2a7dfc746f", + "openhcs/core/runtime_object_label_aggregation.py": "adec2b552206f022d16848803dc6a8fd07a4b3c639ddca37255bfdb30fcb25dd", + "openhcs/core/runtime_object_label_building.py": "8f77125b439d643c6253323486d7499733cecff87456d3dddb135e89cb592d7b", + "openhcs/core/runtime_object_label_domains.py": "32824678741c1caf3fbabe621619d6d8d463936a28bc2d689916ed69fa7582ed", + "openhcs/core/runtime_object_labels.py": "3a40ced06c46ec4b1dcae778b3e4a21e3606ec0c404b9ca541ef0e31538f3a02", + "openhcs/core/runtime_output_matching.py": "61ec75c36fd1d2ae588667327df2a1ccff020e35104bc583941d85b499e6ad11", + "openhcs/core/runtime_pattern_cache.py": "4ee015704ec0fa7414b352b5e7081c9a20a56162a09b4d14d19b80ee84d3305f", + "openhcs/core/runtime_plane_projection.py": "52008bcb5f919d4d69cb7c8add19918e62ba676490d56c830c73f30e0170fb05", + "openhcs/core/runtime_profile.py": "0f5dbca26d999898005bbff8d36d72004c637d1c7b20c3573be41e718df4a3c7", + "openhcs/core/runtime_relationships.py": "98e7834b43157d73450871b9a338405a027d21909179259c3377874011ea4e7f", + "openhcs/core/runtime_slice_alignment.py": "15b38191a3099846eadd63d7aeb1a322ed8f323840a82b1882bf3abc1e8daf4d", + "openhcs/core/runtime_slice_projection.py": "cd6c7553efba0838205f153e96b15570c285894e304827d8c3f3d0c38de664bd", + "openhcs/core/runtime_source_binding_cache.py": "a96a806e61afb93fe7515176c07b7d36f5df0792354a9d6379f701cff23351db", + "openhcs/core/runtime_sparse_labels.py": "aa5128f7f743a1a99011b1418aed5d6cfd3df3a82509e04d3cc03f936105096c", + "openhcs/core/runtime_spatial_graph.py": "b37a3c8d0acf530322e85a58f10607d962623044ca31eaceea090ca1a66b5e29", + "openhcs/core/runtime_spatial_grid.py": "0d7b0e785a417332bb3269bf339adf38b0328d6bc61d4c44cbb25a9ab8e031be", + "openhcs/core/runtime_stack_cache.py": "5bcfd8292feabca891c5a3997f75907f82ee51d151aa0df0825f0c5a8b460662", + "openhcs/core/runtime_stores.py": "f7bf2a9562065ceb1d68e10438724096c1da880c6f4ee8ed2c800f876587ef5d", + "openhcs/core/runtime_tabular_values.py": "51f0d628c7cc7fe73de77573395fc23aa3cf37b2f5f0b441cfa77f39a816398e", + "openhcs/core/selection.py": "da2f314e1c642cab0e1bbd75d058f8697c9c3e86d516e15c27689469668aef78", + "openhcs/core/source_binding_context.py": "ec0e396e5d8bbb702c8afbf470498252f2388959a081a870a3f4bd1dc620bca8", + "openhcs/core/source_binding_selection.py": "798a63c98fa702236860501d53f011377e8c6ed16f2b6cc4929f7217c67da06a", + "openhcs/core/source_binding_workspace.py": "4d994eaeec43135c203dce923453e75945b17bef345833c8d3b799a82a10d986", + "openhcs/core/source_bindings.py": "ef0b856fe1532d96afb155784f9b8d189878022a886ce655f93a0ba53e2b4416", + "openhcs/core/source_bindings_view.py": "0be0d846901920153f5675019817e96d1fe7faf93bf7852adab75eb45da80472", + "openhcs/core/source_image_provenance.py": "6e9ee8f83c001fc6322925b58974f9baeb931be1ad7b4af9118fc0537c108ea0", + "openhcs/core/source_image_semantics.py": "c0488e4c7b36d10df2abe730e9002e7ce82f0eb9473148d3d56f64ca9ec09075", + "openhcs/core/source_load_plan.py": "68d26b074c2b790b820d1f723d4c1ada1ada06a6c600a2084bebaa30a0602ce1", + "openhcs/core/source_matching.py": "128e3b8be9ef3c24ebe357a385a1ca6685cacdc83545bd2dd362849c1dcf95b3", + "openhcs/core/source_metadata.py": "1e50821c5f9d1e5e4bf5873d6bb37882762af1f51c3b4b1a7a26dc7485eb2a60", + "openhcs/core/source_path_identity.py": "191955b43bc53ad4b67100e0f99359bdbbc219e911881288a3470fd700d4e45a", + "openhcs/core/source_plane_alignment.py": "a93d4ec052503e2444d2cf199aa3e5b7920ce3ae233182dfa1d67e8ea1fe4c98", + "openhcs/core/source_projection.py": "e19eddf96d814919f025ff93ada0258765ed382ec0cad2a50d45f8dcf8de2a84", + "openhcs/core/source_spatial_domain.py": "c4a24735f8ff64ca47e0fdc648b40285aefa588a48d99e72cf461526d61d2c2e", + "openhcs/core/source_tile_geometry.py": "d4d4ba711f381c3344365dccba2d729472809087605021783d371f9a21d4dafa", + "openhcs/core/source_workspace_projection.py": "1e54affed309fbc0d150bee4a3deedbc127aedf39a83f0c8a0eaf719257922be", + "openhcs/core/step_dependencies.py": "2be2f66456617fc0a1c9c86e1133d57d792dcd4988adf62960f5fb499d9cfb97", + "openhcs/core/steps/__init__.py": "fa096bcf410393eaedbf5f173ab36e5997338d652242302f17952b5da483ae8b", + "openhcs/core/steps/abstract.py": "fd95ca754bb8abcb9e40c57d228edf2bdfb5dc496cd70428509139261acd4540", + "openhcs/core/steps/function_artifact_materialization.py": "954aef8ac570544ad9654d0d27b2d65ce77f8973d4ab63d6eb96971a1c2849c0", + "openhcs/core/steps/function_execution.py": "2b0c959058812c1ba79bba0aafc41417697894fcea56e5469b1e088745975160", + "openhcs/core/steps/function_io.py": "94b789a8e0581fcfaa6862a0a7cc32c54d6696bc3792606bb457b7ef16b28b8b", + "openhcs/core/steps/function_output_identity.py": "c3c1915ef996e0dd0eb8d8d43135bdc43c461da0839bc778195e8b0ff7565d3e", + "openhcs/core/steps/function_output_manifest.py": "bebb7f1355f63c05d8a4e765919ef7184e0e0377f88e244c7d31d561804cd0e9", + "openhcs/core/steps/function_outputs.py": "d68819e0acc3af1e62bfbbe83b2dc39443207fd5de0c5a0e8134a3fe4faa83ac", + "openhcs/core/steps/function_runtime.py": "933b9102350f72a4d12842d9a2482c6f296f85ca27579443d5552d3245afc344", + "openhcs/core/steps/function_step.py": "8e1243404095691030e9ebb95bb5611679f96c66c6b6819ae71e4b41249e74bc", + "openhcs/core/steps/stream_component_semantics.py": "d146326d65514e377bbc13c0ae584ff11075c1cb54c7a3b62ebec6be40b1a05f", + "openhcs/core/streaming_config_declarations.py": "96ad52912439f8dd6b395b73b041313243f86f98f60eff8a2c3d43f97c7be340", + "openhcs/core/streaming_config_factory.py": "5a3b890539e368f9f5865064dd2ed13e98ef7a8624bcec824053d5b5b714ff24", + "openhcs/core/synthetic_plate_generation.py": "cba8fee5b39a9237883032e2a87facbbde943149f1108062056c78ce058c8378", + "openhcs/core/utils.py": "a3f2f2109a1ae97231d3cc5d00bb1eecf38746190dde0a68c4aa426216cbd59a", + "openhcs/core/variable_component_stack_requirement.py": "0f34c6ecb44cae29266e6c572b80c5393ef588a144e215fa3fe135ea29f737a2", + "openhcs/core/vfs_protocol.py": "b05f57cdc1bae7f6e3cf7b0ecd9ee1a409b865ef864fe067d822e7dc1df06a69", + "openhcs/core/viewer_streaming_service.py": "6bec8b5cb7052d118d7d44fd308721bc055dd48c998565728bf09ad0c1fb556a", + "openhcs/core/virtual_workspace_metadata.py": "25987be96327dadefa1ecb63a93b2678a0957ffdf42383822d02ef666282b24a", + "openhcs/core/worker_start_policy.py": "9493c8729ddfc7457a3a58efb605457d5aa4a54cd42c3f4ef1bd9f28593d9475", + "openhcs/core/xdg_paths.py": "d015a57a46b0052a717d03febe00065041200c7adf079639aa1ac887c24cf45c", + "openhcs/demo/__init__.py": "524c01ac2742f060b054cca816e01b0e4068fd21e5e22a5edd20dda137bd33d1", + "openhcs/demo/basic_pipeline.py": "cf31cabf828a26b7b9448d1479b262beadb3c5273b054f57e953b1663c15897b", + "openhcs/demo/synthetic_data.py": "5ff0a12afcb4e52c2cd27e5a458d33af50d393464bcb5be7e7ecd956a9b58fe5", + "openhcs/demo/synthetic_plate_pipeline.py": "3f8916ff71938ac5b53c7f55329b037653519e9592cf564257f78dde158fbd11", + "openhcs/desktop_deployment.py": "4b8c03a5396050e403e312e4ba65ffdb8047a291255e974860e4720dcdea18f2", + "openhcs/desktop_deployment_cli.py": "02135761e1c5ddda4e0239f5d29f70232010a571c987a98aa95d0bf8286bc2f0", + "openhcs/desktop_installation.py": "244ade0711356f68df9f376e2517dfe1c9fb77cc960c517f7c4e8ee418b5711f", + "openhcs/formats/experimental_analysis.py": "a7067f2e1e0c016ecaed1d0bdc5ac2b5725213a53fb83b730e798fdd664ede9a", + "openhcs/formats/experimental_layout_rows.py": "69e1428d0aefe683f1ee1cf741f83915fbaa1318d9d3f19b8bf8120583d883d2", + "openhcs/formats/experimental_result_formats.py": "ce46b895e4caafec7d026112cacfdfc496de0cb4cd5978cceb94db02b98fe288", + "openhcs/formats/pattern/__init__.py": "eecd8dabd6c2dcc5d239ad51ddc7ffe37468ca8522daef4c40581f3082c752e4", + "openhcs/formats/pattern/pattern_discovery.py": "6cb2b2fc76aed22f816ffa5811a9f85c6c3a468f645d099793cde39ef3865e4b", + "openhcs/gui_startup.py": "c996f065ad2fc3569300df50b16da6c55ac6edbc50ee7ee4c01dfb75add5d77a", + "openhcs/interop/__init__.py": "72f152d416e5f0eb718840196cf58de2dcd42c9fb2088dcd09773d8390209414", + "openhcs/interop/cellprofiler/__init__.py": "af5268368a9f2ad084ed6ac979d02cddac68133a8999e62312d6f6240883e9fe", + "openhcs/interop/cellprofiler/analyst_export.py": "2c479a6da19278ae8686f1af0548bd1b800bf38112bdafad75a8e7b6233508ad", + "openhcs/interop/cellprofiler/cellprofiler_literals.py": "13481e1bf0bb20bfc075f69309cf8ee68093acacb301a88b548a8f63fea7a8c8", + "openhcs/interop/cellprofiler/compile_time_contracts.py": "901e7eb9a9f15766934ec7c596dd77d6e484773754c75690594b9abfc6d9a07b", + "openhcs/interop/cellprofiler/database_column_dialect.py": "777d3e6b1f381abfceee90a0124d289536447e06a65bc4df01851963bba67a9b", + "openhcs/interop/cellprofiler/image_normalization.py": "a840f237daecc63d9e45e65166fd5d0a91117a4e417134e5b1fd6971026a0e6e", + "openhcs/interop/cellprofiler/image_set_numbering.py": "5399510f6a3d14a29eb164f9267f13a4b58f81336bfd8c9968abe8191d403f8b", + "openhcs/interop/cellprofiler/measurement_dialect.py": "230a4b3cf11b0912404e2131f39ccabb580695a8a2143a1a61b439b286f1efc6", + "openhcs/interop/cellprofiler/measurement_lookup.py": "b2aa6fda40a250b08fa185db589c4bd4aa26ab5c6e2712540b632aa7deec0670", + "openhcs/interop/cellprofiler/measurement_scope.py": "ebdfff6cd5abdbfb8d63c50de5e120c5019c6a9ad8062e4badf1a4963fce6ade", + "openhcs/interop/cellprofiler/measurement_semantic_profiles.py": "7801213da58054a9036261f0d46b7365951b94a40d658e16ba41b6ff365358ad", + "openhcs/interop/cellprofiler/module_artifact_contracts.py": "bf2e8f6c66a181218c8fd9afa9132922e86295f65d6102d976e1b36e41e17ee5", + "openhcs/interop/cellprofiler/module_artifact_declarations.py": "c459a1e65a671e0b15e83edba097484d018c4e9236c0e4999565221072096b31", + "openhcs/interop/cellprofiler/module_callable_abi.py": "a8f8e932547bad8e4e729e3dd17a21e79ce1d1d274e04dc1afa0f30ad4178b7c", + "openhcs/interop/cellprofiler/module_declarations.py": "cf3a4609667545ef4a2488ec3c8059181e8c845c4a59fe3034b30ef9ea5fa8a5", + "openhcs/interop/cellprofiler/module_measurement_features.py": "71ea356075abf8bffb6bb6fd6765bdb12abd0f9c0856f76b5d6002a99c7693f8", + "openhcs/interop/cellprofiler/module_settings.py": "5fffa65f175d451149d85e21e9026e36d202e5e6693389af8c4ed336ebb64e4d", + "openhcs/interop/cellprofiler/module_structuring_element_settings.py": "b69e87503275df0f3d9efb70bd8557b665b09c96b83cca48b59e3091cb58fc21", + "openhcs/interop/cellprofiler/parser.py": "419aeddc3f14afc3836632de692a24c319c311e8f01b3795108411c91dc8f7f5", + "openhcs/interop/cellprofiler/pipeline_import.py": "b547c838b2c86fe7cc5fe12d6cbf6a6715e83055c2d8c1a109ac22566d22c51e", + "openhcs/interop/cellprofiler/plate_workspace.py": "d5ff490b1d75cc35b46d11c5723befba81836f442bdc2bbdf83e2fed06e54a94", + "openhcs/interop/cellprofiler/runtime/__init__.py": "9a300dffea57601e9fa252bdc78133166d005ba2b3a161d0b8e48946ab4d66df", + "openhcs/interop/cellprofiler/runtime/adapter.py": "864b31164784b522eb8f6d3a96f790ad89b68fdfd96f2d455751b62b3d178a71", + "openhcs/interop/cellprofiler/runtime/artifact_binding.py": "85736bb5a41300a80e0fddf31bd18774751ffb7d8732b4ff0d2a087fd6a09e59", + "openhcs/interop/cellprofiler/runtime/function_contract_execution.py": "6f0f837ca59465c20f417d43223f42dae89bdbe4e3342762c0dee71cfad865a7", + "openhcs/interop/cellprofiler/runtime/invocation.py": "73a2dcab287a921ea178f56c568abf07e6a9c931e3b7e1b7badde61151a0cda6", + "openhcs/interop/cellprofiler/runtime/main_flow.py": "80d9e06ec771df610c39f3e067705558f3e2e310d81cbbadb04a2159bcd1a76b", + "openhcs/interop/cellprofiler/runtime/measurement_execution_support.py": "4ab892633e9e9884f1ff9a5ce187af5f413d051fb992e712e4731514fffc7f28", + "openhcs/interop/cellprofiler/runtime/measurement_recording.py": "4f7e3ba835a75129a6e06b7d31ea7a5eb8744e2e1ca91d354f8504bc7e5c2b44", + "openhcs/interop/cellprofiler/runtime/measurement_rows.py": "4a7fa98ab0c7fdeff4c9b9d1339efe611a87274e28219451278c4296651e0160", + "openhcs/interop/cellprofiler/runtime/measurement_source_names.py": "08a66b4565d862265cbe0a4e569561c3c645635a3581103b319ce98a9f037219", + "openhcs/interop/cellprofiler/runtime/module_execution.py": "dec3c1afe05fc06ac63db6cd0fe128ac0ba4466165147e29f3b317af21284d26", + "openhcs/interop/cellprofiler/runtime/object_input_policies.py": "bb9eafd98a41436d50a587d2720407ff0cf130219cf1516f5009a5174236f30c", + "openhcs/interop/cellprofiler/runtime/object_label_measurements.py": "f20ebdaeacab0d75f417f1c052b8487dc52238e0de0773508c49d702b2ea8bd8", + "openhcs/interop/cellprofiler/runtime/object_measurement_execution.py": "a8628103964e9d94032c55b077bb971f3c953ba0e9342101b3c99c05815dc041", + "openhcs/interop/cellprofiler/runtime/object_measurement_row_completion.py": "af7ab246a92aff7512f9580ca7a30dad0ee58954dda576fac2fc3ccaa3bcab7d", + "openhcs/interop/cellprofiler/runtime/object_measurement_row_policies.py": "9f5b3bd6867f0cb44d9cc82df49354cdf9a863a22b7c6f91ae90dfe70d1f83a3", + "openhcs/interop/cellprofiler/runtime/object_measurement_tables.py": "a652af9f4ef679936696ee4064005202456651c0c68d4052104b05ddd5e40b58", + "openhcs/interop/cellprofiler/runtime/object_measurement_vectors.py": "55249bc7b43baff02bdd461787099d4a81eb7664c86a65a5b83c9abad97a372d", + "openhcs/interop/cellprofiler/runtime/output_contexts.py": "b5eb84a533cf816bd4c33498cf8ae9ded49f18d9a55f5f55b37c00b6ddbfcd61", + "openhcs/interop/cellprofiler/runtime/output_record_request.py": "89d0230deaf8b832c723cf44bf006cd36c863dddc401c382375015807400cd4b", + "openhcs/interop/cellprofiler/runtime/output_recording.py": "14e10a666ca99cacfb438c83b60703cd672aeeeb05d816062641ee17b7eefd56", + "openhcs/interop/cellprofiler/runtime/primary_image_input_policies.py": "0c7ee04723c4c57aaa1012385c05b1298db65e695d044f7620cd10477f348bcf", + "openhcs/interop/cellprofiler/runtime/profile_fields.py": "f7631160e7d2e6ea1a8427850ddfd8cd1f5b9dcf7396fd7c33a284e42e4d8bb8", + "openhcs/interop/cellprofiler/runtime/relationship_measurement_rows.py": "1c1e4c1a56a59d38ea54dac11a41976eb7031d1c814eef62013c3e5c90415343", + "openhcs/interop/cellprofiler/runtime/runtime_profile.py": "61a9f7b76f782cdba16e639c63380567bae09cd8598bd2ac4bccf5a4844c46fa", + "openhcs/interop/cellprofiler/setting_names.py": "fcbf8f7be0e03ae0751ae38132353c69429cdf04ffd56363f9e43be002b4414f", + "openhcs/interop/cellprofiler/settings_binder.py": "45406353419db00cdae6a10c000365e6edd16ef9e2b50844b4b022064f0c7910", + "openhcs/interop/cellprofiler/source_metadata.py": "ed84f0c70e46c1188ba609d0f8db07a18b6fa566611ead4bb706897542eff2e5", + "openhcs/interop/cellprofiler/workspace_export.py": "462419949f95f28574270d4ea5ffc7aa709f4c9ad8a03c5f2a406b3fd5d4f423", + "openhcs/interop/cellprofiler/worm_measurements.py": "c2d26f72f324b59425f48dab4b61431274c3c0634eb043f1759475a95a2cf144", + "openhcs/interop/cellprofiler_setting_normalization.py": "d422a6238cc40037a9f470b0455653cebc275bbaaebdb57f5aa5f259bfd1b753", + "openhcs/introspection/__init__.py": "cab4d93163c461120ecb99fbd6f5f0875f7a71b09f54a18f3db898fa56dcf6e7", + "openhcs/mcp/__init__.py": "490d5b7112a852639d475acb1d152c5364af161fd33e81e8d05c7e0e4eaa2a96", + "openhcs/mcp/__main__.py": "100cc2ba913c45566cbad083a288e1a12c2023604e1e7438aebde011e15ab283", + "openhcs/mcp/bootstrap.py": "0e8e94cf54a32a1772e52a77d1c89a9ee02c6d2a58eb04f6e18fad2ce79d0394", + "openhcs/mcp/client_registration.py": "2b42825cd36b65c90851c64f11473048fc27c0cd8ef2c0f3259b6380f92560f4", + "openhcs/mcp/context.py": "c2e9b389f5efe75c08fb73ebcd9d898e39db2b0fd1a71784b6e76f66bc4dec57", + "openhcs/mcp/control_timeout.py": "da74437a45c2c7bd3e249b202717c7adfd178433f667d60327fa513db233d0ee", + "openhcs/mcp/dev_client.py": "c4eb92e6b8bb64664269b8c35716adce222ff96712f9d0d9b2da211384435d6a", + "openhcs/mcp/dev_client_commanding.py": "7d7b8f3c18043fdf193937766056c98e89e096238f864cf50d3831854aa0f797", + "openhcs/mcp/dev_client_commands/__init__.py": "ca5ad2d6c1424b8707625674dcb845d8e08720bab007ac23ee9dad5432333a36", + "openhcs/mcp/dev_client_commands/knowledge_pipeline.py": "fcba2bfc67470f22f944a9642dda627ac17b2a9280209500559a5b8414b5e97c", + "openhcs/mcp/dev_client_commands/plate.py": "556622ecd366de7d2573f6a6390051deb3d01935514cc0f9210a7990e682abd7", + "openhcs/mcp/dev_client_commands/ui.py": "f0c849f26a4fc2f986c64c54f7dcfdf22ca5bc14295013edd794689b8c0105d6", + "openhcs/mcp/dev_client_commands/viewer.py": "9d854b05a76d67dc2ba4c4f0873a77b95630269f60d4564f4630ab1e4e3e572e", + "openhcs/mcp/dev_client_core.py": "2aaaffec501e901352192ed35016caa6ce00122b429e41b3f7c8683eb3fd1aed", + "openhcs/mcp/dev_client_renderers/__init__.py": "dff9c54099e9717efe6938f76d3b68d249c830213df114983db0d70e6cf7e8fe", + "openhcs/mcp/dev_client_renderers/config.py": "2477d75b0f8e73aa68c977cc712c53cda0dd48a584a0f47fda793ccb8ad74d5d", + "openhcs/mcp/dev_client_renderers/knowledge.py": "0df19b17d96048a8f6372193db6ede89a444383eec30a4c128f3ba79c96521a2", + "openhcs/mcp/dev_client_renderers/object_state.py": "62e6fc0bf3a9975eccebf36d4a9f18e52c9a1f19c947bfbab7540aa90590c355", + "openhcs/mcp/dev_client_renderers/pipeline.py": "58e4a2a3a4776a738791b70ac23eadc01032abfadb66353c2a2c2d1660ae6a4c", + "openhcs/mcp/dev_client_renderers/plate.py": "a17489fcfbb484c4fffcbc242d8fbf4942d7f2af148cce3af4ec5ee9803b48f5", + "openhcs/mcp/dev_client_renderers/ui_bridge.py": "a8a2b13aed35b6fb54f93ed42993fad6376176949f0a68c6df3e662aadd5a59c", + "openhcs/mcp/dev_client_renderers/viewer.py": "4d01b0968197ee693030df8dd79d3dd179594fce9c5bf2bd3cc0e76d26011841", + "openhcs/mcp/dev_client_rendering.py": "71928056a3cd0fbcc8705bbba53fc388ccad18beed7276d05bc2a74fa5b139bd", + "openhcs/mcp/execution.py": "7debd0155d1b822bc9220a5f0b4d6976f57f6142db65b749d4b6b9752452e067", + "openhcs/mcp/http.py": "56430a939d65607847486d417c693c91523bf5571cb969389c37ff917f4793c4", + "openhcs/mcp/http_auth.py": "1c2801842259c91a764940264e07ad5a05cc6492e42f04a841b0ceeb026d73e2", + "openhcs/mcp/installed_demo.py": "4ea6c0730db6d3938eea1cac558dd46ea5c956ef151a5d68b8ea956e8bf57655", + "openhcs/mcp/lifecycle.py": "671859916b91d5e2f4ce9c5cd329c6d088800d3b8282e0d9505c49c183c7c68b", + "openhcs/mcp/memory_diagnostic.py": "df7adf5331f3020cec231fe4156196c9088c43078586c3018ea189946e0a4985", + "openhcs/mcp/memory_diagnostic_launch.py": "4bf3153320cc0f6026e0f130084ff41d117daa7ed157908edda4c4eb95223c92", + "openhcs/mcp/server.py": "9755e43d18ea8913dd13e078623728967c5e8ce7eed27e8e2a29e50470e41c1a", + "openhcs/mcp/socket.py": "9ec9850cba0868ba6e2d88ac44031babd10d58603c440967396b8c859cfc904e", + "openhcs/mcp/stdio.py": "ec2935e01e9dc7c0ea56781c174f490528002bd736ac19062bd3a848f7397e7e", + "openhcs/microscopes/__init__.py": "8c02c109013bd33aa2841548a7a5ee1d241e11dc5e80a3afd83a87697f3f5f40", + "openhcs/microscopes/bioformats.py": "50df7ed37d246d424216acba266ce6a7be54a8242b3663e41597b0f414408597", + "openhcs/microscopes/bioformats_adapter.py": "6f50083a1261811fe6ed22287acff99ff01cc304f02640a43178e5e67bd0725c", + "openhcs/microscopes/bioformats_well_key.py": "2ebb92085fb6f1dee7b49e4d76dd6e9ea7f69553f7cc82746110829afbf93a17", + "openhcs/microscopes/exceptions.py": "5bfd6936b250e410c48999b13bd79d9213348bb76fd2e6df50171e0ebef7e763", + "openhcs/microscopes/handler_registry_service.py": "b90a881907e2b38fb15ff0b6220c2075107ab56bbea50aa4976709d27d01e3d4", + "openhcs/microscopes/imagexpress.py": "52cd1d7f8b585b602544e8dd2a278564ca5413cf15cde7dc5548ae133ffdd684", + "openhcs/microscopes/imagexpress_source_metadata.py": "6b621641236786eea64254c5ad71256e10d40820d79e894f8366fc4f8bf67cc9", + "openhcs/microscopes/microscope_base.py": "e9542540fffdf8944c584a351a63d6992381cd74ce231aa9b18617d474a4e8e8", + "openhcs/microscopes/microscope_interfaces.py": "cd5c39679bd41ce7805d2cf0cc66a98e7ef441e9026ec3168e625406b51f4223", + "openhcs/microscopes/omero.py": "341733257cfb4c3bbe35dbc311c60e1666d357af6c6b7dc416399f77a92c570e", + "openhcs/microscopes/openhcs.py": "0ee1d23324f21963f913d14136da2563f6c899a1a70b88785520a6c1be27dd69", + "openhcs/microscopes/opera_phenix.py": "ab2c732c47c4adada329b7d1e667a89ee1df667aab7e7182b9d582d67290ae6c", + "openhcs/microscopes/opera_phenix_xml_parser.py": "b80af276e29671a29fd4c710a12cd2727046a7164e4f1a1d22094d14d734f74b", + "openhcs/microscopes/source_bindings_handler.py": "efee19453c9f125e00c230170c0ccedf8e10afac8b9858430b2023a833f4eb54", + "openhcs/microscopes/source_schema.py": "7bb5a27358d82f770b62ba1a6ea443adfad5c6fd8289b6bc2426a2ccfab42fd2", + "openhcs/microscopes/tiff_metadata_mixin.py": "fc58d675d554db1b1ffe5653918c374eda6263e56fdaefb733f6ab7ebced7cd5", + "openhcs/napari.yaml": "a42e9d6288fd43d0855154e415eee0b998d120934754759c480e529c30bacafe", + "openhcs/napari_roi_manager/__init__.py": "640090b6aabd56c4dba6355eb3e90bfe1effab6c6804a57cd0c49e047b751e02", + "openhcs/napari_roi_manager/_dataclasses.py": "e46de1e7b34e98a0a3d39ed9f765a86d24872328e6ff155fec3b773e7938a566", + "openhcs/napari_roi_manager/ij/__init__.py": "3e0c566b0f58a7c153dbadc8d1d6baa9cf264d28f24f7573c8fbb4fb7925085a", + "openhcs/napari_roi_manager/ij/_convert.py": "95fad112389585ca91f808144249f1d1676ed3fb9b2e93a2114cec9ae00c132d", + "openhcs/napari_roi_manager/widgets/__init__.py": "c552d2cdb9cc9ef9469ec03771340a4b210f999b83182e08b3414e12f0284541", + "openhcs/napari_roi_manager/widgets/_dialogs.py": "dbd8208a9f09221d5585755795bc4c7e135d5566910cd2c80b8b7cb4aff3be01", + "openhcs/napari_roi_manager/widgets/_roi_manager.py": "9ae7518576902c4a6d0384e387a08ae73528b39cf3878039c1fc70cfaf6c8a19", + "openhcs/omero/README.md": "8d684ecc2990c93f3cf46d45ed7b15d68b478c3f0bdbbb6e11a67f49dd8e4ac8", + "openhcs/omero/docker-compose.yml": "42be16bd692852af73c92ab7680b8762cc0142c2b0b12bdaceb88317e6b1bedf", + "openhcs/omero/plugin/INSTALL.md": "36f346679688b62369b6246cf07409be659b1a037f6f2ba4a7e8dd84e88b4642", + "openhcs/omero/plugin/MANIFEST.in": "d1c67f527cc46fb6e3119a09130cc8be5d160d7c6314abeae5b1a1e35d5d30f6", + "openhcs/omero/plugin/README.md": "5257f97a9b39ade8c43e5824019924243785d971398f6fa98894e18cd129146b", + "openhcs/omero/plugin/omero_openhcs/__init__.py": "6bcaf437e9d2d1696972aa9266bdd1f05641bd1ad6e3608a60ef713a8a5ebf8b", + "openhcs/omero/plugin/omero_openhcs/apps.py": "405391087c0014ebac3ae8a1a8fb060bd90284f1e07988ca8b2d1aac18a8c31e", + "openhcs/omero/plugin/omero_openhcs/templates/omero_openhcs/panel.html": "2dbcd164bc4998c75f2bea9d31f392db5171a532cbc0b3d4870e7a9b4e3798e2", + "openhcs/omero/plugin/omero_openhcs/templates/omero_openhcs/webclient_plugins/right_plugin.js.html": "05bd03fea74edecd983d8221d7eae4ce44c0c3297d0bf21cec880c478d9c2ef1", + "openhcs/omero/plugin/omero_openhcs/urls.py": "062d2ea3134fa95d21b4945c03682c7fc26858e395422d038d0f5eb2fcb6cf06", + "openhcs/omero/plugin/omero_openhcs/views.py": "4ebf08b49719597c8991a0da558581c369da5ca8a6f885d25690407cb1e16b1d", + "openhcs/omero/plugin/setup.py": "4dacc99c1e497842d2b64199323d0a15e58abed4f05926c60026fdb1f323c2cd", + "openhcs/processing/__init__.py": "2e37d68e60060a6dc41b81b65e00e6ed8a64e39dfc6d623972bb30e41fc750b5", + "openhcs/processing/backends/__init__.py": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "openhcs/processing/backends/analysis/README_SIMPLE_IMPLEMENTATION.md": "d1e68464555e50d34bc185125cb4990ac98db1fa0698c98db1f5d451f171607c", + "openhcs/processing/backends/analysis/__init__.py": "2c2a87306df07f20daad2c37c81318b0e80fab9d3b25538ed722f54338a783bd", + "openhcs/processing/backends/analysis/cache_utils.py": "03eafe55a0739d73a6b08193e3ce17623ac6db4bcc980acc2eff636c604e717f", + "openhcs/processing/backends/analysis/cell_counting_common.py": "f76fdbc47aa26e37ebb5dcfc5c46b6a6ed71ee2c11ca0ac69bac802578a51563", + "openhcs/processing/backends/analysis/cell_counting_cpu.py": "f8ae9aec542ffe2587b70e2c2eae4d29c9589e7354c8b0296d11e2588257876a", + "openhcs/processing/backends/analysis/cell_counting_cupy.py": "884d218dfa6da9735afaf65258dca1dac015e59463d293bebd78f814f3a6ca32", + "openhcs/processing/backends/analysis/cell_counting_pyclesperanto.py": "8c4df721f6957ac724514874af63ec040837612e8cb98111234031fdf35d2054", + "openhcs/processing/backends/analysis/cell_counting_pyclesperanto_simple.py": "5262773b82d1c1cbd676c2277b3ac3784b06dc8f07818f5efa8e97c843a630ec", + "openhcs/processing/backends/analysis/config.xlsx": "3333fc392d79c86f80d1f973fa31463b97ad5a1649f1255af2ad460c0e0a4bcb", + "openhcs/processing/backends/analysis/consolidate_analysis_results.py": "aad546fdc069653d809f9ef6867ad2ae351276ea9ab66b377af7cd6ab2428d60", + "openhcs/processing/backends/analysis/consolidate_special_outputs.py": "30e2582946e21915ca318c5aafca8cb8cede94459d038ad6943c5142663bfff8", + "openhcs/processing/backends/analysis/count_cells_simple.py": "cf45eaaa771e40da20a549fd7b21e831a0ae03968623ee22d67c718a3edb5d19", + "openhcs/processing/backends/analysis/dxf_mask_pipeline.py": "80e5c5afc54ac1ea44b6002fa5401515cc907ebcc1de16525047026e5087d67f", + "openhcs/processing/backends/analysis/focus_analyzer.py": "a9570564cd65d7709c3cbffc05ccca5286284df267c25afa0e472f9064e1df9e", + "openhcs/processing/backends/analysis/hmm_axon.py": "be57f02e249bae5058d02caeea185b92721408a0c05689c7832e8f30ef71ec07", + "openhcs/processing/backends/analysis/hmm_axon_torbi.py": "72e2ffd288168a609ffb2d34943b421b51d6d0562ccafa52af350ff0f1eac92b", + "openhcs/processing/backends/analysis/metaxpress_utils.py": "8795c96a7d4355d363a742b495e770ce4805ec4f69fe0d131664fca4fea398e6", + "openhcs/processing/backends/analysis/multi_template_matching.py": "9f6ab5b607434b62012a37f0953e0b4f68e89699935c7792143fdaac8b535aee", + "openhcs/processing/backends/analysis/neurite_outgrowth.py": "af0ea1116315755200b5d70a9317efd1f52f80c87c702ce11a3a504bf95b3b16", + "openhcs/processing/backends/analysis/region_properties.py": "412b1801fdcb840c4dcf920437acffacad15475a0f470d943e1e0ceb712b8628", + "openhcs/processing/backends/analysis/self_supervised_segmentation_3d.py": "df7e482a4dd46923bae0a14e964451431b10419278d720ae3c12389d1f0fe19b", + "openhcs/processing/backends/analysis/skan_axon_analysis.py": "fffa146fe169de6eaf15c29dd34851bad66f4248a0231aee32df93587c93fabb", + "openhcs/processing/backends/analysis/skeletonize_and_save.py": "e3e6fb3d411e405670de1f10dedcc32ceea78031a62d25cd7eea7c2079d2ceec", + "openhcs/processing/backends/analysis/straighten_object_3d.py": "3f465c19f6b955be1a6d5b4489a5e9d3fe6bc74b3761fdd3447e08c3100b27eb", + "openhcs/processing/backends/analysis/test_simple_implementation.py": "7a629a493280086c72693a34a41136e88a75ba6d4f717e0497e8c732d683384f", + "openhcs/processing/backends/assemblers/__init__.py": "f76d402c04f7d29cfff92547798f16365b7742d3d2b7207a4fcbb6f361da6dbf", + "openhcs/processing/backends/assemblers/assemble_stack_cpu.py": "512503d7f505c6e71faed0c94105a5d68c9830b5c33d0c303a6d7ae5e346e943", + "openhcs/processing/backends/assemblers/assemble_stack_cupy.py": "79e19458c2fc53fe39d7ad4f25d099b0eb8fcbe4176f986e8930a43179f87c60", + "openhcs/processing/backends/assemblers/blending.py": "98edc98db410e54275f6b3f23fb5f7187ed11f7635faf85af7b37a4b34aa5d77", + "openhcs/processing/backends/assemblers/self_supervised_stitcher.py": "a84d4eebc9984fe18219fa6eaad77be2ae66ce48b96442f66512738ac2d5ff67", + "openhcs/processing/backends/cellprofiler/__init__.py": "9b53f15d83fb8ec5a855943931550cfbb4b726063ab630bd5ff2cd0354d52f5a", + "openhcs/processing/backends/cellprofiler/_backend.py": "7c22c49b8690d527d68098931124c18b54e514c0d0b9cf9ce1618eea737b8e5b", + "openhcs/processing/backends/cellprofiler/_granularity_native.cpp": "c59e6700c1e377bac257e51b82d4ef514be2e8f848bdb6ade486556be1877bd9", + "openhcs/processing/backends/cellprofiler/_preparation.py": "06fd520d5e443c7dc217f7a16736af8d39c86eb69d22f1e0f98fbef81701dcdf", + "openhcs/processing/backends/cellprofiler/alignment.py": "65c72c3d69c9516623ebf856ab45cbae8ecba866e7aa6c2bcde951c6ece436e6", + "openhcs/processing/backends/cellprofiler/alignment_mutual_information_offset.py": "0fda181e2f5b885d5eee1b55e85e55a89978c712d4bfbe2fa369c31c65d316e8", + "openhcs/processing/backends/cellprofiler/area_occupied.py": "45baaf2854980dfd769a3f8a581f6fb7bb75d0baea69236c5dac04da75745250", + "openhcs/processing/backends/cellprofiler/calculate_statistics.py": "f08ad4069f88245206e9f3876e6f45e76cb6f83c9f59fba9ee79a6d452d6dd56", + "openhcs/processing/backends/cellprofiler/classification.py": "eaad500708ccfb49403139f547d507d91381097221b0a726017e844bc414c4a9", + "openhcs/processing/backends/cellprofiler/colocalization.py": "1a076dd40300e0e388b91f9c6dd4e6bfa23b764d4a507f97ac6a2d358729bdb5", + "openhcs/processing/backends/cellprofiler/colocalization_costes.py": "b085396b457621289bb5f1a5c6045b585b45378c2a724e57b4d9fd731085c2df", + "openhcs/processing/backends/cellprofiler/colocalization_costes_prefix.py": "50630037c121b95252598cac69440f576c72c11bb5c4583855a250255874b292", + "openhcs/processing/backends/cellprofiler/colocalization_costes_prefix_numba_pearson.py": "146d77121d04b23d9804bfc22e08613fd182e1fcb128f5b62bbe87f762acf165", + "openhcs/processing/backends/cellprofiler/color.py": "3abea177ce41b4bd14d2857dc5db2c203ddbf61a711dcfaec90d8f8e47aeee7a", + "openhcs/processing/backends/cellprofiler/contracts.json": "5343868a944862d8a256a3b49b519fdb985277597bceb6dc415fa863f84e4e6d", + "openhcs/processing/backends/cellprofiler/crop.py": "2dab13183d9e5387add3ac3df38fd741da08b6301501fde53f65ed4123e6638a", + "openhcs/processing/backends/cellprofiler/display_modules.py": "52d77ece478befef1d50118be55eec5094a64ac6c90f10ba290eebdf9f3fd29a", + "openhcs/processing/backends/cellprofiler/distance_propagation_numba.py": "12c4109952634010f8d2e1b8554cba21bb28cd0b6f925c70861081fcdd961be3", + "openhcs/processing/backends/cellprofiler/edge.py": "6521c2e854cc64b28cf6a373c023c01e3dab30e762487d870617669d01734427", + "openhcs/processing/backends/cellprofiler/edit_objects.py": "516b87af88e9d4f5c6179f3b247a867045bf73c67c032c77757d18ace4e03a5a", + "openhcs/processing/backends/cellprofiler/enum_attributes.py": "4645c76a44157ff8871498a6a473c0c77a218cf3c7bc46d5ba79d6e77a8790ba", + "openhcs/processing/backends/cellprofiler/export_to_database.py": "a191f39bca826a03e7736215a4e4e1c46b3233753729fb78804e0d6b0d43d7b2", + "openhcs/processing/backends/cellprofiler/feature_enhancement.py": "03cf091a3fe0c8b14ca343f2f40d5918519259a116d5a8a48dc34f8132c9dc4b", + "openhcs/processing/backends/cellprofiler/flagging.py": "e0c79fff08a470075b114c63e40d04aa45c280d8d839aae4f61308c96c06b470", + "openhcs/processing/backends/cellprofiler/gaussian_filter.py": "097845b6e35b53448f79559f19678d439167950f63922836351b347ba2cc27ae", + "openhcs/processing/backends/cellprofiler/granularity.py": "979e653134edd62a8c4bc898ea13071f5331ab90f99618c0616dddc4e0533ad0", + "openhcs/processing/backends/cellprofiler/grid.py": "df4aff3d02f6aa501d3a4bb452e0020cbbd6827f3321fe552d1161b0ac257f02", + "openhcs/processing/backends/cellprofiler/illumination.py": "10795d6c1ac0fd89da1f88433b44409d0298c35a94165f0f0653454a5c0eb3c7", + "openhcs/processing/backends/cellprofiler/image_geometry.py": "be8b4aa4700b17f3c987b2c88501589048cde0a62278a69e4b11d9111d736c77", + "openhcs/processing/backends/cellprofiler/image_math.py": "2c48fb8dd6f9ad3c9021e9d65029b698cf59d52f1a4c348e98697250fba6b9cd", + "openhcs/processing/backends/cellprofiler/image_quality.py": "46e5301b3edda6857d4b3d187b4aa7ee9ee65a6cb06561d5b616686d1af6b77e", + "openhcs/processing/backends/cellprofiler/imagej_macro.py": "36664137c90f896d0ff093e0ebcb7bdb4717a724ef2a899f3629b28e52c4922a", + "openhcs/processing/backends/cellprofiler/infrastructure.py": "83ba9be2d39e9917fbb4ce31ac010d17a3f16716ce22c52f3f41e46d5844b5a0", + "openhcs/processing/backends/cellprofiler/intensity.py": "ae55d0e21f3600d3f53e1dda76b70604d98997d5846f0b68d9fb67887321d55b", + "openhcs/processing/backends/cellprofiler/intensity_distribution.py": "e5a400a1cd6915701e72ec824fe6f2c16e14a266b0f184eb3ae1b6f154048a53", + "openhcs/processing/backends/cellprofiler/intensity_object_quantiles_numba.py": "f2cabccad8ee096b2b07f0a453ad558ad4d87eff42ae94c9f50b6386f1334ac9", + "openhcs/processing/backends/cellprofiler/label_geometry.py": "2a738fe2767b124a7c97d4d3a1d6f2968d94e398856248f21e6cf750835cf176", + "openhcs/processing/backends/cellprofiler/manual_objects.py": "0d3d38a91c83dce72aeda280cedf4cd90d3c4dcc2eef28595b9e4669eeb0ad47", + "openhcs/processing/backends/cellprofiler/maxima.py": "11c56a566305e73366b96c388a8c355cc47ace829b9f1be90f1e73507401011f", + "openhcs/processing/backends/cellprofiler/measurement_math.py": "2d7be24588e37955c687b54c1e62ed7294e78e02165ca636223666b9a4fd5472", + "openhcs/processing/backends/cellprofiler/medial_axis.py": "ec23045ed572a5a235043b7bbbaae40945f1e57894340cb41c946b2b92adcfd9", + "openhcs/processing/backends/cellprofiler/median_filter.py": "6f5957de0ecf774bbcf96611995c17c780fe3fd96685a01459f6da0052f56618", + "openhcs/processing/backends/cellprofiler/morphology.py": "bf52da0b5e8db68f613deb0bd5c61f76e1c49d6e6b8a8b1117c9dc6e4b0ea647", + "openhcs/processing/backends/cellprofiler/neighbors.py": "2768ecaf850ad3045b8aa3d6a9e0fd5550434407a732b066dd68cd5c19a6794f", + "openhcs/processing/backends/cellprofiler/object_filtering.py": "d80fab4019854fe51c9360c04f0256f42ff26486ce00814bbf7cd267a00aebd6", + "openhcs/processing/backends/cellprofiler/object_images.py": "fff4141d1abaa00dee3f9e2a8ea2139c84505c5b179be91a881c0cfd24f41e77", + "openhcs/processing/backends/cellprofiler/object_overlap.py": "86a30689e69dc7c10b3052e4f87235e3c878325b46f1a74e53651c881dedef4b", + "openhcs/processing/backends/cellprofiler/outlines.py": "fbd5eb9ca3134d052b0db8c8c198b9c58070b040f9b848c8b49b6a7f0a83be70", + "openhcs/processing/backends/cellprofiler/perf_fixtures.py": "917d4de46d31316837188549a200d8de9c8bbb937707f83cbb372740c2b48475", + "openhcs/processing/backends/cellprofiler/primary_object_diagnostics.py": "dda963200f7dde9f016ee0e45630259388718633e5d94142fdac5a41f18db867", + "openhcs/processing/backends/cellprofiler/primary_objects.py": "36d7a49313ae32e6382483ba58dd0fdcdc23fcf412d2059932bfd3c1487f07b8", + "openhcs/processing/backends/cellprofiler/projection.py": "c64d0e6f7895eac43454048310ac5fc11c1f1b06a5dd2d954e0c4e1b962e7090", + "openhcs/processing/backends/cellprofiler/relationships.py": "e79ebc1108b35c91727529763fbd4ca37643c915449e08eb161cefee58da9713", + "openhcs/processing/backends/cellprofiler/save_images.py": "43564b98f64151803363d78f131fbc93ab0cc43f2be1a0e9fe9e3c34f3470188", + "openhcs/processing/backends/cellprofiler/secondary.py": "0ed391a057e2a9c1b943938de3920119844b7f86fd6932e54227473a2d6329ad", + "openhcs/processing/backends/cellprofiler/shape.py": "1ecd193454bf62479cd13fee34245b85bf83e846f5a39f8057037ade10065896", + "openhcs/processing/backends/cellprofiler/skeleton.py": "fdf222ed7bcdde7e81d683ccd61c78f8591b11f625c6d285012e20c322e440ed", + "openhcs/processing/backends/cellprofiler/smoothing.py": "adf70be2e2564564b65c4fce855cd9d6e702486f419cca6870b2d3d45daaa23b", + "openhcs/processing/backends/cellprofiler/spreadsheet_export.py": "a641fd459a776b046a74ea01d5052a78a0556c4626995f40c492b7e6fe31e76c", + "openhcs/processing/backends/cellprofiler/structuring_elements.py": "9e2c173ecacccf14d282bb05e7fb2849d2172223245cc83a31dc3b4ba60fb749", + "openhcs/processing/backends/cellprofiler/texture.py": "fc55e27a4f5ac3e041c9a6ec4607b4c9a989b2cca9ac6714d618d89102ffcdc4", + "openhcs/processing/backends/cellprofiler/thresholding.py": "4ed28e53ec30580fb9558b94ad4c50eb17a59b61a4a516cf992b388fadf887d0", + "openhcs/processing/backends/cellprofiler/thresholding_threshold_numba_diagnostics.py": "06b9018424f4245c6f97c43d39481b0ac267d3bb6359417834cd30ba7b27a037", + "openhcs/processing/backends/cellprofiler/thresholding_threshold_numba_diagnostics_quantized.py": "6650d7e0f35538e8a03827443b377dff7b5debc941baaaec5228c3a81671ab42", + "openhcs/processing/backends/cellprofiler/thresholding_threshold_numba_otsu.py": "2e86d897437cdc22279da20ab442299eed93c3144bb2434efd188a396c837870", + "openhcs/processing/backends/cellprofiler/thresholding_threshold_numba_otsu_histogram_multiotsu.py": "b9362aa20a6ff625d9391df7ba7f267f67dbe8d8e07968df0668119f297a0f57", + "openhcs/processing/backends/cellprofiler/thresholding_threshold_numba_otsu_weighted.py": "a4a78bc16feffaa8a8dc80cb6d62f0a6aa93fffcd1be33c0fc058f47f9ffb346", + "openhcs/processing/backends/cellprofiler/tracking.py": "893f4b423272dcd95b28954bd4c84cf31021457ed2b3466a67ddf017ca3e55c3", + "openhcs/processing/backends/cellprofiler/watershed.py": "e6fa20e6964b8774d1667dde66e6c334adc0dda3ff855bb2fa601357a3af18a5", + "openhcs/processing/backends/cellprofiler/worm_geometry.py": "7ee66581908dd9a90f482e1612fe276af85632ff0175f76c9934a41fa300bad7", + "openhcs/processing/backends/cellprofiler/worms.py": "9a03e5d77e5b1113a72d5301cf07b17886287dbcbb1ac768b252142000ff8eec", + "openhcs/processing/backends/cellprofiler/zernike.py": "90582e0df2ddfb28cc2e3f0f2a2c22f8a3e113d2eb5e0924f906ab9d3665ddd5", + "openhcs/processing/backends/enhance/__init__.py": "7406b3f590f73fdb2876f41886644f8aa6bdf77d54de4aa44b4c3f0179c29da0", + "openhcs/processing/backends/enhance/basic_processor_cupy.py": "5fa49e3e7194f537400c1b217f480124778bccfd86bb68d4a0d385f956870f78", + "openhcs/processing/backends/enhance/basic_processor_jax.py": "510c08d8c8a8cb66623136d6415ebaa001898c9f735f6d0e5e05a399250ff84e", + "openhcs/processing/backends/enhance/basic_processor_numpy.py": "c238e0a82d8ac50f48cf23b9d8ffca6acda6145f567a3185ccb276850cd7c5ba", + "openhcs/processing/backends/enhance/cupy_clahe.py": "abd37da64bf7762f1295ec9f51ce5d2e3d4bb20a436eefd5abc2994f5f49e118", + "openhcs/processing/backends/enhance/deconvolution.py": "84744a86b0caf41e07a7cf85887dadcd2569b300eebe8d516a9f19a591b0667f", + "openhcs/processing/backends/enhance/dl_edof_unsupervised.py": "0cb85a866495ac53405046f4ad9ae0adf9494fa444ce96a038dca039792cc0de", + "openhcs/processing/backends/enhance/flatfield.py": "991122d1ae9c3367e3f96a92959e96d3a0a46dafde68978e2405321e1b3a1910", + "openhcs/processing/backends/enhance/focus_torch.py": "a8d95fb34f0a5672e594cfd025176e6e64e4805a98ae90446ded67c8cf2ba096", + "openhcs/processing/backends/enhance/jax_nlm_processor.py": "88f81ae0848d13416ce00eb1957d21d81b9d1cf9b0daf37869bf3ff6deeb64b6", + "openhcs/processing/backends/enhance/n2v2_processor_torch.py": "64ff854e1fe29c6b11a74862c25f249b029e39b1a30c63f31ce1b016f9ccd4f9", + "openhcs/processing/backends/enhance/self_supervised_2d_deconvolution.py": "ad6d8bc92d520913c4c97424fdc0bea7f177537ba52fd85a111c3ff6189b6cb8", + "openhcs/processing/backends/enhance/self_supervised_3d_deconvolution.py": "134980f379ae418af782aa35f6bda3fa258a52335927e1ef6f06178793a3d2f7", + "openhcs/processing/backends/enhance/torch_nlm_processor.py": "3f3f1871d7918b4b905fdc673d2221a80cca47adee3b0c41de3fc71f75381825", + "openhcs/processing/backends/experimental_analysis/__init__.py": "dffe49d8706b4171e6d137855aee097a04b6088da466061667b9f057a1d596af", + "openhcs/processing/backends/experimental_analysis/unified_analysis_engine.py": "316be268b761bfa74ed1df137f2ba014a1f1c273aa9abd598a8a2e10388afb79", + "openhcs/processing/backends/lib_registry/cupy_registry.py": "5c87a6556d6765a18340c1c07501883211af51e4c0a9ee672b48dc51ea7d26ff", + "openhcs/processing/backends/lib_registry/openhcs_registry.py": "7f3cc2715398b1a899925023b0dffe43a44b8244454245b94a608ff872fbd395", + "openhcs/processing/backends/lib_registry/pyclesperanto_registry.py": "9049165370dbea917e643395c516e08e94509777d9bf8edf9476cf1e75bccc77", + "openhcs/processing/backends/lib_registry/registry_service.py": "d9e6e30b627fae7b01e08872c58ad26ee060919b6b6bd9fd9174223f2ec5a95b", + "openhcs/processing/backends/lib_registry/scikit_image_registry.py": "21b71abb7ff213806c9a591f210e7c0f512432d321e53fe23511f73f02e896b9", + "openhcs/processing/backends/lib_registry/unified_registry.py": "e00fd8d09e6bc384264c19777fcf466c8e742a810b09d04b667ae524e45ee07a", + "openhcs/processing/backends/numpy_runtime.py": "abcd1ee27980bb7912326d97e0f4b2c4b32c15e4a04b1bd3bf2c95d2514fc8dc", + "openhcs/processing/backends/pos_gen/__init__.py": "83acad53ff4981191b792e0a5585131214d3ba88f03c9a88f2f381421e8455cd", + "openhcs/processing/backends/pos_gen/acquisition_positions.py": "c24035d60d123dacaa1a092db6fab359d1ee41397cb5e8256172a03d88825f35", + "openhcs/processing/backends/pos_gen/ashlar_config.py": "ec595c8681c1d9fdb1facde8e2b462ef1dc7bc8053d19be6f8f48b950037751d", + "openhcs/processing/backends/pos_gen/ashlar_main_cpu.py": "2b45b34f378be4b9a35cc4f2b20972467acb334d26acb20aafb16ac113378860", + "openhcs/processing/backends/pos_gen/ashlar_main_gpu.py": "ee135e3819544fff966f0a82b4722c9289e6665c77f6347690d7be86ed69cc1e", + "openhcs/processing/backends/pos_gen/mist/__init__.py": "a752dce85aa3a2bc49b7dda9c39660ef26848f22750d39eec68da2f4b106f558", + "openhcs/processing/backends/pos_gen/mist/analysis_notes.md": "cb4a6107383366016004c5e28300751efcd0167fbab91235fa5a15da2434e8c0", + "openhcs/processing/backends/pos_gen/mist/boruvka_mst.py": "97f19fcb0b98111011a057635250a4e21719462f8e9dc96857713d31aaa33cfb", + "openhcs/processing/backends/pos_gen/mist/gpu_kernels.py": "9f0a6a4f8371ce77b9bc69d0978684d28c57846b6440659ea44bbfd7ab1ab935", + "openhcs/processing/backends/pos_gen/mist/mist-algorithm-documentation.pdf": "addc2feb0c3a31a270029bc67a5f293a3e798af4e0629bbbd67784bd49754dea", + "openhcs/processing/backends/pos_gen/mist/mist_main.py": "ff886bfe2215b9a90d17da5c8517ff630099caf119d9b15c40e709529fa209a0", + "openhcs/processing/backends/pos_gen/mist/phase_correlation.py": "d7f709686739b344e9dd2b44c29c2a33cd8d2bdd5084d7e46656a67b8a8ce68b", + "openhcs/processing/backends/pos_gen/mist/position_reconstruction.py": "34c4f7d3367d655557ed7cb72acbbadbbe7cf71a36375f0b464da95a8c340498", + "openhcs/processing/backends/pos_gen/mist/quality_metrics.py": "7a738d883a4a97e2b2081fad191bd129d227e161ccc93a8306b1fbb906baea22", + "openhcs/processing/backends/pos_gen/mist_processor_cupy.py": "c0297a6b3d6297f3d995a75915b5d2bc0b3efdbfcff2535912b5f030def35f8e", + "openhcs/processing/backends/pos_gen/tile_position_artifacts.py": "58c43c34a10f5ddb573247dce518b9ab98a588a923d2dbc3f4834f73c3c334e8", + "openhcs/processing/backends/processors/__init__.py": "6aa79aa19e049fe5e801ca49577a6e7ed4e6c3c4f7560c8cab16b06918fc16b2", + "openhcs/processing/backends/processors/cupy_processor.py": "088c4527053db8d5137491d8274d2f75eddfa5d6d3475e5703e17b552ccb61e1", + "openhcs/processing/backends/processors/jax_processor.py": "8f34a67eeb2a74c12d8a1e0062c0a60ca73dc627e388782121d99f0cc9f63a28", + "openhcs/processing/backends/processors/method_axes.py": "21e4e9b0a1fb376c95b91c01bd5b893a4d958b656a5629f7788ea0b80360c8f4", + "openhcs/processing/backends/processors/numpy_processor.py": "7152a478305b90c7910b7068ff476cc8d1d0063c7be658f4c5e5e2a0650b99a0", + "openhcs/processing/backends/processors/percentile_utils.py": "6f36816eb0988183efbda89921a91d424451a9d7cf1a1adbb128cb7ce0d31edb", + "openhcs/processing/backends/processors/pyclesperanto_processor.py": "0504e1434a489005a1e0c3d7edeeb306acf1b4f9aba463e45ab0c817970a9652", + "openhcs/processing/backends/processors/tensorflow_processor.py": "3ecc376b692c94435f470dbd6a3066fade6e424f28dd620441e1c3921f8c33b0", + "openhcs/processing/backends/processors/torch_processor.py": "4323080152c5810139e09140477ab24de0b6f11f8205f20d2ae13e11d0767e77", + "openhcs/processing/custom_functions/__init__.py": "375b0fb11eabec55990307fc0b6d082e1611fc2a1ab9bed625d9835bb358ad37", + "openhcs/processing/custom_functions/events.py": "ed62fe7aef90d56ef4c3421d61257a272e9a54f7ec2005cc865ff0e605d8ea35", + "openhcs/processing/custom_functions/manager.py": "f2271f396ab4018ad24e4e8844665bd181bc8baef383499b7be60e9644b3c1db", + "openhcs/processing/custom_functions/runtime_registry.py": "3b1eeb412dbc5a61b1322d709680534e399bccbd697f133415308dde38200827", + "openhcs/processing/custom_functions/signals.py": "027020e7c3f3bdad0cec85b941afe86c471c11a4e6c2fe377e7a625b53ce0325", + "openhcs/processing/custom_functions/source_namespace.py": "c921b5dfb8fe1a59eb4dea180d45be64e962d5b49f58f97236e053da93d63e40", + "openhcs/processing/custom_functions/templates.py": "e114252a60ce5e57111519b98b44954f08733216335fab64413b643f5af61e50", + "openhcs/processing/custom_functions/validation.py": "245ed87136deb3176438f6c4d8d3b401c528bcbf8363a817c50c70c6867b794e", + "openhcs/processing/func_registry.py": "caed456f292f237e6c573fe4985b268261d4873469a0bb14f7e57be71b1fd7ac", + "openhcs/processing/materialization/__init__.py": "132f2a10933d539caf4489c4391fc9e305aea4b0ffa540699bc9dd5f71905b18", + "openhcs/processing/materialization/constants.py": "73a3382baf3ba00ef3dbcf0c02835e95121c76ac90944cf81a70cf324e7df4a8", + "openhcs/processing/materialization/core.py": "38bee7aa75ff14455c4de5e39dca0acfa36e438cb5fd8908980c6e5b0007e3a4", + "openhcs/processing/materialization/options.py": "d3936d9e52c4a1b9352e30ac6256a413d82c4cd807a9b65819e59c66579eba97", + "openhcs/processing/materialization/path_scopes.py": "2392cbe874f19d057855a29a70f0e039f224d53cc32d0cada5795e118b70133e", + "openhcs/processing/materialization/persistence.py": "c88ee00d398270f1d97aaedb3b1ae9d44c2e6171c9ef3549b2cc810c6701828e", + "openhcs/processing/materialization/presets.py": "6f1dc92a9a0a6e3693f96609044fa40234bf3a65059ac6ef308cf0cab2f31e05", + "openhcs/processing/presets/INDEX.md": "81fe902f5f0e0b02d02cc155cbd0c8302e76bd8462e17d6de5caf82b5ab1764b", + "openhcs/processing/presets/QUICK_REFERENCE.md": "251d1f4e5b890f102ab1f5def0c4bf40e1489bf347cb79584c0eca0bfb8293c5", + "openhcs/processing/presets/README.md": "1e829b16ac2883121b8d0d29c9352b1afd421284e7598ca58fb700ccdb5b2e8d", + "openhcs/processing/presets/__init__.py": "6fd2c1076699f05ff50423f75405f71a9295b14b87a061ee0d6261fd2f8849bc", + "openhcs/processing/presets/demo_contribution.py": "df4a0b83856e9b80a328f38a8677534d3874c7a6cda74c34c15d76939c35a5d4", + "openhcs/processing/presets/mfd_specs.py": "6f1808c7cecab58e3317bfa020db7d087947ed2e3b3d11838f11d47924e3a18c", + "openhcs/processing/presets/pipelines/10x_mfd_crop_analyze.py": "f375b0741b13bfc493092448f43756e80792057bfb94dafd457bf83544e8ab9d", + "openhcs/processing/presets/pipelines/10x_mfd_crop_analyze_dapi-fitc-cy5.py": "0893579f9e923dc3eb21af7df763bd458f5c3ee1cb97db44b04e20ca8b77a23c", + "openhcs/processing/presets/pipelines/10x_mfd_stitch_ashlar_cpu.py": "381536d37d958fb287dc0a8f3dd4e2ac6e6d25e789b6241d896c888b7646de0d", + "openhcs/processing/presets/pipelines/10x_mfd_stitch_gpu.py": "a9c5332782ab15e418d1a3deda2d177656041a623818bd56a6c8348c940a50f4", + "openhcs/processing/presets/pipelines/cy5_axon_cell_body_crop_analysis.py": "bdeef81988aaed1087a87e3b7ae6929efa8be608006fca9203a86e8b3fd0da62", + "openhcs/processing/presets/pipelines/cy5_ctb_cell_count.py": "e5d8f5c0f46622f195feb47d4a1350c43426dbee146c399b93632d009b6671d6", + "openhcs/processing/presets/pipelines/czi_brain_axon_cellbody.py": "7ed08d237d265ca438bf1966e2a649ce4868d6f0aa62a35a0c387d0dd77e174f", + "openhcs/processing/presets/pipelines/imx_96_well_neurite_outgrowth_pipeline_cpu.py": "5c1cf5b8343756dae9dad98fb257a9249cd8cc6a4a5de69a8d7c38d52ca628f2", + "openhcs/processing/presets/pipelines/imx_96_well_neurite_outgrowth_pipeline_gpu.py": "c4817f7cf785de126777124dcfe6b75415b664cc731f876b8a2107319ba6a3e7", + "openhcs/processing/presets/pipelines/loose_operaphenix_neurite_outgrowth.py": "46fb1ff75071febae663e5efa088590f579ccdd60e81a997476c32b07ddea491", + "openhcs/processing/presets/pipelines/loose_operaphenix_neurite_outgrowth_metaxpress.py": "8f18c81255963d346d5be6806eda63c39f1a0cbbdb97e0707484315b6ee6c19a", + "openhcs/processing/presets/pipelines/neuroncyto_ii_crossover_neurite_outgrowth.py": "ece248b4282000b14069ae510e3ccf0d8c18b04d194afb81f4537b31f3b8671f", + "openhcs/processing/presets/pipelines/test.py": "48cce18a46a115b8ef9038bfeb3e8d65ea50fb539193cc8d9a477eca0c0fc1fd", + "openhcs/pyqt_gui/__init__.py": "1c5e1b42fc81c7459bb0002499a3d0e69c7fd4d68dee94bbc352e918aa743c4a", + "openhcs/pyqt_gui/__main__.py": "aafd7f6f59b68998cbb3be82048b8746f9a55622b9b92b5f08eb035c75e8bd0d", + "openhcs/pyqt_gui/app.py": "3257f148dfddac3f1ff7409881db8100273adac5c3564b9cd3745e8f75313086", + "openhcs/pyqt_gui/branding.py": "acbd5b5fd51b0aeeead42f5086666661b353c78872095ee78e9f692452182e82", + "openhcs/pyqt_gui/config.py": "a3eece2e5b2926fc6fc0edd197221da451ab7c0d0d6f4ffc8bb2ff865ad74bd4", + "openhcs/pyqt_gui/dialogs/custom_function_manager_dialog.py": "fc67b871212b512661ebbf82641814194472bdc94febc67af85aa3f1e7eb2b4e", + "openhcs/pyqt_gui/dialogs/function_selector_dialog.py": "e11c456a5322038408edd42df7d2674cda42e1992f7f6c6e567e7923bf3526c3", + "openhcs/pyqt_gui/dialogs/metadata_viewer_dialog.py": "b9598d07f87a6a162897cddf6c9c026e073dc472cbb9bba2eae6f42299428770", + "openhcs/pyqt_gui/launch.py": "1bdada29836a4da092136673d8076a108190f239762a3cfec19384850f58326a", + "openhcs/pyqt_gui/main.py": "a156a006a3c40f43107b9b1f6ecb97ed150879eb88ded8ef89e25214309ae33a", + "openhcs/pyqt_gui/services/__init__.py": "98dd5e13cc9f391ac6888af66f633a93af8817e9d1a57f29758d61e2df738321", + "openhcs/pyqt_gui/services/code_document_normalization.py": "3dda5c20ba555311ac936b3be1ef021a90effe95491803de10d43f96cbb9e05f", + "openhcs/pyqt_gui/services/config_window_code_document.py": "bdbf33b254451945239bd1c1f256dedbed40d2a8c0e598c4426bcba939ab5d2d", + "openhcs/pyqt_gui/services/desktop_restart.py": "24ca24c3afc0038a268280a73ae7615045eb107ee541a59c13fcdf07005603a2", + "openhcs/pyqt_gui/services/desktop_restart_worker.py": "52d8a8f223d49dbd9ef42951fe507dfbea803b33ff4dfce3e198f4b1a9fe4ed7", + "openhcs/pyqt_gui/services/desktop_update.py": "42910339c4f11afe8d413dfbe024910a20ac6b275c563d1c6947452f8baec908", + "openhcs/pyqt_gui/services/desktop_update_worker.py": "c8d157ea5d61b5cb52f09f3835b430fe1ef3358822b988451e4ee2a6832729bf", + "openhcs/pyqt_gui/services/embedded_code_documents.py": "a1170ab0ccf1225c8781cd8a718c6109e96075a074745ed67d77d5db42615d49", + "openhcs/pyqt_gui/services/function_step_code_document.py": "3cb9ee3bf0411b0cd9ddf254934dd402de12abb630bc764cd724a9492f912814", + "openhcs/pyqt_gui/services/history_migration.py": "407452243851ccbd87f13554fb32c374a8abd84a0b9394235a4fe93b1a4223a7", + "openhcs/pyqt_gui/services/logging_config.py": "9cf2640115ea4add483834b345cadf9260ff4e9604357acdb977636b7fb8a667", + "openhcs/pyqt_gui/services/main_window_workflows.py": "74d3e4fa2dda4a8223c8d878aad55de9df78a71ff359c0b83346be991d14a594", + "openhcs/pyqt_gui/services/pipeline_object_state_binding.py": "afb190ac9ac38e800c8fe04497bbb78a2f1b6381a21eb14890e3061c61ae5b0b", + "openhcs/pyqt_gui/services/plate_manager_batch_workflow.py": "974aebec62dc0f283f92d8153594771d1206f02decdfd8ea5faae0a563676699", + "openhcs/pyqt_gui/services/plate_manager_root_state.py": "ed0e336a21c69e4845f3215685b593047b3892183945a0cfe237e9c8c365f247", + "openhcs/pyqt_gui/services/plate_manager_row.py": "a4f915edab3b46656526ad102242c50456916f85065f71669ce0c0601e77e708", + "openhcs/pyqt_gui/services/plate_manager_state_projection.py": "814651335543000eb3855975a80af311b6290926da233d02ab5e95ba0daa82ba", + "openhcs/pyqt_gui/services/reactor_providers.py": "e937c310e6dd7f06bf8e2cfc227ce442310f6d249fc0abed4ed0e588b4121fe8", + "openhcs/pyqt_gui/services/service_adapter.py": "518ba7df2494b97c6f79ececb58df24114083d95f250309a5096c5b2443a90e1", + "openhcs/pyqt_gui/services/step_scope_identity.py": "cbccdf20ee85e94c2aeef5d7cf925a645eb7f18c22bb78cbd29323b7ffb76758", + "openhcs/pyqt_gui/services/time_travel_navigation.py": "01edfbf4cc1ea78cef771968f1cf0db4e4e4631c47cb750d6d233cdf24bfa9f2", + "openhcs/pyqt_gui/services/ui_agent_bridge.py": "fa8e7a1cd300c6e5cfde5ac155d3e0fd0a7324632fb150280f57c828d8dfcecd", + "openhcs/pyqt_gui/services/ui_bridge_composition.py": "e7ff43261aba18f4b6f7444716e8614483b5c1286160029247484f42d58168e6", + "openhcs/pyqt_gui/services/ui_bridge_contracts.py": "7b61d3b568f28e01d9faef4f6314f56b2539f52748d057c4cfea3b309bae47ca", + "openhcs/pyqt_gui/services/ui_bridge_live_overview.py": "68302204a1e7d9d0cba2da20f50d98036d76daa5efcebb3652268a33ff1ad77d", + "openhcs/pyqt_gui/services/ui_bridge_object_state.py": "747c284c37e420092ffda9abbb8275fc7deaaff7f3676cecf3f5b1f324314744", + "openhcs/pyqt_gui/services/ui_bridge_object_state_scope_policy.py": "95d38c3dbdceaa1495da564ea8bbc2546cc5173680ee43d634b610bc75273b82", + "openhcs/pyqt_gui/services/ui_bridge_pipeline_editor.py": "49349b907d4fdd3ace506168b2d3fa7291365ce8cc4a0c0fb3c319d406ee296d", + "openhcs/pyqt_gui/services/ui_bridge_plate_manager.py": "66c4a64fece372937926ae4de3ffdafdb26491e801478127b163c1cdfe3037ae", + "openhcs/pyqt_gui/services/ui_bridge_registry.py": "f03f6f335aa56aab921c4471f4bfbcf1d39a4be8a11cd0a0b7f6bc425b05e26c", + "openhcs/pyqt_gui/services/ui_bridge_server.py": "667f582fffd4b489ca7274f8962a759c3d33d24b10ec8e6d1aa5cac01233b067", + "openhcs/pyqt_gui/services/ui_bridge_windows.py": "edb992542dffb88a9cc4557dbd6647b76d5b68584dca27a4c9486ef545be74e9", + "openhcs/pyqt_gui/services/ui_window_ids.py": "f58482c524d445b8297eb3116ec79ccb22403eb2f12dd9ecf6e27e154aa028c1", + "openhcs/pyqt_gui/services/window_config.py": "781408d9ce8e5cc9115ee7db0512d1d16a63dc6a6426707e5b9bdd0f78ec67c0", + "openhcs/pyqt_gui/services/window_handlers.py": "5080a81191a8cfc78ce826db7e241bd41d3df7607deea32128a06449e04a3aa8", + "openhcs/pyqt_gui/services/zmq_version_restart.py": "86d4bf273c75417b2c4f5c38ac83a66e3487bb233be88a608140a0bdb4c8bc67", + "openhcs/pyqt_gui/ui_tab_identities.py": "598bcfb97bdf4ed9671b84e390796e55b97836167c1d2c4ae9baf2df89f9ef71", + "openhcs/pyqt_gui/utils/__init__.py": "956321d3d5c6f226d69d17c8bd6943583fa2c230abf879e511bacd4816d92c1d", + "openhcs/pyqt_gui/widgets/__init__.py": "9b3362d93a343d8a9b9ed7d3562fb95ec63c58d15b7a7e049e131498e06d5a6f", + "openhcs/pyqt_gui/widgets/artifact_plan_view.py": "caa8d75207367831e61ce7586d1dd28eef7e8293a7d4cd7f4653e8ddeacf38f5", + "openhcs/pyqt_gui/widgets/config_preview_formatters.py": "67b2cbdddc7ef1bced7d549ce5bd29ed7222cacb4d8ea255476ec36f5cab6f62", + "openhcs/pyqt_gui/widgets/debug_toolbar.py": "307f1b5a3113c6286214037db9adc49abadbc0a10ea04d19096a7cc40a0a6d5f", + "openhcs/pyqt_gui/widgets/image_browser.py": "72610ea41c3573c46f83303543691df8fc8c3babc091032bb439c257b818575c", + "openhcs/pyqt_gui/widgets/pipeline_editor.py": "450d311712d032d2f811de28a618915bc7e8a7f389e9f23c8a12c3e6ae273206", + "openhcs/pyqt_gui/widgets/plate_manager.py": "6fa48fbcd58e47eb7132d5d9f86a002c6a0e8ff077d9654a03a791629e135378", + "openhcs/pyqt_gui/widgets/shared/__init__.py": "9089c6a140baa85367034e5bd639cb64978fc789bc196b819295a45e98151b04", + "openhcs/pyqt_gui/widgets/shared/openhcs_manager_mixins.py": "f380546421b12f0e5676faf7cf5df59d611dca0452890455c9e7d09eb41496f6", + "openhcs/pyqt_gui/widgets/shared/plate_view_widget.py": "d539dfd21a69c0e88d7194bd07fbdc8057aff65706188d7c8b9b681a1211bf01", + "openhcs/pyqt_gui/widgets/shared/server_browser/__init__.py": "287a6c5e32877fc13ffea0693f694eb0eaee3ea926fe2a27b58dc4169455b24a", + "openhcs/pyqt_gui/widgets/shared/server_browser/live_tree_sync.py": "81dbee5b7f471082bcfeb8ca63e753840ad7134aff7101fd14f1c821a121d1bb", + "openhcs/pyqt_gui/widgets/shared/server_browser/presentation_models.py": "1c41613a3760262a4f68c7f1301b40f24e6bbf9bcafeda44e9ac8c62f90da36c", + "openhcs/pyqt_gui/widgets/shared/server_browser/progress_projection.py": "4b9c4bd90fbe6ed4ac55f5fe1d23cf2a46c3a7f743218d685df8ac2f27be7998", + "openhcs/pyqt_gui/widgets/shared/server_browser/progress_tree_builder.py": "cc826076895f5cb5a7828d7c502ff7591d37124871c60b266ae4bcfa80dcc75e", + "openhcs/pyqt_gui/widgets/shared/services/batch_context.py": "7a502eed9e118e3c662c319c1cd2b740dde960e5427347579b0510e5a1e1e376", + "openhcs/pyqt_gui/widgets/shared/services/batch_workflow_components.py": "abd29f375ab12fdc56058f1c860ce26c3b52129658795eb1c95581d83b7480bd", + "openhcs/pyqt_gui/widgets/shared/services/compile_batch_workflow_service.py": "1b37faeb90ecbc326727bef124ba990a067dffca430955772f8f002356a451f8", + "openhcs/pyqt_gui/widgets/shared/services/compile_workflow_service.py": "e69e5b22686627f2f7794578f4439b15c4fde2b1ad1bb1af7896000603cb320a", + "openhcs/pyqt_gui/widgets/shared/services/debug_progress_service.py": "4eb10d47c39e9e5eab7557e6b6ab348a01c62c481aa5afeb3f63dafb1f044eb7", + "openhcs/pyqt_gui/widgets/shared/services/debug_session_projection.py": "09172141287fea46f3ebe560aa0fa3294a96cd3f265f2be65375b3a0a60f54c3", + "openhcs/pyqt_gui/widgets/shared/services/debug_workflow_service.py": "a92c75f6ab96bdc02a70dbd5908f2d02c03fb4de9b238a75d58c97f656b75701", + "openhcs/pyqt_gui/widgets/shared/services/execution_control_service.py": "a125648738de09f589cd87227c85c6b2dc724fa8afbd91226a664be224772b41", + "openhcs/pyqt_gui/widgets/shared/services/execution_server_status_presenter.py": "b3dccb164b0f64ae12003698770e114d96cedbe9863e36f16bb85c0d170a8223", + "openhcs/pyqt_gui/widgets/shared/services/execution_state.py": "73d03020ffe437d8aaf4b6a5eeb4f43b91130de747d411648cb7fa2e4df27777", + "openhcs/pyqt_gui/widgets/shared/services/execution_submission_service.py": "4a17389c654a72c8b3bee6b7740efda60183542dce492914c858faa8c45f1408", + "openhcs/pyqt_gui/widgets/shared/services/gui_event_bus_broadcast.py": "8ce46c251767078b9d7ee3ea306c2e48ede47e7fdc2a2cba331a7c73e69b2fb5", + "openhcs/pyqt_gui/widgets/shared/services/live_measurement_progress_service.py": "4cdda4296d2e9dba732dc0cfea1e26ab8f09cf70a4c275dd4bc52abf73697d4c", + "openhcs/pyqt_gui/widgets/shared/services/pipeline_debug_actions.py": "8b7d9fed1c024702ac2805c0196ec8ffa2efa92557cdec20cb8323fec584f76b", + "openhcs/pyqt_gui/widgets/shared/services/pipeline_editor_workflows.py": "6664126ac4daa851cacff5014e04a0c09a56bbc76f62661ff97d713e9137d447", + "openhcs/pyqt_gui/widgets/shared/services/plate_config_resolver.py": "b42ef47454d20dcbea8bf27af8021df09812449298133462c79e9160b5962436", + "openhcs/pyqt_gui/widgets/shared/services/plate_manager_workflows.py": "d640bf4b2710009dc3f92719ec97cf09fe3d93ed7eb1bebaf2b02913e8fafbfd", + "openhcs/pyqt_gui/widgets/shared/services/plate_pipeline_request_builder.py": "a650f77d70deeba55362b5b5f9a18de6026fe298f913aedc70a748d962d30295", + "openhcs/pyqt_gui/widgets/shared/services/plate_status_presenter.py": "316a89398b2ff343a0e8ca9ed35183ef0f6da2ac452eff7205399fb283fa934a", + "openhcs/pyqt_gui/widgets/shared/services/progress_batch_reset.py": "8a41bae88512e2f4c9e2d5f4c4aca3f0fb9c7697900b1dcc32f08286b7f926f6", + "openhcs/pyqt_gui/widgets/shared/services/progress_workflow_service.py": "2ac31ade9c7242af5033babd251fff1bba9306842ab93ea40ada2ebbdadb76bd", + "openhcs/pyqt_gui/widgets/shared/services/qt_widget_edit_commit.py": "67989b647ec56867db5c4ccb47614ed0ba78d9a7ee00fd02f0c84617578c73a3", + "openhcs/pyqt_gui/widgets/shared/services/runtime_artifact_progress_service.py": "9ea326fb30ab59494098a157e8b8b2e964e0a5b492ade84af9b82353566566bc", + "openhcs/pyqt_gui/widgets/shared/services/widget_action_dispatch.py": "f4a202513fc3b1de7684fb6a6d4857bdc0c1f8fa68b5f9309b304f139b063155", + "openhcs/pyqt_gui/widgets/shared/services/zmq_client_service.py": "f56f23fc860dab554584cb5fe44d29332c73f7bb7a650c167702efeb986363b7", + "openhcs/pyqt_gui/widgets/shared/time_travel_widget.py": "36bf88227b3e90247b1d0573a209f20b69179f22b51b1d713867108e84c05c9f", + "openhcs/pyqt_gui/widgets/shared/zmq_server_manager.py": "2d2d0ae9e70e04bc7b6c738877bc52e8a37e79a80a849e87388aea400b42977a", + "openhcs/pyqt_gui/widgets/source_bindings_editor.py": "acbfb6b1e86f2ec05535a5d242ce59e48c165c9d946a292c0d6cfa3754ea61e1", + "openhcs/pyqt_gui/widgets/step_parameter_editor.py": "54e0bdd74f8d781c2bfdf1da559bbe7e2393f19ef74826d374a2281e8eb96258", + "openhcs/pyqt_gui/windows/__init__.py": "2793a830be87aee341883bd160124e82b118c991c3ed9294a5e226b2dc46de85", + "openhcs/pyqt_gui/windows/about_window.py": "6d71ed291e59d8fe877189c1b1aef9f8370ae890201ab2fa395bcc4b6a69cc05", + "openhcs/pyqt_gui/windows/config_edit_session.py": "b6d7173ed6c9073bc19cb2d1f535e2b71efe0ec269d3e2bcb088ea500f564ca5", + "openhcs/pyqt_gui/windows/config_window.py": "5775ffba24066c78253af26eac51815deacbfc3922fb6d96fd3f8ea0c0ac5dab", + "openhcs/pyqt_gui/windows/debug_inspector_window.py": "6a5f62db6f9b55ef9e53c5b7b089f96fdad4eafe44e0e234ceca8489361bf9c3", + "openhcs/pyqt_gui/windows/dual_editor_session.py": "bcc8062cda516f9dfd72ecccb4f86c88b2ac3fbcbb0eabbd4880522dc316a036", + "openhcs/pyqt_gui/windows/dual_editor_tab_builder.py": "08fe16896ca3cbb7f4ba64e0115422c7c26fb538014e029d2f4a9f0dc907e1aa", + "openhcs/pyqt_gui/windows/dual_editor_window.py": "7aeb2af64e824d5c9749ee7ec35b18a2db303717ae15c37099e54ce0bdde17c5", + "openhcs/pyqt_gui/windows/help_window.py": "437c849f68698cd78d56e1fd11077d7740eb22233e7d2314cf0220f5618ec4f1", + "openhcs/pyqt_gui/windows/live_measurements_window.py": "0bdea475a11f6b062b9775b05253d21e8a2700099d84f5041f44c8e09891ea52", + "openhcs/pyqt_gui/windows/managed_windows.py": "b1913deeea6b83ec96fa350bebf8038425dd36f6d025a107adda7a33bce51e8b", + "openhcs/pyqt_gui/windows/plate_viewer_window.py": "1960f0c9871eeecded94dfcfea683a49fdc35e1ab55e5f5320a137f2d11d9572", + "openhcs/pyqt_gui/windows/snapshot_browser_window.py": "c8ca14502ddd01bae5c50b7eb06dadc9d52b5f769872e7c45a037db501b69efd", + "openhcs/pyqt_gui/windows/synthetic_plate_generator_window.py": "66ddba05885106acab8f5f9219665e8b611f50984b09c6a4e3408ab783685a9c", + "openhcs/resources/__init__.py": "3dd04dff758036aef8f6fe23354e84ab695039989b2ad26baf2b4f1c0c4ca028", + "openhcs/resources/assets/README.md": "27e72cb5601e7bedd4b795034058a024994364509d21c88f7362a1ec2da68323", + "openhcs/resources/assets/openhcs-favicon.svg": "43ba8aeb9771a218e64acb48769e30ac830430b80d41df444af558eea12cfa21", + "openhcs/resources/assets/openhcs-icon-square.png": "77e70b972785ddae7b7a3a33a7b341ebb105179c5b1df76179edc795398cc68a", + "openhcs/resources/assets/openhcs-icon-square.svg": "267c0d248f6eccbe670d1e0e830016f32ad0785246d90e0c0115afb59d2f9a79", + "openhcs/resources/assets/openhcs-lockup-horizontal.svg": "38b5d3dedc5d142fc162609b9066d5278402e51f57fd2e173e0d3a3281fc56dc", + "openhcs/resources/assets/openhcs-lockup-stacked.svg": "2168570ea95cd1db0223c7cdab6a77295e91eb4c79e8e7d1cd1dd034f1b947f4", + "openhcs/resources/assets/openhcs-logo-source.svg": "a2fcc12bcd5d42e93101e09b360535b853a7166a805ec6d3c5d2347bc1acad19", + "openhcs/resources/assets/openhcs-mark-mono.svg": "c9ab9202d1066d187231692074d5f957432925f12d84a322a5fd2c3d965a5ae0", + "openhcs/resources/assets/openhcs-mark.svg": "8b3357a275ea3233d3ce895a3f24c10144fd4f8e060e71d11d96880373eabd9d", + "openhcs/resources/assets/openhcs.icns": "cfa1313f13b552397aa1c815cd9ec56a3dd366074ce82d063b8a52cd9332f8a6", + "openhcs/resources/assets/openhcs.ico": "e5990ec4267ecd51a234886de80e034932a0d945004887bab0fcc6e248332c17", + "openhcs/resources/brand.py": "e810da87bf0cb643d5466b4858a5c006362fa7935b721bdbcdd5b3ba883c6793", + "openhcs/resources/windows/OpenHCSLauncher.cs": "0b581cdde998fa6f5b46eb85d89a11aa5688914ca8901c1b5e35b15d38870922", + "openhcs/resources/windows/__init__.py": "c7d7dff08a4bcb1e6d669829e5e8bae89b0d966c2cdc933fefb95488b4f3dc7c", + "openhcs/runtime/environment_provenance.py": "2bd3abb4682e94de6437b0f81cf2b3e6b7e4481cafc1d85f088b57e996b37148", + "openhcs/runtime/fiji_macro_runtime.py": "661d759c788112abd323fd0d49d51b6d22a4a0bee288957b075d7f820ad47677", + "openhcs/runtime/fiji_stream_visualizer.py": "62000e9d4116204777dc78573e5ee6d2f0739ea5a658cde30df4e4e3d6a0efc4", + "openhcs/runtime/fiji_viewer_server.py": "56d9e929384a28dd7f5546d0533616fd533c2e8b533743891bb3f675726080b1", + "openhcs/runtime/function_catalog_preparation.py": "88ffcb443ea905cc0249d4c6d4c7e7989489b11b6c5b82b7f1c31ad677dfdae9", + "openhcs/runtime/import_authority.py": "a613ea9dfedd63c9384a04d24b658849bd53294c1b066f855a7333ed9040f6f6", + "openhcs/runtime/napari_orthogonal_widget.py": "c4f0d6d40d12e2244b3f0b0039f12518897dababb7e403746fdb6652e6848635", + "openhcs/runtime/napari_stream_visualizer.py": "f41f1c52e4a99cf357ddc9ad2047ebb9292e8a6978a8db9c8edd7d8c8a5d3f51", + "openhcs/runtime/napari_streaming_handlers.py": "d123be39bfc67a03ae3206bd2afc410c8f11f42a5af1cc61d158a1a598c1edb1", + "openhcs/runtime/napari_swc_reader.py": "cb13aa5a12b1713914c308bb1457917d98f97c0a083a77d516a39dc9889225d6", + "openhcs/runtime/napari_viewer_server.py": "9a38e6e384d3b1924515c617b97644dceb6ac60a010144225bc6a6072674b9f7", + "openhcs/runtime/omero_instance_manager.py": "af94c8b851bd4e1456e5c85b16f83ac8008944b05a71ed9d9db5574416704933", + "openhcs/runtime/viewer_component_system.py": "20640d435d5af97c27def5c2b23f48239418fed229ffbaa094fbf68fec7764a4", + "openhcs/runtime/viewer_controls.py": "4e3a50ad5f83c51716b0bbcff966de628648ee8aa77106b76dc8812e38b2d0b3", + "openhcs/runtime/viewer_measurements.py": "36cb96e1b90f0a1203de0670cb853edee59c4feca5fb6e21c6a62c117dd5023d", + "openhcs/runtime/viewer_protocol.py": "896a630bbbb67c152dd533d57280df098f261b714ea65ee1979f91c813e2ffe9", + "openhcs/runtime/viewer_snapshot.py": "34a71a06066ccad0a9dee5be6696a106447f207b9b1aea320be545622249ca24", + "openhcs/runtime/zmq_application.py": "078dc20848ff11777edefe355b90aa403594f18b6c1abbacaaa7af5773f3577c", + "openhcs/runtime/zmq_compilation.py": "ad958c78ec9a26b778ad231501751f38ec6dd3d0c73ca2c1082207031fc6781f", + "openhcs/runtime/zmq_config.py": "eff825c945cf52f658438f4328997eb3cf5bef970df63a7ff13b198bdd144e7a", + "openhcs/runtime/zmq_control.py": "5c18a1f146076c15d50e5d16446d81871e4fc0661facf894ab6e2049bcfec05a", + "openhcs/runtime/zmq_execution_client.py": "8f98169438b1f9d65dd2a4f1517b5901e5d2ffd944fce4b0779a8f9b17d01db3", + "openhcs/runtime/zmq_execution_observation.py": "01e3a316291a951bc7f9c389cb0ab659b2dfb8085b0bb554be9b46a03e7a603c", + "openhcs/runtime/zmq_execution_server.py": "738450e5af28b1b54595d21685d43e3961273c0d3284ec8dae7161a558353f5d", + "openhcs/runtime/zmq_execution_server_launcher.py": "09c3dd01d5bfd0fe2d08d6d8ffe0c9c806a817940d2df2d176ae5108cf0a1708", + "openhcs/runtime/zmq_execution_signature.py": "41dcdb0a40446947a42a87482f27da051408015eec972e11e4d3329464db11ac", + "openhcs/runtime/zmq_orchestrator_environment.py": "7498c32e2657fdc9d411be2f2791708950c5d764c88de0762fc72b424b20f1a9", + "openhcs/runtime/zmq_progress.py": "354f437fc08bde998b12126b36f92aef793e4a5fd2a0027582b7886130cbaee2", + "openhcs/runtime/zmq_server_hooks.py": "b10f2a9a409ea1b97ad04ab4fa1fcea2fb41b9fbeaa43f7f31f0371be6ef484c", + "openhcs/runtime/zmq_worker_execution.py": "000a65d1619b75d802b3b38001e3e3787524e3859c9430b5d74813f197b29dcb", + "openhcs/serialization/__init__.py": "fb53e3cf59733013cdfde9eeab44c0c95f5d5177ba08b6e198ff0e2a9b4187e6", + "openhcs/serialization/json.py": "5145f2956c583ccce35dd24cc1d87c4d5bf959c96daae1ba0cdbdb903d69bfaa", + "openhcs/serialization/pycodify_formatters.py": "b86d8a18b32084839667ebeb1322fd2e86ccb5fd8bea0365f01c03bc56042e9f", + "openhcs/serialization/source_path_factoring.py": "d8dd55b7d45882e067f9fddbe87327000a7e226dbc531a90fc543f201ea665ab", + "openhcs/ui/shared/__init__.py": "923d954c0cdd5d417114a10688a5afcdb81a3b8d11dfa7c52fdd06e9a9f94122", + "openhcs/ui/shared/code_editor_form_updater.py": "bdef35064a2a003873f0358fe336e77cf1089357d6335233e84b13c89f2740cc", + "openhcs/ui/shared/pattern_data_manager.py": "862ade241cbeb33b0496a486f3d55dca6db508bac71abba4ecf866323a25ca3e", + "openhcs/ui/shared/pattern_file_service.py": "1e8addb223c8cbfa817b3c13564fe2332e58c147caecc6218c63c48b98c3edb7", + "openhcs/ui/shared/plate_manager_code_document.py": "e742b4e6227318a59678e33746b94f74d9224a4071756eb2fd03033e8cff932b", + "openhcs/ui/shared/plate_scope_identity.py": "e6d8e83375d4e493c59ea5af5adb585ecee42763a7799773bca195e9c22de1f1", + "openhcs/utils/environment.py": "8c8c021cbb3ee213656da1ad30ad9237ecb235e60524eff73e64c30f7c56cf3f", + "openhcs/utils/import_utils.py": "39ba3547cff334da81551fb75b85fd2691db4e729b510b701ac89b63cf791a14", + "openhcs/utils/performance_monitor.py": "4235d3e703caaf41a03e92335103d10b6e7b001eea90fafbbca96c00a8ff62c3", + "openhcs/utils/pipeline_migration.py": "2bbabcc0a50bd54c8b28b7038a418435c532e58d0432c3b2b17d7fd6a2b78ead", + "openhcs/utils/recache_function_registry.py": "70bc5ff8b87ca22c90ebc0a048cfd5f3d960b6b47bb2ada34297c036c024737d", + "openhcs/validation/__init__.py": "35a49caca4df9fa87335ca25ed5d551840152fe11f1e0cbe619d70a7f5d891ca", + "openhcs/validation/ast_validator.py": "07a305357e4d902366e97f756456ef76438ac2b91580631609c2ba848420e0bb", + "openhcs/validation/validate.py": "50e0503909e06fb85c6e91df98240b6f2a5181c7bc16f35899706c5120ec73bf", + "packaging/codex/openhcs/.codex-plugin/plugin.json": "94633e826327cfc68d88caff5eccc9bb200ed92e0f72be764032097f4a785089", + "packaging/codex/openhcs/.mcp.json": "83d842ea5fc48ba191ba19914771b10c6685d9cb8748611358a15a92cd152123", + "packaging/codex/openhcs/skills/use-openhcs/SKILL.md": "d8e48c44735e9aae2c7f3e2b96e3981cad91c994a48d2ccf7c402ad139234d0e", + "packaging/codex/openhcs/skills/use-openhcs/agents/openai.yaml": "ea7c4babb6d65844d476f49f8492fe40ede6d7348c9c7943e131ce7855ffc83d", + "packaging/codex/openhcs/skills/use-openhcs/references/analysis-learning.md": "98aaed3480e8115184e7bcac319ff1210d30f9f27f7ee5250e9e7b44da20e25b", + "packaging/codex/openhcs/skills/use-openhcs/references/analysis-strategy.md": "d64aad6085612acc254e3db992ef4219f6540691918334751524aa2039e6b3c0", + "packaging/codex/openhcs/skills/use-openhcs/references/biological-image-analysis-evidence.md": "3d64f5fabc070accd9a8f08e079171de30d00e00ed1b7536f4cf40e8684ed361", + "packaging/codex/openhcs/skills/use-openhcs/references/blind-recipe-promotion.md": "c8a2fc19c859817582608d17f30c179faf486e3ee94af2e1c70a6bf43ebc5710", + "packaging/codex/openhcs/skills/use-openhcs/references/custom-function-authoring.md": "32d7f2de2192a6439a518828d0d6b2c7080383574deda24a78522b9a5dce50e5", + "packaging/codex/openhcs/skills/use-openhcs/references/image-interpretation.md": "1b47bb7f7e6ad9bdf198f0fa5c7c6247352ae271665e4a18446422dd83f4e5d5", + "packaging/codex/openhcs/skills/use-openhcs/references/image-preprocessing.md": "a18933442e627df611ddfb362a13e605389430c1dce0a7745aee94b6efb3f148", + "packaging/codex/openhcs/skills/use-openhcs/references/installation.md": "f9051b9c5f427650994d2a2b4fa9599d91a168ba2a68c4d5f044a07043a15cf7", + "packaging/codex/openhcs/skills/use-openhcs/references/measurement-interpretation.md": "fb25ac9aa3b777f775daa76242546406642d2a75b587ae8adb81ca74f18cfdd0", + "packaging/codex/openhcs/skills/use-openhcs/references/segmentation-diagnostics.md": "beda4b305d81dfe8d9b892b3d721fd07f7b355ff4fa9132a1c05ba680f2f8e85", + "packaging/codex/openhcs/skills/use-openhcs/references/viewer-qa.md": "c5d20201582abb10610adf128518d193a8508409ae9775e5b11622718788c47c", + "packaging/hosted-mcp/Dockerfile": "0a70807959c0cd7f125ed64bfe062761bdc05b5fa943e4aaba4321cc1fa46af8", + "packaging/hosted-mcp/README.md": "fe111c091c78b901c9e3265796aac728ff06857c363224935ae1b7ac24667707", + "packaging/installers/README.md": "447bdf95ab4b7a7ee256919a25f6f8c42a1ed718e5386110dfcb18dbb6a342ac", + "packaging/installers/macos/OpenHCSInstaller.swift": "b79ae9d0be4932cd47ed8b139ba2fb2c6205d685775469bc525422bc6245850c", + "packaging/installers/macos/README.md": "f7e7a45c5e0b2a80cd2360f9dced3717738c103181c148330437f951de54be3a", + "packaging/installers/macos/Sign-Installer.sh": "7aeb2c8bd4163adf529d5990ce10578de00e47325858ccc468fc736e47c56891", + "packaging/installers/macos/build-dmg.sh": "81bb96b0adfb8025520cb36c332723794b2ce526033962e84dca18aa09ead70c", + "packaging/installers/macos/build-installer.sh": "2495c0126f7f2990ab88b53e4a04c01d19b678f24ce3cacbf696c0e4b27e01db", + "packaging/installers/macos/dmg-lifecycle.sh": "b6041ab0e2cfd4bb5fd10b8b130f0f64f4307c9e9caecfe2dae011f9d2199b4b", + "packaging/installers/macos/install-openhcs.sh": "3a0f43c57c14bd7f8ceeb38464e174728f903e0ec524d980dbdb2b5f9bc11544", + "packaging/installers/windows/Build-InstallerLauncher.ps1": "19b9d35464041652a69f2ebc2e870a4eca73f241fb12491b9617c7aff930e9e9", + "packaging/installers/windows/Install-OpenHCS.cmd": "00d1d89b03b5ec4df910ec9b8bd2f2f3be1fa5381f4aff42ddbbf09b44899bfb", + "packaging/installers/windows/Install-OpenHCS.ps1": "ca368082f3d7a414f9e9136b2c5ae459bfb2a9a2a37c096d06eeb93d5c403358", + "packaging/installers/windows/InstallerLauncher.cs": "6567afedc37b0957a8c3e3ed39c8ed30a2d7afe2c7df998dbef2ca71b3ff7ab3", + "packaging/installers/windows/InstallerLauncher.csproj": "3aa0f7afef4bd515c2d3ad45c0bd5b9fd58a7e17594acd89f8173621f4d3439a", + "packaging/installers/windows/Sign-Installer.ps1": "127d46834f7377b16869df0641146c75780787199b49f6a255daa521c52ff097", + "packaging/mcpb/openhcs/.mcpbignore": "c30274f74a4e9f2c17b3866f9054f4136f132c9fc4eef9ffb1ea37b0e212910f", + "packaging/mcpb/openhcs/manifest.json": "a51d5f32ad56d1ea22cf338b5b4eed1e343b7bbb62d9a1acde0ce5cf1fab20e5", + "packaging/mcpb/openhcs/pyproject.toml": "56b8807a2c2c86c2ba59eebcd49ca1f3a9f8c75499d63115b2534a4acbc2f53f", + "packaging/mcpb/openhcs/server/main.py": "a66f6c4826ac16c5b6fa12f08a7f2f9f5cf345b2191a4b44302dbd9bf773cf8d", + "paper/.gitignore": "f3dc4ffa6afb0ce8b250b3bc012ffc8121349d2d5d413a514254ecb1feeec6fb", + "paper/01_abstract.md": "9b2dd7b6ac22a3c6816b5346caf32d8690aafaf9a349bf8f1e2bb9153aebe585", + "paper/02_introduction.md": "6471f9cd05a4ab12fef57035835fc2afcaca53034d524d477c9646ef9792f5dc", + "paper/06_figures.md": "d6fa40fdc527d7b72ddad3a53e91af58b4ab9f57d525bb30685867c326b48293", + "paper/README.md": "1ba1541e0f91a28f70f405246c2e2bd072a524e00f199a358fd148f872337d59", + "paper/benchmarking_plan.md": "560037370a27b5eec4447b51e955d7e244f06db886cfd8de749b5ec1a336ed1b", + "paper/build_docx_from_markdown.py": "72ffa96c57f4dc8ad7ccb78402c33f87b1f376c67e79936be2a21be4cc3939d6", + "paper/build_paper.py": "2c77ee7106a3bf2bf48d6172fdf9ed3fa6605f0122a95f243dbd4707ab3284bc", + "paper/figures/build_slas_agent.py": "a8315f9f435a36c30115a5655f040180e95db2022466ec3731dcd0e0c62040e9", + "paper/figures/build_slas_benchmark.py": "d757d90ea049afff2d4ae6cd0b8264146413e2c4181fca3c1ee4b62e96d62398", + "paper/figures/build_slas_cellprofiler.py": "fa19dc2a6f5e9b4992fd58686b6af2192e134e8137498cc1458f2e23eab2b147", + "paper/figures/build_slas_compiler.py": "4695327ac930ad313f2af161dc46c5e192d6bce3008a201b78fe5a1fdececb29", + "paper/figures/build_slas_complex_workflows.py": "98d7ea099c4165e2872a23ffbd6541254b5a5494e4589dfe24841060149345c4", + "paper/figures/build_slas_extension.py": "33f547f5efb4f44a1d86ddbc76a19507c67d5943810ce3b51910b47ebecf2cab", + "paper/figures/build_slas_independent_validation.py": "71bdde1fd0ff4a11c58770d6d5660ce5347c58eab4b87a62712323cf79327cc8", + "paper/figures/build_slas_outputs.py": "1d2ad59edd73b24d41589abe3cfa3617cc113d87a3114670c976a3e7e27e3c36", + "paper/figures/build_slas_processes.py": "8681d66290044aee52191d517d287cc0510d96e94d580f69651bc14ae36bd8f1", + "paper/figures/build_slas_runtime.py": "be189377a89a1bab69fb428e1151cf0a89d9dccde1df896011049419baae7aa3", + "paper/figures/build_slas_visual_story.py": "9fcb6c749a4b55d8c89c8c5841a004a6a85a96541b01d55a7214ec52314b0c10", + "paper/figures/capture_slas_authoring.py": "a5c0b917e5c807ac0a5a41c33e33b7cc4e3e28ace44cf827bdbbcac66647fbfb", + "paper/figures/diagrams/README.md": "983a70bc3d77a6ad17510addceec23af5fde61f5ffc218aa559c3492ca6ddada", + "paper/figures/diagrams/fig01_field_integration_gap.dot": "ddfe67b88a21a2ff82f4d2b2a80617572881345c2ad1872299c6117c6c897bde", + "paper/figures/diagrams/fig02_compiler_runtime_architecture.dot": "8ba8156db605154181244338ef51a37a5d52d72fc09519a0a8d54eb64aa5e600", + "paper/figures/diagrams/fig03_cellprofiler_import_path.dot": "b93bb6b83ee271078e99eb9740461b34617fdfd4e491e515050f87d1c1cabd0d", + "paper/figures/diagrams/fig04_benchmark_validation_structure.dot": "4006ef6be7bd1be50cc26cf55d1140a3a1e5ae2b625d97da1748f160738b6ba8", + "paper/figures/diagrams/fig05_throughput_amortization.dot": "859ccffd882420502b4f400e360fb1c259accd3e95eff269e442af81a829339d", + "paper/figures/diagrams/fig06_backend_extensibility.dot": "18ba5c5e0642b771d377b1e1b83f84836a990127bd5ad33930f235d4fd1ced46", + "paper/figures/diagrams/fig07_typed_state_bidirectional_editing.dot": "949fa632cc592408abcbffe5eda2e6731253cc740d8210833131b065f96480ea", + "paper/figures/diagrams/fig08_benchmark_corpus_categories.dot": "a61c3d1b5a24ddc1aa0a5e2df2b4b8e113f2433d29e4684e9cf111e1f0b018a9", + "paper/figures/render_diagrams.py": "0e4a33f7f7ba28aca81bdb207c6777f3755d25b79be2a4257216558db2632187", + "paper/figures/rendered/fig01_field_integration_gap.png": "c7afb89193de18b8995de4beece888b3d5431c143fbbe1180bb4fe9da8f2a787", + "paper/figures/rendered/fig01_field_integration_gap.svg": "45abc09cd26032d3bcdee0c03e6875600f7bb8de59d7824dec2bc830cebf1bc7", + "paper/figures/rendered/fig02_compiler_runtime_architecture.png": "bcc4bec4b9a3bcbb34549e31d700b5179f7f2a660eb68641df5904172cec6048", + "paper/figures/rendered/fig02_compiler_runtime_architecture.svg": "519144ad09a0377af5489edcc25d36575e347afed9bedd4ad16936c58727a038", + "paper/figures/rendered/fig03_cellprofiler_import_path.png": "06584f01b2d10ddf219fdb12482a6cc902eb0deb5e1eda93c1862b0ebae50daf", + "paper/figures/rendered/fig03_cellprofiler_import_path.svg": "36026b58ccdb666d73487235eb0f59cc04767bf3284d2d947073958d7d9b963e", + "paper/figures/rendered/fig04_benchmark_validation_structure.png": "aeb74b4622d3f9ac8643e663c32dabe66c781543fa12c072ab7b852e97ac50b9", + "paper/figures/rendered/fig04_benchmark_validation_structure.svg": "eb88c65f4878197a4267f72285a25d0627e63e103bb64c470d7983061b851463", + "paper/figures/rendered/fig05_throughput_amortization.png": "0786ad9ca71980619419f068481bec5f9a0201eaab2b1a11de3aac9fcb7508d0", + "paper/figures/rendered/fig05_throughput_amortization.svg": "6df0457705d6490e54cf2672424f8e86a921e5a2ca56940b5e56d466445c86ec", + "paper/figures/rendered/fig06_backend_extensibility.png": "a1d07d9a2c073e8220ad33c1681c74037e31f05fbe1276a5f8f5c9798bcf5a56", + "paper/figures/rendered/fig06_backend_extensibility.svg": "6b8bae2c53d29366905eb8f5df2f4935b8a7304d0aed447512a15d4e6e4b85e9", + "paper/figures/rendered/fig07_typed_state_bidirectional_editing.png": "469f34e83fb1e80f069c9e6ab882dc1fb1b7957cdf399a89765bacd60c04182d", + "paper/figures/rendered/fig07_typed_state_bidirectional_editing.svg": "6f1222cbb149c1e283b4805fb7431ac32d14f4c056bb78c5b1bd09badcb25205", + "paper/figures/rendered/fig08_benchmark_corpus_categories.png": "b935e03bc3742242c81ab848f50d5ab13271ff3711c11cd7b8867c3e6c819ae2", + "paper/figures/rendered/fig08_benchmark_corpus_categories.svg": "cbbdac66caff4f1435a795bc73460aaae4ac0144e1e2d076f9302e654135e5b4", + "paper/figures/rendered/figure_contact_sheet.png": "b1955c7032f4ff118eaf28088109e1fd58490e53ca468f8f915cef196c9c2537", + "paper/figures/slas/authoring_actions_provenance.json": "c136049995c71be1a421811e594976aef958ab27d606d63175e207fc14f5cdd4", + "paper/figures/slas/authoring_apply_provenance.json": "bec9e9b1e45b9881c436ff3e676e22ad4b1e9e0a8463965d39caafb526dbe235", + "paper/figures/slas/authoring_code_capture.png": "b328e409ac28e08f7b25bb166b72cc36551d9f8eadac0f8ce8a72fd91896e303", + "paper/figures/slas/authoring_code_capture_provenance.json": "1f1e06a61ace7c219fbb9cd0de78603ce6b801b7c9da88416165b7c8ae74a9f4", + "paper/figures/slas/authoring_code_tree_provenance.json": "b7527fb63456c8722f35c0e421f21d2051d8d2b1ea7a8e223ab1581a664435d9", + "paper/figures/slas/authoring_code_verified_capture.png": "9154c252f4d2a86be1ceac9a235d4a5c97e1cdca9516f6ad4699250105f1715b", + "paper/figures/slas/authoring_code_verified_capture_provenance.json": "8bcc0683f03695fb1c70aef2cf883ad3503778a4e9721fb77e883d824191910f", + "paper/figures/slas/authoring_code_windows_provenance.json": "09d85f79ad5c300d432ccc7ee67707c10d3a9a888eac2f203ed26ecc16368c5f", + "paper/figures/slas/authoring_documents_provenance.json": "0e5214541766eed0063b2f77ede57fe83f1d023432ecf344f674592ae957fae7", + "paper/figures/slas/authoring_function_capture.png": "f4add68e31c21a657dcaed9984864f0a52c32bb60a7f6ac5f2ec7f803b23232f", + "paper/figures/slas/authoring_function_capture_provenance.json": "bc706b05e5ab98191ce66f74ea35a15bd6c3fae04c4a15ae4fd3f140c27c2d2a", + "paper/figures/slas/authoring_function_code_provenance.json": "30e51a9a541b4392ee6c160be8fdb6c7663d9f17a774533408911da148d0a2da", + "paper/figures/slas/authoring_function_final_capture.png": "d92ef7cf0b63a9c5027d374198ae66c7bd6bfc218e14e07cbca9e903584d94fe", + "paper/figures/slas/authoring_function_final_capture_provenance.json": "b133b9f714d214d8b256e5582e1bc3a39e268528f93c442e16a0910fa0af1cce", + "paper/figures/slas/authoring_function_fixed_capture.png": "442498fbaf70731422b19c5730c70027376d0477ec8e3ef3013e82e70357aceb", + "paper/figures/slas/authoring_function_fixed_capture_provenance.json": "c654002212695dffed84840df586ab2936a6c17574f6f81c3c67c9ef6796bce3", + "paper/figures/slas/authoring_function_tree_provenance.json": "4261a813b5c6641e579bea7c849a48c1c53e58d95be5db3dfdba3ec00165fd49", + "paper/figures/slas/authoring_function_verified_capture.png": "56c35478fb88c3cd9f0aa4db82f247a287742ba3947db28da18fd7b7bed09d29", + "paper/figures/slas/authoring_function_verified_capture_provenance.json": "b55929ab5aff4c2bff4cd3ab12fe5781930163d8d49d5c477bdff5c1b3740dda", + "paper/figures/slas/authoring_load_provenance.json": "2204a3cf5da20af6b4e3bcaaf8fd507566ed935bb9c3ea9d0b49f1af034253a1", + "paper/figures/slas/authoring_main_capture.png": "fef97515c69409193cf040a680222ad3e2e77c6c3f20f286488c654d4037576e", + "paper/figures/slas/authoring_main_capture_provenance.json": "9412cb35168ed9f896f4d80f8873d623dc10cb5816043ec2d5339d16d1f446d2", + "paper/figures/slas/authoring_main_verified_capture.png": "ed486ff1f356b11db0632530b85cb535e37f688be6617d21b1d41c8ee506f0d7", + "paper/figures/slas/authoring_main_verified_capture_provenance.json": "d33fd64340a7afe504cf33f6b6f33d65c1c561288876842900acce59721e4be5", + "paper/figures/slas/authoring_navigate_provenance.json": "8fc8d1e335b78a18332e206e6050fea17b01b00d87603db3a415962c2ba182f8", + "paper/figures/slas/authoring_parameter_tree_provenance.json": "aad84bb13d31197f66089d09c4c1c04c65cc27f27830a1cd3735541d6b5fab03", + "paper/figures/slas/authoring_plate_tree_provenance.json": "5162833b085384969836a3563c01648bb9398420891415ce416581b20e804b0d", + "paper/figures/slas/authoring_restart_provenance.json": "57cd6a5dd019e80968677225532f6d6010bddcb53ba2c6622efa002cda747d66", + "paper/figures/slas/authoring_roundtrip_apply_provenance.json": "d126fd8d041a1684cf673a14e4c26169c181b447a2ec794fc25d21ddc1e2646c", + "paper/figures/slas/authoring_step_capture.png": "137d21b4f8f977c6df5dc4c9ed51276641e04daa4e5f2479f735ccffe59af100", + "paper/figures/slas/authoring_step_capture_provenance.json": "23ad7329323f1b38a74f14813edc1c85c5a8b718fdf095de13f50788fc825855", + "paper/figures/slas/authoring_step_code_provenance.json": "6bec34e1a6c0980b507fcebe39d09891087be14d04a8ec5e393b49be71015dca", + "paper/figures/slas/authoring_step_fixed_code_provenance.json": "4c7b5cf5a3893340df99b820bfa306c4c4b0969a650c50df8a1d8ce98037d80a", + "paper/figures/slas/authoring_step_tree_provenance.json": "e6de617835acc87626d53913dd095fddebd51b548d03a5a0cd4701c91b2b4b5d", + "paper/figures/slas/authoring_verified_roundtrip_provenance.json": "d5d98d6cb2946ef0b11a4547aa560591174b7c036e99dc2a8af315b4c857ccdb", + "paper/figures/slas/authoring_windows_provenance.json": "920e97e5446bec05ff432c6d47be5c9f1b2f29645d38c14eb706738b5d934ba5", + "paper/figures/slas/cellprofiler_translation.pdf": "5ec3ec0ca3ce0268230a948ddabfc09ebff1c3db8edf93dfc79239afda231880", + "paper/figures/slas/cellprofiler_translation.png": "4a6c8f6708314c273c364abb3bb8ab2b9ee47ef0a403784116fe869018ba1fc7", + "paper/figures/slas/cellprofiler_translation.svg": "f2c4adfe20ca0b86066200735d41bf9f9c446ebe0daf7b31aa6fe34ad8f0bad4", + "paper/figures/slas/cellprofiler_translation_imported.py": "d933bad3b789811fb44669c4fe92ecb3d02b568acf09084de681232629520742", + "paper/figures/slas/cellprofiler_translation_provenance.json": "529cc0d3426fe452695f143ea34ae5a3b3700dcd979d029cea71de80266678b5", + "paper/figures/slas/compiler_preparation.pdf": "5a7d879d13b51a883d14afde5d15b68dfeefe71ec20ee6c118d3618717edbe66", + "paper/figures/slas/compiler_preparation.png": "41d45bf597ceb66aae1e83b990889976b99b651871ceba9e8aca47b3ce52ed60", + "paper/figures/slas/compiler_preparation.svg": "fdfbe4ff5bf332d02256d1560a09db6a86edad8e14a222a0d25589f38cb5d3da", + "paper/figures/slas/compiler_preparation_provenance.json": "48050c49dbe30c0368e68b01a117ffd6046e72c30e477db03a6ce78c21e15171", + "paper/figures/slas/custom_extension_accept_custom_function.json": "83f1edffcf055087ec218b77ac21ba78abab4f139fa7d00519f6b34b9661488c", + "paper/figures/slas/custom_extension_code_before.json": "0643feb3e37b62fab001619e68e6ff993a35cc9919e96aabe696c4ad47d99f0f", + "paper/figures/slas/custom_extension_custom_parameters_tree.json": "62fb8fd96c919eb39f9e6228a7f98ae1399b5560d4acc606234761aa1fa6ac58", + "paper/figures/slas/custom_extension_description.json": "3018643ea5e4252226b2f4464f01008aeea4082f5535f7399ab2f5777af1ea19", + "paper/figures/slas/custom_extension_evidence.json": "dd72dc4c73be803c61ac6864ec611b6f2a37048caa2a0b8f7176a67a345d98bc", + "paper/figures/slas/custom_extension_function_tab.json": "79f8cf6e4b259f4c1c9acd62c90513e8f3ac7ce27b21660aa082bbfd075d59d7", + "paper/figures/slas/custom_extension_load_authoring.json": "178c109f95ed1793d616c319cceecca7d353a5292223e8e0d501cd14fc24ceec", + "paper/figures/slas/custom_extension_open_step.json": "064653c4ea78c7785571298189ffc5077c3f0f019f92dc313f81d29a432e86b7", + "paper/figures/slas/custom_extension_open_visible_selector.json": "9eea9c75c7e7a2c94a0bd233895deb294ed007cb54ab97d3250284ab5156268c", + "paper/figures/slas/custom_extension_parameters_capture.png": "49f3b150a1956bf9415b6e416a2c7c6303ad1c5fb5c0d02ce1e8335bf30e3c69", + "paper/figures/slas/custom_extension_parameters_capture_provenance.json": "3822cb974f240ecaa79bb8f3eef6a1fe5ea5f0bc6e04266c40fd328ba2e4faab", + "paper/figures/slas/custom_extension_registration.json": "2f2b17d6b5e1977d3c524432042abc4a4d3b78272ac731b7497c992245027c4d", + "paper/figures/slas/custom_extension_registration_after_second_gui_start.json": "37b6075b59ca68aa4389d0895badf4ee1a7b0c6bb5d589e51c82a2bc2c846575", + "paper/figures/slas/custom_extension_select_custom_function.json": "4322e69a31ef4fe8e65aac888d923b51b7f1681beab550e7b3e0b9607b1fa8c2", + "paper/figures/slas/custom_extension_selector_capture.png": "0fe9e88471c8adc2b46c4fc8b63a94d73b7aba1c5b164dad005560dc70602508", + "paper/figures/slas/custom_extension_selector_capture_provenance.json": "aba7a762135290dcfee47181e58ca0407f5b4317156b131692a3ae6c98f0f8fe", + "paper/figures/slas/custom_extension_selector_selected_tree.json": "ab7c7a4f0011aa3130952fb69e6ddc645d229e397d54e4434b1d2b7158e823c8", + "paper/figures/slas/custom_extension_selector_tree.json": "343b902367816f317c52daeb282d0dd9ee6a68be8050bda73f7f96b1ff9aec8b", + "paper/figures/slas/custom_extension_selector_windows_ready.json": "35b8fdd981c12c1f9c33bd7a852d2ac78343425e16f11de5bef4786cb84f75ac", + "paper/figures/slas/custom_extension_step_tree_ready.json": "c3bfd51f801438f4856705d4f577f0ed8cef08f48db7ec62138c4c860270e765", + "paper/figures/slas/custom_function_extension.pdf": "bb8bd6b74da445f800c5db5aea02998a0837a039fde7e5c9c9f1fd90221c5724", + "paper/figures/slas/custom_function_extension.png": "af4a67e06a817bad63ffaa96c0d2d7b7a779e7f85e8d183d0d4b398f872d0dcf", + "paper/figures/slas/custom_function_extension.svg": "8fcfaed367242196f4d6e9d8e459e89568dac1b1e6f70374787860e69a6feb9c", + "paper/figures/slas/custom_function_extension_provenance.json": "ee0e49848a9a0f8017d5c1942bce5d5e870eee090f1936ec4cb6f2f0eb57043e", + "paper/figures/slas/custom_signal_example.py": "b84af3e2857cd16636d631244aaf82d34d3bd5ebd658bd92a56281b2b3aef26c", + "paper/figures/slas/editable_analyses.pdf": "9d608160597f4d152f0e25f09f3ef5de4658acbe8ca5fc618671f2503125dba8", + "paper/figures/slas/editable_analyses.png": "c1c34e6426e2b6a22309bfaecea3c7e1fac200d4046e524afc123a880451ff50", + "paper/figures/slas/editable_analyses.svg": "f72fdd9893b4392d72bf7f6ad1874c17655be179cb160f80682553ed49eaa623", + "paper/figures/slas/editable_analyses_provenance.json": "2067df1235ef4aa28b4f598514124b681ddedc1bea6d3dd8cac8433577e51fba", + "paper/figures/slas/figure2_benchmarks.pdf": "03994926673d192af152fe7a96a3d82867dad156ae783a34d1812dcdc139583b", + "paper/figures/slas/figure2_benchmarks.png": "d5da70a00a7296b6a8e45ccba2e6ae29ef6518b217662f60532afb7603a8bc6c", + "paper/figures/slas/figure2_benchmarks.svg": "fe35c22c5dc3b333460b3935de9dc484b090108d47b678910578a47adf658caa", + "paper/figures/slas/figure2_benchmarks_by_workflow.pdf": "d62cc3e89e211fa7036abc44f830ddb7f379179e6dd8781010165b332b28429f", + "paper/figures/slas/figure2_benchmarks_by_workflow.png": "7c71733553595475dc5fce6b5c403884cd668ba56626d8fbde10a448acb5e3f4", + "paper/figures/slas/figure2_benchmarks_by_workflow.svg": "68ed9679a4aed56aff84420d814771f215b34d71518d5b8f9d004d1ef211ad46", + "paper/figures/slas/figure2_historical_timings.pdf": "98613c052ff5f1056f2bdfc8482e521c0f92d9988817ce5b048d3d17a599f7ce", + "paper/figures/slas/figure2_historical_timings.png": "009b64a2b8ef8fe3d6f7ce432677ae000a133fa1448c8ac803df13632f699461", + "paper/figures/slas/figure2_historical_timings.svg": "a36a96494cdd04a1718499223d5d59e1b0f03cf75e3ffdc8fba05d685f2b3574", + "paper/figures/slas/figure2_memory_observations.csv": "ef6ce818e23cc2ad2e4c2eba7d3bafa5b4bf930fbe71083c3914c1a7360c15fc", + "paper/figures/slas/figure2_provenance.json": "9ef2bf66e0b2b1ff3fe2e42aba610db0cf58a454d784b1edfe98ad8a67b1b8ee", + "paper/figures/slas/figure2_scaling_comparisons.csv": "206afb149cce99499cf36218677e74b4c4af87f14a27dc00288d09f2d85a39b2", + "paper/figures/slas/figure2_throughput_observations.csv": "f62b96ffd6e6cc285f3a32ac88389147c6691d83c7748040e1fa0735e11635ad", + "paper/figures/slas/figure2_timed_workflows.csv": "0a52b40f17043db5a89d7897806984706227795ee2303cf7837fd05c595b369f", + "paper/figures/slas/figure3_agent_workflow.pdf": "9e2329abde34358b0d057024da006e8fabd6c08f43f9e69caec87528f1748e6c", + "paper/figures/slas/figure3_agent_workflow.png": "9cacbe660cf64649c7596802d852c383f54766442003f5d1b3837dea314ebd42", + "paper/figures/slas/figure3_agent_workflow.svg": "8b933465f4d8a59fc8a5e9957dfc48906fe262c86346b23bf7cf8606599c0a51", + "paper/figures/slas/figure3_original_video_frame.png": "c52154ecfa8f7ab3c9f8e24416b735e7ca79adf57111ba2b4dc3c824903d13c1", + "paper/figures/slas/figure3_provenance.json": "f5e1d19e29ccdc07792ecadf3ca97942b52e2c2fda6f5314f6b76018bdac3076", + "paper/figures/slas/independent_agent_validation.pdf": "914ab42f9a780cff2d87d2e493bbac97f8fbfaa588dd6a10037f70db64127485", + "paper/figures/slas/independent_agent_validation.png": "6fb1bc3fb340713f2ed1247feb13e4d72908c4fe5003e2f91620cf160d2d6a39", + "paper/figures/slas/independent_agent_validation.svg": "90833b662fba60dafa1ab23a000672c7b6544abf08232c3b4dd40edb29660e33", + "paper/figures/slas/independent_agent_validation_plot_data.csv": "55e2e72e7904ca90b3aeb10cb07d28228425e8e2f13c81ab64ca6e8fdcbd7afb", + "paper/figures/slas/independent_agent_validation_provenance.json": "8a26e3dcd1589dc31b6f4713148acf4cdcc7f9ee8a041a728d1dc5bfb7757bc8", + "paper/figures/slas/inspectable_results.pdf": "975a61350adcf3d955f102901387410527bda1347116a4d6a6f26c729540b388", + "paper/figures/slas/inspectable_results.png": "ab61922ed8d66b9910d99476cf4fc8a81c70f5867deac360e1bd5ecda164ae70", + "paper/figures/slas/inspectable_results.svg": "4f218f6e2a9d9b136edc5aaa4635e69f5e68aaf4bd8d9aab54585a273a0037b6", + "paper/figures/slas/inspectable_results_provenance.json": "d03ebc3b932a3abd6144e435713b6c920c5b06446418bfc275f1fe763e5474c7", + "paper/figures/slas/outputs_and_inspection.pdf": "7719892e326b26f7038add624e0a765b366601c95821e776d98ab13be43af11a", + "paper/figures/slas/outputs_and_inspection.png": "5ecaf0ec334deb9fe6dd7b16c8c1c4b909f63620e9af81d6600bfb14f19bb129", + "paper/figures/slas/outputs_and_inspection.svg": "ce2da452dbf173c6573659557604a5c156201f8443d6b6ef39a8cd97bc656303", + "paper/figures/slas/outputs_and_inspection_provenance.json": "7e7183522611698c8b4307cd703e9e858df3891d7f92a77b40fadba1016cedd3", + "paper/figures/slas/process_architecture.pdf": "1bb8bb2e4021b3f35c70022ec77c47f2cd08fad0bd584ba44e7904d4d5adb2df", + "paper/figures/slas/process_architecture.png": "f6856a5f564d188c14b66769de880facdd9458eb1642fa119c50e11c9b735d59", + "paper/figures/slas/process_architecture.svg": "766d21f793797cdd98fc1d2ddc5fbb9585ea8cc216883c3bd5bb66dfd56c896a", + "paper/figures/slas/process_architecture_provenance.json": "112ff107feac0e86bcc53ff9183c3458b65b51d2dba10af3ac4f1f81a7ca7d96", + "paper/figures/slas/runtime_composition.pdf": "3eea90ecb49518a12c302f62d63985f8ecccbcba537288b5bd50d2d9a29856b9", + "paper/figures/slas/runtime_composition.png": "11abab9bbcccbf1cf83a7ec699815367c95f2c1ed39ec9b75411e43c2f6bbdc7", + "paper/figures/slas/runtime_composition.svg": "5356f083ddf6c9f15f57a326c862b7fe83762fb4041a702a0312b1048efc856e", + "paper/figures/slas/runtime_composition_provenance.json": "c414adb479e97dffea0cab6bb146ba16671fd385223969c3bbb9a5c6326f4b34", + "paper/figures/slas/shared_workflow.pdf": "4fe5268709e401d923777b38aaf9320f4a490dd5b58cfe45e13fa62f507e9545", + "paper/figures/slas/shared_workflow.png": "70d1df787f4f72f7911c94216ee244eb0cb239928f97b20a8eed084ffe393aa1", + "paper/figures/slas/shared_workflow.svg": "9ac75f5bb84a4b5d25588869e1d272407bb73dd28bbf744171d6cc5b1da38985", + "paper/figures/slas/shared_workflow_provenance.json": "893e1422a5c2f26f2c06b22c32a90fe9ad07551a2e4f5153cc99bb5e516c4cd0", + "paper/figures/slas/visual_story_contact.png": "d4cbbe7660ca177ebeb0d289d673f8ba586f1c0c7068a342f15b9a00b239e57f", + "paper/figures/validate_slas_roundtrip.py": "8fe1222d3432e322cf82f720531c617af945a8518d282ff3414f84ccf38b291b", + "paper/manuscript.md": "e5dda54ba0852287f90be15e0da551150fe832e2da01924c1bfa549b15db65bc", + "paper/nature_methods_comparable_papers.md": "901fe5f5d9254325d8abf304495c348533ca96fe9735d31035261c6f9ba0a22b", + "paper/nature_methods_comparator_action_plan.md": "2eedf0a4a5ab209c8adf0ce3b2535ec0e629d85551eb1237ba7a0f5beb1b5696", + "paper/notes.md": "9edef4a2c29c99220e312260a03303d592be17e9de90a80a1d5aa5659b9f7ec3", + "paper/openhcs_comparator_review_20260518.md": "883389712919cf9c00bc7bd8bf74b726300aefb577f522f83864761fcda602e1", + "paper/openhcs_nature_methods_draft.md": "d727b152d3f5d4cbf0c332a33d898ae463aa5259de37d65373132a282779227c", + "paper/openhcs_nature_methods_restructure_plan.md": "7c3a29e96a2c2abafcd251f0c16f27d6aaf1e2d7222c230cdc9346b2ba593e87", + "paper/openhcs_nature_methods_review_comment_audit.md": "2d945d088f2d81e5b5f75eb2f86bdcd1d08f5aa21991cc2eda1ed4313bc7556c", + "paper/openhcs_references.json": "36bf89f27da638ee8ce45aa3db131084c82ad94ffa02c716eaacc77e13ad77c9", + "paper/plans/RESEARCH_SUMMARY.md": "b830a44aea336f118ed282e50a528b6830da8c76a2251d804c7b8008933648bf", + "paper/plans/agenticj_accuracy_harness_gaps_20260929.md": "824979a1f7ab665ddad2e8ba6e393c9fd1bb7b0cacf4a07a29d5461ecab0869c", + "paper/plans/annotated_agent_dataset_candidates_20260915.md": "da62d41bec616793fd466f54fb68fdda7310a5af9dc7f572d91ca497c6d5c98d", + "paper/plans/compile_observation_identity_20260929.md": "d9e11331a8fbaffec98e995ee9624e7ccf1a875ae4e487d64dd4f908c8894b15", + "paper/plans/haase_notebook_translation_candidates_20260915.md": "92a25496bf1e834a10b01ce2fd1550313b827ad547b11f30b49ab493bb2bfc3f", + "paper/plans/haase_validation_corpus_20260917.md": "f03483aa4c7d8eea7240da378f1843e0353dcfceb7f711bdf7be18696b8ca39a", + "paper/plans/materialized_result_followup_20260929.md": "bc655742577585b819b03d587decfcce5bbc3be104627221d3868dd41e9edf2d", + "paper/plans/materialized_result_reopening_20260929.md": "893a3cb337684118e7b8bc4dbdf3af7d050586930ba0e2b7694e98161e00812d", + "paper/plans/materialized_result_route_fix_20260929.md": "d3dc77ee8014e1cf43c52e8bdc40cf9a0a40705741ee9d292ee1b0ff2d13795c", + "paper/plans/mcp_post_dispatch_failure_20260929.md": "291b3e7974071f5a7b3fe80ccf1ae9d4efca14ec75578b932e69cd06acacbc65", + "paper/plans/neuroncyto_fourth_replay_receipt_review_20260915.md": "6dabde2b3340b5e92614ffedfcb50a2d208d0ae9d08020c03b2216b4051b59c9", + "paper/plans/orthogonal_class_census_20260929.json": "69593f1f4729c27cb3b7b3fa9396fd0e06e358649023f309218ce8aaaf7c7142", + "paper/plans/orthogonal_integration_20260929.md": "f117d11a112008ae7c250521ff21bee8a55c6eefa30d3c109b503722d2d203c2", + "paper/plans/orthogonal_viewer_fix_20260929.md": "47a4b1fd2598bcbbdae3b47b940d02735840eb39ffd4656e11938f4b9975cbc5", + "paper/plans/orthogonal_viewer_receipt_20260929.md": "1d3acf9bd7cd51d2253b13af17a8bb5af164f3b8a77794eef19f72733b404b07", + "paper/plans/own_data_neurite_comparator_20260915.md": "cdf99d9b5f4dc6b30db2fc2a5d4c4219ebe58fa690146779370b4fb1c75e5f93", + "paper/plans/own_neurite_blind_analysis_20260915.md": "5db9003ac081f66ecc721fd953a9359033c5f53a75cf0a29071208f9a68d4f0a", + "paper/plans/plan_01_benchmark_infrastructure.md": "b6eda04aebbf0d7ba851839fed89248333b7eb6c50f167993d6f705f244de15e", + "paper/plans/plan_02_ADDENDUM_real_dataset_specs.md": "2db25d7562b4230a39e2a3d3eb179ec8d5ff2fe4175dc1e25ae11e9da65fc0bc", + "paper/plans/plan_02_dataset_acquisition.md": "915611204fb8b30fe4170a94e04483d82261f23741fc953f59564d27eb448e9d", + "paper/plans/plan_03_ADDENDUM_real_pipelines.md": "33cd218eae443f1bcd7a76d76035baead377c93aeb3ce29bf7dde48b27115d96", + "paper/plans/plan_03_tool_adapters.md": "d40c9869171bdccbf83217b950529e5cb3a1f54bec3cd4e46a0bd71856f295c2", + "paper/plans/plan_04_ADDENDUM_correctness_metrics.md": "3912f5a2039706fb3d04fe14b97baaf06c8d55d1bb41daf913d3ee2f5daec4b5", + "paper/plans/plan_04_metric_collectors.md": "d63d3f79ca6209713430bf37be98ce954c422731184731c944342e8ceb277b8b", + "paper/plans/plan_05_pipeline_equivalence.md": "49fd80c60a653d805ed5a309525da40ada2968283a93903d2e0346bba41f56da", + "paper/plans/slas_accessibility_edit_plan_20260914.md": "12f4437e55a151a465053a541f0f3d4e57ccbdec4a53347dd69132009275b751", + "paper/plans/slas_accessibility_focused_20260914.md": "a63b5dceecaf658d07d011c2ea33f5cda7374a03f4f11cafc8c5c8b75b5124bf", + "paper/plans/slas_accessibility_implementation_20260914.md": "317d777bb0718a120a7bae124d6e9270016742399484845c07e5f8c7ba45a402", + "paper/plans/slas_ci_evidence_revision_20260914.md": "f198d6f5e65a1aa1c2698508dfcf928aa368b3216e960b74610112e0a3932d6b", + "paper/plans/slas_confirmed_revision_20260914.md": "645a9bdef0e8fcaf85b54c03645ad4503a892912ec6e74bf70918fdac8bb76fb", + "paper/plans/slas_framing_discussion_20260914.md": "46864ce089a90803c8f9567b2c31471417079a2b014cbd52e52b4cc46d59e486", + "paper/plans/slas_panel_pending_corrections_20260914.md": "d061fb1df24151c4210142f114bfdb605d0041dc3266b6646b735e672a75cc0b", + "paper/plans/slas_revision_20260915.md": "f84ab1bcf4e00f7ce86f8f20163ec9592939607ae0fb56a654b7c4a10abe02b6", + "paper/plans/slas_supported_refinements_20260914.md": "f319a1d62d7d113417cc2b1f6874e0edc953c1ccad60f94776a44a92fbff7e0b", + "paper/prelim_data/figures/benchmark_figure_index.md": "4b475ba84572b6440d0b7472d2ba706f19530e02eb02cbac83002b8101a96033", + "paper/prelim_data/figures/cppipe_accuracy.png": "1008e8f706af822849df6b18759b58f9f1797ffc83f3b4f2ce0d66692e7c6e7d", + "paper/prelim_data/figures/cppipe_accuracy.svg": "97d4e2e170e6359f4b9abf5196041b3e37e7684e916e62b18d95f63ee901308a", + "paper/prelim_data/figures/cppipe_accuracy_zoom.png": "df8028826eecea55015a5ed4bfe6619838b32e4fc252cd0c8eed63bbade82aba", + "paper/prelim_data/figures/cppipe_accuracy_zoom.svg": "5161bc138e52a44abf09288bf7fc45cd3e55d58a798a33f06895fbf2f348332a", + "paper/prelim_data/figures/cppipe_assay_category_accuracy_fraction.png": "df910d8c6a9409337d49115eb73949d9e87832e05c4881a34c9917608d4333c1", + "paper/prelim_data/figures/cppipe_assay_category_accuracy_fraction.svg": "8b254816896bdd80b8fba428308b97ec9062dabf0b85e5dd2e842dda374aa03b", + "paper/prelim_data/figures/cppipe_assay_category_raw_seconds.png": "c907cc49a0f13604611860bdde6ea4344d8b3edf0825909c7fe523e30d6202f7", + "paper/prelim_data/figures/cppipe_assay_category_raw_seconds.svg": "cddd69b96160dfe7f0c0123a775817b10aa08974544bc57194912227a013e895", + "paper/prelim_data/figures/cppipe_assay_category_raw_seconds_log.png": "b8eee5c705253c4843a41194631cb4c76e0a10d30137e469cf577f7d75fec2e2", + "paper/prelim_data/figures/cppipe_assay_category_raw_seconds_log.svg": "7461fb2989c374ca22f4f23833940dc39df095ec7ee8db7c1ffb08aeeb95e36f", + "paper/prelim_data/figures/cppipe_assay_category_speedup.png": "f2ae613488733e692abcd8d8afa91f53a6738751ca92dde827426b6ad16613ca", + "paper/prelim_data/figures/cppipe_assay_category_speedup.svg": "3c5060fc3fb70cd8c76fc469fabf37a44e958b59b7d82ef521da4ad83d01dcc4", + "paper/prelim_data/figures/cppipe_assay_category_speedup_log.png": "1061d707363989fdc3e6e53fdc6c3aa8376f6119075f0e8537f65cea85c382a8", + "paper/prelim_data/figures/cppipe_assay_category_speedup_log.svg": "fcea644ad1422e78c29e4d6b286e0ad6b50913b1d34eb94c93f43be2a9083bf9", + "paper/prelim_data/figures/cppipe_average_speedup_points.csv": "22a059250707ce6ac06f5f14b45ea3ea0ff6b776fde1dd3d556cbf9ec7a889a2", + "paper/prelim_data/figures/cppipe_average_speedup_points.png": "fc9b392490ba4ce4944d5cf3d16bc3f4d1b717319c54b9d76a6b491c18d5533d", + "paper/prelim_data/figures/cppipe_average_speedup_points.svg": "1ffb2e4acc7dfc6efa5220bef963e6bbf326604964ddef15c0474571eea574cf", + "paper/prelim_data/figures/cppipe_comparison_category_metrics_long.csv": "29b2ac7be05fd378060f53a8962958ba962a11c4664eb8db672b550f6b1e14c2", + "paper/prelim_data/figures/cppipe_comparison_metrics_long.csv": "e0a492741908b7c0158bdb78682195acfa0e3f3373f81225eb912cd79e8daf29", + "paper/prelim_data/figures/cppipe_module_category_accuracy_fraction.png": "1978d937686b99fb55defd68cddedbea60a19aa924008a18fe147e1ca133e7fd", + "paper/prelim_data/figures/cppipe_module_category_accuracy_fraction.svg": "334a540ff753f6a3bb9d157dc91a872a17470322b8fa05af9b46c2010617e918", + "paper/prelim_data/figures/cppipe_module_category_raw_seconds.png": "f794f0d4ce25622262f178e8bfa620ab7b68725f830befa9c6f09f4b5d7aa5ee", + "paper/prelim_data/figures/cppipe_module_category_raw_seconds.svg": "f52456a5170ecd27d496b743e41418cfe0b15f078b889341c49d003c49107b4d", + "paper/prelim_data/figures/cppipe_module_category_raw_seconds_log.png": "d316fef1253f60b38ca8094c1e0c17c41750fd15a02ca95ad4fa12220a835d53", + "paper/prelim_data/figures/cppipe_module_category_raw_seconds_log.svg": "89095fb32e06325341e22a4404e953ef2587d5cdfa44adb81d55f4ffb2e6406a", + "paper/prelim_data/figures/cppipe_module_category_speedup.png": "a95ac2eb07e92146d8ce6c07b1b1408f63b320edb9f17ca9c27649d5d6c3fd3f", + "paper/prelim_data/figures/cppipe_module_category_speedup.svg": "0f347603f99a99d785497fd8ffc7383d81b0cd1bdb132414d7eff7e9e73f254e", + "paper/prelim_data/figures/cppipe_module_category_speedup_log.png": "fb5048b751421e98b66a38313866ab82b02818836c2e07ed9af50c39d90a74db", + "paper/prelim_data/figures/cppipe_module_category_speedup_log.svg": "1e851d4560742196aa570243d511049609425776f051c6702b3986b44106391a", + "paper/prelim_data/figures/cppipe_raw_seconds.png": "d38728e59d78f8dfdf95b53906b4cf5b8a559f7e6dceedf90a0ed27c2ea3315c", + "paper/prelim_data/figures/cppipe_raw_seconds.svg": "eb8928b34a7f02b0ff8df8b4804d02b09630c6f285c4d294bf4cd6496d931fa1", + "paper/prelim_data/figures/cppipe_raw_seconds_log.png": "4838927a2e2640d57790e8f1e1edf61f66afb6c57f4ea32d38b5a58564288e17", + "paper/prelim_data/figures/cppipe_raw_seconds_log.svg": "b3b5adc903f401e71cee4b4c9bb2dbca304162fea6412afae1bf12df801b2e32", + "paper/prelim_data/figures/cppipe_speedup.png": "69d2f05b9fe4a6538279c81c9cf6ec09e818c66ab3a003af8d0d1eb819404047", + "paper/prelim_data/figures/cppipe_speedup.svg": "865f98de6757a9d7720f80442d9fecc41da95f5104963585618ecfa6830c1ed1", + "paper/prelim_data/figures/cppipe_speedup_log.png": "48049bde3e41d503781746d8a8415c5dde9e7c1de318e4e1f6f27c5d1357a665", + "paper/prelim_data/figures/cppipe_speedup_log.svg": "ea8bd32a0bd95e7d961410526a7af5ae824e2672e1167aee00b16d5b5d33ba1d", + "paper/requirements-build.txt": "748eca6db1077e668b08accdbbbf3363dc8cd88dda17f078f5591f44ae39fafe", + "paper/review/openhcs_nature_methods_draft_review[99].docx": "482df0d16f5d22e304bf2997df35d3c537499626e47910accfc49c8edb6a2ba3", + "paper/review/openhcs_nature_methods_draft_review_plan.md": "f7d7439228f6d5161dcf31e9aac07b8a6273c90754946920425551f3183f1289", + "paper/styles/README.md": "31cd332517ab7eace982d4b4624b29962c4ea2b6e62b453fb3e33af350814d5c", + "paper/styles/elsevier-vancouver.csl": "005e915c3419eb2b84eb2b31bffc411dce3890619d3fd0ed23ac6591ac128335", + "paper/supplementary/README.md": "dd19206225db44f0cc08fb79e9ae6af400c67c26e5412742a629f5ee5ae62198", + "paper/supplementary/ci_official30_085/README.md": "0b7760be9da48d8a0e20d14e5f473f2131f47e64cf967d013ebca2fd2d2c01c3", + "paper/supplementary/ci_official30_085/observations.csv": "e87aee1631bef063b468a029d2e9c68247c0d9d90c45c8eba78fc462b615d240", + "paper/supplementary/ci_official30_085/observations.jsonl": "e5355d8625d8f774fd3aeb9eede30f807e721c0fbf668ed4ec9a3e8847783f23", + "paper/supplementary/ci_official30_085/phase_timing.csv": "bc52819438a4b1e1f1da9e9ba07a6110e337e91b8f755c2b1c5238ad8ae54c0d", + "paper/supplementary/ci_official30_085/reference_inventory.csv": "d17005e72abf61e803d0045e10448d743fd33c16e7dd1dfba7d0524326a2c68f", + "paper/supplementary/ci_official30_085/suite_metadata.json": "f20a6d2d1803e925b0e58c6221edea5d08d772160b94c1095b459f3b322a62c4", + "paper/supplementary/ci_official30_085/summary.csv": "e0e075d9b29d6b794d5dee0a2f3cf038cfe1edc8832b9188455974e8aede36a8", + "paper/supplementary/complex_cellprofiler_workflows.md": "46f46953e5e388c214b6ff07103ae0582b29af998c4c905879506113299d4ff7", + "paper/supplementary/complex_cellprofiler_workflows_provenance.json": "bb4c146789243e6c7b1184f8f52491d26bad1e670716a441b7fdf159a05491e0", + "paper/supplementary/cp_tutorial_3d_monolayer_imported.py": "d46576dc06db0ccb38756566ee81435a5dd7a7d4685037931e0ea7f8f121d3c9", + "paper/supplementary/cp_tutorial_advanced_segmentation_final_imported.py": "96a537904072149b9663ba084ab60e174b7faebbbcf8066881fa51507e0ed6a7", + "paper/supplementary/current_neurite_replay_summary.md": "47f0adfc7a54ded668eb7a3778c900466b9aec6bc0dcc07d2bbfb8067a79c68f", + "paper/supplementary/independent_agent_validation.md": "65e792fef033e0c2df1bf11f499938851038a6595b881db5040fdadfaa15ffd8", + "paper/supplementary/independent_validation/README.md": "92ee6f0a9cb858f996fa0a31b8d409b5adb4d56d43e84b4128876dd03f2f0113", + "paper/supplementary/independent_validation/bbbc007_frozen_pipeline.py": "ba22537ac2e79dc16031fe04e16ecbd1fbc84dded8c640ea7b993d5fee88a548", + "paper/supplementary/independent_validation/bbbc013_frozen_pipeline.py": "e42c6313d70ff88e0361d6795eed543a0b531b9cddb2cea36b1fba01dfe3546f", + "paper/supplementary/independent_validation/bbbc039_frozen_pipeline.py": "d30df7601c50210ea3cc16c78ee6fd1224f05e07191cb7983bf1699b821c8b88", + "paper/supplementary/neuroncyto_reference_audit.md": "0bdab3199554e593934226427ad1e3c2b0894bf5613f905572703eb8316added", + "paper/test_build_paper.py": "54aa3e622c6cd76f685ba43b005b198cab7c716f66b08864efcd1c51bdfdb07c", + "paper/test_build_regressions.py": "90ae3a7cd8ce506a1c51436772428f28e409b5fee18ec1b4d677c217945f9583", + "plans/cellprofiler_integration/architecture_design.md": "b222e7e299693a6630e7452bbc9116e46c6dbfbd673e06d3975582db65a3f6cc", + "plans/cellprofiler_integration/canonical_architecture_plan_20260504.md": "648d1622e343df7d7e76a3911731a17b86a479d83d182b1b4383a243028ee28d", + "plans/cellprofiler_openhcs_architecture_mapping.md": "010735146adf8b0e8c20cbd25a010e1dcbb5f1cdcc08fe98476dee26481d3879", + "plans/cellprofiler_refactor_plan.md": "7dd4731598cc7cca3c8166f92fa4c299ac84d4e2ee197464c9d8f5da739018e2", + "plans/context_stack/plan_02_simplify_stack_builder_call.md": "e3d3475ceac776eec930c1365799760d9f493a074e7084afa62a81e0d0982da3", + "plans/context_stack/plan_03_resolved_value_cache.md": "f4c797354a8be3ed5dd049da3dfad38d351d3294bcfd0d6bfe8758f43d26035f", + "plans/context_stack/plan_04_object_state_migration.md": "c73959ccf300ad7424b7b2b1dd71e7ed11842fb77e36e73cb5967669be810584", + "plans/context_stack/plan_04_virtual_form_state.md": "2c49b9d7ab026bbbd1d9a1c8d854ca07bd776dcfdc089372e0fab6b9f91914fb", + "plans/core_surface_reduction_plan_20260509.md": "733a1b2b24c87ea96114d157f8d62dbd7e4ec804346f5b6ca8ed5786588b78b3", + "plans/dynamic_function_registration/plan_01_dynamic_function_registration.md": "5994b1a11986ca5ae14e08fce44bd5ee9c0197f6bd5fe76cfd31b86ddbe1d9a6", + "plans/experimental_layout/plan_01_ui_widget.md": "078e0f86d84847f22731c0058f1def7dbb21d6fe2beddfa45e1cb74681a1c59f", + "plans/llm_pipeline_generation/plan_01_llm_pipeline_generator.md": "9fa8c79d4106793976278ac0257015674d5d273c5d23c817ae130738b69a3115", + "plans/object_state_extraction/plan_01_object_state.md": "efe079f196b1fb635765785bdd9198d84e40185fab3bb81f30204b9bcd3724e8", + "plans/object_state_extraction/plan_02_pfm_integration.md": "8346c24655d2a42a435a20cadb3a7e1d0ed608ae1e514ec0df28186549216c67", + "plans/pyqt_ui_extraction/plan_00_master.md": "00b7d0a5fab21082031d9157273c42ac908ee28bd9566e70fc56c671b3618f2c", + "plans/pyqt_ui_extraction/plan_01_package_scaffold.md": "620de59c2ccaf8e74d753d9e890e0b5f6065d6ef51400251ccddbbba131e8a87", + "plans/pyqt_ui_extraction/plan_02_core_utilities.md": "db94715b36944fc5d2176e59dad53008473b5903c524694f7ac29b1d75a8eb0a", + "plans/pyqt_ui_extraction/plan_03_theming_layer.md": "2519038df00630ad14e1ca30a27d1eccdef7dd41cc798cab06c421f71bfe5763", + "plans/pyqt_ui_extraction/plan_04_widget_protocols.md": "7f06fa79260774a884fb7c93f01ef3a403b8d3d9ee9c0ed6992064145e5360e8", + "plans/pyqt_ui_extraction/plan_05_extended_widgets.md": "5554b16676af640c5a4369d72ac48516acc9d7c39024c57cdf2203065c7718f3", + "plans/pyqt_ui_extraction/plan_06_animation_system.md": "022ec73d55e09ab4c66502de993c5b75aa782fba13785e366ac282c420d50278", + "plans/pyqt_ui_extraction/plan_07_service_layer.md": "f0f69c384e9e03e58c68858e0f29e7066baf409e9d74bd6907e4c0e5500b9cb5", + "plans/pyqt_ui_extraction/plan_08_widget_factory.md": "09c4e5d02c24980ff11f0a26d3a2c366f337ae53ef152e94eff021172098c30c", + "plans/pyqt_ui_extraction/plan_09_form_init_service.md": "13fca4def902719544ec8d25792b42793628df47de566c4e4e53113e783df762", + "plans/pyqt_ui_extraction/plan_10_parameter_form_manager.md": "a381115d462f9319cb0120cd0fdfc8e8e1376546369cdbdb8f46dfbdbf0486ed", + "plans/pyqt_ui_extraction/plan_11_import_updates.md": "359d71bcb96766154fec81184887db0e35ddb9e4df032e0640da499048429cff", + "plans/pyqt_ui_extraction/plan_12_test_migration.md": "01e6f20e33e6df139a48f2df4bb79a913baec3a83d490b899ba0747a8f0cc29d", + "plans/pyqt_ui_extraction/plan_13_documentation.md": "4dc181ca1487ebe353b577cae6ebc6a6c45bcbdaa758559494176ef86642d4fe", + "plans/root-artifact-cleanup.md": "68ba0de9c8eec375680855d574e2d248e41bbb0deec98c9fa9c246dec365bf57", + "plans/rot_elimination/plan_01_python_source_serializer.md": "5a5f7aead46dfc22aa2833d487d1ad486c6ca4302d4603dd4588e71f7fd45971", + "plans/runtime_externalization_plan.md": "86e610a423d2e1cb45135da721c25f6464314619eeccf8b7311f6db53cfb2293", + "plans/runtime_value_artifact_upgrade_plan.md": "d08dc2994c09828a866fb44300bfa775a8a278cf402b44e3d458555718ca556b", + "plans/time_travel/plan_06_collection_aware_object_state_UPDATED.md": "0e154feaea979d1985ffbd12ecae52a5a17fccf318d75c3e3c556c55bf5aa73b", + "plans/ui-anti-ducktyping/README.md": "1ddf19862b436ac940ed26abee2c3718e0a887cb0d1e0a27b8b85bf33b8c5a24", + "plans/ui-anti-ducktyping/plan_01_context_tree.md": "5dab2381970bacab92681b91c3a923b9058935fa208185bb2d46f05e52c5f76a", + "plans/ui-anti-ducktyping/plan_01_widget_protocol_system.md": "8fa7d7b3b8af0fc2532775f0ba46de10225a05f547f896bdb8d323c653a70af3", + "plans/ui-anti-ducktyping/plan_02_widget_adapter_pattern.md": "b510b795b7b6271f1dbb981584e8abd63bada0b95a7dfa31a44710499d9972b6", + "plans/ui-anti-ducktyping/plan_03_parameter_form_simplification.md": "e3728492d401e101ee2b41e76144f3c567265c83d9bd60474f9f1c62deb9dda8", + "plans/ui-anti-ducktyping/plan_04_signal_connection_registry.md": "c52af0884034967e87b7a94c541204daeeaa0bf91a40b81ccdf8a40060bc5347", + "plans/ui-anti-ducktyping/plan_05_migration_and_validation.md": "1d84c074ea16f26abd773209e7df4e98530db831ac67c7c5502e6806c2415300", + "plans/ui-anti-ducktyping/plan_06_metaprogramming_simplification.md": "283efb6636557fbd6a7ea4a1cad63bd293e731a949ea50d41221902c92f8e758", + "plans/ui-anti-ducktyping/plan_07_aggressive_abstraction.md": "766d6ce514430d33d4a4d1c03345c61aadd48068d4dd444d0017c59756289d82", + "plans/ui_refactor/plan_14_eliminate_values_dict.md": "7d958d7f31574d6bc98e691c9a8595592b28dedbdf4ec2f6ae2578a03433436c", + "plans/zeroc_ice_dependency_solution.md": "a683c7bb286b4ff3cca361d97ec067067e9f043e0a2e8ffb958ffab20f6863a3", + "pyproject.toml": "1d263e3866d804a642dec3a37f8d5cd9d7df95aa40c807c59624e7906d648aec", + "pytest.ini": "abeb2cd3d7ac83c5988690e5b991c0989a96b46d62febc48ba1c7664b6a30d1f", + "requirements-omero.txt": "c631b5954fe3ec51c5167d622cf1d73359dde5432635261a70ee7b73ebf51b2e", + "scripts/annotate_wells_with_experimental_metadata.py": "706221e6b1dd2b082998016845371be39f94f3ad549cac105003f09bdbda805c", + "scripts/benchmark_cellprofiler_fixtures.py": "0eb75c5235552b1f337e879eb712012b948beb41273a29466159743655be876d", + "scripts/benchmark_cellprofiler_vs_openhcs.py": "d5607333b0595b7553358db021d584af5bacbffde8c95ced5c7fdea160a06902", + "scripts/benchmark_cppipe_throughput_scaling.py": "19a231a3fa56b35954dec184cdfbb1aebcbe4cca6467270a89e4e9517b303c43", + "scripts/benchmark_cppipe_well_throughput.py": "73b30d0cc3174c04cb479a72e97fe094ef6ad9fcfdacbfb37e43fbaad53560c3", + "scripts/blind_analysis/README.rst": "66b66d96462ba385195f1e30e4d86a6cb40cf82bd70f0bf64759279514570362", + "scripts/blind_analysis/VALIDATION.rst": "a40422130589d795422db01567f90f65e5ac0a9c889a2a0dad3d9caad20d7188", + "scripts/blind_analysis/mcp-client.sh": "0b9276c85f682a944f0babb1491d63e20db0080783e5d90a091c00350e614896", + "scripts/blind_analysis/recorded-mcp.sh": "fab193c24c35ae7b80fbc4b2da9e1af4c83087f79fff7a527ebb5c854f19829c", + "scripts/build_hosted_mcp_plugin.py": "b787dfeccdf08639b3773702742e5325224653c939d25fbf33173b2f27ea497a", + "scripts/build_mcp_knowledge_assets.py": "efae1cd52a411ec009580c058583e97f10ea16bb995c72cc2231b240bc01cef8", + "scripts/build_website.py": "9850f134c1e2bc600c5b291b77d4c77d82a5ec9ba80eebfade7dd28739ea557d", + "scripts/capture_media_gallery.py": "987f0b3fe09f98fff0e7878053867311af7b65004569bd75937f627464e063b6", + "scripts/check_basicpy_source.py": "80bb44b887d4ec7cd7bc44a87163cfbd8eb3be6a783bd6ff8a2f6782b6fbc53a", + "scripts/check_mcp_memory_ownership.py": "2f177b54aada3199271c20960e749c5ad492b5a8f277faa7494d5be4bb411813", + "scripts/check_refactor_r1.py": "4c6282f52e7c188068dd9d63399f5522a7cb1d222504d0c0b809be10303884ca", + "scripts/codemods/audit_cellprofiler_declaration_semantics.py": "e5bf793ab628fd87c065c5776770c7c69448d38c6970b25f932679ec11190efa", + "scripts/codemods/collapse_cellprofiler_artifact_binding_declarations.py": "9f4db8c587411877491a81d0de546ab663dc788fae7a231fa16fbefc30cf042f", + "scripts/codemods/collapse_cellprofiler_artifact_output_hooks.py": "735d9a0c6124fdf5d1eac5f952464233ff8f2cf40b2dcb9e669b6b62469b7b17", + "scripts/codemods/delete_cellprofiler_special_input_policy.py": "bfeb1bcfe6d935d041c02351226afd5976f827ded8d9d20f676a1ab52e806cf5", + "scripts/codemods/delete_cellprofiler_typed_artifact_mixins.py": "b2e536e0f1d7dafe807f5da2415883b3da2b0f4702ce9905049a2584c932687d", + "scripts/codemods/migrate_runtime_input_binding_request_api.py": "454911bfe649a7f55591d9566bfbd566924bc77a623973dbc15b080895debd23", + "scripts/codemods/order_cellprofiler_setting_binding_declarations.py": "de5ce8f9f6648ac3bee14c2236de7d2b0a8a9b40b8f3af9f57a1abb621d64ab6", + "scripts/codemods/replace_cellprofiler_typed_binding_queries.py": "ea634ee559c7335c1077855c5043749b39630a2e2e5a48dbf08896c490a98457", + "scripts/codemods/split_cellprofiler_module_measurement_owner.py": "a23e15ceff1aaaf206732b3175ede59f137ea3fbaeeb80a51e27e7ecf67d3c44", + "scripts/codemods/split_cellprofiler_module_settings_owner.py": "7baef4284974307c68c9c17d7ddb56861fce4e125c30ce0814a1db1a4e5af9da", + "scripts/dev_install.py": "b243e436e5c04e2a7cb9a8b57b6a0965e558f7996a5ab949c2a95002adb38933", + "scripts/figures/README.md": "b0221de1a158b6f0e12f158d70dbdaf826f9261f211c2a5afbd71876bd88dfa6", + "scripts/figures/generate_automated_plots.py": "7c5ac5c64321dd347676cbd8e99345ec029d89ea5e7bb2113df6a795392dc957", + "scripts/figures/generate_figure_mosaics.py": "bdd4e5ff927e6b5ee3ee336e355d063f1d72272f3e8369c93fa82af9bfea9c5b", + "scripts/figures/generate_figure_overlays.py": "1856cea883da92c703e69c0b77910758592d4a6b837ee7900f13daff79a6abfb", + "scripts/figures/generate_xy_xz_composite_figures.py": "fc4fff47c547d77e258d9d8c798e4a75a0ce073a70edb0d594e217e8aba9713e", + "scripts/figures/orthogonal_projections/__init__.py": "ed8c1a3121eb209d918153f1fb900f42729751462371f6748a13a2b231b0b6a8", + "scripts/figures/orthogonal_projections/cli.py": "89cf3f6631890c0c2ec957daee7eecf90b7a5640c74fc98a77c231b4678e9826", + "scripts/figures/orthogonal_projections/composer.py": "4b29181a662a73b7320aa72f68f7dba645957f4580e8a65d63a61f1e9b557557", + "scripts/figures/orthogonal_projections/constants.py": "870673e584e224f9a492f84c7aec044c71660cb9c722bade114dc734f8958c9e", + "scripts/figures/orthogonal_projections/discovery.py": "139e6fb2e67809e23da465c5a1944c156a04313d2c6b28b03bd8c641871cde6b", + "scripts/figures/orthogonal_projections/exporters/__init__.py": "f20b766823fd30f6baef38ad85337133f63cca31ce8d85807093c429f9f0b3d1", + "scripts/figures/orthogonal_projections/exporters/assets.py": "ba3f324bddb11ab1019f77db5bd2c081d79c4b734aca0b95b3e57eedbbf2c679", + "scripts/figures/orthogonal_projections/exporters/grouping.py": "bb75b6465d2ce31c60ddfa1010fb697f0e573ef2a09492838e938a4be1223e4c", + "scripts/figures/orthogonal_projections/exporters/layouts.py": "10ba73763e907ae51e5682af0845d842a4bea2fbde3336e7e5860da01f1e95e3", + "scripts/figures/orthogonal_projections/exporters/models.py": "45e84afe264aa1a2a7b7f14b496acb27913c6ff02c257870426777b9a468c457", + "scripts/figures/orthogonal_projections/exporters/powerpoint.py": "c05492f0edb9dc4a45993dbdae0f1cc62d03712dd282b9d09a7625b712df08d4", + "scripts/figures/orthogonal_projections/exporters/service.py": "834a0210eaa25cdc024dffe2b1edd6471856658484489b226299e0f9fdab529f", + "scripts/figures/orthogonal_projections/io_handler.py": "2ba9f49646db722f90334f902acebc9e57045f1c81d91d915224ac4abb52ac24", + "scripts/figures/orthogonal_projections/labeling.py": "1ffabf6335e016c0b73443b9aba8c03f2eb387f330bf6e30815317bd93365d3a", + "scripts/figures/orthogonal_projections/mosaic.py": "58e8a503f752dea44dc831718fcb013d368aa4f6b4d524815bd8ec2ee49e1d69", + "scripts/gallery_catalog.py": "7f493e0cb305e14ee4cf7d3e995c67df4200186a8a8aaf00eef0bc66d8d191cf", + "scripts/generate_brand_svgs.py": "2abd365f16d6ecfd316be22f6356d869e8e5d2c876a6a0c48181ea3c0daf813c", + "scripts/generate_cppipe_benchmark_figures.py": "5320cf489061bb49c69ab8863a3c6ae6775f53cef11edd02c989dfc7f17171e1", + "scripts/generate_cppipe_throughput_figures.py": "ef0256842ae53232b8720ff853f04f5e731243d343979691cc2d15cff0ffae1f", + "scripts/generate_lab_meeting_deck.py": "be7922c3cadb469af36287000bd6ac16e9d32c51d13b790e20423380f32c7ce9", + "scripts/generate_lab_meeting_summary_figures.py": "38e41a6782da4453c0d7976175c461c6d2c2bfe1d472cd9572dc7bbc116f5c78", + "scripts/install_ci_candidate.py": "840eb6612bb41758979104cab1165d7e2297011fc6ea907ab67b9112f349b3e2", + "scripts/install_omero_deps.py": "17d63a27e1635ad624b80fd0eb0668f8b8f01f62e30a303439353634e030b4db", + "scripts/macos_installer_window_probe.swift": "45b22046ae4c98d697beba8a6f91fa3d72c07083b91dcec83a48811795b0552d", + "scripts/master_multi_plate_demo.py": "8115619d0dd4aeedfd8a4ce1b20f7eabd8f3c1f0ffbdc20e4dc8b2231cff7ffb", + "scripts/mcp_assay_showcase.py": "b33e3bcf0babebf7715bee8f4162d65d1d48128f061b8e8ae45344a6adfdd046", + "scripts/mcp_thesis_demo_live.py": "5d26a8b3624775ca9b030b504b7bbc257f57bbf4209c4bdf5604f5cb6d27dd86", + "scripts/mcp_thesis_demo_smoke.sh": "874189a27f7191abcc48ff9d85391d59cc1497465db4721f532d2c07e189ed42", + "scripts/migrate_cellprofiler_function_facade.py": "09acc565958e4ce7bf847a3ff59868f5917ed6430bd72c796865674a1be40cbc", + "scripts/napari-plugins/README.md": "485dba3b9eafef0f216eccf0360237a37d580d0b7a100abf224a90a9660fa123", + "scripts/napari-plugins/napari_orthogonal_projections.py": "f6850edf7f42ccf8f78661594f5063054d088c6ca74d153f6ad51c9647fafcda", + "scripts/prepare_cellprofiler_benchmark_datasets.py": "5721186ca36ba9708acfdaca1f393d4826cf08c044f1fbcc93b8b8a159c010f7", + "scripts/prepare_cellprofiler_reference_exports.py": "05f7d8d3fcac499a546a3fbebf33eb9c006e6df7cd1c47affb5a9175755df43d", + "scripts/prototype_flatten_object_state.py": "b3019b9a4ab451dc10b989c9261755ace355ce0520932ffa8a5146f3d471491f", + "scripts/prototype_unified_none_forcing.py": "ae3a8dc80e258fb6b766595645b34ff0e7e81455b5b7fdbdf1e9be59a8f9d3a0", + "scripts/release.py": "c7afa31cd6f52472fcbca3a6e5df14027fd563c1169c1a414c99eff6989c413e", + "scripts/release_readiness.py": "f8822ade20e4cf9186414986bf2aea4679a5598442d46057267b2ce5dbc0a003", + "scripts/render_brand_assets.sh": "4fb956d28632b8cd8e311c6e93436213dec8c211e9074af8de8c93ed15153bc6", + "scripts/render_installer_contract.py": "da9045e1012cb0a71ff0dfd2f2d9fc98232299f5a2f019b01228e344cf3b40e7", + "scripts/requirements-quality.txt": "a57bf3bf9f3096d3b25a577c5387102e8304e6d8b3a3786c8c31bbafc8a50f80", + "scripts/requirements.txt": "1a1afae3ba770a4954322bfb18c1fe30f23c0b1390fb5664a0da6af6ad5437b3", + "scripts/resolve_successful_job_baseline.py": "8e6541a53dac376176a63cb449e9166a425ef673954847cccd96fe444d60ad48", + "scripts/run_cellprofiler_cppipe_parity.py": "78bb8501f88da47ea6b97ac40a9d138c4d01669505c10e4dff0d2bb010263359", + "scripts/run_experimental_analysis.py": "72b6c60c3e3f5710f4d6b074febb6eb8e68ea96b54b7065b80a3abc0310e145c", + "scripts/run_installed_tests.py": "db4991c7d7fa1cb1cfd5918525f26b42fce799fb4f8136d8740001a9e8ac6b56", + "scripts/smoke_installed_desktop.py": "f745f93e245e5c1b02f6e0ece3a4a0e2af086c3cab77282e3907a167f5ce0a7f", + "scripts/smoke_installed_gui.py": "a5af7f55eab45b7ab43772a9ff8cf758e4940c5ad58857611cc51dbe6004bd89", + "scripts/smoke_installed_mcp.py": "45ce72798566b618b853157d78f2020a874628e4b13d81ea919923152ffcc7bf", + "scripts/smoke_macos_installer_window.sh": "8111d1a357b745cba9620656f46ed1e9ace52c65c028e9bf1f46277dff7aca06", + "scripts/smoke_native_granularity_wheel.py": "4cb4b3738814f6ae3598373dc5689cd589aaab011f2cf356731922d81a79115c", + "scripts/smoke_owner_quickstarts.py": "0d64707dd6c075490c26721acac53ab1f68a1c6b38a38eec6be296f7a19d0c1d", + "scripts/smoke_staged_desktop_update.py": "7e20230236066f43712b0fa6bc0b13ea365ec02cb114ec0066371765ae1bb93c", + "scripts/smoke_windows_installer_window.ps1": "c41cb5b5b0ae935e43843fe0589911b41dbbf616917866bf6d02b98d14dd8044", + "scripts/stage_ci_candidate_version.py": "ce62346132229c5422d33f366763020a83fa73f786c7f61227e936dc5121e241", + "scripts/summarize_cellprofiler_reference_export_run.py": "f9aaf0c05adf30320cad72d5f80b84aafa23060b770407886165246796ff06d5", + "scripts/summarize_cellprofiler_reference_inventory.py": "4927e95b695dec31a56b093c1dfbfd12c0e2bfee001a2cdcd74923f8ba5c27ec", + "scripts/summarize_runtime_image_pair_receipts.py": "72007ab392a14fe56aca18791c7095b7b627dd0e353c0a1b73cd463c8f4ae816", + "scripts/summarize_runtime_profile.py": "e8852140959bec6e40f6f6de73152f477f9da4c8700e8e027a14d42161de1ddf", + "scripts/sync_mcp_release_metadata.py": "95b40ffc3c85af929a553f6fbc9fbaded3c7a40ba7a92bf4eeb6227747a784ca", + "scripts/test_real_global_config.py": "62f78776fb85c8671f20d82144e61063eac288923cda3c99f1884972b2e86bd7", + "scripts/validate_docs.py": "ea0870b2a4e5dcd0cee0a7dcfb00a1e7720a40c1e7413e02eb6a8e49c7423f21", + "scripts/validate_local_release_floors.py": "790b521d6fc60dc38fb4a55ba2d56f4d91a1eb956f28477e98b29313194cf6e6", + "scripts/validate_wheel_deployment.py": "8ae2c9b6c121579816fa5065f7e6ee6ce8f6ee4d3e014ce911c97dc60802d6b7", + "scripts/verify_existing_imagej_bundle.py": "2cee4885f1e1b89a7cd246833121db536dc90b9f6e9f985b85b3244a54b564d3", + "scripts/verify_release_ready.py": "d72e3290f473530fe041a9188190072fd222db991e5860c83b49b4d5aa107f18", + "scripts/wait_for_pypi_release.py": "c98c9fca6b0fa852a245eca10cbe25456c4a05fa150ac97f6c83db99428efd1c", + "scripts/website_gallery_projection.py": "22aba173524c50d274096b32af72803fe4db962f0aef829df9de21ca77020523", + "server.json": "0bbc28e4a91727a98381449c47c4669d9cbacc14bdd5bad60359b2c72da820a8", + "setup.cfg": "110938fc5f369a34d462477768998e4fafd9d2f9749e2897db19620522fe598d", + "setup.py": "4f72c93d6d64a44f02f92857fda73fd69bd8b8f7e88168b53190675ad79030c8", + "tests/FIJI_RUNTIME.md": "b51b5fb4b61b5aacf0be6f350c359e0e0e28dadd6f96e96c3010fd7ba3f7e37c", + "tests/README.md": "febeca8e52955771f8d59f29bfa70d2808344e10e5a86c0fd472d4ec18bd8bf4", + "tests/__init__.py": "735469839c842bc3fbc34792d87ecca2fb190d80bc5c631024bb850a07b5bbfb", + "tests/conftest.py": "8ddda85bd90bfed62fe62c166e5c1262752bcca5bc401617105a8f64d66e7be5", + "tests/core/test_alias_property.py": "06d3041f154e341ee17278687c92b55a1e6232f2e32851901b58917203f946b7", + "tests/diagnostics/basicpy_observation_fixture.py": "298cf2b0b86238846c78505bff1fcf49ba17cff6016fb1370352973bfc32ed51", + "tests/diagnostics/centrosome_watershed_reference_worker.py": "5667a88fccf127c2bcbf86a28ad210b1aae1abf3e06873daf312414587035382", + "tests/diagnostics/check_centrosome_watershed_reference.py": "16290b9f7f19f9795237bc8388b4d178b4f177bb3bb7f31554d60a5fb9787889", + "tests/diagnostics/check_custom_registration_live.py": "5f4db820e51c1181ba3dab1ab1d90e252303574b4d08fe8821c0dfddc86d802c", + "tests/diagnostics/check_owned_bootstrap_live.py": "8ce6a29bfc4c4279589eb5dbb3a160320c7524e491eef086442d162c575c7b09", + "tests/diagnostics/check_viewer_feature_measurement_live.py": "cc61ff29a05f34b827a05e261d312a0aa472bf90cc5d0570758641896e25adc4", + "tests/diagnostics/create_basicpy_acquisition_fixture.py": "0a773fd1d2efa85ecfc118b2f13b22186dc06f27f172bbe4d49f8e7c292ed5ff", + "tests/diagnostics/create_native_point_viewer_fixture.py": "de84bb0dc53908f32223af8750b08eb5f8af75dce2a516e9310ad688167736ba", + "tests/diagnostics/create_native_result_reopening_fixture.py": "8740d81e333548914677bbcff4fa36d4ac683fe0fd9bb441b1524ddae29e535b", + "tests/diagnostics/create_orthogonal_viewer_fixture.py": "b0a6fd3e3264586e360a54a76e7970203813df0f15dd738ff3068627bd02f1f1", + "tests/diagnostics/orthogonal_plate.HTD": "86d74d0e7397fac55569be4e9c6b5cb93d38d4510796a2da31985662a165e05d", + "tests/diagnostics/owned_bootstrap_readback.py": "c8aff5143d454b47fbbeea369fc11247b0dfaeb2b3d2702d51e2493e4d491e7e", + "tests/diagnostics/registration_probe_source.py": "64a0fc300bfe17377ffc608ccb8d714aac811abccbb5cea0b0a032a77c854f72", + "tests/diagnostics/volume_projection_fixture.py": "9b737ed5e669c6f2325cc4af9ebb0b39b706121478149315474f464e3cc30c80", + "tests/fixtures/cellprofiler/quality_control_4281.workspace": "884f14365ed643c8dd7050ea77e416a1b7253dca83ff11d2e01aa54a8e07bdc6", + "tests/fixtures/mcp/start-owned-runtime-400.json": "fe227ffa97abd12b8e394ca78b955616ab4ce522f771940f64d320bdeb33a6a6", + "tests/installer/pytest.ini": "65e6856a27f9ade23ef94ce5d5dc606836a6b4b61e57dfc9a090731497724996", + "tests/installer/test_installed_desktop_smoke.py": "5ac9f0e9e0e2ffe73cbab940da132421424e355c354b7476a8a072090c5aad00", + "tests/installer/test_installer_branding.py": "1045498970a1100616ff58797014f6fdfe2b1d6f1cb687acc9834f9d4c53a7d1", + "tests/installer/test_installer_contract.py": "42a551a7806f043ff464402795bc493ab8ee750fa0dcfa1e1822a4b6e79f8405", + "tests/installer/test_installer_signing.py": "c8f9d050c4337086766e732bb09b39bd7cd61d0f7c4866fd66f6417d99c4ca1b", + "tests/installer/test_macos_dmg_lifecycle.py": "a2cadffe4ad4353b4d2ed4664443f6714f91d6929491eae116dc9d8a91f89862", + "tests/installer/test_macos_simple_installer.py": "49c2948a689e7b406bdc0bde312fe8b2ad1043c6d3dea626f531ef72c62d6e55", + "tests/installer/test_windows_simple_installer.py": "64ac03a0674411b569fafb9ece01c73583b5c4e9184acad054015d23d4f60d6e", + "tests/integration/conftest.py": "7397b869b835c535a8707412e35f5f4b25aa92eec5b7fe9300c83dbce0bc987a", + "tests/integration/helpers/__init__.py": "69254da608bfc5c0139c0728b753886c029f4779b856578c24cfbd24a973537b", + "tests/integration/helpers/fixture_utils.py": "7c75a2f98a2a90c226d0cccdae3ce9090b8d5d45cec7656c6924214ab9222846", + "tests/integration/helpers/omero_utils.py": "0a719c540deaf090118add947bdfa8a0229089220376ecbd33373d1fcf51a407", + "tests/integration/test_agent_observation_export_zmq.py": "ee572c151db282100ebca51d185981eba522599d28571804e70f37727dde2201", + "tests/integration/test_basicpy_real_fit.py": "d6f309675773109723db671a1b16815d34931fa946d9afd9ff4421b4e07ffea2", + "tests/integration/test_benchmark_openhcs_adapter_cppipe.py": "d12bfa29a780635d7154eaa8ee02fce440be067586a58994694fe5268ecca084", + "tests/integration/test_bioformats_handler_runtime.py": "66b9c96eae751e345a82e41f5117129b3120ecac8e55ecc55f7d55b73675d7ef", + "tests/integration/test_bioformats_imagexpress_synthetic.py": "017784acafcd049360c478c3d83feef9965e06329003a9b72a9a6096bf71ae00", + "tests/integration/test_cellprofiler_generated_pipeline.py": "c9e479a9af3ad76f42f8079603b4fa31effa7597b2a7d11787272dd2b093dbf4", + "tests/integration/test_cellprofiler_official30_zmq.py": "bc5abfddf076996a050b0601c46b6039d2d812ab57cd303847b241e477176f53", + "tests/integration/test_chained_callable_lineage_journey.py": "542450fce7a490777def1fe15b095a3e63907ca0d3e124c0ff41e8ca552ee3b7", + "tests/integration/test_compiled_artifact_inspection.py": "cdf70c26c44db7716ed36bc7533de8a5dd38372ccd255b07657523639afa3fbe", + "tests/integration/test_count_cells_simple_dual_channel.py": "96aad0a93805768a9841398e6b477b6aadee7e012c1eae91897273aa57608bac", + "tests/integration/test_custom_source_transport.py": "4b6b4352765d572fb6e6462c44300f09f020e1e729519b836f2d9c3e45b2ca51", + "tests/integration/test_generated_source_relative_paths.py": "d5a5cb107ee77df903b280aa65d0954a52846fc2b073a5bd5426607ffc2f9c6e", + "tests/integration/test_main.py": "1a0c532eb631a89b77f92a4202a7b55033c86d7b872350156f106d276b061e9f", + "tests/integration/test_measurement_declaration_journey.py": "3c7cb5086c8f2e99f96a9269aafa6a9d89ccd88f6699c04e3d5ffa0d00859b9a", + "tests/integration/test_neurite_outgrowth_synthetic_plate.py": "5b220237ea1f257d7572bc0c5ce10c069c9e669c02a9d1d70148a09af63e6ca7", + "tests/integration/test_primary_segmentation_diagnostics_journey.py": "f2600725abf522cbc0e3610fa388edfee1acf61fd3fa121aa478a756befa1e6e", + "tests/integration/test_source_store_code_mode_zmq.py": "3a20bd47775026f08a1e34a0c15894fc541b61edf622decaf2ffeb5357c927f3", + "tests/ome_zarr_fixture.py": "38e65ae14e1a34e3bb89d7435d25ac2b3adb216b03d963caceed257db2b15cef", + "tests/pyqt_gui/conftest.py": "a1cbff794d8624ffd1d895103e70fa924456932472617e8b04a33f8a41823477", + "tests/pyqt_gui/integration/test_end_to_end_workflow_foundation.py": "db2f98b9878565df935d78aaf8d8365cdac5fe160cd4fcee2d6246502dc355d5", + "tests/pyqt_gui/test_code_document_normalization.py": "56efa136f5eedd8a7a724a3d8749d9191f99a25ea206164688f54ceb8c28a974", + "tests/pyqt_gui/test_dual_editor_window_context.py": "4f046917d1b88b4f9d685a3a0405eaa46cc31e907a1007c02521522044bc2854", + "tests/pyqt_gui/test_image_browser_filter_controller.py": "f0e6e297212fc72fa0a855d0244167e781441a20fd612f49740a96d0d60be1be", + "tests/pyqt_gui/test_managed_windows.py": "a20d63527e04b9563c50e4f099c6f4152ebf8967d4ae39d8142c997d4281c09f", + "tests/pytest_integration_options.py": "de36c47ead5e45020fcd6f72cf5ab20bab195962d22ab8e69cde604a324a9ab8", + "tests/runtime_diagnostics/PRIMARY-DIAGNOSTICS-20260930.rst": "772648162e7dec847680cbcd3b148f4345d2139035a2941d5f989da2bc9eef8c", + "tests/runtime_diagnostics/execution-progress-pin-20260929.md": "84e3c34b0c47ebb4b908ba17b931eddfcda038dff122501567c870bb50d9d6d6", + "tests/runtime_diagnostics/orthogonal_class_census.py": "1faa1bbf3b4c7e87cf7269c6e83f7103aa0dbb5a6ef2d06f0bd188df1ae229fa", + "tests/runtime_diagnostics/orthogonal_native_7d.py": "9fb7b5dd670fde2081c68f49b295b749fac53011a0280054e9dc63c8d373d66d", + "tests/runtime_diagnostics/registration_attach_only_20260929/pytest.txt": "fb26f89183ebadd3f83d6e84166cfb856ec0e132330328b2fe432a10fb430f73", + "tests/runtime_diagnostics/registration_attach_only_20260929/resources.txt": "644c97eb4efa42fa736a0c89ae794016f7e0bf76ef72e54fde03234b86bf47a5", + "tests/runtime_diagnostics/registration_live_20260929_attempt01/foreign-control.jsonl": "1abca4e9708c84c8b24e629d0ce8902731c50e202068c1cd502cfdb388e5ca9b", + "tests/runtime_diagnostics/registration_live_20260929_attempt01/foreign-stderr.txt": "8dd2e1b622f473b28981f812a8651b95c6a1bbc311e2388ab7fccf24a229c9fa", + "tests/runtime_diagnostics/registration_live_20260929_attempt01/journey.json": "e41190a4f016d7b64c5618da96c770c7308ed1c8610c36f107b543aad831438f", + "tests/runtime_diagnostics/registration_live_20260929_attempt01/mcp-stderr.txt": "fc2c6374f06e95a9eb5610df83cb510fd1eb89c0e174891b897355ace2f3bb5c", + "tests/runtime_diagnostics/registration_live_20260929_attempt01/owned-control.jsonl": "fe9d5adb994a86327f6e8ca9e8181038dbe04a25b78af3370ebbbc998dad7a9a", + "tests/runtime_diagnostics/registration_live_20260929_attempt01/owned-stderr.txt": "7eb6dab22289d0a5c5d130980368e672864e9e1e01fc2f94e7f6799b6b4d33ca", + "tests/runtime_diagnostics/registration_live_20260929_attempt01/unsupported-control.jsonl": "b539167f827b6829fd8d0a568089e89e7ece840e146037d773e8d6c356a2c5ad", + "tests/runtime_diagnostics/registration_live_20260929_attempt01/unsupported-stderr.txt": "14c2415d6552eda8c37656c0c526b94fa1296f9463bb82de5837b3804821c75d", + "tests/runtime_diagnostics/registration_live_20260929_attempt02/foreign-control.jsonl": "baa83d55f2841e39e194eb65f78989efe51446a973bceeec96b5051942877564", + "tests/runtime_diagnostics/registration_live_20260929_attempt02/foreign-stderr.txt": "e3a8458c276dc39eb4bce5ffa1488bc2a718799e5eab47b144d0e4b82a0b8abb", + "tests/runtime_diagnostics/registration_live_20260929_attempt02/journey.json": "cf56db02a6eaac884e8e1d6e28b870b7b6bdb11a5b994e41c1295106a1c5f72e", + "tests/runtime_diagnostics/registration_live_20260929_attempt02/mcp-stderr.txt": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "tests/runtime_diagnostics/registration_live_20260929_attempt02/owned-control.jsonl": "e8786c2b9e4310d7345412eca3a9883ad5e67c3d8d5af9b83c67f48f07f6a48e", + "tests/runtime_diagnostics/registration_live_20260929_attempt02/owned-stderr.txt": "bd147f73c5fce24293ed7b2875b989930b7003bf10d4399f064a0008b452b81d", + "tests/runtime_diagnostics/registration_live_20260929_attempt02/unsupported-control.jsonl": "a8352cb01963547616e4b1bb3501ef4db46e8cdd6eadd176af8a18440ed57076", + "tests/runtime_diagnostics/registration_live_20260929_attempt02/unsupported-stderr.txt": "0d2c51051fd9a90cd98d682d6a6358f6a0dd485f3b4b4857b74ea257b271e868", + "tests/runtime_diagnostics/registration_main240_build_20260929/build.txt": "3a29d6230f783c6fc1854fc3fcb0cdcc579c32a8cba2392c95eccb4139bf8a6e", + "tests/runtime_diagnostics/registration_main240_build_20260929/imports.txt": "f3b4d1ff39b185c6af834bec4444970531c2653b61b941dcc58750021cfd7331", + "tests/runtime_diagnostics/registration_main240_build_20260929/resources.txt": "b67acd42ff559e3316e0ceaa56b5f95ee8c7b301b7b81c322701d751ab5fd2fe", + "tests/runtime_diagnostics/registration_main240_tests_20260929/pytest.txt": "53ffa0b6948c174f3fb6d4ed3dc9ead02170b1f49e6185c420835c46ffecd1d8", + "tests/runtime_diagnostics/registration_main240_tests_20260929/resources.txt": "056b44c7059c7dd586973f0969578452370c43b95fa263d87863c6bc6a47c187", + "tests/runtime_diagnostics/registration_native_build_20260929/build.log": "7122ffcb495bb45a2b4d9063c96861c5d2683fa033bf1ae3230b52d3537dd733", + "tests/runtime_diagnostics/registration_native_build_20260929/import.json": "4e1ceab558a4b63704f41ac6375595565f4b4ba349c21eae89398521c85457c5", + "tests/runtime_diagnostics/registration_native_build_20260929/resources.txt": "02d71e1fb56faae9216d9287bd87644f1d31dcf108d508b765a4e2dc663043ba", + "tests/runtime_diagnostics/registration_onboarding_20260929/pytest.txt": "0da18c9ca7a6231353214018aa707fd81630a2b95cab45b2f0cb613d358ba929", + "tests/runtime_diagnostics/registration_onboarding_20260929/pytest_initial.txt": "37330b31b71345202a4ab78530f650f5d4a8abcd433361ddc5d3278f39fb48eb", + "tests/runtime_diagnostics/registration_onboarding_20260929/resources.txt": "c4bdad60bd8f0a99040cc3ad08455dcacb2a4cda6e544a2ea021e272fda7e13a", + "tests/runtime_diagnostics/registration_onboarding_20260929/resources_initial.txt": "b3d11bd4e27f7046304b6bcdbf48e586d1d5ac76f4313867287132f0cbb873a1", + "tests/runtime_diagnostics/registration_onboarding_20260929/scope.md": "dd23963ef6049c781aec82dc9a8907965736decced397f51e8428565661f9b6d", + "tests/runtime_diagnostics/registration_owner_five_20260929/pytest.txt": "ee91b7c460a9863f15a58aa1bfb769fb193d35d9ce105deacfdfae7c1df82a2c", + "tests/runtime_diagnostics/registration_owner_five_20260929/receipt.json": "5387b7a7ef1e3fa518ea5738f1350d54f53209cba0c1b56933b603cdf97e61a8", + "tests/runtime_diagnostics/registration_readiness_20260929/pytest.txt": "fe8eb2648bbda97f6dab3422d81e9384157eaa7a49986cc0a26b08198095180c", + "tests/runtime_diagnostics/registration_readiness_20260929/receipt.json": "085b8f0a08c05e0372279b4fa7875a7dad3f5198679e629384a2e3dff401afef", + "tests/runtime_diagnostics/registration_readiness_20260929/resources.txt": "2e7a8be119bccaa5376ad8acc2a3e984b2eb295bdbe90af70f7036570c317107", + "tests/runtime_diagnostics/viewer_admission_live_20260930/captures-reused/20260930T132110280409Z_napari_5794_OpenHCS_Napari_Visualization.png": "e6da1cc37613ef6faf4d4bd1d3c8b503e9d2f53f7fb315c661cd34b8e62735f3", + "tests/runtime_diagnostics/viewer_admission_live_20260930/captures/20260930T131815752112Z_napari_5794_OpenHCS_Napari_Visualization.png": "af10d4def4dd0e67e31ccd8425b5850a3b0df5cfd43b9c726f8b8f4621226be4", + "tests/runtime_diagnostics/viewer_admission_live_20260930/first-client-parser-failure.jsonl": "05d9234693a89b3adfef29f65fc441361a5b16544c9ab171d97e06d313be6ff6", + "tests/runtime_diagnostics/viewer_admission_live_20260930/first-client.jsonl": "106c3097326318267c5d342d46b4c231baae58ebfb15382f85f57a1617dbc308", + "tests/runtime_diagnostics/viewer_admission_live_20260930/plate/openhcs_metadata.json": "733c5b89207f89ec7e3ef514f7223bf563a4deeb28536207f2a754552b3402d5", + "tests/runtime_diagnostics/viewer_admission_live_20260930/plate/synthetic-channel1.tif": "45f5be72728c5275acd1130aeb4c6ce7a127905826cbd4407523cccc48fff760", + "tests/runtime_diagnostics/viewer_admission_live_20260930/plate/synthetic-channel2.tif": "5fcac25545d0559049895eb580dbc240b93f9c57e820556e7b52fc6b8c1d9678", + "tests/runtime_diagnostics/viewer_admission_live_20260930/second-client.jsonl": "dbb3b1fa2ccd4f34e881b29180f5a73cdbd826a6ace5e4fd394fe9c3f5647d5e", + "tests/runtime_diagnostics/viewer_feature_measurement_checkpoint_20260929.json": "490d349117273ecd6a4ce8a966c4fd94f049593216b2e188f0dd41f57c9453eb", + "tests/runtime_diagnostics/viewer_feature_measurement_foreground_20260929.png": "5b1765fb264f47e6e2b4ded5e5361ae6b97f955eb510e3b19efb785754590e98", + "tests/runtime_diagnostics/viewer_feature_measurement_gradient_20260929.png": "af10d4def4dd0e67e31ccd8425b5850a3b0df5cfd43b9c726f8b8f4621226be4", + "tests/runtime_diagnostics/viewer_feature_measurement_live_20260929.json": "a402bc72666d5a0e4fc4687af6fe16cd8fb4b1ff44601be3a039ce1f8af4d4db", + "tests/runtime_diagnostics/viewer_feature_measurement_live_accepted_20260929.json": "9f9a205e41ae50634fc8dba1df4f9dcf15a61cb7a33513b4aa2e63577fefaec1", + "tests/runtime_diagnostics/viewer_feature_measurement_live_attempt02_20260929.json": "60af74cc7241b3c5ef1414896b6092c1586b9c86fdbfadd22bab1e15c5718497", + "tests/runtime_diagnostics/viewer_feature_measurement_pr.txt": "5ae5825b94201ba468ac33fef210d56e5cb40877ea2b2994ea030a2b9fc99bdd", + "tests/runtime_diagnostics/viewer_feature_measurement_sourcechain_20260929.json": "b880f0cc03a5f229fb1794b9bd278f9c04e6eb0de8a0927aba998ed01ba2d5dc", + "tests/shell/fixtures/recorded_mcp/mcp-client.sh": "c95dd2e4aaeb39cd51631a0de50cb815c09a8abc9860ad0ec581b3b72efa195a", + "tests/shell/fixtures/recorded_mcp/resource-check.sh": "cbd34c21179a5c3b3c2c1b1271fcc99e91af3b0d1598681818f58a158abb3ada", + "tests/shell/fixtures/recorded_mcp/slot-env.sh": "feb7c1a44ccc7a8b6cfe686a501c6b5392aac31980720c981e3ef439945239aa", + "tests/shell/test_recorded_mcp_admission.sh": "d0c9e23adf58a6bce7ea511620331c4676ce9cb433ad4efc341d48a39f647d61", + "tests/source_contracts/test_opera_phenix_xml_geometry.py": "a8ae1eb57289f6ecda4cc995909b942cb6bf2185ac4739790f29384f41ce9153", + "tests/source_contracts/test_synthetic_acquisition_identity.py": "18e92f88cc71371c668b163700901591270fcba1af82d6e22eabfed650be870c", + "tests/unit/agent/test_agent_serialization.py": "876fc74f4acefbeaff4e2b6991a5bcd42cc9133518b2d26debc5bbc3b841313e", + "tests/unit/agent/test_agent_services.py": "6b723844b5df0a942238189e84cc702c2d96dc77279b2f0d1d6e96c113422e23", + "tests/unit/agent/test_agent_services_package.py": "97e743b7b987df8ef17bf1cfdb9f22980fcd3ca8e3b27f7a98ac5998883ae365", + "tests/unit/agent/test_analysis_knowledge_transfer.py": "402f80ecdec85330cf9bf61e04c8422ac36ddf63a1e141a9a5784ff750fb63c2", + "tests/unit/agent/test_architecture_projection_service.py": "e820969a0499995097af17fbde9b4694f1626c0ca6d70c75fd20bd4d2cdd7be9", + "tests/unit/agent/test_artifact_plan_renderer.py": "419ff0acf14c331f0e55dd8f1ce90c3292041bb392016f035785e511f1791b51", + "tests/unit/agent/test_authoring_roundtrip_boundaries.py": "9119d274d3ef09b739baf64b02705186488bd7d2fdbd8aa47aed3ca61f0d7f0d", + "tests/unit/agent/test_blind_recipe_audit.py": "63484e05bc715b6bb9cbc36bd31af3ceb7f44a8e76d4596121c0dfed9fe08075", + "tests/unit/agent/test_callable_artifact_reference.py": "00303992f5d5a255ccc916990f9d6916c73f1807cdb33a77ca35c3136a102ef1", + "tests/unit/agent/test_capabilities.py": "306a6c2c7998f852fceeb37439a91535b114b3e073b07b6e6781db17ed31fcc5", + "tests/unit/agent/test_cold_inspection_feedback.py": "6b83c5522a1f4ac7d8f252213612239093e061d14a4bc7c63052bf096a1a31af", + "tests/unit/agent/test_compile_inspection_declared_callable.py": "04bcc69f7a17e2d6d271205e0c4ba8675ea6be1528adf6d53a3561bf8223bb46", + "tests/unit/agent/test_compile_selector_authoring.py": "c0b7fb000bf135392c6259fe9a4bfeeaa1e9df2cf0c9b8f03908d856732647fd", + "tests/unit/agent/test_config_reference_service.py": "de18fb8ff76efe2bdbc46a3f46137622fe53fe6a2a28449d34728f4d04a32a1d", + "tests/unit/agent/test_config_schema_authority.py": "672e5090cdddc68d1c23dc51bbc38ac818fe0233e14b4d92e992a055ca1b378f", + "tests/unit/agent/test_custom_registration_admission.py": "afc4a461ffb8e0777d28bcba5c2e010b81c2d579845b67e921ba725d5088e08d", + "tests/unit/agent/test_declaration_selected_discovery.py": "bdfaed048a3ccd1074357de12340c0aae1fef32e4868c009727a17b3061f0f60", + "tests/unit/agent/test_declared_callable_documentation.py": "671bbc6945b22ff04bcb03bf3caa88610ae483e4ea46191db6ae6fd78bbb1c01", + "tests/unit/agent/test_function_declaration_help.py": "f0ddaae17386f5ae9383d5fb5f7f9b137d876556b183e4218e5e735415953ee2", + "tests/unit/agent/test_hosted_mcp_semantic_ownership.py": "22e25e43771440167a2832e0454861efaa2ee4328a6aa01aebbcdd8679e7d41f", + "tests/unit/agent/test_image_analysis_qa.py": "3b3cba98038a4d4777384fe99a044e13448fe63371fa1eefd5122e74d2b8e06b", + "tests/unit/agent/test_imagexpress_readonly_paths.py": "81cc9d13e9ac7544e1e94f81e3f6903587a9046925554e6f82ca7de4515b4a23", + "tests/unit/agent/test_knowledge_base_service.py": "b32b8039ba7a459762bc305bcdbe1928194543fb8ebb8c38755d6fd9bee1dd32", + "tests/unit/agent/test_knowledge_lazy_conversion_boundary.py": "ec9ce0dac89679eb922afbfe5ef1aa0c68f85a28d3273a90b634a7801b05f4d6", + "tests/unit/agent/test_mcp_affine_inspection_progress.py": "6577a2b4f53c4a284d3023d3943b8e13af545f06863d2503d73f8985c93685bc", + "tests/unit/agent/test_mcp_affine_real_compile.py": "2b8e7cb3ffaed41e334d6ab59cdfcbfc1772b2b141541bedb37096ce2b9bf04e", + "tests/unit/agent/test_mcp_bounded_discovery.py": "48bfc611468a677e0ee99be65e1b05b86426410040c7ee8262454b93890a818e", + "tests/unit/agent/test_mcp_capability_discovery_and_widget_projection.py": "f517cea9a75cf01b95cfd0b5e9a052713b25a35022b79d14da1d456e86fe1ae8", + "tests/unit/agent/test_mcp_cellprofiler_function_contract_friction.py": "ba55f9180fc52163e09b2a4bb631323471f872eb1ddc9fd7e6e690fd9025266f", + "tests/unit/agent/test_mcp_client_registration.py": "0763752fc04c32d2812f509845886f10c366e1a67ec290d50e433096a8d4debe", + "tests/unit/agent/test_mcp_dev_client_config_renderer.py": "c539f708c8e089951c6314cd51023ad2930ae904f300d22597fa7663463a1396", + "tests/unit/agent/test_mcp_dev_client_declared_decoder.py": "b30133ede3abaf07c09bc21ae46b2f7538e263ef70357f373ccf7d5d4954f362", + "tests/unit/agent/test_mcp_dev_client_generated_inputs.py": "2557a42ba4eca81f67fdbfa4e7faf77a5b32d81b67f6259cee64769a7a01204c", + "tests/unit/agent/test_mcp_dev_client_pipeline_results.py": "07bb376755222d31f27168caa9b80ac231a767c517410b1dbc3d89fdd043abc0", + "tests/unit/agent/test_mcp_dev_client_runtime_debug_renderer.py": "021380ec2c7f69418e17242b2d2181e3b3b35e60c06143de13fc1e67bb706ef1", + "tests/unit/agent/test_mcp_dev_client_sampling_results.py": "600f7a63af6668a64656e0a2fdf83e6546e4fdb7460f27b83e971254403b2345", + "tests/unit/agent/test_mcp_dev_client_transport_failures.py": "cd552206bdb5a4496032838eaa397ff950b20e356dbe3bbff350b50b0f200ad7", + "tests/unit/agent/test_mcp_dev_client_ui_action_results.py": "0e98ab0bab815bacec4bce1c969b201f6555a917929dedf2456b255c1d0bf6b9", + "tests/unit/agent/test_mcp_diagnostics.py": "96405a0f94af17972bfcc4b2cc958162f51307e94a18d689b42183a4fc2a160a", + "tests/unit/agent/test_mcp_distribution_runtime.py": "4f28f8eff46a5de20726bc80316f3fec276e51646b6dd133dbef7b39e6c00004", + "tests/unit/agent/test_mcp_http.py": "762e67be7516aa1cac6bc59d1b29d19d35f85b6f362d4a8d3c24a1ba2456df2c", + "tests/unit/agent/test_mcp_http_auth.py": "250326e568cfaaa0762387648e0a2f4c48f2a6ce010896deb5f1b61659a3187c", + "tests/unit/agent/test_mcp_lifecycle.py": "91eda092cec76e6bd770c4c5f8ccd6a6f9e5cae38583cc1d97bfeccf0cb6f6ed", + "tests/unit/agent/test_mcp_plate_stream_progress.py": "29633c670d918e5015abec72f58779b9059329614d7840a09f421b0cafde149c", + "tests/unit/agent/test_mcp_process_resource_lifetime.py": "641958481ff8a991d5f305a9ed0672554310af838e8b66cc4959e4c5c216b285", + "tests/unit/agent/test_mcp_progress_wire.py": "557f4ff4b04a651a197032ec8f98e4346eebcda4723903712ba491ce2674cdab", + "tests/unit/agent/test_mcp_self_description_contracts.py": "67c7f8052c852beef3dd875b5e96c0c7635e001df13a585589e320955667a59d", + "tests/unit/agent/test_mcp_server.py": "6612b576308c8dd55b907bb2993edc56fa3f403fe07c762ea06dd76ab6610d15", + "tests/unit/agent/test_mcp_skill_registration.py": "b4741c8dab110461a02d1f3c893c1f6e020f173911cc0e9ba0dc62d409c3cbff", + "tests/unit/agent/test_mcp_startup_feedback.py": "64b1f2b9c80c789f2a0c82432440e18604a739afb3f4aa3dc6eb2b5cac69f9ad", + "tests/unit/agent/test_mcp_stdio_transport.py": "ffad185f736a7ead7b6e2e7699fb3c9b034c24534af14ea8848e0eb6989cfe1a", + "tests/unit/agent/test_native_presentation_451452.py": "3bee78d7ef0ea2b23230f12b055ceda90c81c64ad87c274524ec1a7bcc0fc9f6", + "tests/unit/agent/test_native_presentation_mcp_451452.py": "16735a50874ad478816fc0c5529bfb00b53ffbb4df473054935b9c385353fde9", + "tests/unit/agent/test_neurite_body_gate_authoring.py": "cf8c8775f2dc12d82f8937268df64541ebce6209d7bcfae14d8a8dcd2db503bb", + "tests/unit/agent/test_object_state_field_help_service.py": "26df2f5ea13773abba21f267ceec43edb69a8b96295faf6b6b036a81663ff7c6", + "tests/unit/agent/test_official30_knowledge_examples.py": "6b81450dc01a33370fdad7a9a3b88bc87c3f85eddcd8b872373da9a89172c7a4", + "tests/unit/agent/test_owned_bootstrap_readback.py": "2ef367aad3af2247f30e6b705ecaa843890dc59d03e58e559db9a29e99d87072", + "tests/unit/agent/test_owned_runtime_bootstrap.py": "4cefddc71983ead4c1faa961b3e2bc66f3b087aa7498b132d3848125c649a089", + "tests/unit/agent/test_path_policy.py": "08274b555ad275e1429d0334a0a2a0432c963cd32a3be0ef1c65df87137336ab", + "tests/unit/agent/test_persisted_output_reopen.py": "9580b55180b79fe0965ac4e23b62ae78fa3fd8a64c0912bd462829c60a0a7f0e", + "tests/unit/agent/test_physical_source_inspection_445.py": "1d96e83e931e7e07f6f39a49f5610e1365fc37a935022343e1177e96cda1f103", + "tests/unit/agent/test_plate_inspection_cold_runtime.py": "da596c352d3a7b0f6e36fce04206f248c37ab84257840e7486d0782aa31a723d", + "tests/unit/agent/test_plate_inspection_service.py": "fcf6a171c5265761b3c4b3c7b730f6304e36079d0c1e689ddea8db7e2ef695f9", + "tests/unit/agent/test_plate_streaming_service.py": "299e60c33736bad13ebc68ed1b5499cee52d9e25822fe2918b5352b05a3e18f7", + "tests/unit/agent/test_progressive_authoring_context.py": "98437a0ca02cf122703e3b38083f3dc1b19e738c6970cf86aa74b93c6692b71b", + "tests/unit/agent/test_public_callable_enum_ingress.py": "8a6fdb4f75f057a6c1ebc5aa8165ebf84dac916576ed5a6a11f173cca3a220ff", + "tests/unit/agent/test_runtime_debug_inspection.py": "8cb28c6e981ba51fc4676ae318fad45952d9ebd7490ed6d50eb08cff7d6827f8", + "tests/unit/agent/test_s1_native_viewer_records.py": "57658f75ead1e01dc8c37942f34346f1337964a46feea18af58ddb3ae953cb0a", + "tests/unit/agent/test_s1_typed_viewer_rendering.py": "75541bd3c686bb9ed6d81374cf0c9dabd6135d05135c8f1be70c49b8e7d6404c", + "tests/unit/agent/test_selected_plane_reopen_stream.py": "598a4e831c596debb5713b6114cef8bb7c6ad082737491861d0ec4d4bc358649", + "tests/unit/agent/test_skill_sync.py": "0ae79c0394c339219262b8cbfeee76c6d01117d21ffbcfb4799b55175a2ba073", + "tests/unit/agent/test_synthetic_plate_mcp_progress.py": "281197bf81d03a8e477026df293dbb385342d2a68c3d10c2897f6504ea85c74d", + "tests/unit/agent/test_synthetic_plate_zero_geometry_journey.py": "d0531ec51325b8233f8a730d0a0a930c3ae50bbf3156aaa93367388647b3ac6d", + "tests/unit/agent/test_ui_bridge_service.py": "8a91032c43f2db796121a2ad5373cdef1fde04543537ed4bdf631df7285db55c", + "tests/unit/agent/test_user_facing_help_projection.py": "74b47e47ff44a251a3a8406e5250a8183567c20e327ff211dc873d99f22d930b", + "tests/unit/agent/test_viewer_render_snapshot.py": "02141305e7056279fde7c2209e089a8cd4247a4c59aacc3aa2dccf809f051686", + "tests/unit/benchmark/test_agent_validation_attempt_recorder.py": "abe151a160d2c38edb9112caaf7cb95f5e2cc98e33163b5e5239e4b4fd55f78f", + "tests/unit/benchmark/test_agent_validation_corpus.py": "766d046e237b41e02f82ad424ee6e850f9cdf7253985763ac8c11f49f9412fc0", + "tests/unit/bioformats_fixture.py": "027104f2a8f654137f2f0e599b0a0999d4a7ada8f177d1ea84e19a0c35a1c3b9", + "tests/unit/bioformats_imagexpress_fixture.py": "cbbb2857a13095516dcf19497c14f39c46a9ddd5a6ac7df9f17ef5162785a023", + "tests/unit/cellprofiler_runtime_test_support.py": "c37112c27a4f7ee2e7f853026d9e1c569709b9baae214f858076d90115cb1105", + "tests/unit/core/test_config_cache.py": "4e21db002c10fd13a12b398ebba0c291a3793dd5c17fce7babf697af2c7030f4", + "tests/unit/metadata_namespace_327_worker.py": "73c0af77ad5faf85a86935581e892874ee7c42e8db62316e010d9bc9fca2220e", + "tests/unit/progress/test_debug_projection.py": "8ea3fdacb5ba4a2c8c7a474159acabac2772bef91d4cca2c5a1fc7886d5681b4", + "tests/unit/progress/test_live_measurements.py": "9dc05a871ebb62a740b7782ef49dd88868e4b6dfa890ab2cba8f6518eded741a", + "tests/unit/progress/test_projection.py": "25a154fffdd169efe68873bf4d67430010f785d866082a29268c2e34aaa458b6", + "tests/unit/progress/test_registry_channel_keying.py": "b7e27609768bda2c31b2f63807bb30f70709c98664ae575db94afe9645e02709", + "tests/unit/pyqt_gui/test_about_window.py": "05244696d0dca4f612628a5dd3b4b511f5429d50ec438e5b9d53a1242ef52129", + "tests/unit/pyqt_gui/test_application_cleanup.py": "c5766b1f4e98db7d63da72ec88c911a67087aa0460503949bfb06f7f424d1669", + "tests/unit/pyqt_gui/test_batch_workflow_compile_engine.py": "a8295fb6edbd0229128025327c975d7c916b791f5774df4a030e6c9778f3c4cb", + "tests/unit/pyqt_gui/test_branding.py": "f4cbe865cd5a68107b0d9839233a6753039b59c3e89b83972dbc0bc719862043", + "tests/unit/pyqt_gui/test_cellprofiler_parameter_help.py": "5927653e12735107ec5b05434efae67fd149b936974c06c3ed074583f7a6d5a5", + "tests/unit/pyqt_gui/test_code_document_catalog_imports.py": "e5b8527f97c94fbec70b85d3413077c4dfaf677afa987c7a172e82af84162034", + "tests/unit/pyqt_gui/test_code_editor_form_updater.py": "9ab853be893f5d0582aef0519c33fdbb4ed5675027a514c9deb21ae02517797d", + "tests/unit/pyqt_gui/test_compile_terminal_supersession.py": "0b04d9c843ce2dcf16833b1c53b5853637802aa35c2d23de992c3db6c2bb2465", + "tests/unit/pyqt_gui/test_concurrent_initialization_progress.py": "c8e960fa83adb73f3533cf4c75acafd59249a1993f4e650733101fdd3d62ddb8", + "tests/unit/pyqt_gui/test_config_preview_formatters.py": "b77b44d666b776ab5f68030c1553c4c3f8e6fd673354f14c852b7606295694e3", + "tests/unit/pyqt_gui/test_config_window_state_resolution.py": "2b24d9e2f612c5b9510ed8d5f9729c389aaa66b9cc96c36259771e311beb5fed", + "tests/unit/pyqt_gui/test_config_window_transaction.py": "2b541713ee3cc4cdc36677bd6f86db091ffb4be038e514c04be059f3754bf1db", + "tests/unit/pyqt_gui/test_debug_inspector_window.py": "7c11dac1b9208e7d1f56494fec9b7ae61cc804e86316a78b4f52eb23d0ff218f", + "tests/unit/pyqt_gui/test_debug_toolbar.py": "e9a5dfa5fbbe7967c5339bda52814a314f14806754fb97b4d2c04f0e8394e0ce", + "tests/unit/pyqt_gui/test_desktop_history_upgrade.py": "1a6a10deb9ae83a381abf245a213a6ace8a1d8fa92e87e786132d8201cab518f", + "tests/unit/pyqt_gui/test_desktop_restart.py": "aafaa6e7a46859f50b44232e12f8db606e0dd4631340a834694a0fe795b5ff70", + "tests/unit/pyqt_gui/test_desktop_restart_worker.py": "a9fbda7d6c78972d6300cd9fe67c2e88497b6b802a9b48057568007bb33b0e1c", + "tests/unit/pyqt_gui/test_desktop_update.py": "b79c4c2620f271ad3a2c08f3002ec9d2c17c8f80b0b72b8ac6b1baba9dd8815c", + "tests/unit/pyqt_gui/test_desktop_update_worker.py": "68dfc122f38164cf6eb47e856bfe369002e03e3b0699ad6bb2fda9f45db2dc8b", + "tests/unit/pyqt_gui/test_dual_editor_window_artifact_refresh.py": "d03a84c8f8504a5cf6880662c1062209b0ed6f3f4b3d52deb4f6b2d458ede4f2", + "tests/unit/pyqt_gui/test_durable_decorated_history.py": "ce767329b25bdeb2e2f3803d5fb95588c8284aeed78bc830c81dbdaa746ecf23", + "tests/unit/pyqt_gui/test_enableable_function_ui.py": "b7bd91891fe82d62ab41a12e112d709f7559f700c8de8d7a05270bb018b22d85", + "tests/unit/pyqt_gui/test_execution_server_status_presenter.py": "1d1e9a8604c0e071a550becb874c79067e0506a52f0a09813b0a210d61cc2d26", + "tests/unit/pyqt_gui/test_execution_server_summary.py": "7e0b17ad242ab17596be60daa00c0107abe248e345a1f986a4b09dbb630b813a", + "tests/unit/pyqt_gui/test_function_catalog_form_materialization.py": "711b69ff0b145b962f0f3518c7a7a77db38d8a545bb9f5ea7d2e259d70598667", + "tests/unit/pyqt_gui/test_function_catalog_projection.py": "fbb41fb4cbffd15fed4108349e35ce2da0cba028c00e1b82ee23a173ca032d19", + "tests/unit/pyqt_gui/test_function_selector_column_presentation.py": "cf459d89d9a1b771647fd58ebe87ec0b6214de83f85b79d24f8645d1c6e05066", + "tests/unit/pyqt_gui/test_function_step_code_document.py": "50e7a17fa1912431d541066f70eaf8a1973600528b6fc0c3c77094f492a44ede", + "tests/unit/pyqt_gui/test_gui_startup_progress.py": "48dd1e33f90a33d3adee7d646a4962b0cbe2213352a69930c1882d23c8b60b94", + "tests/unit/pyqt_gui/test_image_browser_column_presentation.py": "a7b2415579145d5ca93bd410a28684f8b88bbc18a9aa3228280449447543ded3", + "tests/unit/pyqt_gui/test_image_browser_streaming_config.py": "6f030f18030e26d498cf675cc74c6998ab9352fbc19fb50c95aabbf76816516b", + "tests/unit/pyqt_gui/test_interval_snapshot_poller.py": "748d5a2c013c9e861fcd4594f51e35f1c65e0e298f5ba9a2ad933e29f2cb5183", + "tests/unit/pyqt_gui/test_live_measurements_window.py": "4769cf1397625445b4bd18dbcfca88188e3df06640804174dfb18cfa00d4f635", + "tests/unit/pyqt_gui/test_live_server_tree_sync.py": "7f4c00372640e5fbcd22d237d53403ee8ef7e0da773ac47567d481271e8438fc", + "tests/unit/pyqt_gui/test_logging_config.py": "5aa556c32bae67691f52be4ad4335054ea935ed46ba482b060da5d88c8717dec", + "tests/unit/pyqt_gui/test_main_config_propagation.py": "291dc45ca20ead6025c255a8109a2e6c55d90bd7858e80ad12484dafa733d7c5", + "tests/unit/pyqt_gui/test_main_status_bar.py": "19f38968fad8a0599b74bf773ba7bddbc64b0d1f8604d3c9a10bae6f8cc4405e", + "tests/unit/pyqt_gui/test_main_window_embedded_layout.py": "1d91b04430bdad6562db2c1e2f3b29f6b017a6e3afaccbbf18a0173bd87f0213", + "tests/unit/pyqt_gui/test_main_window_file_actions.py": "bbda2f9c205299f36497db3aba6f569ad52ae069dd8ee4ecc5328b337d5e97fa", + "tests/unit/pyqt_gui/test_main_window_time_travel_workflow.py": "a4e4ff0599e317ece876b24960e41f03d31da3cfaf4105971a6f2c8127cd3961", + "tests/unit/pyqt_gui/test_main_zmq_window_routing.py": "d02fe132fda83540f26ed4b7a79fc1409fabbf0ff6ce72f3d1ed8681258e9f6a", + "tests/unit/pyqt_gui/test_object_state_callable_preview.py": "c254e95495dc739943dbf685334ccd393003e1f83799abe1d190ac126eba889d", + "tests/unit/pyqt_gui/test_parameter_form_manager_cross_window.py": "417aab4ec3e838ee4855e27d82f909039bfa12f839870060b9fe4f0b653948bb", + "tests/unit/pyqt_gui/test_pipeline_code_document_transactionality.py": "b7e546e904b897f13d76f0c523e751afa541a75c627349ba79a3a87313d30f4c", + "tests/unit/pyqt_gui/test_pipeline_editor_auto_load.py": "3aee5e89d6206608e9867b7ebf4a25bb3296f53b16315a4e26eec83c80c73f02", + "tests/unit/pyqt_gui/test_pipeline_editor_widget.py": "8f28719c5bd9eb5681e67af8e1f7aceb445bcae97c12a13348f943c8b6bafa35", + "tests/unit/pyqt_gui/test_pipeline_history_occurrence_restart_regression.py": "fe37875c1e0d0b2b3ad62d0e98018e86718fcf6c452372719e84ccde808d1579", + "tests/unit/pyqt_gui/test_plate_compile_connection_action.py": "2ff8a68ed29ccb837e8e6efdf3cd9c03692d206034c2243e67b6de159d3da3aa", + "tests/unit/pyqt_gui/test_plate_manager_cppipe_import.py": "df080e025ddc8ba5e5d883954e6bbe3433eaf9e8ca72303871ad2346fbeca668", + "tests/unit/pyqt_gui/test_plate_manager_widget.py": "b02e81c4a73213577df02a1effbd6843935f5c92f459d6c61ab2998bd489ad58", + "tests/unit/pyqt_gui/test_plate_scope_identity.py": "7efdd8f7ed140d241c06d91283554c5a9110e9c052316f5889d8ac2eb5ced678", + "tests/unit/pyqt_gui/test_plate_status_presenter.py": "b4a23702d53c28a7cb10abe43c34e0302daf842675c258b8036d8e4ecbeffeb7", + "tests/unit/pyqt_gui/test_plate_view_grid_model.py": "80e5db964039812e11ea79aa84ea1a59bb8a0fb2cdf72700024188e6b8223b88", + "tests/unit/pyqt_gui/test_plate_viewer_lifecycle.py": "ae613b3f23faa15f37c34c27dbaf3235c8e98eda78e02d65701af2bab0199035", + "tests/unit/pyqt_gui/test_progress_topology_state.py": "f1c7499be9289b8c7591c8cf1658271bc29ccb2ed5962e3c011c6684090de6c1", + "tests/unit/pyqt_gui/test_progress_tree_aggregation.py": "618092ee65814f13d017e9eff092ff13730e7d77c13cc00ef9ee82bd71eb13dd", + "tests/unit/pyqt_gui/test_reactor_providers.py": "c685c258ba42bf606a72f256d8a529c7c6cb2a96f1fb9daef98f70100386bbde", + "tests/unit/pyqt_gui/test_server_row_presenter.py": "f7c7f172a85b08f54660a953cc02d2e88aee8b80ff1a5d0abc3e75d52d13519c", + "tests/unit/pyqt_gui/test_snapshot_browser_window.py": "568fe4836eef50a53b9c0000c18c534fda94adc1fa1137325c7951284f4460db", + "tests/unit/pyqt_gui/test_source_binding_preview_policy.py": "e0d551b50676e332190aa3ab70115d2566ae2af1ff71a6583d0717b11e9b3475", + "tests/unit/pyqt_gui/test_source_bindings_editor.py": "baa2e7b8e6a7165a8b90f6540b8867d91eb2123f3fff03cc196da28d96a9a5d3", + "tests/unit/pyqt_gui/test_source_bindings_preview_surface.py": "d424f0d9a5abf07b94cf005283bda9e4f564993eebe0768a56a3f67d5c014562", + "tests/unit/pyqt_gui/test_step_code_widget_roundtrip.py": "a67876053a5381e1767060d0ee5d54c79d96dfbaec8ef0e267bd767993a821cd", + "tests/unit/pyqt_gui/test_synthetic_plate_pipeline_document.py": "75e30548751180a92b84ad1b4346c3563798452835ac2647b60c83c1e7b21333", + "tests/unit/pyqt_gui/test_system_monitor_widget.py": "aa2a69497a4ea40c204838299f18d24af18107c2c0254923c40ca2bf5a0c0363", + "tests/unit/pyqt_gui/test_time_travel_viewport_context.py": "eade1dc2ad445b66618e248c60f44109b461c3138e665b0798754c9c957e2860", + "tests/unit/pyqt_gui/test_tree_rebuild_coordinator.py": "faabc7ba6af464c8b24324456dfa39c2df54c636bcfc92a1d5a5c8877766687c", + "tests/unit/pyqt_gui/test_tree_state_adapter.py": "8d7112aa9e633239a40521764ff81b4d877df13ba865cb93e62ad1f90801c957", + "tests/unit/pyqt_gui/test_ui_agent_bridge.py": "1feee4bb413738f04e81cbdf26244dc0d585a68921e6c7749a941a08518007a1", + "tests/unit/pyqt_gui/test_ui_bridge_lifecycle_config.py": "a2ecab6650184ea7b23f1aa65f755ef1c7fdbf82ac61c49dc48cae95b8227df3", + "tests/unit/pyqt_gui/test_ui_bridge_live_measurements.py": "2c6f3742943d968cda49e9675c0bc96370e49c80b1743a23d7d6e5f907caa7de", + "tests/unit/pyqt_gui/test_ui_bridge_live_overview.py": "4567e1a724d9ebd86e7a542f9b203210dde7a349c6e8e051152a196567465179", + "tests/unit/pyqt_gui/test_ui_bridge_object_state_mutation.py": "ae40befdb09bb6b94548425e69f4686be75151656ae38e869f2a1d1cf05961f6", + "tests/unit/pyqt_gui/test_ui_bridge_preview_disclosure.py": "d7b7b5ed3f74be5d69335743eb89e5b391eee4965ba59510dc6754ff7fc8054d", + "tests/unit/pyqt_gui/test_ui_bridge_registry_cache.py": "766a2757fc8de9a67ae30b2b9d4561257364289e2501afd190cc6d8da4639215", + "tests/unit/pyqt_gui/test_ui_config_lifecycle.py": "eeb7c260d3ae8bc7b5e6d94917b1e5e9a214feac9e2a0c2651552950cfe3a179", + "tests/unit/pyqt_gui/test_ui_config_widget_projection.py": "4cbb172354459bd021ec0dfd30c74043d83c37e58e5cda9912a04b62dfae08c3", + "tests/unit/pyqt_gui/test_ui_window_flash_snapshot.py": "8591e3e070c2b71fc0772839e0cc1058f0d17cc37e96a0fd15752dcf06312d79", + "tests/unit/pyqt_gui/test_user_facing_help_surfaces.py": "540d0fc2d796ff80543a7ef245d2450c1ecf988994e244c13472f9756cd904e1", + "tests/unit/pyqt_gui/test_widget_action_dispatch.py": "4645076d78559d61f0cf1a1072af0e656635531f4169f12a3c3a7156b35b5e6c", + "tests/unit/pyqt_gui/test_zmq_client_service.py": "4edfbf7ca673a19be34db52a15e8f3b600feb987a6d0a90e36ed767494db0b42", + "tests/unit/pyqt_gui/test_zmq_server_info.py": "72dbcaf8f28291c6807131d30f097b10d94d33a799c7b4f034f93e7efacae4cd", + "tests/unit/pyqt_gui/test_zmq_version_restart.py": "052699f393497ab23ec49d23fa136d969245c95c0973d6e9898aedfb860c43f9", + "tests/unit/test_ack_return_route_journey.py": "4785f1334577a67044db2ac900471b2d7ee7d8324fef0594105a40800037e016", + "tests/unit/test_acquisition_calibration_pipeline_journey.py": "328a63f88c843a9a6b1d2440f92dce4cf74f55c1faacc09e135f1c43c92ed0d3", + "tests/unit/test_aggregate_layer_materialization_515.py": "3050f0f395fcf58b8a4ed4b9ec25aa8bb2d6fa967c06fe8345ad0806ebd709dc", + "tests/unit/test_aligned_image_payload_device.py": "1e9794faaba06f44e826c8e7f81cff8383bdad66e9073e78fdc007bbc27bc87b", + "tests/unit/test_aligned_image_payload_registry.py": "2e361e02952c6986b3b6060cf61973d2d721bdf441cd96d002946b64b7e01275", + "tests/unit/test_aligned_main_flow_projection.py": "15b5b4535087abc5e23345ad606bd4dbb88eca686fca95399a0a2040d8099679", + "tests/unit/test_aligned_output_projection.py": "923ada2cd0dd29c0712b3c56c6ff34869992ed4549f3e05a71863322fb3c1c90", + "tests/unit/test_annotated_validation.py": "28c70bf256fa568bb3cc22cf2ff115604997d5f0e5e10a92c5879cfd7922a17a", + "tests/unit/test_artifact_declaration_step_context.py": "0252d4a928ad388b8bd319b3d95d2f94be2e4c04b01f4ddbb982a5414550c068", + "tests/unit/test_artifact_input_edge_cardinality.py": "10feb0d15272ad14de773dc2a0842ffde701932fe2c17dbc560dfaf889e19dcd", + "tests/unit/test_artifact_input_parameter_normalization.py": "9307b32bc0404e7ffad6b779cde9c1d846fd9411976833a2289b6100fd59e7b4", + "tests/unit/test_artifact_input_projection_plan.py": "a777c8fd900f15ca5f6a990fb48b36e1497a3555e5575e68487d7cb7b74cdd65", + "tests/unit/test_artifact_output_materialization_planner.py": "b36f4520f158ea915df1afc40a79d5e6da3ebabd75726f7b01082de0fb39f2da", + "tests/unit/test_artifact_output_ownership.py": "b967b89d36a5d337eeebf139acacb57aaf2ca79029572ad3a99c3a5e9963fcf6", + "tests/unit/test_artifact_plan_view.py": "f53f129d6071c3c60e12dc8a77088e948bd915640a8dc4c82e64f6ea779ed850", + "tests/unit/test_artifact_publication_journey.py": "f25dad54b6d1f43dee464a246d0d0d8e851ad39d9b8f77476a26bb5e7f408f9f", + "tests/unit/test_artifact_spec_collection.py": "892981904cff8f85ff0aa3987855ed90e8992b2aaec9e93c11fba32ac14ad263", + "tests/unit/test_ashlar_request_records.py": "28f7263f708fd490307814068a27f404315424c665bd066e862fe42717d6ccfc", + "tests/unit/test_assembly_acquisition_placement.py": "fe899cfedbabadf0820347b7bf01782c637842ae3a61aa990fd0be870d550412", + "tests/unit/test_ast_validator_registry.py": "afdc6404a95dc5f5bd97a5c6e7ab617d02614a5a001ce43512718dde4104d54a", + "tests/unit/test_automatic_image_role_materialization_435.py": "cd4bc38893dd13e3bbf22cc47d002592eff1c119141e8969619990e55503c4ec", + "tests/unit/test_basicpy_acquisition_fixture.py": "86857b170ab714f9d260d6d116456fa7f55966d44f0905c2056595a66cfbfe28", + "tests/unit/test_batch_submit_wait_engine.py": "e2fd500635f79da8ba2c039704b4094a118330b37552fc5b7ffa5352ecf9a8d8", + "tests/unit/test_benchmark_control.py": "1edf8dd50bdac5310337eb7590a4e81d688835e78101119b858c77b1fbc0f405", + "tests/unit/test_benchmark_manifests.py": "5b04a4ed0a2426f2350b133a93bf8a030017fa6bb9d299540732fcd32f82c7bd", + "tests/unit/test_benchmark_pipeline_registry.py": "00d78db059038731048e763992be8215deefe3581e096cfa204c268610f1e9b9", + "tests/unit/test_benchmark_progress.py": "d45d8d99cc679ca5e91835bbb5a1d72c3c594d1a0ebb446e50c7517d19dd4004", + "tests/unit/test_benchmark_timing.py": "2df7b3fe213504676a32406f6926907736d1d6bbe7b636ff53f12e20d40e0d9e", + "tests/unit/test_benchmark_visible_source.py": "6a2134cd19bc6be6ea2d9ed098dc17c4a1c82138a06c8189ad4de42ceea4b5ad", + "tests/unit/test_bioformats_hcs_validation.py": "1056158a2b1f7f766276fb6b90803f00b2f3e5a99be379210dba7a7b5948221b", + "tests/unit/test_bioformats_java_adapter.py": "140467f8ca95def648a88c0910692fe4dcfb4a4ac6864d147cecb57981b28c81", + "tests/unit/test_bioformats_microscope_handler.py": "d12e4e85a13bc28f7d67d1547ce8a347897c89436a129aebf45bc34cd5a193d6", + "tests/unit/test_bioformats_preparation_selection.py": "7e867853eabcd3aafa0519adbb3d34848b2ae175c1039b1bca2e3c993fff5f61", + "tests/unit/test_bioformats_saved_calibration_440.py": "6f8f3e3943b327bcefc89533681f010a2dac4688161f7eba57abf69018a8954a", + "tests/unit/test_bioformats_spw_projector.py": "05279446ee238d2114f1aca1148aee848a6b004ea9f4452a48d32b059415fe26", + "tests/unit/test_bioformats_storage_backend.py": "4756f18ddedb53127a9620c31ffd4834fff56e60938e46976c2ba8e3f46981d9", + "tests/unit/test_brand_assets.py": "ca5382cf06d51e5a4e1aa3ea836ee875d0a909f02b76eb88df8e6c5e12292140", + "tests/unit/test_build_hosted_mcp_plugin.py": "ff80eb73ac6c569be50fd6089af8835a515cedaec74d53535cc823f5e872bef7", + "tests/unit/test_build_mcp_knowledge_assets.py": "8b57a9579f943ebe1f80926a74ea0bcc235b9b197a3eeed250a95158119d0f9d", + "tests/unit/test_build_website.py": "4a8952ba0f51590ffd9f1d787986653802506807079a7e0d118343264252e0e0", + "tests/unit/test_callable_abi_preparation.py": "3725d8bace4e1742610b80943a74be21926982dd57e7bfe06e72e22a88226d79", + "tests/unit/test_callable_contract.py": "58e693b414dc83c919e77aa3429981ddd1ec2facf91433086a0789f55cdd6b8f", + "tests/unit/test_callable_request_binding.py": "a88256297b2707a1ef6de60669c20e9da33f2339fe1b696c752566d1777510da", + "tests/unit/test_canonical_custom_source_lookup.py": "8852e7ecb8e851072ecb145a09bfea5d843f735fffd0829468e98c8cfc0d8e42", + "tests/unit/test_capture_media_gallery.py": "aabfe3defb657b72150caaa3737f06352056e8580060633999a4296818ee8dcd", + "tests/unit/test_catalog_endpoint_incarnation.py": "26fb66e9bd63adba6941d75d4b1562a658bb6bdf3627bec5be4a01b3f5717107", + "tests/unit/test_cell_counting_cpu.py": "0789243bce87c24e10847c9dcccf6398e8786cea0222d5146e1777083a31812a", + "tests/unit/test_cell_counting_cpu_artifact_contract.py": "a6d5baf407224ef12567550cf527eb15aefd8593791bca870903f45fad33bfd5", + "tests/unit/test_cell_counting_cupy.py": "f63f98e676ac6412413a02cb813c79c317a33f37896a17b4177b21989084c672", + "tests/unit/test_cellprofiler_adapter.py": "2d5196ac77d12d1072d25d876088e52a1964e41faacd0b0d09e8a20986dce90a", + "tests/unit/test_cellprofiler_adaptive_guide_threshold.py": "2ce27367c9ff3a012fc998e5bfc48836a78000d4c82b0ee37feaf3aaa3da6a57", + "tests/unit/test_cellprofiler_additional_prepared_payload_abi.py": "072b6e95fed332b1526ab00f8a9ba309c30af612c0571043396ed0adaf77387f", + "tests/unit/test_cellprofiler_analyst_export.py": "d8302ebb5d59fb6fe34d45ad20d49bbb192e73124eb6fcd836818dcc6d87097e", + "tests/unit/test_cellprofiler_area_occupied.py": "df8bae02193bc9c5916c802d72f441e6516a20695a1f8a2049cbac9bddf436b9", + "tests/unit/test_cellprofiler_artifact_activation_identity.py": "b6a75f122455a505cd3dcadcc6710c7bb990a1c7fc6b3305621df0e374dc0918", + "tests/unit/test_cellprofiler_artifact_declarations.py": "71d20f26620b1ce526a20c583975abad23864200d528945346cf33140b7a5c2e", + "tests/unit/test_cellprofiler_artifact_identity_reconstruction.py": "2e9a227df16f901edf0d6f16905a18b29452f1c319271fbb0b242bb19f2c0e33", + "tests/unit/test_cellprofiler_backend_leaf_wrapper_deletion.py": "75516cd87015353da4af1c4a3108bdcebcdf5d2efa53f8f7054330f19ad87808", + "tests/unit/test_cellprofiler_backend_public_api.py": "a56a4a11424f7d0b0bbf2a2187fdf26b8de7d8622a83394c5b951cf45a2fd244", + "tests/unit/test_cellprofiler_backend_selection.py": "d1f7743717346ae426121347101f58652aa98ecdcabdfb972af24a33a83d70a8", + "tests/unit/test_cellprofiler_callable_kernel_preparation.py": "fa30685afc2170bc8718595f4cf8303f656bba585729d6f70a6e1e3af2ebb9d1", + "tests/unit/test_cellprofiler_centrosome_independence.py": "b38a72b822360a01ca3a1c55887dda93f66551e5546ac52ec02d658555e21544", + "tests/unit/test_cellprofiler_closing_hotpath.py": "938b1b26dae4359885a79ad98eccd06414d5dc6133bcae6732323bc1f36853b7", + "tests/unit/test_cellprofiler_combineobjects_source_scope.py": "3447da78c64ac01f29c680dd7095650bedf3547a0f7a2c2e23356c294b525b0f", + "tests/unit/test_cellprofiler_comparison.py": "d466dcd7c24ead62a65cce4b00476916da69920dcb9ba54000e488ee5dac94a9", + "tests/unit/test_cellprofiler_compatibility_matrix.py": "d66a7ab1c0252c169b8850aabdc55e07952607b0f46abae4d480a887be827bce", + "tests/unit/test_cellprofiler_conditional_analysis_images.py": "6a324f7e970b03f5bec32c50be882cba2b1accf9c4393582525a7b8337fd91b5", + "tests/unit/test_cellprofiler_conditional_measurement_outputs.py": "2773cdb08df663098edb3633a729325cef4bc474f6ab9e5c89537fa001eb40b9", + "tests/unit/test_cellprofiler_conditional_named_images.py": "bee6a9ed7ad9b19e29678dd3431dadf41acaad7d6f439058be4408ba62d61af8", + "tests/unit/test_cellprofiler_conditional_topology_declarations.py": "776d4e8e1fd2454e5dbb545e0427370d8861f2d068c3abcd6459924b9ecb564e", + "tests/unit/test_cellprofiler_converter_cli.py": "7060a8839bf4bb0a6389d9bef47b9745a6d9668ef9c918eb278104405c94a70b", + "tests/unit/test_cellprofiler_display_manual_projection_declarations.py": "3633ce284cf58de11eea2eab5cce7223590ae232ba7aca11a65ffe0253d511a6", + "tests/unit/test_cellprofiler_display_plate_map.py": "1d2f397c47cc4b602bb0789496be70040fa9af9509a77f0221c0ca56b18a3356", + "tests/unit/test_cellprofiler_display_runtime_payload.py": "6178b31bb6ddb8d2b29e9eb0d7090925a4333bc68a46c6d482494289200ba537", + "tests/unit/test_cellprofiler_export_equivalence.py": "b103af3823c1abd889a68cd7652c21e448c162b5237d8a44009caf3e830a9c6e", + "tests/unit/test_cellprofiler_export_measurement_outputs.py": "d887822db907057b3f24dc7462fbb746152373639b70ae0275b7ab7ac15d3cc8", + "tests/unit/test_cellprofiler_export_to_database.py": "76c656b2054eccbd2387b9256490052a407acec6e18aa9938918862386c3b365", + "tests/unit/test_cellprofiler_extended_relationship_topology.py": "bba08ad4048be87a037fc25c4bc4e9445cd5bfc3e8374c8c55519a819246ee17", + "tests/unit/test_cellprofiler_full_stack_materialization.py": "ffc6bfe96a431e72611da4e287d496065af9d4bed71984881a29c3f7a902a1ec", + "tests/unit/test_cellprofiler_function_contract_execution.py": "1fc83be8444c59c81ecd6ece3c85e917c50403aceca3d98016967f0a72b072d9", + "tests/unit/test_cellprofiler_generated_pipeline_execution.py": "82678f50e1793ee1414595afbb13eb6cb4e172e39c1a59f36e5bf5c3d6726917", + "tests/unit/test_cellprofiler_generic_special_input_binding.py": "bc6783614da9c25a732ae436d61bf9b8f421d4dcb1353e4c70e11c6656f5015e", + "tests/unit/test_cellprofiler_geometry_prepared_payload_abi.py": "44755ebf3e1b4a4768392f1a77e32f52512c5649bec627654b66e468d89cf37d", + "tests/unit/test_cellprofiler_identify_secondary_replacement_primary.py": "542a706e289becb36e9daae68250d34882a65d84edefecde1eebac2222625d13", + "tests/unit/test_cellprofiler_identify_tertiary_output_abi.py": "2b309eb89f9d092cb2ed564c706b5eefeabbcecc0c36f89029be310221500870", + "tests/unit/test_cellprofiler_image_geometry_cardinality.py": "28aca73d97996b932d4b3976276d86e4e567c2d322bb77ec019106984316381e", + "tests/unit/test_cellprofiler_image_math_hotpath.py": "1f3cd8292a2c8ecd5b162e48f7cffdbde28cd6a172af1435a32becbc461ed267", + "tests/unit/test_cellprofiler_image_math_mask_metadata.py": "8d02a637016bc55440d65cf2783673b92a99e6bc876d3a3993c71f6ec98e96b7", + "tests/unit/test_cellprofiler_image_math_operand_axes.py": "0c97d83928e5bbe5e80c1d9219886292ef4ad3858a4ceb12b98eb913c465606e", + "tests/unit/test_cellprofiler_image_math_public_roundtrip.py": "a97ef845b3c99005e43b106339967bb0dbbf21a2eb49da98b084326277174341", + "tests/unit/test_cellprofiler_image_output_metadata.py": "006cf27e04c1b0af17555adf9e8418864fc35b33dbfb478488da69908ab03bcd", + "tests/unit/test_cellprofiler_image_quality.py": "3130ade2ec2015bdc1d4e6b993c629f8a912f9c2c48ec490d173135f01aad274", + "tests/unit/test_cellprofiler_interop_import_records.py": "91dcb69e8c3fa6b00a7a897149af82077fad5d63869532b9b1333e4cd977c0f5", + "tests/unit/test_cellprofiler_interop_namespace.py": "398626ff0980e7c31644e8e59fcc80ee2cb30abc989b9caf5e320c1f864cc710", + "tests/unit/test_cellprofiler_kernel_preparation.py": "51c6b172c411c282c036d542bceea8de43ec3031e754e0c99053839ead19c609", + "tests/unit/test_cellprofiler_label_hull.py": "6cd43a6edff52996429d0b01225f8db6440768c175169e799481156b8b6146b8", + "tests/unit/test_cellprofiler_library_loading.py": "6d864e5c8b1682403f9c57a76bbe3b204c0fcfa15395c2701b01da68ac531a84", + "tests/unit/test_cellprofiler_library_untangleworms.py": "96d6dba6bf714a1a057d73f6e2f4a698b8754ad57ad767acbbe41d8db701d62b", + "tests/unit/test_cellprofiler_measure_image_skeleton_contract.py": "6b83070e8b462970ae78309b466cb132cfd5929682e6a189c3eb0be779b8711b", + "tests/unit/test_cellprofiler_measurement_math.py": "81e6dbce935f9dfcb23f3d80b1923e76babb63316ef67f8a2287b529be356fe4", + "tests/unit/test_cellprofiler_measurement_projector_cleanup.py": "efebeaf02581e8925fd10a1ede225f770da1c3bce09293c43ee57e6806f27914", + "tests/unit/test_cellprofiler_measurement_rows.py": "075840915d45f71471f10783d693144ce984778f7b9d8b5ecdf462d835fa2742", + "tests/unit/test_cellprofiler_measurement_slice_consumers.py": "6ed678176054a6bd61089506a32b81c240587a491b240d651afc03ba27653546", + "tests/unit/test_cellprofiler_measurement_source_group_scope.py": "87d2454b86ad0b3baf7b1d4a7405363420c14331dba46c544b1329dd586f3e26", + "tests/unit/test_cellprofiler_measurement_source_names.py": "63cc28a24f49c942ca29428da35563bb78feae2b8acf851009f24b085e60389d", + "tests/unit/test_cellprofiler_medial_axis_contract.py": "25f1def3ed4f47823a8c2a1735eff6c915fb602b7ba1d1cfb0345d5710527ca9", + "tests/unit/test_cellprofiler_module_execution.py": "5d28dcb3645197772b77d5f8eb4dc07e729bc4b2094322e20efd6a7468f5993f", + "tests/unit/test_cellprofiler_module_execution_semantics.py": "86cd909cb3484ab39fd9f31e0d4ed63da801bfddfc89644662ca85d42cc92662", + "tests/unit/test_cellprofiler_module_function_resolution.py": "8afc6262bb4fa22c123febba522f29c3e6330e5c5fc6c67934bf3c6f49b1bf9c", + "tests/unit/test_cellprofiler_module_measurement_features.py": "aca4b6f427006999f174396ee17a9007983979c34208e01388c514dda57c7f44", + "tests/unit/test_cellprofiler_module_measurement_scopes.py": "4e5cd550d276e8a9bf04ae370b8cca85e5762d9eaa4ed64c7e5af0744d0e969e", + "tests/unit/test_cellprofiler_module_processing_config.py": "6ae8435f4fac89f5e6963c587dec688f363ebda4d5d9e688fcb56a84664f8b75", + "tests/unit/test_cellprofiler_morphology.py": "a09f4cc9299e41952996451654eff43f33276229263bf05f338297d3e64e563c", + "tests/unit/test_cellprofiler_morphology_public_contracts.py": "d33f057a26cb49b1a792edbd2b035c529695560c2c65a1500d8bac97557aaaa9", + "tests/unit/test_cellprofiler_neighbors_contract.py": "fcdd615077a5b9696d894487ae6d51b624d208d755652da5ea2e4fc0b66c9429", + "tests/unit/test_cellprofiler_nominal_policy_migration.py": "10bd96f1da8756657b0a4b73e9a0e9b481d9b80a525b573ec9933e721d61771c", + "tests/unit/test_cellprofiler_object_intensity_hotpath.py": "125b0125452de94581c238cd4cea493277b86400dc2bf1e11f7487d16e1638e7", + "tests/unit/test_cellprofiler_object_label_payload_inputs.py": "3764b06667a642af04f5f0dc3acc317193009149b809698d1004c4b60c3048c7", + "tests/unit/test_cellprofiler_object_measurement_schema.py": "eb4330cfb3fe69c27ebab0233c64df3fc18c1015909744d604ca7ba7e2c2e7c8", + "tests/unit/test_cellprofiler_object_measurement_subject.py": "ea81a9a03ec20c6040707978b1ce6c828ea9d7b67561cf2275d57f44165722d7", + "tests/unit/test_cellprofiler_object_morphology_hotpath.py": "a62c331445e802e5820938638595472f3dc95dd0032630f9fe79a0324c17b0c9", + "tests/unit/test_cellprofiler_output_cardinality_declarations.py": "2879dd2491590334e9ba6df097dabd50da8ec89c015a5603d52398a7555765ba", + "tests/unit/test_cellprofiler_output_record_occurrence.py": "c264787de54147b0ad6f5973df7cc8dd0572ff6b9b1b3cb49117ebad0a3fd6cb", + "tests/unit/test_cellprofiler_output_recording.py": "d031716e2d20d4e97b304d6123d92a4a9c69745d85671ae94fe8f7d50d4f213e", + "tests/unit/test_cellprofiler_pipeline_import.py": "353f0c1d8e0bc3552d2e418d792794ab0631daa16c78a3e10191b1cc1ea07d73", + "tests/unit/test_cellprofiler_pixel_classification_entropy_parity.py": "e60125c783b1759a9582ea7590eb4761ac0120310fb756dcb2978a04ca3b686a", + "tests/unit/test_cellprofiler_plate_workspace.py": "97602b34774e75926857e62faa446e307cf32a0c7d2c94fab16d5cc0919eaca7", + "tests/unit/test_cellprofiler_prepared_payload_abi.py": "9c367279e90217580066e23a03e7c343e1fd5b6c2a767343b1b1814e01c97ac5", + "tests/unit/test_cellprofiler_primary_object_performance_kernels.py": "2fbe25378814bee5900595476f47ce59b29564d66b3cf24c1742452fb1a058cd", + "tests/unit/test_cellprofiler_prior_measurement_output_relations.py": "c5b21937d07d5a0906bec2cbe0f8d66b08f806656db0faabbb2fe345c663657e", + "tests/unit/test_cellprofiler_processing_backend.py": "949fe2e9c3ab8b7b416121d65cc5b70aea2c59e970aa823c7bf0c0d5e438a4b1", + "tests/unit/test_cellprofiler_producer_row_schema_authority.py": "b3cca837b73e071a4a42f2cdefe721975debd8268c5f92312e5be45af2eabd9b", + "tests/unit/test_cellprofiler_projection_backend.py": "7eae609ac6ff76229b289170b9b5c11406c0a8035555a09cde0b771b5a7b6515", + "tests/unit/test_cellprofiler_public_boundary_contracts.py": "1f025f7e8c3fb8d573408046aa65bd2cafae7615a3e782b7f9facd8720bc3283", + "tests/unit/test_cellprofiler_reference_exports.py": "8b84a9706af7c9226ef93a96a3fdb9c1c16a8f220fbee4a65a53f6e15bc7cb61", + "tests/unit/test_cellprofiler_relationship_contracts.py": "c14b67304599c32405b832c2f1e839bf1132a22b276baff23ee7720c6d117760", + "tests/unit/test_cellprofiler_relationship_hook_caller.py": "bc848110c62fe2e591e57bcedcd0c287b82dc684d1bae44b8de05d78ea368aee", + "tests/unit/test_cellprofiler_repeated_row_declarations.py": "9e9a52dcf7f8b7aefb34d92a8cf5637f3869432c19b79d5d7807979a58776c27", + "tests/unit/test_cellprofiler_rescale_intensity_hotpath.py": "80627ebb7365aae6701f7138ec8a0945930d9502c5d1a1d4bc07923e928a5721", + "tests/unit/test_cellprofiler_resize_hotpath.py": "680502c768c3628e14b4ca43909b4d5005c578079705e9aded393c389dd3fa18", + "tests/unit/test_cellprofiler_runtime_adapter.py": "e4c1e9a86e2dc93a0af24088855caf3c12566e4bd99b9852c9ad3d152e2531a0", + "tests/unit/test_cellprofiler_runtime_binding_identity.py": "ff7ce51901b7d2f6838f19c454c0ecd32c219f82fafcb56748d6a8988ec73629", + "tests/unit/test_cellprofiler_runtime_cache_authorities.py": "67c1ae2f473e272931aba7985b46de77d26ea6b057a0a3eade1ecfb9fa3766ae", + "tests/unit/test_cellprofiler_runtime_callable_introspection.py": "c4a64d9dfcee6edbd28b44582c6cd2e2b0beaab59ad7b199c42d210adb580c93", + "tests/unit/test_cellprofiler_runtime_input_binding_contract.py": "72918563a6e410956e41ba902ef2affb4fae35f60169c924dcabb233715c6e0a", + "tests/unit/test_cellprofiler_save_images.py": "3d85eadb807d48f15b7141e8e708e38ea61d7adfb4997a7519c7d6da439ae732", + "tests/unit/test_cellprofiler_save_images_hotpath.py": "bc099686d2d6cc63f8e91b474ba46881dd783b7aa773d314d0513361ee45e8a0", + "tests/unit/test_cellprofiler_secondary_distance_backend.py": "1b3fb32dbb47b6d00928926591157ee0e97d385e4928475e5ce8cd4c9192fd40", + "tests/unit/test_cellprofiler_shape_hotpath.py": "482780c189ad4e6caef0973b05337fb3b8d092781ce7a5bdbf55ca72751e15d5", + "tests/unit/test_cellprofiler_source_bindings.py": "c10ab63f23a3d3c7332d890a669322c0709ce90192ded71664b02f1a2e7bdfa9", + "tests/unit/test_cellprofiler_source_bindings_ingestion.py": "46cad46526d114aaedb6c1d587224b34cb17c1e7ca8996c09acf21e8d514eae3", + "tests/unit/test_cellprofiler_special_io_declarations.py": "7b1001a3a3c18f8cee3b287fac51c9a63c0ad1ae0d3fadfd51ba8f3ceb421437", + "tests/unit/test_cellprofiler_spreadsheet_export.py": "0bd1bdc2c27c9133ffa4d665ae31f6121f636e1aa39b3ac65a78650a9b5a034d", + "tests/unit/test_cellprofiler_static_deletion_gates.py": "83d81d01ef7d828b2d0fe971a8487aa4cd049bc69e488f8f82aca2e9f02c2cbf", + "tests/unit/test_cellprofiler_strategy_registries.py": "4c6be9a25257af4370271b242072cd2dfe645113a56778108d8fd2f3878e42b4", + "tests/unit/test_cellprofiler_threshold_hotpath.py": "bbf2ec9cce2a366bdd6edd79b4de1ce5e24c8a703ebaa91b975643f94b5d2167", + "tests/unit/test_cellprofiler_threshold_measurement_feature_parity.py": "daab012aa799fb6bf612371ed4c07b5f00c90dca1f5e7ff04d048f8da4c586d9", + "tests/unit/test_cellprofiler_thresholding.py": "3422f937c0511d957a0f2d77e7ccba3ebb194db3af513b6a8e94d3d7de479eb0", + "tests/unit/test_cellprofiler_trackobjects.py": "71cd71125c1373d04da4da046d866d212664e3abe7d8534a67aba54492abbc8c", + "tests/unit/test_cellprofiler_uncovered_image_measurement_contracts.py": "884b0012c53e179d3300d6e174a15c9d354b074f869a8ca547e87b878f956d9a", + "tests/unit/test_cellprofiler_uncovered_object_output_contracts.py": "7587de1c35b7e69ad02a2f4b9c277c4281482b7c8b0e0015fcf934740efc8a07", + "tests/unit/test_cellprofiler_watershed_3d.py": "b4ed415c2daea68654aad5f072782f9338e307d2a24597978b34dbb074abf1e3", + "tests/unit/test_cellprofiler_watershed_hotpath.py": "268dc2d112e078e4edd999a4ecba8cd53f78ffbc60051f96998ab78cb2821f72", + "tests/unit/test_cellprofiler_watershed_provider.py": "163e378d222f889921515bc1b2bc7f58e1d18fb7ca27f9ebafa784ad556ce15d", + "tests/unit/test_cellprofiler_watershed_residual_hotpath.py": "a500ffd630f911f3be5417355538a94993c7c70cf198fe942bf2cc1d2e9ee4a2", + "tests/unit/test_cellprofiler_workspace_export.py": "87cc6873e395b068e07e9ae0e44ec1d45b8ae66f4be14d8464f6bb38d84e6a13", + "tests/unit/test_cellprofiler_worm_external_resources.py": "ca093ad12535ec7208ed91f05ce4779ed7c38e5558bc2f595c5dbcc2ebe801f7", + "tests/unit/test_cellprofiler_worm_geometry.py": "8cd2adc998e3b1e07d3cb4253df8bb8031d94599514f2c7c607cc8e17261e032", + "tests/unit/test_cellprofiler_worm_measurements.py": "ae8605658f4e1efa67a8afcd4e4b7e9227f843a91169e9ffb2fce102bdb430ed", + "tests/unit/test_child_measurement_producer_selection.py": "1baececa0cf0f2420bdee854ebacc3c03d12c6dbf3eb21968c4c32bd48d3d932", + "tests/unit/test_ci_action_pinning.py": "ef540fdc31ce7415adf55e8a6dd16f6524cc44d833e0b94c4e778a7435ba2799", + "tests/unit/test_ci_package_boundaries.py": "691efcdafe66255c55ae11411b441930bdb58161cd74e2580c2531a486863303", + "tests/unit/test_classification_interop_boundaries.py": "c2e1808ad6ab4613fc11ce69d417db7efa804b4bef6d8e1b78076c2e8eb1ee89", + "tests/unit/test_classification_two_vector_authoring.py": "4072744d39aeedd7cbd8ba39b6d30ec1be0428aecd6085e55d907b827357b66c", + "tests/unit/test_cli.py": "2190d0af08ca00f3c75907464055f6a2b0279b080f78ee3494af060c64ddc08e", + "tests/unit/test_code_mode_path_artifact_architecture.py": "d5c86163a5a74d68d9796f8420ff591f4f3130884a2aa430a3a60b53517e6719", + "tests/unit/test_colocalization_metric_setting_authority.py": "9d01d0cbd08dfaef7873a72dafd2654c0ff3d72fde9e52255f2466065451367f", + "tests/unit/test_colocalization_preparation_readiness.py": "0e29f77a8be4bddb6a64cb3b1322bac65c5d975f44fa2517025042afb2904451", + "tests/unit/test_columnar_row_schema_authority.py": "195e527b6d4e80479e15a9db5da71de2eb9a08ce6690d07e5d85134c126e63b2", + "tests/unit/test_comparison_manifest_acquisition.py": "90b08e22526fba440c1108427505932f747abc5738396cb8c1729556294cbdfa", + "tests/unit/test_compilation_paths.py": "0dd385344b28b930d8937ac717af58862d8cd102d96e3a193efdf8c0c0b83e16", + "tests/unit/test_compilation_session.py": "1bf949e58b0dd65469ecc548d7defe15c3d38f76ea15c3e3bc5ee8edf4eb53b2", + "tests/unit/test_compiled_execution.py": "ce77099d48c7379a7ed46147865811308d43d6861fd81fa8325a619f9026d6b5", + "tests/unit/test_compiler_auto_materialization_policy.py": "20e99467cf383d2af65bf1608b7a25fa2ed4ccc87577cee1af15141da11437a6", + "tests/unit/test_config_document.py": "0ee12db4633ab39b34f630e4ee1b0c48b40d8226f91fddc504bb3311b9612cda", + "tests/unit/test_configuration_consumer_coverage.py": "2983d982e12bb3b6a1b20665343457eebae1b2cfe1892538f11fa6fabfb42777", + "tests/unit/test_configuration_mirror_deletion.py": "26002ddfbbf89bf06ae54888645c6b8c90154536a16e93feee1a2fae713c4963", + "tests/unit/test_core_config_annotation_validation.py": "670d1903d03cdc12baea828336da05255d5076a3c22b86752e64b3a115481da6", + "tests/unit/test_costes_parent_mean_qualification.py": "dd13c9bfd9937857c36b6b0401f892f477beb2905d59efb5d90e48fa1d1047ef", + "tests/unit/test_count_cells_simple.py": "d14b5be006f439e65e185c4166ec349cbc017cecf6645bd950357be27d118698", + "tests/unit/test_cppipe_corpus.py": "f331b8d461a705747390b280a1ea6938b18d2949ab10b87de47b2f4da19ad96d", + "tests/unit/test_cppipe_execution_validation.py": "ed60b7e839cad3e30086aaf70e7185dfeb6b1263d5ad43bc40656d30d4df3b49", + "tests/unit/test_cppipe_parser.py": "c4fc16ef34c424addfdb3bd3a8c48c48d01d4d904f0463beacb25535d6864847", + "tests/unit/test_custom_function_events.py": "8cc545a424a3c5235dbca2c123ce7f1e266aaaa007b85082154cbf06ed78122c", + "tests/unit/test_custom_function_lifecycle.py": "fa04ef4891d76e85ba5f97b301a42fbaf077d6e21a8dc9ace34651e198bfe067", + "tests/unit/test_czi_brain_axon_cellbody_demo.py": "d588efdc530936fa2e4fe2c12ef95b95561d284a0d0cfe8de71e27c86aaa338f", + "tests/unit/test_czi_zarr_source_audit.py": "e34cf1bf815561bba0a641e08b1f4cded09c5157e37230844d1e113c9c95fe83", + "tests/unit/test_dataset_acquisition_infra.py": "517e29990e5ef5c038f3933a45545ea87d7e9ba75e29aac8e3ec754f99fe2c99", + "tests/unit/test_dataset_registry.py": "229655ec34e5d9624bbf4adfbda05c414c3b5e01a3ad9c437e9ecab4b9ec3831", + "tests/unit/test_debug_runtime.py": "6435e045afe2b292ce41c11b0cc671dae47a7a4039ec8c0c70f287f406124089", + "tests/unit/test_debug_views.py": "a12558de56bb0a8a2e436fda77f2333efd5689a0422189ac8a71279d173c1d1d", + "tests/unit/test_declared_singleton_composition_437.py": "4963c5d271965647125a5818b417aa40262c1c44ddba123848326beabb787fe0", + "tests/unit/test_dense_object_coordinate_reduction.py": "68b9aed4205541b07c1a1068a395f313b1e0b6598c6a2dce785cef5131d96d1e", + "tests/unit/test_derived_role_publication_435.py": "86e34ae6ad4de6c893ff80be3b842deb908bcf1c111a462098b87e7480ec74c0", + "tests/unit/test_derived_runtime_image_provenance.py": "73d0a93c23320590674e60dfa8a7af41a815b0b806c2383c0d9f1891b59c3b18", + "tests/unit/test_desktop_deployment.py": "ff766161504893139c0639884bacfa10e018a78eecc692fad1586ffe2af4e0f1", + "tests/unit/test_documented_dimensionality.py": "83bef8dcad91750c9acda63b8a4293ccbd0904dd5aea7a32be197f9d51f300a7", + "tests/unit/test_enableable_function_identity.py": "2f7ff821ddefd79c60f9b4b8e89b287c8ebe6b773699638791137ea32fd490d2", + "tests/unit/test_exception_traceback_compatibility.py": "b6bd140d613f67dcf4379dc3937b88f4a1ca258e7c7345153595ea5b2c676467", + "tests/unit/test_execution_server_startup_preparation.py": "d9bd0a0eeccf10d4ad39be72812217d93b63cf664c1d469146773158ed5dd7b6", + "tests/unit/test_execution_status_poller.py": "02c8a35c23b37de67f4f9e03ca822ac8e640f8434db738ed80715778740bd909", + "tests/unit/test_expandorshrinkobjects.py": "ea4b28f647273e6ad03125df104ea47a2d18be3b50111105523be6ada560a1b1", + "tests/unit/test_experimental_analysis_engine.py": "d7033d84b188c4cf7f2e8068599a746375300212d418cbf9c4c7d00c70de0f87", + "tests/unit/test_experimental_layout_rows.py": "d71b1e77aeb31a543e9da104a9dca2169aa7ea6c6e690a5c19302b26e76ae31b", + "tests/unit/test_exported_relationship_equivalence.py": "4fb5fe7a95601b87249952ec6022a60b0e244acaa8497ce787e53a54d106e6fa", + "tests/unit/test_fiji_test_environment.py": "f0ab63aa567b045c655731fa5f52af76618a4c2fe2d96fe2e7de9650346833d3", + "tests/unit/test_fiji_viewer_server.py": "2457abce7f1673f1f05b1c368add152ef73c9cf09a4f86319b15fb49111b3d48", + "tests/unit/test_fiji_viewer_server_launch_config.py": "c575cf5e4bae0d05dc6edf5b158f200bb023a1a3b1eeeeff537774c6a0292fcb", + "tests/unit/test_file_materialization_options.py": "7b7834cc57289b82dc5c2ca50f3a08d1be2b85212f8078d1ce1bf6b76b83d227", + "tests/unit/test_fitted_illumination_fields.py": "b0dba0f59136c74a92634ab4fc7e5edba3c560ff0ce15f5245c020ffcef9bbdc", + "tests/unit/test_fork_compiler_preparation.py": "f6bf0953f28cde60ed4c2c7d4204537cc83ae77e118fa850c3f3bf0abce75de1", + "tests/unit/test_fragmented_roi_materialization.py": "aa9e07f03bd010f23a601dd90a511c840d339c065e7e3f4042b62192fc349bb2", + "tests/unit/test_framework_device_resolver.py": "ba1814ae8eae05a39b594a81b4fc0d1444bf1334574bf4efe49aa829eec43a65", + "tests/unit/test_framework_execution_scope.py": "888a7693d387b0d5007c9868f0b0344fa3df26620f35e40b45832f0931ef7126", + "tests/unit/test_func_registry_projection.py": "2149ff5b4d623ebd93f508fac786c4f76e763e29115b3991cdadbb2bbef6bb18", + "tests/unit/test_funcstep_contract_validator.py": "2188b297564b7c756af16f1138e304a1a7dadbdea28f7c440bc7b484d9eb615c", + "tests/unit/test_function_artifact_materialization.py": "42d4b00c0849bbf28f079a87dbf6552d03e2b1e40f247da1421a603996bbb351", + "tests/unit/test_function_artifact_materialization_io_hotpath.py": "be8b34aa6ce8abad7f3f821bba7484758696f58726960bf24131c5a7c280ad72", + "tests/unit/test_function_artifact_outputs.py": "8da643befd94c558b27b940278aa7695688158951d0bc3153522b9f6a414972b", + "tests/unit/test_function_catalog_zmq.py": "ad58725b8e9eb418ae5775a7f49263e5f0e2eb35bfebec6a71539aae0db2715c", + "tests/unit/test_function_execution_lifecycle_anchors.py": "344e44f83930a929a0b09d6aa7c999fe4ade2f534fd7f5849168275abcf4cd93", + "tests/unit/test_function_invocation_callable_resolver.py": "d3736dcb4733fdb8538d3f9e8f813bcbeb151ffb365b788f69136a4cc5fd7b24", + "tests/unit/test_function_io.py": "c54d592b3b0c8636150d4053eb11164556141036d8d0e1cd70a222b884aabe5f", + "tests/unit/test_function_output_manifest_input_scope.py": "a0c1619a2e7ff80e766d89a494a91536b7b45581e9349571eed63ca56498bf58", + "tests/unit/test_function_outputs.py": "f45696a138d9b1d055cda36468367dcd755e03b27681280f0f043662025371b5", + "tests/unit/test_function_patterns.py": "bb77ff3ca4b2aa7c05b1751757b0937c191e790dad2c046c5cd30273867449ce", + "tests/unit/test_function_reference_identity.py": "bb9e5a5002ffe01284178d5e611e2015d95625a0b226b5e51a9581f2b1acb619", + "tests/unit/test_function_runtime_source_projection.py": "1cadb8286047e8bc19e24aa19603ba3defff8584a23cdc7d43640b56815af6a2", + "tests/unit/test_function_step_document.py": "8a66f2625c781b136674ba7ac390736d4ce1685ee9b85308a49cfec862b7ac36", + "tests/unit/test_function_step_execution_plan.py": "e933c545ed00bcd5ab624f62b6b40a8d2d4e350e3ff19146eb43205a61407fbe", + "tests/unit/test_function_step_execution_scope.py": "c5cc0c80f99cc9a3fa862ec44aaaf9ffbe165f054c9334f16382a63b39d03b65", + "tests/unit/test_function_step_transport.py": "1d0675f3a860bcacebf5fd7b31dd5c85aec08941d20d99d8b4249507c0c43b1c", + "tests/unit/test_git_hook_submodule_safety.py": "5afcd24902dbe701803786736104f565934edb3093638a46a406e56b05dc09e5", + "tests/unit/test_graph_roi_source_roundtrip_134.py": "ad3040d68df96f7a742ec1ddf392c721650510c119ee13794431c1356ac59194", + "tests/unit/test_gray_to_color_binding_axis_432.py": "84fcb3c7471d69f8647ebf577c392c2f4805bb0d1f8b298516d8c69b48a6cd42", + "tests/unit/test_gray_to_color_carrier_compile_432.py": "38582266c22850e1dbfb82caa7a3f62f454570930dd7a161ebb64ecfd17d76be", + "tests/unit/test_haralick_feature_arithmetic.py": "a9b04b224d1f26ef706680d7dcb7b45c6f0836efee7ab40fe73996cc81db5aa9", + "tests/unit/test_hosted_mcp_container.py": "dc16ec4b6aa74ff085c2681638881b76003860378feb3e1ec30ff3b16f2746c2", + "tests/unit/test_image_file_serialization.py": "9d69cac82c9e3eb99860877d2f3ca1b0bebf6ad41a1a49161abbe584773bed60", + "tests/unit/test_image_output_context_projection_proof.py": "7217339612d0cc674cdc0813c6258ad75231e785e3fff7eeed3d097f62c7d76a", + "tests/unit/test_image_payload_projection_algebra.py": "8a53039ceb1248ba04243bbe08cb83f7a1458adf26c78775f7f6790bdf33b5d4", + "tests/unit/test_image_plane_contracts.py": "7d2672411cfad98a4ea21969268591dcfb6bd7211ce4cc79bf3658d13f1936e2", + "tests/unit/test_image_stream_request_projection.py": "4f3560759b74a7116b2c927116f40ad072204d5e62d69644cb400bbf9c71133c", + "tests/unit/test_implicit_main_flow_compilation.py": "3f4721cfbd9669af2d89da7dc0722bce7409132bf179f0033201000c53b1a446", + "tests/unit/test_import_utils.py": "9e0607b1d862a32df02777f1f22d4d08a227f5f3d4c76323bd02aad5ee8b6512", + "tests/unit/test_independent_validation.py": "41162b6c1a0f51f41df27263f24ad48276b9a0dfaaa0259368c80f4c919aabf7", + "tests/unit/test_install_ci_candidate.py": "43b636293b30767c8040d7da77d440090089d097df75dfcf0649efc07fcddcb0", + "tests/unit/test_installed_mcp_demo.py": "f5d4a719a7902b364b551a3cbc4a816ccd7f46e5d9abbc87bf2d53cb0180053b", + "tests/unit/test_invocation_contract_provider.py": "fd06be78e1e5fa09d238b327a70e75ff993c2a00509f57a85f21b2befb1b0c5a", + "tests/unit/test_invocation_input_source_context_identity.py": "2bd47803761442d8aa8d64bb642960c65d21f2abf06cee7e50e59f16814976f9", + "tests/unit/test_label_area_perimeter_performance.py": "c2a77cc2384434a424f9679a92737d3babeb218cd7897146604919d62f7fe6b3", + "tests/unit/test_label_geometry_ordered_selection.py": "d9a367590b99b1c0e6f48bcfaf2b34bd0c22115d20d768335a3e07e7d523b230", + "tests/unit/test_library_registry_discovery.py": "4ed60118ac0a052d043758a1338939fb9521f46046fc86d40376e91e0528be1d", + "tests/unit/test_logical_image_output_snapshot.py": "1543a3859d68d9d166389bc28977f5988f1736b199fc40cc2210e7728fd030a7", + "tests/unit/test_loose_operaphenix_neurite_example.py": "219e2159c50234902c09b9d757e71bfa89143d7b0ef057b6a3a9d4ad9b76876b", + "tests/unit/test_loose_operaphenix_neurite_metaxpress_example.py": "8d483849f35061aab8ab9b8dea7bd4a3491c0251fb380cd1a2178c2e96892fd1", + "tests/unit/test_master_multi_plate_demo.py": "92fe883ad54393a8b444855323c319e08fb40fe47c1a4183aac326132600c2c2", + "tests/unit/test_matched_cellprofiler_batch.py": "469fb3a9da16b1eb7224c63832c7d807d4ccf08776bc0ff9775dcead4625ab46", + "tests/unit/test_materialization_api.py": "3a089a428a541301054b2fb688880a1ccf2eb296f4b4297173b3124b8831b28a", + "tests/unit/test_materialization_batch_outcomes.py": "08abb20627d0d82f537a8c688984f04b8bdc4fa298a29fcf9cfc8c006f30a8ba", + "tests/unit/test_materialization_core.py": "59968a28cc5a838012c5e4ba8bc29a14d972e4a4df0b55bf4110c6938f1f46e9", + "tests/unit/test_materialization_filter_inheritance.py": "ec905e0a8c7188878236e460ea7dc1532ad249f35876e00137c9c7b39e11819f", + "tests/unit/test_materialization_flag_planner.py": "5e1c4751092670e28a352f463b44a57c7df491e515eb14a942bec62c44c35a5e", + "tests/unit/test_materialization_source_extension.py": "199b3e793f6cbafec7f4dd732d356c6705b91bed18f27761e75c6d5392efa3fc", + "tests/unit/test_mcp_assay_showcase.py": "916c0cfd9d75af93628ceb4ff948414078638b4638a51b1b4b075199224729f1", + "tests/unit/test_mcp_dev_client_persistent_session.py": "514cb76e38cd51ea542f7f9fece2758cbee319449a0bcfe832ae064c666bf3fd", + "tests/unit/test_mcp_dev_client_terminal_input.py": "2328b95d10f4e57c048694d3775e4039467307b95bddf8c70303c49f5d170321", + "tests/unit/test_mcp_memory_diagnostic.py": "b9ff12716ffb934b35885764292defb04f4bf542024020094d1308d4cb05b763", + "tests/unit/test_mcp_release_workflow.py": "7d8164b53ad4758e47a6e8dd5235dc0b74ddf1aa232cfaa60ba2589ebdd9a360", + "tests/unit/test_mcp_thesis_demo_live.py": "26cd0380fdd03668baa346931571c9db60ecda541d8ecaf464498f1bc0f87bd1", + "tests/unit/test_measuregranularity.py": "455d5bb8459b35fb4946ac48a565c5dfa04d3f336e10b0e028d4b5e4b92ab891", + "tests/unit/test_measurement_axis_field_projection_performance.py": "89d96a021014c28044579a60470b2509a2b030b643ec179dbdf39ba2bfb5c04c", + "tests/unit/test_measurement_image_alignment.py": "b62069ea0f4aaeddcafbdd28228fcd1a5d5eb776098ec00d8b81676b79bab6b0", + "tests/unit/test_measurement_image_plane_projection.py": "30d3de629d27f56d2ec116b6f497e1e9efdc21ce50bf51727e35b86b3eefb34e", + "tests/unit/test_measurement_lookup_dialect_performance.py": "f13b0d3a4b2396d8686f6a1606bdfcd8f40d5f1d9566771f33536c425e564073", + "tests/unit/test_measurement_output_coalescing.py": "7f059dfb0d4e17eb3865009ee3fdb6c98656e41d965fb0ead4baeac553c29045", + "tests/unit/test_measurement_row_materialization.py": "8d6f36c3782e274d9e3aed3048e793ceb93f751c5a491519817a6986372eb98a", + "tests/unit/test_measureobjectintensitydistribution.py": "630eb3e879bd42c5a74ee64d576107f72e40efb61f67cddbbc7fb13ce671c4d0", + "tests/unit/test_memory_type_authority.py": "0da705f6f5468c2bc8a866f44057c6790a2a679d80648f47c9b373ce1af64632", + "tests/unit/test_metadata_namespace_327.py": "9c5fd4bfaa6b9a800bf3ed584d3f07785f91fa74c918717507e822dccf033323", + "tests/unit/test_metrics_memory.py": "5351747a6cc5f50d989ebb21cb160296c0d0e1a13ecda7b2a31417b27db016f8", + "tests/unit/test_mfd_preset_specs.py": "fcdaff52ff1316d3828b93989ff8b36ca554c482387feb22382f4844833e4052", + "tests/unit/test_microscope_handler_identity.py": "6fcbd57c3171152dbcd24cedac92e9225c9ad48185624d3fe9429334925c42c5", + "tests/unit/test_microscope_virtual_workspace_metadata.py": "3cc22e3ca26666e89b23e7c3973cc089e9bbbcf5411d807a463e393c0754ddc4", + "tests/unit/test_module_only_setting_binding.py": "5b8014238580560aa6ebc844463f9fe68927605da5aef9e0eaeda9852c737dd2", + "tests/unit/test_morphology_declumping_readiness.py": "ad0d4237be7ca1a8ce4fe2ef67cc386b6b8593825e1e89aaa569a5c7dd35ba96", + "tests/unit/test_multi_template_matching.py": "9a9a5de430832ceddffd4aebe8f5c8f33ffc2c737e8cf3f80d108598ae212d15", + "tests/unit/test_named_checkpoint_publication.py": "59e0fabac3d4c2662cd4780e94296ef24cc13cd37782443573e59eb01b6db3c9", + "tests/unit/test_napari_accepted_work_settlement.py": "a6248305f0d4b27b92b3eb81fe5b75a31073695ad3b5ebfab1d76071d9d305e9", + "tests/unit/test_napari_orthogonal_navigation.py": "1a67c3c15c5084f611bc43cc3d9a2f7ff4f3b00d5daacff8e98b5db1854af5bb", + "tests/unit/test_napari_render_snapshot.py": "7774b519d2a9f849080a76f656165697b57a6336e81dbc641687781be1fd6eba", + "tests/unit/test_napari_reset_transitions.py": "197c0adedeaa25343ad617106b83efe62023eb6cdee2cc8155a7d01accdbc80f", + "tests/unit/test_napari_roi_manager_integration.py": "de66b3d7aeb49b100ac5bb3c3acdf1c14afc19fb3681071b4356f6d7949a52dc", + "tests/unit/test_napari_shared_axis_navigation.py": "3be9f70a45b757e1fa729584092f022066c3721f2cdd7abc8ea55c7c1b57f4f6", + "tests/unit/test_napari_source_channel_presentation_448.py": "237122e56b7cd84f15cc7e26e3a67e997ca61fed51249b69687828e4a6127c61", + "tests/unit/test_napari_streaming_handlers.py": "4ccfe29d525db370f0f548469b99daaa608ddc75378fa123a932cd1dc2c2fccf", + "tests/unit/test_napari_swc_reader.py": "9eab981062d90f46c1e73e044185ec85b490cd932280287ce20b6442ec742ca7", + "tests/unit/test_napari_transport_ownership.py": "2b91a92a059a1403dc289744026b7dd1434bbc59790b1760bbcbb6e6b0bf019c", + "tests/unit/test_native_batch_barrier.py": "edb81a784a017ff1d65e7fedb65c0566a06eb96609c8658a45813e613b1bd9ee", + "tests/unit/test_native_synthetic_well_scaling.py": "17143a2dd3f320afd7ba4b7412c7c27b127950bed6e82e0a3ed10ae09f374c5b", + "tests/unit/test_native_tabular.py": "921c715a97276f87190535a406c369c48185e982f3f1a1fe0a4093e999f61bbe", + "tests/unit/test_native_threading.py": "ff1320c75d0318bb729a43543fa94c1ac2f1098930c2a42bb6416729195fbce5", + "tests/unit/test_native_viewer_presentation.py": "2add4f4be6f6c4cdb76b5080de04ff162ec4fdbc93f26994d6b0117550ceb206", + "tests/unit/test_native_worker_durable_evidence.py": "972af31fba20ee9bd320a455e9fbb3dfd1c909ed60d0b1fee68ef249a2d00fd4", + "tests/unit/test_neurite_cell_body_size_control.py": "d25d635e2dd22f67ec3ed29567c96724f09ab3ad4e65ab2e31b21488470ea62d", + "tests/unit/test_neurite_outgrowth.py": "a819cb4b1923223730c68f5b31de1ee8ee6a73c156f18ae70678e0761d82929c", + "tests/unit/test_neuroncyto_ii_neurite_demo.py": "a43e6e5be06ad109d8ef782468d79574f4d790ff5458613537ca9164a5481303", + "tests/unit/test_nlm_slice_contract.py": "ff995327f4134f8a616c575b77459c973f64318e70943f91e9259ac8341329d1", + "tests/unit/test_nominal_contract_architecture.py": "b9a173abb1e1bb73c19d03591cdea79fc6516b0fe30ae8068ea9d2b544256bc7", + "tests/unit/test_nonpersistent_viewer_state_evidence.py": "89b766ab2bbd908cac5d96e86ba26b1bf347a84f3a9bdc3c5926a00ac8c2c9a2", + "tests/unit/test_numpy_runtime_capabilities.py": "fb8ef2e05187df66923a684d81880cdef64b5c57101f8baa41a523c17d2621d7", + "tests/unit/test_official30_lab_meeting_demo.py": "6c4df3cb80e7d6df66843f8de3fbc76f6d3777f03abfaf99041eec78dc3773ed", + "tests/unit/test_omero_instance_manager.py": "c9341221f85069ebb465e67f28f240191a94bc690c2999d9de36212505dccda1", + "tests/unit/test_omero_microscope_metadata.py": "066e612d760bb5d0a75c5301cc6fb2d39ef460f1d7e84c67679505bec11ec7b9", + "tests/unit/test_opaque_main_flow_image_domain.py": "f6af4b334f26d12f4494ae6165e9a10f80d1c004dbbe911092632b8f8f9e8a5d", + "tests/unit/test_openhcs_adapter.py": "6d2f195f0c8438d1587ce93c7ef5fbc9255ab4a237b21da0292a7474bfc8199e", + "tests/unit/test_openhcs_measured_run.py": "5173f0b2403437c2d7d4df91e6fd9dd5f4b940e2ed0b151364acc4d207f215a7", + "tests/unit/test_orchestrator_execution_result.py": "1e96be76377459a6d035920105bbbb01fe5a029a5094f1a38942b496ca799b2d", + "tests/unit/test_orchestrator_lane_planning.py": "09c39f5cba68f8c15a0def8a09843b62d6da5c5a01e7558a9263ce4d311c078d", + "tests/unit/test_path_planner_axis_source_scope.py": "8c1f8a0b581b18ba08c4cfc7fe3e57291f639ca91f2e344af535ca628573ec08", + "tests/unit/test_path_planner_materialization.py": "d81e3c1d88347cce21c3b5cec83a4935ef0ef0b6d0b4486d3cb0f538ebce7565", + "tests/unit/test_pattern_data_manager.py": "3a1edfbd36a9979a9a3609966e52ac39778247bb0b0ed40d1d7f347b3a9a9845", + "tests/unit/test_persisted_image_metadata.py": "625cbb171a283966ee4b2f2a3a81a4d33d8671700fbe375c9dcd0a5ac49459e3", + "tests/unit/test_persisted_roi_only_publication.py": "ad3ad726815f5c4e53ed3bbc37c4abd8da0b3a20b1af6a9647f3b9f7e96858b1", + "tests/unit/test_persisted_semantic_metadata.py": "31d8cca37ec42f3c0614c14612f351d86121decded5030d84f9401f7bd89d75c", + "tests/unit/test_pipeline_definition.py": "4e7f2bbf9731bb1d2430e175f602827d9049645e4480705c0c7667536068ae8d", + "tests/unit/test_pipeline_demo_contribution.py": "695f8455a748e771496734b96fd2637ac8822cd0a177452b9cdf63daaf4e3c50", + "tests/unit/test_pipeline_document.py": "2c18222ac2a34ee267788063a374112b17874c64693bfe542669c4183bc90c36", + "tests/unit/test_plane_nlm_declaration.py": "c39de413370bb3a8f9821475c0fcbbbafcb47e21065d31eca799c7be353d0712", + "tests/unit/test_plane_store_sources.py": "792a832934e9e25ddccf08796bab4ed5c519212f158af9915226f84cea08120c", + "tests/unit/test_plate_image_inventory.py": "d8af910e4e02afd9ebfb24a78eda8a3509c0eec7782feeee85097ecebf09c041", + "tests/unit/test_plate_manager_code_document.py": "23d08a4b3f3726a465d3f78d921788b951e98bb6611a173e709ecdc2c5254363", + "tests/unit/test_polystore_disk_symlink.py": "546520ff47ba2f1f39a66b0afc0257cbaf2053b169e76d1074327a1b114ef597", + "tests/unit/test_preparation_admission.py": "c67492edfd75d408b40661a873cc05940f9a1597c4f660abca1e4cec86f96f9f", + "tests/unit/test_prepare_blind_neurite.py": "255ba56feedf16f8805ccd3a42440f7ff60a29966fc081886c9b345ae127086d", + "tests/unit/test_primary_image_carrier_compile_gate.py": "1e3b1f10e7ed156a5d941b9f9c0e5bb9f5dfea310829d5d6795777de1546978d", + "tests/unit/test_primary_object_diagnostics.py": "44e65892369f02f34fbbe912ee5f236c5a1471c2c47de5186a7a04297e217e4a", + "tests/unit/test_process_environment.py": "eecab72b95e6595c31d58e8f970b1260b191fcd2a31e353e1e6281527570a894", + "tests/unit/test_process_local_cache.py": "29e89b99b665ba272ea93c9b5b3595b7236eba5494050dfa8f30b450b1407ff4", + "tests/unit/test_processing_preparation.py": "ccc9523dd0092483a66e8ddf2ec186cf388d1741c64fa4073a05cb3bc415c027", + "tests/unit/test_processor_method_strategies.py": "4c3172d38136b0961140501fb4c86a92b583c2c66ed35ee8ff94010381782f9a", + "tests/unit/test_produced_plate_source_selection.py": "d99d5f139cdc8fbbd16b955c83daa62734e085edfe8c25245125a14aa1eca928", + "tests/unit/test_projected_image_output.py": "e9d2cc9c869d8988050af1662d8ed78e925c0a801042676d9f2c4bec89d91da7", + "tests/unit/test_pycodify_formatters.py": "345fdfcf543593a4db7217fa7fde143da8510604e96c34e1a0e98eda3f4802da", + "tests/unit/test_registered_configuration_source_readiness.py": "e8e5da26ee482820375dbb756b6556e6d5ec9332661a4a8e29d51bc7bb1b9523", + "tests/unit/test_registered_object_output_boundaries.py": "9780538d98121512da19fa0b7ccc7cc0ed6a5e478e049c17714943fe0ef6e0b7", + "tests/unit/test_registry_owner_iteration.py": "3e042f8980dfac25cf7e27d42f386fc6a63329d4ca7f21348a21589ab56a3046", + "tests/unit/test_release_readiness.py": "72188f254407172a68d149f555b78b3eddfdb8096fb4c4337633c17090343b6a", + "tests/unit/test_repository_layout.py": "e7bcf714d4dce65a0a7abac4eb2bac507cfce79dd87986b3a04f747c43136ecf", + "tests/unit/test_rescale_stream_plane_declaration.py": "f63145674a5ca1885549a02169c3c4c32e646b477fcaeebcbbd877ca8007a967", + "tests/unit/test_returned_output_abi.py": "a0b33c98529e5705e3ac823661746e280d9cbb95c149ecae8a8faa6391232452", + "tests/unit/test_roi_source_metadata.py": "496035ab1ae0f0493c712cbf36a05584209f0680f6aa247566d0fa47190b317b", + "tests/unit/test_routed_channel_selection.py": "f0f7e10c99f6568048817f38ee10f648bb0b6fb4945cc0fae0f988761557745f", + "tests/unit/test_routed_composite_execution.py": "009568bcaec6b6dcfc4e88e1b448254fcf70f8a93aa37fc9ce56392057870fc0", + "tests/unit/test_runner_cellprofiler_compatibility.py": "ad6045ce7bcf4c89f781d8dd70d7e44310d89e51d73181256e5216f26dac2335", + "tests/unit/test_runtime_adapter_source_artifacts.py": "1f630506b2edaa13259d26d063cf08785f3ca385ea662a98212debe7df5bd2c7", + "tests/unit/test_runtime_artifact_queries.py": "91d9748d93994b9bd69f9969b3568fc0dea4aaecc3cc71c2b996963fa68bc904", + "tests/unit/test_runtime_callable_resolution.py": "8e91bdd459730fbb3a1cc4260a5c8d57f7448050ca968a44657c197ee5fbc798", + "tests/unit/test_runtime_equivalence.py": "e7120255a4374a7ef053a1a4e529d241cc74f2616878e6c691ce282acd4b67d0", + "tests/unit/test_runtime_equivalence_package.py": "b1f34bf57809c77f41c9a201646865f419d093380f52454bc9273a8f978a403f", + "tests/unit/test_runtime_execution_validation.py": "0891faa1b82a2aaf12d68f944749ef703211d41fa79d477f8db60f4ea4941014", + "tests/unit/test_runtime_exports.py": "aaee3cb126bd6451d56ed1ad1e4716bf3f7b2cff5041d8650ea41175a83b2017", + "tests/unit/test_runtime_image_singleton_alignment.py": "970ba88fa84cb86476054d0249f9fadd165147cc759365854a32d01376d5b4d9", + "tests/unit/test_runtime_import_authority.py": "506112f13a0dd8162b6e36d366df4fc92e7f604ef2fdea34de8e1790460925ed", + "tests/unit/test_runtime_object_label_domain_transitions.py": "205cd3bd4d7cc5cdd330d8bf87d896548c6f087fbd79d4413ed73dff3a221192", + "tests/unit/test_runtime_output_matching.py": "0c20cd4561371aa1cd2a4b12e8956710e7f4e39728bd6ac89140b249825fd9e9", + "tests/unit/test_runtime_profile.py": "221168e880919fd80097c30f10d1d2c88d5cac647b77378d1012efada8f811b1", + "tests/unit/test_runtime_semantics.py": "f55fba657fc709e558966241a2792971bad6b98ae48a265c4c5e0b0350beb4e6", + "tests/unit/test_runtime_slice_projection.py": "68a13ab84f9718048cc6952f48844c8cfd6fe312ba30c45c65402fe491338faa", + "tests/unit/test_runtime_source_resolution_snapshot.py": "5a0c62e3fa6c305e7a78856c94bcc9671037d68585b5f9ff17cf6a690563c396", + "tests/unit/test_runtime_sparse_labels.py": "2adb3d87b83d564bcbda3cce6814b5a09166f2e14307007503fac330ce5dbfa3", + "tests/unit/test_runtime_stack_cache_lifetime.py": "a63226b25afc995817b496c1cf153ddd324786cb5e746c49399082b0ad2f573c", + "tests/unit/test_runtime_tabular_values.py": "ac6370eebf512011d27eff03f683a816e017461b472709ce36c662ea8af24d64", + "tests/unit/test_runtime_value_store.py": "7f565fb8385ef7ebcf6d604738f29fb7dbbbc275de040c7cdb46bd1b39efc71c", + "tests/unit/test_runtime_values.py": "468d21c5d886176ea8845faa8551eb6f8a3c37da7b551b673f2cc502fd98c138", + "tests/unit/test_saved_source_label_plane_domain.py": "82223582d595a6e1892a5c02d8902addcf567ac3769304164c27770c539290e8", + "tests/unit/test_selected_plane_stream_materialization.py": "19cb73b4731974fd4bb9f6bba2d83f3424231eafe31382896ade9321793e1bfd", + "tests/unit/test_self_supervised_stitcher.py": "724b8666eee39c4a8631da09a94cdebbd0ceccdcaf49f90ffd46f21ff7cc8c40", + "tests/unit/test_settings_binder.py": "5b386f648fa38345eb9c27a930b92d387ef4ff0db660ac11265aac6c1adef2e7", + "tests/unit/test_singleton_rgb_label_invocation_477.py": "4087354457872cb05c1584cd373a25fe7207a4a77598f162b6ced4cdb8d2dff6", + "tests/unit/test_skan_axon_artifact_contract.py": "857de9a98ac74287873dfc26f18d86faa3591f6b5c07bc31801368e2d65f9e1a", + "tests/unit/test_skeletonize_and_save.py": "dd4a38dd043930dac28d6bf7f290cb3060d0b4a66a8ecf20b0a1e5a6234c37ea", + "tests/unit/test_smoke_installed_gui.py": "b8d1a1fcd67c58e2b2749262b44c1dcccbb2e72a0d299d180823e94a0285ae9d", + "tests/unit/test_smoke_installed_mcp.py": "141ba0d21d70791f824ffd1362e6ca84f47fff0d7b18dd109086d6ab5f8bdb61", + "tests/unit/test_snapshot_deadline.py": "66f461fe8457d41b6a7acef0e3c35b89f9cf73c543ac32cc3e2233ce70345ceb", + "tests/unit/test_source_binding_path_admission.py": "eb69e9097a03ecbc55c6aa329f26e83a321bbac3aabe3f60a106a5088db39d21", + "tests/unit/test_source_binding_workspace.py": "69eedf76a5c3cebaf1cb27ada78f00ba8b3f362cf1d31ee982a585841189232b", + "tests/unit/test_source_bindings.py": "fa17e812b265cb2c9ab38c67fa62c404438f704c21fab534a55de720c5363245", + "tests/unit/test_source_bindings_view.py": "ce59871d9820abaa052f25e4cdd8aef84377dc1c43079cb7c99ff35c6434cbcb", + "tests/unit/test_source_bound_matched_image_set_anchors.py": "5c5f98733afa7158c179558759c06033d01d61611dd532f7694ddeeffaa92127", + "tests/unit/test_source_image_provenance.py": "3fc711c7600f65213a4b4e150a09d4289d506dfa669ee1c38e523a3bac665835", + "tests/unit/test_source_image_provenance_hotpath.py": "3539d62d0c1c0706257f8cca8c54452f063b0e70e479976b45b6250621ae34b9", + "tests/unit/test_source_image_set_identity_policy.py": "f106cb03132c41485c6c3dc065481abe80eac0682d25fb3a27cf0e1be093832c", + "tests/unit/test_source_matching.py": "6297d7ba9bb96634122703a3d5d750428080e3894ea92901ae6b2e688fd5c78f", + "tests/unit/test_source_metadata_live_mutation.py": "83b576aa30cd8d8e1a35856c0555406f0dcdc2089f5fc8b3298dbd3cb44e81b6", + "tests/unit/test_source_metadata_owner.py": "e04a9cbaa99775908053421a90c8bbf852dfce5c589842f7583f59f956482728", + "tests/unit/test_source_path_factoring.py": "280b4aa846a37a171dda304b60aadc9f6def826c481e309ae26c613c8a63146e", + "tests/unit/test_source_projection.py": "35ccaa08f3c588a48dbae1eb3ad1bcb2d43fa7bb58592dbf9b0957a77da6cb5b", + "tests/unit/test_source_projection_family.py": "21be7517d3019906131e678a00c520336e9c0150062bc389666c10f5bb1d1f41", + "tests/unit/test_source_provenance_constructor_defaults.py": "e9a397292cebacce5554fedcef29aa5d20854cc57cfdbbe8992aafaedf04f964", + "tests/unit/test_source_spatial_domain.py": "a6f9110452f0a53509dcbc99aad3cab0aec7a1247f0aa59d5c31cf8c4f419e68", + "tests/unit/test_source_tile_geometry.py": "cfef1d2cbfeb4dcfdc57c666e96afbae5e309c4dd809c7fb82112c2c22186f8b", + "tests/unit/test_spatial_graph_materialization.py": "924dbef35f2726996877a8bcc3d58c58f5201a71efbbfb8932a77d72594968a7", + "tests/unit/test_stage_ci_candidate_version.py": "da9cd12d8abbf11497af1c74fc028a6a8f32b25c26ba5832e55266a47865b309", + "tests/unit/test_step_snapshot.py": "463a665e5d542b7a0f6d822f4923b52bc78e2009b2d47b82dbdd23bd043f298c", + "tests/unit/test_stream_component_semantics.py": "a83a41518a708065c8510c17aefb7556f00f9ede5b4d0dab8cefc131543ccd3f", + "tests/unit/test_streaming_config_factory_registry.py": "2c83cb1099389db4b522e3b1e1d994303a7b9cbd64558a75a120de5ee7e06387", + "tests/unit/test_streaming_service.py": "0bee83a7a3746b0399a1cb1b84347cf645360db2411f051f077d7e464c88d76d", + "tests/unit/test_successful_job_baseline.py": "d2e7cb0d1595ef16f8fbe5130fc352e644dddb3ec6bc4bb66b664551a62ccb82", + "tests/unit/test_sync_mcp_release_metadata.py": "a51aa3eaae100c9de985064188712057bbe8d374453028a56a3abc9049401f34", + "tests/unit/test_synthetic_generator_randomness.py": "6ab3efd7f4e083744dc4dda26d97c60b6a7649dd44432362020027b92271717f", + "tests/unit/test_synthetic_generator_zero_geometry.py": "13ef351e9dcee3e25dfb99adb4ab2b08486c2c08a7303a434fe68098fbad6ce8", + "tests/unit/test_synthetic_imagexpress_bioformats_compatibility.py": "f8db87da9fe7c38474b55092a93d751b492e7484dd6ec6750eeecc0c0b67e96b", + "tests/unit/test_template_crop_pipeline_execution.py": "00cb57094299ca9076a17fed870c48dcf783be601049d37250d216ca934eaff6", + "tests/unit/test_tiff_metadata_mixin.py": "4b51833fd7ec8b2e87b97e94c31eb3b947222e74e2296a70b0927b135587accd", + "tests/unit/test_tiff_output_compression.py": "458f576e545a033ed9e23b9dc349ab92c19d296ec7f0e269ea89884cd9b82942", + "tests/unit/test_time_travel_navigation.py": "930254f1a6e953056542b22367bb9b5631c529694709fcc001af3891d94be91d", + "tests/unit/test_ui_zmq_config_authority.py": "006275af836076d84fca50eb5e17df3f9ac000489639aa2e9ea9c3eb93847310", + "tests/unit/test_unified_registry_runtime_payloads.py": "decd7b16e59a1c960af0d16ca56da190b3e9c25d7984bda7129b6c8796eabdd9", + "tests/unit/test_validate_documentation_audit.py": "3934174a30ea2b7043e34809e2e71f967e5ef11c554f65a21f2517e9dbef8ddd", + "tests/unit/test_validate_local_release_floors.py": "36b9e9aa7a4d7ac78c7eaa229750582a025ea8bffe43e3b2ccd2350fe496c242", + "tests/unit/test_validate_wheel_deployment.py": "7909c30f7afc321f939aebf52c5c603e153cfa13e869492e0538f78dc632e145", + "tests/unit/test_viewer_channel_display_metadata.py": "0ba909bedf02b4b2ae27179554fbf0a1caa9ad9ac35bf10cb0b9f16d705f596d", + "tests/unit/test_viewer_feature_measurement.py": "21e716f82e6dd57be71049533ae317eb0b9dcef7163c3dd81cd4480383a6cc99", + "tests/unit/test_viewer_listener_binding.py": "f85871e6faae54781fdd9810ea6b999ed1117b3d465be75efd555c1b9c296470", + "tests/unit/test_viewer_protocol.py": "a6b78dc4b899c9bf4d89300a6518f6a915b27aacc78fbceac3288f9d2de187ad", + "tests/unit/test_viewer_receipt_replay.py": "be7662bfbd4901d6bea915a482f5f5739fc36a93964ebf87d8de33a983c7222c", + "tests/unit/test_viewer_result_element_selection.py": "1c8e1405691cd36926272ebf2463917c6a423c21cae6549fb3030682b1766dca", + "tests/unit/test_viewer_source_projection_chain.py": "8570aea44a3b6f1f44d10507c68813bfd6035576db3c339bb245b78c88629555", + "tests/unit/test_viewer_spatial_sample.py": "4bcda378eb41c3f9e457af1b119b4eaca2a535b4025a635f949dc761eac7a989", + "tests/unit/test_volume_projection_fixture.py": "9488604f53b8612083550cc952d26ea070a7167254ef610b78e6b23679b2bb5c", + "tests/unit/test_wait_for_pypi_release.py": "cabe65c08b8a9d1c5e081f597fe53bbec95c36650a2919a1992d62368096441b", + "tests/unit/test_well_filter_processor.py": "75456737119eaa40ec42b68e967dffd0e99bf28408a1c792963f73b6eb7979e1", + "tests/unit/test_well_throughput_scaling.py": "847021e10de08ad058fe5f9fbbdea8969f71abb87a2eb0907e468f95f7d12ee1", + "tests/unit/test_worker_profiling.py": "f8c103830086034020aabe8582229cf2606d0ccaa1cc212443aca8a4b1600809", + "tests/unit/test_worker_start_policy.py": "a3eaadb10898f10e50391310d65d338d60e9df2f4f6dec8b791be7dc75d31fc9", + "tests/unit/test_yeast_output_identity.py": "e1de14a41cff2cf49dd533da158b96cff7e0cb2139a3ea8b1f3957e6f4af1a1e", + "tests/unit/test_zarr_config_owner.py": "ae63cc5cccbd4276d59db048e3ecc2bc4143992b9f18f7082925518457bde609", + "tests/unit/test_zmq_application.py": "344cb50749a1e737c15078c467c2964a9d27bb8e85ab776588af51edfe937119", + "tests/unit/test_zmq_compilation.py": "a2582fa332c45a4cfbfa1f1b935c0cf87123aa140e5f5289173ac73e289c8b8b", + "tests/unit/test_zmq_compilation_identity.py": "4bc34f8d56e66a4289f4793a424b41297aa170b9654caca5ff5f15a6bdb88262", + "tests/unit/test_zmq_compiled_pipeline_run.py": "a63cc83cb4815b428840ba1b6a6c86ed2831c1204eee23d19726391307fb22cb", + "tests/unit/test_zmq_execution_server.py": "a2854a09486efeda402470a430d284ebb4979273a11e83a68feb5c59f0e6bb54", + "tests/unit/test_zmq_execution_server_process.py": "a3c9a5c03de440b49dd8575879d01514dffa0da32cbbfe15c0d363711685d964", + "tests/unit/test_zmq_orchestrator_environment.py": "ec2e38ee21c1e87af2212184f2275b8c895510dec2c1faf19d49c4c0b1014ce4", + "tests/unit/test_zmq_port_pair_authority.py": "a00dcd470b62193ee7811b39228a4ce3dbfd8e9ee5a198f79f386892233f7cc2", + "tests/unit/test_zmq_progress.py": "66da894d0de1f37f6aa7aa21fe671a5a2b3328685b919932c89f5696cfe05093", + "tests/unit/test_zmq_runtime_outcome_export.py": "038c77fc01fc693149fa3fda72e2caa1f98466c69caf303671474e9c49ba9a20", + "tests/unit/test_zmq_submission_timeout.py": "b525a1cc113bdae987c7f202369cc251ca1129188bd8d3adb834aec44f4c8393", + "tools/reproduce_issue257_filename_identity.py": "43143a3495fe98b43d5e212ad3d6b80a65fa1ed1b4803fab87f693c79306163a", + "validation/MCP-PTY483-SOURCE-CHECKPOINT-20261002.rst": "20b28ff7ff9698a77d71015ff31a5bb357d074583a91dbca61455efc1e27ca23", + "validation/PAIRED-MAIN-FLOW-DIAGNOSIS-20261001.rst": "bab950bfb95b95109081f970f726ba2dcfed6a7379d7279aeb0af5ad2f49331d", + "validation/PUBLIC-PAIRED-388-PREPARATION.rst": "99d458e209090a07641ec1764530f4015d7132dbe822801b56eeec1e20bae6c3", + "validation/canonical-custom-379-evidence.tar.gz": "a6c1f060383e218ece3fcb4580dd59de64967067ee38e50c0051bcde4af62b93", + "validation/canonical-custom-379-pinned-r0-final.json": "c73f7ccc65c0cefc9b109d8818f9bb9ff74df847c37fb4770e26b16e3c46cc25", + "validation/canonical-custom-379-published-head-controls.json": "a8866b87be7922211574ba94847e19e298df1675551cf9211c663cf1814436e5", + "validation/canonical-custom-379-published-head-controls.log": "a84322dc71bc1261493a30646f7164816f18d20f042a3abb01cc1a9a53db49fc", + "validation/cold436-consumer-closure.log": "c217208ef101871c457c808a5f8ae43d8377c77c91caf8d48550370a501ec60e", + "validation/cold436-inventory-closure.log": "84d079e1c458152fa8f527271626d8e0cc82fc7626f5ed567dec51c9c79c77c8", + "validation/cold436-pinned-r0-corrected.log.gz": "d5aacf02d5bce8783706e16886d21431ead961f4a889e503c8f4848e3637e6d9", + "validation/cold436-pinned-r0-first.log.gz": "71f0a2a59e2ea6cdafa73cb968dca44a9d8850362288a132585381667819f3f6", + "validation/cold436-real-compile.log": "ae288b1bfd5b07fca515c0919a2dce9fb865fa3a769dc9228b41e5a231160ed6", + "validation/cold436-source-controls-first.log": "d1e6f693bb95a5b7f0ca7bda2ae6ab44345f9d4d87a235ef1d0d3a0e9f9f1830", + "validation/cold436-source-corrections.log": "a261b9da61f7488c96d049c63106e34a66420600e9d5f69793e8da7ae93a2dc8", + "validation/declared-callable-documentation-461.rst": "bbc2db1be49d157b4d83029ecccd2306938294e8fc72148df925b1b0e6f950d8", + "validation/diagnose_public_paired_main_flow.py": "7fdf1826f5be36c427deb3d96e9168793e430489c268d6bf246e74fb1db5c528", + "validation/doc461-integrated-raw-nra.log.gz": "8e5f75d16e2ff2337e4cc6f829ab8e832945f1ca79e22bda38024bb6275501bb", + "validation/doc461-integrated-raw-nra02.log.gz": "2600bedf023afeea6a0e9b556b0c6ea329f6f7e11ce337fe6c41a6f3d08364d7", + "validation/doc461-owner-after.log.gz": "8fa3ac5073e4d1ae4e03be6c4cdb90323ec1834f9118d2fb733bb48dc4b4c01d", + "validation/doc461-owner-before.log.gz": "4e5d3f2705e541f279839d79cb8252b9157a628a471eca811526eb4640566857", + "validation/doc461-pinned-r0.log.gz": "f1027c6709765fe1a2c46384480c0dbd7550abc02176416b476c46c796e5aaf8", + "validation/doc461-pr-body.md": "ae0145baa4f4a5c5d685f97a043e4f53f90df3750593510d30edc27c1251eb4d", + "validation/doc461-source01.log.gz": "fa2a44ee97f7d3b72bd6391a3d30d334e16b7260e7b01d92bdee378a11e4c7eb", + "validation/doc461-source02.log.gz": "30d8c13921a65187d51e72b83e9eacfb9066161f6c5b830f83a55674d3dfcf72", + "validation/jvm455-lifetime-first.log": "1cb82755f77146a331ad7411ab41410c759558f7c8e38b6929a6c2f95909f37f", + "validation/jvm455-owner-before-corrected.log": "4164c5f4c38d618c82f39f4df1f2289a6e56231a142575b1aba4e379d297af5e", + "validation/jvm455-owner-closure.log": "1fa7f60934f02686679f06fb618c1ed619779786a73bd1dd1b0d2ce12a8dea7d", + "validation/jvm455-pinned-r0-first.log.gz": "0446c3f01995ffcf0f725e1098ec63c45563d0571d389ae9bac82463b8985f50", + "validation/jvm455-resident-first.log": "e8cfe1eaa765e0d04646e713620ff6a4e54eb4773a315fa56256c9abc978caca", + "validation/jvm455-sdkstdio-corrected.log": "96c9bc2080c88108eb6df456a4ab21dca408f780b6c6538a5e64021b84a50ec6", + "validation/jvm455-sdkstdio-exactsource.log": "0cacbb1f87050fa1bf5dca4ecb5b21c83dfd6f460a8bc2868c05e81ea96aca49", + "validation/jvm455-sdkstdio-first.log": "9dc393702998ffcc435b04b47ce8ba692d9d5a23ab1097053aaef72d6de3ef17", + "validation/mcp-pty-owner-after.typescript.gz": "be5cb3674d0a215c4bc63216c64a0b1b799cb8bf27237742ea280110b6183f45", + "validation/mcp-pty-owner-before.typescript.gz": "d4fbb9fd7be36cbac5275470d7b7f94ee867b1a6cf7de2db311ed660f3abb1e0", + "validation/mcp-pty-pinned-r0.typescript.gz": "a59f3202fdc0346174ad755cde5ad45b6cb6191f13dce94a97a2e58c2f39714e", + "validation/mcp-pty-source04.typescript": "7616cf69e817fb0c5a60e3ab82e1f2f72a419e7c04b34912562abb335895c960", + "validation/mcp-pty-source05.typescript": "1386fac4a4837a18fd277924783faf1d065aff1e7a4fc1eeb2cfc322979df06e", + "validation/mcp-pty-source06.typescript": "db57a67878cbc640d9326072c2ef9b3878e7ee879b7a4ced8b8fb8bbe219cc7e", + "validation/mcp-pty483-pr-body.md": "8bdd40cb25f013b1bde26e31e126651f19b93fb865bcbe4c7cf6e551912ef38e", + "validation/mcp_shell_pty_owner_trace.py": "f49d4ab35ffba77ff89d3549b0a69dac666efd9fa66f4824a3230161c0e9ecc7", + "validation/original_377_boundary_witness.py": "ec9ce0dac89679eb922afbfe5ef1aa0c68f85a28d3273a90b634a7801b05f4d6", + "validation/plane-nlm-458.rst": "e9d99efaa9d2001cee59b9b9cd880a4fc5761ae91ac4a987a7763126ff0ec712", + "validation/plane-nlm-issue-body.md": "79c90e4bef185887835bb7fdbb8e82ffc0ad2ceb0f34fc44d099c20dbc7cfdce", + "validation/plane-nlm-owner-closure.log.gz": "1bcb940506f8c3794b4ab950c63b31e439f8466ec70367b4b5888c8dafd3a756", + "validation/plane-nlm-pinned-r0.log.gz": "62efa48e5ec58f3cae262d41ae9a0d154f0020e6d3c1bce7aa73c34695102794", + "validation/plane-nlm-source01.log.gz": "033f426bad294551d1ed5753b837317e6ec0b69cd29cfc8910270fda07cf29e2", + "validation/plane-nlm-source02.log.gz": "bf4abd387a5bc8a49b15cfc49af8b51da1073f69a737176a11f35742098aa88e", + "validation/plane-nlm-source03.log.gz": "4147cb07dd252c2c19645179653d389ec3cb5ce5b07e6570c55f5b636fd17e87", + "validation/public_two_vector_388.py": "d3f259fae72ed5f70117646befa6b68a8301e168d785a7a56159cce1726bfd23", + "validation/r0-fixture-470-artifacts.sha256": "f6797163f02b3cf3ed78ab10e1e00ce0072230cbdfcfabab84e36be5d18d7681", + "validation/r0-fixture-470-evidence.tar.gz": "42be36c171b4e9059011c9da000de027d99f2f81c4084a4f90b046b7d6745ed8", + "validation/r0-invocation-ast.py": "12643290f7c763a7e65baa9317248fc6fae3e7741ea3574d96b45922146c0d43", + "validation/reproduce_saved_label_distance_419.py": "7785f09300db92851bc707b702b4ac2b9addeaf1f2aa42afc57ef9bace299d30", + "validation/run-s1-sampling-source.sh": "61ecabe4da3bbe4670e58c6eb4c2b827ccb14c8aefaf4f700604536fd051a4c9", + "validation/run-s1-sampling-tests.py": "eb25f0b32797eb6acb4a6fed5d43f234260ea3fc918959f6250df500519c730d", + "validation/run_pinned_r0_419.py": "ecb4ae52420f53ad2879a2736abd330eed3f61826cad01539cadd9c686f086c0", + "validation/s1-sampling-evidence.sha256": "28af798b073bde4b4f45d76ee83c2d8e962fcee09a0fe5cdf1a39a4ad606e16f", + "validation/s1-sampling-logs.sha256": "15ca69ebc9c58fd7a9e775b9db735fe7a1e30536fe9172def44789246a6bff83", + "validation/s1-sampling-owner-trace.py": "ddab2dd90c1d32282e15e5950006e0c1f02be209f3f412e5e6e36363aa7127b4", + "validation/s1-sampling-receipt.rst": "a758d781091eb75f15d833c86f5202457410b0fdefe2c6ae701cf8361ed14d23", + "validation/s1-sampling-source-evidence-20261002.tar.gz": "bf42c8b7a6d081e8e0d666b5f03e2ca2c9f3f61e39bcba681bcc2238c4bdc455", + "validation/stream441-first-source-controls.log": "597ea021a676c7e8186473b801c9914701a64f5e8c3dff98ee57f057e4f3b8a9", + "validation/stream441-fourth-source-controls.log": "b585023aeebab417f208abfca318f68e7bd27ecaad0487b91b0ec49b288e2abe", + "validation/stream441-newcase-controls.log": "32b9bcabe6483404085ed301e6300ca890c8aa1747c9978186d5bd44aa19f338", + "validation/stream441-original-controls.log": "876071ddcc1f933d4e27ac6d6ba3385389921abbac21d13b4c83eacc9842a4d4", + "validation/stream441-pinned-r0-corrected.log.gz": "20900bb6f32fa3a177f5b51979ba796e5bef30664686b90d6bc3b019e48cf1f9", + "validation/stream441-pinned-r0.log.gz": "c96accf6b7630769f9e1d2b4e9743b06454097dd515e0819b6d204bd9cf0bd06", + "validation/stream441-pr-body.md": "5f78b59407c62780c35a23a0824a758d4fa90d62316516e16c08df348e36f932", + "validation/stream441-qualified-source-controls.log": "0b548cef61c56f6c5a2a71093a2fec4626a8c5d9a1d019ea3df2204cf51ee50a", + "validation/stream441-second-source-controls.log": "432be31353bae57dabdede4b50c747bfcb66ce38fa88a2ac5a28390a70ccd86e", + "validation/stream441-terminal-controls.log": "513222a264ddd1a58f389dd8d095f1729c1e55c6c886cb84f459b360efcbc798", + "validation/stream441-third-source-controls.log": "aa24d25eed6859c288eadfdeeeab3b30810f08389bcbd128a41aaaffbc0fe001", + "validation/test_public_two_vector_driver_388.py": "3c7e3fc895ab1f169919a3687729d219f48811372c56d350e4655250706c9d12" + }, + "sparse": { + "missing_tracked_files": { + "docs/validation/ack_runtime_parent_20260930/checkpoint.rst": "bac28565a9c604286a1224b584376d4e8d01af6d", + "docs/validation/ack_runtime_parent_20260930/mcp-paired-session.log": "037a2249c1e3ba1b31d0190d07d47481b1d80a21", + "docs/validation/ack_runtime_parent_20260930/paired-source-final.log": "51e73ab105db89df4852a9bef46c16e0ab867f06", + "docs/validation/ack_runtime_parent_20260930/pipeline.py": "2128b9a1093b72b5af85547444d894aabadd41f6", + "docs/validation/ack_runtime_parent_20260930/pr-body.rst": "e03b5203490a348a725ee4aae05c7d1b7c3c2fc7", + "docs/validation/ack_runtime_parent_20260930/run-candidate.sh": "d17fc704fe384e33b9a9752f85dd019eb462d36c", + "docs/validation/ack_runtime_parent_20260930/run-source-check.sh": "a0eba8c3c19ba9575d5497f91d87a180ac67b5f7", + "docs/validation/ack_runtime_parent_20260930/viewer-followup.rst": "19d9c3136cc7466f77ac3aaa9bf121de52d71fc0", + "docs/validation/artifact_fed_parameter_declaration_contract_20261001/ISSUE.md": "777e290f08e6ef8062d2ee50a99bfa80fac08671", + "docs/validation/artifact_fed_parameter_declaration_contract_20261001/PR_BODY.md": "0d717c0157192b1192b228e87679ed3e82cb1c47", + "docs/validation/artifact_fed_parameter_declaration_contract_20261001/RECEIPT.rst": "8c0e139813c44d970a436dd4927d58e735a0fbfb", + "docs/validation/artifact_fed_parameter_declaration_contract_20261001/SHA256SUMS": "3e0cbf0d8d46cfe13e88e9ed628e8e61d6b1b3ee", + "docs/validation/artifact_fed_parameter_declaration_contract_20261001/contract-pattern-shard-resources.txt": "a2ccf235d6fc9db22c8823ac4ccfd7741535c4a7", + "docs/validation/artifact_fed_parameter_declaration_contract_20261001/contract-pattern-shard.xml": "4f97ce6b4117a00d1db716de0cb16b6039a2f2c5", + "docs/validation/artifact_fed_parameter_declaration_contract_20261001/normalization-green-resources.txt": "41cfbbe5893eb1ec417dc2aa627b0408b591ada4", + "docs/validation/artifact_fed_parameter_declaration_contract_20261001/normalization-green.xml": "0a41076760412395c5b8554d3af25813f73d0a0b", + "docs/validation/artifact_fed_parameter_declaration_contract_20261001/original-red-resources.txt": "d6162fdf26f32db3ddf8d29e14814d60d12ae0eb", + "docs/validation/artifact_fed_parameter_declaration_contract_20261001/original-red.xml": "134bab6b6a2f87a5e65177364208f4094c273cc2", + "docs/validation/artifact_publication_315_20260930/baseline-import.log": "e676c882e0fc232337c3687c48733dcd2636d957", + "docs/validation/artifact_publication_315_20260930/baseline-journey.log": "4eb316bb099a23eeaa6ca0c535fc73f955b6d45b", + "docs/validation/artifact_publication_315_20260930/baseline-journey02.log": "82e2c84d5282a9a6541767c0c4e7cd8cc3615259", + "docs/validation/artifact_publication_315_20260930/baseline-journey03.log": "8a66c38c8a742b036cdbc08cc542c3f3fd6ae9d3", + "docs/validation/artifact_publication_315_20260930/baseline-journey04.log": "d239d145d5b338de7015c5e623d987f6f86dc57f", + "docs/validation/artifact_publication_315_20260930/baseline-journey05.log": "608babc22f0958f50ade7ad2ea9ed9caff02bbde", + "docs/validation/artifact_publication_315_20260930/baseline-journey06.log": "255ba5fc2389ccf938d81af34f761cab8c13c11d", + "docs/validation/artifact_publication_315_20260930/candidate-journey01.log": "d19cb7cd08ccc7487f59e963a962c7a34c023fb3", + "docs/validation/artifact_publication_315_20260930/factored-journey.log": "114cee3150450fee197713ec080311151fee7cc3", + "docs/validation/artifact_publication_315_20260930/factored-journey02.log": "ea900336f138dcf067908eb1def6706ac457bcf6", + "docs/validation/artifact_publication_315_20260930/factored-owners.log": "ecd6d8a18eea06fdab7cbe7a3d627d5977691dc4", + "docs/validation/artifact_publication_315_20260930/geometry-final.log": "eab547cbd1fcf0cef149c8ef69d44cfa1027df79", + "docs/validation/artifact_publication_315_20260930/grid-triage.md": "b6b1c8639c8653dbfba3d8ed74eda6cd32209419", + "docs/validation/artifact_publication_315_20260930/merged-main-source.log": "6c5cd1f01778b8e5399394a689e76e2a1616bd20", + "docs/validation/artifact_publication_315_20260930/named-checkpoint-ownership.md": "ac44ad2931765a807c464dd460365bf50122431d", + "docs/validation/artifact_publication_315_20260930/original-native-failure-artifacts.tgz": "60e3ee7e4e19b5bc22d3802be1da44b2fa5b8f66", + "docs/validation/artifact_publication_315_20260930/original-public-journeys.log": "b7c24cf7c00d11b50fe1f4b8db452e3b1c33f354", + "docs/validation/artifact_publication_315_20260930/original-r1-bounded.log": "a4be9a30b4cc2ebfef36aba0dd9530986b15f3e3", + "docs/validation/artifact_publication_315_20260930/original-r1.log": "27821a68023dcfed8bd3adaaae012c4b1f49d331", + "docs/validation/artifact_publication_315_20260930/original-ratchet-benchmark-resources.txt": "80a404400aede62ed3c0307ed0e75483c59b6989", + "docs/validation/artifact_publication_315_20260930/original-ratchet-benchmark.json.gz": "045dd9c8185888dca3f359f9ad6682afcd591293", + "docs/validation/artifact_publication_315_20260930/original-ratchet-final-resources.txt": "b049cb85a7c83813b6ea98200373c3b113b8a216", + "docs/validation/artifact_publication_315_20260930/original-ratchet-final.json.gz": "8fed95cc2f07c7a29c66c8d316830f51972514de", + "docs/validation/artifact_publication_315_20260930/original-ratchet-initial-resources.txt": "28f6bfff14941899772983cafdf6d501561ecf2d", + "docs/validation/artifact_publication_315_20260930/original-ratchet-initial.json.gz": "43090773bba24ec63f568fc7b239d436dafedf6b", + "docs/validation/artifact_publication_315_20260930/original-ratchet-scripts-resources.txt": "c76998894c25f5617bf07c0216dac440c75ee602", + "docs/validation/artifact_publication_315_20260930/original-ratchet-scripts.json.gz": "bcd3423dba525ce4cb81aed7cec7c77f9d2794c0", + "docs/validation/artifact_publication_315_20260930/owner-controls.log": "0c2947406361a2604914d7042e1692ecdafe9bb6", + "docs/validation/artifact_publication_315_20260930/ownership.md": "df51bb557ddaacc0f418bce321b9fb0f2e53c2c7", + "docs/validation/artifact_publication_315_20260930/parent-installed-checkpoint.rst": "5c4fdcbf44cbffc36ce98cd53cb2a71565fdef9f", + "docs/validation/artifact_publication_315_20260930/pr-body.md": "8cb3b957f0bb6badbec20fc2e626b81c9b2ffb75", + "docs/validation/artifact_publication_315_20260930/publication-final.log": "cc9c058e52ca1ad4abad48a90e297d0447cdab56", + "docs/validation/artifact_publication_315_20260930/qualify-original.py": "cfd5b6f9f7d1b19da4e917c92c5bc2a5a551e1ff", + "docs/validation/artifact_publication_315_20260930/results.md": "91eed4df23880d686950ce5ca816d84e6f8db987", + "docs/validation/artifact_publication_315_20260930/run-bounded-r1.py": "06d2cf9a8b94bb8467e4004b996114ea30dcf5ba", + "docs/validation/artifact_publication_315_20260930/run-source.sh": "9a4a8ad48205e4bfe3ab184d31168360080ae696", + "docs/validation/artifact_publication_315_20260930/runtime-controls.log": "8097b63472af6dbfb532720da52f5a377ae63451", + "docs/validation/basicpy_parent_numeric_20260930/check-persisted-live.py": "0b55cc7f9ed8e91ba798cf606bd030337f9b34f2", + "docs/validation/basicpy_parent_numeric_20260930/check-publication-fixed.py": "78216d99b96dfde98380f78edf63c842ebc1320c", + "docs/validation/basicpy_parent_numeric_20260930/checkpoint.rst": "bddff5121dc4b75fce975022afa0063c49b97390", + "docs/validation/basicpy_parent_numeric_20260930/cpu-installed-checkpoint.rst": "88eb43cfb0245b7cf851f62b5f8090452ba73839", + "docs/validation/basicpy_parent_numeric_20260930/installed-failure-receipt.rst": "4738f20b6a1087eed1029ca61d5bb8e08aa9970e", + "docs/validation/basicpy_parent_numeric_20260930/main-integration-20261002.rst": "18ec59c4a1bdfb12cfa7da6f43e36d4bb727876c", + "docs/validation/basicpy_parent_numeric_20260930/owner-closure.rst": "fef702e2accf4bd432a87aa071770630dd5f625b", + "docs/validation/basicpy_parent_numeric_20260930/pipeline-live-wheel.py": "aef9eb3e421bec1128f1156e42131d92c9903201", + "docs/validation/basicpy_parent_numeric_20260930/pipeline-publication-fixed.py": "6af69ac835b67cb9d4af418e00f591fe2c9e1f23", + "docs/validation/basicpy_parent_numeric_20260930/project-dependency.rst": "716c2a8ebd5251054bd66001ccd47aef5466097b", + "docs/validation/basicpy_parent_numeric_20260930/publication-fixed-installed.rst": "13ced7e71eaaaf8b8a3041f2465fd22805c200aa", + "docs/validation/basicpy_parent_numeric_20260930/run-live-wheel.sh": "40721956416b1b92a0e560c0bbb79225caad8920", + "docs/validation/basicpy_parent_numeric_20260930/run-owner-check.sh": "0325194e30ef8bbb11cf7c21530b92eb5f3ba795", + "docs/validation/basicpy_parent_numeric_20260930/run-publication-fixed.sh": "f23e572900aff71dcc3e3916bbbeffa763d92437", + "docs/validation/basicpy_parent_numeric_20260930/run-source-check.sh": "0a39bc8977dcea1da21090d331b7319f1ec3c6f9", + "docs/validation/basicpy_parent_numeric_20260930/target-owner-installed.rst": "4212e100894f6a6d211b830171e0f58a7d54df18", + "docs/validation/bioformats-saved-calibration-440-source-20261002.tar.gz": "a66b8b734c464dfc6fe463e1176af4d12030cf80", + "docs/validation/bioformats-saved-calibration-440.rst": "378da61b8fd856673ff7231807e2e7fe10af7956", + "docs/validation/catalog-endpoint-incarnation-464-20261002/INSTALLED-ACCEPTANCE.rst": "3fb5b1dbbd5d12240ee9e5058447de16fccf6e41", + "docs/validation/catalog-endpoint-incarnation-464-20261002/RECEIPT.rst": "4bb816103a5a069e44cb4070a7e9450d81129146", + "docs/validation/catalog-endpoint-incarnation-464-20261002/owner-after.log.gz": "ec2f4c4dd7cb660a0c9f60a1a96362d330bfdd51", + "docs/validation/catalog-endpoint-incarnation-464-20261002/owner-before.log.gz": "4e3dcb76c3745992f53db342fa955cb67b4eb70b", + "docs/validation/catalog-endpoint-incarnation-464-20261002/pinned-r0-corrected.log.gz": "bf14c1f3a39217502ff625c1d4c6a125b093dbe1", + "docs/validation/catalog-endpoint-incarnation-464-20261002/pinned-r0-final.log.gz": "21148eb8b4f0b30cdd8ac765b373e4533518216e", + "docs/validation/catalog-endpoint-incarnation-464-20261002/pinned-r0-first.log.gz": "dece41177331469ff2bf5e07872fc1fb3c27e83f", + "docs/validation/catalog-endpoint-incarnation-464-20261002/raw-nra.log.gz": "81a74a9bd0db4e9ee6d6440f6a4939f5fc2e7ae1", + "docs/validation/catalog-endpoint-incarnation-464-20261002/source01.log.gz": "b7837059e7262d4449ce2175d96d324a0cb7492d", + "docs/validation/catalog-endpoint-incarnation-464-20261002/source02.log.gz": "2936f957182e42b20c5d5d59561cd7b6c7ead43e", + "docs/validation/catalog-endpoint-incarnation-464-20261002/source03.log.gz": "60db371ecbef789c9f4686a5473d7713a01269e0", + "docs/validation/catalog-endpoint-incarnation-464-20261002/source04.log.gz": "2f28606d55099a478be3bbdcd081a2d0d5b36a8b", + "docs/validation/catalog-endpoint-incarnation-464-20261002/source05.log.gz": "808c42cdb33b032ad4b05f03e24e39f5d3d6d6ed", + "docs/validation/catalog-endpoint-incarnation-464-20261002/source06.log.gz": "d4fc21ec89a1f750d622128c74cb4fe1dfcb5b11", + "docs/validation/catalog-endpoint-incarnation-464-20261002/source07.log.gz": "0b09b51aa1681d7dde961e31e491a351e9daadb0", + "docs/validation/catalog-endpoint-incarnation-464-20261002/source08.log.gz": "fb4737e951f27615ba28b9f2b69803a690c04308", + "docs/validation/channel-contrast-review-20261001.rst": "7fa19afe6e3e85c2a117cf925f03d15f898055be", + "docs/validation/check-bioformats-calibration-440.py": "06cab96f57762d547ce7fb7d17f1e3fdb9167118", + "docs/validation/check-function-help-390.py": "7dd02898c70c6890e7dd1819e7c5698fe0c6c700", + "docs/validation/child-measurement-producer-selection-492-495-20261002/QUALIFICATION.rst": "a673ca917914a2b21be50231eac2f83a0c2970f8", + "docs/validation/child-measurement-producer-selection-492-495-20261002/controls.log": "eca4f8fde67da1bbde2bb29af20b6c619584cc0c", + "docs/validation/child-measurement-producer-selection-492-495-20261002/integrated-controls.log": "ea0477ace4a0eabd39c97007a347cd94ad2a796a", + "docs/validation/child-measurement-producer-selection-492-495-20261002/original-r0.json.gz": "418e849c95202c6c4921772d23f830a020736a48", + "docs/validation/child-measurement-producer-selection-492-495-20261002/original-r1.log": "86814c023357b5d19384cda2b20a33ca2b3c5472", + "docs/validation/child-measurement-producer-selection-492-495-20261002/qualification.json": "3983c8190fa404bcafce2b98eff512dc9ebcdd8e", + "docs/validation/child-measurement-producer-selection-492-495-20261002/strict-native-receipt.json.gz": "a793649eb304fdefd2b5a12d20123d14c9cf5593", + "docs/validation/colocalization-metric-selection-487-20261002/cache-window-counterevidence.json": "97adf6ad8b6362baeecaaae047bdefacb230772d", + "docs/validation/colocalization-metric-selection-487-20261002/common-saved-output-comparison.json": "fbbde3a3c9ed00fd825f5c778e2797e5c1bd2133", + "docs/validation/colocalization-metric-selection-487-20261002/manifest.json": "739fc4d0013e33867d74640587e359c7a163e413", + "docs/validation/colocalization-metric-selection-487-20261002/qualified-controls.json": "3fa8db91b9e23538f4e8d49f8bd93f45f0d7f1d4", + "docs/validation/colocalization-metric-selection-487-20261002/strict-native-full.json.gz": "531b7e9fb574f09a03c8d3dd08e0f85607acb343", + "docs/validation/colocalization-metric-selection-487-20261002/strict-native-summary.json": "14a0803bc13236f9d99f48fe01ad60a4d1ba38d7", + "docs/validation/compiled_metadata_artifact_binding_368_20261001/PR_BODY.md": "bb24ee18bd9f3565ef8c3a9dd1e07bd5a6bdac38", + "docs/validation/compiled_metadata_artifact_binding_368_20261001/RECEIPT.rst": "6b3a647f6c0fb403650b3ff3ee5ed6c4b076d2b6", + "docs/validation/compiled_metadata_artifact_binding_368_20261001/SHA256SUMS": "4ff1dcd41236bb1e9651a1518b12e732847f7a79", + "docs/validation/compiled_metadata_artifact_binding_368_20261001/SOURCE_FREEZE.rst": "f45bb5da1b71de242f57d418dad5b0ac0524344f", + "docs/validation/compiled_metadata_artifact_binding_368_20261001/baseline-legacy-shard-resources.txt": "85326f9e222c911abfbc72f05a14dfcf9b782af3", + "docs/validation/compiled_metadata_artifact_binding_368_20261001/baseline-legacy-shard.xml": "b84a8826e6566e202fb9ab5e4cd9b5952f09f1a4", + "docs/validation/compiled_metadata_artifact_binding_368_20261001/capture_r0.py": "e81ba48b6bce7b9785f03efd92a55cf9fbc76097", + "docs/validation/compiled_metadata_artifact_binding_368_20261001/collection-boundary.xml": "0a7097ded86de783a5030f307e524697d53e2e94", + "docs/validation/compiled_metadata_artifact_binding_368_20261001/final-planner-shard-resources.txt": "e953ac87e99d08216cf0ef8546438a094306d6e3", + "docs/validation/compiled_metadata_artifact_binding_368_20261001/final-planner-shard.xml": "36c92ba1d946f7cf42baaf60f8e5e98d6eeabd03", + "docs/validation/compiled_metadata_artifact_binding_368_20261001/metadata-controls-binding-assertion-failure-resources.txt": "61d1d800c44cb593ccde6c3ffe232b74a984fc3b", + "docs/validation/compiled_metadata_artifact_binding_368_20261001/metadata-controls-binding-assertion-failure.xml": "0a9dd8897875185a47ce754916c3e7e8a91f626f", + "docs/validation/compiled_metadata_artifact_binding_368_20261001/metadata-controls-fixture-failure-resources.txt": "0e2ea41c3d8aac49e1ca8e6d78d498aa883310c4", + "docs/validation/compiled_metadata_artifact_binding_368_20261001/metadata-controls-fixture-failure.xml": "f5c1de56cc961ce257e2f01e363b6d66196f4bc8", + "docs/validation/compiled_metadata_artifact_binding_368_20261001/metadata-controls-resources.txt": "21d7651a39f8668c5a2afda642ad1d6645d34e75", + "docs/validation/compiled_metadata_artifact_binding_368_20261001/metadata-controls.xml": "3d62995beb8bdc92827323628aa1aabd51a41d65", + "docs/validation/compiled_metadata_artifact_binding_368_20261001/mro-planner-shard-resources.txt": "cdd2fc230e138e34fc3d5ba86a5521b4d0370cf7", + "docs/validation/compiled_metadata_artifact_binding_368_20261001/mro-planner-shard.xml": "1967e47ce45f125dbff9d3bb4c413d8ac33d5a5e", + "docs/validation/compiled_metadata_artifact_binding_368_20261001/original-green-resources.txt": "5e22781772b9f196bd1d52ee2e5d3ebe275997c6", + "docs/validation/compiled_metadata_artifact_binding_368_20261001/original-green.xml": "5d9460248817e732478ca39343d7b1e5282a4201", + "docs/validation/compiled_metadata_artifact_binding_368_20261001/original-red-resources.txt": "10686d13a82bb77279562a6632687d5962fd01ad", + "docs/validation/compiled_metadata_artifact_binding_368_20261001/original-red.xml": "58d6f60351c938d4b10fd97cdc90fdd79131d346", + "docs/validation/compiled_metadata_artifact_binding_368_20261001/pattern-runtime-shard-resources.txt": "793c9aa1e537e825a45156e767124032964ed8f1", + "docs/validation/compiled_metadata_artifact_binding_368_20261001/pattern-runtime-shard.xml": "d54ea2305ee8982c2ad27d8e31100a02638ebf65", + "docs/validation/compiled_metadata_artifact_binding_368_20261001/planner-shard-resources.txt": "8aafaee09216b33410b72d97e1421a0c22f648f6", + "docs/validation/compiled_metadata_artifact_binding_368_20261001/planner-shard.xml": "484b3c91eb1f7015154f346f1edb444f36aa6175", + "docs/validation/compiled_metadata_artifact_binding_368_20261001/r0-first-resources.txt": "4c5fda7568bf50a58275aa791f1b95e6f9b7f8f2", + "docs/validation/compiled_metadata_artifact_binding_368_20261001/r0-first.json": "bbfcbe75a91ba7a5051938109ce29bf054e793e9", + "docs/validation/compiled_metadata_artifact_binding_368_20261001/r0-first.stderr.txt": "e69de29bb2d1d6434b8b29ae775ad8c2e48c5391", + "docs/validation/compiled_metadata_artifact_binding_368_20261001/r0-qualified-resources.txt": "957ca3f00b5360afe8e18474ddfb0d47020ae606", + "docs/validation/compiled_metadata_artifact_binding_368_20261001/r0-qualified.json": "b13e3362854657ede1663642198fc1f62145ab1f", + "docs/validation/compiled_metadata_artifact_binding_368_20261001/r0-qualified.stderr.txt": "e69de29bb2d1d6434b8b29ae775ad8c2e48c5391", + "docs/validation/compiled_metadata_artifact_binding_368_20261001/runtime-origin-shard-resources.txt": "9862f3ee51329b251b6c59a90e284614b2ad2d3e", + "docs/validation/compiled_metadata_artifact_binding_368_20261001/runtime-origin-shard.xml": "cc480c8324cb43d79d5f16714be2acb2123faa97", + "docs/validation/compiled_metadata_artifact_binding_368_20261001/source-edge-shard-resources.txt": "c0ee86360818fb0976ab80894c450a4749634bfe", + "docs/validation/compiled_metadata_artifact_binding_368_20261001/source-edge-shard.xml": "dcebc49c29846dff11a726b5bfb3e81438e68a59", + "docs/validation/compiled_metadata_artifact_binding_368_20261001/source_shard.py": "fc67a0334941c76a891a69354c9642d47209bed1", + "docs/validation/context_bounding_20260929.md": "d27dcd7cb8058b3657cc7f0815776ff2cf7db9ee", + "docs/validation/context_bounding_20260929/build-resources.txt": "957dfbf3c284c25497958b41ffbc36076860efe5", + "docs/validation/context_bounding_20260929/build.txt": "de2310ce4f4d34e0ac31335dc0e5bfdc7f4b8aec", + "docs/validation/context_bounding_20260929/pytest-checkpoint-resources.txt": "05fbbe923487fa57fef71ab3e95d6dcd406b92c7", + "docs/validation/context_bounding_20260929/pytest-resources.txt": "3d0e4e46451a43378c98a938e73c51e79497d218", + "docs/validation/context_bounding_20260929/pytest.txt": "3d6abc28e0b833f2b34eecadd18f0efde86805c8", + "docs/validation/context_bounding_20260929/pytest_checkpoint.txt": "060cf9be02a964bea8bea524aa54fea050d14da9", + "docs/validation/context_bounding_20260929/source-projection.json": "44649a6c37a4596b9de401bb2b635b2db7260d83", + "docs/validation/cpa-secondary-source-metadata-444.rst": "46a42dd5477bec0933b9a20e3dbf814418fa79ca", + "docs/validation/cpa-workspace-export-main-480-20261002.json": "dec7f9cf3a67d60a59bf875fdaf19584155b0a32", + "docs/validation/custom-plate-admission-500.rst": "37185a89ab3f535a1cdd4609e2145f96a22ed9f2", + "docs/validation/custom_plate_admission_journey.py": "272c1551f5d70ec3e750067d13f60690fd3d55e3", + "docs/validation/declaration-selected-376.rst": "96fa283dbe971274f5777c6e6397cffffadb28b2", + "docs/validation/diagnose-knowledge-376.py": "653aeb25fb85e002c8cefa6e7743a8c05560647b", + "docs/validation/diagnose-selected-discovery-release-022.py": "c5436844e7ec9903d388b50bf36be346e3f4001f", + "docs/validation/duplicate_editable_metadata_20260930/README.md": "e88df7224d197e1a7e70436b2868bf071b661c17", + "docs/validation/duplicate_editable_metadata_20260930/accept_shared_main.py": "94cc198e13382b85fc7115785c278737cd112795", + "docs/validation/duplicate_editable_metadata_20260930/after.json": "5bc0a8239d9118e06d7e7f5209c4ade3099c1c05", + "docs/validation/duplicate_editable_metadata_20260930/before.json": "25ef5367c5a022ea330de381ba292ae21c84a522", + "docs/validation/duplicate_editable_metadata_20260930/install-retry.log": "323fe4331d58c89c0958b63f6559c03769c80451", + "docs/validation/duplicate_editable_metadata_20260930/install.log": "13cd7a2f6597b0bb2ced9e0862befd6e8939abdf", + "docs/validation/duplicate_editable_metadata_20260930/perf-runtime-projection-shared-main-acceptance-20260930.json": "b57c9dd26d033b5c4114da3abcad113ce1e5aa93", + "docs/validation/duplicate_editable_metadata_20260930/perf-runtime-projection-shared-main-clean-acceptance-20260930.json": "36e0757f6d6adc2c25cd238b13099054db5b1b71", + "docs/validation/duplicate_editable_metadata_20260930/pip-check-after.log": "c688d8ccdad82420475fc31cb40020cccfeeef2b", + "docs/validation/duplicate_editable_metadata_20260930/pip-check-before.log": "28c49ae3de561e41fb102673ff43b61cdb8e8cbf", + "docs/validation/duplicate_editable_metadata_20260930/quarantine.json": "6135d8819601e6963df1e276b419e41bd9461dcd", + "docs/validation/duplicate_editable_metadata_20260930/uninstall.log": "65719ff57aad445cbbc51fb441227ef730189f42", + "docs/validation/faint-structure-viewer-qa-396-20261001.rst": "b0af38756a7f69b54808c0296012c2e561d2a931", + "docs/validation/faint-structure-viewer-qa-396-20261001.tar.gz": "810974b950f5ac395588435261f7b4bc0c1bba7a", + "docs/validation/function-declaration-help-390.rst": "8b77b1fdbebc87fdcabfd588cc40d5663b2e1cf1", + "docs/validation/function-help390-source-20261001.tar.gz": "6bcf831b76cb77e0ac98a56215f3cfdb3ee0cdf4", + "docs/validation/function-help391-registered-source-20261001.tar.gz": "e34ad9b8ce643b29daafd723a23db94c34ca78b6", + "docs/validation/generic_runtime_owners_323_20260930/README.md": "f20b4a29281e83affd55f4e643271b4933633408", + "docs/validation/generic_runtime_owners_323_20260930/SHA256SUMS": "1f4b7d68b451d696a6f7ee952ff38499da8df886", + "docs/validation/generic_runtime_owners_323_20260930/apply_generic_measurement_runtime_owners_20260930.py.txt": "6b8dc7400785769e787711fc49a4a6ce7d1c10cc", + "docs/validation/generic_runtime_owners_323_20260930/census_refill_preparation_20260930.py.txt": "bb17e3da346a0148bf167a55928e1382f98b0da2", + "docs/validation/generic_runtime_owners_323_20260930/check_runtime_owner_fresh_native_facts_20261001.py.txt": "a8302873ef0d4582bc2e41dd759181b06f7851cc", + "docs/validation/generic_runtime_owners_323_20260930/check_runtime_owner_fresh_native_tables_20261001.py.txt": "0d6052e84cc7d1a45393ae476eeb9b37c512885b", + "docs/validation/generic_runtime_owners_323_20260930/closure-global-gc-sitecustomize.py.txt": "57f090330a744cda34da349f04e8ccab1e602bf8", + "docs/validation/generic_runtime_owners_323_20260930/cpu-timeline-candidate-20261001.jsonl.gz": "2d027c1308c2e6cdb593f44e600e6ceb08229bf8", + "docs/validation/generic_runtime_owners_323_20260930/cpu-timeline-main-20261001.jsonl.gz": "7c4d316607269196741f9b0707fd6169e7630be3", + "docs/validation/generic_runtime_owners_323_20260930/cpu-timeline-sitecustomize.py.txt": "1ef8f01a3b330e373af24ad8fe3c74ac69dcd9f9", + "docs/validation/generic_runtime_owners_323_20260930/fresh-native-imaging-provenance.json.gz": "4f05d9295205a014117c23f23dc9a3e45e192e14", + "docs/validation/generic_runtime_owners_323_20260930/fresh-native-imaging-request_0.json.gz": "9a8fc8c8c74239a56cfc5df6fb34583b8fdf0d27", + "docs/validation/generic_runtime_owners_323_20260930/fresh-native-imaging-summary.json.gz": "4117e415eccb3bb227c61c44dab7efc84624b488", + "docs/validation/generic_runtime_owners_323_20260930/global-gc-candidate-intervals-20260930.jsonl.gz": "22db29316b83a06d6d466d1cb48cae92d9d1146c", + "docs/validation/generic_runtime_owners_323_20260930/global-gc-closure-candidate-a-20261001.jsonl.gz": "3c159ac630410f5a8125ce042e9930770d31f704", + "docs/validation/generic_runtime_owners_323_20260930/global-gc-closure-candidate-b-20261001.jsonl.gz": "d85911397036582b207ac80bffe9569619ddb179", + "docs/validation/generic_runtime_owners_323_20260930/global-gc-closure-main-a-20261001.jsonl.gz": "2ab2c982e23def246f2dd86478d2a28b8900419b", + "docs/validation/generic_runtime_owners_323_20260930/global-gc-closure-main-b-20261001.jsonl.gz": "600e0d160157315d321d2f4369940a7766ea1c49", + "docs/validation/generic_runtime_owners_323_20260930/global-gc-diagnostic-sitecustomize.py.txt": "a9a09411fdcbec627d942ef2b5afd4ffc39c7315", + "docs/validation/generic_runtime_owners_323_20260930/global-gc-main-intervals-20260930.jsonl.gz": "38e2685d67a5f943c9136c9eefdd99b67d60744b", + "docs/validation/generic_runtime_owners_323_20260930/kernel-preparation-ownership.json": "dd9d70dea20136283e59358d2fff724baba33450", + "docs/validation/generic_runtime_owners_323_20260930/make_runtime_owner_cpu_timeline_20261001.py.txt": "572cab4beab3e7bd3fd5260bd9a34ae724157312", + "docs/validation/generic_runtime_owners_323_20260930/measurement-cache-and-column-ownership.json": "345cc05b9f1f04c0e8b5342a7dd6494e44904361", + "docs/validation/generic_runtime_owners_323_20260930/move_bound_runtime_profiler_20261001.py.txt": "847be28e27fc2e4cac12bf464a44a2031e156b7c", + "docs/validation/generic_runtime_owners_323_20260930/move_generic_numba_preparation_owner_20260930.py.txt": "27d56d7639dd68537b1d5c430888343468545a06", + "docs/validation/generic_runtime_owners_323_20260930/move_numerical_cache_mechanics_20261001.py.txt": "3984204934d1c698f9277ed9a86c68759a3f12cb", + "docs/validation/generic_runtime_owners_323_20260930/nra-r1.log": "154b8ac1dbc761d7ef1865b5b70a33a7564df9b5", + "docs/validation/generic_runtime_owners_323_20260930/perf-bound-runtime-profiler-plan-20261001.log.gz": "38bae12efbe845f3adc1bb93228939627b1e2374", + "docs/validation/generic_runtime_owners_323_20260930/perf-bound-runtime-profiler-simulation-20261001.json.gz": "79682639751339da47552fd69b823b99c9f8ba58", + "docs/validation/generic_runtime_owners_323_20260930/perf-bound-runtime-profiler-transaction-20261001.diff.gz": "3c60b38126383fa93e9747f2464e51382d72fb7c", + "docs/validation/generic_runtime_owners_323_20260930/perf-columnar-export-frontier-probe-20260930.json": "2930f7d6998565dc8c7d212ee35282b2c8caa737", + "docs/validation/generic_runtime_owners_323_20260930/perf-generic-measurement-runtime-all-consumers-20260930.xml.gz": "00e53d117eb0f626c9bf647195087de85a10c8e6", + "docs/validation/generic_runtime_owners_323_20260930/perf-generic-measurement-runtime-before-census-20260930.json.gz": "d870c00d102886fba7441eff8b95d67cb47f8024", + "docs/validation/generic_runtime_owners_323_20260930/perf-generic-measurement-runtime-focused-20260930.xml.gz": "796dc98b1307483d728b80803a4602ba5d5b5136", + "docs/validation/generic_runtime_owners_323_20260930/perf-generic-measurement-runtime-nra-transaction-20260930.diff": "8ed87673dfb02c39631074c0b57c4b8cd65440f9", + "docs/validation/generic_runtime_owners_323_20260930/perf-generic-measurement-runtime-public-comparison-20260930.json": "83f45404599d541da814252787b8fb4e9f754eda", + "docs/validation/generic_runtime_owners_323_20260930/perf-generic-measurement-runtime-public-observations-20260930.json": "eb71be869df69a3f8375cfb664ba99b4fd10373e", + "docs/validation/generic_runtime_owners_323_20260930/perf-generic-measurement-runtime-refinement-20260930.diff": "a3ef7ebd30854f0d2d7cd17641bc1e12c77bffdc", + "docs/validation/generic_runtime_owners_323_20260930/perf-generic-measurement-runtime-unchanged-main-materialization-20260930.xml.gz": "9827bbcb3ad3bfc115e205b734f30049daee35b4", + "docs/validation/generic_runtime_owners_323_20260930/perf-generic-numba-owner-application-20260930.log": "e5862874dc1f96e2c6a5067a8256d1e851de9cec", + "docs/validation/generic_runtime_owners_323_20260930/perf-generic-numba-owner-application-corrected-20260930.log": "05cfe3c61f44d06e3b330a500de7b46ca62ffa93", + "docs/validation/generic_runtime_owners_323_20260930/perf-generic-numba-owner-complete-simulation-20260930.json.gz": "89479339c6a818e228be9bb2bf40e12f0dd72aa2", + "docs/validation/generic_runtime_owners_323_20260930/perf-generic-numba-owner-consumer-test-20260930.diff": "acdfe30b7d1f59bef69c0fd67199b11e5f2a550c", + "docs/validation/generic_runtime_owners_323_20260930/perf-generic-numba-owner-initial-simulation-20260930.json.gz": "8b144a6dc9102dab2bb04e88a8a52873f674c31d", + "docs/validation/generic_runtime_owners_323_20260930/perf-generic-numba-owner-transaction-20260930.diff": "2de1761043fb1ed70a306f1c6b64f9deea315821", + "docs/validation/generic_runtime_owners_323_20260930/perf-generic-runtime-cache-lifetime-refinement-20260930.diff": "0fda6cc93f6ca7c5c58f38a4ae8c956d55f65a47", + "docs/validation/generic_runtime_owners_323_20260930/perf-generic-runtime-global-gc-diagnostic-observations-20260930.json.gz": "44b43d9c0c98433eaf78f800169616ece7d38d75", + "docs/validation/generic_runtime_owners_323_20260930/perf-generic-runtime-global-gc-overlap-20260930.json.gz": "f2fcb5577c70ddc108323a532cb4d404ae6fa36c", + "docs/validation/generic_runtime_owners_323_20260930/perf-generic-runtime-imaging-confirmation-observations-20260930.json": "b342f9aaf6f2a5828fc81ebfca3779976cb7e6be", + "docs/validation/generic_runtime_owners_323_20260930/perf-generic-runtime-owners-complete-native-artifact-parity-20260930.json": "3d97717a7c9eb41cd5c41b75ea006f13fa52634e", + "docs/validation/generic_runtime_owners_323_20260930/perf-generic-runtime-owners-complete-public-comparison-20260930.json": "741a18be8a71f1741941035d99a0566cde62241c", + "docs/validation/generic_runtime_owners_323_20260930/perf-generic-runtime-owners-complete-public-observations-20260930.json": "1073c59b3e5397baafb34b7e12f0b34942116346", + "docs/validation/generic_runtime_owners_323_20260930/perf-generic-runtime-owners-paired-main-census-20260930.json.gz": "c2d2136632f787a56cdef6cf5efac6a66f528b9b", + "docs/validation/generic_runtime_owners_323_20260930/perf-generic-runtime-owners-paired-main-consumers-20260930.xml.gz": "6de5fbfeebd8086f1ad4521177dde4b5c68e7024", + "docs/validation/generic_runtime_owners_323_20260930/perf-generic-runtime-owners-paired-main-public-comparison-20260930.json": "d1ad1d42316b4a52f0938dd97c738b22f670e445", + "docs/validation/generic_runtime_owners_323_20260930/perf-generic-runtime-owners-paired-main-public-observations-20260930.json": "0302c8fa8ab7a7e1bc1554a4ec84298df0b984ab", + "docs/validation/generic_runtime_owners_323_20260930/perf-generic-runtime-owners-paired-main-r0-benchmark-20260930.json.gz": "c9cefbf2a2a31a60900bdc50c4d6081b41484ddb", + "docs/validation/generic_runtime_owners_323_20260930/perf-generic-runtime-owners-paired-main-r0-openhcs-20260930.json.gz": "15451ec237ed89a87c80051dc257bf67b243cd87", + "docs/validation/generic_runtime_owners_323_20260930/perf-generic-runtime-owners-paired-main-r0-scripts-20260930.json.gz": "97aa8635095963f67f9c602c26e77c951cf60468", + "docs/validation/generic_runtime_owners_323_20260930/perf-generic-runtime-owners-paired-main-r1-20260930.json.gz": "9f57ed8cbf970e3fe5811cbe8bacf0fb1883b7de", + "docs/validation/generic_runtime_owners_323_20260930/perf-generic-runtime-phase-diagnostic-20260930.json.gz": "191406a910209b0421d4afbfc7467ea846c4e0ae", + "docs/validation/generic_runtime_owners_323_20260930/perf-generic-runtime-phase-diagnostic-observations-20260930.json": "d58e1b9a2555ed05bfaf3f520732d7026c17262b", + "docs/validation/generic_runtime_owners_323_20260930/perf-generic-runtime-query-hash-costs-20260930.json": "d4a1f09b0fea1144d3fc3c483c78c1bfb49ba926", + "docs/validation/generic_runtime_owners_323_20260930/perf-generic-runtime-query-hash-diagnostic-20260930.json.gz": "df813b183b2f55b5c586fcfc8070c2877f7f162c", + "docs/validation/generic_runtime_owners_323_20260930/perf-generic-runtime-query-hash-diagnostic-observations-20260930.json": "83feae001a1222789525257cfddf3cd48ca92285", + "docs/validation/generic_runtime_owners_323_20260930/perf-granularity-active-spectra-production-replay-20261001.json.gz": "b6c5a425432ac65844ca41bab61ad3a3708e4211", + "docs/validation/generic_runtime_owners_323_20260930/perf-granularity-constant-spectra-production-replay-20261001.json.gz": "dc5c24c7dd020de222f58f834cb58a50760911e0", + "docs/validation/generic_runtime_owners_323_20260930/perf-granularity-maxtree-admission-20261001.json.gz": "408652714561165d92212f2493ee96083182911b", + "docs/validation/generic_runtime_owners_323_20260930/perf-materialization-ack-current-main-corrected-20260930.xml.gz": "6c1d82298046e463f3bc58a1636255aa6f933a46", + "docs/validation/generic_runtime_owners_323_20260930/perf-measurement-provenance-frontier-probe-20260930.json": "1b2c27389d65eaa9d8fb2cb3ae0009f393f30a97", + "docs/validation/generic_runtime_owners_323_20260930/perf-numerical-cache-owner-simulation-20261001.json.gz": "59e36df308d7d17fbe226785f8523237e2960ea6", + "docs/validation/generic_runtime_owners_323_20260930/perf-numerical-cache-owner-transaction-20261001.diff.gz": "dd1ad53e987e16d3ab66fc40e12a7272850ef678", + "docs/validation/generic_runtime_owners_323_20260930/perf-numerical-cache-owners-before-census-20261001.json.gz": "bfdbaeb39a55f12c5a80f29f33294c7e30337a29", + "docs/validation/generic_runtime_owners_323_20260930/perf-numerical-cache-owners-public-comparison-20261001.json.gz": "5b66a0a1aa9c4ca8cf95129b809d08caf0bdd989", + "docs/validation/generic_runtime_owners_323_20260930/perf-numerical-cache-owners-public-observations-20261001.json.gz": "e7a85a53cbb8c9fc1c81941ce04e5f2cdffddcb1", + "docs/validation/generic_runtime_owners_323_20260930/perf-runtime-owner-closure-census-20261001.json.gz": "fc9cd5f9ee8a9086aa5fcfe3579b3094134a1cdb", + "docs/validation/generic_runtime_owners_323_20260930/perf-runtime-owner-closure-combined-tests-20261001.xml.gz": "01317aff2e7af5c8a0c30d33f7e0b32e772d78aa", + "docs/validation/generic_runtime_owners_323_20260930/perf-runtime-owner-closure-decision-20261001.json.gz": "92fb90e14e36d1d418fbbce03b0b14a75fb0bab9", + "docs/validation/generic_runtime_owners_323_20260930/perf-runtime-owner-closure-global-gc-diagnostic-observations-20261001.json.gz": "bd577cf7fddc470df3e000105b166e0e202a8352", + "docs/validation/generic_runtime_owners_323_20260930/perf-runtime-owner-closure-global-gc-overlap-20261001.json.gz": "7447a61c6d7ec9a02a92cf67e235e652839388f5", + "docs/validation/generic_runtime_owners_323_20260930/perf-runtime-owner-closure-native-artifact-parity-20261001.json.gz": "64c7548874bab4eb3342c8daef1dccfaef047e1e", + "docs/validation/generic_runtime_owners_323_20260930/perf-runtime-owner-closure-r0-benchmark-20261001.json.gz": "8ebae02b05af3c499ec64d6647eeb1ab071d591f", + "docs/validation/generic_runtime_owners_323_20260930/perf-runtime-owner-closure-r0-openhcs-20261001.json.gz": "013b861ad3e798d859c602c31c48e068b2025c5e", + "docs/validation/generic_runtime_owners_323_20260930/perf-runtime-owner-closure-r0-scripts-20261001.json.gz": "dc89aa25ed4d269b3598a64738074c2ea0424d4e", + "docs/validation/generic_runtime_owners_323_20260930/perf-runtime-owner-closure-r1-20261001.json.gz": "da02b68ed8dabddf1729ae5722ce89fa0e97c76a", + "docs/validation/generic_runtime_owners_323_20260930/perf-runtime-owner-closure-step-deltas-20261001.json.gz": "715b42c8fe4dc099422b3b7aa7edd2a93da2d82a", + "docs/validation/generic_runtime_owners_323_20260930/perf-runtime-owner-cpu-timeline-attribution-20261001.json.gz": "7c96f8c9fa65e483c2f2970d4c4a9e8cec41b6f0", + "docs/validation/generic_runtime_owners_323_20260930/perf-runtime-owner-cpu-timeline-observations-20261001.json.gz": "1e1572ede43a67ac8b5c87ccd8112534a054dd80", + "docs/validation/generic_runtime_owners_323_20260930/perf-runtime-owner-fresh-native-fact-parity-20261001.log.gz": "cd56f41e0b9001c2f81713644db92efb489ddfbe", + "docs/validation/generic_runtime_owners_323_20260930/perf-runtime-owner-fresh-native-reference-result-20261001.json.gz": "593fc88fdf83fcbb8beca8ef0065be016c8b1f30", + "docs/validation/generic_runtime_owners_323_20260930/perf-runtime-owner-fresh-native-table-parity-20261001.json.gz": "45f344603d6cb2c58f9e2af2c017da39274ed9bb", + "docs/validation/generic_runtime_owners_323_20260930/perf-runtime-owner-native-binary-inventory-20261001.json.gz": "3d301c123216762399b172f3ee509a9b2d267a89", + "docs/validation/generic_runtime_owners_323_20260930/perf-runtime-owner-native-binary-sections-20261001.json.gz": "6632fec1e3c34d6eb4b68ce9cd1e0fe2a76153d9", + "docs/validation/generic_runtime_owners_323_20260930/phase-diagnostic-sitecustomize.py.txt": "ce6dd100c6874f020e9d7b90fe964569e86e109a", + "docs/validation/generic_runtime_owners_323_20260930/prototype_granularity_active_spectra_20261001.cpp.txt": "d168b48f36a1e3ede3690d037b96b9f713814af5", + "docs/validation/generic_runtime_owners_323_20260930/prototype_granularity_constant_spectra_20261001.cpp.txt": "deb475bec7ef24ceabee04b84751f0179886f263", + "docs/validation/generic_runtime_owners_323_20260930/query-hash-diagnostic-sitecustomize.py.txt": "e453975864a3379ed0d7a45266c7d4d65dcd94fe", + "docs/validation/generic_runtime_owners_323_20260930/refine_generic_measurement_runtime_owners_20260930.py.txt": "c63383ceaf9fdb3b3f9aff2707e7cf622d67b97e", + "docs/validation/generic_runtime_owners_323_20260930/replay_granularity_active_spectra_20261001.py.txt": "0ffffc3af9ff92d1bfbbe49fcbfef09fe1eb15eb", + "docs/validation/generic_runtime_owners_323_20260930/replay_granularity_constant_spectra_20261001.py.txt": "30c839bfddbf9be870ed4568fe11ba452597c3ec", + "docs/validation/generic_runtime_owners_323_20260930/run_generic_runtime_global_gc_diagnostic_20260930.py.txt": "63c0a646190561a95adf2976d921a30d4783c4af", + "docs/validation/generic_runtime_owners_323_20260930/run_generic_runtime_owners_complete_acceptance_20260930.py.txt": "5eab7c6b3e6f27bdc4b6ffa28eb090415959ee14", + "docs/validation/generic_runtime_owners_323_20260930/run_generic_runtime_owners_paired_main_acceptance_20260930.py.txt": "0721a7944a3fe8a54a878b6b30e376a9feb140b5", + "docs/validation/generic_runtime_owners_323_20260930/run_numerical_cache_owners_acceptance_20261001.py.txt": "27902922b6ab3a23451f80afbc0c4ed7b2609910", + "docs/validation/generic_runtime_owners_323_20260930/run_runtime_owner_closure_global_gc_diagnostic_20261001.py.txt": "cc1a8db221cba15d9dd44aa7d9efd859fc7831c2", + "docs/validation/generic_runtime_owners_323_20260930/run_runtime_owner_cpu_timeline_20261001.py.txt": "0f5caba061caf9e8229f32fa9f68b5ff828b52c2", + "docs/validation/generic_runtime_owners_323_20260930/run_runtime_owner_fresh_native_reference_20261001.py.txt": "91d588639fceb23608ae5bc17b3d30d5e3aa29af", + "docs/validation/generic_runtime_owners_323_20260930/separate_cache_values_from_process_lifetime_20260930.py.txt": "17dc0ff15b36d8ebdbb33ec1d02c90bd51c8a85e", + "docs/validation/generic_runtime_owners_323_20260930/test_generic_registered_numba_preparation_20260930.py.txt": "b72e564b794623233858f635f1c8d5131c629d80", + "docs/validation/generic_runtime_owners_323_20260930/test_shared_numerical_cache_owners_20261001.py.txt": "3a12375e8edd8c8d097ca360e55f48e41f856f27", + "docs/validation/generic_runtime_owners_323_20260930/validate_generic_runtime_native_artifacts_20260930.py.txt": "53bb7ab869af4f47bc8892b75499044f170e7f2a", + "docs/validation/generic_runtime_owners_323_20260930/validate_generic_runtime_owners_complete_outputs_20260930.py.txt": "2f1468dbeabe7f7a95f810bfc5f3c2ad1ad96d17", + "docs/validation/generic_runtime_owners_323_20260930/validate_generic_runtime_owners_paired_main_outputs_20260930.py.txt": "ed11df57938eb9ba40f8de453ead30a289f17a58", + "docs/validation/generic_runtime_owners_323_20260930/validate_runtime_owner_closure_native_artifacts_20261001.py.txt": "a07c4caf394e00d77bb72675ac58e62d9dbdd529", + "docs/validation/generic_runtime_owners_323_20260930/validate_runtime_owner_closure_owners_paired_main_outputs_20261001.py.txt": "da798773f1987c6f836fb73a67fbcc21119e8b99", + "docs/validation/generic_runtime_owners_323_20260930/validated-source-tree-95a98b008.txt": "ba6247b4f17ded789bda51d33daa21a575a9733e", + "docs/validation/generic_runtime_owners_323_20260930/validated-source-tree.txt": "088fbd2fa8dd6cddef358e22190946c11ecc9163", + "docs/validation/graytocolor-binding-axis-432-20261002/carrier-compile-diagnosis.log": "d900bf3ed92c8d001d23e3c282a0f78690ddf88a", + "docs/validation/graytocolor-binding-axis-432-20261002/carrier-compile-parent-admission.log": "c4d845baef34ec4eee0a144b5e04bd1e21cbe402", + "docs/validation/graytocolor-binding-axis-432-20261002/carrier-creation-receipt.rst": "f7b766779a88f3ed9ce3d20b2574908f94aeb0d2", + "docs/validation/graytocolor-binding-axis-432-20261002/carrier-repair-binding-controls.log": "0b313f79dddbdc7c5f53cdf15515532988530266", + "docs/validation/graytocolor-binding-axis-432-20261002/carrier-repair-controls.log": "b1ec3adc77269eb81d1afc8c8372188bdcd8c29f", + "docs/validation/graytocolor-binding-axis-432-20261002/carrier-repair-initial.log": "761452635faf23a6d55ac465f0c7d4aba94d6ede", + "docs/validation/graytocolor-binding-axis-432-20261002/carrier-repair-newcase.log": "08658dee1f0747f5dd13444e16efee92c80ea193", + "docs/validation/graytocolor-binding-axis-432-20261002/carrier-repair-owned-proof-controls.log": "35b16abec20c43271b34f31ad3d16541aa290f91", + "docs/validation/graytocolor-binding-axis-432-20261002/carrier-repair-owned-proof-r0.log": "244488f13af27fbac5a60207a0ff955014ed3965", + "docs/validation/graytocolor-binding-axis-432-20261002/carrier-repair-r0.log": "2809ae0efe0625172badfb0ef10e8eb10a39143a", + "docs/validation/graytocolor-binding-axis-432-20261002/carrier-repair-receipt.rst": "7221b311b3496a0805c7620df50b70ab796634b9", + "docs/validation/graytocolor-binding-axis-432-20261002/carrier-runtime-lanes.log": "d768f4328151a488d0095d62ad2c83594083e5c2", + "docs/validation/graytocolor-binding-axis-432-20261002/integer-binding-units.log": "cd005d448eba53a9176333b650bd173677429305", + "docs/validation/graytocolor-binding-axis-432-20261002/obligation-owner-controls.log": "00582b8ffc3a49b828746a6c89ce9e11cf40f25c", + "docs/validation/graytocolor-binding-axis-432-20261002/obligation-owner-final-controls.log": "0b316b37f8929b6ac5d7cfe4897b46444f886583", + "docs/validation/graytocolor-binding-axis-432-20261002/obligation-owner-r0.log": "2145b1d2ced90d2172fc6ada8270d7eb0a58ee9f", + "docs/validation/graytocolor-binding-axis-432-20261002/obligation-owner-receipt.rst": "205c0897a0b5c120f37a3921ead8130e174b7867", + "docs/validation/graytocolor-binding-axis-432-20261002/obligation-owner-scoped-anchor-controls.log": "d3fa09e91d1f8547c66b8b8f824003ae1b6a5133", + "docs/validation/graytocolor-binding-axis-432-20261002/original-assisted4-status-excerpts.log": "175ca08161c3f1d7bf01becba8e7b9bb2b3307b9", + "docs/validation/graytocolor-binding-axis-432-20261002/original-native-excerpts.log": "ca0577c346bd90ea0d38dec3e23f98896e2f78a9", + "docs/validation/graytocolor-binding-axis-432-20261002/receipt.rst": "b389c1e8ee25c3e306b147dba3bed609e29126db", + "docs/validation/graytocolor-binding-axis-432-20261002/source-diagnosis.log": "993b14cd14d00f0277e79548a9b5c968cd54af6c", + "docs/validation/graytocolor-binding-axis-432-20261002/working-pr-body.md": "9753e2e50ec9c0ca6fa609ac475e0f33768bc4f7", + "docs/validation/graytocolor-singleton-binding-432-20261002/composed-consumer-controls.log": "d3ccb44bc3ccb9f42cb742f277b6fc76324dbd0c", + "docs/validation/graytocolor-singleton-binding-432-20261002/declaration-plane-controls.log": "a433301bbf9cfb5785d383bc07d3324daeccb256", + "docs/validation/graytocolor-singleton-binding-432-20261002/existing-module-controls.log": "9667d629f817513009bd796ae467d01b7b1b3fec", + "docs/validation/graytocolor-singleton-binding-432-20261002/main-integration-controls.log": "d0297b69f77ba1aa5c4348f4250ae2a939cb941e", + "docs/validation/graytocolor-singleton-binding-432-20261002/main-integration-r0.log": "15c3286d4ac2f70b6dcf16e3c91b0eb917e494a7", + "docs/validation/graytocolor-singleton-binding-432-20261002/new-declaration-controls.log": "060f5d29d98d55c0a6d4cc9c58c06d1a90354489", + "docs/validation/graytocolor-singleton-binding-432-20261002/new-declaration-first.log": "5e643ab702c603d9983f876b4912890e0c625415", + "docs/validation/graytocolor-singleton-binding-432-20261002/original-unary-red.log": "e812aac7ed0e24d8a73f0eebaddc9ea52ed20b09", + "docs/validation/graytocolor-singleton-binding-432-20261002/pr-body.md": "91671e07993ba6832afcb1bf0ceff30426aa8b83", + "docs/validation/graytocolor-singleton-binding-432-20261002/receipt.rst": "8ba80ee347b0d249dcc9265a3ba0e5c2df5c44e7", + "docs/validation/graytocolor-singleton-binding-432-20261002/repair-receipt.rst": "623e1466840edb5c2db7c8a46e92ef430a781ea7", + "docs/validation/graytocolor-singleton-binding-432-20261002/run_original_r1.py": "aa9be27fd0e6a4a26e4602d21c4f3a615c92c5cb", + "docs/validation/graytocolor-singleton-binding-432-20261002/unary-repair-controls.log": "7e4399444af83f30fba9181ea752535ed876bb1d", + "docs/validation/graytocolor-singleton-binding-432-20261002/unary-repair-first.log": "1bade343800cc1fe87cabf07ec1cb7ce2d051112", + "docs/validation/graytocolor-singleton-binding-432-20261002/unary-repair-r0.log": "74527ac75c6684cb7e769d194b61b6d9f1ceea20", + "docs/validation/graytocolor-singleton-binding-432-20261002/unary-repair-r1-exact-context.log": "3905f55b0b48891088eae323df788626e318b157", + "docs/validation/graytocolor-singleton-binding-432-20261002/unary-repair-r1-verified.log": "42c3da804ff7f1b34fa9c05a2365d9155df23458", + "docs/validation/graytocolor-singleton-binding-432-20261002/unary-repair-r1.log": "c5d54a72c4acbf2f659a746e3068c5fc1749e3e8", + "docs/validation/gui-cold-connect-355.rst": "98f313c20f5ab9188a2323c98d0dceba3f086b2b", + "docs/validation/h001-stream-plane-427-20261002/GREEN-contract-execution.log": "ebfc2d086ec2ea2d5a2fcaca0c30da04901ce03b", + "docs/validation/h001-stream-plane-427-20261002/GREEN-declaration-controls.log": "d2f80a49e6ec8a6eb86d9b93976b3d4494a1cfac", + "docs/validation/h001-stream-plane-427-20261002/GREEN-final-stream-shard.log": "595b3c312e531b09b8da622dd21c4ae804888916", + "docs/validation/h001-stream-plane-427-20261002/GREEN-first.log": "f830c1d4c7dd05da3c208db9f64aa23c8099062f", + "docs/validation/h001-stream-plane-427-20261002/GREEN-main-flow.log": "0296896244a6781f2b4bbeafa1a8222d967d2522", + "docs/validation/h001-stream-plane-427-20261002/GREEN-newcase.log": "9ada5dbf7454d353b5954b1bb293fb177ab67cdd", + "docs/validation/h001-stream-plane-427-20261002/GREEN-strict-native-shard.log": "49ba595caf2d6d745d6c87fc761670ea5fd58b33", + "docs/validation/h001-stream-plane-427-20261002/R0.json": "65307891958cfa9481b0e46878c2b347f40635f5", + "docs/validation/h001-stream-plane-427-20261002/R0.resources.txt": "8e5a7e0ee4bafea2cabad98516779b5594b88aec", + "docs/validation/h001-stream-plane-427-20261002/RECEIPT.rst": "e7c23bb03e43e3bce335d87a67a65b61e56a9b72", + "docs/validation/h001-stream-plane-427-20261002/RED-original-producer.log": "e6c478378e9379bbcc2dbca993d583ef09366ff9", + "docs/validation/h001-stream-plane-427-20261002/RED-production-canonical-config.log": "9ff0a07a73d7da3034a69da7fcac52b69b71ed91", + "docs/validation/h001-stream-plane-427-20261002/RED-production.log": "e3499635b6e34bb4189e6af5de281bd09d3577a6", + "docs/validation/h001-stream-plane-427-20261002/RED-seeded-producer.log": "f41963696adfc11af114c316039dc76a83ef8416", + "docs/validation/h001-stream-plane-427-20261002/RED.log": "c8e645a8099eba6bf2b34c48e248aa2b00ea0e2b", + "docs/validation/input_preparation_installed_20261001.rst": "fd668663d02fcc31e76f0661ee852b581732b7c3", + "docs/validation/input_preparation_parent_20261001.rst": "7266a6373b2313f81a8d3efe25c686bd739e0a3e", + "docs/validation/input_preparation_quality_20261001.rst": "9a7577c747f7bdd337b00c51854239cbc779d913", + "docs/validation/intensity-domain-skill-20261001/VALIDATION.rst": "79179def6cc760fb8eef5ac983ea7d89233f21ed", + "docs/validation/intensity-domain-skill-20261001/quick-validate.log": "bcdbc5fc48236e8bd17b591cf96d1539ec249311", + "docs/validation/intensity-domain-skill-20261001/registry-g.log": "ff2bd9475e4f28261911659d749b3d68bfffd3f8", + "docs/validation/intensity-domain-skill-20261001/tests-a.log": "91538c9ea8f078438de3d4dded3e0c0c730a2c1a", + "docs/validation/intensity-domain-skill-20261001/tests-b.log": "6f700588a88decd597c101f43d545ddd4c05acbe", + "docs/validation/intensity-domain-skill-20261001/tests-c.log": "f75ecb8b7db4e678ef75bc2a672648947e2f190a", + "docs/validation/intensity-domain-skill-20261001/tests-d.log": "7a470d8eba4fabdd8a91f04c6549a00fdd809b7a", + "docs/validation/intensity-domain-skill-20261001/tests-f.log": "1e8e0d76c1cc064f766e28483d479e3c5fe52893", + "docs/validation/intensity-domain-skill-20261001/tests-h.log": "7f24538287d9bcb4a6f0809258e35dbc0ea3bed6", + "docs/validation/issue257-draft-pr.md": "e1686d61590ee8048e5a35bfda38345a0b42a306", + "docs/validation/issue257-implementation-20260930.md": "ad3f7b96849d003e395f94f5b491e386c2be0f6f", + "docs/validation/issue257-runtime-composition-20260930.md": "fb3cd4709dd200ea46f66af8e29dad7bf7ffcbb0", + "docs/validation/issue257-runtime-composition-receipt.json": "059ac40607469c5cd72bf08835806db3658c883e", + "docs/validation/issue257-source-investigation-20260930.md": "dce143b79b3fa34889753e10110a3209fb73b8a5", + "docs/validation/issue257-source-receipt.json": "66b2ba2fd530ed979e604cf98814b8e3503ed18d", + "docs/validation/issue257_projection_contract_20260930.rst": "ba3ef4654f918f442d890c862931c3559038247c", + "docs/validation/issue264-source-extension-20260930.md": "fb710b1c04340b2aeb74347b066e0cc2fbb1d983", + "docs/validation/issue264-source-receipt.json": "9f947c21efa5b3166be92bf9f193f21c2e2535cb", + "docs/validation/issue355-evidence/openhcs-checkpoint.log": "c026eea7f66748014c8875b63c365c18aeed4d50", + "docs/validation/issue355-evidence/openhcs-r0-checkpoint.json.gz": "073411e00640d06813a2a3e2bedc8658cb24ab53", + "docs/validation/issue355-evidence/openhcs-r0-checkpoint.resources.txt": "99f01ef1fe68eae1bae535ac25a2e9d6e864c7ce", + "docs/validation/issue363-binding-source-checks-20261001.tar.gz": "cd5ba424230a486e6cf52784fb9cd3decccd57cc", + "docs/validation/issue363-evidence/reused-extension.sha256": "cf06d3127bed5ff5e57ab607fcc29560aabd012e", + "docs/validation/issue363-source-checks-20261001.tar.gz": "6f791f1dd2816a2edd5d6d02dbd351f8508b7ae0", + "docs/validation/issue376-source-diagnosis-20261001.tar.gz": "3144f9bfe01e1e062189a22eece31a801ddcc2b0", + "docs/validation/kernel_readiness_352_20261001.rst": "70d479b0fd5df4ce8db03cde002e87398b0e3ca3", + "docs/validation/kernel_readiness_352_evidence_20261001.tgz": "3b6253415af10a0f2c4b1c51a62dfaa711c513d8", + "docs/validation/knowledge-lazy-conversion-376.rst": "90de971cf1dbc9b84563a65f52e295e99669d0db", + "docs/validation/knowledge-native-source-499-20261003.rst": "9d45a1ee8b0cff7caebb0d33a1699447e4357e45", + "docs/validation/knowledge-selected-source-tests.py": "80e42cf144ba9b2bf7d97239a77d8069ce2461ed", + "docs/validation/label_selection_346_20261001.rst": "a6a5b2136f8f2bcb17303d66578219b84d2ef999", + "docs/validation/label_selection_346_evidence_20261001.tgz": "bbc52ed08aee23142961577a49137289177ff9ca", + "docs/validation/matched_csv_356_20261001.rst": "d43796e0d10b6f1e1bd02f38ea045111d2cb1621", + "docs/validation/matched_csv_356_evidence_20261001.tgz": "8ef924ae21251564b09e6eb4e921c28025a97921", + "docs/validation/materialization_plumbing_384_20261001.rst": "8125d2b4b78be6d7340cbb73587fa322b3a40f46", + "docs/validation/mcp-affine-inspection-436-20261002/affinity-resident-controls.log": "48c8dfe4c8c07169f3b0394fadc933b3b782f43b", + "docs/validation/mcp-affine-inspection-436-20261002/bootstrap-source-admission-controls.log": "c8791381c728cf3338f9c9c4ff57e6d2fc9da68d", + "docs/validation/mcp-affine-inspection-436-20261002/generated-progress-controls.log": "d09b5decb56b37c50ef9f9cc8aad85d9438adc80", + "docs/validation/mcp-affine-inspection-436-20261002/mcp-boundary-controls.log": "78e5fca9be9a14c10624d564afbb3a0a1591ff95", + "docs/validation/mcp-affine-inspection-436-20261002/pr-body.md": "fc184908bdb460ae5326c2d9972b9d36d2601804", + "docs/validation/mcp-affine-inspection-436-20261002/probe_stdio.py": "6a613dc61b96989a7d6ffeedd902b0f484364b7a", + "docs/validation/mcp-affine-inspection-436-20261002/r0-original-pin.log.gz": "ae69d0108516a05e67a8891d058cf403869bd68e", + "docs/validation/mcp-affine-inspection-436-20261002/real-compiler-controls.log": "e3ac0c845a0a2f19c44503b2f458ba77c43099de", + "docs/validation/mcp-affine-inspection-436-20261002/real-compiler-qualified-controls.log": "7d03b121a128f59a3ab7fdd00013290526d171eb", + "docs/validation/mcp-affine-inspection-436-20261002/receipt.rst": "60a20bf0f1b1bbbb375b0b94658126438cfd6094", + "docs/validation/mcp-affine-inspection-436-20261002/resident-twelve-second-controls.log": "f110325bcbc772419b34226533e97eca348cdde6", + "docs/validation/mcp-affine-inspection-436-20261002/source_fixture.py": "9349baea4a39f24a8ebec86274d1be639dd8ffa5", + "docs/validation/mcp-affine-inspection-436-20261002/stdio-original-controls.log": "a8b232c06d384415b1a41c5aac9c05872be89a75", + "docs/validation/mcp-affine-inspection-436-20261002/stdio-twelve-second-controls.log": "be8d1aae6ca7beddbdf53e543b760f4bcdc8a27f", + "docs/validation/mcp-affine-inspection-436-20261002/stdio-whole-scope-controls.log": "0fe7b136aaeaeb203d79eb642b825dda9ef42cc6", + "docs/validation/mcp-affine-inspection-436-20261002/stdio-wire-controls.log": "6cd2c02206eba2f553d4d53beb403452a434d56c", + "docs/validation/mcp-affine-inspection-436-20261002/stdio-wire-qualified-controls.log": "d98953ed9ff290623d4a3d0cb013347d833bb6be", + "docs/validation/mcp-cold-inspection-feedback-436-20261002.rst": "bcdb35d51554cd8246194627ca86a4e04cee030b", + "docs/validation/mcp-jvm-lifetime-455-20261002.rst": "a2de5f5e5e35ca8becd5923f1e2226217a026376", + "docs/validation/mcp-jvm-lifetime-455-20261002/qualify.py": "3ca6aa903504b65f791aa8ad9d12d59b18b02d89", + "docs/validation/mcp-progress-ack-20261002.rst": "36502f5c9951b86ab4ee05b3c57bd4e6d3bcf685", + "docs/validation/mcp-roi-stream-progress-441-20261002.rst": "dafc566a99e1bd96d03b0807e534f8ac8bb4b32e", + "docs/validation/mcp-terminal-input-483/INSTALLED-ACCEPTANCE.rst": "4611caf7460256a3dfa3014c5730cb1da4fcef59", + "docs/validation/mcp_local_argument_errors_20260930.rst": "a472f70f7ce0ce3bc98d3f9ab862682339825ef4", + "docs/validation/memory-session-20260929.md": "cc804ea4bc7b010557350b47e5e1d529b1860485", + "docs/validation/memory_current_main_integration_20260930.rst": "36f91a6c989b9839439efff02a88f2a36cd494a4", + "docs/validation/metaclass-registry-022-publication-20261001/RECEIPT.rst": "c608530b3edbf9806dd3e8360e87d4d8bd731929", + "docs/validation/metaclass-registry-022-publication-20261001/SHA256SUMS": "bb77bc3ad2f9a85bc314fbde9446831fcba95e78", + "docs/validation/metaclass-registry-022-publication-20261001/artifact-verification.log": "7f9008bc07f37ba7075cc4449417b3c79670324a", + "docs/validation/metaclass-registry-022-publication-20261001/artifact-verification.resources.txt": "673479c067a09a0efb1d05608ff978c336392f68", + "docs/validation/metaclass-registry-022-publication-20261001/artifacts/metaclass_registry-0.2.2-py3-none-any.whl": "ecda496085ead4b4c0188582d42e536d9fac9ae0", + "docs/validation/metaclass-registry-022-publication-20261001/artifacts/metaclass_registry-0.2.2.tar.gz": "095e2ac191c71dcdde2c1805f1335f3ae8b9848c", + "docs/validation/metaclass-registry-022-publication-20261001/github-release.json": "6d60fa911f3a66aeeceec43c61515e82898996dc", + "docs/validation/metaclass-registry-022-publication-20261001/job-queued.json": "6aa5094ac2b96cfc2bcca31d35910463c872559c", + "docs/validation/metaclass-registry-022-publication-20261001/pending-deployments.json": "0637a088a01e8ddab3bf3fa98dbe804cbde1a0dc", + "docs/validation/metaclass-registry-022-publication-20261001/release-session.typescript": "86dcdfc564875a563715634ff7da30fafd325d86", + "docs/validation/metaclass-registry-022-publication-20261001/verify_publication.py": "156249134803eee969e40b4f7aab8853914775f0", + "docs/validation/metaclass-registry-022-publication-20261001/workflow-initial.json": "f292434cbbb523842ce073dc0472c29aa84d7e9c", + "docs/validation/metaclass-registry-022-publication-20261001/workflow-terminal.json": "d0afd19f4da005e8dba3b66439c126ffb77a9787", + "docs/validation/metaclass-registry-022-publication-20261001/workflow-watch.log": "2d4473c9b02781f20c300fbe14450296efc6a16f", + "docs/validation/metadata_namespace_327.rst": "dba3083cdf64896f54cb83de862e67e702c03e98", + "docs/validation/metadata_namespace_327_resources.rst": "7eabc5070dd6d9636dbde176a59685734d87f0df", + "docs/validation/metadata_namespace_327_source_evidence.tgz": "6c2dd1e466edab0ba8c4c08f71726c0fe6c62a2f", + "docs/validation/morphology-library-readiness-481-20261002.rst": "443efd1b3538b88b0ebb85b33d4cb9505b14251f", + "docs/validation/napari-source-channel-presentation-448-20261002/pr-body.md": "d104084329d7d572ab3eb429ff5349a0a7d35e3e", + "docs/validation/napari-source-channel-presentation-448-20261002/receipt.rst": "1443b98cc92103a8f5c419d497beaf4740b672b6", + "docs/validation/native-presentation-451452-20261002/complete-presentation-final.log": "b4294ffb8c1b8059a84a7ca5e34832dc8e1979d2", + "docs/validation/native-presentation-451452-20261002/complete-presentation-first.log": "13ec12bd66cc3f060d3fac66102772c2b6ff74bf", + "docs/validation/native-presentation-451452-20261002/complete-presentation-second.log": "d3f3814fcf525c7b59cbe8ff519fa1a137cbe2c6", + "docs/validation/native-presentation-451452-20261002/display-admission.log": "c7efc378b2f62c11d0362647f93d013d1e282a82", + "docs/validation/native-presentation-451452-20261002/final-original-r0.log": "8fbe80175c974b39d98541004507afecda45ab2e", + "docs/validation/native-presentation-451452-20261002/final-presentation-controls.log": "60f34afca89aaeea5f8269e4693820e937557e67", + "docs/validation/native-presentation-451452-20261002/mcp-controls-first.log": "d60dca98fa1c8f9d33e4ae55bcd0c688264cd2b3", + "docs/validation/native-presentation-451452-20261002/mcp-record-descent.log": "cce248ae4331931e8938bcbb5b7827829b76fb70", + "docs/validation/native-presentation-451452-20261002/merged-main-ast-closure.log": "398c2f39dff12417f1adc99bfe0463e140d2055f", + "docs/validation/native-presentation-451452-20261002/merged-main-native-controls.log": "794ae252346bd87ca00af7985a885e695c8d88af", + "docs/validation/native-presentation-451452-20261002/merged-main-original-r0.log": "e97ebc2ca9a087ce9f3315f199438f22fd9ebdd8", + "docs/validation/native-presentation-451452-20261002/merged-main-public-mcp-controls.log": "77ef1a0371ee947c085d8f223342a2424e1edc08", + "docs/validation/native-presentation-451452-20261002/native-and-consumer-controls.log": "7d3cd96dfe22e1981c94bd4dc3be441d7c84881e", + "docs/validation/native-presentation-451452-20261002/native-family-integration.log": "8e16398e47af72ade418de1a5ed0a4316affa200", + "docs/validation/native-presentation-451452-20261002/original-presentation-controls.log": "4133e2c792e90b055e4ab5001383721c94276307", + "docs/validation/native-presentation-451452-20261002/original-r0.log": "07c67e2f7ec251756c241799e37e64b365a57808", + "docs/validation/native-presentation-451452-20261002/ownership-after-linear.log": "bfd305b0fcb68189c4939c8b7c8d24b8da3f4163", + "docs/validation/native-presentation-451452-20261002/ownership-after.log": "e69de29bb2d1d6434b8b29ae775ad8c2e48c5391", + "docs/validation/native-presentation-451452-20261002/ownership-before.log": "b066ebfd6ec273ae288f40b305971780854fa425", + "docs/validation/native-presentation-451452-20261002/pr-body.md": "82af0a055c8bb88abc2b72b46441859e4d071cfc", + "docs/validation/native-presentation-451452-20261002/qualified-native-controls.log": "4f37dab52bc26f28faa09ab45d882789e4d684eb", + "docs/validation/native-presentation-451452-20261002/qualified-public-mcp-controls.log": "ed89ddddc5b870230938c75ada7e1699103598d3", + "docs/validation/native-presentation-451452-20261002/receipt.rst": "13699c70024cd6bb228ff81b8490950e5cf790ea", + "docs/validation/native-presentation-451452-20261002/root394-roster.json": "00a4f9bcc1606139e817a73a4ab269c6a94ef504", + "docs/validation/neurite-primary-diagnostic-consumption-410.rst": "50f1a71a1ff4723d2648108dcc79c5254496b1ad", + "docs/validation/neurite_body_gate_424_20261002/ARCHIVE-SHA256SUM": "123251e0380b8ec0a76911f9a8ee8df47fe1e8b1", + "docs/validation/neurite_body_gate_424_20261002/EVIDENCE.tar.gz": "ff3917c0599c6f37633d3f032fb4a891a4269490", + "docs/validation/neurite_body_gate_424_20261002/QUALIFICATION.rst": "85ce0adae2accf0ef76dda1b487c1f760c73c9eb", + "docs/validation/neurite_body_gate_424_20261002/RECEIVING.rst": "138d1a0968199bc5d2a240055501056fe320f33a", + "docs/validation/neurite_body_gate_424_20261002/SHA256SUMS": "b444c1d5cc323ca74a2d9bcf4ead1fd3ebb597ef", + "docs/validation/neurite_body_gate_424_20261002/SOURCE-SHA256SUMS": "33cffe0e8b85dd65406b280f5ae458838fd3693a", + "docs/validation/official30_qualification_330_20261001.rst": "203dc1eec4324d05990dfbd7d4b27b784200c987", + "docs/validation/official30_qualification_330_evidence_20261001.tgz": "35e7d883c07b4b2cd276a87da79c54504fa1669e", + "docs/validation/opera_producer_inventory_172.rst": "2fe74656b6005691c87ebe66937f238ff18e90a5", + "docs/validation/opera_producer_inventory_172_main8c512_evidence.tgz": "3714662c0ff6623ac90418878723397dd69bb8c7", + "docs/validation/opera_producer_inventory_172_source_evidence.tgz": "d3d8dbed17d33048b8c248f1ff16d7c54367ce08", + "docs/validation/opera_singleton_172.rst": "e2291c7b1f614f0dee2245605d5a12562cd4b87d", + "docs/validation/opera_singleton_172_source_evidence.tgz": "8508a1c9f5bd64d2d14c1aa550eee4b157ea553b", + "docs/validation/paired-feedback-integration-358.rst": "118e6a971f48597d9820ed9778d3fef7f2c8e804", + "docs/validation/paired-feedback-integration-evidence/PR358.md": "d6dc1ffdb7037b323db6709c47bb15a363e3e6f3", + "docs/validation/paired-feedback-integration-evidence/SHA256SUMS": "5c2d8540d797ed4df48df09ea92bf0d3bb558361", + "docs/validation/paired-feedback-integration-evidence/ZMQRuntime-PR13.md": "89c1836cea7304a96d574a3f539d6134f8ed8c90", + "docs/validation/paired-feedback-integration-evidence/openhcs-r0.json.gz": "5a65c3255e3757a13393bf6a0b862a2670b691f8", + "docs/validation/paired-feedback-integration-evidence/openhcs-r0.resources.txt": "50e3a38b684ec5cf468c95f79287bc5d2ecbdd66", + "docs/validation/paired-feedback-integration-evidence/openhcs-r0.stderr.txt": "f1d833af047295a8cff3918716824be9a7e40a00", + "docs/validation/paired-feedback-integration-evidence/zmqruntime-r0.json.gz": "63effef5b92ed9667ebfca816eb9f96d80de2cb9", + "docs/validation/paired-feedback-integration-evidence/zmqruntime-r0.resources.txt": "53dee34d792b997366eca667c34751aeb9042955", + "docs/validation/paired-feedback-integration-evidence/zmqruntime-r0.stderr.txt": "880125daf16a99d33387375630afce13ffb5da61", + "docs/validation/paired_field_csv_314_20260930/PREFLIGHT.json": "aff217990966162f3b5d3c4de2fdf3af63cbd43b", + "docs/validation/paired_field_csv_314_20260930/SHA256SUMS": "fb062f64846d2b00a87d715601545920617472d7", + "docs/validation/paired_field_csv_314_20260930/check-installed-parent.py": "1fcc3c9c73fc4294c744b5309eec437570cb615c", + "docs/validation/paired_field_csv_314_20260930/checkpoint.rst": "fd32fe1384d5acbd4add88469e36e31e91f95a1e", + "docs/validation/paired_field_csv_314_20260930/core-census.json.gz": "7f12ab38fdcfc4ee5e79cf377a8324c772dce884", + "docs/validation/paired_field_csv_314_20260930/core-census.log": "54631c41b6bea651c74badb8401f59de5a3b6539", + "docs/validation/paired_field_csv_314_20260930/core-overlay.json.gz": "c01643a81743a9e656b6cbc676d4ab29973b0ac7", + "docs/validation/paired_field_csv_314_20260930/core-overlay.log": "75a58cb2db6cffbc77a06f058a843303d770bac6", + "docs/validation/paired_field_csv_314_20260930/create-live-fixture.py": "bb5e57f0e4a83cb94d2b68cac3bc9883cc1a9185", + "docs/validation/paired_field_csv_314_20260930/effective-imports-error.log": "e69de29bb2d1d6434b8b29ae775ad8c2e48c5391", + "docs/validation/paired_field_csv_314_20260930/effective-imports.json": "00903619fd92078d72a4de29bd3f658c657a9028", + "docs/validation/paired_field_csv_314_20260930/final-policy-exporter.log": "3f3e8b5fa5cfe6d7e2edfeb2870d20be49032909", + "docs/validation/paired_field_csv_314_20260930/installed-parent-checkpoint.rst": "44d35e319273ca90492193daffb689d1c4596ad3", + "docs/validation/paired_field_csv_314_20260930/merged-main-census.json": "a32071ea499acd04f746817512244bf0fc717fdd", + "docs/validation/paired_field_csv_314_20260930/merged-main-census.log": "9692aea2a969ae42bc4e90f08c52d6586fa96089", + "docs/validation/paired_field_csv_314_20260930/merged-main-owner.log": "fc5fcfd85ffb0ebebabeb6913e116ba2d45310c5", + "docs/validation/paired_field_csv_314_20260930/merged-main-related.log": "a28aa8e39595aa46fac04e31b2c2e6f0951574e9", + "docs/validation/paired_field_csv_314_20260930/nra-original-resources.log": "f0cc5becc628c4fd4b30c10751eb527e3e7592e2", + "docs/validation/paired_field_csv_314_20260930/nra-original.json": "7a16c89d4e117048161cb379ddd1d294f07f0123", + "docs/validation/paired_field_csv_314_20260930/nra-owner-loop-resources.log": "6f6f8d83e84b11cf88c826f3dd0eb83cd0641cb4", + "docs/validation/paired_field_csv_314_20260930/nra-owner-loop.json": "f3042364c8ccc05dc70a5925d4a15f8b02512d60", + "docs/validation/paired_field_csv_314_20260930/owned-disposable.tar.gz": "3e6e11fdc9afa8d4d50dd7cff516ca598b8401b5", + "docs/validation/paired_field_csv_314_20260930/owner-census-delta.json": "5a074405bb39a6d5b308ad35ddf53879b82abb3e", + "docs/validation/paired_field_csv_314_20260930/owner-census-delta.log": "eaac50f19839e150c8c9053a2ca163460e220678", + "docs/validation/paired_field_csv_314_20260930/owner-fixed-corrected.log": "3a2515575f3e180191767347f13092bf85979adb", + "docs/validation/paired_field_csv_314_20260930/owner-fixed.log": "db16ae61129762a6c50d49d3fa5fe8c11086f4a9", + "docs/validation/paired_field_csv_314_20260930/ownership-receipt.rst": "23ab08d78a78ee265daf00e7950f56a602527204", + "docs/validation/paired_field_csv_314_20260930/pipeline-live-parent.py": "b30ec89770f11554167bc01677db5b3376c96121", + "docs/validation/paired_field_csv_314_20260930/policy-import.log": "90b2be632490c79a40082b6fde0f2e116dc0915a", + "docs/validation/paired_field_csv_314_20260930/pr-body.md": "4455fdfddc7a92fb55eceea7d85e856679a72eab", + "docs/validation/paired_field_csv_314_20260930/related-owner-contracts.log": "f1bdfead08c366c3c6da5f19e7b1e7420e22f50a", + "docs/validation/paired_field_csv_314_20260930/reproducer-original-built.log": "a1ca749ad0cbc1e8540f0a81502801c86bdb951b", + "docs/validation/paired_field_csv_314_20260930/reproducer-original.log": "3ae63c2bd511c69286dd71725d4aca371c202623", + "docs/validation/paired_field_csv_314_20260930/ruff-focused.log": "79cdd685850125f1097bff64d6a4e9da32cf6141", + "docs/validation/paired_field_csv_314_20260930/run-installed-parent.sh": "65efa139bdd8613cc5afdb520be836de465e12ce", + "docs/validation/paired_field_csv_314_20260930/source-anchors-base-empty-snapshot.log": "4a8efd805635061e236d81e3c764b5884895d3d8", + "docs/validation/paired_field_csv_314_20260930/source-anchors-base-verified.log": "379ff18faf5cf5cae18550e19ddf2320cf3f20e9", + "docs/validation/paired_field_csv_314_20260930/source-anchors-base.log": "42da0a71fd65ef9235a810fe96a3db01c6c8c72c", + "docs/validation/paired_field_csv_314_20260930/source-build.log": "1818a8deeae6a8d306b8166048f9f0a81beac546", + "docs/validation/persisted-result-reopen-398-source-20261001.tar.gz": "b0f33d3b7ca0608158a5756682d52d0dbb372f25", + "docs/validation/persisted-result-reopen-398.rst": "166be7e9d0f4f0cbacd2d424481b58c5d9386c0f", + "docs/validation/persisted_result_publication_134_20261002.rst": "fe8e06108650c74ccc3bd0e06fcd307881ab5942", + "docs/validation/physical-source-inspection-445-original-20261002.tar.gz": "aaa04a250a73824cd87fc5f5d1967e3a9c64c9a3", + "docs/validation/physical-source-inspection-445-source-20261002.tar.gz": "42e16130424793d78738636891550ea47e0a0385", + "docs/validation/physical-source-inspection-445.rst": "f78b558b9ba96e7edf929b79f11e8a466bc89cab", + "docs/validation/polynomial-library-readiness-473-20261002.rst": "a1b06c23d69dddd9d4522d342b5e98441b338786", + "docs/validation/preparation-admission-355.rst": "8b60f6c38207e46c9e8367c8860a98d1219301f7", + "docs/validation/preparation-admission-evidence/SHA256SUMS": "911a31629c7b34ed2861174802063538de243213", + "docs/validation/preparation-admission-evidence/after-checkpoint.log": "05dd20e693b5e70ea142ac3af17da5e0003fee43", + "docs/validation/preparation-admission-evidence/after-initial.log": "7a5874764f4b5f1e27e3269068dd6ded7c4db024", + "docs/validation/preparation-admission-evidence/after-paired-source.log": "e4d44069d8f9d557db8725849c2439acc6db3be6", + "docs/validation/preparation-admission-evidence/before-with-native-dependency.log": "1d31be76ba4ac92fda55fb77b52a5e75cb638a4c", + "docs/validation/preparation-admission-evidence/before.log": "2ce8ff176b5f84b7150c714a94ec854ce9619176", + "docs/validation/preparation-admission-evidence/manifest.json": "fad0f4df17f59340fac6342b39ff1f9d9a889098", + "docs/validation/preparation-admission-evidence/r0.json.gz": "1f2ad2510301a42496189222c9e3193aa4dd0989", + "docs/validation/preparation-admission-evidence/r0.resources.txt": "3f093ad5f5d386b2adbc8d5fcb981bdd998f5f16", + "docs/validation/preparation-admission-evidence/source-owner-profile.log": "508ba9d9d7a2ee780883e84d3bf7e9b7de52ba07", + "docs/validation/prepared_callable_signatures_419_20261002.rst": "e987dab3b91b681f9bcaefad18546202f7f5f1cb", + "docs/validation/primary_diagnostics_current_main_20260930.rst": "6a65fd57b81bdcc4ffe3877f6879e4240cfe160f", + "docs/validation/pyqt_zmq03_dependency_20260930/README.md": "2effcf4d718d46b9c97f22b514131450b8b4979b", + "docs/validation/pyqt_zmq03_dependency_20260930/normal-resolving-install.log": "6bc205ab6fca1a701c4fb986a16c0ff1c29a8be9", + "docs/validation/pyqt_zmq03_dependency_20260930/openhcs-consumers.log": "4f0395dee63513f763b6445d78fbda0dcd37ed65", + "docs/validation/pyqt_zmq03_dependency_20260930/pyqt-consumers.log": "90f8b4f16be29da332b468fee80890d99eb9975d", + "docs/validation/pyqt_zmq03_dependency_20260930/resolver-counterexample.log": "fe3b3ab9c647b8141bc6012a91df9c851c9c3470", + "docs/validation/r0-policy-fixture-invocation-20261002/CLI-SOURCE.py": "e601cb9ce16da8b4554eeaf87345094815f6e829", + "docs/validation/r0-policy-fixture-invocation-20261002/PLAN.rst": "a2ebe0339e946b1fc3aa831a5bfa6cd61f571f79", + "docs/validation/r0-policy-fixture-invocation-20261002/RECEIPT.rst": "f302bd77586f376c41f09495bb8fe0e980d7ad5f", + "docs/validation/registered-object-output-categorical03-20261003.tar.gz": "4b485a0e1f7bccccaa608b58fea9606436a67ae4", + "docs/validation/registered-object-output-categorical95-20261003.tar.gz": "563455dc8b3e66b8b2680cc83152d0b03bf5ae65", + "docs/validation/registered-object-output-installed-20261003.tar.gz": "22f2037597697d0208edb85c3989b04086b639d3", + "docs/validation/registered-object-output-public04-accepted-20261003.tar.gz": "c2d075d899036eaa6ebd576c96f188eb3442e9e5", + "docs/validation/registered-object-output-public95-20261003.tar.gz": "df9564734c84e14558ab87f99efed79e95242ead", + "docs/validation/registered-object-output-scalar04-20261003.tar.gz": "08f7147bd3115421b3e28831b7c3079cbabd6292", + "docs/validation/registered-object-output-source-20261003.tar.gz": "90abba6a5f6faa6f8418424eec0978d1b69475c7", + "docs/validation/registered-object-output-split95-20261003.tar.gz": "c99da45b3e7c8ba17f5015daea7461bf83113544", + "docs/validation/registered-object-output-working-20261003.tar.gz": "1997e9a84a3f43f323252bb4feccb9884cf7384d", + "docs/validation/registered_object_output_boundaries_20261003.rst": "836d3070db48f93600732f94581437b92ef49539", + "docs/validation/run_metadata_namespace_327.py": "c5811c1f78683a95cc6d259fedbb801cf929e8f0", + "docs/validation/runtime_bootstrap_20260930.md": "6ca6e264997e9f36e8aeb0e410cd95b1007ae52a", + "docs/validation/runtime_bootstrap_20260930/close-dependency-census.json": "cc2af236d1bab57fe723c2cf4daeae446fbfc319", + "docs/validation/runtime_bootstrap_20260930/close-dependency-census.txt": "f3641a0f906abd40c591c85a7daa1cc8027aeab5", + "docs/validation/runtime_bootstrap_20260930/close-source-census.json": "7ef88093cf291976df551e9173b2698c55697178", + "docs/validation/runtime_bootstrap_20260930/close-source-census.txt": "c4827ff49ef96da0166a922b79ea44815537cec4", + "docs/validation/runtime_bootstrap_20260930/dependency-census.json": "d5167ec1f06443e4c6478e888ddbdd68fa2c16ec", + "docs/validation/runtime_bootstrap_20260930/dependency-census.txt": "ea316a4d756eaeb11edb180f3f8635866c9432c2", + "docs/validation/runtime_bootstrap_20260930/effective-transport/checkpoint.md": "dff016387d14d72c15b7015d1e2c55262abb57bc", + "docs/validation/runtime_bootstrap_20260930/effective-transport/parent-witness.txt": "d2c25899c45e48be81858ccb0e67ec3259e193cd", + "docs/validation/runtime_bootstrap_20260930/effective-transport/source-tests-b.xml": "90b84977426308d0281a2b78377b64d7673d5249", + "docs/validation/runtime_bootstrap_20260930/effective-transport/source-tests.xml": "0d7564bcb3a2cf1397ceba15733b8530e0bd5d36", + "docs/validation/runtime_bootstrap_20260930/launch-plan-factoring/checkpoint.md": "570233428716019df69bc7214073856485539fb4", + "docs/validation/runtime_bootstrap_20260930/launch-plan-factoring/source-tests-b.xml": "3e319d1ba111689e13123a42286c3cb96969e5ec", + "docs/validation/runtime_bootstrap_20260930/launch-plan-factoring/source-tests.xml": "ef92711f5d7dbbb153ffd7f1a4c2b689b50023ca", + "docs/validation/runtime_bootstrap_20260930/native-attempt01/build.txt": "b0d6aff4fe7699a9a251162cc7ac2544e100e524", + "docs/validation/runtime_bootstrap_20260930/native-attempt01/checkpoint.md": "16cc31aaacbe213eb995eb15bd5cb58ac684f8c1", + "docs/validation/runtime_bootstrap_20260930/native-attempt01/journey.json": "cc9bf7bafbd142de0ae6cab64122f53c0bd02a7a", + "docs/validation/runtime_bootstrap_20260930/native-attempt01/mcp-stderr.txt": "ca517f933b9788cf76a8dc7c1e2a8c2b92426847", + "docs/validation/runtime_bootstrap_20260930/native-attempt01/pipeline.py": "2872892f8254ea6b88d0e1efbb7f7aecdb4c897b", + "docs/validation/runtime_bootstrap_20260930/native-attempt02/build.txt": "6b34b579eb65f33519a4ed908d064d368d9c814e", + "docs/validation/runtime_bootstrap_20260930/native-attempt02/checkpoint.md": "61518ced9e95c57d28f3d769c8557727f75d7774", + "docs/validation/runtime_bootstrap_20260930/native-attempt02/journey.json": "21668791073aac5fc4b78917e021850894d9624b", + "docs/validation/runtime_bootstrap_20260930/native-attempt02/mcp-stderr.txt": "592433884d187f541fca263a42228249f6976fbd", + "docs/validation/runtime_bootstrap_20260930/native-attempt02/owned/data/openhcs/logs/openhcs_zmq_server_port_5964_1790754393037041240.log": "97f28af65b2dc6adbbff3f06b4e6304a3312dc93", + "docs/validation/runtime_bootstrap_20260930/native-attempt02/owned/data/openhcs/logs/openhcs_zmq_server_port_5964_1790754393037041240.startup.jsonl": "367d70e1ddfc889f5f0f994f99d4d924aa0b7c55", + "docs/validation/runtime_bootstrap_20260930/native-attempt02/pipeline.py": "66468189fff3aea7e22a0347ed924c93b338f6d4", + "docs/validation/runtime_bootstrap_20260930/native-attempt03/build.txt": "c21bcf6297db51561a91ff8be44998fd544d13cb", + "docs/validation/runtime_bootstrap_20260930/native-attempt03/checkpoint.md": "c58f54d249ca8b9d5c5c9cbc0572127c3689c983", + "docs/validation/runtime_bootstrap_20260930/native-attempt03/inspect_volume_fixture_v2.py": "8d89630cc331f58a84b149bc1972f5b93fffb257", + "docs/validation/runtime_bootstrap_20260930/native-attempt03/journey.json": "b0bdf59c8196c7b5609ee47f383431b8f5205251", + "docs/validation/runtime_bootstrap_20260930/native-attempt03/mcp-stderr.txt": "e69de29bb2d1d6434b8b29ae775ad8c2e48c5391", + "docs/validation/runtime_bootstrap_20260930/native-attempt03/owned/data/openhcs/logs/openhcs_zmq_server_port_5965_1790758999303299469.log": "ee86a18d35f73c27cdfc223e527efb272502b8a1", + "docs/validation/runtime_bootstrap_20260930/native-attempt03/owned/data/openhcs/logs/openhcs_zmq_server_port_5965_1790758999303299469.startup.jsonl": "b0d01bd9b7e0b958163ff1ca96898faef47b5930", + "docs/validation/runtime_bootstrap_20260930/native-attempt03/select_volume_fixture_planes_v2.py": "9ffae9cc867d25517ec0db4190559af521067bca", + "docs/validation/runtime_bootstrap_20260930/native-owner-tests-b.xml": "373d16afb7d0c80dd072253c60c59acd20ee4499", + "docs/validation/runtime_bootstrap_20260930/native-owner-tests.xml": "d5f41caf8b56660204555746e1218f88c2545a7c", + "docs/validation/runtime_bootstrap_20260930/owner-factoring-checkpoint.md": "bd19c8cdedac8b5b58da18fa74ec1eb6d016b986", + "docs/validation/runtime_bootstrap_20260930/owner-factoring-ratchet-resources.txt": "1404eb0e547cac7f8fc12978786edfd3e764db87", + "docs/validation/runtime_bootstrap_20260930/owner-factoring-ratchet.json": "a3cfb179d7f4cf5dcf6d9cb0cf61a18fc50d0a67", + "docs/validation/runtime_bootstrap_20260930/owner-factoring-source-tests-b.xml": "65d87d542477d5e98698b03f20b4194b0cdca771", + "docs/validation/runtime_bootstrap_20260930/owner-factoring-source-tests.xml": "0334221ad8d6d7f7a3559ddc977d5295792a53fb", + "docs/validation/runtime_bootstrap_20260930/paired-native-owner-checkpoint.md": "1df91d486b53b15dd0bc70589ef953e4b7e35356", + "docs/validation/runtime_bootstrap_20260930/paired-owner-source-tests.xml": "54929c5cd715cbfdbc4b4aa00405b9a1ac77de03", + "docs/validation/runtime_bootstrap_20260930/paired-pin-handoff.md": "6ba5105c6c2db19804d729acdb746626dfe0386c", + "docs/validation/runtime_bootstrap_20260930/paired-pin-source-resources.txt": "df43decc13b9b8cba6d081b15f7f97b7cd39e913", + "docs/validation/runtime_bootstrap_20260930/paired-pin-source-tests.xml": "4303fdfbff3a99dc9ceb244dad86f850788b5af1", + "docs/validation/runtime_bootstrap_20260930/parent-main-integration/checkpoint.rst": "a47d6a1c7018214abba7ab82827d445f88c5e0a9", + "docs/validation/runtime_bootstrap_20260930/parent-main-integration/native-build.log": "330b8da57c1e9b23ba9b11a775d9372b0620a402", + "docs/validation/runtime_bootstrap_20260930/parent-main-integration/ratchet-resources.txt": "075cfdf68740c526762a59d5c084e87c9ecbcfef", + "docs/validation/runtime_bootstrap_20260930/parent-main-integration/ratchet.json": "c4ee3670c841481bb3d934d20344425783b13ed5", + "docs/validation/runtime_bootstrap_20260930/parent-main-integration/run-source-check.sh": "fe37cdd037920a6455afd274ca4e3fb4907bd64d", + "docs/validation/runtime_bootstrap_20260930/parent-main-integration/source-tests-native-built.log": "273ca3c96373fdecaecd5ed80d0b17a229880815", + "docs/validation/runtime_bootstrap_20260930/parent-main-integration/source-tests-native-built.xml": "9152ebb3b6799d5c1d5925868f7f2e01c3890cb4", + "docs/validation/runtime_bootstrap_20260930/parent-main-integration/source-tests.log": "edfbce2c41d567076236915d8fc0ea032e0c6ffd", + "docs/validation/runtime_bootstrap_20260930/parent-main-integration/source-tests.xml": "18f86e293c6ab762368b0f395b716a87abce2594", + "docs/validation/runtime_bootstrap_20260930/pr-body.md": "ccee14e64209f0d9cea2c0fff13a5d39fa2d2fda", + "docs/validation/runtime_bootstrap_20260930/pre-spawn-rollback/checkpoint.md": "321d259f44da9847f72a805085e37f8a18d9e571", + "docs/validation/runtime_bootstrap_20260930/pre-spawn-rollback/combined-resources.txt": "9ed8a88f427a2ca9f5f6ff8adf5a77808836c8a6", + "docs/validation/runtime_bootstrap_20260930/pre-spawn-rollback/combined-tests.txt": "017a6cb772097bb700fef2e198a9f6c578108f42", + "docs/validation/runtime_bootstrap_20260930/pre-spawn-rollback/dependency-initial-resources.txt": "46728632f1e8a841633fd94f7cc8c5041a0e34b4", + "docs/validation/runtime_bootstrap_20260930/pre-spawn-rollback/dependency-initial-tests.txt": "961d59015dca03b62e11d3e7bf6093cc9abd1fcf", + "docs/validation/runtime_bootstrap_20260930/pre-spawn-rollback/dependency-resources.txt": "cc0ae92337496dd2b92a59067353f0946f894ca6", + "docs/validation/runtime_bootstrap_20260930/pre-spawn-rollback/dependency-tests.txt": "e271aec270b4cef4168cf7e41bbf232b204d2807", + "docs/validation/runtime_bootstrap_20260930/pre-spawn-rollback/zmq-pr-body.md": "214b20a269b2bcfd2784e745d8937546d11809c1", + "docs/validation/runtime_bootstrap_20260930/projection-attempt03-preparation.md": "934e797f60d3d89a830fd8ab7b04f0b126dd57c8", + "docs/validation/runtime_bootstrap_20260930/r0-ratchet-before-resources.txt": "38a357812ddd7963c42e4b6b40a0249fc17893d5", + "docs/validation/runtime_bootstrap_20260930/r0-ratchet-before.json": "280dafe2978b56a7819c10a9d7af27f17288e9d7", + "docs/validation/runtime_bootstrap_20260930/reserved-child-takeover/after-resources.txt": "cf24b472a39330f25da9b8a1040d34ce1f917cc5", + "docs/validation/runtime_bootstrap_20260930/reserved-child-takeover/after-tests.log": "38c39ad4f3a2a649f2455460ffcdc38137729c29", + "docs/validation/runtime_bootstrap_20260930/reserved-child-takeover/after-tests.xml": "cf6d08018f12208f03046d4a41fe075d76d41ba2", + "docs/validation/runtime_bootstrap_20260930/reserved-child-takeover/before-corrected-resources.txt": "8c45933a072db3415df96d3cdf016a3dea2ae6ae", + "docs/validation/runtime_bootstrap_20260930/reserved-child-takeover/before-corrected-tests.log": "16925a458c5d1f09155b6af76cea189c73e74b6a", + "docs/validation/runtime_bootstrap_20260930/reserved-child-takeover/before-corrected-tests.xml": "e78c93b030fece092757149383231edb16d18288", + "docs/validation/runtime_bootstrap_20260930/reserved-child-takeover/before-resources.txt": "a9fe891dd334a9cf2ddeea7cb73eea164b547aad", + "docs/validation/runtime_bootstrap_20260930/reserved-child-takeover/before-tests.log": "dd4c18fc74a01ff023a12eedb64dd2e27019b08d", + "docs/validation/runtime_bootstrap_20260930/reserved-child-takeover/before-tests.xml": "db7f6d5c9fb6c70308fb8dab21ef6f121feb566c", + "docs/validation/runtime_bootstrap_20260930/reserved-child-takeover/checkpoint.rst": "6ce1e1f00a24997a547cd0f7aad7845df475b26e", + "docs/validation/runtime_bootstrap_20260930/reserved-child-takeover/pr256-body.md": "c773b5b3196af0207655b244db1d8ea43d5e8ec8", + "docs/validation/runtime_bootstrap_20260930/reserved-child-takeover/pr9-body.md": "4fdbff385553cb9327a41889f8df7c531a415683", + "docs/validation/runtime_bootstrap_20260930/source-census.json": "78310e9c93058de0c820b2998f7c3d3bf1328521", + "docs/validation/runtime_bootstrap_20260930/source-census.txt": "8eda50d914bb26deb3fd3919d558022009f08556", + "docs/validation/runtime_bootstrap_20260930/source-close-122-resources.txt": "f8747c95f5a762ac66b3e1ebb81c73579b022528", + "docs/validation/runtime_bootstrap_20260930/source-close-122.txt": "275d1d8ef135185545d8609d39dd20fd538a4884", + "docs/validation/runtime_bootstrap_20260930/source-close-final-resources.txt": "ce8669d67f1ab48ce3920bbdd461fe8a22e88137", + "docs/validation/runtime_bootstrap_20260930/source-close-final.txt": "38db049079337c42d13ea6a2ba5076ff7dcc32e1", + "docs/validation/runtime_bootstrap_20260930/source-close-fixtures-resources.txt": "2a2b4e7d2268af365a9ddf161a213f4b0d21a54a", + "docs/validation/runtime_bootstrap_20260930/source-close-fixtures.txt": "c9df67d54d6541585ff62b611a14f302510dfc5c", + "docs/validation/runtime_bootstrap_20260930/source-close-initial-resources.txt": "f5c8d6f803dc6a5253e33b29e1354c7a12e3832d", + "docs/validation/runtime_bootstrap_20260930/source-close-initial.txt": "2c499ebc6892c48a3f543e99a6698956e2f86114", + "docs/validation/runtime_bootstrap_20260930/source-close-resources.txt": "aa50b3ffb9046f5a60e9b1b5756b8b89188d5d00", + "docs/validation/runtime_bootstrap_20260930/source-close-wire-fixtures-resources.txt": "2c79f55227db91a82c7703b5812728fa8440af42", + "docs/validation/runtime_bootstrap_20260930/source-close-wire-fixtures.txt": "1157b4a179a25dc309ea8aa747cfa7b75b6f7a42", + "docs/validation/runtime_bootstrap_20260930/source-close.txt": "5756a47cf9bd82ca3a0baf948f22d858182750c7", + "docs/validation/runtime_bootstrap_20260930/source-hardening-resources.txt": "3c94c2faa1461bd116e019854df810402d4b3e6b", + "docs/validation/runtime_bootstrap_20260930/source-hardening.txt": "07107201b0537718e5e1083709659a9243d87a50", + "docs/validation/runtime_bootstrap_20260930/source-test-resources.txt": "c54f1ee47e2b00697eeadfecd9fadd620c3ccad4", + "docs/validation/runtime_bootstrap_20260930/source-tests.txt": "c544751de60fc35cd50f81d3f5c67f9672b91915", + "docs/validation/runtime_bootstrap_20260930/viewer-main-source-resources.txt": "2576dca7141c581017988b6e9e7d5aa09283e220", + "docs/validation/runtime_bootstrap_20260930/viewer-main-source-tests.xml": "b79b9b01cd2f8e84d52c4b2005a32f16c5ae8fab", + "docs/validation/runtime_bootstrap_20260930/viewer-merged-source-resources.txt": "b657651f041de5a4589cff4e9ba29905e070f517", + "docs/validation/runtime_bootstrap_20260930/viewer-merged-source-tests.xml": "8787d51722de8d08ab3b4b311ab94110afeefa1e", + "docs/validation/runtime_fixture_sync_387_20261001/RECEIPT.rst": "4b5fcae674b70309072814bc91573ef97e21b74b", + "docs/validation/runtime_fixture_sync_387_20261001/SHA256SUMS": "a4783d90dc58f553f5429a0126b7f21598011128", + "docs/validation/runtime_fixture_sync_387_20261001/pytest_evidence.tgz": "182b99251992b19fe5546663ddab183bcc7193ca", + "docs/validation/runtime_owner_sync_323_20261001.rst": "9179812109e25e5c122e08bf7a635db7e8e5b5b8", + "docs/validation/runtime_owner_sync_323_evidence_20261001.tgz": "65704fb6b7ddab59afbf83525898bcbf370598ff", + "docs/validation/s1_typed_viewer_20261001/NATIVE-RECORDS-ARCHIVE-MEMBERS.txt": "241a927f9dc976613330da2536c8df4944b0ecf2", + "docs/validation/s1_typed_viewer_20261001/NATIVE-RECORDS-ARCHIVE-SHA256SUM": "06992c747a033d5e3595bdaa7ae9132a5640b580", + "docs/validation/s1_typed_viewer_20261001/NATIVE-RECORDS-INCREMENT.rst": "de67df9abed42e110ffdcc80e5590244bda047e8", + "docs/validation/s1_typed_viewer_20261001/NATIVE-RECORDS-RECEIVING.rst": "b6fafe2874d43a55a8d16795765729cdcc8d22bf", + "docs/validation/s1_typed_viewer_20261001/NATIVE-RECORDS-SHA256SUMS": "d130c9872fcdda97b79a7689668259cf561d6524", + "docs/validation/s1_typed_viewer_20261001/NATIVE-RECORDS-SOURCE-SHA256SUMS": "fc4c7bd2a758700fa5ca6b68884d092f8fe45b6a", + "docs/validation/s1_typed_viewer_20261001/PUBLISHED650-QUALIFICATION.rst": "fc0cad39f8b279c441f1d5903aa63e400adf9639", + "docs/validation/s1_typed_viewer_20261001/RECEIVING.rst": "2eeb4afd4f1ad951f42a63b850c4327b89becfdc", + "docs/validation/s1_typed_viewer_20261001/STATE-INCREMENT.rst": "2592bb0983f7f29bf26c9515aa7f7723ee7afb38", + "docs/validation/s1_typed_viewer_20261001/checkpoint-framed-resources.txt": "b6d5c0cd5d9529f900d1d5c8960eb94a95b0a160", + "docs/validation/s1_typed_viewer_20261001/checkpoint-framed.log": "595135b4bc6fa4ac8ef28ea2ed9b72915ed405c8", + "docs/validation/s1_typed_viewer_20261001/checkpoint-framed.xml": "b89f86bb89b3d2a4dd0eb065a10003b16a174434", + "docs/validation/s1_typed_viewer_20261001/checkpoint-resources.txt": "8b74c1b4b38ceb069431f4d19f2c8b4b08e422e7", + "docs/validation/s1_typed_viewer_20261001/checkpoint.log": "77f19a02ed286ca18f3dcc4c91213641db4ffdb6", + "docs/validation/s1_typed_viewer_20261001/checkpoint.xml": "52f42d6489e3392e16eddc84afbd3d60ea31ed76", + "docs/validation/s1_typed_viewer_20261001/native-records-evidence.tar.gz": "9a6fd1d3a408c3efab582acab70e2dc760634054", + "docs/validation/s1_typed_viewer_20261001/original-state-omission-resources.txt": "dcf3775991d891ddfd8006902ac9776bb1a78a45", + "docs/validation/s1_typed_viewer_20261001/original-state-omission.log": "68535cdbf6ed7a176debc4603f78cc2befaaab94", + "docs/validation/s1_typed_viewer_20261001/original-state-omission.xml": "e5d6625b1ac43f147a6ae650dde362ab96c6b68a", + "docs/validation/s1_typed_viewer_20261001/post406-installed-state.json": "628ec0b4a20717cc94c9af00faef6e7e9fa9d0d1", + "docs/validation/s1_typed_viewer_20261001/published34-r0-monitor.log": "862ebc7495da714a4cddc3b20e0cb8724c2a126d", + "docs/validation/s1_typed_viewer_20261001/published34-r0-resources.txt": "e35aaf44a2d6439971ac250f2ede4649b2f326a6", + "docs/validation/s1_typed_viewer_20261001/published34-r0.json.gz": "42fa248963e850084a5e15a00954bca9e7ef1b11", + "docs/validation/s1_typed_viewer_20261001/published34-r0.stderr.txt": "e69de29bb2d1d6434b8b29ae775ad8c2e48c5391", + "docs/validation/s1_typed_viewer_20261001/published650-behavior-guard-resources.txt": "ce4dc0f401c957ab381038d2402d32a2e9a7fd90", + "docs/validation/s1_typed_viewer_20261001/published650-behavior-guard.log": "d36db5155fe2b153859255d0c6ba08d73b361575", + "docs/validation/s1_typed_viewer_20261001/published650-behavior-guard.xml": "1173ea663eedabd0a13af50f54a59620b6243e03", + "docs/validation/s1_typed_viewer_20261001/published650-r0-resources.txt": "100b169ab77c83914b616b2335bec17cda96dd8d", + "docs/validation/s1_typed_viewer_20261001/published650-r0.json.gz": "d711494afb20f3081624d06a520b4b511828d03f", + "docs/validation/s1_typed_viewer_20261001/published650-r0.stderr.txt": "e69de29bb2d1d6434b8b29ae775ad8c2e48c5391", + "docs/validation/s1_typed_viewer_20261001/reproduce_original_state_omission.py": "f6801b08faa0e20914c812766714ec7d680c6e5a", + "docs/validation/s1_typed_viewer_20261001/state-increment-corrected-resources.txt": "bf2c743000a61af3d3712d21b312022399b472d6", + "docs/validation/s1_typed_viewer_20261001/state-increment-corrected.log": "afd659f67964a7ac0e289385d687950d50d18a83", + "docs/validation/s1_typed_viewer_20261001/state-increment-corrected.xml": "1ea8d5b8d00f106b0e22ddc67aea1e023b4b47c4", + "docs/validation/s1_typed_viewer_20261001/state-increment-resources.txt": "74a66dac08309d0cea9e3a13ba676a2f3797d6af", + "docs/validation/s1_typed_viewer_20261001/state-increment.log": "2be4a6e85ccaed4e680e28418d78d79cd97cd3d5", + "docs/validation/s1_typed_viewer_20261001/state-increment.xml": "18375bae4ff5d70b76fa0ea4e0341e4eb4272268", + "docs/validation/s1_typed_viewer_20261001/state294-r0-monitor.log": "f7a60b9dc5575d66d4ded85934a7eae7bfc3285a", + "docs/validation/s1_typed_viewer_20261001/state294-r0-resources.txt": "a240c3958d4b8a51ad51ab772e27deffde951c6c", + "docs/validation/s1_typed_viewer_20261001/state294-r0.json.gz": "60994794eb31bacc43cf67977c46aceb7d561be8", + "docs/validation/s1_typed_viewer_20261001/state294-r0.stderr.txt": "e69de29bb2d1d6434b8b29ae775ad8c2e48c5391", + "docs/validation/s1_typed_viewer_20261001/state294-r1-monitor.log": "0209bee5e9027650cf1273db7cfcd0bd9d675f51", + "docs/validation/s1_typed_viewer_20261001/state294-r1-resources.txt": "ef338765487ba9891073e7729f565ae96dbe68cf", + "docs/validation/s1_typed_viewer_20261001/state294-r1.json": "e69de29bb2d1d6434b8b29ae775ad8c2e48c5391", + "docs/validation/s1_typed_viewer_20261001/state294-r1.stderr.txt": "ab09c3ebb1356cd02a2ddf9e4f13282eeac2ba68", + "docs/validation/saved-label-plane-domain-419-20261002/COMMANDS.rst": "385c712a83a98d616761dd5eda82bb2b097924b0", + "docs/validation/saved-label-plane-domain-419-20261002/RECEIPT.rst": "492dc048d7585598757432b7c6a37329e0a1c463", + "docs/validation/saved-label-plane-domain-419-20261002/adjacent-controls.log": "217db116620257f55d58b81663c88e8785c1d25b", + "docs/validation/saved-label-plane-domain-419-20261002/adjacent-controls.xml": "88de603f5597a8165d44f967a139af49893a56e9", + "docs/validation/saved-label-plane-domain-419-20261002/distance-original-red.log": "0935b82fd8a52ae802d79f7507e85f19bb395ed1", + "docs/validation/saved-label-plane-domain-419-20261002/distance-original-red.xml": "1b50b9250c47c06161de8b20dfa255c903125e97", + "docs/validation/saved-label-plane-domain-419-20261002/final-owner-controls.log": "0633afc7cd25a953f56f56666c48cb48b58abf4f", + "docs/validation/saved-label-plane-domain-419-20261002/final-owner-controls.xml": "1af5068e03712169271c089ea5a4f69391f7bbe8", + "docs/validation/saved-label-plane-domain-419-20261002/geometry-and-runtime-values.log": "85672c40e5d041b16c369b9a0f3f20adf45312a8", + "docs/validation/saved-label-plane-domain-419-20261002/geometry-and-runtime-values.xml": "b711aac3c208935e3eebd695afc6bc36f6ed012e", + "docs/validation/saved-label-plane-domain-419-20261002/geometry-focused-corrected.log": "67961abd2ebf88f506d7b181fd99b564f0764d94", + "docs/validation/saved-label-plane-domain-419-20261002/geometry-focused-corrected.xml": "cf1cbc8bf10904f6fbdb82255c9573b255c86e2c", + "docs/validation/saved-label-plane-domain-419-20261002/geometry-focused.log": "bd808eea17d64a6f1d16ed412a90845d629b04d2", + "docs/validation/saved-label-plane-domain-419-20261002/geometry-focused.xml": "2c5220952da545f94ce019b0db3cbbbc2701a1d2", + "docs/validation/saved-label-plane-domain-419-20261002/metadata-owner-proposal.patch": "a58137aae0915104f871e92176478f57eef74dac", + "docs/validation/saved-label-plane-domain-419-20261002/original-red.log": "f0a4d63621aa6fbbd7af1f2223a40c0329a56c43", + "docs/validation/saved-label-plane-domain-419-20261002/original-red.xml": "0ea07a91ad7faa482ebde026158d10888e1f6e01", + "docs/validation/saved-label-plane-domain-419-20261002/projection-owner-controls.log": "94c17b5c289c2ebbd8ed5c6a663b7952d7b78193", + "docs/validation/saved-label-plane-domain-419-20261002/projection-owner-controls.xml": "edffba841649a5809631acfcf5b10d3941f013c7", + "docs/validation/saved-label-plane-domain-419-20261002/r0-final-production.log.gz": "0afc257ae98b5428acc92f911c12350df879c1d1", + "docs/validation/saved-label-plane-domain-419-20261002/r0-original-pin.log.gz": "e02043a93a49a6de57bab11f5fd1b7f86c3bbf25", + "docs/validation/saved-label-plane-domain-419-20261002/r0-unapplied-metadata-proposal.log": "53c0e7f55a14d605b2a68715a0bfacbf4ee2f240", + "docs/validation/saved-label-plane-domain-419-20261002/r0-unapplied-proposal-commit.log.gz": "16cf8a7b0eed1052267dae69040d95e649c9fe4d", + "docs/validation/selected-discovery-evidence/INTEGRATION-R0-UNCOMPRESSED-SHA256SUMS": "60ab702ea6a83acb95041aa3e63d6f9b06ab0686", + "docs/validation/selected-discovery-evidence/INTEGRATION-SHA256SUMS": "a82e500d504cdd966ae453e82e483d2a727e1634", + "docs/validation/selected-discovery-evidence/POST409-R0-UNCOMPRESSED-SHA256SUMS": "a2982775f4cd29ae57ae917beb12cb240c4019a0", + "docs/validation/selected-discovery-evidence/POST409-SHA256SUMS": "6f7204ea783b9c90b93eb5581beb66381c355045", + "docs/validation/selected-discovery-evidence/R0-UNCOMPRESSED-SHA256SUMS": "53874490e7062142ca36733e8cd97d7a69a7d95b", + "docs/validation/selected-discovery-evidence/SHA256SUMS": "9c09ab29b9d225c295cf5b574b14ec7e726c42ba", + "docs/validation/selected-discovery-evidence/batched-source.log": "49ea4edb76ce4e644624e66a13b4b2e7e5d95bc0", + "docs/validation/selected-discovery-evidence/dependency-r0-final.json.gz": "a9ec6a671edb44f90c00b4f966e09e0d89d43887", + "docs/validation/selected-discovery-evidence/dependency-r0-final.resources.txt": "0c3c98ac15d07852f987d3542c5b74160c8cb2c4", + "docs/validation/selected-discovery-evidence/dependency-r0.json.gz": "e272aac8d8cf7a791c19a1fb238801a988a0cba5", + "docs/validation/selected-discovery-evidence/dependency-r0.resources.txt": "793a1a8fe61e2737f243b83342e81c76deb0bdad", + "docs/validation/selected-discovery-evidence/final-cold-profile.log": "8290ce24ed1121d87377ce042caf2a0ca808057a", + "docs/validation/selected-discovery-evidence/final-focused-source.log": "18a634a74c7cc7e56acbd2a3cab7f1ca1299d123", + "docs/validation/selected-discovery-evidence/final-owner-source.log": "2fc3df39ad80b65d98e701f1008262711abbab76", + "docs/validation/selected-discovery-evidence/final-source.log": "3113156d5731e814300e01facaf145da706772a0", + "docs/validation/selected-discovery-evidence/first-source.log": "0bfd077db4a182f2260a745f248bf8916e31f063", + "docs/validation/selected-discovery-evidence/integration-376-commands.sh": "c2477afd71c77dc44051383e624fdc2b46bbd26f", + "docs/validation/selected-discovery-evidence/integration-dependency-r0.json.gz": "32cc0253c8443f42edc87b6836331d345341495c", + "docs/validation/selected-discovery-evidence/integration-dependency-r0.resources.txt": "a4009ff8c023c68d1b96ad1c7db551975dd76032", + "docs/validation/selected-discovery-evidence/integration-focused-source.log": "5ac12e45098d2dc19b73590396760adc290ba26e", + "docs/validation/selected-discovery-evidence/integration-openhcs-r0.json.gz": "5a0bfb4d8da3bd5caec78476a7f2cfe7f292fdc9", + "docs/validation/selected-discovery-evidence/integration-openhcs-r0.resources.txt": "b6636aee03c140cce4b459dd40330a85eeabc02e", + "docs/validation/selected-discovery-evidence/openhcs-r0-final.json.gz": "f0c8ef0b51f6c7e515643b23e7c39029c9107746", + "docs/validation/selected-discovery-evidence/openhcs-r0-final.resources.txt": "d8426f591c0ab26776f5552c3210a50094a79ea1", + "docs/validation/selected-discovery-evidence/openhcs-r0-rejected-24a.json.gz": "1b827134822a8c7bd98b9efcc714f6c799ececd8", + "docs/validation/selected-discovery-evidence/openhcs-r0-rejected-24a.resources.txt": "954f53d05babb60b291f94aad2fb431a37a50671", + "docs/validation/selected-discovery-evidence/openhcs-r0-rejected-5fd.json.gz": "c2efbf879d45865162dc6b9251e7b95a18bb09e0", + "docs/validation/selected-discovery-evidence/openhcs-r0-rejected-5fd.resources.txt": "e0de745d2076531d1262f875a0fe1d1e27240eb0", + "docs/validation/selected-discovery-evidence/owner-source.log": "9eacde31351bcf8c9441d52cd955149e1959d79d", + "docs/validation/selected-discovery-evidence/post409-focused-source.log": "ed8f481e215212d842e746a92da29e279503fd7a", + "docs/validation/selected-discovery-evidence/post409-openhcs-r0.json.gz": "28282d69330b9a72bc433ee010907e3321df81bc", + "docs/validation/selected-discovery-evidence/post409-openhcs-r0.resources.txt": "b6b29f817cca798b6a9b9bced7a4c81f89920de2", + "docs/validation/selected-discovery-evidence/real-callable-newcase.log": "b8242db498b0e06ec73ebf6969e36604b3e6475c", + "docs/validation/selected-discovery-evidence/retrieval-admission-newcase.log": "c3fd2c3424ec4cd778dc34299ac7f849a7812d21", + "docs/validation/selected-discovery-evidence/second-source.log": "1e857c7fe4cca32c83e3c755434f4485cbcfd11b", + "docs/validation/selected-discovery-evidence/selected-cold-profile.log": "5ad0bba48e610bb72bbea10e98416e5503fb5aea", + "docs/validation/selected-discovery-evidence/source-roundtrip-newcase.log": "055310a63fdd0179556bceb57ed65c0242ccdde0", + "docs/validation/selected-discovery-release-022-SHA256SUMS": "2b860575ffbd1824e023d30f8bbd1d0331b5a19c", + "docs/validation/selected-discovery-release-022-dependency-r0.json": "f94be654ceabe530c9e9d1e9da090695b41caf0e", + "docs/validation/selected-discovery-release-022-dependency-r0.resources.txt": "0ed151cf0d9223295ad2bf784611ad0636c024e7", + "docs/validation/selected-discovery-release-022-probe.json": "3ba6ce3299d8b79bcb2286bb8cee1c0a7fa0f7b4", + "docs/validation/selected-discovery-release-022-probe.resources.txt": "6ab52a7ac2358ce27eb00b2ac5877ba1ad4231d5", + "docs/validation/selected-discovery-release-022-source.log": "a01d698b541773b2eb42900a0498c9d61e8ff70e", + "docs/validation/selected-discovery-release-022.rst": "b0dd34398fba8d42e12bd24791bf6a4a5e7bca77", + "docs/validation/selected_plane_reopen_stream_20261001/ARCHIVE_COMPARE.txt": "81fb9e59f5e1631ae07e37084d63c963ba8dfe07", + "docs/validation/selected_plane_reopen_stream_20261001/ARCHIVE_SHA256.txt": "633fea014f2c1034c83388825dff1833cf46ef45", + "docs/validation/selected_plane_reopen_stream_20261001/MANIFEST.json": "279f3d06cead04b99703bd40cff90ff947ec6dec", + "docs/validation/selected_plane_reopen_stream_20261001/RAW_EVIDENCE_SHA256.txt": "8b4193e2d0be8039f4fcfaab3c51a0c914a42418", + "docs/validation/selected_plane_reopen_stream_20261001/RECEIPT.rst": "fdbc750541d375d0a3a684760094b21615a6495e", + "docs/validation/selected_plane_reopen_stream_20261001/pr.md": "c2aea34186795575d3d8df8203374d74c628a24b", + "docs/validation/selected_plane_reopen_stream_20261001/raw-evidence.tar.gz": "45169b39d8b20c583d8596c437c410d242b19ba8", + "docs/validation/selected_plane_stream_materialization_20261001/RECEIPT.rst": "5a4f1fbc52b9ec93947210eb4c552f9bfe2ae629", + "docs/validation/selected_plane_stream_materialization_20261001/bounded-cellprofiler-stack-resources.txt": "e1a283237d800b18ab4a1b65792e78c9d4ff278c", + "docs/validation/selected_plane_stream_materialization_20261001/bounded-cellprofiler-stack.log": "bc31f99cc1de8fc0fa90c9a1689affe1b25e3de6", + "docs/validation/selected_plane_stream_materialization_20261001/bounded-cellprofiler-stack.xml": "1d4c75f08c042b7bd161141d05c2a51d635b89b9", + "docs/validation/selected_plane_stream_materialization_20261001/bounded-current-focused-resources.txt": "b84393e1e529b0e2baaa1c2a47820ce6a0d13d6f", + "docs/validation/selected_plane_stream_materialization_20261001/bounded-current-focused.log": "16a0e9858bcec8f8f9ac792cf0179d3e2fb793bb", + "docs/validation/selected_plane_stream_materialization_20261001/bounded-current-main-controls-resources.txt": "fff95ca06e667bdb4a2ecea8392ad698a0ab7b32", + "docs/validation/selected_plane_stream_materialization_20261001/bounded-current-main-controls.log": "fc4c79d4c0a3563778f6dab8c2fb09fb2bf602f7", + "docs/validation/selected_plane_stream_materialization_20261001/bounded-current-main-controls.xml": "cbd0d08ecf02731548109cd909db9c07bfe32b6f", + "docs/validation/selected_plane_stream_materialization_20261001/bounded-function-artifacts-resources.txt": "d728112daf14889aefdd378dc574ff0b6ec41348", + "docs/validation/selected_plane_stream_materialization_20261001/bounded-function-artifacts.log": "c214af2e137b6f7af6c3f1f498a3c72ad14eeb17", + "docs/validation/selected_plane_stream_materialization_20261001/bounded-function-artifacts.xml": "b6693849fecb1535d219630ae1d2a0a0f9e9c205", + "docs/validation/selected_plane_stream_materialization_20261001/bounded-image-contracts-resources.txt": "ece83ad94f83b6ee1cd5ef13ed824779bb98f3a1", + "docs/validation/selected_plane_stream_materialization_20261001/bounded-image-contracts.log": "813e428658b44e0ba9be66aa3e267371b2b96e03", + "docs/validation/selected_plane_stream_materialization_20261001/bounded-image-contracts.xml": "8cee761c14c1235f15a11e21c12a5bc65301491f", + "docs/validation/selected_plane_stream_materialization_20261001/bounded-main-qualified-resources.txt": "b1669d6bd307795ba1d877d9a637a2dae578cef7", + "docs/validation/selected_plane_stream_materialization_20261001/bounded-main-qualified.log": "723253fde729c23d90511be8897716e31480aba5", + "docs/validation/selected_plane_stream_materialization_20261001/bounded-materialization-core-resources.txt": "351afbcfb2ab7c57d9f75b5bffdd1044a864afdc", + "docs/validation/selected_plane_stream_materialization_20261001/bounded-materialization-core.log": "60e90ebf74deac34629a5cb54f1b6dbe12142897", + "docs/validation/selected_plane_stream_materialization_20261001/bounded-materialization-core.xml": "c91c6cd297d75ca49cf0ecab55221f8bd45dfdd2", + "docs/validation/selected_plane_stream_materialization_20261001/bounded-materialization-resources.txt": "606ad5e0be4db00f8d3c3575ade1ab6d364d1c61", + "docs/validation/selected_plane_stream_materialization_20261001/bounded-materialization.log": "85d6a6f805c92fcaa6a820eee1857e95f1190aa2", + "docs/validation/selected_plane_stream_materialization_20261001/bounded-no-autoload-resources.txt": "4ad4fd312796f97de5af39a735927d88a83b239c", + "docs/validation/selected_plane_stream_materialization_20261001/bounded-no-autoload.log": "9cbbfefc43651f0e3c01de0e67a5fd35045332b1", + "docs/validation/selected_plane_stream_materialization_20261001/bounded-no-autoload.xml": "f0dafe1dd6734ffda06149a6824b6400a4e6642f", + "docs/validation/selected_plane_stream_materialization_20261001/bounded-public-path-resources.txt": "0f98d46222836207950737f5faecd30c724839aa", + "docs/validation/selected_plane_stream_materialization_20261001/bounded-public-path.log": "1bb15d38df56971062ff523d88191959e5153320", + "docs/validation/selected_plane_stream_materialization_20261001/bounded-public-path.xml": "43503c464a26482305a7f9d55cc0bb696067c10a", + "docs/validation/selected_plane_stream_materialization_20261001/bounded-viewer-controls-resources.txt": "d0e09319c1de7474b7ed52287aaa6cbc5751c5f0", + "docs/validation/selected_plane_stream_materialization_20261001/bounded-viewer-controls.log": "79bad4861e84d3c2644ff59695b302e7fe304c2e", + "docs/validation/selected_plane_stream_materialization_20261001/bounded-viewer-controls.xml": "e157e2c382647ff2e2af15237e506b9e6d09ee52", + "docs/validation/selected_plane_stream_materialization_20261001/current-main-controls-resources.txt": "8c4cd9f78f2e45fe22adc6051aa5f50cc8b9f8dd", + "docs/validation/selected_plane_stream_materialization_20261001/current-main-controls.log": "5713da9bacb7187771e12fd4631e357e4788917c", + "docs/validation/selected_plane_stream_materialization_20261001/current-main-controls.xml": "0b5cc2c17847f6090cc8bad5160953eb9dbf998b", + "docs/validation/selected_plane_stream_materialization_20261001/expanded-first-resources.txt": "a12ff8fafb487a27bd201c9e54c1cf8dc6a69a4d", + "docs/validation/selected_plane_stream_materialization_20261001/expanded-first.log": "4d14c3465cbf02f4983037a148c16b472532a1f5", + "docs/validation/selected_plane_stream_materialization_20261001/expanded-first.xml": "3c56c3ff15c998be0486b9ce537b163fbde2b3c9", + "docs/validation/selected_plane_stream_materialization_20261001/expanded-second-resources.txt": "e4d95537a58ac5782157689574da5e108385efdf", + "docs/validation/selected_plane_stream_materialization_20261001/expanded-second.log": "4d0b14aebc15158fe4624c03aeb618c6a9056250", + "docs/validation/selected_plane_stream_materialization_20261001/expanded-second.xml": "a496e2ce72960cfc17c3be5080cb28fc8d95a206", + "docs/validation/selected_plane_stream_materialization_20261001/expanded-third-resources.txt": "7d696a1a3d92f9f6f67ce082253151a58b5d250d", + "docs/validation/selected_plane_stream_materialization_20261001/expanded-third.log": "5025a52217b6d83bb3c96d82c470a96d7384364a", + "docs/validation/selected_plane_stream_materialization_20261001/expanded-third.xml": "c50499837ae490d513f701cf24b89a838434f24c", + "docs/validation/selected_plane_stream_materialization_20261001/green-initial-resources.txt": "3f3bebeefc03122e9a8e1720fbefa2913a29460d", + "docs/validation/selected_plane_stream_materialization_20261001/green-initial.log": "a7bdbf582528708d44165952968985e51072bd7c", + "docs/validation/selected_plane_stream_materialization_20261001/green-initial.xml": "0d83b06f2b7428c6f1eabaff51b50a5aa83068b8", + "docs/validation/selected_plane_stream_materialization_20261001/image-contract-controls-resources.txt": "ba8602a882602d2910a63ef8954850e6da3e6ca6", + "docs/validation/selected_plane_stream_materialization_20261001/image-contract-controls.log": "f6fd70513601458dd44fc35e83037a4d6d8b0aa0", + "docs/validation/selected_plane_stream_materialization_20261001/image-contract-controls.xml": "19adda2ebce593d99c717ccadec12a6dfb718015", + "docs/validation/selected_plane_stream_materialization_20261001/issue.md": "47e58a72d676456c25e7594d3d0ab84140e396c6", + "docs/validation/selected_plane_stream_materialization_20261001/materialization-controls-resources.txt": "1762eb0901fac062c06b9c77db532a0a2b48b566", + "docs/validation/selected_plane_stream_materialization_20261001/materialization-controls.log": "5e2e0d089a7656ba9c710d736bbc28a591e2ae96", + "docs/validation/selected_plane_stream_materialization_20261001/materialization-controls.xml": "327a26d0604c63b1348380bd6ecedf55c6656f55", + "docs/validation/selected_plane_stream_materialization_20261001/neurite-output-base-resources.txt": "9c794e8bdff10ea4be6ff041685cced65230388f", + "docs/validation/selected_plane_stream_materialization_20261001/neurite-output-base.log": "3f08b87b14a77213b0f83c492374c468f547a857", + "docs/validation/selected_plane_stream_materialization_20261001/neurite-output-base.xml": "cf9bb97876c5af58ae1db44fe572364b18482365", + "docs/validation/selected_plane_stream_materialization_20261001/neurite-output-controls-resources.txt": "287eaff2cdcf02267c8f6b38aad70ac945e18cda", + "docs/validation/selected_plane_stream_materialization_20261001/neurite-output-controls.log": "40e4215ac49ca259704922d7629148b0487c0b2b", + "docs/validation/selected_plane_stream_materialization_20261001/neurite-output-controls.xml": "fe937f0df0b09f5153f25bbcadc417f8ad31ef25", + "docs/validation/selected_plane_stream_materialization_20261001/nra-current-full.json": "5f0d0430651f5354ee095da8d8b77bf33363335c", + "docs/validation/selected_plane_stream_materialization_20261001/nra-current-full.stderr.txt": "e69de29bb2d1d6434b8b29ae775ad8c2e48c5391", + "docs/validation/selected_plane_stream_materialization_20261001/nra-current-resources.txt": "7e9334bb4b4dab78f6995a6fb8a582e8af33122e", + "docs/validation/selected_plane_stream_materialization_20261001/pr.md": "cdcf590788576a0358f0dc4e115af6a497c861c5", + "docs/validation/selected_plane_stream_materialization_20261001/r0-current-main-resources.txt": "69f179098bcd29f89a01a6e2ad1df8890bf2462b", + "docs/validation/selected_plane_stream_materialization_20261001/r0-current-main.json": "ca71a7b7840309572d124e2a85f6b248461889d9", + "docs/validation/selected_plane_stream_materialization_20261001/r0-current-main.stderr.txt": "e69de29bb2d1d6434b8b29ae775ad8c2e48c5391", + "docs/validation/selected_plane_stream_materialization_20261001/r0-resources.txt": "b14e0cf66910c7c28150f747bea44cd90194c2d2", + "docs/validation/selected_plane_stream_materialization_20261001/r0.json": "b3b6b60a8cdcbe58c67b242129d4775cf53e3852", + "docs/validation/selected_plane_stream_materialization_20261001/r0.stderr.txt": "e69de29bb2d1d6434b8b29ae775ad8c2e48c5391", + "docs/validation/selected_plane_stream_materialization_20261001/r1-exact-policy-resources.txt": "530d313eb927836acec4ba9511fb02e02ee29581", + "docs/validation/selected_plane_stream_materialization_20261001/r1-exact-policy.json": "e69de29bb2d1d6434b8b29ae775ad8c2e48c5391", + "docs/validation/selected_plane_stream_materialization_20261001/r1-exact-policy.stderr.txt": "2c46a4c72ba4028f03a8cf53d35491a571e94209", + "docs/validation/selected_plane_stream_materialization_20261001/r1-original-resources.txt": "707ed1413918b0c5962f72a5c1b88685209226b8", + "docs/validation/selected_plane_stream_materialization_20261001/r1-original.json": "e69de29bb2d1d6434b8b29ae775ad8c2e48c5391", + "docs/validation/selected_plane_stream_materialization_20261001/r1-original.stderr.txt": "82c013ba078eb9fac0a5915cf9497f17d51f5a18", + "docs/validation/selected_plane_stream_materialization_20261001/red-resources.txt": "37ca748e13d6ebce82aa9b2147f4ac3a29fb6486", + "docs/validation/selected_plane_stream_materialization_20261001/red.log": "803c889307080e402828278706ccc4481c903530", + "docs/validation/selected_plane_stream_materialization_20261001/red.xml": "563f93f39c4019a6c42e1cb7a86ccd5b32492231", + "docs/validation/selected_plane_stream_materialization_20261001/run_bounded_source.py": "d56801d4f9d4fa8cd59a2dc712fa875cfe86d529", + "docs/validation/selected_plane_stream_materialization_20261001/run_original_projection.py": "dae94c422f00893fe30b57dbb6b6452970466669", + "docs/validation/selected_plane_stream_materialization_20261001/validation_summary.json": "b16d35df609780902f22bd44ac32ac976eb6c7d4", + "docs/validation/selected_plane_stream_materialization_20261001/viewer-rejection-controls-resources.txt": "80ce1f2419e748d6afcaba3c8c650f821866ee9e", + "docs/validation/selected_plane_stream_materialization_20261001/viewer-rejection-controls.log": "df1dffe90373aca50b736183443a930d8bf54408", + "docs/validation/selected_plane_stream_materialization_20261001/viewer-rejection-controls.xml": "400984b717426746439ab885e5df490c519837fa", + "docs/validation/shared-dense-coordinate-owner-20261002.rst": "4d865af45f6a5ed0dd88b5fea81f260805d99c70", + "docs/validation/shared-quantized-hull-geometry-20261002.rst": "2760a5d2be84cf452f2504ea107aaaf20600e827", + "docs/validation/shared_runtime_plumbing_384_20261001.rst": "ef9275122450bf2d0b27132c78db9425191487d6", + "docs/validation/singleton-label-invocation-477-20261002.rst": "faad1c18a468a3fdb7324fa6b6a0cf1194bd7efd", + "docs/validation/singleton-label-invocation-main-477-20261002.rst": "1ffb2b32130bc342aa54a5c21557e0b89227503f", + "docs/validation/skill478-distributed-threshold-diagnosis-20261002.rst": "25cfcdf6722eb8406e7d4eed1da069f37a7f3662", + "docs/validation/source-projection-family-20261002.rst": "a73cb632402afd8723e6f45076308110b3de1ce9", + "docs/validation/source_projection_fixtures_20260930.rst": "94e414fcab1e415f782b6c7213b4140b7bfe74b6", + "docs/validation/startup-feedback-358.rst": "11807fe78d670160dbcdabcf7ca36021e0969b7f", + "docs/validation/startup-feedback-evidence/SHA256SUMS": "1700bda0530d87e8e707461c09341f3b3dfb4889", + "docs/validation/startup-feedback-evidence/green-final-feedback.log": "3ac02840d869cb2aeb60cdc65cc4778d8866e2b2", + "docs/validation/startup-feedback-evidence/green-initial.log": "415fe42acdfdd3d29ee0c442e11dd46ede50b285", + "docs/validation/startup-feedback-evidence/green-lifecycle.log": "82fdda617344359633f27452ed2b01879f802180", + "docs/validation/startup-feedback-evidence/green-published.log": "d3b70233618488b24b4ae1c975771d72ed484ad3", + "docs/validation/startup-feedback-evidence/green-wrapper.log": "0bbcaa2c8afd4f7c720d2d84d3f6ca808b54cdd8", + "docs/validation/startup-feedback-evidence/lint-final.log": "6b20a95e0253c4ec65e5a5756067ef6949039a7b", + "docs/validation/startup-feedback-evidence/lint.log": "807b43a96184cc913ba8144f7711073770d6cdb7", + "docs/validation/startup-feedback-evidence/red.log": "3c81c6e1313402a667138689d66652aedcd85be3", + "docs/validation/startup-feedback-evidence/source_tests.py": "92b660c35623e543dd7dba4c4779efecca44b5cf", + "docs/validation/startup-feedback-evidence/wrapper-delivery-diagnostic.log": "4d2f32589e23d84d97184c13f97a99e1b576a730", + "docs/validation/startup-feedback-evidence/wrapper-diagnostic.log": "dfb821979227bd115c5a309efe0288fc4a718840", + "docs/validation/startup-feedback-evidence/wrapper-identity-diagnostic.log": "378693425b31b9db8e032f00596a076b1e62c04a", + "docs/validation/startup-feedback-evidence/wrapper-scope-diagnostic.log": "7a7aaccdc6ba727e365fb25d042ff87266f209c5", + "docs/validation/strict-mcp-arguments-484.rst": "c28c02b340540e4f0a89f7faa2b6be14d381a958", + "docs/validation/viewer_current_main_integration_20260930.rst": "fa17021a832cb5b06db07721299926b12ccae96e", + "docs/validation/viewer_reset_lifecycle_308_20260930/all-owner-bounded-first.log": "86ae5a05cd75fa2e0e8b7d576a5e5f770b43096a", + "docs/validation/viewer_reset_lifecycle_308_20260930/baseline-shapes-bounded.log": "0ee8745d3e43e441bdafe16feafc415ab261012f", + "docs/validation/viewer_reset_lifecycle_308_20260930/baseline-valid-transitions.log": "137c936229b9d7f307d7c69c91b964fd915721f8", + "docs/validation/viewer_reset_lifecycle_308_20260930/check-parent-artifacts.py": "6c809beddaf0009d5a4ea9fbf6f0c86251d1af1d", + "docs/validation/viewer_reset_lifecycle_308_20260930/checkpoint.rst": "c68deb8666a45ee2d4cd147e236bc01c766bac18", + "docs/validation/viewer_reset_lifecycle_308_20260930/final-matrix.log": "88500fd025fc2e3758c48bfc88aebed997bed875", + "docs/validation/viewer_reset_lifecycle_308_20260930/mcp-witness.py": "921a41830f22c9446eef4680b7e42eedf7058174", + "docs/validation/viewer_reset_lifecycle_308_20260930/native-calibration-owner.log": "69c8773bcabc2c676c24ce08c19700114c31cb22", + "docs/validation/viewer_reset_lifecycle_308_20260930/native-layer-owner-complete.log": "d422fd94462821e67c403373e93a4771ab5a752f", + "docs/validation/viewer_reset_lifecycle_308_20260930/owner-image-clear.log": "4dd89c31ffaf70a9ef1da333d35877ca6bdb1167", + "docs/validation/viewer_reset_lifecycle_308_20260930/owner-regressions-first.log": "a04db7cb1ef062ce756ac5127f772a936f3a9310", + "docs/validation/viewer_reset_lifecycle_308_20260930/parent-acceptance.rst": "8b3705122e275ae2961fea870ee4a5b466635b7b", + "docs/validation/viewer_reset_lifecycle_308_20260930/pipeline-parent.py": "e9d60f5b4ac1b0479f761a909611f4946c5a5ce0", + "docs/validation/viewer_reset_lifecycle_308_20260930/pr-body.md": "d949b9cea0c326c0273ee91d9fd87c4f84c0a6eb", + "docs/validation/viewer_reset_lifecycle_308_20260930/queue-owner-shard.log": "74d755424bb132585fde329dd4cd61f5b2534580", + "docs/validation/viewer_reset_lifecycle_308_20260930/ratchet-final-resources.txt": "122957dff43465c040348092132ab7066a3519f1", + "docs/validation/viewer_reset_lifecycle_308_20260930/ratchet-final.json.gz": "e862eb3ffb51d07df16bf52fde03bb3466c0978b", + "docs/validation/viewer_reset_lifecycle_308_20260930/ratchet-first-314-resources.txt": "44218bcc365b3229c5dabb76630b401c30c6038f", + "docs/validation/viewer_reset_lifecycle_308_20260930/ratchet-first-314.json.gz": "5e9413806ea2c20fd49511c6adcd90ce0e25f760", + "docs/validation/viewer_reset_lifecycle_308_20260930/ratchet-first-resources.txt": "f07bb39be5aaaeb0a1b2f6e6dc77f5556e859833", + "docs/validation/viewer_reset_lifecycle_308_20260930/run-parent.sh": "d84f18caf1daf3ab35ddbe1fc7885b8c979c27d0", + "docs/validation/viewer_reset_lifecycle_308_20260930/run-source-check.sh": "b40a096759c874c441a8e3c8d89d9293223814ab", + "docs/validation/viewer_reset_lifecycle_308_20260930/shapes-4097-owner.log": "fd61d005e34b312b8ca2208538f5c895f904a382", + "docs/validation/viewer_reset_lifecycle_308_20260930/shared-axis-authority.log": "ffc43913c71c8000b67dfd42db66bc6f692110fe", + "docs/validation/viewer_reset_lifecycle_308_20260930/transitions-final.log": "1f0a6a1bb1e3efad6dd622b33c1ad9b7a300e630", + "docs/validation/viewer_route_spatial_302/checkpoint.rst": "7ff23f0464c40a89dff5f5741c39eb32de684fbe", + "docs/validation/viewer_route_spatial_302/pipeline.py": "08ee53dfada49729735c5ddd9eefe43e4c173012", + "docs/validation/viewer_route_spatial_302/run-candidate.sh": "00ec1187921a7ee4f3509d41cd139e90420ed615", + "docs/validation/viewer_route_spatial_302/run-source-check.sh": "d772039d7c19c91bd8b95121eb7721a7d610fe6a", + "website/assets/agent/cold-start-workflow-events.jsonl": "18ecc15b33bfe9378fec68c1535d7e33a2ba4085", + "website/assets/agent/cold-start-workflow-final.md": "69a3f13c652d089edf20692eaff5269771766cf0", + "website/assets/agent/cold-start-workflow-pipeline.py": "e6e4b5a7e3e12e86a559404e1d6b260ce17e35e7", + "website/assets/agent/cold-start-workflow-record.json": "5477f32586f486edeae4daa113dd95dc119c3c36", + "website/assets/agent/cold-start-workflow-transcript.txt": "f7699d258d92bb96afe2476259132320f76205b8", + "website/assets/agent/cold-start-workflow-uncut.mp4": "4db8ca6871bdeaa9d5f6d5e7b092f6cc1d48b2cf", + "website/assets/agent/neurite-outgrowth-workflow-poster.webp": "fedbae315af0b56e6288341c56913b3337814655", + "website/assets/agent/neurite-outgrowth-workflow-record.json": "1b882cb6be4098f37a5ed8a930b70af52caa4c92", + "website/assets/agent/neurite-outgrowth-workflow.mp4": "3224afe95c92b9bd1617d4ca2d93148fdfc9203d", + "website/assets/agent/neurite-outgrowth-workflow.webm": "51488d55e5e6cbe67161629a26ddde1c285e9238", + "website/assets/gallery/current-neurite-result.webp": "13a8fa80486c4d7e1ce331d4c9f689ac8168ca64", + "website/assets/gallery/execution-log-viewer.webp": "6a7b24d78fa287a2155ca45527e632ba41dabcdc", + "website/assets/gallery/fiji-review.webp": "2b4394e0faae58a41560560949d121d6fd3c5c5f", + "website/assets/gallery/first-plate-workflow.webp": "d619829751cba891a74f6db950ed0cba7dcd0c6a", + "website/assets/gallery/global-configuration-editor.webp": "55780efb53dcb5d2bba6a6d8ea912ca877e56564", + "website/assets/gallery/lazy-inheritance-poster.webp": "4a4c20313a6cb3a58aa30319dbf46616314b1a64", + "website/assets/gallery/lazy-inheritance.mp4": "9d4fc4701299354d3e7dd5f5aa119be313af59e7", + "website/assets/gallery/lazy-inheritance.webm": "51a17360669fe49e321f3bb21486045ef90a03de", + "website/assets/gallery/multi-plate-overview.webp": "76578dd9936d5560eddaac7fd8bec52882bc2404", + "website/assets/gallery/napari-roi-navigation-poster.webp": "1647a27ea6383a2b862d9cb29a414ef8593951ff", + "website/assets/gallery/napari-roi-navigation.mp4": "355a78bd4c9679f931bde6ee5ac7bf293d857d9d", + "website/assets/gallery/napari-roi-navigation.webm": "71df0cb54d071b657fc0283b7db0f370f8c67947", + "website/assets/gallery/pipeline-editor.webp": "f4034aaac227ad4b0d0c3b54030ae459721a12be", + "website/assets/gallery/release-media-record.json": "d934e58f1fe06bba152669d58a1ecdb726541ec8", + "website/assets/gallery/source-capture-evidence.json": "ffd79ddf629e75e70625381ba87e52c03f25f3f6", + "website/assets/gallery/source-image-browser.webp": "685b9428b0060724e527759e517d8ae3c76228a7", + "website/assets/gallery/stitched-neurite-overview.webp": "2c00993a6c69c2a9385f928d3cb47b029a323179", + "website/assets/gallery/ui-about-openhcs.webp": "6c40ca74d3de9b7efe3b0723cd19cb3b2db5814f", + "website/assets/gallery/ui-custom-function-manager.webp": "99366549cdfbc1e38ce4c0874482d1d80d4a257f", + "website/assets/gallery/ui-function-configuration.webp": "b41a55999e69063eabcd72e675425a817c5fef0d", + "website/assets/gallery/ui-function-selector.webp": "071c5d26a49770333fa2a2d8b7915823ca779dbf", + "website/assets/gallery/ui-global-config.webp": "55780efb53dcb5d2bba6a6d8ea912ca877e56564", + "website/assets/gallery/ui-image-browser.webp": "18b414b2d33b9e292be12f7b7b13dd226d9c2cc0", + "website/assets/gallery/ui-knowledge-base.webp": "c337bf822c05e489855003c52aad4e122487e3d2", + "website/assets/gallery/ui-live-measurement-results.webp": "fa0ffb29451046b6d0664d70bdba77b5c7f68b40", + "website/assets/gallery/ui-log-viewer.webp": "4a7529d02062c1522996e318730c950042a9ac3d", + "website/assets/gallery/ui-main-window.webp": "ae12c6e2d482e6bd637cf01037a2e99ffc187667", + "website/assets/gallery/ui-pipeline-configuration.webp": "c0753903187c1f8c92d0a6744243c7cd70b18aae", + "website/assets/gallery/ui-pipeline-editor.webp": "6a6269c1d12066db84f947523f6fc8f49fdf7d0a", + "website/assets/gallery/ui-plate-manager.webp": "e30ea9c0357e8f869000754daa623290ebeb94fa", + "website/assets/gallery/ui-plate-metadata.webp": "a7f4cb7584a98fec5b6bf118e9387dada06be2a3", + "website/assets/gallery/ui-step-settings-editor.webp": "bf1b857403e02d6033476a87317a393ff20920cc", + "website/assets/gallery/ui-synthetic-plate-generator.webp": "8635f1cb8fde1c061df942c334b10e3a1d4db1dc", + "website/assets/gallery/ui-system-monitor.webp": "91e02cfc1dc54ddaa47e1320bdfa094960de6d0e", + "website/assets/gallery/ui-zmq-server-manager.webp": "dca97c12e45c093deb09ef0c789e5b2ab0e9ff86", + "website/assets/gallery/zmq-startup-compile-poster.webp": "28fefa04e06985cf838c2651d95a4e3b9dbe8069", + "website/assets/gallery/zmq-startup-compile.mp4": "fb13e04cf1d2bb1e94aec18214682d012c5ff766", + "website/assets/gallery/zmq-startup-compile.webm": "4f8b84d308885c1fecacd9ace5a9964c37a1cebb", + "website/assets/logos/README.md": "b54b2ed49cd8d548b0b49727b6c6d68687e00d03", + "website/assets/logos/bioformats.svg": "759f3df7d6f7b4147f92ce99845c1f7d713475cf", + "website/assets/logos/cellprofiler.png": "90c4212f6017c0611140b897922b450d599a5ece", + "website/assets/logos/client-claude-desktop.svg": "0f8385a6554aaa25cd24d8222ba62b4778c7e1b7", + "website/assets/logos/client-codex.svg": "7d9d324ed02e32254e021834e7991e667f5e93bf", + "website/assets/logos/client-cursor.svg": "b9672494f2d63174153dae038ca72d821027c530", + "website/assets/logos/client-gemini-cli.svg": "60197dc4adcf912128756b32ead43b8b1da61222", + "website/assets/logos/client-vscode.svg": "d7701ef43ffef61bf0f96df0a4edea54662736b2", + "website/assets/logos/client-windsurf.svg": "7670303f63da0ef1f7224367f06a04930cd9de6e", + "website/assets/logos/cupy.svg": "60ecb29e7142ef02e2b239c79413d53575a6ed6d", + "website/assets/logos/fiji.svg": "8c85740e15b13d8dbeb6e9c2b51e1f5142ad92c1", + "website/assets/logos/jax.png": "a0c7393ef78578f6b3d38cf38c219a8075555f5c", + "website/assets/logos/mcp.svg": "03d9f85d32bf343db07e6e472d555d0a7be41c58", + "website/assets/logos/napari.svg": "1bed786fc4cd7717c56f314cf536f75274b62f8a", + "website/assets/logos/platform-macos.svg": "796e5662f1445b8a195fa2bb147d004695726bdc", + "website/assets/logos/platform-windows.svg": "e635dcd64607e9324318675aeff53a62ac6cb219", + "website/assets/logos/pyclesperanto.png": "e00cd372b95cd75fb1e948060b865296440fd87a", + "website/assets/logos/python.svg": "297a11e090227bfd6bab3ff110f3ce39b400d745", + "website/assets/logos/pytorch.svg": "575f6823e4762f1c5ad7dd4ff7229a51537eb6e4", + "website/assets/logos/tensorflow.svg": "2c510f01c53758c4dbae20f6db3f88f6f565d04d", + "website/assets/logos/zarr.svg": "fb85504af0fb79424c109526b175b3d43b643a07", + "website/globals.css": "e170e436411140dab7c1ba07cf160faa4940b042", + "website/index.html": "ba570cbd696d1638be91f4b4cf54355ecbf07ea7", + "website/privacy.html": "e783fead7959d6eb4264a5ffc4cec4a075d9e08a", + "website/styles.css": "60f4d0aefd282f53cd35ecf3dcffcc32244ddf73", + "website/support.html": "40e06cffd9a8b80742c07994712e6e21c4f2a2a0", + "website/terms.html": "0ab5910bb72357832b31d70c83354c2d9e33ec2c" + }, + "declared_gitlinks": { + "external/ObjectState": "a01f8939b9bf4659502a33fe3febe62cab0f3c9a", + "external/PolyStore": "84f322e46871de5ed47e7fd20976ad03e533c1c4", + "external/arraybridge": "1e53d03d9f468322a1c085c8be29485fb139caf2", + "external/metaclass-registry": "393a7e03003cdc56df9013f932ed4f26e632d77a", + "external/pycodify": "792b03413331fdf107e369c924c257a2f0b16126", + "external/pyqt-reactive": "ad4948775ab81180a354d4b793d17ee5ddff3972", + "external/python-introspect": "ed1e4eb15f7a0bf8315274d3e47858fa2b4372bb", + "external/zmqruntime": "668edafcb5ee530a163377c936431ae1e8334e85" + }, + "sparse_patterns": [ + "/*", + "!/website/", + "!/docs/validation/" + ], + "website_receipt_sha256": "743be25a32804961ba4c05bd32b8ecc696bdcb15e52f5350678260bcf3fad36f", + "website_preserved_sha256": { + "terms.html": "e12f9e60c4906bfaa4e4769a06ef0715e26bdaf1b14684f9590c026dbe9b31df", + "support.html": "c77d2a2a5c1c1362bb27372e9773c23569bd5c9834ea0b1777d960dc4e1f0003", + "globals.css": "4b9a2d89a05db28816a3ebba363247e774a277cc414e2bd918c4a9d8984beef1", + "privacy.html": "09dbc87f2b3749be4926f97d67aa2c4264844731bf0f037cf754297891b1eaf9", + "styles.css": "2ad02ff21a51c047cea2a5c3f9b19bfaa85e4d20d70f326c339b71206310cddf", + "index.html": "311b8c9d5b232cb4eb3e27958da3d5dd6cf0c8665f3474833b9f720925af153b", + "assets/logos/README.md": "244baac8bc62478d51d3f50a750559edc1205763bcdb4c6fbab87e698a93e43b", + "assets/logos/platform-windows.svg": "e50c2a77d210b422a90dcebf271bfa7a2b6cb1a7132bb798e045100b823e123e", + "assets/logos/client-claude-desktop.svg": "aef68a9c94bdbb26485c7bcc79c94ccc9d798b4f17d20a9019d7932598dc5c1b", + "assets/logos/client-windsurf.svg": "310a4f7fd2a2591ec45cba3313790f42ad8b805896e825c8fcbfada06f8dda7a", + "assets/logos/pyclesperanto.png": "b551c7e270028cfc29b5d8997a49ed83c3c49029e41124c2e0ec339b533157db", + "assets/logos/bioformats.svg": "19cfb3bc6a2274b98c76a1e9af43f1d94c56b5b5e718e60b1fecdb633c7ddf9a", + "assets/logos/zarr.svg": "4e7d278e12a6000c54ce3dfdee274d4dd98595bdf04d2afacda17b5a6e61ecf6", + "assets/logos/client-cursor.svg": "ea5d9706762f2eae285b69c8769c376892ba1efe068febd8e2857aff0afebc85", + "assets/logos/mcp.svg": "05f47fb3ffb7323bdbf6b397330229a7f32a3a1f2d17365e748f8777a82dd6c0", + "assets/logos/cupy.svg": "30100286bd74ae633d2196b2d8ea175e405c258c22441582e6bb1715866d1756", + "assets/logos/python.svg": "adca85e1d0bd6d796abea422d983fd131a432fe78efeac58af18461eb1548780", + "assets/logos/fiji.svg": "36b2b05f93e28fb37085f8d9eedaddcdda7718732bbf3f4ed40e0bd4722babea", + "assets/logos/pytorch.svg": "fa653a3e79a36d6c8738c9c05e10c0265e466db23fc4b2d7ef65d32ff84cc839", + "assets/logos/client-codex.svg": "730508e7487d4e4ba758bfcca3e4cdfd31953938efad6d506acd502858559db3", + "assets/logos/napari.svg": "e7d39d1a8d8ddc43190e55fb09c7ac6f3653120b4afff2dd981b3a66b326623d", + "assets/logos/jax.png": "b336e0959efcf4835f1c4ab717398b4a8fe11dccac6790f2dcff504820d9b095", + "assets/logos/tensorflow.svg": "5ce40657105dc138823732bc446fe8e0bee666e9348fe80b7ef1b03bd873b953", + "assets/logos/platform-macos.svg": "aab854e12a2a1a639c90662705452313b06b22c670bcfeeb49975a065d792afc", + "assets/logos/client-vscode.svg": "e6a85a48bf3f458a3c061ec2096f6ed435a17f809a6ecfb66905cc16ec1feb37", + "assets/logos/client-gemini-cli.svg": "cc58217af6ff40b9de0d105a3820ca2cbc8b806905dbedf3baf47ff7eec91a7a", + "assets/logos/cellprofiler.png": "820dc710604ae6bfa5605b7a6c17817c484d91e289c15d5953e2769b083333b3", + "assets/agent/cold-start-workflow-final.md": "145a0231f59bc359d88e0213a401912aeaf4921ab951e11451278e9535bed503", + "assets/agent/cold-start-workflow-pipeline.py": "48b6e4f9dbc54932df8a95c405f4b832c1ca35856d866a261faf15fa3c14b754", + "assets/agent/neurite-outgrowth-workflow-poster.webp": "d523a664ecaf1f9f06d1cbe6e8717795f4a463a5c5e191ba1724a78cd88be3b5", + "assets/agent/cold-start-workflow-record.json": "52d126027b39a05cd5e799e4aca28e45fd8edd251c7b523204c33c14fa7de65c", + "assets/agent/neurite-outgrowth-workflow-record.json": "da03fea3e052de378582999b0a7b67ab2a16196f7863064189a11cf7469f4997", + "assets/agent/cold-start-workflow-transcript.txt": "0a1242f902d8fdb76137edf6f5d37055ff3f43650b3691f54fc77a8c333a9e50", + "assets/agent/cold-start-workflow-uncut.mp4": "e3c71086fbe6ea85bfb8ae557d3cc129c6a745779fcfa6c0c0b5388e13956c58", + "assets/agent/neurite-outgrowth-workflow.mp4": "b5c2a0489a3cbace65a1abc27393a57620515ceeb7a4968bcab5724473c3b8eb", + "assets/agent/cold-start-workflow-events.jsonl": "de8342948e39a9a9a8dc487770bdb32012f683799d4479a1ebeb5d125a563749", + "assets/agent/neurite-outgrowth-workflow.webm": "fbc9a4ce52cb7a02682e2b9f71a5479836e7c35e9c0d9edc8b96b402f72ec1e7", + "assets/gallery/ui-synthetic-plate-generator.webp": "e175587baba4afdd7826f168a99308b66e1287e5286e17ae72e73bd4d86675ff", + "assets/gallery/source-capture-evidence.json": "ae0d19fca99f3bb5e98eb299b044075b812cf414b4917216fa8233fa721e9c64", + "assets/gallery/fiji-review.webp": "c02d9e4e02c3e8f504fcedc4440dafa154072a876f8669c3b7d9df89254ed893", + "assets/gallery/first-plate-workflow.webp": "991de0cb39524792a41c1d47bf1078d31fcdbd5b2dc55c81daf064a74a3a18a5", + "assets/gallery/stitched-neurite-overview.webp": "537df1dbc4e2ccc3ae6b96245daf79a504dee29e8b8b498a7a2f12c2dd43bd0b", + "assets/gallery/release-media-record.json": "fffe771e55e88377e8c46a40ff81dbd3222d9cbb152842f5edce49d89ac23fa9", + "assets/gallery/ui-log-viewer.webp": "0ac13269eed5832e5aa4c9a9ca27da59044da18709da4a17f40687c14fccb9ba", + "assets/gallery/lazy-inheritance-poster.webp": "84c9dd0c6c9b3af0facc08adc4f8cebf2169c610e34271991c06a54c7291341a", + "assets/gallery/ui-plate-metadata.webp": "061b1f5d32b64427c0ef06ef1c82664eac09a7e06aac797b1a25bb73c3cd15e1", + "assets/gallery/ui-zmq-server-manager.webp": "7a8e86bd8c11c914103cd685f87177b367cf8219ef0ee2ac375a66557c97b3ff", + "assets/gallery/napari-roi-navigation.webm": "345676c83e17d7ff634daf880587b44f16c6364ae67475f06cc6a5aad2618d26", + "assets/gallery/ui-live-measurement-results.webp": "b39a8ed25ca440cfb799a73f5b54c23d030dd7eed92c57c1fa8ac0f5c8a8565b", + "assets/gallery/ui-about-openhcs.webp": "00a701ee47c35da96788e1dfcf63ef161fa8d92ead27f47b5302e8997fe251f8", + "assets/gallery/current-neurite-result.webp": "e55ea2fda442740f58e93f4773419c53026faa4b3336d0148039ea996f65f551", + "assets/gallery/lazy-inheritance.webm": "4f6184f6c5e75febdfcd7d5c36c7d9499aafbd37c17e9bd6d58b76145ca9ec82", + "assets/gallery/ui-global-config.webp": "b4b69cd74899639c12c9f7014449501f9fafe91a2cd65533631583e2f5ec48e9", + "assets/gallery/ui-function-selector.webp": "4bff760ae10c02e41e8a6f5754438021cb92ae7985ad4ec6e8183e43a92fd8bd", + "assets/gallery/execution-log-viewer.webp": "ac0476352392fe6135fca60bdcf37c40c91a21f00384eb4fef3be023b9165eab", + "assets/gallery/ui-custom-function-manager.webp": "10e8e32bdb175ea13e0861479f843ae1ef9f18746a7548ec75d2148a060ef144", + "assets/gallery/ui-system-monitor.webp": "7a910e3b565712d75050ec5846282e733ab218132d5eb09a41853f48777782f0", + "assets/gallery/zmq-startup-compile.mp4": "1aa4588d577f575beac0249423d63fdec7a81149990d1916b2866dca6d6ba28f", + "assets/gallery/napari-roi-navigation.mp4": "30b8a83a2304b4dc053563d84d5e8b2ee34192bf95a3c161320ee4fd41f05686", + "assets/gallery/lazy-inheritance.mp4": "af7d69d8a12bc80648af2236d564bda31d111c6c67d32d396112c57b964380df", + "assets/gallery/ui-knowledge-base.webp": "f436036fc3b3cf85481051ebd690a2167468d09d186efce811936949b734613c", + "assets/gallery/source-image-browser.webp": "cf9631e3b61b22772eec772c3b7acc9f761c1bc46a0528de19107a86d7419d1c", + "assets/gallery/ui-function-configuration.webp": "003c0278077d2d239b90308958715808e3a1a99d767a7abfca3dd65ba6be1bd9", + "assets/gallery/ui-image-browser.webp": "adecdbec3e1381eb71f8fff813f1a56824e4c57a9d5f2d3c6659606682d7bfd8", + "assets/gallery/ui-main-window.webp": "b42b3b03c23e6e168fdb1c515739831cd98fe022a9e41de3949e2f0cebd787bc", + "assets/gallery/napari-roi-navigation-poster.webp": "f1e9c29db9436df7e6e2dcdb134b6d8529538143f05b732cbe38ec100cd5e1b5", + "assets/gallery/ui-step-settings-editor.webp": "df440ca834f62e34f8da792320c4159424b05848bada8fc2cb8ea502da741c4a", + "assets/gallery/ui-pipeline-configuration.webp": "1ca2eb172ca33a2cd9ba3f74d1aaae81f448f5c48c85bd9b6f51642e9b1fa570", + "assets/gallery/global-configuration-editor.webp": "b4b69cd74899639c12c9f7014449501f9fafe91a2cd65533631583e2f5ec48e9", + "assets/gallery/multi-plate-overview.webp": "dbbafaea1a1eced14c1c521b0d4efb2d0306bda6c2353a9011106bebdc07b324", + "assets/gallery/zmq-startup-compile-poster.webp": "cd86354953790f70041504f2be4cf225f678294f51624ce477d9414cede7028d", + "assets/gallery/ui-pipeline-editor.webp": "88b9ecfce130e15d6bc98765414f36a02fc2a0eef37953a1cdea7bcadf07b82f", + "assets/gallery/zmq-startup-compile.webm": "64109edac63e3bb22d8a155cc757114e11af6028d7a08d33d81a61aae11f93cf", + "assets/gallery/pipeline-editor.webp": "b0931e1c10d905123a1b5ad32ed7362b07c401fefcba2211ae5688a5003e6d8e", + "assets/gallery/ui-plate-manager.webp": "09a340b7b6320827429ca67e22b35aa39ed9543424be07bae399de881201d5b3" + }, + "validation_receipt_sha256": "be95471be7db9104c4f70679043f36c0dcf3dd6afef7c375a7c42dd252ec308e", + "validation_archive_sha256": "a94d12b0267c813da88398c151c1b1f21938e5d2eeccb3324daa7b81b1fbb6e4", + "validation_preserved_sha256": { + "docs/validation/ack_runtime_parent_20260930/checkpoint.rst": "7725593e1289e6dd311a08ab5ec94376a69908fe2da73eac452ce1df6fb4e273", + "docs/validation/ack_runtime_parent_20260930/mcp-paired-session.log": "92b11754a5fa805b64726dc08c85249f26b299acb3bd075dbf22889cd241309b", + "docs/validation/ack_runtime_parent_20260930/paired-source-final.log": "6321bbee4f8d59ef3d54726c0d96052d0b13bde1bb2ee3f3acb58dd71c35e664", + "docs/validation/ack_runtime_parent_20260930/pipeline.py": "04bb12bff2d2afd64de5df0489d84360c517aadfe51a77d4bbcd1d232f4f17e1", + "docs/validation/ack_runtime_parent_20260930/pr-body.rst": "7513b54a7ca1f2c64040fb1f1e9ee934133fe3c9a45964df307f942fae21794d", + "docs/validation/ack_runtime_parent_20260930/run-candidate.sh": "12d5f43f03bbb068cf94aa10043d396dfd688fa04e432815b7e03df4f03b5003", + "docs/validation/ack_runtime_parent_20260930/run-source-check.sh": "fd035c31bd369ef3b9b9d53c4a369dc78bd8e396d16013a46d344f7bffd80324", + "docs/validation/ack_runtime_parent_20260930/viewer-followup.rst": "ca27aff503b361489148c9d4c6b508cd2af8006825abbbdafe7a01ec486ed6bd", + "docs/validation/artifact_fed_parameter_declaration_contract_20261001/ISSUE.md": "6356aae96cf5b14277df9344123561e4a82cacb07ad16f79406ad92fcbab1032", + "docs/validation/artifact_fed_parameter_declaration_contract_20261001/PR_BODY.md": "6d76ba7b7a4a05fa5b6dcdf91d11113af4a6cef5f6c9fcc34427be096bf96d4f", + "docs/validation/artifact_fed_parameter_declaration_contract_20261001/RECEIPT.rst": "58ea474286448e3033c3da2ac9add3b0c990d0ac7c5d35aac4b6dd293a09d57c", + "docs/validation/artifact_fed_parameter_declaration_contract_20261001/SHA256SUMS": "6c57519baeb5c5348e0166212ca0ced6f52b4f79b7405b161d0c41994bbdc0d7", + "docs/validation/artifact_fed_parameter_declaration_contract_20261001/contract-pattern-shard-resources.txt": "54ee7530366072ed9b4a208d4c3ec8b5ede84d80ce3f5d5ef1e02d2f12bbd26e", + "docs/validation/artifact_fed_parameter_declaration_contract_20261001/contract-pattern-shard.xml": "5072c684af61b581e7c1e3aa17da822cd18e56338f4465e356ba3f7a9a3da3ce", + "docs/validation/artifact_fed_parameter_declaration_contract_20261001/normalization-green-resources.txt": "0cb0f323a14b6651017a46817b7faf85295a590ed77f2caf536565eaeddc51bd", + "docs/validation/artifact_fed_parameter_declaration_contract_20261001/normalization-green.xml": "e4518c3a08d37eb26a01bf2a4e40edf8ceae7985dc1261b3ccc5a4892a583789", + "docs/validation/artifact_fed_parameter_declaration_contract_20261001/original-red-resources.txt": "a42ec8b7e6414d532521dead2ba7d6acbc849bbca9e53faf61cc1c0739a2ee3e", + "docs/validation/artifact_fed_parameter_declaration_contract_20261001/original-red.xml": "a181c710d8abb7a64d77e17fc060a2053b0b4dba3a2831ff4107ed4073ab2cd7", + "docs/validation/artifact_publication_315_20260930/baseline-import.log": "6e609cec624cda587fdb991174260ad1f95cbcdfb3b4dd5cdf84729c6ce6a02d", + "docs/validation/artifact_publication_315_20260930/baseline-journey.log": "b65e4cc426d5806c491f9c0eb72cd7817d248a38a99dd2cc49cb971bb0ac7277", + "docs/validation/artifact_publication_315_20260930/baseline-journey02.log": "fcfb1067f66b6a2abf560d0a180ed2ad2c0d39ff04adbde7ec5ae5992277b5d0", + "docs/validation/artifact_publication_315_20260930/baseline-journey03.log": "af8f1dab9665e91dd1885d790cef63e055895ef95afc4f4f3246838827ba31f2", + "docs/validation/artifact_publication_315_20260930/baseline-journey04.log": "6eda53043b7f4c1bb86c17d992f53283aa7411643a0bae8bcb9db430403031f6", + "docs/validation/artifact_publication_315_20260930/baseline-journey05.log": "b35b49a9c6b804077f5d7361cd2a524a588597170bf519e6f5ea6a212ad99daf", + "docs/validation/artifact_publication_315_20260930/baseline-journey06.log": "3580af3a73576001e4862d84fdb9fc2b15ab0c7e88d17f17e7ceec002a6a65ce", + "docs/validation/artifact_publication_315_20260930/candidate-journey01.log": "4e4eeb7110157fa40178637b3953d6f06c9875058a70b85cb187a7e5de6b3158", + "docs/validation/artifact_publication_315_20260930/factored-journey.log": "c914dfeebf2e14f997cb7826c61eaf29aefb99a293f657f473b41c984d60b80a", + "docs/validation/artifact_publication_315_20260930/factored-journey02.log": "f53b3271d1b98d0687be6d328d4c9466652f3af54dfe18e0b74ec88f5749233b", + "docs/validation/artifact_publication_315_20260930/factored-owners.log": "37eb73da5e30dbee9824b55e9da3a90306b8d2e1739348e3b224fc193be58369", + "docs/validation/artifact_publication_315_20260930/geometry-final.log": "c487742702d708c9cb943a35b5708e215203fd98ef7497d2f9ada4cbca9ca75c", + "docs/validation/artifact_publication_315_20260930/grid-triage.md": "32a845a94a8cdc93919a1fa64ef7f3e0674c3abda35382f22f876f13b51a903e", + "docs/validation/artifact_publication_315_20260930/merged-main-source.log": "fc4f6f8d33865b47a8aaacdcee162ef044c694c3b32abcb56661885ce06be8ec", + "docs/validation/artifact_publication_315_20260930/named-checkpoint-ownership.md": "2ec76388caf5660710272ebaaa32e6c8f645a62c1ff1e8cfa6f407e7419d3595", + "docs/validation/artifact_publication_315_20260930/original-native-failure-artifacts.tgz": "f98ba196b7be496c01604ba4a75dc66657f8664020ec0678ef2a95f287252308", + "docs/validation/artifact_publication_315_20260930/original-public-journeys.log": "3390b50f0482f49b51478d95ebc9c04c014321af3de38da2c0eccd5d928c310f", + "docs/validation/artifact_publication_315_20260930/original-r1-bounded.log": "e3b7f9f3b95320b52817126e0526adb6d2d7bdfa46c8efb2720e0ad4bba8cea9", + "docs/validation/artifact_publication_315_20260930/original-r1.log": "7437360b9deda8a490549b853a57b88b6278c171a44bd63a4ae4c43e9fe5929a", + "docs/validation/artifact_publication_315_20260930/original-ratchet-benchmark-resources.txt": "1d401d96d59f2a7e62dd58fc6482fa341f7e6e3708c6ce08c5e15802bc73f29e", + "docs/validation/artifact_publication_315_20260930/original-ratchet-benchmark.json.gz": "0527c9effac1a406c457f9069d8f70bf49dd6094ae55ef378d1ce533a05acaa8", + "docs/validation/artifact_publication_315_20260930/original-ratchet-final-resources.txt": "3c1fffae4b2d7fa23828c18e39b6a233566a8f389118bc521a3738530a029c34", + "docs/validation/artifact_publication_315_20260930/original-ratchet-final.json.gz": "d1033144eb999abd2d017a3dd9b247f685e0b488fdf7700c2184b06c4a5f06f2", + "docs/validation/artifact_publication_315_20260930/original-ratchet-initial-resources.txt": "bdb9721d92a0fac9cfa9f3c959b6e6480311cf4df4d599955b3e9ac963dad527", + "docs/validation/artifact_publication_315_20260930/original-ratchet-initial.json.gz": "85d628579b2d771875e47b4e8c235e5afd57bd15ad55c9619574681d347c70b6", + "docs/validation/artifact_publication_315_20260930/original-ratchet-scripts-resources.txt": "f8ad26db9e228856c0a5ad90e304c4e67d562e56ecfdb689e277a78946a292ed", + "docs/validation/artifact_publication_315_20260930/original-ratchet-scripts.json.gz": "f721787b37da1689019b7a6e2e24417a57ce372da245d9e8d27ed702fb66f1ba", + "docs/validation/artifact_publication_315_20260930/owner-controls.log": "6fa26fabf287c57a0fe06c5f244b46a7ea34b482bbcf3a8004b1e1aff9691e2c", + "docs/validation/artifact_publication_315_20260930/ownership.md": "d879067753f5ceb41428bf2a08f786bb5422083789c5efba376917ed0b71d4bf", + "docs/validation/artifact_publication_315_20260930/parent-installed-checkpoint.rst": "c07c834bc806b0713d07bf51545260e9420e0fee1e2db6847146ccee422b8900", + "docs/validation/artifact_publication_315_20260930/pr-body.md": "217aa78c2dcd386fb093ca5d4461c83332b26947c15a0bef92e32dd9b443c406", + "docs/validation/artifact_publication_315_20260930/publication-final.log": "adcaed1c83152ae331487094408cd8d360f5a9db9b3cb7a9a10bfe178755bc91", + "docs/validation/artifact_publication_315_20260930/qualify-original.py": "9d7280aa3bb4b2a50ea056304f8e7283d8e94ec3aaa681c2ab525b3f4f657018", + "docs/validation/artifact_publication_315_20260930/results.md": "4196b68aa14afae530ceca966a8f2c911343c86c457148f9b99efa64a2cbd58e", + "docs/validation/artifact_publication_315_20260930/run-bounded-r1.py": "fb2b897beda3dfb1da3be2fffe5b39b69187ab263c07009e4522c5765e104032", + "docs/validation/artifact_publication_315_20260930/run-source.sh": "af094220c56f56aabdb44406c3e3f003aa126d0b88f02230d7fc0c48063947f1", + "docs/validation/artifact_publication_315_20260930/runtime-controls.log": "7e234186cd5d05cbe6f881a18ced10993869144d1e177b554f8f7bd3d03ff325", + "docs/validation/basicpy_parent_numeric_20260930/check-persisted-live.py": "3038b6b84deab7def98068fc8877fcb34d48486738b3729c66c70c04c5addbdd", + "docs/validation/basicpy_parent_numeric_20260930/check-publication-fixed.py": "55fc3bafda5df955cb1026ea6f6aedc0056be4a2242b41bc7155942439a9c0b2", + "docs/validation/basicpy_parent_numeric_20260930/checkpoint.rst": "ccad590b657883de7fcb1cc5b7f5f2c6985f882d1bc57ddabd074c7f0c2a9e45", + "docs/validation/basicpy_parent_numeric_20260930/cpu-installed-checkpoint.rst": "5dd93a1cc8647c4a74c64a666b7d24381b6a3680e18af359fd3cded8a6c26221", + "docs/validation/basicpy_parent_numeric_20260930/installed-failure-receipt.rst": "e18ab6bc8c23b0b46cbfff2ed52bc25f0aa917a2e43220c9d419d3d4de03a80d", + "docs/validation/basicpy_parent_numeric_20260930/main-integration-20261002.rst": "18ceb85b7fba53b734698af0e078e515018fdcf01f89d0c9ad555ec988f974a6", + "docs/validation/basicpy_parent_numeric_20260930/owner-closure.rst": "7892cc2c64a3f8768e55935d8465c11ccd38b86fe2ae7fdd1854a5c8900c79f7", + "docs/validation/basicpy_parent_numeric_20260930/pipeline-live-wheel.py": "c78a56251fec8c8238071dc5aca9e170261ce91db6ed4f8ec380a01ff24ae086", + "docs/validation/basicpy_parent_numeric_20260930/pipeline-publication-fixed.py": "ad1a268f92f95127b6e59b46c885f17f6237774b97e2194c023627363dcc60b3", + "docs/validation/basicpy_parent_numeric_20260930/project-dependency.rst": "3aebb960c3031db6abd46819c801b6b41622993afd051852e966d4b59d10cb60", + "docs/validation/basicpy_parent_numeric_20260930/publication-fixed-installed.rst": "d11c75f1053c0238fd190fa2e71b99a73741ef16cec4727b1b54fc19e838c496", + "docs/validation/basicpy_parent_numeric_20260930/run-live-wheel.sh": "8242cd3c2e06073575ef55f799ab75c9587eb331d447a4d0dd43d851dced4dcb", + "docs/validation/basicpy_parent_numeric_20260930/run-owner-check.sh": "fa65185ca29803380e6055a0d1143a869276c45d3b64ff1f8b6d23f2c6c4aeda", + "docs/validation/basicpy_parent_numeric_20260930/run-publication-fixed.sh": "6aefef1898e5dc4914e7f7060462b9ec0323f1d7dd9ed8fdfc4c0cf7c7d9c462", + "docs/validation/basicpy_parent_numeric_20260930/run-source-check.sh": "029dcd6f1bc4f38ad3637418d939339953daebb36b5300afc627a34c64cda4bf", + "docs/validation/basicpy_parent_numeric_20260930/target-owner-installed.rst": "18df22a4c4feb0ac980c1f4f520079184642c0691aeb118d12fd58b47ad9bb76", + "docs/validation/bioformats-saved-calibration-440-source-20261002.tar.gz": "944296e6c2ebce08cda8734da534cc6bcecd5e7abd01e3aa2e9190ac1c986477", + "docs/validation/bioformats-saved-calibration-440.rst": "9abf682f48f8b209756ff02bca957005e16b9da0fe57f7ad2f5ea792072a9d1a", + "docs/validation/catalog-endpoint-incarnation-464-20261002/INSTALLED-ACCEPTANCE.rst": "a3757722f4b07352784053340d550be6d91109f43198c13edad4b4226577a44c", + "docs/validation/catalog-endpoint-incarnation-464-20261002/RECEIPT.rst": "0d75557d6928e148d36005aad2ef18402ba84f2c87dfa8ca6521d87a1a044ba8", + "docs/validation/catalog-endpoint-incarnation-464-20261002/owner-after.log.gz": "e49966caeb5b54f3a9d7ddc388bfb1deaf47d8e03b96e0f27d55929aa716d453", + "docs/validation/catalog-endpoint-incarnation-464-20261002/owner-before.log.gz": "43dd40957531c0327aa8822c729e6b9ff03c6ddee57f5d351d2fe81935e28036", + "docs/validation/catalog-endpoint-incarnation-464-20261002/pinned-r0-corrected.log.gz": "8880443eb248e7e443bbc24a2bc3227d9ffe25554f5c3cad2aa5a3d8592ee4f9", + "docs/validation/catalog-endpoint-incarnation-464-20261002/pinned-r0-final.log.gz": "621c9325eb9bcf5a9266ff6e7233e6027b71e03ec8e6d6c07c4cd24492e8a38f", + "docs/validation/catalog-endpoint-incarnation-464-20261002/pinned-r0-first.log.gz": "561a76791c429223de21d6b93cb5398db4943b54a9cc54770e1fbdc941026d46", + "docs/validation/catalog-endpoint-incarnation-464-20261002/raw-nra.log.gz": "2e6f2c9b98e9bce4a3b526041a4d6a918c88dd82c0e08f4a0995ad5c7de27f5f", + "docs/validation/catalog-endpoint-incarnation-464-20261002/source01.log.gz": "27d9d55ca17cf6fb5464cf9a3ef0365ef2257acc4d666cd7dd5a61da1c263fe9", + "docs/validation/catalog-endpoint-incarnation-464-20261002/source02.log.gz": "1612c6f3b5254c24db7c5bf5e4ff71fffdc9b7564a9c70f04cbb43e11a025d07", + "docs/validation/catalog-endpoint-incarnation-464-20261002/source03.log.gz": "14d3781b0a8cd44fb4912225ee9c6d37d3344301ad0bbcdea1dce0c06e6a8e86", + "docs/validation/catalog-endpoint-incarnation-464-20261002/source04.log.gz": "f149a9760a153740b975e7147aa9913bc5c71e6e6e0b81306e67af7f6bb12866", + "docs/validation/catalog-endpoint-incarnation-464-20261002/source05.log.gz": "ad04d3d7c8a2db779cb09c7140074ab2310c8c41b4cb2c97ab2c2e6298eeec7b", + "docs/validation/catalog-endpoint-incarnation-464-20261002/source06.log.gz": "c621ace1387a712bf307f25972b0db28203d2eb4f82ba5abf27f50315033f6e6", + "docs/validation/catalog-endpoint-incarnation-464-20261002/source07.log.gz": "71625a44885b90d5314f252dcf79838abae6164ebe964fd30bf10a1e4a686b78", + "docs/validation/catalog-endpoint-incarnation-464-20261002/source08.log.gz": "627d98bcf81b21048de5434d80238877fdb3d0c9c5baed2f72b6360854100e13", + "docs/validation/channel-contrast-review-20261001.rst": "1ea1785d8fd4a53a988d4855e72095dc23b20123e24cf476aeaf83983fc4e79a", + "docs/validation/check-bioformats-calibration-440.py": "96464e5b4e4bdbc20e029f901a64b74afa33b8279d4f228632aeb9c91b1d7d38", + "docs/validation/check-function-help-390.py": "88c0ac5465be59f4e6f3684b769ef939c7f860a6ca2eda5a2ef551b06a86e9a2", + "docs/validation/child-measurement-producer-selection-492-495-20261002/QUALIFICATION.rst": "5f369e46b1550fc10ee240d305fc44be483d8ff08b1b6ad163779f4aa448ed09", + "docs/validation/child-measurement-producer-selection-492-495-20261002/controls.log": "48038b27256912c2e3c977b9a035778c7cec1640137184c11ecfa93ea045f05b", + "docs/validation/child-measurement-producer-selection-492-495-20261002/integrated-controls.log": "25e6892c70e8be88adcc2d55ff41d8bd4208ef3c070f2170149bd219445e1a55", + "docs/validation/child-measurement-producer-selection-492-495-20261002/original-r0.json.gz": "4bf0e5414f2b3b0a60e2703713a13a4b3435180911e85a64d497cead44a3b3ea", + "docs/validation/child-measurement-producer-selection-492-495-20261002/original-r1.log": "b9f0c9e862359e5826e827359edffa4edecc345ded1840c3cfcccbe5891befe2", + "docs/validation/child-measurement-producer-selection-492-495-20261002/qualification.json": "37fd10e40b71c3f3ca2ad2d14bfe2eb552a97e23232d275b922b1f2a5c792f9f", + "docs/validation/child-measurement-producer-selection-492-495-20261002/strict-native-receipt.json.gz": "638ab12edb5efff30583aaff3b39ba32ca2b790d84345b7a055b5aa1554225ac", + "docs/validation/colocalization-metric-selection-487-20261002/cache-window-counterevidence.json": "c643418cbb9aaaf9da1de962b1f105a7f3272d6019e66dbe413c514fb185f07a", + "docs/validation/colocalization-metric-selection-487-20261002/common-saved-output-comparison.json": "6a3b2737c6adb71734af22dcefb3d41f2d6a3ec9960380c383652a748ee1a5fb", + "docs/validation/colocalization-metric-selection-487-20261002/manifest.json": "4df3d1e37b7f49efb6d4dfb65d657fad43e636c8a95fecf6abc4aee1fd8808e3", + "docs/validation/colocalization-metric-selection-487-20261002/qualified-controls.json": "96f34ac97ff5ca1bb96bbb50e83d4e9b49fe17b9c518f341728aff629d7db0ab", + "docs/validation/colocalization-metric-selection-487-20261002/strict-native-full.json.gz": "c84d03bf38a2e4b10e4a36feb1a7dd9f9933872b66473031f5083c371ce18aad", + "docs/validation/colocalization-metric-selection-487-20261002/strict-native-summary.json": "a73d12dd885125fa5837aad42e263ba5c6e48240c223a99039a9fd4373befb65", + "docs/validation/compiled_metadata_artifact_binding_368_20261001/PR_BODY.md": "846b72ad5b71004c44dc1a239d3911eea65b898afac99209796af63c96b6fc49", + "docs/validation/compiled_metadata_artifact_binding_368_20261001/RECEIPT.rst": "583596a6a0b36784ab93e7fff086077d95d34193e11db9fab65c329669cb18d7", + "docs/validation/compiled_metadata_artifact_binding_368_20261001/SHA256SUMS": "e7da910e4cd04d99d66cd4af4b7cc9dc2dbc650f4a87a33b4c2fae4f37b77b87", + "docs/validation/compiled_metadata_artifact_binding_368_20261001/SOURCE_FREEZE.rst": "800f4a1b25bda0885c966e2fb16387e2181b3ec879a9d23dbcf6a5ba9b7dddd7", + "docs/validation/compiled_metadata_artifact_binding_368_20261001/baseline-legacy-shard-resources.txt": "e098be0e08dea8e2ae2abd8d3b44fd9706b7ffa2487eeaa9456a54fd4d279ebc", + "docs/validation/compiled_metadata_artifact_binding_368_20261001/baseline-legacy-shard.xml": "5626928be73ca37ee3b9f968032d4669f657258034aeb0d9d9085a4cfafee14f", + "docs/validation/compiled_metadata_artifact_binding_368_20261001/capture_r0.py": "6e4399a4368d60b39cc43ea4d82cfe072748dfded55c8611d4e4f3647699a38a", + "docs/validation/compiled_metadata_artifact_binding_368_20261001/collection-boundary.xml": "2b0f0505cbe10a0208dfb2466ed4fbb6ff2d202421d63329fa2b13d9ba83e227", + "docs/validation/compiled_metadata_artifact_binding_368_20261001/final-planner-shard-resources.txt": "136faf3d79164f9f6a7ce3e7554d90b94cd0d619c2cc2685ff0cf5db34775def", + "docs/validation/compiled_metadata_artifact_binding_368_20261001/final-planner-shard.xml": "b5d0098adc4dcb011f81daa309cffb5784a1394741de205fb4aaffbeaa6838cf", + "docs/validation/compiled_metadata_artifact_binding_368_20261001/metadata-controls-binding-assertion-failure-resources.txt": "a1bf255764570adb72c3eff6b2214b574a67579e463f0bc0374bac90baa308a0", + "docs/validation/compiled_metadata_artifact_binding_368_20261001/metadata-controls-binding-assertion-failure.xml": "bc220f6fdb4f321fa25bb3dd33ba212169c3d49df8077627ca0a6fb7125a2874", + "docs/validation/compiled_metadata_artifact_binding_368_20261001/metadata-controls-fixture-failure-resources.txt": "831ed27902a79af947c433225b353f1014f951a9cd4e5d3361dc42550a628d04", + "docs/validation/compiled_metadata_artifact_binding_368_20261001/metadata-controls-fixture-failure.xml": "3b06f5e927616b0dc826f9dddfc1ec1febdd98b63760a67e076c22d6fda0375e", + "docs/validation/compiled_metadata_artifact_binding_368_20261001/metadata-controls-resources.txt": "5985fb2a1184a670d205b882fdea9e2cd5c9be1a7180f8cdb347e1f6fddbd3f4", + "docs/validation/compiled_metadata_artifact_binding_368_20261001/metadata-controls.xml": "ee2a825a1631139c223f458d48bfd2183911c6797d7efb471a6838bb707aa56b", + "docs/validation/compiled_metadata_artifact_binding_368_20261001/mro-planner-shard-resources.txt": "6496eb0aae10667c590bad24a6e5335a1eb599983fd0762773765eb46223cac4", + "docs/validation/compiled_metadata_artifact_binding_368_20261001/mro-planner-shard.xml": "17a6fa26bdf2fb3c89ebbb488b9d9763bd38ed3360121e525fdc875cde9b081f", + "docs/validation/compiled_metadata_artifact_binding_368_20261001/original-green-resources.txt": "e601f920c1119835eb0f8a65c1c2723f4f2fe239c1f25aac314996bc194f3b9c", + "docs/validation/compiled_metadata_artifact_binding_368_20261001/original-green.xml": "5519de5a0fe5480532de4f2fdb0f91b3c1fbed34deac8519e32c701b855070d9", + "docs/validation/compiled_metadata_artifact_binding_368_20261001/original-red-resources.txt": "b3d61ddda15ca06ee95df4e58f6384d29d86ce64b2d4e8e612dbb7379fd65119", + "docs/validation/compiled_metadata_artifact_binding_368_20261001/original-red.xml": "ee96bf627f8604b1e294a6edd26bfa01e28f18719d0b909ccd38a1daefd765ef", + "docs/validation/compiled_metadata_artifact_binding_368_20261001/pattern-runtime-shard-resources.txt": "60f9f4e5cefbdf5858318fbdeabfc6c6c5ef29b1e8e0c57a9d32eb5e299a5bf6", + "docs/validation/compiled_metadata_artifact_binding_368_20261001/pattern-runtime-shard.xml": "acea7a32f81c4b53d6fc98d5f0ff53bd5134b32313db5832734c9a189db60e2b", + "docs/validation/compiled_metadata_artifact_binding_368_20261001/planner-shard-resources.txt": "9a5250beb89376ad414396491ec5156642b4cf376c331adce82fb8eba9731a05", + "docs/validation/compiled_metadata_artifact_binding_368_20261001/planner-shard.xml": "aec249fa55af23238720d577ca4ebc931e577f06d956280605d2fa51bc594bf9", + "docs/validation/compiled_metadata_artifact_binding_368_20261001/r0-first-resources.txt": "56d7c2afbcd1c452cf1908d5c1a267e45afb4ae2316895b3ea4aea2dfdcbe054", + "docs/validation/compiled_metadata_artifact_binding_368_20261001/r0-first.json": "e6e403e314bf8084d9f82676c56cfef0c32a027226bf636aedd4290621aed68c", + "docs/validation/compiled_metadata_artifact_binding_368_20261001/r0-first.stderr.txt": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "docs/validation/compiled_metadata_artifact_binding_368_20261001/r0-qualified-resources.txt": "4527b1b5afaaa515d2bde22c33b26f73f8e1e23855bd1ffd2f2f8c6259a511d9", + "docs/validation/compiled_metadata_artifact_binding_368_20261001/r0-qualified.json": "b9885273c495cdddf5c081d2f9c4fc5e45246a24ee57509bad4d805b01816ce8", + "docs/validation/compiled_metadata_artifact_binding_368_20261001/r0-qualified.stderr.txt": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "docs/validation/compiled_metadata_artifact_binding_368_20261001/runtime-origin-shard-resources.txt": "760c8c5b1c5cb64a755883bdbdc040611e3c24c555bfa31572b80492273e5ac8", + "docs/validation/compiled_metadata_artifact_binding_368_20261001/runtime-origin-shard.xml": "5212829da9a87d3dfaf63558eb447e2356337584742fe4b113e2811ba59c4448", + "docs/validation/compiled_metadata_artifact_binding_368_20261001/source-edge-shard-resources.txt": "2c705aba27e7066d0ab2d9f0d22619edc01f1cb2a145c0af124eaed74e046cfd", + "docs/validation/compiled_metadata_artifact_binding_368_20261001/source-edge-shard.xml": "4712921e735971d3ed83ea74fb1df7e0d5006ef5859217de96d9555b3bd44ed8", + "docs/validation/compiled_metadata_artifact_binding_368_20261001/source_shard.py": "05f7dd98f7a449a0d86863b163807f700ba328cc9c5a1225c8fe66dd4a1634a2", + "docs/validation/context_bounding_20260929.md": "5b89b2440f9f97ad97e3d9871052ae47d4f15e0c6b1f6894f4bbb0244d06f7ec", + "docs/validation/context_bounding_20260929/build-resources.txt": "b9177265b12ec93e2b2fafd4d71000aef3cc6e177847848fdcd84fb00d3bdc4e", + "docs/validation/context_bounding_20260929/build.txt": "5d92d736ca4e0aa7086db67cf6a581c85645c7ad432516d791746386778a0c86", + "docs/validation/context_bounding_20260929/pytest-checkpoint-resources.txt": "e9d0ef10b1ca453d0387607b0603fc955956b7c6bb4a2403fc21e1f88499a3d7", + "docs/validation/context_bounding_20260929/pytest-resources.txt": "4730b783914d69df2df5559f4b496fd02d0463527176f228b0070626c9c084a5", + "docs/validation/context_bounding_20260929/pytest.txt": "c644c1958d436a41aed4ba1eac418d11ed66bca31d2750e8604ff066abdbe117", + "docs/validation/context_bounding_20260929/pytest_checkpoint.txt": "94a847d124339d6c353014d17e560447eacedc27bf567fe222fafe63686b3435", + "docs/validation/context_bounding_20260929/source-projection.json": "9c35601c2331c300256ccb088a10725bcf8b56e9df8503041543c840abac5e06", + "docs/validation/cpa-secondary-source-metadata-444.rst": "fbecd57b752d6ac6af5803d6a96698210de68332d6a147462ea5b96e2b83aa38", + "docs/validation/cpa-workspace-export-main-480-20261002.json": "83fc927bb066cc4d85ee1bfe5b14e8017dc8a5eea2ef09451c131ac3ab985e1b", + "docs/validation/declaration-selected-376.rst": "e71bf11e640a2bc50dafa1db22dd8375a161a7522412cd29db8c7eb7be01350a", + "docs/validation/diagnose-knowledge-376.py": "d09f0ed43b220a1452f02ecba88ebfca267247b2c607722c6b7b0b124d96ef0b", + "docs/validation/diagnose-selected-discovery-release-022.py": "f11048350dc61fe50d7638a4bbd43396a37f65b6aa4bcea64ee33803c794f3c6", + "docs/validation/duplicate_editable_metadata_20260930/README.md": "f804bd89cf3c89e67f822522150f6ff5c648e22640ed3aa02596a469174ee5fc", + "docs/validation/duplicate_editable_metadata_20260930/accept_shared_main.py": "10849580de618e902a8621012d0e68972e5a93d008d939a9452517d288b4d94a", + "docs/validation/duplicate_editable_metadata_20260930/after.json": "55b1f80727738bf8a89908f1f7401b72e7cff88681ad24d702ab9e2b6e9dce48", + "docs/validation/duplicate_editable_metadata_20260930/before.json": "7785adfbd5c4631aae1acba015805dce33b284fcbfce8972a91844eea5ffb178", + "docs/validation/duplicate_editable_metadata_20260930/install-retry.log": "971ea6d97b6c8cb9b7bf8288b866a9f872bee18082c864427baa1d413e212ad2", + "docs/validation/duplicate_editable_metadata_20260930/install.log": "1779b8c6f08324246a7082d7f09208f944518de3a40fde66d7b6c09769f0fdcb", + "docs/validation/duplicate_editable_metadata_20260930/perf-runtime-projection-shared-main-acceptance-20260930.json": "d5d7ea1e170f561833676c4d67c23cf899fa486f6920214d39601e4ba8169acf", + "docs/validation/duplicate_editable_metadata_20260930/perf-runtime-projection-shared-main-clean-acceptance-20260930.json": "0260592aae772fdb2062a7d5453479d3ee7d67499da663343bec89a99729490f", + "docs/validation/duplicate_editable_metadata_20260930/pip-check-after.log": "9261363b733079a641c2e4cc9bc46ffa1d8336945a87f807b6cf68847dbc9b09", + "docs/validation/duplicate_editable_metadata_20260930/pip-check-before.log": "375012431ab8acd88f801cac8b443b2122312f05f1fb9dd25e3a58d319338e1c", + "docs/validation/duplicate_editable_metadata_20260930/quarantine.json": "e3372214bde19c0260244bcedc7a7fd6da79d28c4bacf391c8e768fa0966917e", + "docs/validation/duplicate_editable_metadata_20260930/uninstall.log": "bada22327e0164fda3fcfb72fe3d3749db6138c153861ee8d0d88f5c123d3817", + "docs/validation/faint-structure-viewer-qa-396-20261001.rst": "69f9f7d3b0e5a92b3a83db317bf14625c333ea545e8bda3f1ef2abe35d0a4742", + "docs/validation/faint-structure-viewer-qa-396-20261001.tar.gz": "5e522283673fdb90c0ad5f6369ed9ad393aa3d24c3c049b040deb804e355e0f7", + "docs/validation/function-declaration-help-390.rst": "790f22ce0854f0eb8d54f7b41add83ff76174f3ae8d1d64f3213300f33db9ee3", + "docs/validation/function-help390-source-20261001.tar.gz": "49cf8f15566fa412242bbe0d8b3dcd22ab3d705564e36c23f6d0a21836929ee8", + "docs/validation/function-help391-registered-source-20261001.tar.gz": "f358213706b8dd8fba26939d4e699f0df1a29b50967e3f7bc51262b789e9d02b", + "docs/validation/generic_runtime_owners_323_20260930/README.md": "acaf4581c3404cabf9c7488b812a1d73139402125f5b72e96887cca66e979973", + "docs/validation/generic_runtime_owners_323_20260930/SHA256SUMS": "5d0c2150ce5990eb73a80c6fb7929731348c0e05002b7a2a863eebddf414fccf", + "docs/validation/generic_runtime_owners_323_20260930/apply_generic_measurement_runtime_owners_20260930.py.txt": "f811c8c56ad671caaa92d51be13c4fcf87eb55d098e22808f9c2dc84310cb83f", + "docs/validation/generic_runtime_owners_323_20260930/census_refill_preparation_20260930.py.txt": "94ce22b82a2ff871397f5aa827b79e7a390cb46c2a2fab08e77dbd19304fdd0c", + "docs/validation/generic_runtime_owners_323_20260930/check_runtime_owner_fresh_native_facts_20261001.py.txt": "33d08eea6b45dbbe76c7e0eb4afd9a861cbd832b98eb74688ed31df8993018b0", + "docs/validation/generic_runtime_owners_323_20260930/check_runtime_owner_fresh_native_tables_20261001.py.txt": "584a3b4d5d848aa9aa6400d552f6a7ca0a398160c17c92b29115d695306d1f6b", + "docs/validation/generic_runtime_owners_323_20260930/closure-global-gc-sitecustomize.py.txt": "69ce8bac6365fca894e58c666e72547f15e98ba3e2ebe154fdf7c7a1984765fd", + "docs/validation/generic_runtime_owners_323_20260930/cpu-timeline-candidate-20261001.jsonl.gz": "21e987a04a75fae94244197cca4cfaf87734ec208ca3b6555f848c76e21de49b", + "docs/validation/generic_runtime_owners_323_20260930/cpu-timeline-main-20261001.jsonl.gz": "794fe3c70b50df604d26ad73d646a946f07bc55daa22e28344fe5aaa19dd7aee", + "docs/validation/generic_runtime_owners_323_20260930/cpu-timeline-sitecustomize.py.txt": "5e6eade3d2c8b404ff7910001133bf5f51e0b5e2fa5c14780d888c1e812123cf", + "docs/validation/generic_runtime_owners_323_20260930/fresh-native-imaging-provenance.json.gz": "cde3ebcd93bbea6287a5e809225401118badd15c5c70cae2a31bf3aadfee2874", + "docs/validation/generic_runtime_owners_323_20260930/fresh-native-imaging-request_0.json.gz": "6007fd0a0bb5c49d6c2b9f2ed4536c0dc4a937563c4877dc1813ddf6508a583f", + "docs/validation/generic_runtime_owners_323_20260930/fresh-native-imaging-summary.json.gz": "84d17ba1384d1e908bd781b1b24d419d13949f804c41999634958cbd63b51fcc", + "docs/validation/generic_runtime_owners_323_20260930/global-gc-candidate-intervals-20260930.jsonl.gz": "a97203b9937186d312725de6314314f513e60e5ca4f5f65d5ffc481e53b8ac09", + "docs/validation/generic_runtime_owners_323_20260930/global-gc-closure-candidate-a-20261001.jsonl.gz": "b326124946b5391403c2874fc08961b91d9f07ac65a8e5252f291f6cf7d5313b", + "docs/validation/generic_runtime_owners_323_20260930/global-gc-closure-candidate-b-20261001.jsonl.gz": "868a746a14ce2ac5e076b069e7fd53400f9363ec9e301af66295718e89fb730a", + "docs/validation/generic_runtime_owners_323_20260930/global-gc-closure-main-a-20261001.jsonl.gz": "7c6808bb95297f94c40bd3ee1a074808bb7c4bc38e9e17c2c0d7f1f0a68dc35a", + "docs/validation/generic_runtime_owners_323_20260930/global-gc-closure-main-b-20261001.jsonl.gz": "03e545a5f82951362b3cab6260b86926e97454c893b8917d232f89307ab5afb9", + "docs/validation/generic_runtime_owners_323_20260930/global-gc-diagnostic-sitecustomize.py.txt": "1a6517c2b8c2cc8e9b1b1576f0f7c4811eb6b8b88fadb913d6081c50444465c0", + "docs/validation/generic_runtime_owners_323_20260930/global-gc-main-intervals-20260930.jsonl.gz": "8c31483ab3505148aad41f026180d5c79e875d84e95cd3846fb33bd3c2046fc3", + "docs/validation/generic_runtime_owners_323_20260930/kernel-preparation-ownership.json": "7b73fc33d3d06a0c967338f21fd1396ae51216703d200a39133117bae00f4956", + "docs/validation/generic_runtime_owners_323_20260930/make_runtime_owner_cpu_timeline_20261001.py.txt": "120db5ef628f5ea3fd637500535287b668f24aff61a253ed1653d09ea1970543", + "docs/validation/generic_runtime_owners_323_20260930/measurement-cache-and-column-ownership.json": "b04939348a028e78b884376d5aa0122d130cd767aff916c3dbfc4624679a3945", + "docs/validation/generic_runtime_owners_323_20260930/move_bound_runtime_profiler_20261001.py.txt": "476b7ebe896143deac434c944affaf7bb9b39ca4350fa1bbd9c392c40066041d", + "docs/validation/generic_runtime_owners_323_20260930/move_generic_numba_preparation_owner_20260930.py.txt": "fe0a2e90822203cff4a070e47ef02e5aaa4b8216f95afcd2ea3e8c7136f9d405", + "docs/validation/generic_runtime_owners_323_20260930/move_numerical_cache_mechanics_20261001.py.txt": "d527ce08164db70c6daa478cdc873a83ac4745758a80389fecde7dabb7a9aeac", + "docs/validation/generic_runtime_owners_323_20260930/nra-r1.log": "cd910aa324d5f1e8fc9573e18d76a546798b0f131e27cbb8b48cdbbbe4936fd9", + "docs/validation/generic_runtime_owners_323_20260930/perf-bound-runtime-profiler-plan-20261001.log.gz": "eabdb9b75fa08eedb84c33363b9e35b3e82a384a43b500c5f6f7bd21f967d46d", + "docs/validation/generic_runtime_owners_323_20260930/perf-bound-runtime-profiler-simulation-20261001.json.gz": "f149be2f9a012008661151a404d51d511a0d3b2400b5b7bed6a238f3e2f66592", + "docs/validation/generic_runtime_owners_323_20260930/perf-bound-runtime-profiler-transaction-20261001.diff.gz": "1e1c7c8d830f8906012e60598bc5899cfdfc4a44914fb3705f4ea7a678b36729", + "docs/validation/generic_runtime_owners_323_20260930/perf-columnar-export-frontier-probe-20260930.json": "5c54512dcdce2b8526bf2efc5ed75f2862649632475ab6ab78f6e5be266dd7ac", + "docs/validation/generic_runtime_owners_323_20260930/perf-generic-measurement-runtime-all-consumers-20260930.xml.gz": "715f4ebf7e8d88180eacce70b90153c783616dcce797d36ea2135bef1ef957ec", + "docs/validation/generic_runtime_owners_323_20260930/perf-generic-measurement-runtime-before-census-20260930.json.gz": "3999c8d302700616164169c4d2a1075263dc004984eaed8fb22ab1f465bbc9bc", + "docs/validation/generic_runtime_owners_323_20260930/perf-generic-measurement-runtime-focused-20260930.xml.gz": "24b9af7fa6d55c8799fc10828c6984f28042a04d55caad5b965c2fdffa244ec8", + "docs/validation/generic_runtime_owners_323_20260930/perf-generic-measurement-runtime-nra-transaction-20260930.diff": "351016c98e961a1908a59b828c09ee4fc293d1c126923be3e88783a148ecc694", + "docs/validation/generic_runtime_owners_323_20260930/perf-generic-measurement-runtime-public-comparison-20260930.json": "37c1f8f5044ac4865731904290a376ec4d52ac3d9d2096961fb9883bfc3336a3", + "docs/validation/generic_runtime_owners_323_20260930/perf-generic-measurement-runtime-public-observations-20260930.json": "068e41e5ef204ed81d194e4d74ab8f680788ad89985b26976e67fdedb1a58a18", + "docs/validation/generic_runtime_owners_323_20260930/perf-generic-measurement-runtime-refinement-20260930.diff": "5d6a203617b60d9f666b645db0f6418216b74c95f478babdba7a3dce941af472", + "docs/validation/generic_runtime_owners_323_20260930/perf-generic-measurement-runtime-unchanged-main-materialization-20260930.xml.gz": "aa6ca25c2c7710b28239424328cd5db70f45a352af6103024c92c7bb9fa50d2c", + "docs/validation/generic_runtime_owners_323_20260930/perf-generic-numba-owner-application-20260930.log": "608fd83495f1cab4d6de55f2b2594e35abee5767beef577944a0cb33fe3154b2", + "docs/validation/generic_runtime_owners_323_20260930/perf-generic-numba-owner-application-corrected-20260930.log": "547bd55b8968612ee9a7fa4e1fdbc2d8cd8539f8b2d624aa8cbee6548e6c008e", + "docs/validation/generic_runtime_owners_323_20260930/perf-generic-numba-owner-complete-simulation-20260930.json.gz": "07fdeb69d3f170e9fb5970f81c160081a2ed9f692e6610f6ba28797b8c74296b", + "docs/validation/generic_runtime_owners_323_20260930/perf-generic-numba-owner-consumer-test-20260930.diff": "02953b04c2af9f34709a77a5f8d31cd14fd63323cbe2d92016072db6da16e953", + "docs/validation/generic_runtime_owners_323_20260930/perf-generic-numba-owner-initial-simulation-20260930.json.gz": "0ef0e0ea3c540db1b0c2a0a67cf74aca0043fb3b05c3ba6eb3a5e02f4c17a51d", + "docs/validation/generic_runtime_owners_323_20260930/perf-generic-numba-owner-transaction-20260930.diff": "a4edd93a01f35364580d1a72f4d22d535cb032a385e0528c29d8f57ffdb736ad", + "docs/validation/generic_runtime_owners_323_20260930/perf-generic-runtime-cache-lifetime-refinement-20260930.diff": "442259f07ddef37242fd141c700f2364a7aa6e188c5ad0dc461dcb4dd4349302", + "docs/validation/generic_runtime_owners_323_20260930/perf-generic-runtime-global-gc-diagnostic-observations-20260930.json.gz": "9f4dcf635fd7f5edf1d93a0a6dd3b8dbaf2403efd2eedb7998ec7de98885d828", + "docs/validation/generic_runtime_owners_323_20260930/perf-generic-runtime-global-gc-overlap-20260930.json.gz": "fbbf338c32b3775dbc8cb664015ea98c344525d46c46f01ef831fc7b62f6d149", + "docs/validation/generic_runtime_owners_323_20260930/perf-generic-runtime-imaging-confirmation-observations-20260930.json": "231afd93b32397b47daf0a4b3d6d7400bb4dec8fc3d5262a016a75402138795a", + "docs/validation/generic_runtime_owners_323_20260930/perf-generic-runtime-owners-complete-native-artifact-parity-20260930.json": "0e4f21a37c8b9efaa88162c7f28bc18238a605123e4498bf6c1ca464d0eaf6f2", + "docs/validation/generic_runtime_owners_323_20260930/perf-generic-runtime-owners-complete-public-comparison-20260930.json": "2ecdf52add8d59670cad2fe7bae2382bb80fa4ee3c47a5f44f038e7dcab80ed3", + "docs/validation/generic_runtime_owners_323_20260930/perf-generic-runtime-owners-complete-public-observations-20260930.json": "c9ac1892db4386160f4671a3b1b32135543b0c6aa1ac24babbf837f1ceac617d", + "docs/validation/generic_runtime_owners_323_20260930/perf-generic-runtime-owners-paired-main-census-20260930.json.gz": "93efa739dfe467693536873670c2d35ceaa988962e16d21431d9948843fb63e9", + "docs/validation/generic_runtime_owners_323_20260930/perf-generic-runtime-owners-paired-main-consumers-20260930.xml.gz": "c07f660f556cfad7606c45da0bd2e202e98786e0aa03ed1a486229fd9dcb2c80", + "docs/validation/generic_runtime_owners_323_20260930/perf-generic-runtime-owners-paired-main-public-comparison-20260930.json": "b3c8851acfe6d889c3a4da647697a881384b3e8a06b14254c33862f8a8e4a245", + "docs/validation/generic_runtime_owners_323_20260930/perf-generic-runtime-owners-paired-main-public-observations-20260930.json": "8457700a5d399e9f1a44c5e8822844a5fd5260835424486cb5dc5e0ac5d0808b", + "docs/validation/generic_runtime_owners_323_20260930/perf-generic-runtime-owners-paired-main-r0-benchmark-20260930.json.gz": "3a090e8bc409e732966d5d5f4493b93cae8628c235f1a499e806f04493a89a29", + "docs/validation/generic_runtime_owners_323_20260930/perf-generic-runtime-owners-paired-main-r0-openhcs-20260930.json.gz": "39fc10c2f32b6527ddd922b2d7422144818a74dfcc21b0daf5a2727a20c8ff0f", + "docs/validation/generic_runtime_owners_323_20260930/perf-generic-runtime-owners-paired-main-r0-scripts-20260930.json.gz": "7fd1e33e5ed6bcc1ee3399f51106c6fab21fe96afb56baca13da4d24e2e39a51", + "docs/validation/generic_runtime_owners_323_20260930/perf-generic-runtime-owners-paired-main-r1-20260930.json.gz": "66f0f0b649c6664db782e050c8012ac444d5ee72c97c1222fca0ede32eae7c0e", + "docs/validation/generic_runtime_owners_323_20260930/perf-generic-runtime-phase-diagnostic-20260930.json.gz": "79b09a99387139ab0eb0252e707ddec5576fb1d370a886fb19e1b15ee95b91de", + "docs/validation/generic_runtime_owners_323_20260930/perf-generic-runtime-phase-diagnostic-observations-20260930.json": "260e95439002eaba2f1a079d517fbf7e82ff338821bdb286cb6619b5d0ba5232", + "docs/validation/generic_runtime_owners_323_20260930/perf-generic-runtime-query-hash-costs-20260930.json": "edfc603c06fc80f01c3caccb6a638ef201cef3d22bc74f0ea0fe2bb59380c0a5", + "docs/validation/generic_runtime_owners_323_20260930/perf-generic-runtime-query-hash-diagnostic-20260930.json.gz": "1c876e12ec9e6d7d4101e6b25311397bd1396ae8d5601dcffaad7f5d85bd4bf2", + "docs/validation/generic_runtime_owners_323_20260930/perf-generic-runtime-query-hash-diagnostic-observations-20260930.json": "9971939a1ba0f59790497f823c87c80b7bfc13b41089532c4be8251e5eaa8ccb", + "docs/validation/generic_runtime_owners_323_20260930/perf-granularity-active-spectra-production-replay-20261001.json.gz": "f5fb958c42347bd57cce48b10df065c60396c5b995c788d34f2d0d8a07e1d56f", + "docs/validation/generic_runtime_owners_323_20260930/perf-granularity-constant-spectra-production-replay-20261001.json.gz": "aeb705f6a2c2192e04121b0569e389266b8a5ca4a034af811ec774810072344b", + "docs/validation/generic_runtime_owners_323_20260930/perf-granularity-maxtree-admission-20261001.json.gz": "97acbd937fdeab5a484cfc0778e3edcd1efdbb8d0145457abdf3e8c690c21e6b", + "docs/validation/generic_runtime_owners_323_20260930/perf-materialization-ack-current-main-corrected-20260930.xml.gz": "b9848aa105498128470b5a39e84c874ae97a6c7a6b3416ebaa576f8777ea8066", + "docs/validation/generic_runtime_owners_323_20260930/perf-measurement-provenance-frontier-probe-20260930.json": "6c2e8b8e742394ebaabf1b5a90a77f2cc83aff8edc2ea9b7a994bda3531774e7", + "docs/validation/generic_runtime_owners_323_20260930/perf-numerical-cache-owner-simulation-20261001.json.gz": "5f61e515cf8cfdda7ec41642bdcb50df8368cf15601a9d11607f541939cb5337", + "docs/validation/generic_runtime_owners_323_20260930/perf-numerical-cache-owner-transaction-20261001.diff.gz": "b68864ab4ac025a031b2cf6cb0d578a58a0114fe9bb2812fe52acf4a07405bcd", + "docs/validation/generic_runtime_owners_323_20260930/perf-numerical-cache-owners-before-census-20261001.json.gz": "1a6f5fd354b349b3828917595bf625a1fce6cb095658a00d87aa9c48a5dbb653", + "docs/validation/generic_runtime_owners_323_20260930/perf-numerical-cache-owners-public-comparison-20261001.json.gz": "1607f17f03daeadfcb3ae7584b9644e38c03ce0d0f6f643fd61aca4b9084b494", + "docs/validation/generic_runtime_owners_323_20260930/perf-numerical-cache-owners-public-observations-20261001.json.gz": "0d647bc19eab2609c04dd9effe7a4d1546ddbc705261e679de0343c5dbb8071b", + "docs/validation/generic_runtime_owners_323_20260930/perf-runtime-owner-closure-census-20261001.json.gz": "a81c59e0a166b6cd7d5187d3cb98fe4644eecffa5bcbe6cc97c80a15b556e8ca", + "docs/validation/generic_runtime_owners_323_20260930/perf-runtime-owner-closure-combined-tests-20261001.xml.gz": "e22c93ed6b91282c3a9ad5772696a20d2cfb51600e4fabe72dcbff4e46bdbda9", + "docs/validation/generic_runtime_owners_323_20260930/perf-runtime-owner-closure-decision-20261001.json.gz": "4df0f9526b980d3fa365ba7291f97e5bab086b81165058b99eb386ca61d438d4", + "docs/validation/generic_runtime_owners_323_20260930/perf-runtime-owner-closure-global-gc-diagnostic-observations-20261001.json.gz": "2e99a110b98c5cb17953b082f6b65bf6f4c3fc628ef99dc227d8b59007b6e9c0", + "docs/validation/generic_runtime_owners_323_20260930/perf-runtime-owner-closure-global-gc-overlap-20261001.json.gz": "24d626dd75926894689beeaa850ad6c9b046f0d69a820ca0544cd7e6baa4efdf", + "docs/validation/generic_runtime_owners_323_20260930/perf-runtime-owner-closure-native-artifact-parity-20261001.json.gz": "97235d573eb8500fbb4a3df157c68ff21adf1a800433611b0443bd95afdf823c", + "docs/validation/generic_runtime_owners_323_20260930/perf-runtime-owner-closure-r0-benchmark-20261001.json.gz": "e54285d23bfbdc7274698b6291be496048c560a8bcae693d8ab5a58ea383413f", + "docs/validation/generic_runtime_owners_323_20260930/perf-runtime-owner-closure-r0-openhcs-20261001.json.gz": "9da0cdeae0c1a6ce89a028860270468ed8b8d752573bd4124e7c3e265f4bbb9c", + "docs/validation/generic_runtime_owners_323_20260930/perf-runtime-owner-closure-r0-scripts-20261001.json.gz": "6e1eed08ebae793c0dfb8c28a99fb8210d318095cb73692438f440193e0354fa", + "docs/validation/generic_runtime_owners_323_20260930/perf-runtime-owner-closure-r1-20261001.json.gz": "ef8ed3b62f225ee4049ff4bda30c91925e09e35f933f3bfb0ff71c9ce80c6a26", + "docs/validation/generic_runtime_owners_323_20260930/perf-runtime-owner-closure-step-deltas-20261001.json.gz": "c54b6f8d9846e2018417a634e879568386f07975525ed97c479b38ce6c713d63", + "docs/validation/generic_runtime_owners_323_20260930/perf-runtime-owner-cpu-timeline-attribution-20261001.json.gz": "0e10472d75e657b9bef4a2c64e16e1ed435fd8fc00e1fe205f654d47cbf5a346", + "docs/validation/generic_runtime_owners_323_20260930/perf-runtime-owner-cpu-timeline-observations-20261001.json.gz": "4d5387738be36f2a347f919eb1e0d4452d5537ee0512d9b5bfb35fc9c8f1a866", + "docs/validation/generic_runtime_owners_323_20260930/perf-runtime-owner-fresh-native-fact-parity-20261001.log.gz": "a5505b33d3b9dec8731ac0c1e54959cfcef8ed4d73f288de81c832a8659f489f", + "docs/validation/generic_runtime_owners_323_20260930/perf-runtime-owner-fresh-native-reference-result-20261001.json.gz": "d8b42efa1d665f118c963c756cb27abbc42ec74ef2b3a514b3f7ae523016b930", + "docs/validation/generic_runtime_owners_323_20260930/perf-runtime-owner-fresh-native-table-parity-20261001.json.gz": "7b0f898e093ec6fb7103adfbd053c96073d7f3678a0687e51dadb510db02ff03", + "docs/validation/generic_runtime_owners_323_20260930/perf-runtime-owner-native-binary-inventory-20261001.json.gz": "87fd01d23102c614e6f6eeec6b1d2d7142f438ce32574a05bf836fab4a941c49", + "docs/validation/generic_runtime_owners_323_20260930/perf-runtime-owner-native-binary-sections-20261001.json.gz": "d3b53cba58c6fa534103474240df70b182612a6ad37e9c4345ae1b7b4e33532b", + "docs/validation/generic_runtime_owners_323_20260930/phase-diagnostic-sitecustomize.py.txt": "ff2bc219b1a5268cf4a064f224d89cfcd3b0c69a32427bb6633d31074f4af031", + "docs/validation/generic_runtime_owners_323_20260930/prototype_granularity_active_spectra_20261001.cpp.txt": "751863adb3ebe1bad8d0226144ace36011a3cb7507c7075660918129e3d0c789", + "docs/validation/generic_runtime_owners_323_20260930/prototype_granularity_constant_spectra_20261001.cpp.txt": "e7d285828c814cd8e772473f26657472fc948e204ddcdb8410882d653844bd7e", + "docs/validation/generic_runtime_owners_323_20260930/query-hash-diagnostic-sitecustomize.py.txt": "1277d57e6e12687ee2815f27309dae9e97ee5701b44b83091211e0e904e26a3f", + "docs/validation/generic_runtime_owners_323_20260930/refine_generic_measurement_runtime_owners_20260930.py.txt": "788638395ab7ba7ff35bb3ad0ce15de745ad8bd028dabbca4c586d38a00ca17d", + "docs/validation/generic_runtime_owners_323_20260930/replay_granularity_active_spectra_20261001.py.txt": "44cc7382bbdf46221fb60b57923b520b806e09b472811d243cb3c3f31550b4c8", + "docs/validation/generic_runtime_owners_323_20260930/replay_granularity_constant_spectra_20261001.py.txt": "3904cd2d117602fd10873e84b1b44150345128f1f3298d66dc3d26f1fd03dae5", + "docs/validation/generic_runtime_owners_323_20260930/run_generic_runtime_global_gc_diagnostic_20260930.py.txt": "dc913b82d2c5ff5697cccc2f86a758b6be1c1da0b13fd58f75348d8591e6c625", + "docs/validation/generic_runtime_owners_323_20260930/run_generic_runtime_owners_complete_acceptance_20260930.py.txt": "bceb63cf7887e666b41659255b9c9a90711eabf9f19ba6be4ac4a300c7d81c6a", + "docs/validation/generic_runtime_owners_323_20260930/run_generic_runtime_owners_paired_main_acceptance_20260930.py.txt": "6d27682ebc27534b4239c6f521e57511c252cbbf33b46a6c055745e96b8223e6", + "docs/validation/generic_runtime_owners_323_20260930/run_numerical_cache_owners_acceptance_20261001.py.txt": "701ffd4cdc9411d5554679c04d1bc63d3da44ad1cedf7672491ffa5ed5ff66e9", + "docs/validation/generic_runtime_owners_323_20260930/run_runtime_owner_closure_global_gc_diagnostic_20261001.py.txt": "d5fea9a13a7274e107c152de14422e0c6bf6e5a619bf6df590ba46807161ea63", + "docs/validation/generic_runtime_owners_323_20260930/run_runtime_owner_cpu_timeline_20261001.py.txt": "bbd45e7ef81557afa8247897c116ace623ecde1bd57c3e11986dbc519a18c106", + "docs/validation/generic_runtime_owners_323_20260930/run_runtime_owner_fresh_native_reference_20261001.py.txt": "8c9a358652706862a06b023b732189d614e628546bfb084d2ca79813c6bf1bb5", + "docs/validation/generic_runtime_owners_323_20260930/separate_cache_values_from_process_lifetime_20260930.py.txt": "c75793d666d48231d018d00c5a9a5888484f19044dc0e5203aac91cf1763419e", + "docs/validation/generic_runtime_owners_323_20260930/test_generic_registered_numba_preparation_20260930.py.txt": "a1caf62cc3213dc4b22012d7bec071c96f69291da2be7e7813e8e910ba0261a7", + "docs/validation/generic_runtime_owners_323_20260930/test_shared_numerical_cache_owners_20261001.py.txt": "4499f08266a16f84cf98756eee83ad4c2b65d13ae12bd0d153c733a3051b3413", + "docs/validation/generic_runtime_owners_323_20260930/validate_generic_runtime_native_artifacts_20260930.py.txt": "cf1507206fed074104e432033711f4ea98762fc4a328bede9e031464fecc90dd", + "docs/validation/generic_runtime_owners_323_20260930/validate_generic_runtime_owners_complete_outputs_20260930.py.txt": "77b93bf1147aed2551cb0d4099194f17b1e9d9c203c2a11ea3f751d479686915", + "docs/validation/generic_runtime_owners_323_20260930/validate_generic_runtime_owners_paired_main_outputs_20260930.py.txt": "c1b5cb55dc12208ffad5c904da93235d6a33616a580c2775a37ab67c011f240c", + "docs/validation/generic_runtime_owners_323_20260930/validate_runtime_owner_closure_native_artifacts_20261001.py.txt": "945bfa8f8e001e9e5a3c6a231de82bf682eb1b7eb653186242af5932b0ddbb37", + "docs/validation/generic_runtime_owners_323_20260930/validate_runtime_owner_closure_owners_paired_main_outputs_20261001.py.txt": "c6965dbee67d9d759f20f22f6294c4d69840a164fe2853edf4603d8a21959c4c", + "docs/validation/generic_runtime_owners_323_20260930/validated-source-tree-95a98b008.txt": "1f47d79bc11ae78c7aa9d1740b94da396ab48969966b2d4cb254b8fb7b79f89b", + "docs/validation/generic_runtime_owners_323_20260930/validated-source-tree.txt": "6b28fec58c0a0dce691a0ab0bcd4e1372cb8c05ad71b3222d41158201d0ffdec", + "docs/validation/graytocolor-binding-axis-432-20261002/carrier-compile-diagnosis.log": "907dde7a9413803ddd90424b658d1b2bf706a7c80d6a452b13242b255e3f26ad", + "docs/validation/graytocolor-binding-axis-432-20261002/carrier-compile-parent-admission.log": "91f69e3172ceceb00ad5f426b13ec551988d97c2b2cb28069c062f4f67d4bed6", + "docs/validation/graytocolor-binding-axis-432-20261002/carrier-creation-receipt.rst": "69e0547d53be831e6ee84d1c32227fb3581e203c5b8ed8cc4db5c929c3ca5b4b", + "docs/validation/graytocolor-binding-axis-432-20261002/carrier-repair-binding-controls.log": "eb34d888882103ff4daa79c44226d7cf2ecc88682bf71b4c934729ac70fab417", + "docs/validation/graytocolor-binding-axis-432-20261002/carrier-repair-controls.log": "3800c60f6a49421a64d44c14a200054eb3e722926b05505aa7a09749dce128d0", + "docs/validation/graytocolor-binding-axis-432-20261002/carrier-repair-initial.log": "a39a2d6fd3db7dbc654ce4c860a48fc6d30e0a48c2ca439c4be0108c2032486b", + "docs/validation/graytocolor-binding-axis-432-20261002/carrier-repair-newcase.log": "5e54e8f5f865f27e2c0066551cbc93b5de7f45100a6af1c53d182b9c872f96ce", + "docs/validation/graytocolor-binding-axis-432-20261002/carrier-repair-owned-proof-controls.log": "a6059017178e17a14d030ea0b80204f502debb86acc7ce58f67abf0d90117cb9", + "docs/validation/graytocolor-binding-axis-432-20261002/carrier-repair-owned-proof-r0.log": "190618d057afb4b4a73d9282869db1e15e77d238816f57e226ff0b022c65b781", + "docs/validation/graytocolor-binding-axis-432-20261002/carrier-repair-r0.log": "cdef90688df3363145a613992dd5b033c7fcb61239bb1804d42b816f7e2bed0d", + "docs/validation/graytocolor-binding-axis-432-20261002/carrier-repair-receipt.rst": "b149e5985857b640d047cbcb23eec4c181b94f5e33e8d3dc2d9917d66aa10964", + "docs/validation/graytocolor-binding-axis-432-20261002/carrier-runtime-lanes.log": "08c1407f95b3ab3e3ec11226310d99b307832d28baef19248f207ecf7f2c49b9", + "docs/validation/graytocolor-binding-axis-432-20261002/integer-binding-units.log": "1af396a9bd634d34391fc57024211caf0d5371cd6c0d74657ec264fe7528397a", + "docs/validation/graytocolor-binding-axis-432-20261002/obligation-owner-controls.log": "0f7a895e1e12b95e52eed0609a06f5b0e2fef0647024d6223e249d35e059365f", + "docs/validation/graytocolor-binding-axis-432-20261002/obligation-owner-final-controls.log": "4f92bce420f26bb650ffc95c9095dc6e8365b0a3dd5d49dd085d3169c6c1ab82", + "docs/validation/graytocolor-binding-axis-432-20261002/obligation-owner-r0.log": "887015a10f6db24f7aca9f3e9cfac33957c1d6d73ef7c0567a06009998b6e68b", + "docs/validation/graytocolor-binding-axis-432-20261002/obligation-owner-receipt.rst": "f97f0e68dfa0bd9532447b20e6812442adaa40a5d8284fd503e2ba24266e6c7a", + "docs/validation/graytocolor-binding-axis-432-20261002/obligation-owner-scoped-anchor-controls.log": "92dd0c2024dbe42e72a15a237803c12d156058ce9c76e31e086180fe6c5f016f", + "docs/validation/graytocolor-binding-axis-432-20261002/original-assisted4-status-excerpts.log": "1e424bf7fcc646dfa9bb039f437925a39fc81b33f1f7fc25f8c476ba0cc63b51", + "docs/validation/graytocolor-binding-axis-432-20261002/original-native-excerpts.log": "31d2d4a60cbe700993e2a772fe4a5178769cc1043e828dd98179b9d896ce50af", + "docs/validation/graytocolor-binding-axis-432-20261002/receipt.rst": "e7d229284ca917e0173c714a5ebcaa5004d520f4e897ee7b98ee2118def868a1", + "docs/validation/graytocolor-binding-axis-432-20261002/source-diagnosis.log": "fb20f19413a334217179f30046bdd4d4607a0ab3cb0216c734eb048abbd305ca", + "docs/validation/graytocolor-binding-axis-432-20261002/working-pr-body.md": "82615acbe9d2bc156ee9b36facb4f3e6faf568fd5c960fc200d926b645de5e6c", + "docs/validation/graytocolor-singleton-binding-432-20261002/composed-consumer-controls.log": "06c57ff3a4615f5ebe330454a6e526ecab692d6b570a9c5b6e6300438d6a7d84", + "docs/validation/graytocolor-singleton-binding-432-20261002/declaration-plane-controls.log": "65a0c94fa21a3b5c79d03cce732792e517df9d42976a5b846bcfe9ee614f6dea", + "docs/validation/graytocolor-singleton-binding-432-20261002/existing-module-controls.log": "74ebbfbb24ebd5967e0f2e4724a40e0351ad9030ad6f0099570a8ed1a4779c92", + "docs/validation/graytocolor-singleton-binding-432-20261002/main-integration-controls.log": "eacb5e228d71398484c4b6b04b02a1bbefb97be0e8d05b4cc852c0fbbdc3ab45", + "docs/validation/graytocolor-singleton-binding-432-20261002/main-integration-r0.log": "61b329cd166dc48365ba4012fb01fcaf620e2a4c4f118d3af3c64efad7c75165", + "docs/validation/graytocolor-singleton-binding-432-20261002/new-declaration-controls.log": "a702d2b16cee42fec12ba5c41a51a1e06f39bac0264e18f6dfe7168e472f03cb", + "docs/validation/graytocolor-singleton-binding-432-20261002/new-declaration-first.log": "6f498cc3dacab75a1ce44f9dbc0430443c24c431ca8baf617ac5cbf07cf35ecd", + "docs/validation/graytocolor-singleton-binding-432-20261002/original-unary-red.log": "bea7fe37138af10be784f516570fc118efb1150442b2cf70304fb89161279c3e", + "docs/validation/graytocolor-singleton-binding-432-20261002/pr-body.md": "d798f67f805773c6c3a33d228a75532dc2136d73370cd275722641f16c65ad78", + "docs/validation/graytocolor-singleton-binding-432-20261002/receipt.rst": "89adec88cafb225ed65e623826c4980086a0737a6e02042fb3df476a5cad6104", + "docs/validation/graytocolor-singleton-binding-432-20261002/repair-receipt.rst": "09254298002cf762cb574889bb3e2594013ca9fdd8c82190d5319d26901b17cb", + "docs/validation/graytocolor-singleton-binding-432-20261002/run_original_r1.py": "0fd56084e477277733c4e8073d8c89614af38554f7d1efca78e9d0c8266701f6", + "docs/validation/graytocolor-singleton-binding-432-20261002/unary-repair-controls.log": "8b8cd3c734d070dd9be99b0b75c9dbf9ed1059e1a458cec2b878e5ca719103b0", + "docs/validation/graytocolor-singleton-binding-432-20261002/unary-repair-first.log": "f84c357bde143e5ba566fc58b5658e079aa55272a37691465c492f5449dabac2", + "docs/validation/graytocolor-singleton-binding-432-20261002/unary-repair-r0.log": "a361b4720b0fa860ebed4af5a5f6438aa52cbd073f4f341e5844294335aceb91", + "docs/validation/graytocolor-singleton-binding-432-20261002/unary-repair-r1-exact-context.log": "3f6b96ba2512bbef04c4042f986061d783a991daaa063d48dda71585854cdc9d", + "docs/validation/graytocolor-singleton-binding-432-20261002/unary-repair-r1-verified.log": "416882a9636e31bd0081d82200463b4d79f1f858f6c0da98dde6c6c8a8e2e2e8", + "docs/validation/graytocolor-singleton-binding-432-20261002/unary-repair-r1.log": "0f8a790b5dab177921b963cccd61fb94513d4293a2aa80b0fcb1e637478e48a9", + "docs/validation/gui-cold-connect-355.rst": "a2d76fd5e697217f5a65714ed5ffbfc28c49ac50bad219d9fac0b2bdeae6392d", + "docs/validation/h001-stream-plane-427-20261002/GREEN-contract-execution.log": "faabccf838d5dfe0d4297daef6a31b85445ed75bf8734803a29d304e1ed9770b", + "docs/validation/h001-stream-plane-427-20261002/GREEN-declaration-controls.log": "32eb22bf00e5e5c62f4844fbe2a03e09e95ca60a8aa39bb9f138465bce2c787a", + "docs/validation/h001-stream-plane-427-20261002/GREEN-final-stream-shard.log": "4e37ef683861fc79d6352fda0cb6d695223431e7e08a7723c7aa38f190d25b5b", + "docs/validation/h001-stream-plane-427-20261002/GREEN-first.log": "70c0a3186736f1dfa4e5f2cc03b4504fe525b721186d19c8ff3980422b9091e9", + "docs/validation/h001-stream-plane-427-20261002/GREEN-main-flow.log": "39824bd95cfc7f27a18fcea7c6c3aa5bb47181b7bb9fd6edf46b7b25d5cecf56", + "docs/validation/h001-stream-plane-427-20261002/GREEN-newcase.log": "a26cab67cdc63f2d91391eae580da7cf31a3c713072bf21d4ab1379a51efb035", + "docs/validation/h001-stream-plane-427-20261002/GREEN-strict-native-shard.log": "08fa2b6eada6da8d121075bdf39c24d62c74d8969f1984fc615cbff4daba6610", + "docs/validation/h001-stream-plane-427-20261002/R0.json": "e82f99e97fef098bd0f48320cd887c64f71fa9ec9d756d827d54159d967cc26b", + "docs/validation/h001-stream-plane-427-20261002/R0.resources.txt": "2a70155afa1e06aa58c5cad5ccd220bb9618055c5410cf7a3c648cda4ec79735", + "docs/validation/h001-stream-plane-427-20261002/RECEIPT.rst": "0721cfb7fcf65c1aa565964db405e0d92133455b58668d5f7d7c908a4177e1ef", + "docs/validation/h001-stream-plane-427-20261002/RED-original-producer.log": "334e41c5ca62bfaf4e0f46eeb0976d677e5ae58f4eb302a813277bddff989501", + "docs/validation/h001-stream-plane-427-20261002/RED-production-canonical-config.log": "723e5b0b8df0af583b7221268727e4bc057309a2d96a9adcb8e91145051a2e29", + "docs/validation/h001-stream-plane-427-20261002/RED-production.log": "18d1efe4be0240f2bddb33ac5a40bbcb94133f98a8d79ae99f0e4815f0fd17f8", + "docs/validation/h001-stream-plane-427-20261002/RED-seeded-producer.log": "6da534ad4b089b898fe118edfc4ee27bb10faa0b1ea51c46f20c60cafa5e7677", + "docs/validation/h001-stream-plane-427-20261002/RED.log": "85beb75abf569c53ac9fe104f99010dab29168d2bed81c78161bba917a9cbca5", + "docs/validation/input_preparation_installed_20261001.rst": "e6eaeb49b2e7f05af98874dbecce6b3b1570b01f455cfb8ee7a11aee77c95f71", + "docs/validation/input_preparation_parent_20261001.rst": "9bd95a547e786b42c7a1d882fcad2dca518f497afd51f177c8ee3cf4b18e973c", + "docs/validation/input_preparation_quality_20261001.rst": "1dee61ebca89b1685b12a14dbfcb9ff40f2b0cab03a10ba4eb80d0f60c61f48b", + "docs/validation/intensity-domain-skill-20261001/VALIDATION.rst": "2b37cffb0fcc0a9b94d218e7cc208c88b9912052ad8a536af2308525e852902b", + "docs/validation/intensity-domain-skill-20261001/quick-validate.log": "bb45634c2dfb41fe24517a54162996b5649fd30cdc5aa58a07998ad52b3123e3", + "docs/validation/intensity-domain-skill-20261001/registry-g.log": "5e4d8ad984fd69a1805d8c7f13ab53c5d3aff7defaab42732268c80e50a88c6b", + "docs/validation/intensity-domain-skill-20261001/tests-a.log": "c01f3653fd221c66d766a585b0ba4e28a2f9dc95894c72590a615bff6ae29c6b", + "docs/validation/intensity-domain-skill-20261001/tests-b.log": "66990fbc0235687378d87924c2137af18959472bedf5ce53e8d5e8961809d739", + "docs/validation/intensity-domain-skill-20261001/tests-c.log": "1ded53aee79417dda59e6368a2b0984d85ed5260c29b96266c8a39638a8cffab", + "docs/validation/intensity-domain-skill-20261001/tests-d.log": "fe079be6315a5667045d060eb24b67dee9be8ead2be574ea4a46c1ef9387fc49", + "docs/validation/intensity-domain-skill-20261001/tests-f.log": "7d86b8be4cd48a31f94cfb4e3d2402215d881524fdac29257822f98225921472", + "docs/validation/intensity-domain-skill-20261001/tests-h.log": "c89edf06d6e634894e9bf84abf3c14fe0a6d0deb8199a69faffe0d066584095e", + "docs/validation/issue257-draft-pr.md": "dd94b04ce76f03512d405ef63a8d8246c961473a99437e78d035258917b1868a", + "docs/validation/issue257-implementation-20260930.md": "e622c9a6df5af72bfe328873103551e5ad9fcf856c97cabf945707e672889140", + "docs/validation/issue257-runtime-composition-20260930.md": "075321618b6e138179737c75a71bd7cd27323c384c247fb894b622b3741ae956", + "docs/validation/issue257-runtime-composition-receipt.json": "f279afca16d3c4157582ee6d33a124789f5946046652086697890996c2267b65", + "docs/validation/issue257-source-investigation-20260930.md": "f02eb2feda1405140ed8c737dfb30f8d2a64894ae6ece785f9b318b78d4c048c", + "docs/validation/issue257-source-receipt.json": "047c384d28f4e74d69341876401175c4dc0a54f8ddc9717e1f7acb79d6585ef5", + "docs/validation/issue257_projection_contract_20260930.rst": "ed74c97c2688a362b1467aa2aae2468e1ec9fc9490fbacfa490f246315fb6341", + "docs/validation/issue264-source-extension-20260930.md": "f99a72aa06cb93c758f27dce28583d4f6d77ab0264412ab26f470873ddde27c8", + "docs/validation/issue264-source-receipt.json": "3563d2581846b0fab24d74b1a39c0fcb32957aad81d74afb50ea9719b13a0d95", + "docs/validation/issue355-evidence/openhcs-checkpoint.log": "076778a6c9e9a50306036070a6dafa29832e11b6c0d53c5960fc0e441b23b6a5", + "docs/validation/issue355-evidence/openhcs-r0-checkpoint.json.gz": "6521b6baaa80a213f7234a227b5505059f0facfdeec415883a4afb0347c38da9", + "docs/validation/issue355-evidence/openhcs-r0-checkpoint.resources.txt": "c02a718e6f40892816fa267a804b08f84a84449ed926f55ff4f4614534f359dd", + "docs/validation/issue363-binding-source-checks-20261001.tar.gz": "e20adeb454127d6f8a2bba945b44ef4a2a2a435f6fbf4e3a396c1bc511091029", + "docs/validation/issue363-evidence/reused-extension.sha256": "3ef64c7ce27b2bb31b60ac8321f9d10e68b1305bc619009dad3c4fe3d31ee1a4", + "docs/validation/issue363-source-checks-20261001.tar.gz": "9d6413d78a20c74a8129869c40a5a182d528f22f64d88c0341f59300d17292f7", + "docs/validation/issue376-source-diagnosis-20261001.tar.gz": "f9cbf53216cf89ce0ddd0c6ea80b5d44c35b4aa5d40f968c127215df37409321", + "docs/validation/kernel_readiness_352_20261001.rst": "1476315ac6f5b7e16fc19973e41b4518c976263a3d0e32c3a84a3e4e10289126", + "docs/validation/kernel_readiness_352_evidence_20261001.tgz": "186b39e0b8abdacffdd7a41c1b3e1bda1b0c37d75e98245e873113dd45b56f1b", + "docs/validation/knowledge-lazy-conversion-376.rst": "75a80e46208dedbb992fa34a0b166efbf7984b7daa108474b1f4f8a64720f024", + "docs/validation/knowledge-selected-source-tests.py": "55ef9ffd991301a415c5f025bee47de83a35a00f48d4e5a17e3f13cc266576d3", + "docs/validation/label_selection_346_20261001.rst": "053411e208ccbd4d57c55fed297bbc913d64a8047306d8810e579641be09c633", + "docs/validation/label_selection_346_evidence_20261001.tgz": "c665ef02ec2be0ccd743663e8f1c4335aff55411358671e3689fafbca427a38b", + "docs/validation/matched_csv_356_20261001.rst": "beecd672a88313ad63f45a9e8177ced650828175041c57481a3f7372c4cae7f8", + "docs/validation/matched_csv_356_evidence_20261001.tgz": "d33e0bcb4caa5d1c14f1929cb03a691e3a872f4b933d22938f9dd3329923c467", + "docs/validation/materialization_plumbing_384_20261001.rst": "3912d4a87180a81e1891591a27093120ac4a1e0128a441b7005988727d0912f6", + "docs/validation/mcp-affine-inspection-436-20261002/affinity-resident-controls.log": "d5c3af0a05e652e55a1a6fc418788fef9b47e8e58be8a8a691e4d37b386b1277", + "docs/validation/mcp-affine-inspection-436-20261002/bootstrap-source-admission-controls.log": "ba664407767d8db1503840a952e9a1039700ec8e9b7e5d29576572498ec387e0", + "docs/validation/mcp-affine-inspection-436-20261002/generated-progress-controls.log": "3eee7d7aa59e34ba1c71c4ef3534de6895be0370d8ccc58c1d871ea593bce153", + "docs/validation/mcp-affine-inspection-436-20261002/mcp-boundary-controls.log": "b8d8d1759c4401f5c4ecb73a6e3b62105c588f5cee67656be5044c83b2c56c4f", + "docs/validation/mcp-affine-inspection-436-20261002/pr-body.md": "fec6eb0d360da0b151f409833881b593435497c38f1e3c6752184b664d50132d", + "docs/validation/mcp-affine-inspection-436-20261002/probe_stdio.py": "3c34070e543db4f702670ffa04aaf503bfce33c6c7a0dab0f5c5e1a479f0b731", + "docs/validation/mcp-affine-inspection-436-20261002/r0-original-pin.log.gz": "23550ce952948178d8a4749e1208a6f960b2f422bdfb676fd86fa8b2abf3a3b0", + "docs/validation/mcp-affine-inspection-436-20261002/real-compiler-controls.log": "9a7d57cb6b836929853549b006fe9facdf534957621d46c563ff2224f083d10b", + "docs/validation/mcp-affine-inspection-436-20261002/real-compiler-qualified-controls.log": "128cf685659d2f17562b863122854e506f95d815128d8035771580d3d8adebd3", + "docs/validation/mcp-affine-inspection-436-20261002/receipt.rst": "2d51e7bc6db7cbfa5c9cd5eee196d6baad7d545dad7394c69506a2730a25d758", + "docs/validation/mcp-affine-inspection-436-20261002/resident-twelve-second-controls.log": "884d65cdf912c1f05bcfb20800be2c0da047c9bd5a9fa8de6b264c0d361c6879", + "docs/validation/mcp-affine-inspection-436-20261002/source_fixture.py": "cf2a8941c22fb66ec89e06d089b635718010134c540f9e182a7c7612042c5406", + "docs/validation/mcp-affine-inspection-436-20261002/stdio-original-controls.log": "2107c6e8ff29e0becadd40decbb1abebfdcf3cdb29af0290c4bc44529f29d870", + "docs/validation/mcp-affine-inspection-436-20261002/stdio-twelve-second-controls.log": "5941a0753f066157355dfa504c6b763c231c8c1395a68f3f06fca7d8de83d426", + "docs/validation/mcp-affine-inspection-436-20261002/stdio-whole-scope-controls.log": "ffb3455097892e18cceeefaef44563d8577f2ac85a46bc9516b4fa2352ef9120", + "docs/validation/mcp-affine-inspection-436-20261002/stdio-wire-controls.log": "80aa37d9fad7cd43435d6798b535b558d6b9fcc30b36315cad0dc172173b386d", + "docs/validation/mcp-affine-inspection-436-20261002/stdio-wire-qualified-controls.log": "341bd70033a13eaecdf050d52314a12e56ff095f9c5cec9340cef00a7a9c49c6", + "docs/validation/mcp-cold-inspection-feedback-436-20261002.rst": "60dc29871484fceb90f0a7eeb30dc9d6b458902a4c14eec6cf4385ff0469b6e9", + "docs/validation/mcp-jvm-lifetime-455-20261002.rst": "dc9ffd17d81b73bcebae79b4886cf4fc97d0077b89409454d1ad15147f12d1cc", + "docs/validation/mcp-jvm-lifetime-455-20261002/qualify.py": "f806e5105cc0ae01e4f97e3650bec5b6b530356afbe5b392c9f7a920e97bf173", + "docs/validation/mcp-progress-ack-20261002.rst": "c58f0b08879fce9de65df3f12b7926efa3bd9e5c6d364a177b306c5d0cd973fa", + "docs/validation/mcp-roi-stream-progress-441-20261002.rst": "78eb8fd599f8987b4c1522835199322fe5e2cc6578def585aec897492342f72f", + "docs/validation/mcp-terminal-input-483/INSTALLED-ACCEPTANCE.rst": "bf9d6ad92834af37c39165fac3b124b1c7222787dabf4039226574d4a742d193", + "docs/validation/mcp_local_argument_errors_20260930.rst": "ee95239a8530e56ba2d84bf83b00196b645c2860308a2d4dfdce30f301ac6d2b", + "docs/validation/memory-session-20260929.md": "1be51da878f05a777d916e56b7479be6a7fac5c39ca08ae90991352a915a9fed", + "docs/validation/memory_current_main_integration_20260930.rst": "5ba2810cc9c3df769aeeae9920c39496abf8f99495300238dbbdb93a0f1cb74b", + "docs/validation/metaclass-registry-022-publication-20261001/RECEIPT.rst": "45eee23e4ec97cefbfcad768f165e9e9ee8d58b035656e11b555db85d4eb6369", + "docs/validation/metaclass-registry-022-publication-20261001/SHA256SUMS": "2793231c3c5665011cd2ae5623d5ec54d91853fd7132b1e0f66341a3e3768572", + "docs/validation/metaclass-registry-022-publication-20261001/artifact-verification.log": "0beee0649d3efa7468b4f630d1202595d0bdc81180fe08127d492e298c00f493", + "docs/validation/metaclass-registry-022-publication-20261001/artifact-verification.resources.txt": "25afa796fc6061dd476f43347c8c74a3d8659ec1dc1f8955c5a0f08a905a0ff4", + "docs/validation/metaclass-registry-022-publication-20261001/artifacts/metaclass_registry-0.2.2-py3-none-any.whl": "67ae17c58d9d10cd58acf83ebe01833c1f1fe0a1a2e281924fab836958d592ed", + "docs/validation/metaclass-registry-022-publication-20261001/artifacts/metaclass_registry-0.2.2.tar.gz": "540bd730c52a535e08866c487b34aa4f9cb2fe857eb07a312882cdc43a15517c", + "docs/validation/metaclass-registry-022-publication-20261001/github-release.json": "742a3ac59191573de6dc09097b9d7890776e950d28542d30b75185b232c2fab3", + "docs/validation/metaclass-registry-022-publication-20261001/job-queued.json": "0422e1a4841db83e61d052634a80036358978812d6b07215d46c53553d34a177", + "docs/validation/metaclass-registry-022-publication-20261001/pending-deployments.json": "4f53cda18c2baa0c0354bb5f9a3ecbe5ed12ab4d8e11ba873c2f11161202b945", + "docs/validation/metaclass-registry-022-publication-20261001/release-session.typescript": "0231889209c76b3d9f6fe4c11dddba6d8cc91359010d82c3d83e967d27cb94ff", + "docs/validation/metaclass-registry-022-publication-20261001/verify_publication.py": "9690d44f2e0426c5ffb19d80356df2f41c32b7ea5a24c144912e8632e5fc8960", + "docs/validation/metaclass-registry-022-publication-20261001/workflow-initial.json": "7b80e7b28ee1f3111fd7462853e15636d064a368726e6f1d3898ad465036c3f9", + "docs/validation/metaclass-registry-022-publication-20261001/workflow-terminal.json": "13a18c7696575cf7ec50bbe4c0787637880fcf76471dc46570ad983a31e7598e", + "docs/validation/metaclass-registry-022-publication-20261001/workflow-watch.log": "0470677218e39615ce28d29f1bd1747c4017ce4d6113bcf52a475a22933fd498", + "docs/validation/metadata_namespace_327.rst": "a7d4213c30ea3fd731ddc08565c9708499d7f6782ba8ee4484c688d9ddc5bb78", + "docs/validation/metadata_namespace_327_resources.rst": "aa889cde67e850e2e6452b3a2cf892338304d06df5dcdc70b42fd40afc70e3c9", + "docs/validation/metadata_namespace_327_source_evidence.tgz": "05b24739c81fbdc86c3dbc9e96f45e1764a5f50ffe946953271c386df68c8dfa", + "docs/validation/morphology-library-readiness-481-20261002.rst": "d0330dd4c8466200f166799f78fa99bb37ef4c2f0436cb1b7111a93665754a02", + "docs/validation/napari-source-channel-presentation-448-20261002/pr-body.md": "05d7d27c19836a7a57737d9ae69320cab55bebc76023244a3d1a8ef0bd35801d", + "docs/validation/napari-source-channel-presentation-448-20261002/receipt.rst": "5ab74657d73dd22abe3928c2e76de01181805b5b3710a601c9427def457c8cb0", + "docs/validation/native-presentation-451452-20261002/complete-presentation-final.log": "0e449d5f53262937e0b1b7994355c2024ca392ba343f12300f98774347613dd7", + "docs/validation/native-presentation-451452-20261002/complete-presentation-first.log": "29286b91f073c7b6fa2385bdaeb6f6e0123fb5c07a9d14a8a5421ca1e1d17a49", + "docs/validation/native-presentation-451452-20261002/complete-presentation-second.log": "5b5316ee7bf57b71e000bd83d80eefe4894e5b7731b7354fb5c35c2df12bbddb", + "docs/validation/native-presentation-451452-20261002/display-admission.log": "0071b826032c2b52f5ae8f88f6e2b18fb26887cc90d91ed3f29ab0371f90d9dd", + "docs/validation/native-presentation-451452-20261002/final-original-r0.log": "150466f41c07f5c911070b4986bf028bdde2349a226dfb6ed11ead9638d7f05d", + "docs/validation/native-presentation-451452-20261002/final-presentation-controls.log": "26626a2a8dcec2311a16b79651bd9f2164cf6778bc4c0ceb3394277db0945e9b", + "docs/validation/native-presentation-451452-20261002/mcp-controls-first.log": "6647123a7108427adfccd39227c7d8f115d5caa2036be8056556846a9f844513", + "docs/validation/native-presentation-451452-20261002/mcp-record-descent.log": "e7de3c456abd999d9bd863b42c93ca776a369a59a6a559082608cdf60284d3a3", + "docs/validation/native-presentation-451452-20261002/merged-main-ast-closure.log": "31454a498ba95dd73ad41e654e9de469cf7765ba4abde917f38e3f6ffd354804", + "docs/validation/native-presentation-451452-20261002/merged-main-native-controls.log": "b058c5cef92808c5de09573179b76d59a018e164ff9ee6473fc5d1eb095645ff", + "docs/validation/native-presentation-451452-20261002/merged-main-original-r0.log": "f9a615a12b5d67c05cd3fa47ed332436a86c9b8021e4d99d7a91cc99f5c4a3ce", + "docs/validation/native-presentation-451452-20261002/merged-main-public-mcp-controls.log": "aa0a2211d3676d0c547422e19d504611ffd647d8947db7bd23bbeb5b40d959c1", + "docs/validation/native-presentation-451452-20261002/native-and-consumer-controls.log": "f37fd50443d138e23f4c6bdf9a9df32c2add50d56d63805cb6193dc734fcb432", + "docs/validation/native-presentation-451452-20261002/native-family-integration.log": "a5fd1911a024aad9ed195e1a328252091f862c04f6fc175c1b0541ca8af03c3a", + "docs/validation/native-presentation-451452-20261002/original-presentation-controls.log": "eaf958911e7d9fa199633a2485ec2df017f416000e49372311e306f18f51832f", + "docs/validation/native-presentation-451452-20261002/original-r0.log": "003f1092ae56bae05efceff379520e6c14c0a77fc2e4dca297e38eb267630c61", + "docs/validation/native-presentation-451452-20261002/ownership-after-linear.log": "5e34488b9cba397149c88c16e05f0838baaabcfdb72ecc5842536a1cb312256d", + "docs/validation/native-presentation-451452-20261002/ownership-after.log": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "docs/validation/native-presentation-451452-20261002/ownership-before.log": "8a95a83d3e8d3aeef953cf69483060436246dea038fd77840d743a161e38e3fc", + "docs/validation/native-presentation-451452-20261002/pr-body.md": "48a44086b2e0e03d585412f27384f82a3bba9f096b2d5e792e83b209d505193f", + "docs/validation/native-presentation-451452-20261002/qualified-native-controls.log": "d6e2ce08fc95bc04037a5e690298dd516bcd0f092acfc68477c2482e8a9a4d10", + "docs/validation/native-presentation-451452-20261002/qualified-public-mcp-controls.log": "4b6aca8b6d87466feb33c679dd70e9dbfd616705ee9adbe2e54cc1f8a5d490b3", + "docs/validation/native-presentation-451452-20261002/receipt.rst": "00e217a1229aafb420c69553946c14c11da601c28311b733a41e3c9bdd934e81", + "docs/validation/native-presentation-451452-20261002/root394-roster.json": "28f2c08e5b9cd7f33201db1c757b187207069a993205b9cac65d8deb6961f606", + "docs/validation/neurite-primary-diagnostic-consumption-410.rst": "b62f5b9f224eecf34c856b360153a5e3d5b7650b7c0fa3be0b7b523958479b87", + "docs/validation/neurite_body_gate_424_20261002/ARCHIVE-SHA256SUM": "50a5d341534d3a7b9587b26bfa26c9d049d74c257181aeadf48c8d7e56519109", + "docs/validation/neurite_body_gate_424_20261002/EVIDENCE.tar.gz": "857540666bfdc5583f3c87ded48943e5b7c0e21b0e0247c8743f2284708c017e", + "docs/validation/neurite_body_gate_424_20261002/QUALIFICATION.rst": "e8813f23c315ca5042479bf009705226625a72c59edb75c00676ddbe6941b226", + "docs/validation/neurite_body_gate_424_20261002/RECEIVING.rst": "5c7085dff22e4174109cb9e107dc234ea8691cc0a144beef8c267ac30c709c4e", + "docs/validation/neurite_body_gate_424_20261002/SHA256SUMS": "09e4cd4781b7c923d5b1a8ef840192cb5ab9b6835b3ce6a8a11c118e52b950b2", + "docs/validation/neurite_body_gate_424_20261002/SOURCE-SHA256SUMS": "eaaa78f729074d50787d5457dc35e2e797b32445f3f10a1a49bcdc9c379ad430", + "docs/validation/official30_qualification_330_20261001.rst": "e2c8006699d88990d35d1ced74a1145121b3818d65d69abd0560ef7f77d6fa58", + "docs/validation/official30_qualification_330_evidence_20261001.tgz": "6b17e4ed0bae1cd460607f4618772868d565d9377270819f5049c2caf4c672ed", + "docs/validation/opera_producer_inventory_172.rst": "bc34a6c7cfccc142d08f8941a6b21cb86428010997a8b63874f696011593e81d", + "docs/validation/opera_producer_inventory_172_main8c512_evidence.tgz": "df6cb051e96b6eded6860958ffecda1e3debe57412342676becffb9ba0676c4a", + "docs/validation/opera_producer_inventory_172_source_evidence.tgz": "326541e4ccb3a4b5378ad4322614c4d9bdc03448bba9575535548f02285aaa7b", + "docs/validation/opera_singleton_172.rst": "8a18127a76354e80be69509c2327b2f9bd5a06707f09f785cff6c947c0563bf0", + "docs/validation/opera_singleton_172_source_evidence.tgz": "f46c0a64917011026493d4c60e9435995534fb0e9574e0e6e42aa906d21d9b9b", + "docs/validation/paired-feedback-integration-358.rst": "78d7ea521016daccf366d5509829cfac7131316d404d9f8c32b94d2e1a289ff3", + "docs/validation/paired-feedback-integration-evidence/PR358.md": "a5a235895998d822b5b8f6fe3fcf47aeaea22c7e854c73dc09f5233025263150", + "docs/validation/paired-feedback-integration-evidence/SHA256SUMS": "5318151d42951c7d1431dc8ac6fae33056ec5e4cd27c7a3ec6793eec7619ad65", + "docs/validation/paired-feedback-integration-evidence/ZMQRuntime-PR13.md": "8df33100756cfb58c864fbd5cbed8e3908ce41906c670c22e2cabc2b3d2e2a5f", + "docs/validation/paired-feedback-integration-evidence/openhcs-r0.json.gz": "0f9a85aaa787e6cd63d3cae3777dc5ad8909f337ef30eb02751ba791ab4b0e0e", + "docs/validation/paired-feedback-integration-evidence/openhcs-r0.resources.txt": "52e4c5d1f650a129a1fca859793b7e97810e1439eab32ca58013a748fdafda5f", + "docs/validation/paired-feedback-integration-evidence/openhcs-r0.stderr.txt": "7986c663bbeb1f7f77b571bafc6773e8872d8666c1d2c23bd92dd33316a7ba82", + "docs/validation/paired-feedback-integration-evidence/zmqruntime-r0.json.gz": "9a2ddba42722c036ed795cc8d143007e74784085818c8fa2b6544b4cf1dad0b1", + "docs/validation/paired-feedback-integration-evidence/zmqruntime-r0.resources.txt": "b224497a3d60be1870e4dd8f14c4ce9690f22a7ab13d999d96b40fcd4ef12a13", + "docs/validation/paired-feedback-integration-evidence/zmqruntime-r0.stderr.txt": "b9156d81a5171a0ed86908a6e9d1fca8d5da5690a831aecf279e5f3b4252dcfe", + "docs/validation/paired_field_csv_314_20260930/PREFLIGHT.json": "09bc36d6a804f1601315bb842a3c67852ed5d08f5a71b6fc632dd6f7c7a1e12a", + "docs/validation/paired_field_csv_314_20260930/SHA256SUMS": "a9ab37c955e6f625f76272f318fac729b34c83fdc6af68ef6a434259e4ffaa82", + "docs/validation/paired_field_csv_314_20260930/check-installed-parent.py": "73461928418fa47201eae32d855d563a52ee5301a800cdba6ed41e697ef33b16", + "docs/validation/paired_field_csv_314_20260930/checkpoint.rst": "e935c5bcb0d0bf4da40c68f855bff5afa484c6b1a6e667405004cb06164f0cd7", + "docs/validation/paired_field_csv_314_20260930/core-census.json.gz": "f7a149a70dd9f82cadd4b1b43eae69a6c70354d04c870113bae2e80d6c697fcf", + "docs/validation/paired_field_csv_314_20260930/core-census.log": "abcc421cce2ad109a4be6f9bae9c7ffdb80c48725a416bf4db5f60266fe610d5", + "docs/validation/paired_field_csv_314_20260930/core-overlay.json.gz": "22a3cbbcc9ac4d15b10c6ae38d5b930fb2a37a687f832f978d29543d803f399b", + "docs/validation/paired_field_csv_314_20260930/core-overlay.log": "f842402ed5c9f2eb35f5a9abeb97ee7342e1e0269233d2149aab2a3b03ba4318", + "docs/validation/paired_field_csv_314_20260930/create-live-fixture.py": "f9a61c9e5235a38f21f05ae4d43a44a543adf1208d1f3e4c412d8ef1dc6c0475", + "docs/validation/paired_field_csv_314_20260930/effective-imports-error.log": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "docs/validation/paired_field_csv_314_20260930/effective-imports.json": "6260f67c73bdbb1e138b9733e3100f9c3b82daa032beaa1ab821891a830b8d68", + "docs/validation/paired_field_csv_314_20260930/final-policy-exporter.log": "2d22257b758889c28b6cc68e230075176e81e94b8b3eb5b93f0c8c0458040102", + "docs/validation/paired_field_csv_314_20260930/installed-parent-checkpoint.rst": "89baf9a17dce5bf5d91e0fc48791e7936b88034e59de9c0018cda40223f8727b", + "docs/validation/paired_field_csv_314_20260930/merged-main-census.json": "4e6b60bb28c884fddf203e176e39b6b2a8fec79b0db065e2d3fb87bfc11967a1", + "docs/validation/paired_field_csv_314_20260930/merged-main-census.log": "2a91055d7bc8f70cd70a234c0970babbf0bedf15cfce723dfecd4e028032cbb1", + "docs/validation/paired_field_csv_314_20260930/merged-main-owner.log": "bf1aee9710d476cd67ea9ef6e6a03805d50498d1dd38eb1f3f7e325e7fd2a1bd", + "docs/validation/paired_field_csv_314_20260930/merged-main-related.log": "ef34e28b0d9ebe85c9a364f9d64bcba276f1af3de33c782a5452c74d8dd665b5", + "docs/validation/paired_field_csv_314_20260930/nra-original-resources.log": "45bb910ec84bccf47c98eab8d48668058c32f888bf3337eadf6af54ebdcc69a0", + "docs/validation/paired_field_csv_314_20260930/nra-original.json": "76efdf6231fe3d520aa5aad4ed07aa619696ed0a1bbc0d9ac58207439fbc1d1c", + "docs/validation/paired_field_csv_314_20260930/nra-owner-loop-resources.log": "ca8e2518377ceb506f4b6616de041d8e5901d3abb7d53499aacacd284927f365", + "docs/validation/paired_field_csv_314_20260930/nra-owner-loop.json": "85fa34cc7c9365e1433cf13cfde3728b93e826212a862d5a896ee50f24215587", + "docs/validation/paired_field_csv_314_20260930/owned-disposable.tar.gz": "0ef110ed10150278f09ba7ea4abf837c87f163d834794a99f26731ec3b722a69", + "docs/validation/paired_field_csv_314_20260930/owner-census-delta.json": "4068fc6aebd829bde62c38c9fd8a9c980ff2480214f9e68d638684cb643d6bef", + "docs/validation/paired_field_csv_314_20260930/owner-census-delta.log": "d221f41dafd990a5434428d86703b59b1eec66fb99c6537fb40a0c52bdd1205f", + "docs/validation/paired_field_csv_314_20260930/owner-fixed-corrected.log": "8db82b08046f81c30100fe92751276352cef7f8a444a3297ec4df82ce2d95c0b", + "docs/validation/paired_field_csv_314_20260930/owner-fixed.log": "d50a0ddd323c80c4992f46e4a96c8a3a1515c6787ee2ad5f86191357ac964989", + "docs/validation/paired_field_csv_314_20260930/ownership-receipt.rst": "d8375d089d79fb532af311d7d3b8f1509d0f21e9e045b7cd14a9ed04a132f509", + "docs/validation/paired_field_csv_314_20260930/pipeline-live-parent.py": "37ed9534c0acddf3e8a71c62314997435a0dc8cb19f9201528fae1b7f84e5ef1", + "docs/validation/paired_field_csv_314_20260930/policy-import.log": "17988389f4355b8274b59fd1141bb8aa5757b6cb6adf94fe879c0b199ca023e3", + "docs/validation/paired_field_csv_314_20260930/pr-body.md": "6b76484efe7c0bcd2634c61337c0f73018d457338bfb077c05c836ec42e3b481", + "docs/validation/paired_field_csv_314_20260930/related-owner-contracts.log": "77b93b241966cb96c7e7e8e2adc7964d488abbaa14fb2ab94e74ddb1598c3673", + "docs/validation/paired_field_csv_314_20260930/reproducer-original-built.log": "63ad8bd8fac5a6a06141b607f4d6bd51145a8952ee63bbc9c27c844c07724dcb", + "docs/validation/paired_field_csv_314_20260930/reproducer-original.log": "9aa5f6c2c1dd4b980dc653be3b1fca951a5eb42ba05e2a99709140190f08ffd0", + "docs/validation/paired_field_csv_314_20260930/ruff-focused.log": "93abbe5307fdb809eae183b7e3fd79f276fb1044b1e889cf95ae3ec754dd36aa", + "docs/validation/paired_field_csv_314_20260930/run-installed-parent.sh": "206e183ccb312731fea5e7c66b9a536c633c0e0de659beb49932a30bd6244752", + "docs/validation/paired_field_csv_314_20260930/source-anchors-base-empty-snapshot.log": "9a5daa28530cfdb8a9a5dfaf7e4469862c7755067be421ee89f83f824ac2a6d7", + "docs/validation/paired_field_csv_314_20260930/source-anchors-base-verified.log": "05d26c97cc6db8b17026c5dfb984b13f5cc667479d0962613118c6d764edc22e", + "docs/validation/paired_field_csv_314_20260930/source-anchors-base.log": "89e8f8287e324c431d734ec1f3dbb247459ed329ec939cc9478143cf239ccba3", + "docs/validation/paired_field_csv_314_20260930/source-build.log": "5e739265347dec1ea5319579c3575f0ca9d4ba12a0a6c4209cbab692196c0b50", + "docs/validation/persisted-result-reopen-398-source-20261001.tar.gz": "7c1f69c9663445e9a489a86d593eaefe5dc1b71bceb1cac183058b2f3d6502ee", + "docs/validation/persisted-result-reopen-398.rst": "332c29d0070e41bb404d4c0205110a7653bf090dd43fb5598442df8b97b177a3", + "docs/validation/persisted_result_publication_134_20261002.rst": "5521ecb67990b8598faa704bf76430dc23f4b460895cf23d83868c80d355b213", + "docs/validation/physical-source-inspection-445-original-20261002.tar.gz": "f60cedd5c063c2ea06c23bc3902125bf013f459648f2700acdb5dd8eefe99fba", + "docs/validation/physical-source-inspection-445-source-20261002.tar.gz": "ffc8001ed2d76c43626f6154f84b06fa54a4b1865f209ab4a00212d9b6ccef8a", + "docs/validation/physical-source-inspection-445.rst": "1a82d5fe328a0a199e097d79125eb441934059b24942c5cda1ad9f8a63d79528", + "docs/validation/polynomial-library-readiness-473-20261002.rst": "784accee8adad50b3ba146596add42406b2119275965d50f0ec9ebca54f10654", + "docs/validation/preparation-admission-355.rst": "e3ca89ba99ba4d48388b000b7cc011eaf4da630b85ea704379e1125c8bd9478a", + "docs/validation/preparation-admission-evidence/SHA256SUMS": "b5c6cb1b83ce8ff6d35ea9ce172f078f6165a4493d8e1d5dde593c66ee3c41de", + "docs/validation/preparation-admission-evidence/after-checkpoint.log": "b0447f8cfd6a8ac550889aaa4d0e0ad5651fb7067740e6003d6bdae6d1af3167", + "docs/validation/preparation-admission-evidence/after-initial.log": "05a2c1cff034b92c78db1774241e0dc96a95a0f92f8928b1e7f2426fda9b4221", + "docs/validation/preparation-admission-evidence/after-paired-source.log": "15cb97e5524a2c776df6d3dd806a1b5bbfe456635c089fc749ad219de3f533ff", + "docs/validation/preparation-admission-evidence/before-with-native-dependency.log": "98aea15afd57065d6b2a3616521c2516c71a0f3bad3560837ebdbf793b1dcf15", + "docs/validation/preparation-admission-evidence/before.log": "e04fef9816be769f039bc3403c705cd221a00d2107a784edf0cd93e5938e5ae0", + "docs/validation/preparation-admission-evidence/manifest.json": "5f5212b235270e3131957c894366d608866140e8cee15d189e85030b06d46069", + "docs/validation/preparation-admission-evidence/r0.json.gz": "d8c1f6c1fe25438b3fdde770a40702ac429594419e1782b374cabf278c088693", + "docs/validation/preparation-admission-evidence/r0.resources.txt": "85ed6d829fdf9f34f335d8809e922f755473de3fe92c77d31a17a35c423197ac", + "docs/validation/preparation-admission-evidence/source-owner-profile.log": "c5792a79cba3868812d96fa7027ca0fbfcfe50f1f99b5f3e0291a553a8516517", + "docs/validation/prepared_callable_signatures_419_20261002.rst": "bfe3cf254f75a2927919f38718927ed7956395909ad48d48e37fdcf0774642a5", + "docs/validation/primary_diagnostics_current_main_20260930.rst": "e44fb70f5df372fa11b495952942a7fac30a777c29105628079fbf17fc0962f3", + "docs/validation/pyqt_zmq03_dependency_20260930/README.md": "95b2e6dc991b8df24e621c702bb5b494d88b5777a84dbb63014f81d476593642", + "docs/validation/pyqt_zmq03_dependency_20260930/normal-resolving-install.log": "3ca114de7bc8509814f0476b3237799158e505ad56b3bde03e1d65dff9a63d0c", + "docs/validation/pyqt_zmq03_dependency_20260930/openhcs-consumers.log": "cd716188cc66c2cffbdcf62f21534893a8aa4e071587a1760dc59a31df7646cb", + "docs/validation/pyqt_zmq03_dependency_20260930/pyqt-consumers.log": "f80274d2745eee4aabafa0a8a73f8f3d8826bdf9dfa95b5a2d813fbf845eaed3", + "docs/validation/pyqt_zmq03_dependency_20260930/resolver-counterexample.log": "891c272ba48618d0d646af3aa8572fefbec747ee4efa0745bbf7effa83ab7f0e", + "docs/validation/r0-policy-fixture-invocation-20261002/CLI-SOURCE.py": "b1446d088d0da9f004c20082cfbc771c1384f28b131e69b26bf0470b63c31961", + "docs/validation/r0-policy-fixture-invocation-20261002/PLAN.rst": "51e2f94277e9b8d4af6977dd15aff57041425aed2de29132c37eb0dcb7edefc7", + "docs/validation/r0-policy-fixture-invocation-20261002/RECEIPT.rst": "2060d0d8796bc3650a2826cf93cda2b577cfed32c04c7807a57acbaa38e02bd7", + "docs/validation/run_metadata_namespace_327.py": "c2c42e718c51ac5d388b3091808fea5e8e385e5908c3b3a1c499b45e7799dcea", + "docs/validation/runtime_bootstrap_20260930.md": "37c444da091e57ea5ad47634d6f94ac8ab7518cb61b8c4053592b429f45a5d44", + "docs/validation/runtime_bootstrap_20260930/close-dependency-census.json": "5dc06e14485b6fb48713496568760398b6d41508299faf88ca369c38b524eadc", + "docs/validation/runtime_bootstrap_20260930/close-dependency-census.txt": "ba0a3ca99e97fe18b76b61294729c9aea4f6f9b48fcc360876cf5b06c18df3b9", + "docs/validation/runtime_bootstrap_20260930/close-source-census.json": "154026a741b6c991b9b0a9c2dd4c10ae59214031b725a9189406ccbdb03816ce", + "docs/validation/runtime_bootstrap_20260930/close-source-census.txt": "34d8fb01701dd0800223c5f0cba5af77aa55fc4ba7f2c0d916ca4fbba304bbd9", + "docs/validation/runtime_bootstrap_20260930/dependency-census.json": "f3b2643a5cb52a26c0e313a9dd98ea111df3d92a4b94e212d5f154ab3a1b44a8", + "docs/validation/runtime_bootstrap_20260930/dependency-census.txt": "16e8e97d1ae50311ef08160df72ab5abec680b191ba05b13ca5aa0f74bfc1e16", + "docs/validation/runtime_bootstrap_20260930/effective-transport/checkpoint.md": "7ff7d046f27b8c86829b3cca146cd147fa6cfdcc92939ce5ac3132c433388ddf", + "docs/validation/runtime_bootstrap_20260930/effective-transport/parent-witness.txt": "d6f1cca0afcfd86a7262cdf778ff55d6573e1995d968671830630f90411687d4", + "docs/validation/runtime_bootstrap_20260930/effective-transport/source-tests-b.xml": "430f95d1d0aa90a5b2295e834209cb1ec712106fb056ecae9e36952600fad763", + "docs/validation/runtime_bootstrap_20260930/effective-transport/source-tests.xml": "868283cb8f29b798d09ab87435df24237fbb05f1727a98ee01953fc49fd9c1a9", + "docs/validation/runtime_bootstrap_20260930/launch-plan-factoring/checkpoint.md": "57ce52fa593f590e5fe9b300047d2f92b2b06d09778203e797510830d8703fbe", + "docs/validation/runtime_bootstrap_20260930/launch-plan-factoring/source-tests-b.xml": "3aef4f99246993a53a89b5039005bbeb634c6de20d694376c3e164103f089efd", + "docs/validation/runtime_bootstrap_20260930/launch-plan-factoring/source-tests.xml": "6877aef3cd2456489c582f271ebd32e7ed709ebec273b1ce9a7bd13b59fce5e7", + "docs/validation/runtime_bootstrap_20260930/native-attempt01/build.txt": "52ca8c419407854176ee38bed15f7203eb3efcb31e3a5c8ef83cb150a53f7396", + "docs/validation/runtime_bootstrap_20260930/native-attempt01/checkpoint.md": "be3da4dbf04c98c71653792b3848801b85a1c210a04bcc0c64affb63ac4f4abb", + "docs/validation/runtime_bootstrap_20260930/native-attempt01/journey.json": "dd3c9669f14a11fa2662ce9af90d8329dad9fce3ba6fc8e4ed847b26342eae7a", + "docs/validation/runtime_bootstrap_20260930/native-attempt01/mcp-stderr.txt": "fc2c6374f06e95a9eb5610df83cb510fd1eb89c0e174891b897355ace2f3bb5c", + "docs/validation/runtime_bootstrap_20260930/native-attempt01/pipeline.py": "6aefbfb68105340f7eb0acce68ea712022ec3e27ba3a58ca0d940d8911a30c1d", + "docs/validation/runtime_bootstrap_20260930/native-attempt02/build.txt": "e5dfa59d188c5f682207e4bd7a6d3ef0ef24b75e8054f888e452f50e0e2609e6", + "docs/validation/runtime_bootstrap_20260930/native-attempt02/checkpoint.md": "ccb81b00a94042d9e812295d3fd4f2ddd36d1ccd9f155d21ec2ab684dd65a891", + "docs/validation/runtime_bootstrap_20260930/native-attempt02/journey.json": "2163e36b97a64be121ef167d8a58be52c992328b948dc6331c79671ed45454e7", + "docs/validation/runtime_bootstrap_20260930/native-attempt02/mcp-stderr.txt": "57ea5239335f3732bda6ba2b19002c02bfbc13f7bce1ec8f27ba1d0eb2b68261", + "docs/validation/runtime_bootstrap_20260930/native-attempt02/owned/data/openhcs/logs/openhcs_zmq_server_port_5964_1790754393037041240.log": "314bb73133434779bd2b5bc8504dd20cc8152cc8fb67109890d96a03bde4f947", + "docs/validation/runtime_bootstrap_20260930/native-attempt02/owned/data/openhcs/logs/openhcs_zmq_server_port_5964_1790754393037041240.startup.jsonl": "52e82e6734e3ce65c1720870a0b0bd33cad8fb85a8a3757d972d061f8ed4ca15", + "docs/validation/runtime_bootstrap_20260930/native-attempt02/pipeline.py": "78614093b82ba33ff428888760b1e7aa7cb1f1fc8d0ffa27b13e81c5fcd1dede", + "docs/validation/runtime_bootstrap_20260930/native-attempt03/build.txt": "185868583dd50801adb4d64ad1e26e8f5f9273f22a8ac918b2de1971be3a1698", + "docs/validation/runtime_bootstrap_20260930/native-attempt03/checkpoint.md": "141a0572959fdb2197525be2a8cf7e8a4356987277ec8da8fabaf961f28507d6", + "docs/validation/runtime_bootstrap_20260930/native-attempt03/inspect_volume_fixture_v2.py": "0e21b6aefd591e7d9842cf5695e99060fc2c85294c6619f07122884e4581d48c", + "docs/validation/runtime_bootstrap_20260930/native-attempt03/journey.json": "e4f16a83f49b00672f8125be8f5b36ad5a6b7bd2ed2c7620b1da16e13d6d8c19", + "docs/validation/runtime_bootstrap_20260930/native-attempt03/mcp-stderr.txt": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "docs/validation/runtime_bootstrap_20260930/native-attempt03/owned/data/openhcs/logs/openhcs_zmq_server_port_5965_1790758999303299469.log": "719d7554ebbc8a91fa0413062f89cbb1013540918df6d51e486073e2a687ca98", + "docs/validation/runtime_bootstrap_20260930/native-attempt03/owned/data/openhcs/logs/openhcs_zmq_server_port_5965_1790758999303299469.startup.jsonl": "eba57b5d00e0878cd0b7349a1b27b77a231be4bbb1f5022cedf3aac6f932224d", + "docs/validation/runtime_bootstrap_20260930/native-attempt03/select_volume_fixture_planes_v2.py": "cc21d744b6f454db57503928faaabce060855d06be5ad3c28271c5af53d0f587", + "docs/validation/runtime_bootstrap_20260930/native-owner-tests-b.xml": "cb918af10ab3200b83d1e931a9b3b7b2f7239b166ee5b05ab65b526595883c27", + "docs/validation/runtime_bootstrap_20260930/native-owner-tests.xml": "0184ab8acebfde82f73aa4b2ae938ad400f48959a4b1c2a2650df66ea358658d", + "docs/validation/runtime_bootstrap_20260930/owner-factoring-checkpoint.md": "6b9ba079c1cd638320f5b58ed5a116b976e98223478ed25d269dbbcf9161bc75", + "docs/validation/runtime_bootstrap_20260930/owner-factoring-ratchet-resources.txt": "31a1c5eec77e5c5f5e9d91a01150bad91162c426161fc6edef0c873fdcb2b6ef", + "docs/validation/runtime_bootstrap_20260930/owner-factoring-ratchet.json": "b5a591a281789fe0889b179acad65ab5051d80513832001e95a409e417bc66c0", + "docs/validation/runtime_bootstrap_20260930/owner-factoring-source-tests-b.xml": "50cbb06ba8ec067bee3b61bce3bfd81171729f4208e8a985484264ab85b9307b", + "docs/validation/runtime_bootstrap_20260930/owner-factoring-source-tests.xml": "ae9d53d94575d9c0f71703dd3534a5c62f4dcb7b706f8f26277e25bab5d4baad", + "docs/validation/runtime_bootstrap_20260930/paired-native-owner-checkpoint.md": "114f620851c324ccef185a7f041cd10a1827f214ccf8ff6c613f15f92fd0f7ee", + "docs/validation/runtime_bootstrap_20260930/paired-owner-source-tests.xml": "14adb1de144dcec9c3d394782dac9838b72c023eae297763c0a203b65bda70ca", + "docs/validation/runtime_bootstrap_20260930/paired-pin-handoff.md": "6510912ce02371581864fcde2db78dd74fc65be05eb5daa1154187f68920ac17", + "docs/validation/runtime_bootstrap_20260930/paired-pin-source-resources.txt": "299f8bc3dce04a53d87e16eb3f83d8f007853c5604e6153cbc7c20be0c045010", + "docs/validation/runtime_bootstrap_20260930/paired-pin-source-tests.xml": "cb46ec3208aa694fa899e6e41eeb03d79407b20380d6fa1fd74f988f5a94c589", + "docs/validation/runtime_bootstrap_20260930/parent-main-integration/checkpoint.rst": "c86f6b1d1b7d99aebe38eb693b7ce65cf01be6af0cd84a6b23c1a0147652c092", + "docs/validation/runtime_bootstrap_20260930/parent-main-integration/native-build.log": "6aa818d0832f3c541b82e3e1888549722aefc03bbd2097b223048431eb88dd42", + "docs/validation/runtime_bootstrap_20260930/parent-main-integration/ratchet-resources.txt": "96bdf1aad53c02fe8cd4bb92057bc8d68b6092d01fba861e60fe05deb3529cdd", + "docs/validation/runtime_bootstrap_20260930/parent-main-integration/ratchet.json": "692307e5b347474d02720a4c39fa99cbf53db5272b29d860d75049a100b217c7", + "docs/validation/runtime_bootstrap_20260930/parent-main-integration/run-source-check.sh": "6f1a224197241353eb44986402329e917c934f227bc045a93144781eba7bdf4f", + "docs/validation/runtime_bootstrap_20260930/parent-main-integration/source-tests-native-built.log": "e61ffc0ec57e83bffc8d73d55be5d62372d801a670b90fc16bf85b3ea175c923", + "docs/validation/runtime_bootstrap_20260930/parent-main-integration/source-tests-native-built.xml": "d45a2d2d5f66587283443eb7728bfb826c0379ee5de510c4a9a74d46df4b032d", + "docs/validation/runtime_bootstrap_20260930/parent-main-integration/source-tests.log": "ebf16a13e6b3dda87f6d5b6ae18969d55ca42bd5a4fa099325c5dedfba949d7d", + "docs/validation/runtime_bootstrap_20260930/parent-main-integration/source-tests.xml": "68b100a58a23ee6b236198aa90e7c33f68377c64d6fcbed7acd02aa796186e70", + "docs/validation/runtime_bootstrap_20260930/pr-body.md": "50e8cf8f979abece5eafad96d10c4f6fb5bc43c960ca5efff53221c324d5636c", + "docs/validation/runtime_bootstrap_20260930/pre-spawn-rollback/checkpoint.md": "624737bcaa927195479e51282e213ab36d4d4228d55e03b33adf84479edefbf5", + "docs/validation/runtime_bootstrap_20260930/pre-spawn-rollback/combined-resources.txt": "7f377facc86459f827d99b5aa4de86f46036fa6a607a0908cd50f85a7a56ef3a", + "docs/validation/runtime_bootstrap_20260930/pre-spawn-rollback/combined-tests.txt": "f075cc1d80aab228abd444761e911270d943b75f5876243f24b4370ea06bec91", + "docs/validation/runtime_bootstrap_20260930/pre-spawn-rollback/dependency-initial-resources.txt": "790b820e15f234f30f3f8fc2cb7ab0184171fbf74e1eb07e20d3bf56b256185a", + "docs/validation/runtime_bootstrap_20260930/pre-spawn-rollback/dependency-initial-tests.txt": "4c92b2d38f648ca4a2a51d87367079cc54be864b42c2eaba2d65bbd6e64963ac", + "docs/validation/runtime_bootstrap_20260930/pre-spawn-rollback/dependency-resources.txt": "d1d7ac25844cdacae8b05e9daaa40e8086cc14c42252f2b9d597eb3dcdd9e6eb", + "docs/validation/runtime_bootstrap_20260930/pre-spawn-rollback/dependency-tests.txt": "ce9378eca44c9c372d4e0a13193d90c4f04c497f702bc14919cc349bb78830ac", + "docs/validation/runtime_bootstrap_20260930/pre-spawn-rollback/zmq-pr-body.md": "d38e1685fe968d08a96b9be3e5c8656f47a8cd6a7d0653ba27855e153435f83d", + "docs/validation/runtime_bootstrap_20260930/projection-attempt03-preparation.md": "f12dac93f4174918442ef094d164caf4922f011989a63d1a48bb42834cc097ad", + "docs/validation/runtime_bootstrap_20260930/r0-ratchet-before-resources.txt": "25c56cd46cbc662501855f4689e4201721c22b50ef2f12e894ebbd6aa37a38e2", + "docs/validation/runtime_bootstrap_20260930/r0-ratchet-before.json": "b60fc0d27d705739bf7ddd5cfdcc45cd2a4f1dbbc092f00c0d609bd4e8730d98", + "docs/validation/runtime_bootstrap_20260930/reserved-child-takeover/after-resources.txt": "7175fcc16572855e2705a17fbfa60bcd5a430f8a5a96a2e05b24a43a37b5fb9b", + "docs/validation/runtime_bootstrap_20260930/reserved-child-takeover/after-tests.log": "18bb74050853e8a6738428de25d77e6812c9af6c1d506f656661aafbdf9925b5", + "docs/validation/runtime_bootstrap_20260930/reserved-child-takeover/after-tests.xml": "15eecd13b138a4dd4707ea61236a5d16578cb316d9f5fd96339458b32f2c33cb", + "docs/validation/runtime_bootstrap_20260930/reserved-child-takeover/before-corrected-resources.txt": "3f4ccca29d5d8d6f75ffb1aa39a1780224d3293ec669e38a817d39faed72b5cb", + "docs/validation/runtime_bootstrap_20260930/reserved-child-takeover/before-corrected-tests.log": "c2d423238fb96e6987461d1b9803dc4cc7fc9a2fb071b4f281dc177c154ef06e", + "docs/validation/runtime_bootstrap_20260930/reserved-child-takeover/before-corrected-tests.xml": "6c14d238f5cd486fbed5cc4a5a80f43df00666d2c95bcad805f381f9b8db89fb", + "docs/validation/runtime_bootstrap_20260930/reserved-child-takeover/before-resources.txt": "f577d6af6038b8888691831f55d5568fea81b4882b6887fb58c35d2cf03fc49e", + "docs/validation/runtime_bootstrap_20260930/reserved-child-takeover/before-tests.log": "619105d4912a46f6b684a74bd1ef9de61e8edf1fdc302f3f7ba462ab8062ef1e", + "docs/validation/runtime_bootstrap_20260930/reserved-child-takeover/before-tests.xml": "b00c6b13279c43c052154ee60fb7fd9ffcc9c6d94b9c5fc2cc9e539d6ac9c0cd", + "docs/validation/runtime_bootstrap_20260930/reserved-child-takeover/checkpoint.rst": "172530cedc3dae6bcdc1c52937108d45afba0a77b1edd41e3afb8ed0504c27e2", + "docs/validation/runtime_bootstrap_20260930/reserved-child-takeover/pr256-body.md": "109e3480dab367be700bc8111c013ef182bf33df16b7d864f9b4a031ffe362a5", + "docs/validation/runtime_bootstrap_20260930/reserved-child-takeover/pr9-body.md": "7c3c28e0e0959b32a7b277dbc47b1c294a8e5596cad252508b804fb3dfa8c1d5", + "docs/validation/runtime_bootstrap_20260930/source-census.json": "1f0468a4fe5559c1113c70202e2576034f050c4680ae76deef1cb9921be2fbc0", + "docs/validation/runtime_bootstrap_20260930/source-census.txt": "fe699d7ba5cf427a3e84b41d30783a9209cf1a2a723be44142e124ddfbf124f4", + "docs/validation/runtime_bootstrap_20260930/source-close-122-resources.txt": "4733a731eae30b391ddca5f227665e40263a16d46c41326593ab86cac3d269cd", + "docs/validation/runtime_bootstrap_20260930/source-close-122.txt": "47994d7219e7ea55288b595167756f6f63c0c74beddae4dbac6a2b102a1af386", + "docs/validation/runtime_bootstrap_20260930/source-close-final-resources.txt": "26c418ec0d2b1115327f2a8cecd0d1d674b22ed6f4c56b23add85edde59793fb", + "docs/validation/runtime_bootstrap_20260930/source-close-final.txt": "ce37a347f55eef5a0b1cf18a4b7286377fb3e1ab287ba952f944a6d834505c3a", + "docs/validation/runtime_bootstrap_20260930/source-close-fixtures-resources.txt": "be092b114b6d9cd0910544ffbbc65b3471575c778244dca136ce6ddaadc09210", + "docs/validation/runtime_bootstrap_20260930/source-close-fixtures.txt": "c2ff8cd5ec093862bfab65fe0073f9bdfb78241d941a2d2b6861ed90054e21c9", + "docs/validation/runtime_bootstrap_20260930/source-close-initial-resources.txt": "f5db7a4ae92d972ca004602325b02f206be9bc0c44ed617dc3b8a213d19b66a6", + "docs/validation/runtime_bootstrap_20260930/source-close-initial.txt": "20a9f75d4a4913e0cf0f7bf26602c5812217f84171c98d6eb5e9823f69227cac", + "docs/validation/runtime_bootstrap_20260930/source-close-resources.txt": "46cb30319bbde3d3bad80615d458fdee4a77f56831de7ace533ffde1030ebaa3", + "docs/validation/runtime_bootstrap_20260930/source-close-wire-fixtures-resources.txt": "ef4b151e50d2f24727516e2da39bf793654a5294b047675fe36e6ac39ac87e6a", + "docs/validation/runtime_bootstrap_20260930/source-close-wire-fixtures.txt": "b419217ee1cb91b44efc30ae4b2b258d4aae8f9106508593e007b507c7423d16", + "docs/validation/runtime_bootstrap_20260930/source-close.txt": "9667fecc377d148f04a685757ee1c781bddd9ab82dede509fadaa59c34218f93", + "docs/validation/runtime_bootstrap_20260930/source-hardening-resources.txt": "240bc56208ae6889d44b7e5075b0f75797304ed1ecd7651af612503fd42aa168", + "docs/validation/runtime_bootstrap_20260930/source-hardening.txt": "967e61b78ad73f5a2af58e0d8b25dd60e7dc8ffaacfecde9ba866ca4b33d858d", + "docs/validation/runtime_bootstrap_20260930/source-test-resources.txt": "d8b4fff3da0cf5b57b6704dbccd7b1c35cb991348600cdd2646b1883d7b3b620", + "docs/validation/runtime_bootstrap_20260930/source-tests.txt": "21f89c8385ea85e365ff88d5e5f313cf5a62b63679de02b2e526665ccc4462fa", + "docs/validation/runtime_bootstrap_20260930/viewer-main-source-resources.txt": "db07fba19890d876a23b740baffd9a0376cb7a650d8aff9dcc82c8cb84fc66f4", + "docs/validation/runtime_bootstrap_20260930/viewer-main-source-tests.xml": "3c010622f5100a20488313a25da972e6e5557f04f83ee9fe4cb154c39d253d9c", + "docs/validation/runtime_bootstrap_20260930/viewer-merged-source-resources.txt": "8848453ea6e2beebefacbe20ae0a48e1615f4301416e5d2664391b1eef89eb6e", + "docs/validation/runtime_bootstrap_20260930/viewer-merged-source-tests.xml": "76b246d64c73df83d36ca3aa3d05bd8f7e06e55e0aae8071726c2e65f631f156", + "docs/validation/runtime_fixture_sync_387_20261001/RECEIPT.rst": "d758b11726ec75dd63edcea635bd839b850fff1e7f443f5abe8052b2e87042c0", + "docs/validation/runtime_fixture_sync_387_20261001/SHA256SUMS": "a4ce5fa9305f612769a7b41f8370d5fc23bdc623655d2b6ec5ea341b50fa1e2c", + "docs/validation/runtime_fixture_sync_387_20261001/pytest_evidence.tgz": "17a7e26badcb55df9c225ad7b38eb45c5199c5ed53b85d3f8afe315f02f7af8c", + "docs/validation/runtime_owner_sync_323_20261001.rst": "ba42abd16e29e28996fa829e9f6923f9aaa2a21273040e499d01760e6e605616", + "docs/validation/runtime_owner_sync_323_evidence_20261001.tgz": "fcaf4f7da4cdb143f6625fea47975faa03c394786da5c3386865325c2003a30f", + "docs/validation/s1_typed_viewer_20261001/NATIVE-RECORDS-ARCHIVE-MEMBERS.txt": "ea245e97091f0757abfeb2e8d5955f01cc66dcdb9a56d0ccd2b58185fd4d4c1e", + "docs/validation/s1_typed_viewer_20261001/NATIVE-RECORDS-ARCHIVE-SHA256SUM": "cc2fb6d2f09b73b7bdcd128c9eb5a72646a6f498f42b067ac0d7b3392bf59436", + "docs/validation/s1_typed_viewer_20261001/NATIVE-RECORDS-INCREMENT.rst": "fccd8914f71fae74cec1c6d2360b6800ceaaca6a48c2a147645b5d995fc2a703", + "docs/validation/s1_typed_viewer_20261001/NATIVE-RECORDS-RECEIVING.rst": "7f722393de06400dd9e0d52cd07e23dcbd72bc5d56dc705fbab18ebe044518e7", + "docs/validation/s1_typed_viewer_20261001/NATIVE-RECORDS-SHA256SUMS": "01e336f8625b7ecedf967b065d3f551484475432318a82cca673f23888d1cabb", + "docs/validation/s1_typed_viewer_20261001/NATIVE-RECORDS-SOURCE-SHA256SUMS": "f3391e85a14633df28102c843747e1727fca4d2c3e6ec848b964f7bc4acd47f6", + "docs/validation/s1_typed_viewer_20261001/PUBLISHED650-QUALIFICATION.rst": "8f563926cdf42d2224542ed0709d573a31636aa5a0c536ef411c2e976e48eef8", + "docs/validation/s1_typed_viewer_20261001/RECEIVING.rst": "94cf5a5be5ce9ec7932b12e726c78336604545c175af66049edc5df58f42bf7e", + "docs/validation/s1_typed_viewer_20261001/STATE-INCREMENT.rst": "76df74174b5dacce4a584b7f5f844d3ab1f628cb48cfebc992e42faf2f87ba65", + "docs/validation/s1_typed_viewer_20261001/checkpoint-framed-resources.txt": "c139e3878bd18454f8221f1a5ff95b5dcb868fce23356448f2121c2cc0f1e538", + "docs/validation/s1_typed_viewer_20261001/checkpoint-framed.log": "afb38b6a1a08d99126ac6e7a9cb15189d97f8c0c28491d969a0df9e982c511c6", + "docs/validation/s1_typed_viewer_20261001/checkpoint-framed.xml": "86a4685a8bb7186f5e493b8c492b8fcb3cc01d14cec82196604325f2e3b010d8", + "docs/validation/s1_typed_viewer_20261001/checkpoint-resources.txt": "d237bf264cccfa5780605e330cb6db12ef65ed1b9eda43cd7f0a58fb6741fd87", + "docs/validation/s1_typed_viewer_20261001/checkpoint.log": "10f15e1ac5ffc96fb9291e9149f40632664cdd84c2e40601a539cfc748f64602", + "docs/validation/s1_typed_viewer_20261001/checkpoint.xml": "3c6cc3ecc626162fd3eeba3186d91e8fc5d38819ce520a4b48f16d6212b4948b", + "docs/validation/s1_typed_viewer_20261001/native-records-evidence.tar.gz": "a65b053280d100f8957d81bfe8c0db0bf64d333b5d2d25df6a2a81eacebb2c48", + "docs/validation/s1_typed_viewer_20261001/original-state-omission-resources.txt": "ad07e195688b69d151f46b18acb6fce714894bb6782adc0026dbf94317211927", + "docs/validation/s1_typed_viewer_20261001/original-state-omission.log": "5252cea3e72f2d63cb16d77b686f2999d887d32614e7e15aac93b08b38357324", + "docs/validation/s1_typed_viewer_20261001/original-state-omission.xml": "4730ec696ed68865536fc526eaea121eeebeb81a4da9c9efa3680f7ea5d2ed46", + "docs/validation/s1_typed_viewer_20261001/post406-installed-state.json": "0e3ee0c358c8d9028a6c9b0c20690adbd7d1cabd753cf1801ef2225505d3c804", + "docs/validation/s1_typed_viewer_20261001/published34-r0-monitor.log": "4eb50c1b27d739bc9b16e1a71bc9011b0050052243cb77e870acc4104e0bb1f9", + "docs/validation/s1_typed_viewer_20261001/published34-r0-resources.txt": "42c2931ba158439b1562ada139e11cc0f3081c0cb0ef12e0d15854b9a8506359", + "docs/validation/s1_typed_viewer_20261001/published34-r0.json.gz": "051e1aa392fd50f846228a4abc5bc17e702882b0eb7c23bc1b2782259a4a5fd1", + "docs/validation/s1_typed_viewer_20261001/published34-r0.stderr.txt": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "docs/validation/s1_typed_viewer_20261001/published650-behavior-guard-resources.txt": "029eff604b7e6ecc9d0d0c654208313622c0c5a944d4b3c55d4fe62f0a0c208d", + "docs/validation/s1_typed_viewer_20261001/published650-behavior-guard.log": "1a734c2bb878fcbed3260593b6550ddde3cbcd9583ca3f882714904801b42857", + "docs/validation/s1_typed_viewer_20261001/published650-behavior-guard.xml": "d2efba2fed76273726d75652c9e21f1b50493db1b10713223926bb765e50d82b", + "docs/validation/s1_typed_viewer_20261001/published650-r0-resources.txt": "371023f0109f550aa6178afadf393e345f7a335b61d91e3a0b999179265146c6", + "docs/validation/s1_typed_viewer_20261001/published650-r0.json.gz": "a23684d02d7ba5d38d7da14482ed75aee457aff63c873e0fa85a7d65af45f576", + "docs/validation/s1_typed_viewer_20261001/published650-r0.stderr.txt": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "docs/validation/s1_typed_viewer_20261001/reproduce_original_state_omission.py": "19283f743be303b4ae83332bfbff5dfa1b7235866d1b49dcb152c56057a4dc6b", + "docs/validation/s1_typed_viewer_20261001/state-increment-corrected-resources.txt": "fe16c912770db2206d6a1a8cb10a9bfa82825c5cdd7bb95a598c74989653625d", + "docs/validation/s1_typed_viewer_20261001/state-increment-corrected.log": "254d1b321849d327d913d328a9de0b7f181592c659186ad7de8fad3c197f8f01", + "docs/validation/s1_typed_viewer_20261001/state-increment-corrected.xml": "71eb7924a34c2c54ff4c18e8c8b7dfa0ac5a28b4363d8c502185a0fee4b9a402", + "docs/validation/s1_typed_viewer_20261001/state-increment-resources.txt": "2cf59a9dcc53f9ce0715d59bf21a530e5cd512f84a6120a5be2ad1d06daaa643", + "docs/validation/s1_typed_viewer_20261001/state-increment.log": "46da625e68f3ebba3dfafbd830d0e9d6d0ec975d410ee676564cbd24ab52d6ef", + "docs/validation/s1_typed_viewer_20261001/state-increment.xml": "a7d74bd83f5a3317f084114638dd94e1f638b3a7e1e7e4fa9240b95c4ae8c831", + "docs/validation/s1_typed_viewer_20261001/state294-r0-monitor.log": "ab3006a9704297f8cfc23681ad067aabd3ebb74d9f4c636b789734ccc9d3371c", + "docs/validation/s1_typed_viewer_20261001/state294-r0-resources.txt": "88da2f583390a30345c30ca2f980aa765744aeedb0439ed979e0fbcadd852e18", + "docs/validation/s1_typed_viewer_20261001/state294-r0.json.gz": "a2fed5f2c614933baf3871b024ede05a35f1e741cee9e683a89dc84a7ef0aaf1", + "docs/validation/s1_typed_viewer_20261001/state294-r0.stderr.txt": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "docs/validation/s1_typed_viewer_20261001/state294-r1-monitor.log": "016352ac2d9f99ff17391cd8152818ae24a665694924970eb7010fcc7264fe22", + "docs/validation/s1_typed_viewer_20261001/state294-r1-resources.txt": "2d7b3c3ecfb4d3c44f304a542792c88e7e1d7e5cf9b5a58ca38e05a70d8408f8", + "docs/validation/s1_typed_viewer_20261001/state294-r1.json": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "docs/validation/s1_typed_viewer_20261001/state294-r1.stderr.txt": "c73ae9d0958e21ee045b54f40aed84d1d5a168cc5db3217b03f1f7bbaaccd017", + "docs/validation/saved-label-plane-domain-419-20261002/COMMANDS.rst": "623b2e8e27b6d65ecaa0380f1b22ebed2b2a7a0e3c9884d2f990fd1830560cda", + "docs/validation/saved-label-plane-domain-419-20261002/RECEIPT.rst": "b7e2f6f5a6c81a735697625d893ee05a9e920cae8efbcb06f8a310b3c0b9d10f", + "docs/validation/saved-label-plane-domain-419-20261002/adjacent-controls.log": "2040d0529e119c1cf4bd9990dcee635363ea88e7d6fa9f310a1470fdad3e2593", + "docs/validation/saved-label-plane-domain-419-20261002/adjacent-controls.xml": "e1748f4735194d2c73c261095945a4fee33291024eec2eb1a23a8258e5c1e6d9", + "docs/validation/saved-label-plane-domain-419-20261002/distance-original-red.log": "507cff5c5a877b05998766a7230571b74b08f08f34f949ceb14e856e7eeec75e", + "docs/validation/saved-label-plane-domain-419-20261002/distance-original-red.xml": "e52f0e31f427f738e7bd0794fb6f11c6e288f097a5bc412eac79ef5d77762806", + "docs/validation/saved-label-plane-domain-419-20261002/final-owner-controls.log": "f53685e5d35f8d165bca7c5025d6529fed4e25a534941d505d29f4a352c583b8", + "docs/validation/saved-label-plane-domain-419-20261002/final-owner-controls.xml": "4c986a6c379af168ac3b2084a766f4f746d888f2e0904f8753160e8ac639ddf2", + "docs/validation/saved-label-plane-domain-419-20261002/geometry-and-runtime-values.log": "c90fc9b248c9b58d80bc925d6b423822549ff56e521bce23c9fa1a67d2468e26", + "docs/validation/saved-label-plane-domain-419-20261002/geometry-and-runtime-values.xml": "ea4f2c0f2cce1a1b0ffab25bd344964db00a97e1c59cb1b340099c767bcc4bc2", + "docs/validation/saved-label-plane-domain-419-20261002/geometry-focused-corrected.log": "537f437c7e370c4c371ada9da906e453a7df6eba507ae1015a9f3dd0e34b722f", + "docs/validation/saved-label-plane-domain-419-20261002/geometry-focused-corrected.xml": "d0fd31efd8c0ac05756911e1ce37c4c33c2742fc78717c13a390b3597161abf1", + "docs/validation/saved-label-plane-domain-419-20261002/geometry-focused.log": "0d1188e656fb161643b8a5b1e5c74c353d5a6339eabff5b73a57a4693d701692", + "docs/validation/saved-label-plane-domain-419-20261002/geometry-focused.xml": "63fb1d68390a01aa1e51cc4b56762985ac88ba5e626b741423a15e28d62713fd", + "docs/validation/saved-label-plane-domain-419-20261002/metadata-owner-proposal.patch": "70d25df2a6c124a2713bad58f26a9426301a23121b1598358886a624a54aa9fd", + "docs/validation/saved-label-plane-domain-419-20261002/original-red.log": "c91bc58472af8fba735e3c59d98fc10126078f518a0aa4c54afdb21ef3d977d3", + "docs/validation/saved-label-plane-domain-419-20261002/original-red.xml": "a19699054d7619903a6d78ff2643a6eb52a480f1ecf4b3e4e334327ad6fb5b16", + "docs/validation/saved-label-plane-domain-419-20261002/projection-owner-controls.log": "54d34e37cb02a7b303069dae6321139c1f41558d42199b2873b2f2857a558177", + "docs/validation/saved-label-plane-domain-419-20261002/projection-owner-controls.xml": "d83541cd5294bac9b6eb6582ed63d40e101e35fa10f5340a89c6a226621b8e92", + "docs/validation/saved-label-plane-domain-419-20261002/r0-final-production.log.gz": "16de3af95169cb460b3804c0739cca2be11cf5fa41da425c8ee34595b5a5f4b2", + "docs/validation/saved-label-plane-domain-419-20261002/r0-original-pin.log.gz": "fb62e3e1bd27f14962c1ff6fd80219b76fa46d439b061c45fdb2d156b37128bf", + "docs/validation/saved-label-plane-domain-419-20261002/r0-unapplied-metadata-proposal.log": "3a27d8907764a5d507e7b5224ddd1ac2531a75045467114fd41144693af3b78e", + "docs/validation/saved-label-plane-domain-419-20261002/r0-unapplied-proposal-commit.log.gz": "332e17a1bafada3a973a6c6f342582af9c37900d1b1d0f628962ed5e96f6038c", + "docs/validation/selected-discovery-evidence/INTEGRATION-R0-UNCOMPRESSED-SHA256SUMS": "be70dafdd273ed3451c0fb856232944ce1c2913d14d637477896115c6bc902d2", + "docs/validation/selected-discovery-evidence/INTEGRATION-SHA256SUMS": "e9d5f53b006829923cb21b1723c90de85a2f6831f35dfee3d866d2d134183931", + "docs/validation/selected-discovery-evidence/POST409-R0-UNCOMPRESSED-SHA256SUMS": "c4ad34524e6d3a07ae23069a6b682c1e51dba209e5eeac19eb46c84b3569c8ef", + "docs/validation/selected-discovery-evidence/POST409-SHA256SUMS": "4789abd3c950e993f62311c5e330c2538457e6f6044e25ba8b49e226a75d6de9", + "docs/validation/selected-discovery-evidence/R0-UNCOMPRESSED-SHA256SUMS": "1904920c804514e02e5724f668a9cf7a366d17802f6216fbeb3a451f2ee2f845", + "docs/validation/selected-discovery-evidence/SHA256SUMS": "d1cce732f480f0a0c560841d1886985dba17228cf9a9836461090c901827e60e", + "docs/validation/selected-discovery-evidence/batched-source.log": "dd9a7176dca9cf7fe8469b22e84bd9d18d6ea6d2403889ceb35070d964c6d722", + "docs/validation/selected-discovery-evidence/dependency-r0-final.json.gz": "2e78680aee46bd87337a6daba134a4581eba3faecaa98098b6db2cc0c4667fd5", + "docs/validation/selected-discovery-evidence/dependency-r0-final.resources.txt": "6f7f002a149e1e1f6ef637ab5a21fe91ca916be6460a9ea09ac587ae994c230c", + "docs/validation/selected-discovery-evidence/dependency-r0.json.gz": "6384b08273e512617fe093e93afc3075b763018bde0c4763b15910d96eed549f", + "docs/validation/selected-discovery-evidence/dependency-r0.resources.txt": "8807884bd3219966fbf8298f44fc8016e61fb75b4863202a93dea4bf1c456000", + "docs/validation/selected-discovery-evidence/final-cold-profile.log": "966738b1d54475af8832eba82a43e5af5a469cfc012f0c51473defd0d4d70357", + "docs/validation/selected-discovery-evidence/final-focused-source.log": "47d54fd3d8273cfd817175999c00b2371e1b78f5f76d705adbac33b620b3f63a", + "docs/validation/selected-discovery-evidence/final-owner-source.log": "add8d502e1c43e9539d3c23b867b3324c179157af274061ae33c8647ab767781", + "docs/validation/selected-discovery-evidence/final-source.log": "9e95a6eb3ee8b6dd7486cc119eec33881e67af196f027b263caf419e85f05298", + "docs/validation/selected-discovery-evidence/first-source.log": "2a9664210c327d1c1bf04666378e94a3f5d97595d833d30cbaefb26d9f208142", + "docs/validation/selected-discovery-evidence/integration-376-commands.sh": "fbece378e58ffa81e784c832eb49e12768a21c1cc4ebac11696ee413a36c417b", + "docs/validation/selected-discovery-evidence/integration-dependency-r0.json.gz": "1d2724497115a55f624731a4a1dd7fcfb9a8c597420d13a48451ed2a6ac0ebb0", + "docs/validation/selected-discovery-evidence/integration-dependency-r0.resources.txt": "e5a4e30cf0f41b3b37551048679565e31e376ea495c6efa07bd0dc284094f964", + "docs/validation/selected-discovery-evidence/integration-focused-source.log": "b56a1f6e7357a8ae759227fb2b305128207d28815c771d3e507fb8337f4efec5", + "docs/validation/selected-discovery-evidence/integration-openhcs-r0.json.gz": "a17fb99918637752df40c9c13ed3a9d0e1063066e431b3278d6996b9a3ec603c", + "docs/validation/selected-discovery-evidence/integration-openhcs-r0.resources.txt": "d5ea604cdfb2c7a7aa0146c29643680fb8aae512a8ddcd75dc956687cc7ad13a", + "docs/validation/selected-discovery-evidence/openhcs-r0-final.json.gz": "22a5b2681b463f6bd703945b215ac3771a976a73f40798fe2c1d346df35365d4", + "docs/validation/selected-discovery-evidence/openhcs-r0-final.resources.txt": "c8220ad8608fd00d673e7ee21320bff5fcdaa5c1cd4dcfd60fcf5e7256fcb6d3", + "docs/validation/selected-discovery-evidence/openhcs-r0-rejected-24a.json.gz": "e0a038a85c8ccb738b5a83ea6407f645fce077e0659504aab4207f87de6ab8b1", + "docs/validation/selected-discovery-evidence/openhcs-r0-rejected-24a.resources.txt": "7d35370cb80f8cdcd3844ce440538f7dd3f2a2e6d48c734b4df748ac0b131e54", + "docs/validation/selected-discovery-evidence/openhcs-r0-rejected-5fd.json.gz": "9d1aa365b7f5fe9f0df1fa32838cc02d5a76263e43e92a4db4d3d58100ff93a5", + "docs/validation/selected-discovery-evidence/openhcs-r0-rejected-5fd.resources.txt": "3bbf9700b0fe8e4909d85f742c03e873e1f942aca57ed817979e21a338c9eaff", + "docs/validation/selected-discovery-evidence/owner-source.log": "42e82c8604c2acbadbc9ae357b3637ef60d10cdedb158a1f662a9b067b5dddc0", + "docs/validation/selected-discovery-evidence/post409-focused-source.log": "1882553f43e2c9c9c317da989f0a01e2bc5926fdfc0cc071af21193a33b3f9f3", + "docs/validation/selected-discovery-evidence/post409-openhcs-r0.json.gz": "8b6fb413e437868d7d3a8f57d6c95357a82a24513bc08a47ef8aae14751a83aa", + "docs/validation/selected-discovery-evidence/post409-openhcs-r0.resources.txt": "26f81936ae1fa819759de8fa36ffe8b85b12171dad403e903a7a176333a7c54e", + "docs/validation/selected-discovery-evidence/real-callable-newcase.log": "a6009050c70e67e3fbbeb7ab539bb945b3ea2d90ba91b0ac2845093b5b2c5bdb", + "docs/validation/selected-discovery-evidence/retrieval-admission-newcase.log": "6be237db318800db8743aa4b1704cdbf869ae618e8d104d1f0bc8c07b786c26b", + "docs/validation/selected-discovery-evidence/second-source.log": "fc3bfdccd74bab0fa2ee1c419977b10a012b635ff23cea398436c83de0dbbee9", + "docs/validation/selected-discovery-evidence/selected-cold-profile.log": "da7dee38615dcea87f5f32107b43d508ae2c9a023d71343717e64098127ea7de", + "docs/validation/selected-discovery-evidence/source-roundtrip-newcase.log": "b6c618c01b13edeb60951cb832d16a55591117eeb64233a960dc745e0df9f504", + "docs/validation/selected-discovery-release-022-SHA256SUMS": "a63b333d22b1661f697f82ccdbd08b647caa247340aab68a0c6b4fdd3beb19c8", + "docs/validation/selected-discovery-release-022-dependency-r0.json": "29c7c539e72b2a7ea5eeecc78d0f63e47295ad7481d342f37f2ca054664304fb", + "docs/validation/selected-discovery-release-022-dependency-r0.resources.txt": "d84918440598f01fec5d398291c0a693a29877fd835181e835ca4fa23984e529", + "docs/validation/selected-discovery-release-022-probe.json": "7cd9d87e95e6fa126b026c9ebe5318cae6f0db2060fcb1f9b76946d65f65603a", + "docs/validation/selected-discovery-release-022-probe.resources.txt": "31704c7fafd27915b07fa37fe4ff2860c9fc57a84cae6d29b36b6f990de6d150", + "docs/validation/selected-discovery-release-022-source.log": "dc7ae3abeec2d9c22fc02904a2c7cae12e07ee4e82923f49507e9386ee4ebc72", + "docs/validation/selected-discovery-release-022.rst": "2721642aa582978ca9d259bf4c4ba0d8c8b97144d2cc9253b34e01888a8f60d1", + "docs/validation/selected_plane_reopen_stream_20261001/ARCHIVE_COMPARE.txt": "78f64d6b776ddef11592119e980c92143fa3ac6187ee5230927ece67c0053bd2", + "docs/validation/selected_plane_reopen_stream_20261001/ARCHIVE_SHA256.txt": "95b3799721a65e092221486597023ddaaf5ace34ece35dd34b346a4e6a2c6f86", + "docs/validation/selected_plane_reopen_stream_20261001/MANIFEST.json": "bb9e434c7624a0a33a6620ddafb1bfb98153a308fbd98ee673f92909b67613e5", + "docs/validation/selected_plane_reopen_stream_20261001/RAW_EVIDENCE_SHA256.txt": "df7689317ce04f13036b68ab9dd6109090d0c1dc1a03bc2740ee49f896bf0439", + "docs/validation/selected_plane_reopen_stream_20261001/RECEIPT.rst": "cf9f0984fe13d15b902686b271a61f2265df7d55dc4fb85c69c41e83a0f321f7", + "docs/validation/selected_plane_reopen_stream_20261001/pr.md": "c8bd030f3993bb98ea7cbcba8d03cdd022d4a843ec29a4f5327cf3e5342fea32", + "docs/validation/selected_plane_reopen_stream_20261001/raw-evidence.tar.gz": "e9a10347805e3e334c0783b742136328430389ff2abd9932ace08779bbfe28b8", + "docs/validation/selected_plane_stream_materialization_20261001/RECEIPT.rst": "cfb9e1eae7a5d3ea473258f03125a6df40eae1741f95d848b8d087458c7ff6cd", + "docs/validation/selected_plane_stream_materialization_20261001/bounded-cellprofiler-stack-resources.txt": "2fd486f6e1036a1d74a169085092fe66da9ece0c6697722a725bb8d3f6e408a1", + "docs/validation/selected_plane_stream_materialization_20261001/bounded-cellprofiler-stack.log": "57c950ee9f24d5e712bd6ff8bd64e7ddc06805f45545e0ff815bb510aff1a424", + "docs/validation/selected_plane_stream_materialization_20261001/bounded-cellprofiler-stack.xml": "7c293ae9f1863dc54854dc416fd7c8a34646f4b4b850963f36d17d069f441b8f", + "docs/validation/selected_plane_stream_materialization_20261001/bounded-current-focused-resources.txt": "245bfcc52b1060a35c8f9f1613bfa1b339aaddd399c63872a9d72a45fc0223a8", + "docs/validation/selected_plane_stream_materialization_20261001/bounded-current-focused.log": "483ddbeac21528d0c49e8957e780f0db4f01e6112caadb2f62c2f43a5f765171", + "docs/validation/selected_plane_stream_materialization_20261001/bounded-current-main-controls-resources.txt": "4acf2221407b8a076e06a5cd51f3d98649dc276bc0109aae62070310c60acc7d", + "docs/validation/selected_plane_stream_materialization_20261001/bounded-current-main-controls.log": "4ecc9f939969305b5088436c1801fc2bc2f132a7230a32bd40fed3795a696df7", + "docs/validation/selected_plane_stream_materialization_20261001/bounded-current-main-controls.xml": "05174345fa49314c637ea60efac1d0407ddd0c9baa0e9a53e13aafc07d7dac74", + "docs/validation/selected_plane_stream_materialization_20261001/bounded-function-artifacts-resources.txt": "cf019fcdde882b2f654e4b29c15e8a74cc536746fd0ae92385a759585c09306a", + "docs/validation/selected_plane_stream_materialization_20261001/bounded-function-artifacts.log": "53161fa4a3dcceb6845946bdb4163cf6e931385c6dcaa9f3e9fcf27af0aeecce", + "docs/validation/selected_plane_stream_materialization_20261001/bounded-function-artifacts.xml": "cc9100925376e93d85d8a7e581d843e2e12d6efe15b9e1050759d387098939da", + "docs/validation/selected_plane_stream_materialization_20261001/bounded-image-contracts-resources.txt": "0828ad48c2ecfb0d373f25d124a969a0577da355e85a46e576c6b16c18cee20a", + "docs/validation/selected_plane_stream_materialization_20261001/bounded-image-contracts.log": "7d37aa4af9703aa1a86359430146dcf38d7b5a74a7f219eb1bc8d9fcd00eb0dd", + "docs/validation/selected_plane_stream_materialization_20261001/bounded-image-contracts.xml": "1cdb2f2a3b79bd14bbefe57f94c6dc885b97cdb49f97c12e635bb8b5900b015c", + "docs/validation/selected_plane_stream_materialization_20261001/bounded-main-qualified-resources.txt": "59d0935aaac753b956707fe42998b26d7df1c94c884b5b9634c62308d5e77fb1", + "docs/validation/selected_plane_stream_materialization_20261001/bounded-main-qualified.log": "0036ba913e6bb8c6cccb6c99e83211f1367902f0f84f40762bfafd966cacfe42", + "docs/validation/selected_plane_stream_materialization_20261001/bounded-materialization-core-resources.txt": "2f930896c44509a51af7f94e95d9fc7fc0a887c14591817e2ff1e75328a338ca", + "docs/validation/selected_plane_stream_materialization_20261001/bounded-materialization-core.log": "bd05cbdcb3653fa21b5596ea24f7b260d3a8e08cff4646eec02a8699ea421bcb", + "docs/validation/selected_plane_stream_materialization_20261001/bounded-materialization-core.xml": "4aaf829830b30fac695d4450046c8c9abcef08937df944f6b4c074eccdccfda7", + "docs/validation/selected_plane_stream_materialization_20261001/bounded-materialization-resources.txt": "f3b98aa56c951ba800daf4ae1d749020cf1ca9e20158273aae12c1689a30f9d3", + "docs/validation/selected_plane_stream_materialization_20261001/bounded-materialization.log": "a1ce4b0fbaed634268995c5649cc0c852ddcfb73a1aeb5bc50ebc21f0e24f2b2", + "docs/validation/selected_plane_stream_materialization_20261001/bounded-no-autoload-resources.txt": "250e68f8d3eabf2f7668caf27f52fe7fcb65566b09eb7f66195f6607ab22eaf0", + "docs/validation/selected_plane_stream_materialization_20261001/bounded-no-autoload.log": "120ae968c0313e0e6de36943d5fbd1b2e572d32ca8d4b93a0780d93bac796275", + "docs/validation/selected_plane_stream_materialization_20261001/bounded-no-autoload.xml": "eb48f69dddc6cc6cfc1d91113435b9305dcaf0912702c8d9ef0d67ccddbb62cb", + "docs/validation/selected_plane_stream_materialization_20261001/bounded-public-path-resources.txt": "eca634d87fa14d341efbd09540cc8adf386dc94697ea900c3eec78b9cc17f51b", + "docs/validation/selected_plane_stream_materialization_20261001/bounded-public-path.log": "5411dd0da5be0bc9f8f1f6bcc4354d3432619672c8e3f1f15af532782e9dc6b2", + "docs/validation/selected_plane_stream_materialization_20261001/bounded-public-path.xml": "040b5fbe73e4d289fb3459a8a3fc7fc86f7c03cff30bfc4713810b01e676c6d4", + "docs/validation/selected_plane_stream_materialization_20261001/bounded-viewer-controls-resources.txt": "6fcb6bcdfd4d57b7cc015bfafbca2015563ba539416209e67f2464ae2b166445", + "docs/validation/selected_plane_stream_materialization_20261001/bounded-viewer-controls.log": "e89efd39c9162b9e41ac96918ea1c23f0a2885026aea1eb1077ce5b2891fbbe0", + "docs/validation/selected_plane_stream_materialization_20261001/bounded-viewer-controls.xml": "ddef8fe1733027f486b299f78bd35899c1bc9b838e4c94c1219b2a3d3261b02d", + "docs/validation/selected_plane_stream_materialization_20261001/current-main-controls-resources.txt": "17d97343edfacf087b380998b354f202c35f14323e06bf811af460696fd0799c", + "docs/validation/selected_plane_stream_materialization_20261001/current-main-controls.log": "d0cc26ae4d40d6e070e56e94def8ecb144a726c6b0c076f563c92453dffaaa0e", + "docs/validation/selected_plane_stream_materialization_20261001/current-main-controls.xml": "1a1ca8a990284717bdb505b22750488f5e016c0db7cad7289419a99ddb9c80d6", + "docs/validation/selected_plane_stream_materialization_20261001/expanded-first-resources.txt": "83323e64caa0828dffdea1ce1fbe4314d1fbb09912e76293a2c7def041981493", + "docs/validation/selected_plane_stream_materialization_20261001/expanded-first.log": "bd3fde0560246e25e729e44a37d471e26800130a220ce8f46a5dd0a0e0142151", + "docs/validation/selected_plane_stream_materialization_20261001/expanded-first.xml": "a397af52eb6fffc37e8c9b69e35a4801ccf68cbbd8a352066b9a76279b00177a", + "docs/validation/selected_plane_stream_materialization_20261001/expanded-second-resources.txt": "c014b5aa67865cb831d9c13ed23010dcbd980a14b123cc87e9e6ce63f457e0ea", + "docs/validation/selected_plane_stream_materialization_20261001/expanded-second.log": "9f73cc78f977dfd3ceaf42e06cf156d32bb4069495257665edd0d597a7dd5141", + "docs/validation/selected_plane_stream_materialization_20261001/expanded-second.xml": "f58908dcb36c59d235e7f4f4d23ee046b62c69bba7e66e26ec971ffc183f28b8", + "docs/validation/selected_plane_stream_materialization_20261001/expanded-third-resources.txt": "e7415545efd460a1df144ee9163a47cf8c88efb8ee139e173990c0cba5fad3f4", + "docs/validation/selected_plane_stream_materialization_20261001/expanded-third.log": "f6979a441ce7342d673f04787891175209a9b5c4cdc29edee46cdaba57eabc95", + "docs/validation/selected_plane_stream_materialization_20261001/expanded-third.xml": "554edb8d5eb68c1e5ef7403d30f0d9339e54e7b6ec6b8fd0112cf49885fc3b9f", + "docs/validation/selected_plane_stream_materialization_20261001/green-initial-resources.txt": "d01f90da65eb6064520a111898caa5ab22d327dd2b44cc1e7caf3d8fad0b3252", + "docs/validation/selected_plane_stream_materialization_20261001/green-initial.log": "e831ffc1b00add910a59de3680f959ce40d9edb277938955dfaddd9080dd89db", + "docs/validation/selected_plane_stream_materialization_20261001/green-initial.xml": "4665aa39d7cbf3c2e6b7a1f63b729e1069f8480246bfe61ad33ebd0946842962", + "docs/validation/selected_plane_stream_materialization_20261001/image-contract-controls-resources.txt": "9f541151141bd3d845167395629fd58bcc716dc93bd9e4fd901cb3598dce971b", + "docs/validation/selected_plane_stream_materialization_20261001/image-contract-controls.log": "62d6885ca5729bdb8ae0b3e758a284583ec707f96b958d7841896e23fac16780", + "docs/validation/selected_plane_stream_materialization_20261001/image-contract-controls.xml": "4927e53aa381f5c021467ba709f7f75d7699d93e7d5984bb67869474df271171", + "docs/validation/selected_plane_stream_materialization_20261001/issue.md": "1ff26d4f02f7ece635c3679c5b7af6d3882d8f175f4a1118149b6101aaa2f9a9", + "docs/validation/selected_plane_stream_materialization_20261001/materialization-controls-resources.txt": "c989c058cf6e001f3ed615b97abdac89f178f1fe7731b0138e88c9ff5a9a940d", + "docs/validation/selected_plane_stream_materialization_20261001/materialization-controls.log": "8fd42c72e1ec52b9524d4e1a91bfbc378ebea513082e7a65e5769e5c3704a8d0", + "docs/validation/selected_plane_stream_materialization_20261001/materialization-controls.xml": "66094ff8a49d1dc0582f970560dbc4aae10a4e95dd7fc776e83919ebb1a7d503", + "docs/validation/selected_plane_stream_materialization_20261001/neurite-output-base-resources.txt": "d573eeb2fe4e6031831eeefe0046f4246483c74145f58cef69c1f53c7598d2da", + "docs/validation/selected_plane_stream_materialization_20261001/neurite-output-base.log": "d527be247c901531629833a96a5a82893ad03e686e2b98917e72f413f6fd9951", + "docs/validation/selected_plane_stream_materialization_20261001/neurite-output-base.xml": "e79c96d3a4782c8291c1c3fab32ae150f3730ac7a3529442853d8bf97717e34a", + "docs/validation/selected_plane_stream_materialization_20261001/neurite-output-controls-resources.txt": "76483b1e7e4dbccdc7401f7f6fc014f81be93ffe5bb48c7fc4a1a08029f1ac32", + "docs/validation/selected_plane_stream_materialization_20261001/neurite-output-controls.log": "0b22a8b7a65fdd23afd05010321a43b9a46316a38cf26aa83799cf2e35a0e791", + "docs/validation/selected_plane_stream_materialization_20261001/neurite-output-controls.xml": "6c15424ecab3c6af922abc720f05a8d4e9fb4c683d86e879d0e42087fc7170bc", + "docs/validation/selected_plane_stream_materialization_20261001/nra-current-full.json": "b9972265184516bb5e21f7f00618d41191553c660b558f193b77a902b55c2c4e", + "docs/validation/selected_plane_stream_materialization_20261001/nra-current-full.stderr.txt": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "docs/validation/selected_plane_stream_materialization_20261001/nra-current-resources.txt": "f28756e88ccc7d4fdf6374c4cea84a9e1dcc3a40d436378cd7a2043fbfa4f4b2", + "docs/validation/selected_plane_stream_materialization_20261001/pr.md": "c97b1560636ed18fca4d120d31fcd74a592293ffd232976a332d1b8d5725ed89", + "docs/validation/selected_plane_stream_materialization_20261001/r0-current-main-resources.txt": "c183e6b674c98de8408c822ae2bf3e04bbe44bb97cb89c2eb1f51de38f130f90", + "docs/validation/selected_plane_stream_materialization_20261001/r0-current-main.json": "6430b77980922e48afa039d43ed7df86951161ed47df85c5fddbc46e7f84106d", + "docs/validation/selected_plane_stream_materialization_20261001/r0-current-main.stderr.txt": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "docs/validation/selected_plane_stream_materialization_20261001/r0-resources.txt": "bae4f86f8ec8e541185511a82ae7a689fce1837254d241aee2d9e714385db91a", + "docs/validation/selected_plane_stream_materialization_20261001/r0.json": "081a684a115b3b32e1b42a1f67313119d1b1189657a907166ecfa4e8c982bf4f", + "docs/validation/selected_plane_stream_materialization_20261001/r0.stderr.txt": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "docs/validation/selected_plane_stream_materialization_20261001/r1-exact-policy-resources.txt": "2852c4b6a2f459c5fd0caa0cd33368e5248887c5bd1688df9eee5ed034c962ed", + "docs/validation/selected_plane_stream_materialization_20261001/r1-exact-policy.json": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "docs/validation/selected_plane_stream_materialization_20261001/r1-exact-policy.stderr.txt": "fe927dd1e1a7184b7b40aa0c2d4a396fc39caf92cce49627107fca98ad4737c1", + "docs/validation/selected_plane_stream_materialization_20261001/r1-original-resources.txt": "8282dd261e48cc8f6f8d893572f5d1eaa4f267bbe9f21164382f211ae07f5441", + "docs/validation/selected_plane_stream_materialization_20261001/r1-original.json": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "docs/validation/selected_plane_stream_materialization_20261001/r1-original.stderr.txt": "a004b8179efd0457ab5b59783330f711d65de6170d13553b5592417390c62e0d", + "docs/validation/selected_plane_stream_materialization_20261001/red-resources.txt": "b2e8463ad7747250c591bf0999a8e065c953132c44b61fb0aefeb7287cffda40", + "docs/validation/selected_plane_stream_materialization_20261001/red.log": "2f085f7c452c1af3103c0cbfb24ea5d21c2a1b8af45ddae19815236e76f34a5f", + "docs/validation/selected_plane_stream_materialization_20261001/red.xml": "764fab3bfaffb3854fae58a687a0e57a71df6b77bd7e9c33636aed3a7ec3345e", + "docs/validation/selected_plane_stream_materialization_20261001/run_bounded_source.py": "85df89047c2ce6c08c5fd9271dd99143187c8f9c69bfe249a3979625cb594204", + "docs/validation/selected_plane_stream_materialization_20261001/run_original_projection.py": "108e30547b560c85f8579f71e0ad3fa56c579f8bb89877a3c9d97ebec5934b49", + "docs/validation/selected_plane_stream_materialization_20261001/validation_summary.json": "55e0261bac8922b0ca07b21e3560ab49220011cf77813314e3ed9e49ac65f06b", + "docs/validation/selected_plane_stream_materialization_20261001/viewer-rejection-controls-resources.txt": "6e0134be1695477ae0c87d7579c5181db11c35cfef42d09edc73c022adba913c", + "docs/validation/selected_plane_stream_materialization_20261001/viewer-rejection-controls.log": "9123634ee7c6f12cc325157198f190fe103174c761594201f0ff592ce54affc5", + "docs/validation/selected_plane_stream_materialization_20261001/viewer-rejection-controls.xml": "e3c27f934172a14bed6caf2f47aa0e5d7f9f17925eac9b04602479f500afa7d1", + "docs/validation/shared-dense-coordinate-owner-20261002.rst": "76ca78efc8cf399eb57e67a47c0f5e2db0eeda7878847b8019b94b404ce70481", + "docs/validation/shared-quantized-hull-geometry-20261002.rst": "3d7ffdb5487822f018765cc31662131d32def122f2552d62fa14f15d23d3117c", + "docs/validation/shared_runtime_plumbing_384_20261001.rst": "c3a67e1dd9088cd4f52cddd8fbed167f72412b62321ce4008e88797e540ad29a", + "docs/validation/singleton-label-invocation-477-20261002.rst": "df9e2a1dc03db18a9a70ac3091a20f1e20c37ef8b07d4dfb624970981ce04425", + "docs/validation/singleton-label-invocation-main-477-20261002.rst": "df796e3e93eec384bc1708aef914295a69bf9ecb1ab46c6e7defa4e5be9b5401", + "docs/validation/skill478-distributed-threshold-diagnosis-20261002.rst": "6e55c9d155a1c244026db7831e62bce849c55b35b3e439cfdf1b7e1b9766124b", + "docs/validation/source-projection-family-20261002.rst": "5d2d8454a2cba7ad2fb4733b514a4fc6970de23e853185ddab6173f82ccc0d9d", + "docs/validation/source_projection_fixtures_20260930.rst": "2235c0638619dd25e61ae0a464b239ce326a73b3238c662fc0a83dfd986151b7", + "docs/validation/startup-feedback-358.rst": "4e7c4a5c23d615925fda680457243bec02e4c32c3242909ee116d1871729ae23", + "docs/validation/startup-feedback-evidence/SHA256SUMS": "c3ff98677ff01010ac43e2bbb294c470547d111fe3fa18077c78da4ff6bad82a", + "docs/validation/startup-feedback-evidence/green-final-feedback.log": "666edfd46df8704756cf8bba2f35aca0e1ca047811213992b8808cf0bd35d0e8", + "docs/validation/startup-feedback-evidence/green-initial.log": "285ff582ecaa4393df051d7046d72093198d06df1f759d89fb754a200c67ddea", + "docs/validation/startup-feedback-evidence/green-lifecycle.log": "5d1c5fd8b9798a219ef8ef074875fbdd893cb19c99824d854868c8ab20944da3", + "docs/validation/startup-feedback-evidence/green-published.log": "62692fd9cb6f07247ddd752dd461bd70e171e7b66ea07d3ffa234885663dcfa4", + "docs/validation/startup-feedback-evidence/green-wrapper.log": "3dcde6d6cb4b726e569267573da10136ae9dad6217042272ca1751fa466b007d", + "docs/validation/startup-feedback-evidence/lint-final.log": "d63ab3df51a50c66f9c57056288c7d4faf9dce413552d89215714320ac2b748e", + "docs/validation/startup-feedback-evidence/lint.log": "248cab557f593e8647e791bd7cd20e5f865019a3377a098f71bbd34a0d4f88d2", + "docs/validation/startup-feedback-evidence/red.log": "acee3ab05dd4773af10f01d23149a8ae084edf6b3b0f69d824da24fd2cd55f7c", + "docs/validation/startup-feedback-evidence/source_tests.py": "1325551caa7db9242fd5962a0290ff159370b67095aa31908b6a7f144937ac49", + "docs/validation/startup-feedback-evidence/wrapper-delivery-diagnostic.log": "c8666e0b95008596a4ec0fca34cc57a0c41f1affb90ac4e65ecd2861e7de144e", + "docs/validation/startup-feedback-evidence/wrapper-diagnostic.log": "810b80e0779b36bdc69f66eb32ea162161c371b34daa6893f34d52197930368c", + "docs/validation/startup-feedback-evidence/wrapper-identity-diagnostic.log": "6ae2bdbaecc6fca34e7fdd1a949c5e5368271c69de76e3e68c5227578df99272", + "docs/validation/startup-feedback-evidence/wrapper-scope-diagnostic.log": "fb70a117dbaab868c17c577ea4dc7d005729274ab0c47af731f207f4206b16cf", + "docs/validation/strict-mcp-arguments-484.rst": "8ab8b5f86d78eb057deeb41abd9acefc215618d4f6d153ef169780b0d43bba9e", + "docs/validation/viewer_current_main_integration_20260930.rst": "e38ac840a61fd88a6f726650cdca4e6c292eaab2d3ec62d53fcec1dc44f6fc89", + "docs/validation/viewer_reset_lifecycle_308_20260930/all-owner-bounded-first.log": "9916c9eebf3fea7c059532aa48bccf4858b622bb7e4e3abd0d3f68d481762b62", + "docs/validation/viewer_reset_lifecycle_308_20260930/baseline-shapes-bounded.log": "34beac2c43735d1ff1b5677765ad1ee0ebecaa6d988e1ac11bc20aae0ea909f2", + "docs/validation/viewer_reset_lifecycle_308_20260930/baseline-valid-transitions.log": "330004ca4e0e567b8e381c1776abbc342e11742b3ad8c5be084c8e4a94796732", + "docs/validation/viewer_reset_lifecycle_308_20260930/check-parent-artifacts.py": "8f556b3a73c09e4c0b08c395657f9cf82ec1f8108ad8be5d6cd2bb2e29f87a4c", + "docs/validation/viewer_reset_lifecycle_308_20260930/checkpoint.rst": "d8e96f262df080c82395dbe9bb3fdb8555330c280a004399625ffff75dd8ccf7", + "docs/validation/viewer_reset_lifecycle_308_20260930/final-matrix.log": "67fa3627739582d8e0131b80cdbc6e95e71a2973dc2ec72312f680438b064efc", + "docs/validation/viewer_reset_lifecycle_308_20260930/mcp-witness.py": "e754735e27fbe955f813a2da9ab5eb556ec3c48013aeab31b918a0b81a393f6e", + "docs/validation/viewer_reset_lifecycle_308_20260930/native-calibration-owner.log": "7c9903a4889900185e04ca6aeb5eb7da2b316dcb8f1ec857143db297566faa7a", + "docs/validation/viewer_reset_lifecycle_308_20260930/native-layer-owner-complete.log": "95d9ed4f50cd181f2e38bb887a1034e2b59e79f2656656c53829fb5121c7e2a5", + "docs/validation/viewer_reset_lifecycle_308_20260930/owner-image-clear.log": "8526bae6f0609d450c8d4fb153dc8faee16e74ce8bc525277fdf5ea46d3d6186", + "docs/validation/viewer_reset_lifecycle_308_20260930/owner-regressions-first.log": "7ce86ac591ec0f7e43c08fb45b57cd85dedfa7ad3a35077eb24194196d3d84a7", + "docs/validation/viewer_reset_lifecycle_308_20260930/parent-acceptance.rst": "d0e0241d1f4caea5d6e4ac6ee1b8a884dbb0a36f34a004fe880171afab90841e", + "docs/validation/viewer_reset_lifecycle_308_20260930/pipeline-parent.py": "d988a7b112ab8793c22cb452287d19d805f3dce8bb0c2305c9a7906c4f6d4e9e", + "docs/validation/viewer_reset_lifecycle_308_20260930/pr-body.md": "0abd364780ca4f8407464424374008cac9ceccd59b69e3876c23100cc619d898", + "docs/validation/viewer_reset_lifecycle_308_20260930/queue-owner-shard.log": "abca21fcf9ad6e1f9cefb7ef8c38a484f73375875179680771f03caaeccf89e1", + "docs/validation/viewer_reset_lifecycle_308_20260930/ratchet-final-resources.txt": "bdeab9583749d9b6d1bfce1d492fadb3a8f672a86c83730731fa1c22cadb97ad", + "docs/validation/viewer_reset_lifecycle_308_20260930/ratchet-final.json.gz": "70ee2d911ba7f205a27d83b7c7f8f294b42562e38b810af8fdd8de6524d2d6bb", + "docs/validation/viewer_reset_lifecycle_308_20260930/ratchet-first-314-resources.txt": "0ec866ba617a3c023d2ed284ead089a2818cbab29b06a3a5b9f55298118c1a65", + "docs/validation/viewer_reset_lifecycle_308_20260930/ratchet-first-314.json.gz": "344840c4424fa4780335a788858747b3a1441e599e1d1f74cc4dce2a022ff534", + "docs/validation/viewer_reset_lifecycle_308_20260930/ratchet-first-resources.txt": "dd7480f81ca757aff9fc1457129dccec6cd8bb1425a746de992e76a34ef6d27e", + "docs/validation/viewer_reset_lifecycle_308_20260930/run-parent.sh": "2d27b3cfb94d4444b91a0566840df5fda899f2a8c8d66a172134e7ada90b3fd6", + "docs/validation/viewer_reset_lifecycle_308_20260930/run-source-check.sh": "61447838b1691795ffc7e0bdb06d01b0544683267c218221ad996467f9471929", + "docs/validation/viewer_reset_lifecycle_308_20260930/shapes-4097-owner.log": "b2abbeba4cd5abc7235bc90c9216a493e9f3d5715417688036a0815313c11918", + "docs/validation/viewer_reset_lifecycle_308_20260930/shared-axis-authority.log": "e7935c30c741375b620afd614ef0078c289c24b5989ffdbe839576ba83bc0f65", + "docs/validation/viewer_reset_lifecycle_308_20260930/transitions-final.log": "c26d1c763a9a66fdcc46335ddcd37cbe103321d237c8ac5dc9196969e0f32ba9", + "docs/validation/viewer_route_spatial_302/checkpoint.rst": "a6b33c5439f99cfb65ddf08d523db9669244adc109b16f3a6de15bfd75980f71", + "docs/validation/viewer_route_spatial_302/pipeline.py": "0b7bad084f866391fa16109d63ec2c49975cccea723891a7a2c0ffe951df3ccb", + "docs/validation/viewer_route_spatial_302/run-candidate.sh": "7c0235b7b95d0047258618e111b14aa82f81e7fe7eca7538cf058e0512f965f3", + "docs/validation/viewer_route_spatial_302/run-source-check.sh": "bd8979cba48790c86a9af134694d5212367d0e77c539c27da6866c520301d033" + }, + "supplement_receipt_sha256": "4591cf83209105017f8d78bb64cc64f42d2b46d9968375186f92fa675c6b5b8a", + "supplement_preserved_sha256": { + "docs/validation/custom-plate-admission-500.rst": "efd0d37398ed532f15c1780e22d638c8527d7cf390febf8356b420ce2ee2e4f9", + "docs/validation/custom_plate_admission_journey.py": "8c16833a763456342bc521c5b12faf5904dee6c0c8265d9a99d4caf4be209eaf", + "docs/validation/knowledge-native-source-499-20261003.rst": "52a77c7752cb6b53f7a5f7974aaa2199b40e4865e6dbc4a3d3418630833fc688", + "docs/validation/registered-object-output-categorical03-20261003.tar.gz": "cfb5acbc8b132d3287a3f484586211598c6ec0004425da71b350b4e98e02c521", + "docs/validation/registered-object-output-categorical95-20261003.tar.gz": "16d29b1c1629c1908211ed1280504ae02fe0fc07b1ad63fedfd2f805bd4dc3c7", + "docs/validation/registered-object-output-installed-20261003.tar.gz": "2f76da3cf82a7f431a73bfdd73b5c13a5751677ff9c6515e61f83bf77f3c8cbc", + "docs/validation/registered-object-output-public04-accepted-20261003.tar.gz": "e9e5ef2aeddfc3c274790a8752a708b66d3d0c4d7fa400650c67b18737ebc470", + "docs/validation/registered-object-output-public95-20261003.tar.gz": "562e6d03beb246732d197fce156a2656b044f4495c997b85edff655af2b62e39", + "docs/validation/registered-object-output-scalar04-20261003.tar.gz": "0406ce8ccd7ce3ef7b72793d0aa0424c8297705c2348cd213310fc07ffd142d2", + "docs/validation/registered-object-output-source-20261003.tar.gz": "c6f6184f9ae097c05542e187398c7c0b174c108feba087463ad035cec4214f1a", + "docs/validation/registered-object-output-split95-20261003.tar.gz": "9be6f11b2dfd749aec5a2f0b71eb26515744e44d1299ccf76129236bc3a19003", + "docs/validation/registered-object-output-working-20261003.tar.gz": "c8fee189f0e2101d1bd8568094cb58fb1eaa4bc17d070fc2b027d7702e007fc4", + "docs/validation/registered_object_output_boundaries_20261003.rst": "1a6cc7d1a8490ac7845fbd0ef77687ff8fca7f2d451e3148ac30d74aa3146150" + }, + "law": "Every preserved website/validation file checked; every currently absent tracked byte equals current Git blob; exact8Gitlinks retained. Only these two explicit sparse prefixes admitted." + }, + "sparse_supplement_manifest_sha256": "4591cf83209105017f8d78bb64cc64f42d2b46d9968375186f92fa675c6b5b8a", + "canonical_head": "902913616e19f5b242928d4e835b8c2e10ab2fce", + "canonical_status": "", + "dependencies": { + "external/ObjectState": { + "head": "b0004daf3223326ac78689ba7b2e68abc18ae298", + "status": "", + "files": { + ".github/badges/coverage.svg": "5f87bee9f8cf0a67b8cf6e1eceb1fcbb1bf57b3875e1979527faedf2ab2a8c9c", + ".github/workflows/ci.yml": "f93e84bd08fd1c8254b7b863cb2d99c74db85fb8b16bb3779a698b166f660d90", + ".github/workflows/coverage-pages.yml": "222698b93c43d62c6a301b00429084c6b64efaeebad41df2c29949205992057f", + ".github/workflows/publish.yml": "9ce34113e7ff654cfa86cff6018299a98fc03a8851f0b9899777e90bb1bbee9b", + ".gitignore": "a26875c24503b80c1699f99988e68bb14ef3f4834d476864139553a63be5148a", + ".readthedocs.yaml": "2f5648c67a8a1ba1db73ec8dc32fbb82ffb83b246671e1dade4cb8836d667c6f", + "BADGE_SETUP.md": "8395730f7b6a6b5c7c97de76802bd2513bca8cc29a4dd8fcad7a91d4f713b097", + "LICENSE": "c5a804a1e4c08f5593eb8466c91dc4e871fe79319d81737a82a3cc514b7b2ff6", + "README.md": "1d72de341fc17c96587a75bba4a913787321bf598b848474a833b34a0547842e", + "docs/.gitignore": "79b7c477e1d731b44f15770e60642935f79fcaffdad433be5a9a82d6c790d66a", + "docs/Makefile": "43df277c1f15a11e9ab7180cfaa9e65e014571beec43b19530a363f4e62e0cd9", + "docs/api/modules.rst": "bb05baa62c63a0ed6a5773ca4b644de247b91486f65cb1f18e4671e3cce2a595", + "docs/architectural_fixes.rst": "278558dd9d4bd42a347147b22b5f52262192f8a72819fb4365055c2e5c5b4448", + "docs/architecture.rst": "2523332a130b3e06aae51f127543261788b208e61d0646ddbc99104d0383266e", + "docs/archive/DOCUMENTATION_AUDIT.md": "5d2ba10f1b5f3a6f20ec74ffb10ed6358866f193737a71ce4ad2af025be12807", + "docs/archive/DOCUMENTATION_FIXES.md": "89d8f817cdfc018af56c879cd5edad906acc566b2444404a94f0b00c65eb007d", + "docs/archive/README.md": "e5a389ed4d06d204e0af5dc2502f5b661804108beb404c03fb8e5f71ef0ec820", + "docs/conf.py": "bc49d86e265031fd39550513524727428685c836d73d5434a43031db4490301b", + "docs/examples/atomic_operations.rst": "c3b719cb22ddda78a4d7836d6bc7c67f56482cfeac6c8cb3823d6666f1e3b428", + "docs/examples/basic.rst": "487b5fcae6e2d98480c39bd613f17552bf95568ad1bf85168113c4872667094c", + "docs/examples/dual_axis.rst": "df17e2f8efa9bf10d1ef12cfdeb755504395b11c5fb66a22c414dd2b3a49c05b", + "docs/examples/index.rst": "0fd2ab7c22363ef78158d43928779b83b3ffbd0f4153162dd77e7e0e323993c2", + "docs/examples/ui.rst": "04d9c0c1354730c98efeb16503e3b8d31ff569ef145e09dadf60dc07991cbfe0", + "docs/index.rst": "bb8c0eb64c2e2e57ef490943cd88b0b11b1b58bd6760bcaa6b7327766a49b2bf", + "docs/make.bat": "ed525cc4d41b62b8b96d4b62a44ef32d6ccfd9324a379a82d5f71b5fb6d57776", + "docs/provenance.rst": "f7b883738fc949f3b5806dbdfe33f18715dd81dae3f98aaf68a2b8c021b5d245", + "docs/quickstart.rst": "318fd7296e2f4c3be4907cdd39b6bd89853af2132baa7df14d569b77ad7bd55f", + "docs/state_management.rst": "4a12f5b3e3438f66fa8135de44127c2feb51da0f8973cee39001af64f83a97b3", + "docs/state_propagation.rst": "b1483c16840d7ccc928b2be19e71a54166650b10d6960e173d72a116f842a203", + "docs/undo_redo.rst": "6355cd0faa82c2261645287ff1c4aebc8d85dee31c8705e698b2b0b53c0cf3ec", + "paper.bib": "4ed4113559097ad565ffa3a098e126a830e0bac39afc7798bf61d12f6b071876", + "paper.md": "f44f04ce7d7f1f037a34a89f560825a9666fb1c4c31788412cf948b2195fc41d", + "plans/n_dimensional_inheritance.md": "e55beb4463a8f0bb2d699618a44f16f3bac7f9c084154c4efc9567ebd1ac94b3", + "pyproject.toml": "a0d2835c65fe7c65b5f40259cc1d9527095bf4a3b87d1f70030df6ef9e7ef16a", + "scripts/check_ruff_added_lines.py": "e88118d5e1fb5db477cc11fb80f594ba213482614c565f3ed6383d992995c81d", + "scripts/release.py": "52abee369fee146ee8cf83fa266b5f1dbaacc31bb5934e967265054dbc7561ba", + "scripts/update_and_release.py": "80896e49f856d6a193bb1dc3917f55d2878acf1476c8240333eda16b92e8e61a", + "scripts/update_version.py": "63d0085d6b72ff34bf9560f60e4a91351ba21416b4eccd9b48aa30d40c49022a", + "scripts/verify_release_ready.py": "0a8d8fec9af999c3bba6281f2cafdadd06365090536580c8b168f43c96674dd2", + "src/objectstate/__init__.py": "6c71001be0c325b1344a9d48948c4521e1c1f7b36821741591b76271e7682b1b", + "src/objectstate/collection_containers.py": "a939d07f5dc391b7131f7ffaa7d1390b0449b4931d54ed5b09b27f59056b6e9b", + "src/objectstate/config.py": "6db2d9de077872009f1d6defe351cf8f40e441a0de31ff574b02741cefb4ffe3", + "src/objectstate/construction_binding.py": "9cfed94cad1cc9d5cf2cf0f7e8f534f72192168bdf3ba90b2b8d7ee57f4950d3", + "src/objectstate/context_manager.py": "a01b0fc8aeb9b5b0888346f725f92cbfd96b90963bf20001b5414a5e6cd6c0e6", + "src/objectstate/docs/configuration_framework.rst": "75ef312d77f009aef7b01b506797efaddb8fcd3e16b958bf7a74e752df950cb6", + "src/objectstate/docs/context_system.rst": "fe834139f63b1a92665d12ec768ec1cbf216b355dac3b12905d31081df4e0824", + "src/objectstate/docs/object_state_lifecycle.rst": "7a9b977fadc226e0fd03cc17e1ac31cb807f23b2b6794462a6f3f7ff80ceb4aa", + "src/objectstate/dual_axis_resolver.py": "17fcda62912050bdcdd018bee2fca5f81c2f4940c5f27f2af3dc19b7691e1fb0", + "src/objectstate/edit_session.py": "003cfaff8d3687b0fa115e051c3cf833a3cbb21ad9d9becfe16c59359d656350", + "src/objectstate/field_access.py": "77f483322a504c392c0ca41cc3ee6b691d258396f70f00a61b98d9f4bc03d43a", + "src/objectstate/global_config.py": "a8187811f87806579640a8147f287114e7127401530178dd37e8d28ed788a6ae", + "src/objectstate/history_migration.py": "1c24097040e38c159ea7e809424c0b94ec6c34efa3dc84cd664ff6a2f790815f", + "src/objectstate/lazy_factory.py": "f81ce722695dbab98fd02658f2015e5cb93c1e1e69547d24249e62d896e2a828", + "src/objectstate/live_context_resolver.py": "bd169b0bf2e9eea833ffc1d28331d320b2386193652fca041387f32bf018d71e", + "src/objectstate/object_state.py": "735ce860ab650b281534e24e3c7354f37b64bb06832cf186d6b1f626f87108fe", + "src/objectstate/object_state_metadata.py": "4c5be42e313e3f896f2db0d3f89ca18ca6ab09b9d25f202a7b2af9e59a099ddb", + "src/objectstate/object_state_registry.py": "f848746a9c2a023a616c37531691073ea7bdb8d28d7db3bca5c8a3dcb176107a", + "src/objectstate/parameter_owner.py": "908606ec2da70f223a93071e92ca24affb3f172f7df14c64dfd27974f1fbb85c", + "src/objectstate/parameter_structure.py": "00a786af17bca57b4e819d39c76a6523af3bec116d119c323dea8c2953c7be3d", + "src/objectstate/parametric_axes.py": "7229b518f8d5cca522a3020361c16a601f3084bc5a7d34ef92a2fef11619e40c", + "src/objectstate/placeholder.py": "4e057cf3225dd38ef3859f20fcd1305526829f044af45ef616381ea734df8f67", + "src/objectstate/reified_generics.py": "39ad0897ec45ba929c0fae694dd870df987c06e2b005644189212fe224eceab2", + "src/objectstate/snapshot_model.py": "001cc83d354b040763b2da9aad0014619fdee22c82dce622dbd93ecfba780681", + "src/objectstate/subfield_semantics.py": "97aa6a7f2659260b1950c068f47d9bccec15087ed1852f1dd182272c8230c14a", + "src/objectstate/time_travel_profile.py": "c59d157f9cb85ee29aa64e18393d916ded656c6ce88bb46782f44e2463fcd007", + "src/objectstate/token_cache.py": "d6b7cdb71c15e13e8bab7271d70e0b96ccbe0825004c45c4e88851ee30a9435f", + "src/objectstate/transaction_checkpoint.py": "4c105f2078bf23c9312c600543623b9456de256c7093b9cb8a9b753b49b67530", + "src/objectstate/ui_visibility.py": "be0c60b66b86ebb696583ee394c0d45b05fd1f68a609a6aa0c29aa1098dc2592", + "src/objectstate/value_semantics.py": "4b8a43ca8667c592b74f0d46b8507ef8331402e376230dd7cac217870b2ae2f9", + "tests/__init__.py": "b0f08e026c34c8ec04203081ad79f7ed1c6cbabd784cf475333965f279ea33ae", + "tests/conftest.py": "0fa840dddea79e86afe717e146ba7ac7ee713b032e0e398b0a9f56842e4a1d62", + "tests/test_callable_baseline.py": "638929e6eb97a7c899443272e307beaa62a12922debdc7594a45ec0a85da3356", + "tests/test_config.py": "973b08f470fd54a4990cf39c7f176b9f5d02ed0b808dbf8ea2549a01d7b30d77", + "tests/test_construction_history.py": "88469c8157d4010b9877f76b7a605bb7222222d614e1ea22aeec0c39870d1609", + "tests/test_context_manager.py": "c14d3ce760520544cda14273e76df66606e47ae1bba410f83746b216b4a6418c", + "tests/test_field_access.py": "7484f7b0127e1be332ac013ea5f5c61ec5da9f2cd7fef9fcde8a8e8ab1384c54", + "tests/test_global_config.py": "f4624ffd22cf4d09bc05466dac91cf952e81033b34ab475bd1442c3d96887833", + "tests/test_history_persistence.py": "547d0cba078c2caec8b6217ec0b8713aac1ac2efd69d143e6549b023e5cd4d33", + "tests/test_integration.py": "df082bcca0ee4d6cf1c3899b4e43ccd2a004891446a05480bcdb1930ed467c24", + "tests/test_lazy_factory.py": "b3f1602d85a6e91a1b4e42490dd5253d2d0c43371a193d7369fe149bc839ceb4", + "tests/test_object_state_metadata_contracts.py": "dbd555d1659a1dd79c8c93c1d5168282a8cfaa3d727ac3fcc4d7d913eea00360", + "tests/test_object_state_restore.py": "3319b7244e0be237896902955f4c49829d4135c057116885935791bd8f125a81", + "tests/test_object_state_update_instance.py": "aef1aa303a2f3d68246f87a1a6871c0e0e48cc12d5574ef105be5aa3202a7526", + "tests/test_parameter_owner.py": "b28675a55ab72d8fdf011f972e3c5154fc683fc8206a7195342ac0a774bd873d", + "tests/test_parametric_axes.py": "8717ac074d559294e00a3d33afaac6415230efcce78f38b1e296a11c9596dcce", + "tests/test_placeholder.py": "1b9d20e8931234622ef1cf726d12e8e4fa00328c0b1cb33e9eb0fdf7acc1631d", + "tests/test_registry_subscription.py": "c634b5e416a7ea3ca04abcab65679c2852595c595b6e23cde6424ba9f6c7643d", + "tests/test_reified_generics.py": "548f5b6a282fc26b73cb5211fc8a9eb92f37fe9cc57e37cf964597293fe98866", + "tests/test_resolved_change_notifications.py": "d0addec005be985da187845efba11e1dd03367b5b9557cc1fcc54a119e42c66a", + "tests/test_subfield_semantics.py": "f156d9666a909abe9c9dbb8f69823b1e88edab310248687c4e012ab97e5a43ec", + "tests/test_timeline_projection.py": "e02529d96f61f3601c91fe30e133c4f78107d3ea6f65c864198b232b8ad76780", + "tests/test_transaction_checkpoint.py": "531c4df6b3fa25a28ac17d020532179877d4f53d66f57af1bff7beb07d08f89d", + "tests/test_ui_visible_field_projection.py": "27e016e8755374e9322460b83344836f9a3f1f0e54e9303c4b16e6abf775baea", + "tests/test_undo_redo_cascade.py": "5f8cd61f70b966ac506b5a2ba4460d58c789137f7f992dd7537d572efdcefc67", + "tests/test_value_semantics.py": "fb98e8637abe45a981faae3b61fcc9ddc14ef84b4ef5e41b95fa5736bdae2968" + } + }, + "external/python-introspect": { + "head": "4e8f8bde5f750d9a50eacac80acd3806123addd8", + "status": "", + "files": { + ".github/actions/validate-python-release/action.yml": "ba8808c30bfcf27ce6f9dcbbf12e60af274f4d309c8e409eb3cd93ab2809436b", + ".github/actions/validate-python-release/validate_python_release.py": "96275b643ee03adac9a13996006cca803ec07a0f0d0835d47f559677af016fbc", + ".github/workflows/ci.yml": "da7bc66a370447d0dfcfb7de4ff723fe92fa3f6b34219066bee30efc3fbfb6a1", + ".github/workflows/docs.yml": "62187d940fb88d0ff42ba69a2aa1127462b04424441a039097fe956934fd0293", + ".github/workflows/publish.yml": "3dbae1430de7372a6638d339d955bc036d64b88c968edcf96ea578afbd4a4d17", + ".gitignore": "6ec409ab221e797f3f6d5e63ad9dd8e7bf09913976f8dc8a0268ecbd3cec280d", + ".readthedocs.yaml": "c95cbaad19adbbe07f93650fdb705f22629d20dfb51296e6ed566f280abfe6c6", + "CONTRIBUTING.md": "73bff7a6b106765f0e3a2f9df7e9c4da7b6243f0a9522d737ca3ed33ef16496d", + "LICENSE": "c5a804a1e4c08f5593eb8466c91dc4e871fe79319d81737a82a3cc514b7b2ff6", + "README.md": "d861f8aff2e79d9e77fbb2286b2f353c5b568412482a57efce9a488e58d543fe", + "docs/.gitignore": "7f1d49f8fa7578f81fec5b86469e14d2cf3a94ae0d85abe6bf5373f5f760ac42", + "docs/Makefile": "e33bf74d59130029ba24168a813112dd923d7044d780ce942db6645d93f56acf", + "docs/make.bat": "d2a8ebcce0de81abca77b2cbc26afd00385a61fb624e7060a8e5402fd900a72a", + "docs/source/_static/.gitkeep": "bacb37455f4ed8710d244dbe230509e632f06da53df6f849443d1deb2315dbff", + "docs/source/_templates/.gitkeep": "b32922d255e14ebf318fa34bf4519185b2498b279b89cac175150eea8e9ba76c", + "docs/source/api.rst": "f2743f0d134d71d8799d0ba4d995bf2b378234da40aa9a5008fa78b5cd2d379d", + "docs/source/conf.py": "534c6205463a628d4d7d58b2793d95cffea83a6ec2c0085b012a29b046c398ea", + "docs/source/development.rst": "fb7c848d6d5b1ee40acf259a306a20f7380c4e6928e76df938978b565e6d416c", + "docs/source/extensions.rst": "cd50883eb7b31ac94ea55b1dc662a637e844626c1950cdfc2c0cd211e776ac0a", + "docs/source/index.rst": "c98c4bcc2623fb87c1b4eb0858819ed11efa3618fd0fa56e8df3dccba415d6a9", + "pyproject.toml": "3dceb0255a1cce6f92d0ddc4d1c1e5a52de72e4594cccc73df77ce5db273e1e3", + "scripts/release.py": "f5ba54de5d2ef89ec7c75e536b63817989b8f9f17e3b2c10bb981b5bf8d08837", + "scripts/update_and_release.py": "80896e49f856d6a193bb1dc3917f55d2878acf1476c8240333eda16b92e8e61a", + "scripts/update_version.py": "303a09dca1b7374ed1d8e4aa26d76ec1bc76cfb6a769e002f2088927d51a6aa5", + "scripts/verify_release_ready.py": "5fe0aebbcaee7f60540f50221a1f8da1beab2b8b59d9b97f3b4a240f0e72211f", + "src/python_introspect/__init__.py": "5e4938dfcdfbda603c0b90a21b9a0039ebae0a59dd8e44d51059aa28c3a74e3d", + "src/python_introspect/annotation_types.py": "dc126879a8a581cea0758eec4df18ec20c47ca4b1e135abde23699b65b790bde", + "src/python_introspect/callable_declaration.py": "3bb8b474624fe6b2964a5c1f9a6aa540b2703500bfa124e7808995cb789d6951", + "src/python_introspect/dataclass_projection.py": "82662ff8eaa4f2aeb3b33edd61abae57020a7f139c3aa396d82dcecf8b801160", + "src/python_introspect/docstring_annotations.py": "444e8064f833f1a044208bd4a15107a6b688b597e36ab78ac58bee6996b51fc9", + "src/python_introspect/enableable.py": "025eadd64a6a6f1648bc36fbd1724f6049355a0b9b1a259443248d70170b8eb6", + "src/python_introspect/environment_projection.py": "8ab7d1e01e9a4529ea0b77d8996a5feeb94bdc2e905dd6263afb28d11bc217a0", + "src/python_introspect/exceptions.py": "4c6f15a3625d02b05b2fc8651e67e6b77d4bb442ad180b85121d91874ec3407b", + "src/python_introspect/runtime_parameter.py": "59fed2d467e751686447322f8e19a8633d964741d3d8afccb850dc504a619897", + "src/python_introspect/signature_analyzer.py": "51f4729861062ab857153c57d64b01bd7b0f47daa6f18fc4443819fb75c77b45", + "src/python_introspect/unified_parameter_analyzer.py": "ac52ab997fb385425920614451e8cc754fece0176bab4cc9b132eae8c930ab15", + "src/python_introspect/validation.py": "46fba78bd068c75c89b91baa4a5cbe8cdca9692e75a285eaf76311183df77b64", + "tests/__init__.py": "c752ad382f759406b1c9c102142aac7cc10a2693b8e5848536e44315567a034f", + "tests/test_annotation_types.py": "ae38706899ad48445224b09babff76496006576e7f188af7e27261521ea34ad9", + "tests/test_callable_declaration.py": "b8486dcca0c85805a14975c00987c7c3247c2c8abcb75545f89e04a01f738c32", + "tests/test_dataclass_projection.py": "6f662d0adcdd4531d8cbd94c2ffed55ced3a53c3ec481a9dce67979ac8489990", + "tests/test_environment_projection.py": "e11e2c180c605e761acd48103fcba10dada614a326e40a55d4777abcf0853899", + "tests/test_exceptions.py": "41f4a70df08a7718b4c9daa05569e6c491c0148abf975f0aeae78688e99d8744", + "tests/test_init.py": "7e9ca130ed8254034e32b991f8abd4624f6c1bfcdba65f911dc28c12d9cdfeca", + "tests/test_runtime_parameter.py": "b728307c8e6c7e50ca9b0befd1aaf154ad293eb18f332be544719d7ae9dd3fb4", + "tests/test_signature_analyzer.py": "0708fdcb848fe874eb4dae025c1c9fd9b0929e983cb1c1c53cb268af9fb37c2e", + "tests/test_unified_parameter_analyzer.py": "deb55bac9e31465c8368c6101a93e3c951e139c5c7ebd442a5f8cdc98842f1cd", + "tests/test_validate_python_release_action.py": "65fc7bdff5d20229e74e3abd44f936d7cfcaf9fa5881a7e9e65c59bbd65c6c12", + "tests/test_validation.py": "ce9cab31e33a001df0d40454a8d7de9e7a2ab6dc6296399adb234d06f7dfae39" + } + }, + "external/arraybridge": { + "head": "1e53d03d9f468322a1c085c8be29485fb139caf2", + "status": "", + "files": { + ".github/workflows/ci.yml": "cadf2e9e7f8378357df650beb1a99f89c1ce9404aa297e8d707bff14c9a3f60f", + ".github/workflows/coverage-pages.yml": "4d6692efebe182beb62829c1bf3c19616159316b649b84cf5ba3d30d2a44599f", + ".github/workflows/gpu-tests.yml": "ab3b757bfb18d9b508347ca1be122ef2b084cad5e9baec8bd99c73ca8ac44ec3", + ".github/workflows/publish.yml": "98eafc9d3a4250b4fead850300eebd9e63dda05f162614ac28fa757a7d2996ee", + ".gitignore": "a26875c24503b80c1699f99988e68bb14ef3f4834d476864139553a63be5148a", + ".readthedocs.yml": "64f56fbb4a8a1ec0124b2704c97ac75ca57dd9d75922f0f32122ccc07d9d5dec", + "ADDING_NEW_FRAMEWORKS.md": "cc7f1899e7c7fb553acfd5f86e468689c367ec9eceb334d74f5d9a9c1845fb20", + "CONTRIBUTING.md": "e8e3288c0eda555fc5a55f93c3de958951bb5d339ed1e88407be837d5b392405", + "LICENSE": "c5a804a1e4c08f5593eb8466c91dc4e871fe79319d81737a82a3cc514b7b2ff6", + "README.md": "b108a144e2f797425a1734f745a73ac7a215bd5e58b3f6fe4342b18e7d16b892", + "TESTING.md": "04f1c2f01407bf49f4144301b567e766f920bac8c90ef7361d17a94f87935292", + "docs/Makefile": "e33bf74d59130029ba24168a813112dd923d7044d780ce942db6645d93f56acf", + "docs/archive/CI_ARTIFACT_UPDATE.md": "46a466f6398118a214279f30115db82d22f20847de0afbba6947f3a807d2fe18", + "docs/archive/CI_CUPY_FIX.md": "2c271a926da57ebe1914d8784e03dde43c372ee086e69981513962dcdfc977ab", + "docs/archive/CI_IMPROVEMENTS.md": "d52addf07d29e00a4a145e164c01d2499f0d063c4d28913b361c259187e083b4", + "docs/archive/CONFLICT_VISUALIZATION.md": "5ad9a1b04c6d1271506c3a94b6e7df36c80f146014425094ae3fb9e2f649a7f8", + "docs/archive/COVERAGE_AUDIT_PLAN.md": "3c54a04e3a7f0149f7e0d2a77fe8e734fe7b85593c6542851ed1d0934aee710a", + "docs/archive/DEPLOYMENT_SUMMARY.md": "40c0e2337792f659e92d4391ff8a7bf5f5b7b8b46f3379c8792d2e9055127060", + "docs/archive/GPU_TESTING_SETUP.md": "b9b94a8b40705767eb1d192ac6c140975aa624d541352847e3cb7a4734f22efd", + "docs/archive/MERGE_CONFLICT_RESOLUTION.md": "a0a3a028c5583b8eb4903ed206946c0b712b4342371f0aa10d0b6185e2726fa2", + "docs/archive/MIGRATION_SUMMARY.md": "22c0cc300f73972dafa606cb69a28025a2e0e73490ae35eb65dd5f45deb5d998", + "docs/archive/QUICK_FIX_GUIDE.txt": "44bbfe657f6f178cc3c148ede870ae2c4b3c756179b13f532d97132c45bd5307", + "docs/archive/README.md": "a28d7cde396af47e9bd985d54e517643b6f789410aa02ddaf878bd927a9714e9", + "docs/archive/RESOLVED_FILES.md": "fb72be1ebb40adddaff772ef4b3520eb578b3d028e8fb2bd526eaefe6a897e81", + "docs/ci-cd.md": "94bedfc598f0dc498e22e1a0d46e5399ed169595eefbcb95242ffc5d00a7be77", + "docs/source/.gitignore": "0485bfc859ca5866baa1043a32e732b18fa606ced2fcf39c27a7e7d3c89695c9", + "docs/source/Makefile": "8b6587b859607f200f116e2cb043fc358e1c3a26c326b563bf348453cfc68307", + "docs/source/README.md": "537352768576aa21efe985e7abbe266e43b1000298ae74097625173fb99588df", + "docs/source/advanced_topics.rst": "97b6134aba0c54f2920cf0b2978c09c092e8baaef09a044a4bc2b54df3acb3f8", + "docs/source/api_reference.rst": "9e337146f1fd22efe834f9739eab4135775c47bb1e3b01b57b33d4f3ec055072", + "docs/source/ci-cd.rst": "22e0ad2df054c693ee570833132daeca77b14ae494b8be2ba92fa1516ca4b3c2", + "docs/source/conf.py": "1b43c862dc93e51e93c0ef0435a9e5cf208665d84a2d0ed1c2477d5e4dbf3832", + "docs/source/contributing.rst": "b71e6e678251a155fa14980d64ae833b4c028bbb089b6b4d44b7baf280909190", + "docs/source/converters.rst": "b658d186779669a7eb367dcb60963fa57995c26ae63fbaad4a5c5bb75d10eb97", + "docs/source/decorators.rst": "3ff68560435fd1e0c1d5b3ee883f06f5bb3e6bb207f96e915556a662e4e461fb", + "docs/source/examples/basic_conversion.rst": "be11e27873b61fedfe0abd5f421817f683d99b731b5dbeb913aaee60dba5f08d", + "docs/source/examples/decorators.rst": "c6b0fadc2c3d36e6dc28e7fb50024c685df4f1e9e86a18be909c9cdfb00cad9b", + "docs/source/examples/index.rst": "eabe217c250d3301bf26ba2a6ae58fa4eff82c85c12e2e60e6ced6b533e1f295", + "docs/source/examples/multi_framework.rst": "1d7534ceeb611861f69aa7a0cc55c001b5f7949298192dc5e02f68fea5838c13", + "docs/source/gpu_features.rst": "8ab989045317cf0bc7ddac077caa93d6d7fe2a6f90e205462ae09ef03e605843", + "docs/source/index.rst": "963d5249c33b2ba4103c95fbf2c65038f82a883e561e9de7db825709bde3205a", + "docs/source/installation.rst": "89b6309bde9a0b72b4e6477e2b3f99efcbdce947374149c2dec92df7d8ccc003", + "docs/source/quickstart.rst": "99324fb002fb28a08700015b54083c97a6505f733b1329504ed302b1f003ee72", + "docs/source/release_035_validation.rst": "4afb3f121805a2a63e912fd85197b76adac82d67b6d070fa73908e38c577fa3f", + "docs/source/release_036_validation.rst": "d9f902b370403e824c8047fe1cf14aae36e3ae26de50c1aebdce2783c8cc2f12", + "docs/source/stack_utils.rst": "e3203ed0755ac5714674f9db908c3fa990205e7161baacae1f97a31354fefb3e", + "docs/source/user_guide.rst": "50e205f365a839ed956103fc93f59a546dabe3a963ee5ba2285e75ded021516a", + "paper.bib": "20228af15370805fe07f53154b27a977e7bd32ae84cc44bfdf127a696c5ca0b0", + "paper.md": "363b3be3c60859de0bed4ef7db739e6e41b9345284c5c28e0b1f3b6fca61844e", + "pyproject.toml": "8134c94077df2defe89328963c250e6defaa2ec2b5f49c190f0966e9e575661b", + "scripts/release.py": "3e9caa24fbfde769e347f52542a557610bb02249b81aaa71649bd579d081b69d", + "scripts/update_version.py": "9d57e7324469c34691c4561466cc4d3330485812ce1c14418d8034d30bd85a3c", + "scripts/verify_release_ready.py": "bff7cb1232eeceb6d6d235309cfc75866c7b6c1f44c48f5b2ab65f856830477e", + "src/arraybridge/__init__.py": "ae1b2dd87b91b191356e9e1fdb74a32ba7131cda6341402c4a7aa087d47a4140", + "src/arraybridge/array_geometry.py": "0a8a5f1a61552b057997e94e4c89a19b5615875f307949e0d11784179f2a94f2", + "src/arraybridge/array_operations.py": "7e9ebda3d058702cdf8662dc5ab1faf1254649f3cbde76fa0adcbe02677fa103", + "src/arraybridge/array_payload.py": "ebf8c9c0f4726b4307ad435203d9173e54c84a92dad06ef8aea0d56a51972b1e", + "src/arraybridge/converters.py": "ab8e04e8f835ac9cfccaae964083cb3993efd65aaa7147041b81a1e03e4cd7fa", + "src/arraybridge/converters_registry.py": "fe11ed6ddfb748c20a530f1fbcdbb7b703d6258eea1f237243f361569dde4874", + "src/arraybridge/decorators.py": "28f9bf4770bd4cc1ef34045fdef28065063ede029296f62b8a6c4140cc88e40e", + "src/arraybridge/dtype_scaling.py": "283818c82bf182c4172c9265fdbb399c7e3acd08a6b00edcd4e96feb1276cf5a", + "src/arraybridge/exceptions.py": "7e17a3e594b7f50701156ccd78d623a2a78b5673a0c30a7e7162267b6e63caea", + "src/arraybridge/framework_config.py": "e724d3b7d356730cca0cc5db73e7ea09d88597ea6228eb774949f19915d70909", + "src/arraybridge/framework_ops.py": "eac427f155ed3e7e10ae0f9cc603a9a17d7c3f54b30db339e23f33873c94fff4", + "src/arraybridge/gpu_cleanup.py": "003238c0c2e4f4620ef6b27a049b8d937b9923200da00a89ed51539cb273adb1", + "src/arraybridge/oom_recovery.py": "846bceb891d54a8a6222a6e5ce830596a5bcfe82ba66500617f978a5f1258de2", + "src/arraybridge/slice_processing.py": "e51d743a61d6f0149b245c13d5445dd92cf73f5e68e4485a236567554508be44", + "src/arraybridge/stack_utils.py": "1558a43745c6f97af2c3ed69f4c6924544d97adee42dccb48131044528dcf6be", + "src/arraybridge/types.py": "7b94760d57e54008d7adf4e4d37dca45d8a2c288a9dc8400be00c26148cf7624", + "src/arraybridge/utils.py": "46a4e1b5849c3c4384406e3dd5d03c6ff56f5138e07058702db8747ab42ee4db", + "tests/__init__.py": "a0ac3b43f372047f4b85b516a7e4471f98744cf549dbeec484ff3f79728f0257", + "tests/conftest.py": "6a2fe5d7206ac30e37e544ba8ff939ffa4576565b9c7559fd660f0e41db6f24c", + "tests/test_array_geometry.py": "f9c0e91d6275a940399418f2c0de810ca90c781c30219d720b745f1cf912f0a3", + "tests/test_callable_dtype_default.py": "52f343317d9d943bee46edf4edfa7e1dfd9afbe2e2ced2a297b9bc764bacedc7", + "tests/test_converters.py": "390edeb089747cc13a6378d715996f238ece1610f7aa4e9e0c3a6c932a23e315", + "tests/test_converters_registry.py": "f40974f61e55cc49fc31dd53af0dda1790301edc2218d5ec6dbcbda0c712365f", + "tests/test_decorators.py": "0b841b293e82b59133c895159c9773552dc4e7a508bbe7976da45aaa1e5d894d", + "tests/test_dtype_scaling.py": "7fcea155eede82781b9566166079a86e403afa075c5335118696a390c1ed531b", + "tests/test_durable_decorator_context.py": "53e4bfb9a2491b6d5a238ca4aaf24ffce5853346d46621e25ebf92adfdf70642", + "tests/test_exceptions.py": "441f10606ee9175814b01a243f8aea572f341bb53517c31c2c719ce41a36fe27", + "tests/test_framework_config.py": "4995b8649bef8ff4bfbf80dae282a6c8e008b0120f1a905f118903fa903e8d8c", + "tests/test_gpu_cleanup.py": "bcd6ef4f4f56850e1f12eaf9fc237d756b06841bd1c2d093ebbd81cf1a04a0bf", + "tests/test_integration.py": "e8d87ba83d8fec2ea7a9841c413277516bf665aa08f688b29da819a4c545edd2", + "tests/test_oom_recovery.py": "773b96e901e85663b6418d4deefbb28bb3ac9298b7b20589373cfa0de05e2bf4", + "tests/test_registry_integration.py": "49b88b4f692af569b66c298c8751a78b0e28a08f4db41034ef05684352df5418", + "tests/test_slice_processing.py": "b7f996dd6c38382148c1b48c5428d33775c3067f91562f082de9ec0ce20ebb5f", + "tests/test_stack_utils.py": "918e015e452b31adef93ceb829e949043390d22888daff9a295317940a58a6bd", + "tests/test_types.py": "ae1701b48c68c6f07bb23d83800ef3ca049545c254840ad5a7863db4213b3c16", + "tests/test_utils.py": "15a78a8269843d90b8dee4a2b4a50cd1b34bc791fcd1588260d45cae3956aab5" + } + }, + "external/metaclass-registry": { + "head": "393a7e03003cdc56df9013f932ed4f26e632d77a", + "status": "", + "files": { + ".github/workflows/ci.yml": "036ed258494f0a2203882461397a9a2bc92f584b6006dbacaa77c2eb5beace14", + ".github/workflows/coverage-pages.yml": "410fdf83d1a1456975635cb4ae09dbaffaad8fb7ac8597c98268377b4c4c7896", + ".github/workflows/publish.yml": "85a7866717cc0a1285e74f751571d7d0b97b1210137b83585c66ed115619e600", + ".gitignore": "a26875c24503b80c1699f99988e68bb14ef3f4834d476864139553a63be5148a", + ".readthedocs.yml": "7506f658eb3b8583c0887684c3290910652325e33ab20f2041373feb7a89af19", + "CHANGELOG.md": "296f2431172f457518be6ad3789ed7d0ded103af4718937123269537b7e6bf6e", + "LICENSE": "c5a804a1e4c08f5593eb8466c91dc4e871fe79319d81737a82a3cc514b7b2ff6", + "PYPI_RELEASE_SETUP.md": "578df82d6426379a517799ed2edbf93298ecd6d848e39c7016514744df565de8", + "README.md": "668dab2cc7c536778ca0010f957c85335eda5eb2392e60c62d08b11d79009c37", + "RELEASE-SELECTED-DISCOVERY-022.rst": "2fa12717c0650cdccd83878b98b1f70a61ef94520acbc1cb7ca64c5e1c561c0f", + "SELECTED-DISCOVERY-376.rst": "22f0b41eeb3aa86183f8e2e83e225bff5ee8072aae39405dbcf9ff2bef07881c", + "docs/Makefile": "dd53c72b2b1c989f748fb2af7d719d8f351e757ae26bdf4f657b763bfe1ec4d9", + "docs/make.bat": "d2a8ebcce0de81abca77b2cbc26afd00385a61fb624e7060a8e5402fd900a72a", + "docs/source/api.rst": "d2da0de8358b7fb3fe1376358bffbf10cf39c827edae150a176b75a91490de52", + "docs/source/conf.py": "1d1618299bdaed818c3518ccc11dcd99f7277e4574b78a1db345c85fa2d949dd", + "docs/source/examples.rst": "fab494bfcff26a6aa84f7e3203a4f131832cf001b60fd4e87fb1ad24ce78ae24", + "docs/source/index.rst": "f707777948f83a5bba22528814b43520e61c76da730d0b93e0c5f3f91d6c5b12", + "docs/source/patterns.rst": "cb67e1b458cb073d226ad6691f4ed107bd35b887ad65452157a7283009707402", + "docs/source/quickstart.rst": "785bfb1e3d212247c730b79b756ba894af84d2dd4d61c43e9850c1ce79efdccd", + "docs/validation/issue251_cache_projection_20260930.md": "a740a1c5bd743564f795ec8563770788e78d719c221cafaf274d33987097c00c", + "paper.bib": "10b564cf153c1168960a822ff71950b16a16853f026a31838b23394d08d1cfee", + "paper.md": "d3d47e17ff3699034e9dfacaf7e0e2e18d3770c631048dc335e34e3d2fdc26d8", + "pyproject.toml": "2bc5a1a364bb17b03a4220cc3595d7889bfad3f731de3fe78453b16908b291c2", + "scripts/release.py": "19344fc3616a3d63e035df687ac82e8a040d0f7b69d5fb934c6e801df0ed5947", + "scripts/update_and_release.py": "80896e49f856d6a193bb1dc3917f55d2878acf1476c8240333eda16b92e8e61a", + "scripts/update_version.py": "f15d84a33dce9188e36576b21a84b7423dc868fc5e7eea22f8528dca83c3a5ba", + "scripts/verify_release_ready.py": "8747b1de6233c106025abe5fc4cfbbdf2a8d07641566445f4151b6fe4b5a9e1f", + "src/metaclass_registry/__init__.py": "b7dd8d905bcac00f490a6155df09e68d148f3e7b8238fed2854f2e1b5de06567", + "src/metaclass_registry/_home.py": "6949afb54c145a8c58f680c61177e3aa7a04e9b432b73552f5beb4b1b92169e0", + "src/metaclass_registry/cache.py": "10ba153bbbd6a45388a47aa28f5b18ab77847a33acec4820d31cf909153fb6ca", + "src/metaclass_registry/core.py": "5fbfc22dee24ac7cf653209ca06ca511ddedfb2c9e96a5354d7d4d4600828493", + "src/metaclass_registry/discovery.py": "757958272d11633e7b854c7104c07f0d90845c37fee6ab0c3646fb14c2ed8daa", + "src/metaclass_registry/exceptions.py": "333ae9a5b87cb884213a1833fde35c178734f5e684a8f772d6c0e35a090ec987", + "tests/__init__.py": "dadf7fb5f53a6c573dffaecd51460f3d36c83fd4ed903a5ed7ed21da331dd9d3", + "tests/conftest.py": "a2ad838c1e90bcfa8c368c51f07f473a85cbe4a95d27134349f94bfb1a57f767", + "tests/test_cache.py": "c0d077f47be112b257abf7ad574ca2bb4dbb7e7f3fbbe0c8044b69b69bf5c7cb", + "tests/test_cache_path_projection.py": "8da2d89cb7e88bc838b0a0d59068afe4a6ffc0010e3d4fcc196f55519d730ced", + "tests/test_core.py": "26446d33fcdd012ecf12ff7e541ce434aa38fb8f1fb110ee4ce4c74cbf0bea00", + "tests/test_discovery.py": "f28535b526c4fe95d68a33386c4378237468fb160867dd9b07a55de920939d3f", + "tests/test_exceptions.py": "11dd2d86ec4baea6834b28d9f368bb71c90dd91f23a12dcf795fb821a29ebf1b", + "tests/test_selected_discovery.py": "b20e2ff2441a37fc2700223e18cde1d64d1eba314521a656d8be2376da2c0b0a" + } + }, + "external/zmqruntime": { + "head": "668edafcb5ee530a163377c936431ae1e8334e85", + "status": "", + "files": { + ".github/dependabot.yml": "34790e08d06d30f3f06cf2f071fcb2430df398c0a70bf1d99b5cca71d69080ef", + ".github/workflows/publish.yml": "e0a6fd7824dfe9d4f8cd6e634038a940ee2ca78144535a64d40b44018328db81", + ".github/workflows/tests.yml": "f9b74f8a33d2b47746f7bec36c3b74979640e95d23d6da2849bc5c34a8ba7fa4", + ".gitignore": "80a49a462dd53e5509406a5305931664d212012c4cbf7ef7c48505527f632b15", + ".readthedocs.yaml": "8dd778d3217f13c531400542c6aa1e2ca620c84e68f73bbedd3bcffad5c9de33", + "ACK-ISSUE10-DRAFT-PR-BODY.md": "6e308ff02b10ab06fa58c209b1d6bfbb13191946ab1412cec644af26ed869a98", + "ACK-ISSUE10-OWNERSHIP-RECEIPT.md": "92228b50c7ca5e2d620d51f00ae46c464f3bfdc19d37cc1a7b7b8017adb74056", + "ACK-RETURN-ROUTE-DELIVERY-20260930.rst": "1a45185666390e9cf25032aa020fdeefb9988a1f7f47ff0a1fe82128e20e2454", + "LICENSE": "c5a804a1e4c08f5593eb8466c91dc4e871fe79319d81737a82a3cc514b7b2ff6", + "README.md": "c8f7fa1b36636d6cbcee78bf259f2e2511ef7e19a5533ae246548167e35b3eb9", + "docs/source/api/endpoint_handshake.rst": "b823c73359e3b140c24de84aacd567600381e726ebe3cdadfdad5bfe419a5980", + "docs/source/api/index.rst": "a598b60df852571f5d42508d9bd4025f07ca5d8cb1cf72b08910183b590c0239", + "docs/source/api/viewer_protocol.rst": "6d5d4d3abf96c69161c94a0127597b79fd0d26b6cdae5a1e0be258bbed549396", + "docs/source/architecture/execution_batch_submit_wait.rst": "f9e276c4057656c7c8ab2f594f76b04f9d25c0c1b0beeeaf103fcd86aa43e241", + "docs/source/architecture/execution_lifecycle_engine.rst": "27fb0eb4c639212c7f959ad4bdac87db55395a183163ffce713fe9c41fe58373", + "docs/source/architecture/execution_progress_stream.rst": "777bf4da41ca2c235b63a2d774a94cce1c35a03c3b87b2c501afc082a56f86ef", + "docs/source/architecture/execution_status_poller.rst": "7e801869b0b762325f889b76600eb06fa4eb04f7d80eb8acf773a9ab90308ced", + "docs/source/architecture/execution_wait_policy.rst": "acd5e60a3b294103f2b0b67e3922e49f54fd2015f360ae75ac37252ec1f1d8b3", + "docs/source/architecture/image_acknowledgment_system.rst": "650231482b3e7f38108b37a017612bc1fefa3aefddc5aaf1753d447134cc9341", + "docs/source/architecture/index.rst": "cfad2756cb9b78f0aa51b848181a113964ea547123671d4418f5fd56d2df6e37", + "docs/source/architecture/progress_registry_projection.rst": "98caca592c9f90121f14e4d71b7b756b017346303b8ca7b5d836bd3d7f19567f", + "docs/source/architecture/viewer_state_management.rst": "fe40e1beb8cfbb4c129e8a7bf5a6a2ad3d1e6e48b8df3e787a62bd2738c6c920", + "docs/source/architecture/viewer_streaming_architecture.rst": "3a380ec7fb52129c0013cfc6619c5b8686ae3531a8ab15215de04920923a6c84", + "docs/source/architecture/zmq_execution_system.rst": "6417a400634ed9aeed0f968cea0db98787304f8ab8387148ff77c8afa7f0d629", + "docs/source/conf.py": "e2224f5e41f473e9a9a213dfff036859c0834eee3561a9d6ce5415bc4487d126", + "docs/source/index.rst": "9ecc16d64526fb5799a40befecaaab6a3f55d41c5f901fed5c6a28084734a4a3", + "docs/source/installation.rst": "a3431edfd6ac76cf4b820efbdfd7a534d6e41258fb93c7d78ef290993fac8c40", + "docs/validation/issue10_ack_return_route_followup_20260930.md": "201ae9cb42395b0f774eb8bb56cf43faeb5f21106bb892320058a85874f4321b", + "docs/validation/issue10_journey.txt": "83f34a9f9ab21c1218ea1845908c1c25c705347b546958aa1ae631e1b2c9af06", + "docs/validation/issue10_journey.xml": "616ee69fb92d921ceb097bfaf7f1743b8f3385257b4afe8503e800dd43c8cf1a", + "docs/validation/issue10_native_final.txt": "db5ec543ed1f88465cd5c2d244f66d0e4199054bf65e24b5d566847f86843f24", + "docs/validation/issue10_native_final.xml": "0698e4d64d7eef028c190db21caa989bed789440b7588ce820ca804834c171aa", + "docs/validation/issue10_native_focused.txt": "44b9e7c9feb834f5c3c072184a13c8c2ff8e1cc791f42d60d74c631461212bd7", + "docs/validation/issue10_native_focused.xml": "94d03b8bfa3ee6b9ddebc9c47b6ee5ccc35871acc2a4561e16fe19d0d7593a5a", + "docs/validation/issue10_native_source.txt": "ad612a11edf1b6ebf11e0e0314cddca80566fa85d24b9fe56972ffaaf1f6775a", + "docs/validation/issue10_nra_loop_final.json": "dc6ffc60c762c658ba45db2137f1ae558ce6968cc6f628483fb259f9ff49155a", + "docs/validation/issue10_nra_loop_final.resources": "a2cf28d114cb5681018f5ff1bf36c333680479e3d80cd39a6709b1b996b82b1c", + "docs/validation/issue10_nra_source_20260930.json": "8d7f4f473df884ab1507c183e63268e552cb32f1d12096aa5bf9919c46a5dd67", + "docs/validation/issue10_nra_source_20260930.resources": "be2a0d372a464c2dc9ecf1dfb1aac25c5df38e50cfaf4d20d07a5a6c19c97478", + "docs/validation/issue10_nra_source_final.json": "775676eee04a81a811c04b2cdf74b19b36b9d9c46b813d3609c3009b63745abb", + "docs/validation/issue10_nra_source_final.resources": "5a5755bb6b22bc47592ab49d7c7a19e015510ee92294384636787d90fdd360e0", + "docs/validation/issue10_openhcs_final.txt": "e85a7720cfa71b1b84b6165d937fef22500bbe22b87db120bf76efbcda5d1a19", + "docs/validation/issue10_openhcs_final.xml": "9768040d37aed08c074e9a9b8b3da0ce3b0eef710d0ff34af5620ecd2637a4d2", + "docs/validation/issue10_openhcs_source.txt": "0671a73d20ec35588becac9898e56d16ad2ad28a76dcd94a984e336cc6adc484", + "docs/validation/issue10_openhcs_source.xml": "7da50332d3af51720f57ceae85562d750fd12e65ee62ea4196b4769cdd2433f9", + "docs/validation/issue10_polystore_final.txt": "6732430df17ceb02f4e66b69f507c7ac7cb71911a53cab4b8059175c98011d38", + "docs/validation/issue10_polystore_final.xml": "da2a6460c9a0140a6231fe786b88826cc601f674c032e570e0b5d608d38482fb", + "docs/validation/issue10_polystore_handler_import_failure.txt": "f8def2482b6d9dc99917cc00ed5c5be9b53855e0cd114821433842f229e254e3", + "docs/validation/issue10_polystore_handler_import_failure.xml": "39b00fdfbf4453c19ece38e8bc25fd270e8dd0b6d9f4c5cf5c589161e4fee6ea", + "docs/validation/issue10_ratchet_native.json": "2e8b7069023283406e8f9a66be26482eeed155c64a99dddf2d99785fcb5a1c9b", + "docs/validation/issue10_ratchet_native_final.json": "926801db2596332cc51cc84873d15bb729d57cc328a2717ae9f62013b2811352", + "docs/validation/issue10_ratchet_openhcs.json": "b4d1d3ba15de5b124227a52ccbfc9b5078ba27c7dc522fc6c2c74a32a9c72b7b", + "docs/validation/issue10_ratchet_openhcs_final.json": "4f1cfb30e7c16f4bb14758a29257164499c38f7f7264949ce4f13c0d7128e714", + "docs/validation/issue10_ratchet_polystore.json": "8cfbfc52f4caf1d169ef89007826a5f455492bd21ee795d7de5650041c71454b", + "docs/validation/issue10_ratchet_polystore_final.json": "243c642d60b78563c0d5e88f13ca3dc7dd41f82198d7105edede2977346fbf7e", + "docs/validation/issue10_startup_diagnostic.txt": "88d2d47c1b3c572a459808fd3f65f03c8d7b6e95b196fbf2ded75f8ce044564a", + "docs/validation/issue243_progress_annotation_20260929.md": "3fca37d4eed0f9e6e61013b4ead34790cf2720bbbb22ab859e26a7fc7c8ae956", + "docs/validation/issue243_progress_annotation_20260929/after-pytest.txt": "e98090351cae140807dcadf5fa326c1b48aaa9cb2e6e4e69edd31a60e476a807", + "docs/validation/issue243_progress_annotation_20260929/after-resources.txt": "26b7455faf39aff8a67d46c704f786f6cc4d5a44178add263ef9c84eda2ee95c", + "docs/validation/issue243_progress_annotation_20260929/before-bootstrap-pytest.txt": "8d68629c63d6da0ccbf8fe589eb0270d0c458ff20d3832c30ca4300f8eac010a", + "docs/validation/issue243_progress_annotation_20260929/before-bootstrap-resources.txt": "af1d21b52a918978e9674dfcfa0fc8efd0bfbcae49230a94b2a68bad846a94fd", + "docs/validation/issue243_progress_annotation_20260929/before-pytest.txt": "7307af3e5c62a2254ebf0f80e9219659834d7fb2f1d586f19f62255b0d5b5897", + "docs/validation/issue243_progress_annotation_20260929/before-resources.txt": "6db4de7dfe0424476b54d332fbdcd40f210f8f034bcaa69aa1d9c83a1504e32f", + "docs/validation/issue251_bootstrap_20260930.md": "4870894202f12f769efa03d22e4f12b9641e5ce87f2185f5a5364ef3d9825fb7", + "docs/validation/issue251_owner_factoring_20260930.md": "1aad3ec56b7994b95151c8c5ce4e284a03810b052d40edf10da0fcd6b207b2e4", + "docs/validation/issue251_owner_factoring_ratchet_20260930.json": "f3a7851e79b53234a593912e43efada908eb020fdbde6263a609e3a670a4c3d2", + "docs/validation/issue251_owner_factoring_resources_20260930.txt": "80d8faf518c6fe67c33ef071da2aaf4305d52c607d71886603efe3e1f40ee42f", + "docs/validation/issue251_pr_body_20260930.md": "fe06804512d647d7e92e66d63e55a54d1edd1a23c4ff9ea19210618b15a21913", + "docs/validation/issue251_reserved_child_ratchet_20260930.json": "2900dd5ff2046d8a6b47ab2d53c924946eb2bfaf26ff02cd8879a2be95383126", + "docs/validation/issue251_reserved_child_ratchet_resources_20260930.txt": "c6f11a8e92ed8252bca51c49813d40edc5c23c31e762d40e482ec72bb3711199", + "docs/validation/issue251_reserved_child_takeover_20260930.rst": "a55e9498a5dfb44254c3fb2d6811a882cc21ce96e72bc898b4b9cb2549cc9fc9", + "docs/validation/issue251_viewer_main_ratchet_20260930.json": "e168caa9b16ffd15a533ec5da0600d7b56b0f1117d2ae06ed5906d91343fd463", + "docs/validation/issue251_viewer_main_ratchet_resources_20260930.txt": "6d3e00434a29cedc1d4646f0d867c5d04d185f6e15a6c6f95858fb029b6341c6", + "docs/validation/issue355-evidence/dep-r0-rejected-806faa1.json.gz": "6a84c60aefc099cb05b86c29e93a4a75d201fc0759a086f23ed47707b9e26d09", + "docs/validation/issue355-evidence/dep-r0-rejected-806faa1.resources.txt": "da041805e258c61f5eedac2060ae2e6bfd234002cc78271b99846df81c4b9fd9", + "docs/validation/issue355-evidence/dep-r0.json.gz": "f8ab21863a79683d50416dc3b3e8f92fb9c979cd617e3966acae38648e1f8695", + "docs/validation/issue355-evidence/dep-r0.resources.txt": "b05ed2bcaf17ef6ca654c7b1221b8952f041806bd0b2e10ad459aa6fe92c1784", + "docs/validation/issue355-evidence/nra-local.json.gz": "8e76415ff2fedf981a01e2abeb9043b8bb231f260d38aa4ba0a896baed8a54d3", + "docs/validation/issue355-evidence/nra-local.resources.txt": "9329e39c1ff375fe1d650517412081b97a446d48b5f1e00dc63a34c7bba5d65a", + "docs/validation/issue355-evidence/startup-checkpoint.log": "836cbba2d26f0df6e09768d665e13c11f92468e5325c4f3fb36473b46e26376a", + "docs/validation/issue385-evidence/SHA256SUMS": "8a0d7b90dacce001f9704c669f1bf9d761898d8744fb612c51ce89eb429cf61a", + "docs/validation/issue385-evidence/viewer-owner-after.log": "a5c400de7c336e4c301d53e793c8de0102d9de41da5b7297c0a95f851b1bed03", + "docs/validation/issue385-evidence/viewer-owner-before.log": "fc1b12f8887694c419c99f3e97546a3ac74e26c71a3fc868125a43a557e92b3c", + "docs/validation/issue385-evidence/viewer-owner-r0.json": "f89a93d9a41729f7756749d30a9cb73f27ae013f8fcde037e5d553f87f1c7878", + "docs/validation/issue385-evidence/viewer-owner-r0.resources.txt": "1658475b38e73d7f4dac6f77d641b45b38f14fda1f41ce5b0ce1c058d8445cf8", + "docs/validation/managed-viewer-385.rst": "ff7219e3b4879fcd430d2241016293a8492aae8ea751d50ceb756e56f01bf929", + "docs/validation/openhcs355-cold-start.rst": "844f2e5836f5abe514efc69a4bdaa979def4e8fd84e7c15bbd5b02a1ee5cdfb0", + "docs/validation/startup-feedback-358.rst": "50e894dd18dae9fab0d5dc580f584d73032ec58043d92556412346eea68dd463", + "paper.bib": "cf1e534b04aaae97ffdf926efe9aeab42a6f76a7adf63553c0bf74e108837c8f", + "paper.md": "cffb0012fad980e7cd9f98bbc0275b620ee2c224ca7935c28a1f1c520ec41728", + "pyproject.toml": "e2b56ba5b94418c99ee04142edf0fc4f14a06860fbecad7170d4a2e1e4be70c5", + "scripts/release.py": "109327ab88e002e4fdd56e6a50a8b5e265fda3723fb3c0ccc184c9d1b0539c2e", + "scripts/update_and_release.py": "80896e49f856d6a193bb1dc3917f55d2878acf1476c8240333eda16b92e8e61a", + "scripts/update_version.py": "d70feec0d50ca0a8d90f0105be3e85bf5a5b17a7bb0ca63a6178ad443f0ad60f", + "scripts/verify_release_ready.py": "e8190c4f79b1fae85af698b704b339564e77090f8adb7393f0079cf0d13bd844", + "src/zmqruntime/__init__.py": "37f3e14f58b4c1dda3d338a3a2fb075aefea215f6f25b69f44091891341755ef", + "src/zmqruntime/ack_listener.py": "da5aa8d1031f971c2621071a6da40b41f10dedf12839060db13d10153050cd6d", + "src/zmqruntime/client.py": "00757150b06b837b918153bc3c2752dbdba396569ebb4f4ed91cfbff7c23d25d", + "src/zmqruntime/config.py": "79840f3b72593042b6a56e3a703a1064e0d1faa19b12446d99e0903af494f2a3", + "src/zmqruntime/execution/__init__.py": "7a5d9f1636946d5fe6edcaaef181e8740e17d5b348d81e04b50a9fccf6fb16f9", + "src/zmqruntime/execution/batch_submit_wait.py": "c447b2ccbc372a5336f5a3b32844b896dc5d58566cb3de31640ae3be2379edee", + "src/zmqruntime/execution/client.py": "1b9453ea2be540b29849770cc3fe82f284f501e0e140797dd48c2c257ec36f12", + "src/zmqruntime/execution/lifecycle.py": "23596c31b9efe812f1ab66b4300ee1bb19125ea9bef6e51ddcd8acaafb0f4ed6", + "src/zmqruntime/execution/logs.py": "c7d1816835620a2b3e82a889bd36f2a97b80aad7c0f639a07c5c9d426c6ae803", + "src/zmqruntime/execution/progress_stream.py": "13b39fb4d256cd835302f7a8949e9e56bfe0b045e3e6fc1d197ce8ae40bc57a4", + "src/zmqruntime/execution/responses.py": "43ebbaf9451c34a5cb5a0c3182cb4de4c3745e13db8482ba1373becbfc8a2a03", + "src/zmqruntime/execution/server.py": "13663ba20e62326171ff8b43c2474419940729e90b2c0b25b04ea3514734d599", + "src/zmqruntime/execution/status_poller.py": "da0c7c304f293ba4f52aaefc4c722442b5a2859d1fcb806e8fccdcd3b4f6cdc6", + "src/zmqruntime/execution/wait_policy.py": "df4a9cad5a2fb74aa0c030def22dd8cc5b851983c3f04c26d479b607075ef922", + "src/zmqruntime/messages.py": "76018d6f6ac6795e076eabed9c6dd018b8c2fb9640e194a19086a013c0a50785", + "src/zmqruntime/progress/__init__.py": "1767a50989e4a19e4ae8a7ed4343b6be564740236cdcb4c5c56c06f55c21f68f", + "src/zmqruntime/progress/projection.py": "72b22f765dabbcf6983c619c8cc5404bc52518186ef72d85a6f6c6ab65cb426f", + "src/zmqruntime/progress/registry.py": "2943b28d1490688bddcba914db5aadd445cc8e6c9b6381230f0451366e98a0c2", + "src/zmqruntime/queue_tracker.py": "b2e380a93699f85e608d1ae7c03b5a20ee62d8beb82cc93272b050084156610f", + "src/zmqruntime/runner.py": "9f52b69f23b4626adb4e1394e0ed476624d2a38d9cd2c8ec656ae3b2e6816df9", + "src/zmqruntime/server.py": "a38ed80dfbbf9d738f4a96b4bcff8ca667f592b84413c33731550513dcc924d0", + "src/zmqruntime/shutdown.py": "67acebb3ac7a2c419320005931f0de44e28f5ab0b393e6bfbdc3f11207a2073f", + "src/zmqruntime/startup.py": "55118bc44633926434f0e0b057c167dc2948f2a632a902b5bdb60dcb92731d69", + "src/zmqruntime/streaming/__init__.py": "911cac6c1f747d77ec6614dd0961ebb799a7dbaa276e4259e1f38087e3b7320b", + "src/zmqruntime/streaming/process_manager.py": "8229c322c309969f89e2a51a3e416ea38a4990248776844dbcbb01ad9796b3e5", + "src/zmqruntime/streaming/server.py": "6a587842676bdd2f414d8df8f277e5e671a5f41a7b3c4615bf1ea2a5da182834", + "src/zmqruntime/subscription.py": "4a393bd94d8a3611ff7d7423ec4ea681df6f26cf906a77e2682c76cc0e762696", + "src/zmqruntime/timeouts.py": "bb5121a03070f0f2a0ed76170a2324512ed4a4d64536ecc7ba8bdc6a4b8961d0", + "src/zmqruntime/transport.py": "e486a4215d4b977553030e897589bccac637dfe4e9abb28cfb7594139b2196c2", + "src/zmqruntime/transport_modes.py": "12bec1c13d87bb8f05b049dc76d3cb7c130414c9e69d6220228ceeb0087f9ad8", + "src/zmqruntime/viewer_protocol.py": "5580efffddca2f723b11a652f482fbdb52ebae657620fad95217b313997b9fc9", + "src/zmqruntime/viewer_state.py": "f3dd0b35c3c75b0537bf8e50624b8f05a6dce02b40f1700a878189c3312ae30c", + "tests/diagnostics/check_ack_startup_failure.py": "08856fa0ca60e4b00c8577ce2ed3bb82e6e3fbbe16eb2876b69a03500ff130ad", + "tests/test_ack_listener.py": "a616052e042aa145d4eb2b9bca6b153633662bbd54588038730c9d8a2551f70d", + "tests/test_ack_return_route.py": "4519ccf21b0d6bc892d43405541308326a8a7ae885e0ec8942e3596eda3078bd", + "tests/test_ci_action_pinning.py": "a636dd4d70e231d06c5de2802afc89c389f678b3b49a40ce8463eac5b0c308dd", + "tests/test_cold_start_activity.py": "3e0486f8e520e3bb2a767f1aca49df0ffc269476cea0f29594cb08bfce1d7896", + "tests/test_config.py": "f9a16ae6cdb8c9d1dce74bcbc95ff59e853245b219ce848d8aca9704eadfb95a", + "tests/test_endpoint_ownership.py": "e37ddca59beb48b4c1ccca4d1feee1793728cfc54b2aef69870e120bf17098e5", + "tests/test_execution.py": "7b547a68e912b012144519216097bde868264fcf7bb0ad20b3223862701bea0c", + "tests/test_execution_logs.py": "3136e1cf250b02d89e9da9be06b90ecab59fe34ba58e2e22145fd1b0e9fe2a90", + "tests/test_messages.py": "8223e0a5b461e7dd3fc6392c9f652cd74180c8de1b07fef9d28305ffffb2f229", + "tests/test_owned_close.py": "92c3149704b88278ce6771c0c2c064aa897948bd7303b8100f24f99e97d9ac84", + "tests/test_owned_startup.py": "95d3997eaf5d627925108b85dbbe5937abe448c666f26caa43f2bad5586bf73a", + "tests/test_process_manager.py": "b21d1eedd0f98549a7b0c235cca43fbea35afb3c041df81b362d94f3fde9439d", + "tests/test_progress_annotation.py": "27b237877b660d6699402a091dc7843201a4fc0636e4b9f0fc1e25d16cddee75", + "tests/test_progress_projection.py": "e56b49ba046b7c459cee386076201b252d3c831a3d8eca535eafbe0ff6affced", + "tests/test_progress_registry.py": "bf80de2da039272700a366884e5aee4163f04b156fe5c8f58912d4c7f42e7ef4", + "tests/test_progress_stream.py": "27d056146596e7e7c4f2a15ae7e7f7e01e9b4882f3258fa48108d799ecb19698", + "tests/test_queue_tracker.py": "85257cf345a02532441f188242134a2fcb4b60f793eead2f21a6bda360529a29", + "tests/test_shutdown.py": "ffff454475abed18dc520b8629a2799d5a30d0e83abd0292c5acb916d3e63eee", + "tests/test_startup.py": "3e5441886d22921b255de1016bedefd74e87e57f7099bc9e72f8021d1b115148", + "tests/test_startup_callback_scope.py": "06c9dfe205fef9aa293ca0a5dfbaaa8d5083da02fb7c2e06bc9895dea607760b", + "tests/test_timeouts.py": "8c4c95ce4c2d02d5210ef4ccfd4d0cbd1850535c8d5793b87380e995c126babb", + "tests/test_transport.py": "02072b46ca87c082eeedccb02f4b85a1ba02bc51a4c24ebfc6930a6b8b2a21f9", + "tests/test_viewer_process_ownership.py": "972bf0988a9b3b49371ddbd8e1ba7ce965c9fa9a37f04ece70fa93905335b348", + "tests/test_viewer_protocol.py": "26adaa73cc3a39cefc4c797880fb5b2e52082adaa980e479e318fa3805e7fe28", + "tests/test_viewer_state.py": "2f7b0dabbed227db35fbac5321f85b84352aafe19e33c879a50b3aee0fc9d8ea" + } + }, + "external/pycodify": { + "head": "792b03413331fdf107e369c924c257a2f0b16126", + "status": "", + "files": { + ".github/workflows/ci.yml": "7cdaf326512e98ce07256301a152b286d2c06492d67e09d6162d1312c95dd203", + ".github/workflows/publish.yml": "e10379aa724dff1ecf13fdfc3baaf32cb33de77fa65eaf8c9af270d3b3a3dbaa", + ".gitignore": "2c9d25459eec48f9d654932218ffab8dddc041060191c98a67b6505bb9726a00", + "CONTRIBUTING.md": "f39c2677fef7b7243f37e3e95e35a09e118dd1fe30b1f43a25ed119b6064ae69", + "LICENSE": "41a2e56fd632fc59805cecefbd30011033d0e67fccddc93529a1a6cff03aa766", + "README.md": "f32db990f5e1feb01ee3d7adbe1195fd691c8964acd789759901d00170cecf7e", + "docs/Makefile": "43df277c1f15a11e9ab7180cfaa9e65e014571beec43b19530a363f4e62e0cd9", + "docs/api.rst": "f613bec5644911b1d5fc6d6875ff9a843b49526a5b2e00a22488cf825a3ddd05", + "docs/architecture.rst": "dba4502673b43a48f775827acb5dc6a3c75a88836ab59ec5fc0e7dfd722d4b51", + "docs/conf.py": "3cacb5b7a11daa491ff739fe6df58494ed38e50fde40d6bd6fb7c9b4d4eb782c", + "docs/index.rst": "d20074f7b6d7d9d205d453f9fef04a3fc7120b943c6c098664dbf9376bbbdcfe", + "docs/usage.rst": "40677c937662fde6d2d96399b63c83424bc80756036df4c2f6f34c541202e606", + "paper.bib": "ba515e9b812130cc2da5991c37921c93d947808909953fc5c9949202e54507b4", + "paper.md": "c52498a740b040def7feafdd6d1aa4253515d6228e5cc534c00a417998d65f8b", + "pyproject.toml": "1103178d6661d94d66f6b43039d0961557e6d07861e46bbf8df18b6d40a0b1b5", + "scripts/release.py": "9027086b71a742b688bc984dd2fe50c4af2ad6e5ba1b1c564cf531a414e19f62", + "scripts/update_and_release.py": "80896e49f856d6a193bb1dc3917f55d2878acf1476c8240333eda16b92e8e61a", + "scripts/update_version.py": "f93a6a1ab4aa714f699edab98d36d3f610c7b7e14ff5748a22fc656214958d8d", + "scripts/verify_release_ready.py": "aa51d925335037158e0d34d0b198039e4d3833df564f01622ae4005bc7e9d6eb", + "src/pycodify/__init__.py": "b839bc2a7cd2afdfd8756eb39f22b791cb4f7aa55c0fc9c11099b7219c9c663b", + "src/pycodify/core.py": "b32dea495ceb8745c1b363f2e42aa62eaa28a1d54198a5d6541e0b1546facfb4", + "src/pycodify/formatters.py": "08791a7f3cb779889ef24a5bfb395a1acfb4d3320fe9a7cf037986c98a9d7faa", + "src/pycodify/imports.py": "17fc080d60ef168a9c211f27111b04da1d527d2bf87e2188c674e4de9d25bef1", + "tests/__init__.py": "efd53630f4e3c520366b8aa444fe2d4d33c07c7caa0e3841fbb43a04cfdd9183", + "tests/test_core.py": "164dd47f93e4adfd8fe9de851f5db74744509179f6eaaae877be879f22689e66", + "tests/test_imports.py": "ce63bc44d8fc24a02e3439a7b1504b4dacf21e64ac51f1581e60f0099664c3bb" + } + }, + "external/PolyStore": { + "head": "84f322e46871de5ed47e7fd20976ad03e533c1c4", + "status": "", + "files": { + ".github/badges/coverage.svg": "e6e5c18d37513ef246d24694ae7e124f83597ef6e839baaa8269408f6be4690d", + ".github/dependabot.yml": "34790e08d06d30f3f06cf2f071fcb2430df398c0a70bf1d99b5cca71d69080ef", + ".github/workflows/coverage-pages.yml": "1b0c45ae4b4bbd8a38c9208c9f2f6d90faee1545bcec090b776403be9c33b470", + ".github/workflows/docs.yml": "0753d09dd18b885655926115317a45200099f8b024f3df29841f92dae248a2e2", + ".github/workflows/publish.yml": "b1e8d3648e3f38a894c8fa2d98ad2842b388c5effff69a91cd53aeb9f53781ca", + ".github/workflows/smoke-test.yml": "cec1eeec266d5e67c440709ecf5efbfcd263a75046d7e4d9e99acffe057da8e7", + ".github/workflows/tests.yml": "26cf33ecbe48e0bfffdebb2834b3f31f705cbb7293a4d864cb430ffee8f75cbe", + ".gitignore": "4edac7cffd81b322d4edc9422eb4b4574b0227939c52524b95004033891828cc", + ".readthedocs.yaml": "4d16c3881aedd586c6b7f3febd7a0ccbb2df964eac8ff17748acce0745a194c2", + ".zgroup": "2383746e67b4bcc2762b3f100f06c3fa2d5f149ab5a8e5da5d33521464a01959", + "LICENSE": "63c1c82941031bd46dc233be9b616b8e9510f5e30ae57f16a581613e7378d953", + "README.md": "c054ab7a02e743a089ea7e258444ca2982318b86af27457877cc60156a3831cf", + "docs/Makefile": "eb696db665096bf6d05567dadd0213f3ac84275b621909c9014d12d01048e73c", + "docs/archive/README.md": "56692f0cd4664b0cb34e9475a30e9c73e1de1e8f88d22edb4fb00f32593e33ca", + "docs/archive/TEST_PLAN.md": "6b840ad8555985dc78b7984ae7ebd35547da6d051558a8244269551c6072a44f", + "docs/archive/TEST_PLAN_DISK_MEMORY.md": "41619cf02d71f16149b53eb5bdbe6834fb84e69e90e154ab2f070f5c2f8f9d86", + "docs/plans/native-imagej-point-roi-20260929.md": "b7943227c7be98d2315c01b898323fbafcbf392c61239df18066767045c41a68", + "docs/roi_region_properties_checkpoint_20260929.md": "6cfd26c9550315c63dd3ac41c597ad5eb3a7cb942c3c308d97d59d10a7fc8aae", + "docs/source/_static/Main_menu.png": "dbff6948a2354eac88ed6d883ae1d9b2dc2bbc39cbfa8a8a7b21ffe7ed9fba58", + "docs/source/_static/ezstitcher_logo.png": "6e2fdd7f872fa57e595ecbd296a56ea5fcb58923863df4b5852e5c72da8a9438", + "docs/source/_static/function_pattern.png": "c6ddd31d6fefa6f398a942beffb4648a30fd4d403e4000c3579cacd27d498256", + "docs/source/_static/generate_plate_tut.png": "9fe5351407df65d9a7dc66743a887a49e006cd7919c4790426529b96d6151e28", + "docs/source/_static/image_browser.png": "d19a043b5947af2af09abef3f36581ccb4e42e388cad8c24c6dde6a5fdb950ff", + "docs/source/_static/metadata_viewer.png": "abbc92272b036d406e0aed104d1eb44695af872f4e59c5cc964b64e6c5a28f5e", + "docs/source/_static/pipeline_editor.png": "b8c9a96f3613d6c46aa1d9f28446cd57d3edab2e658dc1d631d9f4208378b865", + "docs/source/_static/plate_viewer.png": "43d934e7136dce72e587639cc55336dd3f5c4f31d966d5b8e0d68e19b9fcbba7", + "docs/source/_static/step_settings.png": "9fcdb0e446de8dac2943ee29b7044d1d9def4570c2786c043de065931a767b6e", + "docs/source/api/atomic.rst": "1d82a7883d5cd5954d4ef7680a7e736419cf09dcd454575e4b3ce03a365dfea2", + "docs/source/api/backends.rst": "fe8f91f6c630146977e00d31c2f16be1225bf9fbc6563c80a6bc52a7d3ba5e8c", + "docs/source/api/exceptions.rst": "3419b20eee89d7f9fae9d9064afb4151e6b524d48da65d0f6de4a92f66aa5ebf", + "docs/source/api/filemanager.rst": "ffbd8b43975becb7c5913149c0e8cb80cc89cfc3579816b9eff7b0ee1fb2ac75", + "docs/source/api/imagej_runtime.rst": "ee69fe61cf24c7cbe24a6c0a45f5b2f30b3db685a41f6e4ca4ffb1723ba578c9", + "docs/source/api/index.rst": "23a2dfcbc3abba4e9f2fc7fc8b12ddbd1395f2873f87c651167df7185097de74", + "docs/source/api/registry.rst": "6e96ef632a2144de51adaba15ef51b32884e36ca1c09087eb8d70b59706f4a19", + "docs/source/architecture/file_format_system.rst": "97e6ff244a875b68ffd93a1429b1a66ca5754489cd2b3be67da9e1a5e4f15c1f", + "docs/source/architecture/index.rst": "b67a0219b9e16b05561233bf8a6c9d25edc62ba3f30cda7d96fbee85d2de1dab", + "docs/source/architecture/source_and_virtual_workspace.rst": "8510f954c1de38f7330b3c62448c350ad99cbeea0f0f999adcc0dc7abc65704e", + "docs/source/architecture/streaming_receiver_projection.rst": "51049541a05db0ab130468c08e0f244cf7f181c5b4cf5a17777508be797d5a42", + "docs/source/conf.py": "7cb4e271ad57f025b60ede742e8df94a095dea71e32aa44cc7527180d8d90bb7", + "docs/source/guides/custom_backends.rst": "76b85ead72c2165c0d4e578e11a83a5c65bc3d1340cf17693a0f3a7a5c3d9ee6", + "docs/source/guides/omero_backend.rst": "77a8a6b816597de6c13633f56cbc3f797976f42799b61d574bc60181b74da1d3", + "docs/source/index.rst": "e179fa4a9bfacf5bf50754cf78d66d6e4f0f60de61f84020e65f1e7ce592e55d", + "docs/source/input_preparation_installed_20261001.rst": "2c62ed3d3d85e37fcb974a38eb511cdcccfc13deabe014dea4c7da18b5a53eee", + "docs/source/input_preparation_parent_20261001.rst": "f30ffbde998099815bb1da39bab10b1c59963db43fea8777959cd9e7d4b0c903", + "docs/source/installation.rst": "f0dc946cd61f386b3fa70d767d4a8633f153726c3771a3635214a0f6e1e2413b", + "docs/source/metadata_namespace_327.rst": "73a7bc504da48035419cc09904c139ce2604c6037fbec2179a5c47687510b909", + "docs/source/quickstart.rst": "321494c996433752be2d5a2bf1659469226a69abf71dca591b871869e7d0e374", + "paper.bib": "3f6f21182c566ad8b4124604dbdd39197f92303af864e6f6e45bedb2e0ca7e32", + "paper.md": "bba1edb7a23c365db162f99944e03675246ed6e2503ffab90936a3d8f576b689", + "pyproject.toml": "2f3edfdb1307f3300e3db056b2828814017270a9726f4d7bdac52caf84f96f8c", + "scripts/release.py": "25ef09845453b73a29ea84c303c6c77a79f291775bdba97347f296f35e8629d1", + "scripts/update_and_release.py": "80896e49f856d6a193bb1dc3917f55d2878acf1476c8240333eda16b92e8e61a", + "scripts/update_version.py": "e96bc7111806eb9a15b5d739329a6a41730fc0591e31f7975e52b17e67e1f721", + "scripts/verify_release_ready.py": "1c32aae8b7ab774eb0fb99d0a51ce6535ed7ee5020f44ca9dc8f6d3ae50af01a", + "src/polystore/__init__.py": "15dabedec6acd92b025d4a0b4e8151227a4496e8b7d5e87f28713f7799919b5a", + "src/polystore/array_payload.py": "3eb7e2cf8eb01a2b10b860778a8fd4ea47e7557fdbe28ab8adf31045088e145e", + "src/polystore/async_init.py": "21d9b8af54ff21247a2012d1ae759550ae0147cf75f667a73b4a5a8387bf3d0f", + "src/polystore/atomic.py": "5e412948fb919ce27f09971b0a5fdf0851499812e4c0ae8bd456abbd8ca86b90", + "src/polystore/backend_registry.py": "a4c4e73a79aa4363301f76727b35db2c8b55fa14107f8866a05f74da4fefb64c", + "src/polystore/base.py": "ae641affae21b61448816a14bd68b7f2f3fc0082f0f1fbe51079ed32520450b1", + "src/polystore/bioformats_java.py": "e7ee3fc888dfeebaab48681ac3e9dd2463cca693a0ff0d77ce274c72135666ff", + "src/polystore/bioformats_storage.py": "0f57d0b35619de4aa6fdad0839ae689ae6f91b0be099fd0b28742c28795f3b71", + "src/polystore/config.py": "62c8acad3da3abed8ccf7f1166fc6a0d094be1c3e842cec6446780541df292a0", + "src/polystore/constants.py": "246da078ce8a3aae6d1fdb76183f1ff724795014cbca4d670b80174f74084635", + "src/polystore/disk.py": "cf089b8c79f86099a7cea1b6cbe43ceaec6331196a44b43183f2e64b7746c219", + "src/polystore/exceptions.py": "0ecbd94af34ae3d1a37eab29e1f72be3e68c651c9a93bf52264a783a8fc65ab3", + "src/polystore/fiji_stream.py": "62a60a36f1da5668f60bc0b4e3a5d0e65008042b2361787f4909224dd9b51db9", + "src/polystore/filemanager.py": "877a2b10731b12904b1784a5b42c9e39688e3a84f7f86018c1c2beee96ea2296", + "src/polystore/formats.py": "6f7ec984549b45a31bb32b9051672e996a67d9caab3ce2030ddc7d50e17101c5", + "src/polystore/imagej_distribution.py": "29000b7f7d8067a8a1667fc8ee603d3c2f33fd87f0a318a21cf0093473df49b4", + "src/polystore/imagej_runtime.py": "150983b2da981b31f974ad384a0fbadf5804003fd59c085993701b876384276a", + "src/polystore/memory.py": "4ac155187a80c5b6f096b2170d6851e6ce119938222beef4bd99440cbccba9e8", + "src/polystore/metadata_migration.py": "4390dc79fd1f9dd3fa405b961ea15573037bc19c6db2b31b36a5bcb7170abc5e", + "src/polystore/metadata_writer.py": "987b8ff3cfb45b170656fb7dd405abc68c460381871ca26cc26cf82e0550e256", + "src/polystore/napari_stream.py": "29286154e37d7eeb2c75d9a48cd12fa696f40c02d5ac35865360b7673801f905", + "src/polystore/ome_zarr_metadata.py": "ed0e4a3de24a6f590404d98578e19b76c9c76b27e854639e68b521f49924fbbc", + "src/polystore/ome_zarr_storage.py": "005bdd6ce615ff115050e1853aab0c56c50c65d1361c31ef6219bb0d6c4852b7", + "src/polystore/omero_address.py": "8a3ae8789fceba0f099eef2ee983d858a8f83b764f19b70dfa7bb88f521c0c92", + "src/polystore/omero_local.py": "35d39564317510234c2a3ded00bb06a09417d1b6f7359e52e74c7bd0a086f642", + "src/polystore/omero_tables.py": "910aaa6bea75f40bae82df71dd414415278b1387b80c7f1bc11e8d681874451e", + "src/polystore/omero_text.py": "9f51daef3d96cf191994d8a9c7aacf6182941ec2b0ada3f5ba61e0cc4f9412f1", + "src/polystore/roi.py": "fa945e9a3f7272e72f3ea022c7a3ae6cd30520ed7924591dd3f3cad5d0e71fc0", + "src/polystore/roi_converters.py": "50c37e5b070db7cbe418a5a64576595ee3ea7e5bbcf014492f38958f4debbf07", + "src/polystore/source_tile_geometry.py": "ebe4a422ec76972f2318ba56910ba6ccaef28734764ed3b88a3ba478ed69d322", + "src/polystore/streaming/__init__.py": "e401faf53b6fb9a08e237535313e5b99d7e371372875182b76132921233e5adc", + "src/polystore/streaming/_streaming_backend.py": "7caf2252677a894a5a761b60c473b92184b83745608c2b50a75eb1733c77cd10", + "src/polystore/streaming/base.py": "353e87dc92ad8df2ccec0136ab8ef7de7729896522cf8b16c0ec79bde455c176", + "src/polystore/streaming/handlers/__init__.py": "78daf5078f1914dc5b646ebeeb79bea336036b3b4737e122865be41ab7b24f03", + "src/polystore/streaming/handlers/fiji_images.py": "b5f06390cfeaef6c6a10c06bf9af00eab29f90ce1bb2899794d2e516cf86c7d0", + "src/polystore/streaming/handlers/fiji_rois.py": "5edcdc8d7344c5793730beb5a1c3baea89e96b13e62b746cc1cbeded3217a978", + "src/polystore/streaming/identity.py": "a8e48d76c8fd222515121e2ebc879dccc820e0ebf5b576a8728c1a7ffd35dc4e", + "src/polystore/streaming/receivers/__init__.py": "07953a0ecae9f307b9a2706062c1f452648267887e8cd03fbdb87d4b301b4877", + "src/polystore/streaming/receivers/batching/__init__.py": "c045df607fc2c07983659caff8b191660dd2ce5e73aeceb89894be3a457926ec", + "src/polystore/streaming/receivers/core/__init__.py": "b61b9545e4e373556d5beb87a23c3f6475238361d0c3a4cf18a3a5e197dedcba", + "src/polystore/streaming/receivers/core/batch_engine.py": "36d1dd9a7a2beae134c6f149ca148dd4cc2921fa2feb37cbcb88c42312743055", + "src/polystore/streaming/receivers/core/contracts.py": "c89f3f2dfb3e23482112a6b98ae3238d1768b2f4a01b4b2d605b698bd307f561", + "src/polystore/streaming/receivers/core/image_presentation.py": "dbe1395afce5a280fc1ab0c66bf302e324577ff15c6dff7a1698f50f1fc72a73", + "src/polystore/streaming/receivers/core/layer_inspection.py": "e93f707de62516eb0d48d9fdb0f71862b4265389723ca92a05145fce99a28802", + "src/polystore/streaming/receivers/core/metadata_presentation.py": "5e021ff3659039856616a75b4e19918b709121ee4b8902d39430f110b1adc5e8", + "src/polystore/streaming/receivers/core/viewport_presentation.py": "936378683122ad28deba10d71e9561abfc904017582e345316bf1c760d2abfb0", + "src/polystore/streaming/receivers/core/window_projection.py": "e95d0ccda66aa866082c5afc5bf9908259c727ca33270d3f069384651e1783e3", + "src/polystore/streaming/receivers/fiji/__init__.py": "a86e999752d8212da5bd58f1a3db43ffa7ce867fb0ae1209bf0f148bfe5b4b50", + "src/polystore/streaming/receivers/fiji/fiji_batch_processor.py": "165919f2e36c37e221bdd6f17e4398795745a95da9ddd7bba0ab93d74b9bdab2", + "src/polystore/streaming/receivers/napari/__init__.py": "ab4ba3ba76e98365e67abf6f9d79c0be098a774bf9e17e8523fc430a0babb9f1", + "src/polystore/streaming/receivers/napari/image_presentation.py": "1abb2d4c33ea073deb415cf9a242baa64d0b9d73985b7920d72508f2a5998a8e", + "src/polystore/streaming/receivers/napari/layer_inspection.py": "6bb86202480b5aad55d6641e3a6891105c5284d4408ff1cb7f8cbb36929888cc", + "src/polystore/streaming/receivers/napari/layer_key.py": "650eba665a58130fd67c38b164f97f677d805e07e53c2c7f367f850ae6db4a8f", + "src/polystore/streaming/receivers/napari/napari_batch_processor.py": "c3ed3f9fb4d89f82cc887a4d7775db911c96fc7e67d437cdfe8c4b78e62a16e3", + "src/polystore/streaming/receivers/napari/viewport_presentation.py": "aef743171c8d27ac56b53217f8fb2352584d447b33791ee2ce3e1c8fa4ade356", + "src/polystore/streaming/viewer_transport.py": "3b883e3078ded6b8e9c80e135a2eab876f9399fb7813dcd1dc8dd8f6049a3537", + "src/polystore/streaming_constants.py": "645e1685a1cf23167b2f6f06d4807c76444c339fbde66f3b12de9bba3adbe170", + "src/polystore/tiff_header.py": "714c6ddd0ff3928df37b2e65775c2987c285538b2375ee17254ae0dee868fa6b", + "src/polystore/utils.py": "1dd12cb9742f58f9537f1e23832f44f90deaf4332de8ae9b97e8df711ed261c7", + "src/polystore/virtual_workspace.py": "b19fcda85369d812e70bfc1a0efc5d8861ae256f69e94372e2e9515c591d36af", + "src/polystore/zarr.py": "b9404235a3a7882dd6f64383c11aeb6073c8f3a6485bec74264ad6434a1ee35f", + "src/polystore/zarr_batch.py": "8ed86ac525b561e6557a8ac55c6cb0d3954311a31d3ae65ea84af196246d60d9", + "src/polystore/zmq_config.py": "14123ce6fe232144f8a4fa086cad164a0b29e3b014ab809810d622e39ac92854", + "tests/conftest.py": "5ca35c45b774ffda10030f950823eedb160628aad1076b805e401e277bf624f4", + "tests/constraints/zarr-minimum.txt": "ddc0b24cd684f9742b7ecdbc0939072ca89dbf147c4e238268140e4678bb37a7", + "tests/imagej_cache_process_fixture.py": "bf04cebf8be7fb4e911ec1df75cc3e4fc311745981975620b2946b308c461d93", + "tests/integration/test_imagej_runtime_live.py": "bc1c16a755e12682b5b94b81b902068fb4a2e4b8f8b708a43c814b28ecd78bf5", + "tests/metadata_namespace_worker.py": "5db68ec70ba017d1b81cad2302788dbcf0a1cce5be019358259d3aec5ffd7ef5", + "tests/test_array_payload.py": "95a02bc11cd21f57da986ab8f90196a7343c70513d034e69dec581c413ee802c", + "tests/test_atomic_lock.py": "0ee06b9b53964df6777f72cd0ddf0faaa63d9316ec7edfdedb6e1b6b9087f736", + "tests/test_backend_registry.py": "6af08f5ca00bebde1a4190bb40cc2df99e025aa3465521770a22da0cc51b5651", + "tests/test_basic.py": "803e5643003e4bea60fb48c89cc84d732c77b2a3a68bccbdc6be3747ca053aba", + "tests/test_bioformats_java.py": "bf8b626c3081c26de73902822129ece5128549ec6544b604285dc9b1ac2ddc6d", + "tests/test_bioformats_storage.py": "e97642deacceab3348e8a337b34e79da235c1e1283fccfb844c0142f8632a35a", + "tests/test_ci_action_pinning.py": "a636dd4d70e231d06c5de2802afc89c389f678b3b49a40ce8463eac5b0c308dd", + "tests/test_disk_backend.py": "423c0bb9389cb002ad9c5384add0e08d4c8f99c4279ffa7d1d6621ff90ce9747", + "tests/test_disk_coverage.py": "8f0486f4611c3cfbc449e5cc7276a3cbd72f50de683eeea9647e68a0d2533be7", + "tests/test_disk_more.py": "78ae7241ab3a1d031bc733fa8f20368ba24b225c59cee47ab00624da8b77aab4", + "tests/test_filemanager_backends.py": "f506fde0e7aa4fac67c9682fcb7ed5c850c0a9ac069dd3a6ed7732427ab5578e", + "tests/test_filemanager_extended.py": "3b20c0038ba749f3d4a0f787d2e854bcd7c4e65ea58305231193f415fa734a4c", + "tests/test_imagej_cache_environment.py": "0c3b854542257e09ec13806048ceb5cc3deadf1a6302c621f44c3bc4e6efa9c7", + "tests/test_imagej_distribution.py": "fa7740c10975dfbc2e654ac3b7fc0df0f2f08599a98966e51c2c046f8cae01e1", + "tests/test_imagej_runtime.py": "fb5ce7c8d53354eb46756644d3d0c135bbeae10a21a76718f67e458f046bf480", + "tests/test_lazy_package_exports.py": "ee015f6ea3c2dc198f522db1f494f886b892540750ca3289f7f39909c4700460", + "tests/test_memory_backend.py": "ac68a5bb7c0cc4bf6a74bf3d54cc3a75df2986b9f73e92af5316d878f678b16b", + "tests/test_memory_coverage.py": "a53b737d7899f52ccc0f683ae0312094760e532be709c17a5accba7249a60542", + "tests/test_memory_type_authority.py": "ec326f948fa957b0cc8358629199442db397b9676c884d6e730e23048468cdd0", + "tests/test_metadata_namespace.py": "5a4809a6024b6eec30130ec1bc98cdd6a2541779496cea717f8a89a98d5ca5c9", + "tests/test_metadata_namespace_ownership.py": "175737cbf844b620132bea2c5e5827ffaacac01bf53de136ea49ab32727428f9", + "tests/test_napari_batch_processor.py": "a62c8875fdde0bac50059aebc3b54dfb736246ba7e1980301ebb9e7124592cd5", + "tests/test_ome_zarr_metadata.py": "7444723fcc0bd0cdedd6d8b9454be57ce929caa61698539da55c782f0b7fb420", + "tests/test_ome_zarr_storage.py": "b70a93d160cb0ba0acfd603c75ade965fbf1f95158d7c0cfc680e6a8ce907deb", + "tests/test_omero_address.py": "15d81321402ccf015f5d687b70c27e64d58ba97e719bb090efeea74821e7ffd0", + "tests/test_omero_image_plane_batch.py": "ea857b139476e127a0ee026c20cf5ca918a65f45a70bc1fe27787313d6e830b8", + "tests/test_omero_tables.py": "45ab6ce56b95dfcf9b2c202e2caa587a67bd0de4769e77b36a9986b482cea159", + "tests/test_omero_text.py": "ddf16ee95766440f5ec4d3b0e60e159cc70b2f7694e7136ec13a72c85117ca88", + "tests/test_png_format.py": "f74821025f5d962a45287d88ede69793601725f6f158fdd9cb4c9635ad75cc62", + "tests/test_receiver_layer_inspection.py": "b1b153e86978aa31e933a26072be6e3a19f4881408d10df9044fe351ad0483a8", + "tests/test_roi.py": "a2f256e55483b45ce54264fd667452230ec1024ddb7f57432711b6be7278912b", + "tests/test_roi_region_properties.py": "5cac0122893d4df5289b2e7a14018625333103a713c87ae8c559872958ba0743", + "tests/test_streaming_cleanup.py": "2edca13d06e25936076c624fd9ff6db3b66d0997c08c41082c822a0b7e8fe8ab", + "tests/test_streaming_identity.py": "7d0256ce52d48d944961bad8dff436197c45dd0ac93c8946bc354aec0cfcabff", + "tests/test_streaming_metadata.py": "806cf4998459d90ed532307a48d0f793bfada277c69537ec031fd4e28babcb46", + "tests/test_streaming_receiver_core.py": "c79e5a32d46c39b6974d421bef2ec90099e67d6b6e13d4baa5eaa48588781548", + "tests/test_streaming_return_route.py": "e20baf9443d034ab18bfff0bfc38d60af7d7245e94ec0b7e01f80d8ce403c120", + "tests/test_streaming_shared_memory.py": "c5ecc8e9c027f5fa14783ce9e568b07eb3f39ddd07254e5fa2f9847d1a86aff2", + "tests/test_viewer_transport.py": "35f4e6ffd0bb7de1c5ebb1163e2d46d71f8dcbd0544fe3494e197c2d1ac610be", + "tests/test_zarr_backend.py": "7896159c33ee7fefb89976291e35db507acf282e92361c1abd86eca54160e2fa", + "tests/test_zarr_batch.py": "883da1109c08c53ddb5e03397e5e43bdb0f878c2da8ec4c4158ee9a70520bb17", + "uv.lock": "d4465b3bae7afc90311db1265dbfcb34fbca917c5c0b99da212902ef2463bbeb" + } + }, + "external/pyqt-reactive": { + "head": "ad4948775ab81180a354d4b793d17ee5ddff3972", + "status": "", + "files": { + ".github/dependabot.yml": "34790e08d06d30f3f06cf2f071fcb2430df398c0a70bf1d99b5cca71d69080ef", + ".github/workflows/ci.yml": "043b14a1d996285f2bf77abfe65d84286e9653fb1dc238030330baa256b7818b", + ".github/workflows/publish.yml": "eacab9aaf5db73c7dc4d58de7384b12ce6532382ef51736dc3bb6dde5e8f90bc", + ".gitignore": "348e5192909c25210099ecfa274a4be8fb5faee2fe96b47595b6e4f53f3eea89", + ".readthedocs.yml": "2f5648c67a8a1ba1db73ec8dc32fbb82ffb83b246671e1dade4cb8836d667c6f", + "CHANGELOG.md": "e2e6847f7981ad1a522894ae0e15ede7eeb59b3fdbbdb7b7d3b7a5b469152d93", + "LICENSE": "c5a804a1e4c08f5593eb8466c91dc4e871fe79319d81737a82a3cc514b7b2ff6", + "README.md": "59794f0817776c30f1ba9f82919c9ce29cc96203f0e95cc0bcdaa91c55542909", + "docs/Makefile": "43df277c1f15a11e9ab7180cfaa9e65e014571beec43b19530a363f4e62e0cd9", + "docs/api/modules.rst": "617c09bc67116f3a6ad8c737392fb483471bda2a3a29102f6dddeecea541a125", + "docs/architecture/abstract_manager_widget.rst": "ec6ca7a732c048649b8627b514a653ad050685d9b776174af7303877cf756c4a", + "docs/architecture/abstract_table_browser.rst": "3c6f2e9a7b6fea5e0e2015a1051ce1decc3f339ddea21292380d02112b704363", + "docs/architecture/button_panel.rst": "454f18ec0d2dcb906caeeab5bd504838420909ccd22e9ab1b93796ec8bd68847", + "docs/architecture/cross_window_update_optimization.rst": "3e2507130ea670ed92ff1053a4f55db768e4c45055613e4046251ceb1d49a287", + "docs/architecture/enableable_form_ownership.rst": "1d61d9dd8b3ab79f1b7780b4a5380e2b876452fcf80a09a7fe8e6ff0bb6bf99a", + "docs/architecture/field_change_dispatcher.rst": "93964ac421e2ded054a4c151cc0b2383be67d7b68d4d10b871fbc1f8be4fcde2", + "docs/architecture/flash_animation_system.rst": "fc005a4748e5e312cfe61232556a38b0b2855f31d50704fbd1b6373c1178124a", + "docs/architecture/flash_callback_system.rst": "f56f1902b4747eee31c2e77848de3662580810f4295781c0e8019d373b1b5951", + "docs/architecture/form_scroll_containment.rst": "5c3b46d864459cb5900a1be2b1147d93147c8e8e781ef2b97e55d86127ef9513", + "docs/architecture/gui_performance_patterns.rst": "0ae20c36992e6f5935ce3809d6edfb81e30750791b66d7785185ada00709cc68", + "docs/architecture/index.rst": "da94b32fe4ca3245ba69b1c8c0f6551885a0bca9feb1e61af964caca5e720a94", + "docs/architecture/list_item_preview_system.rst": "d7a0fbda2c99389cfc531fde81006bbd3a32d596d395112a1e6cb97f8f2d44e4", + "docs/architecture/log_viewer_system.rst": "335f4c93673eecb1e70705cb6499cd5072a504bfb607157b0f17003f9b4df2cf", + "docs/architecture/parameter_form_lifecycle.rst": "788a41edad8bee2eaa46299f1005ada60dacbbb748ae695362163d9ae45f0c16", + "docs/architecture/parameter_form_service_architecture.rst": "307b81c106e936ba70fee6c3e1fe47f97ebb5340896ccba20a00995ec14b76c0", + "docs/architecture/parametric_widget_creation.rst": "127604ce9226b48662cf062061b2bcc20476b9331a33d5f85ec09be5ee0b4dcc", + "docs/architecture/persistent_system_monitor.rst": "4f6248e3049912c30d68cf6a57eb33ee4a8d33f36dc76aac046f490296a0f0db", + "docs/architecture/scope_visual_feedback_system.rst": "8532d95d91a514612d4e12155bc47d69a9df6f0edddc6d1548914c7465f8bd08", + "docs/architecture/scope_window_factory.rst": "7b405c0ddce22b9e1d361d090fcdefb961142d1fc8d2d942390403c8061cd230", + "docs/architecture/server_scanning_and_polling.rst": "9f8540fe237778f095f5c177abeee77734ff3e2124b2a7ccf9b520ee2459cc45", + "docs/architecture/service-layer-architecture.rst": "69e14c574ab79eb9e2c03f825cbae889893cc4d471c4a499aef0fc2e23899211", + "docs/architecture/service_registry.rst": "39c8f6361b1bcc00be0532be5faa3355b8c5e6dfb3b992f51aad3ba82ff419c1", + "docs/architecture/styling_architecture.rst": "1f7dcd355460a1634f995d7f46c13699eb9dbf41b5528535c0d5fd7673ca36bd", + "docs/architecture/system_monitor.rst": "9b099a9c66f9889ae01f7cadfdc180a48c6be1c70bbc2ba78ff1001a9f75a0e7", + "docs/architecture/system_monitor_core.rst": "2f0288776c503fed3155a206dfe068dbc40675941e97c28499119247220f08af", + "docs/architecture/tabbed_form_registry_pattern.rst": "2e3c1f428765917a7e658b0687f544025a2e46ee2622dc77611702d874593b13", + "docs/architecture/tree_aggregation_strategy.rst": "cdc28440e3560170b20c8d600da96a3a3317f1c3ce285b5a72f8922081c4ffe9", + "docs/architecture/tree_state_sync_system.rst": "1fc2178f9f7f2171cc8a05d064ca3e8a8ff89c44ca9d735c67563286dc913d85", + "docs/architecture/ui_services_architecture.rst": "afa100e0281a8b93571771d2a78c85ce1d75c654268abedd4bfaac87eba19ccc", + "docs/architecture/widget_protocol_system.rst": "9382b7b91dbcd0953bf5e68e2bd93059c84d9b2337f9c6eef1ae0893322b361b", + "docs/architecture/window_code_documents.rst": "21d801e7e83e8d084144efc4a99b23acd48832783eb147f8d88fce39619ca834", + "docs/architecture/window_snapshot.rst": "2ae5ce2a50b165e79766c91f3efb09d55d6e14365de130bf646cfe4605fa97c3", + "docs/architecture/zmq_server_browser_widget.rst": "9b133796b0588362452be0c8ddb92e03a3f1a1578a0d2b0aadd96faf617b8e3c", + "docs/archive/IMPLEMENTATION_NOTES.md": "7ff23ba35575a35cab88851ed46075d9d92c47d34e87c9b9025aecf85b3e2fed", + "docs/archive/JOSS_READINESS.md": "395798c13b9764e131eb6a62fba73bce676f274e573b941cc1c6a1b04dbcb979", + "docs/archive/README.md": "34682a4046790ad3a59f328ed23cb88af9d34f4b649656847bf9863b340f337c", + "docs/conf.py": "2ef313507c9b6ce6941cbe82863a0373b818ea5627c9dec2824953ffc7f312d3", + "docs/development/index.rst": "fc0f4501f81b733702e21d79ca31d8971e9f2605620073b933f7c8147320c5c9", + "docs/development/ui-patterns.rst": "b017023d420458c9964406bfc050242d1f16a1032243492565db35c84dd2ded0", + "docs/development/window_manager_usage.rst": "8d4fdc1d8e3f7cd3d6ac9370680cd66d935f7338b6d249cb6401057feb86279f", + "docs/examples/index.rst": "89c204c6cae088698980aaa189fc2ca0b19f5f0eddbd818f9e8b042691e70fcd", + "docs/examples/ui.rst": "b3f370b8912e8e5ceb0f5510c46a53a5fab01de513b391cd3cfda2991839bc8b", + "docs/index.rst": "f14e5ddb3320bd277ab839925e63620c1f745c2dbbc0bb17460faaffe64cc464", + "docs/make.bat": "ed525cc4d41b62b8b96d4b62a44ef32d6ccfd9324a379a82d5f71b5fb6d57776", + "docs/plans/flash_performance_optimization_plan.md": "e7cc1c22050afed51b5fa908a4099a853e4cc62b86200ad46077b8ac9037ec60", + "docs/plans/opengl_flash_acceleration.md": "28fc4cacf5c19ae7990bcc7fd81a46e8172839ba880ad8a2d85ef2ce50d8afbc", + "docs/plans/opengl_multi_window_architecture.md": "4bf4e27a62cd9d3e61a0086d8b2edb1e6595df49ae3afe0ca379e38efafd383f", + "docs/plans/parameter_form_manager_live_context.md": "dea7242aaa7c9c4e30025a457e8e77927bb1725d8c31267be0634fb24a788aee", + "docs/plans/window_manager_usage.md": "7060816a81b449c2727b1f59cecf71cc7ca5cd536a372828b178104c3e394da6", + "docs/quickstart.md": "98777cb7438f6c72d7443227e92d9b1c4a079971c7e5c6b4ac51c53baecb0b9c", + "docs/quickstart.rst": "25e9faed76719ed6d0ed95ba2416f002e3f0adcb048a605d19b57867e5ec1469", + "docs/responsive_layout_widgets.rst": "96c737263e7ba05cc2e6f21be65ead024e0d894fe6880d30c9ceea351e329156", + "docs/state_management.rst": "c23255071cf550b481797dbc91a406219be4493faca7eb835b8f02651026650d", + "docs/tear_off_tabs.rst": "fea9c04ab60cecbd54aa3b43cffda6f26d6c29ebae2ada6e3999a859bca2ecd7", + "docs/undo_redo.rst": "0cb27f79befce8a209468c86aa120a03725d1bcbabbbf055d27af06ed88169c7", + "examples/tear_off_tabs_example.py": "5506bb39a1953d99d1a8b730851a53233dddd79aa0a4cc738f422fad10b2d640", + "paper.bib": "67e65471f9b4f38e0b4beecfd7cf8b7c2ed815f7b8abfdc680e63262c3652f91", + "paper.md": "b305c23c401bc8ee17d0b1049727c867d86f2bb5c44bc51a77640e74a6c7867a", + "pyproject.toml": "524865db6ac36de136ee2b8dd43b1c741152f5ade3f8195f637650d252dbf8c2", + "requirements-ci.txt": "7da9971ef9b437b35bd507d1e35e09f37d39b4c16b4ef09c9b9a6849d20fdb04", + "scripts/benchmark_form_construction.py": "a2597d87f99c5ad0859e66732f7f7e43a73b4c896b3733d2ee9d501227d1a3d9", + "scripts/check_ruff_added_lines.py": "67ed9e6064204caca990b7b7054cd0774f59b235e241a4fa46db28ad48213ad7", + "scripts/release.py": "09fa8c9c7ccd7f4936aa9a9994b6c47726ce27e8bf99e0cfdcf06d528ff4565f", + "scripts/update_and_release.py": "80896e49f856d6a193bb1dc3917f55d2878acf1476c8240333eda16b92e8e61a", + "scripts/update_version.py": "3f771c59e65b5f6674faef3dafa3b660f152b58ea61114ae0a37f840a9ce4f04", + "scripts/verify_release_ready.py": "7a023ed885a132d922f1fd3942dd56b66158958192f7e5371e838c537cd5d2b5", + "src/pyqt_reactive/__init__.py": "5b37a90f246987a98087428e80d2cbdcc030b80ae962c347482f21719054f68c", + "src/pyqt_reactive/animation/__init__.py": "f449133ede280b74aec90dc85e88a9a2800e38c45b239996d9abde51d0cee6d9", + "src/pyqt_reactive/animation/flash_config.py": "efc6859a2de5115775a940be0a9e1c5e58f7e60e068872f11a256060b045fdeb", + "src/pyqt_reactive/animation/flash_mixin.py": "37cd2b32047109fc16255a3f9a9938ae553d5f8bd5987cd10460c7ba500f1486", + "src/pyqt_reactive/animation/flash_overlay_opengl.py": "f6bc6452e56cae0a17b07244547b55820c091fa20615de3ab1a8159f638f1dd0", + "src/pyqt_reactive/animation/flash_trace.py": "9a2e71467be16a31e0abd1f7999253e4842447289400d15cd3ff995fd06af9a2", + "src/pyqt_reactive/core/__init__.py": "c111f382ba9945651f0b385131896ea2ae522141f7a91f7a1e1eae9657e97122", + "src/pyqt_reactive/core/background_task.py": "4afa0d07107479f028557d23f15a6c5146cdb9f33e253b81f856f9092824c2aa", + "src/pyqt_reactive/core/collapsible_splitter_helper.py": "8d959845294513e0240c994c1bd9142a968f682be994cb2e3fd02f38f0403c3b", + "src/pyqt_reactive/core/debounce_timer.py": "7c3bcef0d7dc0107df0d413f6188ece136e3be5cfea473e3e74b69496af95763", + "src/pyqt_reactive/core/deferred_callback.py": "b52167f36cef2e58bc0f6b38c15359cbfb28a12a71c3a41ad9ac62155f357803", + "src/pyqt_reactive/core/future_completion.py": "7ba6ef203bae81319004ccc4ddfe4226e0230b177df663cfb0d02c364e1dbc47", + "src/pyqt_reactive/core/log_utils.py": "8a2f67434497cf5bc3d637b945b75590c735ff8d97b8db56f9efe5bbaff5e351", + "src/pyqt_reactive/core/path_cache.py": "dfca58e2ae9deb036d4df4038ce8f78125cb5ddeb2e691293bb4d54ca673b586", + "src/pyqt_reactive/core/performance_monitor.py": "09299865cc6641b87bdc195442a297d982ee3909b35c8d2063859933180834eb", + "src/pyqt_reactive/core/reorderable_list_widget.py": "edbba72d7aa88362860b923c0b86715a8349dfec9a7d85660f12cf33d859429e", + "src/pyqt_reactive/core/rich_text_appender.py": "fce3d7be3654c988f6eb16117231e6032718b28608f99f625054ff60269768a2", + "src/pyqt_reactive/core/sort_utils.py": "ac9cb5bd209113980dc398197f461e19e6c9716a5110a889bfdd7bf7b85f3d81", + "src/pyqt_reactive/dialogs/__init__.py": "a9ab9bde099f50c796b1c29c77482f0bf771591fbb12514f1b9ab8dfbddeb4a9", + "src/pyqt_reactive/dialogs/group_by_selector_dialog.py": "a62fdc652c3ff9fe2ac3babce17968a5786877e38ff5b6c2a10ea0678d5a5e67", + "src/pyqt_reactive/flash_trace.py": "c0110553bed7908221c10d1a33e48f4324366b047eda75f5b2561b68f5855063", + "src/pyqt_reactive/forms/__init__.py": "5c9c1af2df09c479f1cfc50fb8d8ee7ff3e157a940d137fcde8af95c95d035a5", + "src/pyqt_reactive/forms/form_init_service.py": "4d34e5f2494a075f9aac68e40c07b07cdb06600d832bd5b510ee971db980b82d", + "src/pyqt_reactive/forms/form_value_validation.py": "ec3ca9d48168b651e8fe0b0ef6f90a67ad32f145332a8798f1cfad220c9fd597", + "src/pyqt_reactive/forms/inline_dataclass_chrome.py": "5d224ea256bffbb840f380d9ad75f9f98b7c3ed18fc4b1ba4db0b64f92a428a1", + "src/pyqt_reactive/forms/inline_dataclass_context.py": "c0d7a19651dc1b88e66b656a031b39a7aae67ff8998e50cc4e5962a184f4fb10", + "src/pyqt_reactive/forms/layout_constants.py": "a16ebe77ea6fb5d6c26d658bc586dd8357d18506c0935cb6426edbffc906ff98", + "src/pyqt_reactive/forms/object_form_document_renderer.py": "c47fada4032d685b6bf7dca4cb9f31e4e9240a25bd1039b165b045d5de541f1f", + "src/pyqt_reactive/forms/parameter_form_base.py": "f35bb8ddd6c630a47cc5095df93ffee608a384abadf755b2f0cf12bcc963b36b", + "src/pyqt_reactive/forms/parameter_form_chrome_sync.py": "94fda5faae9adaddb1cddd1b7a4d3b0452906828d94c582f6024ff72d89ca4a3", + "src/pyqt_reactive/forms/parameter_form_constants.py": "4d4ae05b91d525108342a10e9b2da7860b5a52b0028612f244339d4531d02097", + "src/pyqt_reactive/forms/parameter_form_manager.py": "a561e62e29af42630fa107b0929fc87b74007f7ed14ec8f0a6881c49070dc923", + "src/pyqt_reactive/forms/parameter_form_service.py": "0cbf305c99b0d7ab0c558162ba5d86dcd18f81eb8cce0ad271fbd4b3d15ebc89", + "src/pyqt_reactive/forms/parameter_form_tree_index.py": "e343c3ae5535bbd46dff964844225df13fad5431253eb3924b86f8c8d1dad273", + "src/pyqt_reactive/forms/parameter_info_types.py": "3f87562ecc9b1a4cbf541767ae39d53e1b2dcfe71d9a5e211456d8b34a0a75f8", + "src/pyqt_reactive/forms/parameter_type_utils.py": "c7fd2f17faa1e3d5c3027179135de51b859d204c4a2cb9f9be10837652530ea6", + "src/pyqt_reactive/forms/parameter_value_contracts.py": "109b82548f6a90e1d495d825eeb81309b555b6122db67867a2c91769e9c54f78", + "src/pyqt_reactive/forms/ui_utils.py": "96521f8a8b75f501ca9f2dd34f377025a7d5fdf543dcbed84ec17939875ca0ec", + "src/pyqt_reactive/forms/widget_creation_config.py": "01f32efb0dadc4d5e1a42344f43e7704c47468844b4a05bd13936e490ad4489a", + "src/pyqt_reactive/forms/widget_creation_types.py": "3b1c08a0a94334facb76afa273fef0d247a93f748ce86c3fb9e7026d46ef844f", + "src/pyqt_reactive/forms/widget_dispatcher.py": "5b13da9b2aee79344c343ddcbc296f125429c9780696ed35f996e982c3ee1562", + "src/pyqt_reactive/forms/widget_operations.py": "708bf6dfd51c01154e02210abe8840eeb496af51db57cfda425d51a365080b72", + "src/pyqt_reactive/forms/widget_registry.py": "6529d5879667827e7c6adf36129e6dfdfa18239c4e0ae32bec27eab7b03805c0", + "src/pyqt_reactive/forms/widget_strategies.py": "6eb7fc78526a247dc30c39493f36f54f2df5560b0af63d743d41b30b4f469384", + "src/pyqt_reactive/pattern_metadata.py": "7c2aa3f2660d530503acdbf8e122711cf7b3d1c0aae2d05bf6addb7091dcb4cd", + "src/pyqt_reactive/process_launch.py": "c324a6bcc3b5002bd4e6e5db184d4fd80bdcdeb7b130565ca52eb37bbaa08f9e", + "src/pyqt_reactive/process_signals.py": "8b4c44c98d6979fab6935485ea94d64bdfec6eb0143855078628451d4cd9ce82", + "src/pyqt_reactive/protocols/__init__.py": "2f59ae586807161ac8d019d904646684be0cc458b8b4bcef66f3d233002fd294", + "src/pyqt_reactive/protocols/codegen_provider.py": "98c030fbf5fc99ac8ce53bba0305f0591e0b1a12403b1cd22dd282d1df476fb3", + "src/pyqt_reactive/protocols/component_selection.py": "a68d8ca325a0972c7e911901a47521e44882699729f98bd4cfde57cda7b4d1fb", + "src/pyqt_reactive/protocols/form_config.py": "cfee9524e2e2c92fe1317d9cf1229580df1e1c04a45d9583c4b97fde1b3543e2", + "src/pyqt_reactive/protocols/log_providers.py": "c6602cec12dfa687a6f4e122aa62ebaf3ba7c5472a0d63b29ab0af9db3c18514", + "src/pyqt_reactive/protocols/preview_formatter.py": "05ed6999327cf4483a79d3bb5c9d1f1bc231fd3c0a33026e1e7069f1e8d3771c", + "src/pyqt_reactive/protocols/widget_adapters.py": "1ae6653bf3f2786eafa9f53f246e145ebfa34b81c190aaa8f41c19a1463a42f9", + "src/pyqt_reactive/protocols/widget_protocols.py": "4877e65746459f556954eb718d276748fd5211d244e15f1e92973e5ee01c24d4", + "src/pyqt_reactive/qt_types.py": "cca393ec5c0126b296c2462b414a84acd0cd1b5f63de9a2b6112a0b6593921b7", + "src/pyqt_reactive/services/__init__.py": "9ec1b77dc39cd6e0f550e7ca014c4e6a560ac0fa46f071c0f6ea47a6a34fe46a", + "src/pyqt_reactive/services/async_operation_executor.py": "f1252a0244f816b2187881bee484776ebd41529d1a17df08a1360967d4e03516", + "src/pyqt_reactive/services/coalesced_scan_requests.py": "5a565f9ed1bf34871f2802400fbe6b9ae7623cc612f07dbde44df10e92a1fe21", + "src/pyqt_reactive/services/enabled_field_styling_service.py": "0a16f22878c4ff68a3a75c937ad50314a0acf14014ceb39bf2420673a75e01ac", + "src/pyqt_reactive/services/enum_dispatch_service.py": "20b18b0ef51d7ecdab99e3fe0fb20fc38c605ce80995945f5e1033e24bb4bee4", + "src/pyqt_reactive/services/executable_action.py": "6942ff087473fc102c5395184aa74c8b6c8088cab5d7fa394bc5e103e41c5d28", + "src/pyqt_reactive/services/field_change_dispatcher.py": "0875f01a405b95de12cb0d4fc396d959a758d67a39c211d3056c512352d0f1c5", + "src/pyqt_reactive/services/flag_context_manager.py": "88b634b8aa899f82f6e9525101ade1f60b0be11763a33908ed3ad23ad3bfe147", + "src/pyqt_reactive/services/function_list_editor_actions.py": "68a0fe00e8b80cf1154aaa1545725b48b0c4b75e338afbcd23fed159d6d100d3", + "src/pyqt_reactive/services/function_navigation.py": "47664c983d2f515f2c4e6599eb4fbf269817e69f9abe68101872e6380ee60e85", + "src/pyqt_reactive/services/function_pattern_code_document.py": "bdf41b58bff009890e6e696cfc4f18313adfb1669566b2566f9e7b93d863c071", + "src/pyqt_reactive/services/help_document.py": "c0c1973e7ab02823c204dfd7003ac2a2b44acea36b895a82604ac31d0f4db1e3", + "src/pyqt_reactive/services/interval_snapshot_poller.py": "77fcd5b147bcf66782ebb1bbd6a9e9a8379c9e38672a47fd14fd2432eeeed11f", + "src/pyqt_reactive/services/manager_host_abc.py": "a9a3ffc9b2cc2c5d6f6b1224c89838f74bc9d41d2c8de8da39bf33f98483b90a", + "src/pyqt_reactive/services/parameter_help_service.py": "422f9e7b818f855f28979400512b4943524606827a74bf807bbf26afef1a589c", + "src/pyqt_reactive/services/parameter_ops_service.py": "8814b7c13bc56a2b0d3f69fbfb2a6153b4e2b5d0433779db6ffce5ba480890e7", + "src/pyqt_reactive/services/parameter_service_abc.py": "c5818d83e39444cbd88e135e2a075e45872d49f8c83c34e1d0e925e7de38d387", + "src/pyqt_reactive/services/pattern_data_manager.py": "ddcf9659dab6ee50ea3c155f57e1a4111a97e414ecf74b58151da1ef6557ac88", + "src/pyqt_reactive/services/persistent_system_monitor.py": "2041aaa91a3e242bd43e1686a65feed89078d18f8f7626bff00225895bde0007", + "src/pyqt_reactive/services/process_tracker.py": "5850b647c4c75ab2ced0ea91be34fe99b8e1a004cf3b2df597caa7769f7bc899", + "src/pyqt_reactive/services/scope_color_service.py": "b9d958c27205ca5a9eed16dd729a354642d90bcca96a519b01a0b19d94b1c822", + "src/pyqt_reactive/services/scope_token_service.py": "f84056a6b542d1d9a7df9e05c2ec344d6acb7cafd3301054158e89f04eb32b17", + "src/pyqt_reactive/services/scope_window_factory.py": "fc2a4606f89c85d44014ea6d08018e34921b8898816d8a09ca8febf80a448338", + "src/pyqt_reactive/services/scope_window_navigation.py": "39a0b4e95ce6e9a478c5882b91aa0822f53b683c9f2a706727bbf88922679331", + "src/pyqt_reactive/services/search_service.py": "e72ef88fdaf28d069bc80c2eec722ffa6921015613815929006fa35fd7de2054", + "src/pyqt_reactive/services/service_registry.py": "8f6dff4b7e6db9eb4ba2a0944d18cfa3c03b75e9cef85594b1e8bc7c5bd03e58", + "src/pyqt_reactive/services/signal_service.py": "04680bff5098b52edb1f4998356c1ef9543bcca96b3f37a7377ce4f98c1f18b1", + "src/pyqt_reactive/services/system_metrics_sampler.py": "7f0df0d9425a9998e371c86f55a27cc492fb71b36817ae07b6280f73e25b8ad6", + "src/pyqt_reactive/services/system_monitor_actions.py": "2aa205be430ff8b0429279a3ec44e5bc0c672b6da7a246a208f1ed40b79aded3", + "src/pyqt_reactive/services/system_monitor_config.py": "2f7259cafbdfd28f19d2a291afcd2deeef4e5eba2402bfb0e303a0aa643d6dd4", + "src/pyqt_reactive/services/system_monitor_core.py": "1712ed50c76e6303dcb96f65c8294922084bf2e3f90d21be56b766abca0dd39a", + "src/pyqt_reactive/services/tab_identity.py": "48274c530cd0792b3565c1becf1cef9c90d2f48b4e6ccec26cdd8807c51715ff", + "src/pyqt_reactive/services/tree_item_key.py": "e908f21bd6cb1621cd8356611f1ea0d7daa59d19171b211f3c3038598b8a5aef", + "src/pyqt_reactive/services/ui_thread_dispatch.py": "f2dbe7e8ce8ac0ad3116001d7dfcd91affd516a34615775ce4ce9921480e40bd", + "src/pyqt_reactive/services/value_collection_service.py": "33562f9b50e1080a26c28467ec31c3915e5f734bdc237cc04f4802db2b36b911", + "src/pyqt_reactive/services/widget_service.py": "cf3248353552db77b3257cbcf982987848fb16acd38ab2245dbef1fcf5e25223", + "src/pyqt_reactive/services/widget_tree_projection.py": "05d5221d64e74ff14483f203975f17543381d959c30ee5918c200fa8e9957547", + "src/pyqt_reactive/services/widget_tree_projection_config.py": "8f616aa3f2fe1dc88077dc612cb7c527970363692c6a8ace15b92ba56a806e4b", + "src/pyqt_reactive/services/window_code_document.py": "d0ab321af0eb2b14fac3ab2577c8c61672763d2f13a70a7ce8a35ee7bfab7c75", + "src/pyqt_reactive/services/window_manager.py": "84fff75ff74e59c5d7080f103ad1a4baa2c884aff3d2f87891a0afdae9a5c332", + "src/pyqt_reactive/services/window_navigation.py": "88da77ed07ea220b7c6874e71029b5bd50805fb2c3048701f9df773fe17257f2", + "src/pyqt_reactive/services/window_snapshot.py": "bced886e6bbfd69ae9bdebf950027b809e72c23eddadcaa5fcf7151adf7ae913", + "src/pyqt_reactive/services/zmq_server_info.py": "1050f0e9ada59580eba9a6c4a703678f0945f4a2cd83df4fb32251733911b81d", + "src/pyqt_reactive/services/zmq_server_scan_service.py": "ae12092dfd8b85a3354b87a708f3c32aef787c2f9fd0402158d32d14b654c7de", + "src/pyqt_reactive/strategies/__init__.py": "cab5cb18e271d822d459ab8b7f6427f03b8beee5ac9a4d04b4b73a0914d58e9b", + "src/pyqt_reactive/strategies/preview_formatting.py": "dc1a423246ca40f13633847d5d3ffde3916e53c1a8a8a92de893d3e80ad8fda7", + "src/pyqt_reactive/strategies/status_presentation.py": "435d97f7804e2db714cf60b236074c7a56fc87542b05a4d7a4b1722a340a7893", + "src/pyqt_reactive/strategies/tree_aggregation.py": "d28be44b8472fe1db805fb706485f02bae2c48d99e41f422dc534d24e0084c5f", + "src/pyqt_reactive/theming/__init__.py": "ddbd3f379805b6ebc01a86c86ba41999617b46498b4436563e5a427afea3866d", + "src/pyqt_reactive/theming/accent_chrome.py": "2ae2fd7cc5b3d2b60a99942792ed0621040339e117338107be01fc6128b36f86", + "src/pyqt_reactive/theming/color_scheme.py": "45f621f809accb5dd3fab03c1bbe95b43d680e6b4e03680e89ac2fe6400f16e4", + "src/pyqt_reactive/theming/color_scheme_resolution.py": "e8c9a7501268979d0fbb3e02f693b31a63e08688e80c3cb23abe0a856e1de09a", + "src/pyqt_reactive/theming/palette_manager.py": "00b81b76f39b561eb7a4bf37d0547bf2db6e7b63efa18ef752f614005f56be90", + "src/pyqt_reactive/theming/style_generator.py": "7433368f14efdefa05a401501122704c08f061412a343531fba5400a5807c885", + "src/pyqt_reactive/theming/themed_checkbox.py": "93426143261ca2c1da431264cec69e89ee76a35d7bf85d9e54db27e72c058ea3", + "src/pyqt_reactive/utils/__init__.py": "6b8f0030c2822411d7efb3433a2276320b985423ade229529196cf09fce17e3f", + "src/pyqt_reactive/utils/log_highlight_client.py": "db8e2fd014eedc85af1d0805250931f74257a402651edad2bedbc4588cc82f7b", + "src/pyqt_reactive/utils/log_highlighter.py": "e38237cfea9d757910a7b4ac84a8095068ea1c4531abd56c6fd15228b40e4703", + "src/pyqt_reactive/utils/log_loader.py": "c0cc1d6e4c7ac286562e2659b327e738f3cbed32686c09292b0d957ea61d159d", + "src/pyqt_reactive/utils/log_streamer.py": "ac195bf633e690695d61c1ea4cdfa7bcb45a4ecc20dc237f35bc220a87a08669", + "src/pyqt_reactive/utils/preview_formatters.py": "76a383c498300e2672d6b67ee0261e0dd90df0ed2fd64fc2ffd3513cdf097838", + "src/pyqt_reactive/utils/scroll_filter.py": "cb38375d28d5613f162dc020e2b8735824ceea767ae5cc1156c7086240e22fa8", + "src/pyqt_reactive/utils/styling_utils.py": "22d32d0e01fca8f575c15fa4a61b27cde2e46616cb86088733e8d15f312a1da6", + "src/pyqt_reactive/utils/window_utils.py": "11b222927102bc79d8a5f6a957bd99ab1e828bfb6586e1d647aebd564b99afb2", + "src/pyqt_reactive/weak_events.py": "446b5ea3e71eef459a2afd3663aac3e05a4242c6e9e21379f79fadf9563202c8", + "src/pyqt_reactive/widgets/__init__.py": "ddcf678b0dc5c03aaf11d2b6f12bb9cda681a29f0105925c51a5b9263d751716", + "src/pyqt_reactive/widgets/editors/__init__.py": "6fdb2746dd03af27487402eddb929f4f10664f6dab82726dba5894dee8d33878", + "src/pyqt_reactive/widgets/editors/simple_code_editor.py": "b84df51fd669c550dddfc5484e178f585d7b05f9ca3b230cab6bb82b3d0ecdab", + "src/pyqt_reactive/widgets/enhanced_path_widget.py": "5c72029a13fcf4e58a99ece7bb898afebab083f20c104f9255082b5f9ab1b232", + "src/pyqt_reactive/widgets/function_list_editor.py": "3a71a7af92cd6a3e304a030f7e821710af53cefb63c9e13cfb331c61b86d48b6", + "src/pyqt_reactive/widgets/function_pane.py": "da0f781f1948df80c856751fb6ca5f552583395d0f5b2d2beaa83d03738e1abf", + "src/pyqt_reactive/widgets/help_document_browser.py": "f8f0bb2e454ef458f2fd4f686f4d6814a717e8f1da0de1790ddb6f8a96795e8a", + "src/pyqt_reactive/widgets/log_viewer.py": "e68eda879c7cd3f5360dd1b4a08a481298cabf85cd72bdfda66b0efbd54d56f9", + "src/pyqt_reactive/widgets/mixins/__init__.py": "fc5176659b1c3239954ce3257c3615c5053c65e233ff350c869da5a4a356bfb5", + "src/pyqt_reactive/widgets/mixins/cross_window_preview_mixin.py": "663d644a603e6da4a07eb06faabc7f4eedc21ebab392094b3c76fa2f0abb3117", + "src/pyqt_reactive/widgets/mixins/selection_preservation_mixin.py": "94fc92d98854f4bbc611fe616033abccea19ea401ef9a3e9c53ea1017a77bd66", + "src/pyqt_reactive/widgets/no_scroll_spinbox.py": "f6be116d4976fc8a83ff576ef6ca0968ed95312b6333631a7705727dede10cfd", + "src/pyqt_reactive/widgets/shared/__init__.py": "e7525c16a67b93240ce3597d7f6e6b7b9bc9841d6e4b2de1084d10fd6aea2c4b", + "src/pyqt_reactive/widgets/shared/abstract_manager_widget.py": "92f8ede35a48392112c6c1aa17e959c3cc4a9450e69f5b1447cbc4ef5498dd5b", + "src/pyqt_reactive/widgets/shared/abstract_table_browser.py": "478feab4d742bfbc4170df25e5e3cc3bc0b409506192290817a064250dd9ff5d", + "src/pyqt_reactive/widgets/shared/action_tabbed_window_body.py": "246128cd317deb382bf830a67fc6468f768e6e5547ff0e17896b16e304371ecf", + "src/pyqt_reactive/widgets/shared/base_form_dialog.py": "9b5280ef06b1c8421b3889c1c477fb311dca3b5f960e8ecfb58a0a7812551369", + "src/pyqt_reactive/widgets/shared/base_managed_window.py": "3fda59f66502bfb9ce14565981f2c8738d074c78a08ae3afc9c8e00e93c882fe", + "src/pyqt_reactive/widgets/shared/button_factory.py": "78b69f821ad925773ca049d0c08715375a4d38eaf7ed075701417401b461a14c", + "src/pyqt_reactive/widgets/shared/button_panel.py": "280f904f101681461a8899b0dae53fd10e0f616e54511ee09c3324c2a589ee43", + "src/pyqt_reactive/widgets/shared/checkbox_group_widget.py": "593b9a2c1358556c710a9a3b406042e6e335cee5c46aff1e1ef42e5025c36a4f", + "src/pyqt_reactive/widgets/shared/clickable_help_components.py": "c480f45796f893e8f9431198a0d08f5acfee3ead9034764005587aae88902e4d", + "src/pyqt_reactive/widgets/shared/column_filter_widget.py": "7e492ba7cd8d2d91ead001be293bdd69dc6a98332102e30ed45d0bb6968be589", + "src/pyqt_reactive/widgets/shared/config_hierarchy_tree.py": "150062486b1e4d092ce703cee83a3d400097267dba3670d9a0120378f0045b34", + "src/pyqt_reactive/widgets/shared/config_tree_contracts.py": "8e6b4b0047219c2f7c8297de1baf7437b2571016bd2d82e1f2e1c520bc4a35e0", + "src/pyqt_reactive/widgets/shared/detachable_action_bar.py": "37157c0874e5495d3fc5c4b33042d6334b439a57d912e354ff48529e1d434ef1", + "src/pyqt_reactive/widgets/shared/dirty_window_presenter.py": "d0171ce0b9009780675f8eee0b528fe3fd2446c8b800934a476778e1c554a147", + "src/pyqt_reactive/widgets/shared/form_window_action_header.py": "18725af2a223d9c00b2496f298f745af1628c5e0cd07a2cbfc8e39b684b574c2", + "src/pyqt_reactive/widgets/shared/function_table_browser.py": "654c394929b744ca3fd6293fadfced3966d64626ddcf5f8b74f46e63cf026340", + "src/pyqt_reactive/widgets/shared/image_table_browser.py": "3a9b45805225021f6f17174e06985ab19f75b473bc0dfbf3ecfa7a5eef9931e2", + "src/pyqt_reactive/widgets/shared/list_item_delegate.py": "282c8fe0c88f9bfd51df7eb95c739a8d428d2e9d99478796bb073c698f5907a7", + "src/pyqt_reactive/widgets/shared/list_item_text_rendering.py": "0d997923c78dcb363748daf685cdc4e93ef5d6a4ee1f7d74100cd5266cdc5220", + "src/pyqt_reactive/widgets/shared/manager_action_controller.py": "e21b2407ec7cf6f891a7a67b2ae554e741f4a16aa35537b31e3b9992c009b317", + "src/pyqt_reactive/widgets/shared/manager_item_access.py": "21540ce53728a72028cc3c9af770bbca5210aa7c18bd4f697cad42bf5d27b276", + "src/pyqt_reactive/widgets/shared/manager_item_display_builder.py": "fe1d01ba449c69a052ed796e9c6901b080e2982b565f3ae0e0d73ad6599da45f", + "src/pyqt_reactive/widgets/shared/manager_item_hooks.py": "3dbb99e17114c9869db7a4cdf9284574921f4865e10f90a2161877c41da6c222", + "src/pyqt_reactive/widgets/shared/manager_list_updater.py": "c7036bb3f37198b06f5af6859c7bc6d9a0a85520da126286d31f00750a93b50b", + "src/pyqt_reactive/widgets/shared/manager_list_visual_state.py": "ba8a54d4b682d7bf61c2286439894d59eeddebf160102f4367038866cb54a2bd", + "src/pyqt_reactive/widgets/shared/manager_preview_formatting.py": "b9057f97f87f757272027baf402740db99da945fb04a4985ad0df5dc11f29b24", + "src/pyqt_reactive/widgets/shared/manager_reorder_controller.py": "64c829c64193e6cd1b604fc883fc0406fc43ecc329adc5066fa93196e2d67551", + "src/pyqt_reactive/widgets/shared/manager_selection_controller.py": "900fcec4c0a8e61b60130cc7a53ef8b0fd157d906182f96aa85fe57e5f008d46", + "src/pyqt_reactive/widgets/shared/manager_state_binding.py": "5fc9598ab1319cdf7048ab4e20c36c9d4c64d6ba7da584efc039e6c333cf888b", + "src/pyqt_reactive/widgets/shared/manager_status_controller.py": "b0e9fb4010775206b9b66889115be864d22f8e060b67bba2ef30dc0cccca4f9c", + "src/pyqt_reactive/widgets/shared/manager_time_travel_binding.py": "4cfeeef4badfe945c8ce2bd0e86254251fe79c5884261ac2d3f07c649ac3bda3", + "src/pyqt_reactive/widgets/shared/manager_ui_scaffold.py": "1332a8b69c8c562fd49146ea29a6b9aa5e156c90db06a00731e7716788e84589", + "src/pyqt_reactive/widgets/shared/manager_workflows.py": "e9e107b3129aa6f8725031abf35b2a67a52840643efdd120554ec78b13ce157a", + "src/pyqt_reactive/widgets/shared/reflowing_vertical_scroll_area.py": "7b04fd0dcd92ae470f9b6e7005bbae811ad3a614ddac86592381d840269c4387", + "src/pyqt_reactive/widgets/shared/responsive_groupbox_title.py": "a195a584afe51c456b35038a55d63c9e8cef708ca559df01d6dbbe42e399db0e", + "src/pyqt_reactive/widgets/shared/responsive_layout_widgets.py": "4adf600b914cf0769ca37c490523f744ac5fc2e5809028a6a24f21661e05359c", + "src/pyqt_reactive/widgets/shared/scope_border_renderer.py": "ab5a8246f3ca1d88bcd935f76fe59a33782e8ccb6944aff943386fe06fc46268", + "src/pyqt_reactive/widgets/shared/scope_color_receiver.py": "8b75714a16d6cf90d0f55c68f2d7d0935b0a1fa906ac2fd659c3409406568905", + "src/pyqt_reactive/widgets/shared/scope_color_strategy.py": "aa53231e9830e66721ef637177ae1470403cc9a13519015babdec8c824febffe", + "src/pyqt_reactive/widgets/shared/scope_color_utils.py": "d4c317df9c3d1391c3f8768b2bbd041435196cc876f16be2f929b63cab8aae10", + "src/pyqt_reactive/widgets/shared/scope_style_applier.py": "cd649a820631ceb367444c38ef3722489308147f9857f451cb95d5373d9ee763", + "src/pyqt_reactive/widgets/shared/scope_visual_config.py": "51286f8aa2f960e9d656f11f5ee57a11f1b2e1213511d0d17b46ad7be3b6fa4a", + "src/pyqt_reactive/widgets/shared/scoped_border_mixin.py": "f291c293302adf863574b6abf398605687d0325a8e3af16c37abb929d3fdbfad", + "src/pyqt_reactive/widgets/shared/scoped_table_widget.py": "cf81e6a8075ae89b10a46dc0e262de9f465cf5a0cd25a915dadb91dc0601a2b0", + "src/pyqt_reactive/widgets/shared/scrollable_form_body.py": "5a00352eda3b8e7932a878c18ef6ceae68a58358d15987dd8155702b70afd20c", + "src/pyqt_reactive/widgets/shared/scrollable_form_mixin.py": "e1ac397789a515097f464fb72b9378ba91e5dfbc6bfb6c316054049004fdcffe", + "src/pyqt_reactive/widgets/shared/styled_text_layout.py": "f174770e600b58e9d7b22f10db7a7e176d11207d534d090926e747af2ab594bd", + "src/pyqt_reactive/widgets/shared/tabbed_form_widget.py": "f2914db1586963f3dfe3cda7d6940d13b2bbb7ec1ffb4bb894c3844443b34a4d", + "src/pyqt_reactive/widgets/shared/tear_off_registry.py": "b44b1d391588d2290ff50b7f73379a875698e61de926e2ea153470744399091d", + "src/pyqt_reactive/widgets/shared/tear_off_tab_widget.py": "6b4fa8aebd7134cb2451135662f6b9aaee39a688c7b3ad8b37639985c7447fc7", + "src/pyqt_reactive/widgets/shared/tree_rebuild_coordinator.py": "deb28fea82fc963f999876dc54b37a4d0e310995bb16a1892befebdef79eccaa", + "src/pyqt_reactive/widgets/shared/tree_state_adapter.py": "ba4877d3431f4cfe344c530493b934b6d181254492070ca210fdcf2ed07f148c", + "src/pyqt_reactive/widgets/shared/tree_sync_adapter.py": "0031145c849a7ab6f2c4787bdc44692306073f08b2c17bea9b12932c45698f07", + "src/pyqt_reactive/widgets/shared/zmq_server_browser_widget.py": "35a7bc0ce56461336967a2a3f2e357edf8ccae122beb179d9dd438c86df105ae", + "src/pyqt_reactive/widgets/status_bar.py": "7acd1e194c1bdb350e2dd288adc9c55a37b1027fed97df0c5fb3e77ed794c940", + "src/pyqt_reactive/widgets/status_indicator.py": "96cd497e82336c02feec80dcc7c1bbf2e81336055e5b933f1cd1b96b240a0489", + "src/pyqt_reactive/widgets/structural_table.py": "4a757027ced7529f7b4f7737c09dbfa2d9dda48e7944b5375566299d3315f346", + "src/pyqt_reactive/widgets/system_monitor.py": "620f54ccd75eeeb0e370db4d461cfbf82f3625b898d343bb7c214de1cb5d671b", + "src/pyqt_reactive/windows/help_window_manager.py": "3946e3c1f7a99e75f86c87f44fab0af1282454dbf58dc95db14bb5a3fd66c7d2", + "tests/__init__.py": "db6cc46f8f6d69c35c72a39f4829527f661a63d906f091bc59a2055943a43281", + "tests/conftest.py": "911c65976a80aa48405b9c6bf0b18830599a2185c05434cbef8b7c25c4a48b39", + "tests/test_accent_chrome.py": "0862933afb738e2866611167a7c70e412d15e72ea46f9712a0b641587cadb709", + "tests/test_action_tabbed_window_body_lazy.py": "6f5b16efb53510e2a2806e1e412d89438c5e93c4efa5a9568439daf5a9daf9e8", + "tests/test_async_operation_executor.py": "2c8bc81bff7a3fd8879b6b79d2e9e09a3a22610fbb3785d970400e5e55dcd84e", + "tests/test_ci_action_pinning.py": "a636dd4d70e231d06c5de2802afc89c389f678b3b49a40ce8463eac5b0c308dd", + "tests/test_column_presentation.py": "aa83341b1443c131637e5b2b498b42cfed858927fa3f7ded00885e03f38e688a", + "tests/test_compact_dataclass_projection.py": "b765e0b8ced31a5cc351125bb2d86670e30cc973779c0b6931c75b026a14b271", + "tests/test_core.py": "a2aba8923fd176a75a9e94f5c3b1fa0a6d18f41b28935b0c4d39ed75892894fb", + "tests/test_deferred_callback.py": "1c59913d1b19a9725e5735bbd342dc115fdf4b555863427169b5001324e83b1c", + "tests/test_enabled_field_styling_ownership.py": "d831ab09cb4a0b92c3c33e4f2c368874a454c85eb8943d9acce48388ea961263", + "tests/test_enabled_title_row_ownership.py": "01052fea145b31698ec29319f521179adda5945ce324f3d976bdcc144aeb5be4", + "tests/test_explicit_function_pattern_overrides.py": "69179658cd4d89cdbf8bd469166e819f3421c39a6fcb6a38cc330dbbcb592a33", + "tests/test_field_mutation_authorization.py": "cab1faf400063e32df23249457738b9b28f59c760a6fe4d3cfcbba34884800ea", + "tests/test_flash_destruction_lifetime.py": "a567e8b978182773d316e9a7dc7934b80da2708e2804bd8e84898b4b1a030b37", + "tests/test_flash_mask_rendering.py": "9ca43be6bb9bb98a6950e9025688a6f40d8c7d050dec2bbe5721c215c47122f8", + "tests/test_flash_playback.py": "51438a64b08edec35a54447dbf3acd8aebd77a8dde92dfd7ccb3b0755bc196df", + "tests/test_flash_scroll_ownership.py": "f660469075d1c96e1fdce5bfaa0bd94857001d5e4f9ccf33fbae9ce9b2a51072", + "tests/test_form_build_transaction.py": "fc9860a115de764ee14d2a246fb5dd2d66bb60b159ae7f5853050d1e28442417", + "tests/test_function_list_editor_tokens.py": "5eea6d8a08f76c22fe81f4fca16b80d82ab8bb2ccc6f21428e5eed739065741b", + "tests/test_function_table_browser.py": "e0289caa47564647e1952a8592cda03840a58b11fb10fac6e6db9b35b1045541", + "tests/test_future_completion.py": "fddee2a4c4b210e43c137a24f5730c0e8303a38ecc67afec7a4ac5f39d2ad860", + "tests/test_help_document.py": "b28d3fb53b253372cdd4e5fa542faf5ef9a2cd7f6b42cd3a3694c2713f4f5768", + "tests/test_help_document_browser.py": "b04eca203a5d7be904ef86f490370bb71b598bc9f9d8f2ec441d118c4baa5d71", + "tests/test_host_provider_contracts.py": "ccc75dee1cd12eb05b29debe8da84a9b98a4714607bebdb9ad75c901f24f846e", + "tests/test_inline_dataclass_chrome.py": "e2c62d17ff58ad6dbe3dc2ec7e8caa1b8eeabc7e26f92c27a1a4489d1b12656b", + "tests/test_key_sequence_adapter_lifecycle.py": "bb4e57ee2548822f06252bdf07a9e3f36d569a01165f8707c2687150e4364824", + "tests/test_list_preview_wrapping.py": "60bfe5b16e9f17f3fed1f88213e69644ad2bcf278d7012b446689fbc75e181a2", + "tests/test_log_viewer_lifecycle.py": "4c7372276b7e65d84568c01489a544df7b9b2df791910c21cba11ad9c0eaff75", + "tests/test_manager_ui_scaffold.py": "cef43797060e94628d04fc581268ccd7e054cd5810b37105a68ce7930594eba6", + "tests/test_nominal_contract_architecture.py": "d02bb10514bab0bb58ad9585f986e208d88365838597eef520186f066685867a", + "tests/test_numeric_roundtrip.py": "5975b0ce8bd7bfcf1b21bf03593b72882c775a7982d834894081b6012c556566", + "tests/test_parameter_form_service.py": "30bb0cbb28b6edd5c144a58cc30a4e9fc068f9e56ee2dbe19e39f2b64fd1982d", + "tests/test_parameter_form_tree_index.py": "d28a29f77a68a22b3fce087de2c2679f2a291dd6a66cecf94f68ac700c1fded5", + "tests/test_parameter_help_service.py": "d41f813fbefd005003ab90a6e83d44727cc1adf925a9d521095068cbed2355b7", + "tests/test_parameter_ops_placeholder_capability.py": "8e4006e9b04df1efbcc4d878a68505a7057b83d6ac44e5b47dc1ea0bdd9dad6f", + "tests/test_path_name_roles.py": "86f5ef6cc8677dd92faa349d6e3254bbf6edc734e31fe0e13f8436dc4283c34a", + "tests/test_preview_configuration_imports.py": "7bec54d0815d88d2dce8dea9b73febbf23216b32c06666eab34e1487f0ec142b", + "tests/test_preview_formatter_registry.py": "9b62974f3e42be630f8f38a72d894f937affd6a694fe6f13c71629b5a38104ee", + "tests/test_preview_formatters.py": "4d6bbd9ada4ced6e6d2b49ff8c582d30b6341dd3403ee0c458a6bc4f0e595e49", + "tests/test_process_launch.py": "49c14b825f7fd3f7f7aa51f727c436c529cd2aaabefa3bee13e9f9e9d955e489", + "tests/test_process_signals.py": "de4d134edc1345bfe53df7f8b4ed362a24e4b3da35cfbc2132c5f6fb5107a662", + "tests/test_protocols.py": "3843eb80885957639b40d1cd260c87d0680df3a63d6ac448a084a25e8a37d8f2", + "tests/test_qt_types.py": "c24a5242ec6395b8c72723540e4b100e41f573d071444fc8c27eaac9a42de911", + "tests/test_reset_flash_changes.py": "3b901bd26e339f4585d90f25a70957fd949c7bdecbcfd56c0100c5a80f006d4b", + "tests/test_scoped_border_mixin.py": "9914504211aeaeb0cc713b9aa2c11619a00bfc53dc8dc6aa68d2d5ce3bd2f538", + "tests/test_scoped_table_widget.py": "764ed376f2e284682ddab7ab8379071d19ee703c391ea8196562b8f7b5b9a2fb", + "tests/test_scroll_area_content.py": "4b6f4a9e1fed02a267e2c707b1618ad3de8c451fe5e44b2f404360ef00e579ca", + "tests/test_scrollable_form_viewport_context.py": "d445d86f08bee9cc364868d4f50c976ee95bd85827b02790353c9f7439c9df7b", + "tests/test_status_indicator.py": "78f0e0b01548b8d676fd6ed75c79a800a4399826dcc5d2770ff3bb49a7e2a85e", + "tests/test_system_metrics_sampler.py": "524776fcf817233d461402b0f096623763f119a5d690a738434b390c6c752b07", + "tests/test_system_monitor_config.py": "2cc61be642ee7c9e26dab9e13497800bd3f85490a5253e5634a1374d4fe8287a", + "tests/test_theming.py": "bb811e5a73ee0a4fb95a0b87a40165442c39e3afdfa6c6ca6c0061590dae781c", + "tests/test_tree_state_adapter.py": "76d12b348ed6a015cb9b8f5bf3173968ca1b17a219df21aae82df23b12341907", + "tests/test_ui_thread_dispatch.py": "3478d122a45ee394edd3ab191f46636c62fe3b1ba1705d80e48c9e764b31e8d7", + "tests/test_weak_events.py": "d752129493c8cdd1d427024c64c7f02cd37d0e7a87bbf854b1ed332d174fa710", + "tests/test_widget_projection_safety.py": "f124cf36ca48fe51bae0aedad633f420bccd469ea8d9059d82d64dff3ca841e2", + "tests/test_widget_tree_projection.py": "3d6a1224caf0913ca194b13f4cf791cfcb3ce9e9c38b88281fe2dac4a0e222ef", + "tests/test_widgets.py": "f24b7bace49d7c6ce5357d38e9b5362ba0625b9f4421222788ab661ae278ed19", + "tests/test_window_code_document.py": "5c546e6151f19a8bcebfaa6a332a301b888416236baa982e2ae761e015326712", + "tests/test_window_navigation.py": "0f2bd021ca9d547f2b3d64e42cba1d13d0ffb1ed52e86bd07df836d5d3f649e3", + "tests/test_window_snapshot.py": "33fa1d5509217b0c16e926f7b4643ae1d5176ac77434f16099acd9b7cd52b8e2", + "tests/test_window_snapshot_bindings.py": "44af6189d6bf64bcfcad9e87150d2f01620e2a2c0b4877d581f64428176decf9", + "tests/test_zmq_server_browser_lifecycle.py": "2789e1a2cd5c81bddd37b62eb5fbe507228972e9f0dac0d1ea06b87dda066579" + } + } + }, + "actual_import_dependencies": { + "external/ObjectState": { + "path": "/home/ts/code/projects/openhcs-shared-runtime-plumbing/external/ObjectState", + "head": "a01f8939b9bf4659502a33fe3febe62cab0f3c9a", + "status": "", + "files": { + ".github/badges/coverage.svg": "5f87bee9f8cf0a67b8cf6e1eceb1fcbb1bf57b3875e1979527faedf2ab2a8c9c", + ".github/workflows/ci.yml": "f93e84bd08fd1c8254b7b863cb2d99c74db85fb8b16bb3779a698b166f660d90", + ".github/workflows/coverage-pages.yml": "222698b93c43d62c6a301b00429084c6b64efaeebad41df2c29949205992057f", + ".github/workflows/publish.yml": "9ce34113e7ff654cfa86cff6018299a98fc03a8851f0b9899777e90bb1bbee9b", + ".gitignore": "a26875c24503b80c1699f99988e68bb14ef3f4834d476864139553a63be5148a", + ".readthedocs.yaml": "2f5648c67a8a1ba1db73ec8dc32fbb82ffb83b246671e1dade4cb8836d667c6f", + "BADGE_SETUP.md": "8395730f7b6a6b5c7c97de76802bd2513bca8cc29a4dd8fcad7a91d4f713b097", + "LICENSE": "c5a804a1e4c08f5593eb8466c91dc4e871fe79319d81737a82a3cc514b7b2ff6", + "README.md": "1d72de341fc17c96587a75bba4a913787321bf598b848474a833b34a0547842e", + "docs/.gitignore": "79b7c477e1d731b44f15770e60642935f79fcaffdad433be5a9a82d6c790d66a", + "docs/Makefile": "43df277c1f15a11e9ab7180cfaa9e65e014571beec43b19530a363f4e62e0cd9", + "docs/api/modules.rst": "bb05baa62c63a0ed6a5773ca4b644de247b91486f65cb1f18e4671e3cce2a595", + "docs/architectural_fixes.rst": "278558dd9d4bd42a347147b22b5f52262192f8a72819fb4365055c2e5c5b4448", + "docs/architecture.rst": "2523332a130b3e06aae51f127543261788b208e61d0646ddbc99104d0383266e", + "docs/archive/DOCUMENTATION_AUDIT.md": "5d2ba10f1b5f3a6f20ec74ffb10ed6358866f193737a71ce4ad2af025be12807", + "docs/archive/DOCUMENTATION_FIXES.md": "89d8f817cdfc018af56c879cd5edad906acc566b2444404a94f0b00c65eb007d", + "docs/archive/README.md": "e5a389ed4d06d204e0af5dc2502f5b661804108beb404c03fb8e5f71ef0ec820", + "docs/conf.py": "bc49d86e265031fd39550513524727428685c836d73d5434a43031db4490301b", + "docs/examples/atomic_operations.rst": "c3b719cb22ddda78a4d7836d6bc7c67f56482cfeac6c8cb3823d6666f1e3b428", + "docs/examples/basic.rst": "487b5fcae6e2d98480c39bd613f17552bf95568ad1bf85168113c4872667094c", + "docs/examples/dual_axis.rst": "df17e2f8efa9bf10d1ef12cfdeb755504395b11c5fb66a22c414dd2b3a49c05b", + "docs/examples/index.rst": "0fd2ab7c22363ef78158d43928779b83b3ffbd0f4153162dd77e7e0e323993c2", + "docs/examples/ui.rst": "04d9c0c1354730c98efeb16503e3b8d31ff569ef145e09dadf60dc07991cbfe0", + "docs/index.rst": "bb8c0eb64c2e2e57ef490943cd88b0b11b1b58bd6760bcaa6b7327766a49b2bf", + "docs/make.bat": "ed525cc4d41b62b8b96d4b62a44ef32d6ccfd9324a379a82d5f71b5fb6d57776", + "docs/provenance.rst": "f7b883738fc949f3b5806dbdfe33f18715dd81dae3f98aaf68a2b8c021b5d245", + "docs/quickstart.rst": "318fd7296e2f4c3be4907cdd39b6bd89853af2132baa7df14d569b77ad7bd55f", + "docs/state_management.rst": "4a12f5b3e3438f66fa8135de44127c2feb51da0f8973cee39001af64f83a97b3", + "docs/state_propagation.rst": "b1483c16840d7ccc928b2be19e71a54166650b10d6960e173d72a116f842a203", + "docs/undo_redo.rst": "6355cd0faa82c2261645287ff1c4aebc8d85dee31c8705e698b2b0b53c0cf3ec", + "paper.bib": "4ed4113559097ad565ffa3a098e126a830e0bac39afc7798bf61d12f6b071876", + "paper.md": "f44f04ce7d7f1f037a34a89f560825a9666fb1c4c31788412cf948b2195fc41d", + "plans/n_dimensional_inheritance.md": "e55beb4463a8f0bb2d699618a44f16f3bac7f9c084154c4efc9567ebd1ac94b3", + "pyproject.toml": "a0d2835c65fe7c65b5f40259cc1d9527095bf4a3b87d1f70030df6ef9e7ef16a", + "scripts/check_ruff_added_lines.py": "e88118d5e1fb5db477cc11fb80f594ba213482614c565f3ed6383d992995c81d", + "scripts/release.py": "52abee369fee146ee8cf83fa266b5f1dbaacc31bb5934e967265054dbc7561ba", + "scripts/update_and_release.py": "80896e49f856d6a193bb1dc3917f55d2878acf1476c8240333eda16b92e8e61a", + "scripts/update_version.py": "63d0085d6b72ff34bf9560f60e4a91351ba21416b4eccd9b48aa30d40c49022a", + "scripts/verify_release_ready.py": "0a8d8fec9af999c3bba6281f2cafdadd06365090536580c8b168f43c96674dd2", + "src/objectstate/__init__.py": "b972d45dccc8143cf141b31582fc50d2a9a1f992f3fa374dac2b07e1183ccd73", + "src/objectstate/collection_containers.py": "a939d07f5dc391b7131f7ffaa7d1390b0449b4931d54ed5b09b27f59056b6e9b", + "src/objectstate/config.py": "6db2d9de077872009f1d6defe351cf8f40e441a0de31ff574b02741cefb4ffe3", + "src/objectstate/construction_binding.py": "9cfed94cad1cc9d5cf2cf0f7e8f534f72192168bdf3ba90b2b8d7ee57f4950d3", + "src/objectstate/context_manager.py": "a01b0fc8aeb9b5b0888346f725f92cbfd96b90963bf20001b5414a5e6cd6c0e6", + "src/objectstate/docs/configuration_framework.rst": "75ef312d77f009aef7b01b506797efaddb8fcd3e16b958bf7a74e752df950cb6", + "src/objectstate/docs/context_system.rst": "fe834139f63b1a92665d12ec768ec1cbf216b355dac3b12905d31081df4e0824", + "src/objectstate/docs/object_state_lifecycle.rst": "7a9b977fadc226e0fd03cc17e1ac31cb807f23b2b6794462a6f3f7ff80ceb4aa", + "src/objectstate/dual_axis_resolver.py": "17fcda62912050bdcdd018bee2fca5f81c2f4940c5f27f2af3dc19b7691e1fb0", + "src/objectstate/edit_session.py": "003cfaff8d3687b0fa115e051c3cf833a3cbb21ad9d9becfe16c59359d656350", + "src/objectstate/field_access.py": "77f483322a504c392c0ca41cc3ee6b691d258396f70f00a61b98d9f4bc03d43a", + "src/objectstate/global_config.py": "a8187811f87806579640a8147f287114e7127401530178dd37e8d28ed788a6ae", + "src/objectstate/history_migration.py": "1c24097040e38c159ea7e809424c0b94ec6c34efa3dc84cd664ff6a2f790815f", + "src/objectstate/lazy_factory.py": "64ae924c176757863a84eef19b9df0eff516e32443c2661134ec2ae72f234bf9", + "src/objectstate/live_context_resolver.py": "bd169b0bf2e9eea833ffc1d28331d320b2386193652fca041387f32bf018d71e", + "src/objectstate/object_state.py": "735ce860ab650b281534e24e3c7354f37b64bb06832cf186d6b1f626f87108fe", + "src/objectstate/object_state_metadata.py": "4c5be42e313e3f896f2db0d3f89ca18ca6ab09b9d25f202a7b2af9e59a099ddb", + "src/objectstate/object_state_registry.py": "f848746a9c2a023a616c37531691073ea7bdb8d28d7db3bca5c8a3dcb176107a", + "src/objectstate/parameter_owner.py": "908606ec2da70f223a93071e92ca24affb3f172f7df14c64dfd27974f1fbb85c", + "src/objectstate/parameter_structure.py": "00a786af17bca57b4e819d39c76a6523af3bec116d119c323dea8c2953c7be3d", + "src/objectstate/parametric_axes.py": "7229b518f8d5cca522a3020361c16a601f3084bc5a7d34ef92a2fef11619e40c", + "src/objectstate/placeholder.py": "4e057cf3225dd38ef3859f20fcd1305526829f044af45ef616381ea734df8f67", + "src/objectstate/reified_generics.py": "39ad0897ec45ba929c0fae694dd870df987c06e2b005644189212fe224eceab2", + "src/objectstate/snapshot_model.py": "001cc83d354b040763b2da9aad0014619fdee22c82dce622dbd93ecfba780681", + "src/objectstate/subfield_semantics.py": "97aa6a7f2659260b1950c068f47d9bccec15087ed1852f1dd182272c8230c14a", + "src/objectstate/time_travel_profile.py": "c59d157f9cb85ee29aa64e18393d916ded656c6ce88bb46782f44e2463fcd007", + "src/objectstate/token_cache.py": "d6b7cdb71c15e13e8bab7271d70e0b96ccbe0825004c45c4e88851ee30a9435f", + "src/objectstate/transaction_checkpoint.py": "4c105f2078bf23c9312c600543623b9456de256c7093b9cb8a9b753b49b67530", + "src/objectstate/ui_visibility.py": "be0c60b66b86ebb696583ee394c0d45b05fd1f68a609a6aa0c29aa1098dc2592", + "src/objectstate/value_semantics.py": "4b8a43ca8667c592b74f0d46b8507ef8331402e376230dd7cac217870b2ae2f9", + "tests/__init__.py": "b0f08e026c34c8ec04203081ad79f7ed1c6cbabd784cf475333965f279ea33ae", + "tests/conftest.py": "0fa840dddea79e86afe717e146ba7ac7ee713b032e0e398b0a9f56842e4a1d62", + "tests/test_callable_baseline.py": "638929e6eb97a7c899443272e307beaa62a12922debdc7594a45ec0a85da3356", + "tests/test_config.py": "973b08f470fd54a4990cf39c7f176b9f5d02ed0b808dbf8ea2549a01d7b30d77", + "tests/test_construction_history.py": "88469c8157d4010b9877f76b7a605bb7222222d614e1ea22aeec0c39870d1609", + "tests/test_context_manager.py": "c14d3ce760520544cda14273e76df66606e47ae1bba410f83746b216b4a6418c", + "tests/test_field_access.py": "7484f7b0127e1be332ac013ea5f5c61ec5da9f2cd7fef9fcde8a8e8ab1384c54", + "tests/test_global_config.py": "f4624ffd22cf4d09bc05466dac91cf952e81033b34ab475bd1442c3d96887833", + "tests/test_history_persistence.py": "547d0cba078c2caec8b6217ec0b8713aac1ac2efd69d143e6549b023e5cd4d33", + "tests/test_integration.py": "df082bcca0ee4d6cf1c3899b4e43ccd2a004891446a05480bcdb1930ed467c24", + "tests/test_lazy_factory.py": "b3f1602d85a6e91a1b4e42490dd5253d2d0c43371a193d7369fe149bc839ceb4", + "tests/test_object_state_metadata_contracts.py": "dbd555d1659a1dd79c8c93c1d5168282a8cfaa3d727ac3fcc4d7d913eea00360", + "tests/test_object_state_restore.py": "3319b7244e0be237896902955f4c49829d4135c057116885935791bd8f125a81", + "tests/test_object_state_update_instance.py": "aef1aa303a2f3d68246f87a1a6871c0e0e48cc12d5574ef105be5aa3202a7526", + "tests/test_parameter_owner.py": "b28675a55ab72d8fdf011f972e3c5154fc683fc8206a7195342ac0a774bd873d", + "tests/test_parametric_axes.py": "8717ac074d559294e00a3d33afaac6415230efcce78f38b1e296a11c9596dcce", + "tests/test_placeholder.py": "1b9d20e8931234622ef1cf726d12e8e4fa00328c0b1cb33e9eb0fdf7acc1631d", + "tests/test_registry_subscription.py": "c634b5e416a7ea3ca04abcab65679c2852595c595b6e23cde6424ba9f6c7643d", + "tests/test_reified_generics.py": "548f5b6a282fc26b73cb5211fc8a9eb92f37fe9cc57e37cf964597293fe98866", + "tests/test_resolved_change_notifications.py": "d0addec005be985da187845efba11e1dd03367b5b9557cc1fcc54a119e42c66a", + "tests/test_subfield_semantics.py": "f156d9666a909abe9c9dbb8f69823b1e88edab310248687c4e012ab97e5a43ec", + "tests/test_timeline_projection.py": "e02529d96f61f3601c91fe30e133c4f78107d3ea6f65c864198b232b8ad76780", + "tests/test_transaction_checkpoint.py": "531c4df6b3fa25a28ac17d020532179877d4f53d66f57af1bff7beb07d08f89d", + "tests/test_ui_visible_field_projection.py": "27e016e8755374e9322460b83344836f9a3f1f0e54e9303c4b16e6abf775baea", + "tests/test_undo_redo_cascade.py": "5f8cd61f70b966ac506b5a2ba4460d58c789137f7f992dd7537d572efdcefc67", + "tests/test_value_semantics.py": "fb98e8637abe45a981faae3b61fcc9ddc14ef84b4ef5e41b95fa5736bdae2968" + } + }, + "external/python-introspect": { + "path": "/home/ts/code/projects/openhcs-shared-runtime-plumbing/external/python-introspect", + "head": "ed1e4eb15f7a0bf8315274d3e47858fa2b4372bb", + "status": "", + "files": { + ".github/actions/validate-python-release/action.yml": "ba8808c30bfcf27ce6f9dcbbf12e60af274f4d309c8e409eb3cd93ab2809436b", + ".github/actions/validate-python-release/validate_python_release.py": "96275b643ee03adac9a13996006cca803ec07a0f0d0835d47f559677af016fbc", + ".github/workflows/ci.yml": "da7bc66a370447d0dfcfb7de4ff723fe92fa3f6b34219066bee30efc3fbfb6a1", + ".github/workflows/docs.yml": "62187d940fb88d0ff42ba69a2aa1127462b04424441a039097fe956934fd0293", + ".github/workflows/publish.yml": "3dbae1430de7372a6638d339d955bc036d64b88c968edcf96ea578afbd4a4d17", + ".gitignore": "6ec409ab221e797f3f6d5e63ad9dd8e7bf09913976f8dc8a0268ecbd3cec280d", + ".readthedocs.yaml": "c95cbaad19adbbe07f93650fdb705f22629d20dfb51296e6ed566f280abfe6c6", + "CONTRIBUTING.md": "73bff7a6b106765f0e3a2f9df7e9c4da7b6243f0a9522d737ca3ed33ef16496d", + "LICENSE": "c5a804a1e4c08f5593eb8466c91dc4e871fe79319d81737a82a3cc514b7b2ff6", + "README.md": "d861f8aff2e79d9e77fbb2286b2f353c5b568412482a57efce9a488e58d543fe", + "docs/.gitignore": "7f1d49f8fa7578f81fec5b86469e14d2cf3a94ae0d85abe6bf5373f5f760ac42", + "docs/Makefile": "e33bf74d59130029ba24168a813112dd923d7044d780ce942db6645d93f56acf", + "docs/make.bat": "d2a8ebcce0de81abca77b2cbc26afd00385a61fb624e7060a8e5402fd900a72a", + "docs/source/_static/.gitkeep": "bacb37455f4ed8710d244dbe230509e632f06da53df6f849443d1deb2315dbff", + "docs/source/_templates/.gitkeep": "b32922d255e14ebf318fa34bf4519185b2498b279b89cac175150eea8e9ba76c", + "docs/source/api.rst": "f2743f0d134d71d8799d0ba4d995bf2b378234da40aa9a5008fa78b5cd2d379d", + "docs/source/conf.py": "534c6205463a628d4d7d58b2793d95cffea83a6ec2c0085b012a29b046c398ea", + "docs/source/development.rst": "fb7c848d6d5b1ee40acf259a306a20f7380c4e6928e76df938978b565e6d416c", + "docs/source/extensions.rst": "cd50883eb7b31ac94ea55b1dc662a637e844626c1950cdfc2c0cd211e776ac0a", + "docs/source/index.rst": "c98c4bcc2623fb87c1b4eb0858819ed11efa3618fd0fa56e8df3dccba415d6a9", + "pyproject.toml": "cd108ffbf3b756dbc3b8a1d85530cdeab0d2d0f452751c131db489a31178fff4", + "scripts/release.py": "f5ba54de5d2ef89ec7c75e536b63817989b8f9f17e3b2c10bb981b5bf8d08837", + "scripts/update_and_release.py": "80896e49f856d6a193bb1dc3917f55d2878acf1476c8240333eda16b92e8e61a", + "scripts/update_version.py": "303a09dca1b7374ed1d8e4aa26d76ec1bc76cfb6a769e002f2088927d51a6aa5", + "scripts/verify_release_ready.py": "5fe0aebbcaee7f60540f50221a1f8da1beab2b8b59d9b97f3b4a240f0e72211f", + "src/python_introspect/__init__.py": "d4e29e9b857a785f8ea1a1e26ea5317a39958a527df053677c335057671e4a94", + "src/python_introspect/annotation_types.py": "dc126879a8a581cea0758eec4df18ec20c47ca4b1e135abde23699b65b790bde", + "src/python_introspect/callable_declaration.py": "3bb8b474624fe6b2964a5c1f9a6aa540b2703500bfa124e7808995cb789d6951", + "src/python_introspect/dataclass_projection.py": "82662ff8eaa4f2aeb3b33edd61abae57020a7f139c3aa396d82dcecf8b801160", + "src/python_introspect/docstring_annotations.py": "444e8064f833f1a044208bd4a15107a6b688b597e36ab78ac58bee6996b51fc9", + "src/python_introspect/enableable.py": "025eadd64a6a6f1648bc36fbd1724f6049355a0b9b1a259443248d70170b8eb6", + "src/python_introspect/environment_projection.py": "8ab7d1e01e9a4529ea0b77d8996a5feeb94bdc2e905dd6263afb28d11bc217a0", + "src/python_introspect/exceptions.py": "4c6f15a3625d02b05b2fc8651e67e6b77d4bb442ad180b85121d91874ec3407b", + "src/python_introspect/runtime_parameter.py": "59fed2d467e751686447322f8e19a8633d964741d3d8afccb850dc504a619897", + "src/python_introspect/signature_analyzer.py": "7e25a0355159c86d361a21a7afc449ec758cbf8a32e9b72d06de66a924f04159", + "src/python_introspect/unified_parameter_analyzer.py": "ac52ab997fb385425920614451e8cc754fece0176bab4cc9b132eae8c930ab15", + "src/python_introspect/validation.py": "46fba78bd068c75c89b91baa4a5cbe8cdca9692e75a285eaf76311183df77b64", + "tests/__init__.py": "c752ad382f759406b1c9c102142aac7cc10a2693b8e5848536e44315567a034f", + "tests/test_annotation_types.py": "ae38706899ad48445224b09babff76496006576e7f188af7e27261521ea34ad9", + "tests/test_callable_declaration.py": "b8486dcca0c85805a14975c00987c7c3247c2c8abcb75545f89e04a01f738c32", + "tests/test_dataclass_projection.py": "6f662d0adcdd4531d8cbd94c2ffed55ced3a53c3ec481a9dce67979ac8489990", + "tests/test_dataclass_source_preparation.py": "c7438b14578eb59d53df2499c4db2004ff1b22d5e6d8350b0aa6ed2eb262a535", + "tests/test_environment_projection.py": "e11e2c180c605e761acd48103fcba10dada614a326e40a55d4777abcf0853899", + "tests/test_exceptions.py": "41f4a70df08a7718b4c9daa05569e6c491c0148abf975f0aeae78688e99d8744", + "tests/test_init.py": "7e9ca130ed8254034e32b991f8abd4624f6c1bfcdba65f911dc28c12d9cdfeca", + "tests/test_runtime_parameter.py": "b728307c8e6c7e50ca9b0befd1aaf154ad293eb18f332be544719d7ae9dd3fb4", + "tests/test_signature_analyzer.py": "0708fdcb848fe874eb4dae025c1c9fd9b0929e983cb1c1c53cb268af9fb37c2e", + "tests/test_unified_parameter_analyzer.py": "deb55bac9e31465c8368c6101a93e3c951e139c5c7ebd442a5f8cdc98842f1cd", + "tests/test_validate_python_release_action.py": "65fc7bdff5d20229e74e3abd44f936d7cfcaf9fa5881a7e9e65c59bbd65c6c12", + "tests/test_validation.py": "ce9cab31e33a001df0d40454a8d7de9e7a2ab6dc6296399adb234d06f7dfae39" + } + }, + "external/arraybridge": { + "path": "/home/ts/code/projects/openhcs-shared-runtime-plumbing/external/arraybridge", + "head": "1e53d03d9f468322a1c085c8be29485fb139caf2", + "status": "", + "files": { + ".github/workflows/ci.yml": "cadf2e9e7f8378357df650beb1a99f89c1ce9404aa297e8d707bff14c9a3f60f", + ".github/workflows/coverage-pages.yml": "4d6692efebe182beb62829c1bf3c19616159316b649b84cf5ba3d30d2a44599f", + ".github/workflows/gpu-tests.yml": "ab3b757bfb18d9b508347ca1be122ef2b084cad5e9baec8bd99c73ca8ac44ec3", + ".github/workflows/publish.yml": "98eafc9d3a4250b4fead850300eebd9e63dda05f162614ac28fa757a7d2996ee", + ".gitignore": "a26875c24503b80c1699f99988e68bb14ef3f4834d476864139553a63be5148a", + ".readthedocs.yml": "64f56fbb4a8a1ec0124b2704c97ac75ca57dd9d75922f0f32122ccc07d9d5dec", + "ADDING_NEW_FRAMEWORKS.md": "cc7f1899e7c7fb553acfd5f86e468689c367ec9eceb334d74f5d9a9c1845fb20", + "CONTRIBUTING.md": "e8e3288c0eda555fc5a55f93c3de958951bb5d339ed1e88407be837d5b392405", + "LICENSE": "c5a804a1e4c08f5593eb8466c91dc4e871fe79319d81737a82a3cc514b7b2ff6", + "README.md": "b108a144e2f797425a1734f745a73ac7a215bd5e58b3f6fe4342b18e7d16b892", + "TESTING.md": "04f1c2f01407bf49f4144301b567e766f920bac8c90ef7361d17a94f87935292", + "docs/Makefile": "e33bf74d59130029ba24168a813112dd923d7044d780ce942db6645d93f56acf", + "docs/archive/CI_ARTIFACT_UPDATE.md": "46a466f6398118a214279f30115db82d22f20847de0afbba6947f3a807d2fe18", + "docs/archive/CI_CUPY_FIX.md": "2c271a926da57ebe1914d8784e03dde43c372ee086e69981513962dcdfc977ab", + "docs/archive/CI_IMPROVEMENTS.md": "d52addf07d29e00a4a145e164c01d2499f0d063c4d28913b361c259187e083b4", + "docs/archive/CONFLICT_VISUALIZATION.md": "5ad9a1b04c6d1271506c3a94b6e7df36c80f146014425094ae3fb9e2f649a7f8", + "docs/archive/COVERAGE_AUDIT_PLAN.md": "3c54a04e3a7f0149f7e0d2a77fe8e734fe7b85593c6542851ed1d0934aee710a", + "docs/archive/DEPLOYMENT_SUMMARY.md": "40c0e2337792f659e92d4391ff8a7bf5f5b7b8b46f3379c8792d2e9055127060", + "docs/archive/GPU_TESTING_SETUP.md": "b9b94a8b40705767eb1d192ac6c140975aa624d541352847e3cb7a4734f22efd", + "docs/archive/MERGE_CONFLICT_RESOLUTION.md": "a0a3a028c5583b8eb4903ed206946c0b712b4342371f0aa10d0b6185e2726fa2", + "docs/archive/MIGRATION_SUMMARY.md": "22c0cc300f73972dafa606cb69a28025a2e0e73490ae35eb65dd5f45deb5d998", + "docs/archive/QUICK_FIX_GUIDE.txt": "44bbfe657f6f178cc3c148ede870ae2c4b3c756179b13f532d97132c45bd5307", + "docs/archive/README.md": "a28d7cde396af47e9bd985d54e517643b6f789410aa02ddaf878bd927a9714e9", + "docs/archive/RESOLVED_FILES.md": "fb72be1ebb40adddaff772ef4b3520eb578b3d028e8fb2bd526eaefe6a897e81", + "docs/ci-cd.md": "94bedfc598f0dc498e22e1a0d46e5399ed169595eefbcb95242ffc5d00a7be77", + "docs/source/.gitignore": "0485bfc859ca5866baa1043a32e732b18fa606ced2fcf39c27a7e7d3c89695c9", + "docs/source/Makefile": "8b6587b859607f200f116e2cb043fc358e1c3a26c326b563bf348453cfc68307", + "docs/source/README.md": "537352768576aa21efe985e7abbe266e43b1000298ae74097625173fb99588df", + "docs/source/advanced_topics.rst": "97b6134aba0c54f2920cf0b2978c09c092e8baaef09a044a4bc2b54df3acb3f8", + "docs/source/api_reference.rst": "9e337146f1fd22efe834f9739eab4135775c47bb1e3b01b57b33d4f3ec055072", + "docs/source/ci-cd.rst": "22e0ad2df054c693ee570833132daeca77b14ae494b8be2ba92fa1516ca4b3c2", + "docs/source/conf.py": "1b43c862dc93e51e93c0ef0435a9e5cf208665d84a2d0ed1c2477d5e4dbf3832", + "docs/source/contributing.rst": "b71e6e678251a155fa14980d64ae833b4c028bbb089b6b4d44b7baf280909190", + "docs/source/converters.rst": "b658d186779669a7eb367dcb60963fa57995c26ae63fbaad4a5c5bb75d10eb97", + "docs/source/decorators.rst": "3ff68560435fd1e0c1d5b3ee883f06f5bb3e6bb207f96e915556a662e4e461fb", + "docs/source/examples/basic_conversion.rst": "be11e27873b61fedfe0abd5f421817f683d99b731b5dbeb913aaee60dba5f08d", + "docs/source/examples/decorators.rst": "c6b0fadc2c3d36e6dc28e7fb50024c685df4f1e9e86a18be909c9cdfb00cad9b", + "docs/source/examples/index.rst": "eabe217c250d3301bf26ba2a6ae58fa4eff82c85c12e2e60e6ced6b533e1f295", + "docs/source/examples/multi_framework.rst": "1d7534ceeb611861f69aa7a0cc55c001b5f7949298192dc5e02f68fea5838c13", + "docs/source/gpu_features.rst": "8ab989045317cf0bc7ddac077caa93d6d7fe2a6f90e205462ae09ef03e605843", + "docs/source/index.rst": "963d5249c33b2ba4103c95fbf2c65038f82a883e561e9de7db825709bde3205a", + "docs/source/installation.rst": "89b6309bde9a0b72b4e6477e2b3f99efcbdce947374149c2dec92df7d8ccc003", + "docs/source/quickstart.rst": "99324fb002fb28a08700015b54083c97a6505f733b1329504ed302b1f003ee72", + "docs/source/release_035_validation.rst": "4afb3f121805a2a63e912fd85197b76adac82d67b6d070fa73908e38c577fa3f", + "docs/source/release_036_validation.rst": "d9f902b370403e824c8047fe1cf14aae36e3ae26de50c1aebdce2783c8cc2f12", + "docs/source/stack_utils.rst": "e3203ed0755ac5714674f9db908c3fa990205e7161baacae1f97a31354fefb3e", + "docs/source/user_guide.rst": "50e205f365a839ed956103fc93f59a546dabe3a963ee5ba2285e75ded021516a", + "paper.bib": "20228af15370805fe07f53154b27a977e7bd32ae84cc44bfdf127a696c5ca0b0", + "paper.md": "363b3be3c60859de0bed4ef7db739e6e41b9345284c5c28e0b1f3b6fca61844e", + "pyproject.toml": "8134c94077df2defe89328963c250e6defaa2ec2b5f49c190f0966e9e575661b", + "scripts/release.py": "3e9caa24fbfde769e347f52542a557610bb02249b81aaa71649bd579d081b69d", + "scripts/update_version.py": "9d57e7324469c34691c4561466cc4d3330485812ce1c14418d8034d30bd85a3c", + "scripts/verify_release_ready.py": "bff7cb1232eeceb6d6d235309cfc75866c7b6c1f44c48f5b2ab65f856830477e", + "src/arraybridge/__init__.py": "ae1b2dd87b91b191356e9e1fdb74a32ba7131cda6341402c4a7aa087d47a4140", + "src/arraybridge/array_geometry.py": "0a8a5f1a61552b057997e94e4c89a19b5615875f307949e0d11784179f2a94f2", + "src/arraybridge/array_operations.py": "7e9ebda3d058702cdf8662dc5ab1faf1254649f3cbde76fa0adcbe02677fa103", + "src/arraybridge/array_payload.py": "ebf8c9c0f4726b4307ad435203d9173e54c84a92dad06ef8aea0d56a51972b1e", + "src/arraybridge/converters.py": "ab8e04e8f835ac9cfccaae964083cb3993efd65aaa7147041b81a1e03e4cd7fa", + "src/arraybridge/converters_registry.py": "fe11ed6ddfb748c20a530f1fbcdbb7b703d6258eea1f237243f361569dde4874", + "src/arraybridge/decorators.py": "28f9bf4770bd4cc1ef34045fdef28065063ede029296f62b8a6c4140cc88e40e", + "src/arraybridge/dtype_scaling.py": "283818c82bf182c4172c9265fdbb399c7e3acd08a6b00edcd4e96feb1276cf5a", + "src/arraybridge/exceptions.py": "7e17a3e594b7f50701156ccd78d623a2a78b5673a0c30a7e7162267b6e63caea", + "src/arraybridge/framework_config.py": "e724d3b7d356730cca0cc5db73e7ea09d88597ea6228eb774949f19915d70909", + "src/arraybridge/framework_ops.py": "eac427f155ed3e7e10ae0f9cc603a9a17d7c3f54b30db339e23f33873c94fff4", + "src/arraybridge/gpu_cleanup.py": "003238c0c2e4f4620ef6b27a049b8d937b9923200da00a89ed51539cb273adb1", + "src/arraybridge/oom_recovery.py": "846bceb891d54a8a6222a6e5ce830596a5bcfe82ba66500617f978a5f1258de2", + "src/arraybridge/slice_processing.py": "e51d743a61d6f0149b245c13d5445dd92cf73f5e68e4485a236567554508be44", + "src/arraybridge/stack_utils.py": "1558a43745c6f97af2c3ed69f4c6924544d97adee42dccb48131044528dcf6be", + "src/arraybridge/types.py": "7b94760d57e54008d7adf4e4d37dca45d8a2c288a9dc8400be00c26148cf7624", + "src/arraybridge/utils.py": "46a4e1b5849c3c4384406e3dd5d03c6ff56f5138e07058702db8747ab42ee4db", + "tests/__init__.py": "a0ac3b43f372047f4b85b516a7e4471f98744cf549dbeec484ff3f79728f0257", + "tests/conftest.py": "6a2fe5d7206ac30e37e544ba8ff939ffa4576565b9c7559fd660f0e41db6f24c", + "tests/test_array_geometry.py": "f9c0e91d6275a940399418f2c0de810ca90c781c30219d720b745f1cf912f0a3", + "tests/test_callable_dtype_default.py": "52f343317d9d943bee46edf4edfa7e1dfd9afbe2e2ced2a297b9bc764bacedc7", + "tests/test_converters.py": "390edeb089747cc13a6378d715996f238ece1610f7aa4e9e0c3a6c932a23e315", + "tests/test_converters_registry.py": "f40974f61e55cc49fc31dd53af0dda1790301edc2218d5ec6dbcbda0c712365f", + "tests/test_decorators.py": "0b841b293e82b59133c895159c9773552dc4e7a508bbe7976da45aaa1e5d894d", + "tests/test_dtype_scaling.py": "7fcea155eede82781b9566166079a86e403afa075c5335118696a390c1ed531b", + "tests/test_durable_decorator_context.py": "53e4bfb9a2491b6d5a238ca4aaf24ffce5853346d46621e25ebf92adfdf70642", + "tests/test_exceptions.py": "441f10606ee9175814b01a243f8aea572f341bb53517c31c2c719ce41a36fe27", + "tests/test_framework_config.py": "4995b8649bef8ff4bfbf80dae282a6c8e008b0120f1a905f118903fa903e8d8c", + "tests/test_gpu_cleanup.py": "bcd6ef4f4f56850e1f12eaf9fc237d756b06841bd1c2d093ebbd81cf1a04a0bf", + "tests/test_integration.py": "e8d87ba83d8fec2ea7a9841c413277516bf665aa08f688b29da819a4c545edd2", + "tests/test_oom_recovery.py": "773b96e901e85663b6418d4deefbb28bb3ac9298b7b20589373cfa0de05e2bf4", + "tests/test_registry_integration.py": "49b88b4f692af569b66c298c8751a78b0e28a08f4db41034ef05684352df5418", + "tests/test_slice_processing.py": "b7f996dd6c38382148c1b48c5428d33775c3067f91562f082de9ec0ce20ebb5f", + "tests/test_stack_utils.py": "918e015e452b31adef93ceb829e949043390d22888daff9a295317940a58a6bd", + "tests/test_types.py": "ae1701b48c68c6f07bb23d83800ef3ca049545c254840ad5a7863db4213b3c16", + "tests/test_utils.py": "15a78a8269843d90b8dee4a2b4a50cd1b34bc791fcd1588260d45cae3956aab5" + } + }, + "external/metaclass-registry": { + "path": "/home/ts/code/projects/openhcs-shared-runtime-plumbing/external/metaclass-registry", + "head": "393a7e03003cdc56df9013f932ed4f26e632d77a", + "status": "", + "files": { + ".github/workflows/ci.yml": "036ed258494f0a2203882461397a9a2bc92f584b6006dbacaa77c2eb5beace14", + ".github/workflows/coverage-pages.yml": "410fdf83d1a1456975635cb4ae09dbaffaad8fb7ac8597c98268377b4c4c7896", + ".github/workflows/publish.yml": "85a7866717cc0a1285e74f751571d7d0b97b1210137b83585c66ed115619e600", + ".gitignore": "a26875c24503b80c1699f99988e68bb14ef3f4834d476864139553a63be5148a", + ".readthedocs.yml": "7506f658eb3b8583c0887684c3290910652325e33ab20f2041373feb7a89af19", + "CHANGELOG.md": "296f2431172f457518be6ad3789ed7d0ded103af4718937123269537b7e6bf6e", + "LICENSE": "c5a804a1e4c08f5593eb8466c91dc4e871fe79319d81737a82a3cc514b7b2ff6", + "PYPI_RELEASE_SETUP.md": "578df82d6426379a517799ed2edbf93298ecd6d848e39c7016514744df565de8", + "README.md": "668dab2cc7c536778ca0010f957c85335eda5eb2392e60c62d08b11d79009c37", + "RELEASE-SELECTED-DISCOVERY-022.rst": "2fa12717c0650cdccd83878b98b1f70a61ef94520acbc1cb7ca64c5e1c561c0f", + "SELECTED-DISCOVERY-376.rst": "22f0b41eeb3aa86183f8e2e83e225bff5ee8072aae39405dbcf9ff2bef07881c", + "docs/Makefile": "dd53c72b2b1c989f748fb2af7d719d8f351e757ae26bdf4f657b763bfe1ec4d9", + "docs/make.bat": "d2a8ebcce0de81abca77b2cbc26afd00385a61fb624e7060a8e5402fd900a72a", + "docs/source/api.rst": "d2da0de8358b7fb3fe1376358bffbf10cf39c827edae150a176b75a91490de52", + "docs/source/conf.py": "1d1618299bdaed818c3518ccc11dcd99f7277e4574b78a1db345c85fa2d949dd", + "docs/source/examples.rst": "fab494bfcff26a6aa84f7e3203a4f131832cf001b60fd4e87fb1ad24ce78ae24", + "docs/source/index.rst": "f707777948f83a5bba22528814b43520e61c76da730d0b93e0c5f3f91d6c5b12", + "docs/source/patterns.rst": "cb67e1b458cb073d226ad6691f4ed107bd35b887ad65452157a7283009707402", + "docs/source/quickstart.rst": "785bfb1e3d212247c730b79b756ba894af84d2dd4d61c43e9850c1ce79efdccd", + "docs/validation/issue251_cache_projection_20260930.md": "a740a1c5bd743564f795ec8563770788e78d719c221cafaf274d33987097c00c", + "paper.bib": "10b564cf153c1168960a822ff71950b16a16853f026a31838b23394d08d1cfee", + "paper.md": "d3d47e17ff3699034e9dfacaf7e0e2e18d3770c631048dc335e34e3d2fdc26d8", + "pyproject.toml": "2bc5a1a364bb17b03a4220cc3595d7889bfad3f731de3fe78453b16908b291c2", + "scripts/release.py": "19344fc3616a3d63e035df687ac82e8a040d0f7b69d5fb934c6e801df0ed5947", + "scripts/update_and_release.py": "80896e49f856d6a193bb1dc3917f55d2878acf1476c8240333eda16b92e8e61a", + "scripts/update_version.py": "f15d84a33dce9188e36576b21a84b7423dc868fc5e7eea22f8528dca83c3a5ba", + "scripts/verify_release_ready.py": "8747b1de6233c106025abe5fc4cfbbdf2a8d07641566445f4151b6fe4b5a9e1f", + "src/metaclass_registry/__init__.py": "b7dd8d905bcac00f490a6155df09e68d148f3e7b8238fed2854f2e1b5de06567", + "src/metaclass_registry/_home.py": "6949afb54c145a8c58f680c61177e3aa7a04e9b432b73552f5beb4b1b92169e0", + "src/metaclass_registry/cache.py": "10ba153bbbd6a45388a47aa28f5b18ab77847a33acec4820d31cf909153fb6ca", + "src/metaclass_registry/core.py": "5fbfc22dee24ac7cf653209ca06ca511ddedfb2c9e96a5354d7d4d4600828493", + "src/metaclass_registry/discovery.py": "757958272d11633e7b854c7104c07f0d90845c37fee6ab0c3646fb14c2ed8daa", + "src/metaclass_registry/exceptions.py": "333ae9a5b87cb884213a1833fde35c178734f5e684a8f772d6c0e35a090ec987", + "tests/__init__.py": "dadf7fb5f53a6c573dffaecd51460f3d36c83fd4ed903a5ed7ed21da331dd9d3", + "tests/conftest.py": "a2ad838c1e90bcfa8c368c51f07f473a85cbe4a95d27134349f94bfb1a57f767", + "tests/test_cache.py": "c0d077f47be112b257abf7ad574ca2bb4dbb7e7f3fbbe0c8044b69b69bf5c7cb", + "tests/test_cache_path_projection.py": "8da2d89cb7e88bc838b0a0d59068afe4a6ffc0010e3d4fcc196f55519d730ced", + "tests/test_core.py": "26446d33fcdd012ecf12ff7e541ce434aa38fb8f1fb110ee4ce4c74cbf0bea00", + "tests/test_discovery.py": "f28535b526c4fe95d68a33386c4378237468fb160867dd9b07a55de920939d3f", + "tests/test_exceptions.py": "11dd2d86ec4baea6834b28d9f368bb71c90dd91f23a12dcf795fb821a29ebf1b", + "tests/test_selected_discovery.py": "b20e2ff2441a37fc2700223e18cde1d64d1eba314521a656d8be2376da2c0b0a" + } + }, + "external/zmqruntime": { + "path": "/home/ts/code/projects/openhcs-shared-runtime-plumbing/external/zmqruntime", + "head": "668edafcb5ee530a163377c936431ae1e8334e85", + "status": "", + "files": { + ".github/dependabot.yml": "34790e08d06d30f3f06cf2f071fcb2430df398c0a70bf1d99b5cca71d69080ef", + ".github/workflows/publish.yml": "e0a6fd7824dfe9d4f8cd6e634038a940ee2ca78144535a64d40b44018328db81", + ".github/workflows/tests.yml": "f9b74f8a33d2b47746f7bec36c3b74979640e95d23d6da2849bc5c34a8ba7fa4", + ".gitignore": "80a49a462dd53e5509406a5305931664d212012c4cbf7ef7c48505527f632b15", + ".readthedocs.yaml": "8dd778d3217f13c531400542c6aa1e2ca620c84e68f73bbedd3bcffad5c9de33", + "ACK-ISSUE10-DRAFT-PR-BODY.md": "6e308ff02b10ab06fa58c209b1d6bfbb13191946ab1412cec644af26ed869a98", + "ACK-ISSUE10-OWNERSHIP-RECEIPT.md": "92228b50c7ca5e2d620d51f00ae46c464f3bfdc19d37cc1a7b7b8017adb74056", + "ACK-RETURN-ROUTE-DELIVERY-20260930.rst": "1a45185666390e9cf25032aa020fdeefb9988a1f7f47ff0a1fe82128e20e2454", + "LICENSE": "c5a804a1e4c08f5593eb8466c91dc4e871fe79319d81737a82a3cc514b7b2ff6", + "README.md": "c8f7fa1b36636d6cbcee78bf259f2e2511ef7e19a5533ae246548167e35b3eb9", + "docs/source/api/endpoint_handshake.rst": "b823c73359e3b140c24de84aacd567600381e726ebe3cdadfdad5bfe419a5980", + "docs/source/api/index.rst": "a598b60df852571f5d42508d9bd4025f07ca5d8cb1cf72b08910183b590c0239", + "docs/source/api/viewer_protocol.rst": "6d5d4d3abf96c69161c94a0127597b79fd0d26b6cdae5a1e0be258bbed549396", + "docs/source/architecture/execution_batch_submit_wait.rst": "f9e276c4057656c7c8ab2f594f76b04f9d25c0c1b0beeeaf103fcd86aa43e241", + "docs/source/architecture/execution_lifecycle_engine.rst": "27fb0eb4c639212c7f959ad4bdac87db55395a183163ffce713fe9c41fe58373", + "docs/source/architecture/execution_progress_stream.rst": "777bf4da41ca2c235b63a2d774a94cce1c35a03c3b87b2c501afc082a56f86ef", + "docs/source/architecture/execution_status_poller.rst": "7e801869b0b762325f889b76600eb06fa4eb04f7d80eb8acf773a9ab90308ced", + "docs/source/architecture/execution_wait_policy.rst": "acd5e60a3b294103f2b0b67e3922e49f54fd2015f360ae75ac37252ec1f1d8b3", + "docs/source/architecture/image_acknowledgment_system.rst": "650231482b3e7f38108b37a017612bc1fefa3aefddc5aaf1753d447134cc9341", + "docs/source/architecture/index.rst": "cfad2756cb9b78f0aa51b848181a113964ea547123671d4418f5fd56d2df6e37", + "docs/source/architecture/progress_registry_projection.rst": "98caca592c9f90121f14e4d71b7b756b017346303b8ca7b5d836bd3d7f19567f", + "docs/source/architecture/viewer_state_management.rst": "fe40e1beb8cfbb4c129e8a7bf5a6a2ad3d1e6e48b8df3e787a62bd2738c6c920", + "docs/source/architecture/viewer_streaming_architecture.rst": "3a380ec7fb52129c0013cfc6619c5b8686ae3531a8ab15215de04920923a6c84", + "docs/source/architecture/zmq_execution_system.rst": "6417a400634ed9aeed0f968cea0db98787304f8ab8387148ff77c8afa7f0d629", + "docs/source/conf.py": "e2224f5e41f473e9a9a213dfff036859c0834eee3561a9d6ce5415bc4487d126", + "docs/source/index.rst": "9ecc16d64526fb5799a40befecaaab6a3f55d41c5f901fed5c6a28084734a4a3", + "docs/source/installation.rst": "a3431edfd6ac76cf4b820efbdfd7a534d6e41258fb93c7d78ef290993fac8c40", + "docs/validation/issue10_ack_return_route_followup_20260930.md": "201ae9cb42395b0f774eb8bb56cf43faeb5f21106bb892320058a85874f4321b", + "docs/validation/issue10_journey.txt": "83f34a9f9ab21c1218ea1845908c1c25c705347b546958aa1ae631e1b2c9af06", + "docs/validation/issue10_journey.xml": "616ee69fb92d921ceb097bfaf7f1743b8f3385257b4afe8503e800dd43c8cf1a", + "docs/validation/issue10_native_final.txt": "db5ec543ed1f88465cd5c2d244f66d0e4199054bf65e24b5d566847f86843f24", + "docs/validation/issue10_native_final.xml": "0698e4d64d7eef028c190db21caa989bed789440b7588ce820ca804834c171aa", + "docs/validation/issue10_native_focused.txt": "44b9e7c9feb834f5c3c072184a13c8c2ff8e1cc791f42d60d74c631461212bd7", + "docs/validation/issue10_native_focused.xml": "94d03b8bfa3ee6b9ddebc9c47b6ee5ccc35871acc2a4561e16fe19d0d7593a5a", + "docs/validation/issue10_native_source.txt": "ad612a11edf1b6ebf11e0e0314cddca80566fa85d24b9fe56972ffaaf1f6775a", + "docs/validation/issue10_nra_loop_final.json": "dc6ffc60c762c658ba45db2137f1ae558ce6968cc6f628483fb259f9ff49155a", + "docs/validation/issue10_nra_loop_final.resources": "a2cf28d114cb5681018f5ff1bf36c333680479e3d80cd39a6709b1b996b82b1c", + "docs/validation/issue10_nra_source_20260930.json": "8d7f4f473df884ab1507c183e63268e552cb32f1d12096aa5bf9919c46a5dd67", + "docs/validation/issue10_nra_source_20260930.resources": "be2a0d372a464c2dc9ecf1dfb1aac25c5df38e50cfaf4d20d07a5a6c19c97478", + "docs/validation/issue10_nra_source_final.json": "775676eee04a81a811c04b2cdf74b19b36b9d9c46b813d3609c3009b63745abb", + "docs/validation/issue10_nra_source_final.resources": "5a5755bb6b22bc47592ab49d7c7a19e015510ee92294384636787d90fdd360e0", + "docs/validation/issue10_openhcs_final.txt": "e85a7720cfa71b1b84b6165d937fef22500bbe22b87db120bf76efbcda5d1a19", + "docs/validation/issue10_openhcs_final.xml": "9768040d37aed08c074e9a9b8b3da0ce3b0eef710d0ff34af5620ecd2637a4d2", + "docs/validation/issue10_openhcs_source.txt": "0671a73d20ec35588becac9898e56d16ad2ad28a76dcd94a984e336cc6adc484", + "docs/validation/issue10_openhcs_source.xml": "7da50332d3af51720f57ceae85562d750fd12e65ee62ea4196b4769cdd2433f9", + "docs/validation/issue10_polystore_final.txt": "6732430df17ceb02f4e66b69f507c7ac7cb71911a53cab4b8059175c98011d38", + "docs/validation/issue10_polystore_final.xml": "da2a6460c9a0140a6231fe786b88826cc601f674c032e570e0b5d608d38482fb", + "docs/validation/issue10_polystore_handler_import_failure.txt": "f8def2482b6d9dc99917cc00ed5c5be9b53855e0cd114821433842f229e254e3", + "docs/validation/issue10_polystore_handler_import_failure.xml": "39b00fdfbf4453c19ece38e8bc25fd270e8dd0b6d9f4c5cf5c589161e4fee6ea", + "docs/validation/issue10_ratchet_native.json": "2e8b7069023283406e8f9a66be26482eeed155c64a99dddf2d99785fcb5a1c9b", + "docs/validation/issue10_ratchet_native_final.json": "926801db2596332cc51cc84873d15bb729d57cc328a2717ae9f62013b2811352", + "docs/validation/issue10_ratchet_openhcs.json": "b4d1d3ba15de5b124227a52ccbfc9b5078ba27c7dc522fc6c2c74a32a9c72b7b", + "docs/validation/issue10_ratchet_openhcs_final.json": "4f1cfb30e7c16f4bb14758a29257164499c38f7f7264949ce4f13c0d7128e714", + "docs/validation/issue10_ratchet_polystore.json": "8cfbfc52f4caf1d169ef89007826a5f455492bd21ee795d7de5650041c71454b", + "docs/validation/issue10_ratchet_polystore_final.json": "243c642d60b78563c0d5e88f13ca3dc7dd41f82198d7105edede2977346fbf7e", + "docs/validation/issue10_startup_diagnostic.txt": "88d2d47c1b3c572a459808fd3f65f03c8d7b6e95b196fbf2ded75f8ce044564a", + "docs/validation/issue243_progress_annotation_20260929.md": "3fca37d4eed0f9e6e61013b4ead34790cf2720bbbb22ab859e26a7fc7c8ae956", + "docs/validation/issue243_progress_annotation_20260929/after-pytest.txt": "e98090351cae140807dcadf5fa326c1b48aaa9cb2e6e4e69edd31a60e476a807", + "docs/validation/issue243_progress_annotation_20260929/after-resources.txt": "26b7455faf39aff8a67d46c704f786f6cc4d5a44178add263ef9c84eda2ee95c", + "docs/validation/issue243_progress_annotation_20260929/before-bootstrap-pytest.txt": "8d68629c63d6da0ccbf8fe589eb0270d0c458ff20d3832c30ca4300f8eac010a", + "docs/validation/issue243_progress_annotation_20260929/before-bootstrap-resources.txt": "af1d21b52a918978e9674dfcfa0fc8efd0bfbcae49230a94b2a68bad846a94fd", + "docs/validation/issue243_progress_annotation_20260929/before-pytest.txt": "7307af3e5c62a2254ebf0f80e9219659834d7fb2f1d586f19f62255b0d5b5897", + "docs/validation/issue243_progress_annotation_20260929/before-resources.txt": "6db4de7dfe0424476b54d332fbdcd40f210f8f034bcaa69aa1d9c83a1504e32f", + "docs/validation/issue251_bootstrap_20260930.md": "4870894202f12f769efa03d22e4f12b9641e5ce87f2185f5a5364ef3d9825fb7", + "docs/validation/issue251_owner_factoring_20260930.md": "1aad3ec56b7994b95151c8c5ce4e284a03810b052d40edf10da0fcd6b207b2e4", + "docs/validation/issue251_owner_factoring_ratchet_20260930.json": "f3a7851e79b53234a593912e43efada908eb020fdbde6263a609e3a670a4c3d2", + "docs/validation/issue251_owner_factoring_resources_20260930.txt": "80d8faf518c6fe67c33ef071da2aaf4305d52c607d71886603efe3e1f40ee42f", + "docs/validation/issue251_pr_body_20260930.md": "fe06804512d647d7e92e66d63e55a54d1edd1a23c4ff9ea19210618b15a21913", + "docs/validation/issue251_reserved_child_ratchet_20260930.json": "2900dd5ff2046d8a6b47ab2d53c924946eb2bfaf26ff02cd8879a2be95383126", + "docs/validation/issue251_reserved_child_ratchet_resources_20260930.txt": "c6f11a8e92ed8252bca51c49813d40edc5c23c31e762d40e482ec72bb3711199", + "docs/validation/issue251_reserved_child_takeover_20260930.rst": "a55e9498a5dfb44254c3fb2d6811a882cc21ce96e72bc898b4b9cb2549cc9fc9", + "docs/validation/issue251_viewer_main_ratchet_20260930.json": "e168caa9b16ffd15a533ec5da0600d7b56b0f1117d2ae06ed5906d91343fd463", + "docs/validation/issue251_viewer_main_ratchet_resources_20260930.txt": "6d3e00434a29cedc1d4646f0d867c5d04d185f6e15a6c6f95858fb029b6341c6", + "docs/validation/issue355-evidence/dep-r0-rejected-806faa1.json.gz": "6a84c60aefc099cb05b86c29e93a4a75d201fc0759a086f23ed47707b9e26d09", + "docs/validation/issue355-evidence/dep-r0-rejected-806faa1.resources.txt": "da041805e258c61f5eedac2060ae2e6bfd234002cc78271b99846df81c4b9fd9", + "docs/validation/issue355-evidence/dep-r0.json.gz": "f8ab21863a79683d50416dc3b3e8f92fb9c979cd617e3966acae38648e1f8695", + "docs/validation/issue355-evidence/dep-r0.resources.txt": "b05ed2bcaf17ef6ca654c7b1221b8952f041806bd0b2e10ad459aa6fe92c1784", + "docs/validation/issue355-evidence/nra-local.json.gz": "8e76415ff2fedf981a01e2abeb9043b8bb231f260d38aa4ba0a896baed8a54d3", + "docs/validation/issue355-evidence/nra-local.resources.txt": "9329e39c1ff375fe1d650517412081b97a446d48b5f1e00dc63a34c7bba5d65a", + "docs/validation/issue355-evidence/startup-checkpoint.log": "836cbba2d26f0df6e09768d665e13c11f92468e5325c4f3fb36473b46e26376a", + "docs/validation/issue385-evidence/SHA256SUMS": "8a0d7b90dacce001f9704c669f1bf9d761898d8744fb612c51ce89eb429cf61a", + "docs/validation/issue385-evidence/viewer-owner-after.log": "a5c400de7c336e4c301d53e793c8de0102d9de41da5b7297c0a95f851b1bed03", + "docs/validation/issue385-evidence/viewer-owner-before.log": "fc1b12f8887694c419c99f3e97546a3ac74e26c71a3fc868125a43a557e92b3c", + "docs/validation/issue385-evidence/viewer-owner-r0.json": "f89a93d9a41729f7756749d30a9cb73f27ae013f8fcde037e5d553f87f1c7878", + "docs/validation/issue385-evidence/viewer-owner-r0.resources.txt": "1658475b38e73d7f4dac6f77d641b45b38f14fda1f41ce5b0ce1c058d8445cf8", + "docs/validation/managed-viewer-385.rst": "ff7219e3b4879fcd430d2241016293a8492aae8ea751d50ceb756e56f01bf929", + "docs/validation/openhcs355-cold-start.rst": "844f2e5836f5abe514efc69a4bdaa979def4e8fd84e7c15bbd5b02a1ee5cdfb0", + "docs/validation/startup-feedback-358.rst": "50e894dd18dae9fab0d5dc580f584d73032ec58043d92556412346eea68dd463", + "paper.bib": "cf1e534b04aaae97ffdf926efe9aeab42a6f76a7adf63553c0bf74e108837c8f", + "paper.md": "cffb0012fad980e7cd9f98bbc0275b620ee2c224ca7935c28a1f1c520ec41728", + "pyproject.toml": "e2b56ba5b94418c99ee04142edf0fc4f14a06860fbecad7170d4a2e1e4be70c5", + "scripts/release.py": "109327ab88e002e4fdd56e6a50a8b5e265fda3723fb3c0ccc184c9d1b0539c2e", + "scripts/update_and_release.py": "80896e49f856d6a193bb1dc3917f55d2878acf1476c8240333eda16b92e8e61a", + "scripts/update_version.py": "d70feec0d50ca0a8d90f0105be3e85bf5a5b17a7bb0ca63a6178ad443f0ad60f", + "scripts/verify_release_ready.py": "e8190c4f79b1fae85af698b704b339564e77090f8adb7393f0079cf0d13bd844", + "src/zmqruntime/__init__.py": "37f3e14f58b4c1dda3d338a3a2fb075aefea215f6f25b69f44091891341755ef", + "src/zmqruntime/ack_listener.py": "da5aa8d1031f971c2621071a6da40b41f10dedf12839060db13d10153050cd6d", + "src/zmqruntime/client.py": "00757150b06b837b918153bc3c2752dbdba396569ebb4f4ed91cfbff7c23d25d", + "src/zmqruntime/config.py": "79840f3b72593042b6a56e3a703a1064e0d1faa19b12446d99e0903af494f2a3", + "src/zmqruntime/execution/__init__.py": "7a5d9f1636946d5fe6edcaaef181e8740e17d5b348d81e04b50a9fccf6fb16f9", + "src/zmqruntime/execution/batch_submit_wait.py": "c447b2ccbc372a5336f5a3b32844b896dc5d58566cb3de31640ae3be2379edee", + "src/zmqruntime/execution/client.py": "1b9453ea2be540b29849770cc3fe82f284f501e0e140797dd48c2c257ec36f12", + "src/zmqruntime/execution/lifecycle.py": "23596c31b9efe812f1ab66b4300ee1bb19125ea9bef6e51ddcd8acaafb0f4ed6", + "src/zmqruntime/execution/logs.py": "c7d1816835620a2b3e82a889bd36f2a97b80aad7c0f639a07c5c9d426c6ae803", + "src/zmqruntime/execution/progress_stream.py": "13b39fb4d256cd835302f7a8949e9e56bfe0b045e3e6fc1d197ce8ae40bc57a4", + "src/zmqruntime/execution/responses.py": "43ebbaf9451c34a5cb5a0c3182cb4de4c3745e13db8482ba1373becbfc8a2a03", + "src/zmqruntime/execution/server.py": "13663ba20e62326171ff8b43c2474419940729e90b2c0b25b04ea3514734d599", + "src/zmqruntime/execution/status_poller.py": "da0c7c304f293ba4f52aaefc4c722442b5a2859d1fcb806e8fccdcd3b4f6cdc6", + "src/zmqruntime/execution/wait_policy.py": "df4a9cad5a2fb74aa0c030def22dd8cc5b851983c3f04c26d479b607075ef922", + "src/zmqruntime/messages.py": "76018d6f6ac6795e076eabed9c6dd018b8c2fb9640e194a19086a013c0a50785", + "src/zmqruntime/progress/__init__.py": "1767a50989e4a19e4ae8a7ed4343b6be564740236cdcb4c5c56c06f55c21f68f", + "src/zmqruntime/progress/projection.py": "72b22f765dabbcf6983c619c8cc5404bc52518186ef72d85a6f6c6ab65cb426f", + "src/zmqruntime/progress/registry.py": "2943b28d1490688bddcba914db5aadd445cc8e6c9b6381230f0451366e98a0c2", + "src/zmqruntime/queue_tracker.py": "b2e380a93699f85e608d1ae7c03b5a20ee62d8beb82cc93272b050084156610f", + "src/zmqruntime/runner.py": "9f52b69f23b4626adb4e1394e0ed476624d2a38d9cd2c8ec656ae3b2e6816df9", + "src/zmqruntime/server.py": "a38ed80dfbbf9d738f4a96b4bcff8ca667f592b84413c33731550513dcc924d0", + "src/zmqruntime/shutdown.py": "67acebb3ac7a2c419320005931f0de44e28f5ab0b393e6bfbdc3f11207a2073f", + "src/zmqruntime/startup.py": "55118bc44633926434f0e0b057c167dc2948f2a632a902b5bdb60dcb92731d69", + "src/zmqruntime/streaming/__init__.py": "911cac6c1f747d77ec6614dd0961ebb799a7dbaa276e4259e1f38087e3b7320b", + "src/zmqruntime/streaming/process_manager.py": "8229c322c309969f89e2a51a3e416ea38a4990248776844dbcbb01ad9796b3e5", + "src/zmqruntime/streaming/server.py": "6a587842676bdd2f414d8df8f277e5e671a5f41a7b3c4615bf1ea2a5da182834", + "src/zmqruntime/subscription.py": "4a393bd94d8a3611ff7d7423ec4ea681df6f26cf906a77e2682c76cc0e762696", + "src/zmqruntime/timeouts.py": "bb5121a03070f0f2a0ed76170a2324512ed4a4d64536ecc7ba8bdc6a4b8961d0", + "src/zmqruntime/transport.py": "e486a4215d4b977553030e897589bccac637dfe4e9abb28cfb7594139b2196c2", + "src/zmqruntime/transport_modes.py": "12bec1c13d87bb8f05b049dc76d3cb7c130414c9e69d6220228ceeb0087f9ad8", + "src/zmqruntime/viewer_protocol.py": "5580efffddca2f723b11a652f482fbdb52ebae657620fad95217b313997b9fc9", + "src/zmqruntime/viewer_state.py": "f3dd0b35c3c75b0537bf8e50624b8f05a6dce02b40f1700a878189c3312ae30c", + "tests/diagnostics/check_ack_startup_failure.py": "08856fa0ca60e4b00c8577ce2ed3bb82e6e3fbbe16eb2876b69a03500ff130ad", + "tests/test_ack_listener.py": "a616052e042aa145d4eb2b9bca6b153633662bbd54588038730c9d8a2551f70d", + "tests/test_ack_return_route.py": "4519ccf21b0d6bc892d43405541308326a8a7ae885e0ec8942e3596eda3078bd", + "tests/test_ci_action_pinning.py": "a636dd4d70e231d06c5de2802afc89c389f678b3b49a40ce8463eac5b0c308dd", + "tests/test_cold_start_activity.py": "3e0486f8e520e3bb2a767f1aca49df0ffc269476cea0f29594cb08bfce1d7896", + "tests/test_config.py": "f9a16ae6cdb8c9d1dce74bcbc95ff59e853245b219ce848d8aca9704eadfb95a", + "tests/test_endpoint_ownership.py": "e37ddca59beb48b4c1ccca4d1feee1793728cfc54b2aef69870e120bf17098e5", + "tests/test_execution.py": "7b547a68e912b012144519216097bde868264fcf7bb0ad20b3223862701bea0c", + "tests/test_execution_logs.py": "3136e1cf250b02d89e9da9be06b90ecab59fe34ba58e2e22145fd1b0e9fe2a90", + "tests/test_messages.py": "8223e0a5b461e7dd3fc6392c9f652cd74180c8de1b07fef9d28305ffffb2f229", + "tests/test_owned_close.py": "92c3149704b88278ce6771c0c2c064aa897948bd7303b8100f24f99e97d9ac84", + "tests/test_owned_startup.py": "95d3997eaf5d627925108b85dbbe5937abe448c666f26caa43f2bad5586bf73a", + "tests/test_process_manager.py": "b21d1eedd0f98549a7b0c235cca43fbea35afb3c041df81b362d94f3fde9439d", + "tests/test_progress_annotation.py": "27b237877b660d6699402a091dc7843201a4fc0636e4b9f0fc1e25d16cddee75", + "tests/test_progress_projection.py": "e56b49ba046b7c459cee386076201b252d3c831a3d8eca535eafbe0ff6affced", + "tests/test_progress_registry.py": "bf80de2da039272700a366884e5aee4163f04b156fe5c8f58912d4c7f42e7ef4", + "tests/test_progress_stream.py": "27d056146596e7e7c4f2a15ae7e7f7e01e9b4882f3258fa48108d799ecb19698", + "tests/test_queue_tracker.py": "85257cf345a02532441f188242134a2fcb4b60f793eead2f21a6bda360529a29", + "tests/test_shutdown.py": "ffff454475abed18dc520b8629a2799d5a30d0e83abd0292c5acb916d3e63eee", + "tests/test_startup.py": "3e5441886d22921b255de1016bedefd74e87e57f7099bc9e72f8021d1b115148", + "tests/test_startup_callback_scope.py": "06c9dfe205fef9aa293ca0a5dfbaaa8d5083da02fb7c2e06bc9895dea607760b", + "tests/test_timeouts.py": "8c4c95ce4c2d02d5210ef4ccfd4d0cbd1850535c8d5793b87380e995c126babb", + "tests/test_transport.py": "02072b46ca87c082eeedccb02f4b85a1ba02bc51a4c24ebfc6930a6b8b2a21f9", + "tests/test_viewer_process_ownership.py": "972bf0988a9b3b49371ddbd8e1ba7ce965c9fa9a37f04ece70fa93905335b348", + "tests/test_viewer_protocol.py": "26adaa73cc3a39cefc4c797880fb5b2e52082adaa980e479e318fa3805e7fe28", + "tests/test_viewer_state.py": "2f7b0dabbed227db35fbac5321f85b84352aafe19e33c879a50b3aee0fc9d8ea" + } + }, + "external/pycodify": { + "path": "/home/ts/code/projects/openhcs-shared-runtime-plumbing/external/pycodify", + "head": "792b03413331fdf107e369c924c257a2f0b16126", + "status": "", + "files": { + ".github/workflows/ci.yml": "7cdaf326512e98ce07256301a152b286d2c06492d67e09d6162d1312c95dd203", + ".github/workflows/publish.yml": "e10379aa724dff1ecf13fdfc3baaf32cb33de77fa65eaf8c9af270d3b3a3dbaa", + ".gitignore": "2c9d25459eec48f9d654932218ffab8dddc041060191c98a67b6505bb9726a00", + "CONTRIBUTING.md": "f39c2677fef7b7243f37e3e95e35a09e118dd1fe30b1f43a25ed119b6064ae69", + "LICENSE": "41a2e56fd632fc59805cecefbd30011033d0e67fccddc93529a1a6cff03aa766", + "README.md": "f32db990f5e1feb01ee3d7adbe1195fd691c8964acd789759901d00170cecf7e", + "docs/Makefile": "43df277c1f15a11e9ab7180cfaa9e65e014571beec43b19530a363f4e62e0cd9", + "docs/api.rst": "f613bec5644911b1d5fc6d6875ff9a843b49526a5b2e00a22488cf825a3ddd05", + "docs/architecture.rst": "dba4502673b43a48f775827acb5dc6a3c75a88836ab59ec5fc0e7dfd722d4b51", + "docs/conf.py": "3cacb5b7a11daa491ff739fe6df58494ed38e50fde40d6bd6fb7c9b4d4eb782c", + "docs/index.rst": "d20074f7b6d7d9d205d453f9fef04a3fc7120b943c6c098664dbf9376bbbdcfe", + "docs/usage.rst": "40677c937662fde6d2d96399b63c83424bc80756036df4c2f6f34c541202e606", + "paper.bib": "ba515e9b812130cc2da5991c37921c93d947808909953fc5c9949202e54507b4", + "paper.md": "c52498a740b040def7feafdd6d1aa4253515d6228e5cc534c00a417998d65f8b", + "pyproject.toml": "1103178d6661d94d66f6b43039d0961557e6d07861e46bbf8df18b6d40a0b1b5", + "scripts/release.py": "9027086b71a742b688bc984dd2fe50c4af2ad6e5ba1b1c564cf531a414e19f62", + "scripts/update_and_release.py": "80896e49f856d6a193bb1dc3917f55d2878acf1476c8240333eda16b92e8e61a", + "scripts/update_version.py": "f93a6a1ab4aa714f699edab98d36d3f610c7b7e14ff5748a22fc656214958d8d", + "scripts/verify_release_ready.py": "aa51d925335037158e0d34d0b198039e4d3833df564f01622ae4005bc7e9d6eb", + "src/pycodify/__init__.py": "b839bc2a7cd2afdfd8756eb39f22b791cb4f7aa55c0fc9c11099b7219c9c663b", + "src/pycodify/core.py": "b32dea495ceb8745c1b363f2e42aa62eaa28a1d54198a5d6541e0b1546facfb4", + "src/pycodify/formatters.py": "08791a7f3cb779889ef24a5bfb395a1acfb4d3320fe9a7cf037986c98a9d7faa", + "src/pycodify/imports.py": "17fc080d60ef168a9c211f27111b04da1d527d2bf87e2188c674e4de9d25bef1", + "tests/__init__.py": "efd53630f4e3c520366b8aa444fe2d4d33c07c7caa0e3841fbb43a04cfdd9183", + "tests/test_core.py": "164dd47f93e4adfd8fe9de851f5db74744509179f6eaaae877be879f22689e66", + "tests/test_imports.py": "ce63bc44d8fc24a02e3439a7b1504b4dacf21e64ac51f1581e60f0099664c3bb" + } + }, + "external/PolyStore": { + "path": "/home/ts/code/projects/openhcs-shared-runtime-plumbing/external/PolyStore", + "head": "84f322e46871de5ed47e7fd20976ad03e533c1c4", + "status": "", + "files": { + ".github/badges/coverage.svg": "e6e5c18d37513ef246d24694ae7e124f83597ef6e839baaa8269408f6be4690d", + ".github/dependabot.yml": "34790e08d06d30f3f06cf2f071fcb2430df398c0a70bf1d99b5cca71d69080ef", + ".github/workflows/coverage-pages.yml": "1b0c45ae4b4bbd8a38c9208c9f2f6d90faee1545bcec090b776403be9c33b470", + ".github/workflows/docs.yml": "0753d09dd18b885655926115317a45200099f8b024f3df29841f92dae248a2e2", + ".github/workflows/publish.yml": "b1e8d3648e3f38a894c8fa2d98ad2842b388c5effff69a91cd53aeb9f53781ca", + ".github/workflows/smoke-test.yml": "cec1eeec266d5e67c440709ecf5efbfcd263a75046d7e4d9e99acffe057da8e7", + ".github/workflows/tests.yml": "26cf33ecbe48e0bfffdebb2834b3f31f705cbb7293a4d864cb430ffee8f75cbe", + ".gitignore": "4edac7cffd81b322d4edc9422eb4b4574b0227939c52524b95004033891828cc", + ".readthedocs.yaml": "4d16c3881aedd586c6b7f3febd7a0ccbb2df964eac8ff17748acce0745a194c2", + ".zgroup": "2383746e67b4bcc2762b3f100f06c3fa2d5f149ab5a8e5da5d33521464a01959", + "LICENSE": "63c1c82941031bd46dc233be9b616b8e9510f5e30ae57f16a581613e7378d953", + "README.md": "c054ab7a02e743a089ea7e258444ca2982318b86af27457877cc60156a3831cf", + "docs/Makefile": "eb696db665096bf6d05567dadd0213f3ac84275b621909c9014d12d01048e73c", + "docs/archive/README.md": "56692f0cd4664b0cb34e9475a30e9c73e1de1e8f88d22edb4fb00f32593e33ca", + "docs/archive/TEST_PLAN.md": "6b840ad8555985dc78b7984ae7ebd35547da6d051558a8244269551c6072a44f", + "docs/archive/TEST_PLAN_DISK_MEMORY.md": "41619cf02d71f16149b53eb5bdbe6834fb84e69e90e154ab2f070f5c2f8f9d86", + "docs/plans/native-imagej-point-roi-20260929.md": "b7943227c7be98d2315c01b898323fbafcbf392c61239df18066767045c41a68", + "docs/roi_region_properties_checkpoint_20260929.md": "6cfd26c9550315c63dd3ac41c597ad5eb3a7cb942c3c308d97d59d10a7fc8aae", + "docs/source/_static/Main_menu.png": "dbff6948a2354eac88ed6d883ae1d9b2dc2bbc39cbfa8a8a7b21ffe7ed9fba58", + "docs/source/_static/ezstitcher_logo.png": "6e2fdd7f872fa57e595ecbd296a56ea5fcb58923863df4b5852e5c72da8a9438", + "docs/source/_static/function_pattern.png": "c6ddd31d6fefa6f398a942beffb4648a30fd4d403e4000c3579cacd27d498256", + "docs/source/_static/generate_plate_tut.png": "9fe5351407df65d9a7dc66743a887a49e006cd7919c4790426529b96d6151e28", + "docs/source/_static/image_browser.png": "d19a043b5947af2af09abef3f36581ccb4e42e388cad8c24c6dde6a5fdb950ff", + "docs/source/_static/metadata_viewer.png": "abbc92272b036d406e0aed104d1eb44695af872f4e59c5cc964b64e6c5a28f5e", + "docs/source/_static/pipeline_editor.png": "b8c9a96f3613d6c46aa1d9f28446cd57d3edab2e658dc1d631d9f4208378b865", + "docs/source/_static/plate_viewer.png": "43d934e7136dce72e587639cc55336dd3f5c4f31d966d5b8e0d68e19b9fcbba7", + "docs/source/_static/step_settings.png": "9fcdb0e446de8dac2943ee29b7044d1d9def4570c2786c043de065931a767b6e", + "docs/source/api/atomic.rst": "1d82a7883d5cd5954d4ef7680a7e736419cf09dcd454575e4b3ce03a365dfea2", + "docs/source/api/backends.rst": "fe8f91f6c630146977e00d31c2f16be1225bf9fbc6563c80a6bc52a7d3ba5e8c", + "docs/source/api/exceptions.rst": "3419b20eee89d7f9fae9d9064afb4151e6b524d48da65d0f6de4a92f66aa5ebf", + "docs/source/api/filemanager.rst": "ffbd8b43975becb7c5913149c0e8cb80cc89cfc3579816b9eff7b0ee1fb2ac75", + "docs/source/api/imagej_runtime.rst": "ee69fe61cf24c7cbe24a6c0a45f5b2f30b3db685a41f6e4ca4ffb1723ba578c9", + "docs/source/api/index.rst": "23a2dfcbc3abba4e9f2fc7fc8b12ddbd1395f2873f87c651167df7185097de74", + "docs/source/api/registry.rst": "6e96ef632a2144de51adaba15ef51b32884e36ca1c09087eb8d70b59706f4a19", + "docs/source/architecture/file_format_system.rst": "97e6ff244a875b68ffd93a1429b1a66ca5754489cd2b3be67da9e1a5e4f15c1f", + "docs/source/architecture/index.rst": "b67a0219b9e16b05561233bf8a6c9d25edc62ba3f30cda7d96fbee85d2de1dab", + "docs/source/architecture/source_and_virtual_workspace.rst": "8510f954c1de38f7330b3c62448c350ad99cbeea0f0f999adcc0dc7abc65704e", + "docs/source/architecture/streaming_receiver_projection.rst": "51049541a05db0ab130468c08e0f244cf7f181c5b4cf5a17777508be797d5a42", + "docs/source/conf.py": "7cb4e271ad57f025b60ede742e8df94a095dea71e32aa44cc7527180d8d90bb7", + "docs/source/guides/custom_backends.rst": "76b85ead72c2165c0d4e578e11a83a5c65bc3d1340cf17693a0f3a7a5c3d9ee6", + "docs/source/guides/omero_backend.rst": "77a8a6b816597de6c13633f56cbc3f797976f42799b61d574bc60181b74da1d3", + "docs/source/index.rst": "e179fa4a9bfacf5bf50754cf78d66d6e4f0f60de61f84020e65f1e7ce592e55d", + "docs/source/input_preparation_installed_20261001.rst": "2c62ed3d3d85e37fcb974a38eb511cdcccfc13deabe014dea4c7da18b5a53eee", + "docs/source/input_preparation_parent_20261001.rst": "f30ffbde998099815bb1da39bab10b1c59963db43fea8777959cd9e7d4b0c903", + "docs/source/installation.rst": "f0dc946cd61f386b3fa70d767d4a8633f153726c3771a3635214a0f6e1e2413b", + "docs/source/metadata_namespace_327.rst": "73a7bc504da48035419cc09904c139ce2604c6037fbec2179a5c47687510b909", + "docs/source/quickstart.rst": "321494c996433752be2d5a2bf1659469226a69abf71dca591b871869e7d0e374", + "paper.bib": "3f6f21182c566ad8b4124604dbdd39197f92303af864e6f6e45bedb2e0ca7e32", + "paper.md": "bba1edb7a23c365db162f99944e03675246ed6e2503ffab90936a3d8f576b689", + "pyproject.toml": "2f3edfdb1307f3300e3db056b2828814017270a9726f4d7bdac52caf84f96f8c", + "scripts/release.py": "25ef09845453b73a29ea84c303c6c77a79f291775bdba97347f296f35e8629d1", + "scripts/update_and_release.py": "80896e49f856d6a193bb1dc3917f55d2878acf1476c8240333eda16b92e8e61a", + "scripts/update_version.py": "e96bc7111806eb9a15b5d739329a6a41730fc0591e31f7975e52b17e67e1f721", + "scripts/verify_release_ready.py": "1c32aae8b7ab774eb0fb99d0a51ce6535ed7ee5020f44ca9dc8f6d3ae50af01a", + "src/polystore/__init__.py": "15dabedec6acd92b025d4a0b4e8151227a4496e8b7d5e87f28713f7799919b5a", + "src/polystore/array_payload.py": "3eb7e2cf8eb01a2b10b860778a8fd4ea47e7557fdbe28ab8adf31045088e145e", + "src/polystore/async_init.py": "21d9b8af54ff21247a2012d1ae759550ae0147cf75f667a73b4a5a8387bf3d0f", + "src/polystore/atomic.py": "5e412948fb919ce27f09971b0a5fdf0851499812e4c0ae8bd456abbd8ca86b90", + "src/polystore/backend_registry.py": "a4c4e73a79aa4363301f76727b35db2c8b55fa14107f8866a05f74da4fefb64c", + "src/polystore/base.py": "ae641affae21b61448816a14bd68b7f2f3fc0082f0f1fbe51079ed32520450b1", + "src/polystore/bioformats_java.py": "e7ee3fc888dfeebaab48681ac3e9dd2463cca693a0ff0d77ce274c72135666ff", + "src/polystore/bioformats_storage.py": "0f57d0b35619de4aa6fdad0839ae689ae6f91b0be099fd0b28742c28795f3b71", + "src/polystore/config.py": "62c8acad3da3abed8ccf7f1166fc6a0d094be1c3e842cec6446780541df292a0", + "src/polystore/constants.py": "246da078ce8a3aae6d1fdb76183f1ff724795014cbca4d670b80174f74084635", + "src/polystore/disk.py": "cf089b8c79f86099a7cea1b6cbe43ceaec6331196a44b43183f2e64b7746c219", + "src/polystore/exceptions.py": "0ecbd94af34ae3d1a37eab29e1f72be3e68c651c9a93bf52264a783a8fc65ab3", + "src/polystore/fiji_stream.py": "62a60a36f1da5668f60bc0b4e3a5d0e65008042b2361787f4909224dd9b51db9", + "src/polystore/filemanager.py": "877a2b10731b12904b1784a5b42c9e39688e3a84f7f86018c1c2beee96ea2296", + "src/polystore/formats.py": "6f7ec984549b45a31bb32b9051672e996a67d9caab3ce2030ddc7d50e17101c5", + "src/polystore/imagej_distribution.py": "29000b7f7d8067a8a1667fc8ee603d3c2f33fd87f0a318a21cf0093473df49b4", + "src/polystore/imagej_runtime.py": "150983b2da981b31f974ad384a0fbadf5804003fd59c085993701b876384276a", + "src/polystore/memory.py": "4ac155187a80c5b6f096b2170d6851e6ce119938222beef4bd99440cbccba9e8", + "src/polystore/metadata_migration.py": "4390dc79fd1f9dd3fa405b961ea15573037bc19c6db2b31b36a5bcb7170abc5e", + "src/polystore/metadata_writer.py": "987b8ff3cfb45b170656fb7dd405abc68c460381871ca26cc26cf82e0550e256", + "src/polystore/napari_stream.py": "29286154e37d7eeb2c75d9a48cd12fa696f40c02d5ac35865360b7673801f905", + "src/polystore/ome_zarr_metadata.py": "ed0e4a3de24a6f590404d98578e19b76c9c76b27e854639e68b521f49924fbbc", + "src/polystore/ome_zarr_storage.py": "005bdd6ce615ff115050e1853aab0c56c50c65d1361c31ef6219bb0d6c4852b7", + "src/polystore/omero_address.py": "8a3ae8789fceba0f099eef2ee983d858a8f83b764f19b70dfa7bb88f521c0c92", + "src/polystore/omero_local.py": "35d39564317510234c2a3ded00bb06a09417d1b6f7359e52e74c7bd0a086f642", + "src/polystore/omero_tables.py": "910aaa6bea75f40bae82df71dd414415278b1387b80c7f1bc11e8d681874451e", + "src/polystore/omero_text.py": "9f51daef3d96cf191994d8a9c7aacf6182941ec2b0ada3f5ba61e0cc4f9412f1", + "src/polystore/roi.py": "fa945e9a3f7272e72f3ea022c7a3ae6cd30520ed7924591dd3f3cad5d0e71fc0", + "src/polystore/roi_converters.py": "50c37e5b070db7cbe418a5a64576595ee3ea7e5bbcf014492f38958f4debbf07", + "src/polystore/source_tile_geometry.py": "ebe4a422ec76972f2318ba56910ba6ccaef28734764ed3b88a3ba478ed69d322", + "src/polystore/streaming/__init__.py": "e401faf53b6fb9a08e237535313e5b99d7e371372875182b76132921233e5adc", + "src/polystore/streaming/_streaming_backend.py": "7caf2252677a894a5a761b60c473b92184b83745608c2b50a75eb1733c77cd10", + "src/polystore/streaming/base.py": "353e87dc92ad8df2ccec0136ab8ef7de7729896522cf8b16c0ec79bde455c176", + "src/polystore/streaming/handlers/__init__.py": "78daf5078f1914dc5b646ebeeb79bea336036b3b4737e122865be41ab7b24f03", + "src/polystore/streaming/handlers/fiji_images.py": "b5f06390cfeaef6c6a10c06bf9af00eab29f90ce1bb2899794d2e516cf86c7d0", + "src/polystore/streaming/handlers/fiji_rois.py": "5edcdc8d7344c5793730beb5a1c3baea89e96b13e62b746cc1cbeded3217a978", + "src/polystore/streaming/identity.py": "a8e48d76c8fd222515121e2ebc879dccc820e0ebf5b576a8728c1a7ffd35dc4e", + "src/polystore/streaming/receivers/__init__.py": "07953a0ecae9f307b9a2706062c1f452648267887e8cd03fbdb87d4b301b4877", + "src/polystore/streaming/receivers/batching/__init__.py": "c045df607fc2c07983659caff8b191660dd2ce5e73aeceb89894be3a457926ec", + "src/polystore/streaming/receivers/core/__init__.py": "b61b9545e4e373556d5beb87a23c3f6475238361d0c3a4cf18a3a5e197dedcba", + "src/polystore/streaming/receivers/core/batch_engine.py": "36d1dd9a7a2beae134c6f149ca148dd4cc2921fa2feb37cbcb88c42312743055", + "src/polystore/streaming/receivers/core/contracts.py": "c89f3f2dfb3e23482112a6b98ae3238d1768b2f4a01b4b2d605b698bd307f561", + "src/polystore/streaming/receivers/core/image_presentation.py": "dbe1395afce5a280fc1ab0c66bf302e324577ff15c6dff7a1698f50f1fc72a73", + "src/polystore/streaming/receivers/core/layer_inspection.py": "e93f707de62516eb0d48d9fdb0f71862b4265389723ca92a05145fce99a28802", + "src/polystore/streaming/receivers/core/metadata_presentation.py": "5e021ff3659039856616a75b4e19918b709121ee4b8902d39430f110b1adc5e8", + "src/polystore/streaming/receivers/core/viewport_presentation.py": "936378683122ad28deba10d71e9561abfc904017582e345316bf1c760d2abfb0", + "src/polystore/streaming/receivers/core/window_projection.py": "e95d0ccda66aa866082c5afc5bf9908259c727ca33270d3f069384651e1783e3", + "src/polystore/streaming/receivers/fiji/__init__.py": "a86e999752d8212da5bd58f1a3db43ffa7ce867fb0ae1209bf0f148bfe5b4b50", + "src/polystore/streaming/receivers/fiji/fiji_batch_processor.py": "165919f2e36c37e221bdd6f17e4398795745a95da9ddd7bba0ab93d74b9bdab2", + "src/polystore/streaming/receivers/napari/__init__.py": "ab4ba3ba76e98365e67abf6f9d79c0be098a774bf9e17e8523fc430a0babb9f1", + "src/polystore/streaming/receivers/napari/image_presentation.py": "1abb2d4c33ea073deb415cf9a242baa64d0b9d73985b7920d72508f2a5998a8e", + "src/polystore/streaming/receivers/napari/layer_inspection.py": "6bb86202480b5aad55d6641e3a6891105c5284d4408ff1cb7f8cbb36929888cc", + "src/polystore/streaming/receivers/napari/layer_key.py": "650eba665a58130fd67c38b164f97f677d805e07e53c2c7f367f850ae6db4a8f", + "src/polystore/streaming/receivers/napari/napari_batch_processor.py": "c3ed3f9fb4d89f82cc887a4d7775db911c96fc7e67d437cdfe8c4b78e62a16e3", + "src/polystore/streaming/receivers/napari/viewport_presentation.py": "aef743171c8d27ac56b53217f8fb2352584d447b33791ee2ce3e1c8fa4ade356", + "src/polystore/streaming/viewer_transport.py": "3b883e3078ded6b8e9c80e135a2eab876f9399fb7813dcd1dc8dd8f6049a3537", + "src/polystore/streaming_constants.py": "645e1685a1cf23167b2f6f06d4807c76444c339fbde66f3b12de9bba3adbe170", + "src/polystore/tiff_header.py": "714c6ddd0ff3928df37b2e65775c2987c285538b2375ee17254ae0dee868fa6b", + "src/polystore/utils.py": "1dd12cb9742f58f9537f1e23832f44f90deaf4332de8ae9b97e8df711ed261c7", + "src/polystore/virtual_workspace.py": "b19fcda85369d812e70bfc1a0efc5d8861ae256f69e94372e2e9515c591d36af", + "src/polystore/zarr.py": "b9404235a3a7882dd6f64383c11aeb6073c8f3a6485bec74264ad6434a1ee35f", + "src/polystore/zarr_batch.py": "8ed86ac525b561e6557a8ac55c6cb0d3954311a31d3ae65ea84af196246d60d9", + "src/polystore/zmq_config.py": "14123ce6fe232144f8a4fa086cad164a0b29e3b014ab809810d622e39ac92854", + "tests/conftest.py": "5ca35c45b774ffda10030f950823eedb160628aad1076b805e401e277bf624f4", + "tests/constraints/zarr-minimum.txt": "ddc0b24cd684f9742b7ecdbc0939072ca89dbf147c4e238268140e4678bb37a7", + "tests/imagej_cache_process_fixture.py": "bf04cebf8be7fb4e911ec1df75cc3e4fc311745981975620b2946b308c461d93", + "tests/integration/test_imagej_runtime_live.py": "bc1c16a755e12682b5b94b81b902068fb4a2e4b8f8b708a43c814b28ecd78bf5", + "tests/metadata_namespace_worker.py": "5db68ec70ba017d1b81cad2302788dbcf0a1cce5be019358259d3aec5ffd7ef5", + "tests/test_array_payload.py": "95a02bc11cd21f57da986ab8f90196a7343c70513d034e69dec581c413ee802c", + "tests/test_atomic_lock.py": "0ee06b9b53964df6777f72cd0ddf0faaa63d9316ec7edfdedb6e1b6b9087f736", + "tests/test_backend_registry.py": "6af08f5ca00bebde1a4190bb40cc2df99e025aa3465521770a22da0cc51b5651", + "tests/test_basic.py": "803e5643003e4bea60fb48c89cc84d732c77b2a3a68bccbdc6be3747ca053aba", + "tests/test_bioformats_java.py": "bf8b626c3081c26de73902822129ece5128549ec6544b604285dc9b1ac2ddc6d", + "tests/test_bioformats_storage.py": "e97642deacceab3348e8a337b34e79da235c1e1283fccfb844c0142f8632a35a", + "tests/test_ci_action_pinning.py": "a636dd4d70e231d06c5de2802afc89c389f678b3b49a40ce8463eac5b0c308dd", + "tests/test_disk_backend.py": "423c0bb9389cb002ad9c5384add0e08d4c8f99c4279ffa7d1d6621ff90ce9747", + "tests/test_disk_coverage.py": "8f0486f4611c3cfbc449e5cc7276a3cbd72f50de683eeea9647e68a0d2533be7", + "tests/test_disk_more.py": "78ae7241ab3a1d031bc733fa8f20368ba24b225c59cee47ab00624da8b77aab4", + "tests/test_filemanager_backends.py": "f506fde0e7aa4fac67c9682fcb7ed5c850c0a9ac069dd3a6ed7732427ab5578e", + "tests/test_filemanager_extended.py": "3b20c0038ba749f3d4a0f787d2e854bcd7c4e65ea58305231193f415fa734a4c", + "tests/test_imagej_cache_environment.py": "0c3b854542257e09ec13806048ceb5cc3deadf1a6302c621f44c3bc4e6efa9c7", + "tests/test_imagej_distribution.py": "fa7740c10975dfbc2e654ac3b7fc0df0f2f08599a98966e51c2c046f8cae01e1", + "tests/test_imagej_runtime.py": "fb5ce7c8d53354eb46756644d3d0c135bbeae10a21a76718f67e458f046bf480", + "tests/test_lazy_package_exports.py": "ee015f6ea3c2dc198f522db1f494f886b892540750ca3289f7f39909c4700460", + "tests/test_memory_backend.py": "ac68a5bb7c0cc4bf6a74bf3d54cc3a75df2986b9f73e92af5316d878f678b16b", + "tests/test_memory_coverage.py": "a53b737d7899f52ccc0f683ae0312094760e532be709c17a5accba7249a60542", + "tests/test_memory_type_authority.py": "ec326f948fa957b0cc8358629199442db397b9676c884d6e730e23048468cdd0", + "tests/test_metadata_namespace.py": "5a4809a6024b6eec30130ec1bc98cdd6a2541779496cea717f8a89a98d5ca5c9", + "tests/test_metadata_namespace_ownership.py": "175737cbf844b620132bea2c5e5827ffaacac01bf53de136ea49ab32727428f9", + "tests/test_napari_batch_processor.py": "a62c8875fdde0bac50059aebc3b54dfb736246ba7e1980301ebb9e7124592cd5", + "tests/test_ome_zarr_metadata.py": "7444723fcc0bd0cdedd6d8b9454be57ce929caa61698539da55c782f0b7fb420", + "tests/test_ome_zarr_storage.py": "b70a93d160cb0ba0acfd603c75ade965fbf1f95158d7c0cfc680e6a8ce907deb", + "tests/test_omero_address.py": "15d81321402ccf015f5d687b70c27e64d58ba97e719bb090efeea74821e7ffd0", + "tests/test_omero_image_plane_batch.py": "ea857b139476e127a0ee026c20cf5ca918a65f45a70bc1fe27787313d6e830b8", + "tests/test_omero_tables.py": "45ab6ce56b95dfcf9b2c202e2caa587a67bd0de4769e77b36a9986b482cea159", + "tests/test_omero_text.py": "ddf16ee95766440f5ec4d3b0e60e159cc70b2f7694e7136ec13a72c85117ca88", + "tests/test_png_format.py": "f74821025f5d962a45287d88ede69793601725f6f158fdd9cb4c9635ad75cc62", + "tests/test_receiver_layer_inspection.py": "b1b153e86978aa31e933a26072be6e3a19f4881408d10df9044fe351ad0483a8", + "tests/test_roi.py": "a2f256e55483b45ce54264fd667452230ec1024ddb7f57432711b6be7278912b", + "tests/test_roi_region_properties.py": "5cac0122893d4df5289b2e7a14018625333103a713c87ae8c559872958ba0743", + "tests/test_streaming_cleanup.py": "2edca13d06e25936076c624fd9ff6db3b66d0997c08c41082c822a0b7e8fe8ab", + "tests/test_streaming_identity.py": "7d0256ce52d48d944961bad8dff436197c45dd0ac93c8946bc354aec0cfcabff", + "tests/test_streaming_metadata.py": "806cf4998459d90ed532307a48d0f793bfada277c69537ec031fd4e28babcb46", + "tests/test_streaming_receiver_core.py": "c79e5a32d46c39b6974d421bef2ec90099e67d6b6e13d4baa5eaa48588781548", + "tests/test_streaming_return_route.py": "e20baf9443d034ab18bfff0bfc38d60af7d7245e94ec0b7e01f80d8ce403c120", + "tests/test_streaming_shared_memory.py": "c5ecc8e9c027f5fa14783ce9e568b07eb3f39ddd07254e5fa2f9847d1a86aff2", + "tests/test_viewer_transport.py": "35f4e6ffd0bb7de1c5ebb1163e2d46d71f8dcbd0544fe3494e197c2d1ac610be", + "tests/test_zarr_backend.py": "7896159c33ee7fefb89976291e35db507acf282e92361c1abd86eca54160e2fa", + "tests/test_zarr_batch.py": "883da1109c08c53ddb5e03397e5e43bdb0f878c2da8ec4c4158ee9a70520bb17", + "uv.lock": "d4465b3bae7afc90311db1265dbfcb34fbca917c5c0b99da212902ef2463bbeb" + } + }, + "external/pyqt-reactive": { + "path": "/home/ts/code/projects/openhcs-shared-runtime-plumbing/external/pyqt-reactive", + "head": "ad4948775ab81180a354d4b793d17ee5ddff3972", + "status": "", + "files": { + ".github/dependabot.yml": "34790e08d06d30f3f06cf2f071fcb2430df398c0a70bf1d99b5cca71d69080ef", + ".github/workflows/ci.yml": "043b14a1d996285f2bf77abfe65d84286e9653fb1dc238030330baa256b7818b", + ".github/workflows/publish.yml": "eacab9aaf5db73c7dc4d58de7384b12ce6532382ef51736dc3bb6dde5e8f90bc", + ".gitignore": "348e5192909c25210099ecfa274a4be8fb5faee2fe96b47595b6e4f53f3eea89", + ".readthedocs.yml": "2f5648c67a8a1ba1db73ec8dc32fbb82ffb83b246671e1dade4cb8836d667c6f", + "CHANGELOG.md": "e2e6847f7981ad1a522894ae0e15ede7eeb59b3fdbbdb7b7d3b7a5b469152d93", + "LICENSE": "c5a804a1e4c08f5593eb8466c91dc4e871fe79319d81737a82a3cc514b7b2ff6", + "README.md": "59794f0817776c30f1ba9f82919c9ce29cc96203f0e95cc0bcdaa91c55542909", + "docs/Makefile": "43df277c1f15a11e9ab7180cfaa9e65e014571beec43b19530a363f4e62e0cd9", + "docs/api/modules.rst": "617c09bc67116f3a6ad8c737392fb483471bda2a3a29102f6dddeecea541a125", + "docs/architecture/abstract_manager_widget.rst": "ec6ca7a732c048649b8627b514a653ad050685d9b776174af7303877cf756c4a", + "docs/architecture/abstract_table_browser.rst": "3c6f2e9a7b6fea5e0e2015a1051ce1decc3f339ddea21292380d02112b704363", + "docs/architecture/button_panel.rst": "454f18ec0d2dcb906caeeab5bd504838420909ccd22e9ab1b93796ec8bd68847", + "docs/architecture/cross_window_update_optimization.rst": "3e2507130ea670ed92ff1053a4f55db768e4c45055613e4046251ceb1d49a287", + "docs/architecture/enableable_form_ownership.rst": "1d61d9dd8b3ab79f1b7780b4a5380e2b876452fcf80a09a7fe8e6ff0bb6bf99a", + "docs/architecture/field_change_dispatcher.rst": "93964ac421e2ded054a4c151cc0b2383be67d7b68d4d10b871fbc1f8be4fcde2", + "docs/architecture/flash_animation_system.rst": "fc005a4748e5e312cfe61232556a38b0b2855f31d50704fbd1b6373c1178124a", + "docs/architecture/flash_callback_system.rst": "f56f1902b4747eee31c2e77848de3662580810f4295781c0e8019d373b1b5951", + "docs/architecture/form_scroll_containment.rst": "5c3b46d864459cb5900a1be2b1147d93147c8e8e781ef2b97e55d86127ef9513", + "docs/architecture/gui_performance_patterns.rst": "0ae20c36992e6f5935ce3809d6edfb81e30750791b66d7785185ada00709cc68", + "docs/architecture/index.rst": "da94b32fe4ca3245ba69b1c8c0f6551885a0bca9feb1e61af964caca5e720a94", + "docs/architecture/list_item_preview_system.rst": "d7a0fbda2c99389cfc531fde81006bbd3a32d596d395112a1e6cb97f8f2d44e4", + "docs/architecture/log_viewer_system.rst": "335f4c93673eecb1e70705cb6499cd5072a504bfb607157b0f17003f9b4df2cf", + "docs/architecture/parameter_form_lifecycle.rst": "788a41edad8bee2eaa46299f1005ada60dacbbb748ae695362163d9ae45f0c16", + "docs/architecture/parameter_form_service_architecture.rst": "307b81c106e936ba70fee6c3e1fe47f97ebb5340896ccba20a00995ec14b76c0", + "docs/architecture/parametric_widget_creation.rst": "127604ce9226b48662cf062061b2bcc20476b9331a33d5f85ec09be5ee0b4dcc", + "docs/architecture/persistent_system_monitor.rst": "4f6248e3049912c30d68cf6a57eb33ee4a8d33f36dc76aac046f490296a0f0db", + "docs/architecture/scope_visual_feedback_system.rst": "8532d95d91a514612d4e12155bc47d69a9df6f0edddc6d1548914c7465f8bd08", + "docs/architecture/scope_window_factory.rst": "7b405c0ddce22b9e1d361d090fcdefb961142d1fc8d2d942390403c8061cd230", + "docs/architecture/server_scanning_and_polling.rst": "9f8540fe237778f095f5c177abeee77734ff3e2124b2a7ccf9b520ee2459cc45", + "docs/architecture/service-layer-architecture.rst": "69e14c574ab79eb9e2c03f825cbae889893cc4d471c4a499aef0fc2e23899211", + "docs/architecture/service_registry.rst": "39c8f6361b1bcc00be0532be5faa3355b8c5e6dfb3b992f51aad3ba82ff419c1", + "docs/architecture/styling_architecture.rst": "1f7dcd355460a1634f995d7f46c13699eb9dbf41b5528535c0d5fd7673ca36bd", + "docs/architecture/system_monitor.rst": "9b099a9c66f9889ae01f7cadfdc180a48c6be1c70bbc2ba78ff1001a9f75a0e7", + "docs/architecture/system_monitor_core.rst": "2f0288776c503fed3155a206dfe068dbc40675941e97c28499119247220f08af", + "docs/architecture/tabbed_form_registry_pattern.rst": "2e3c1f428765917a7e658b0687f544025a2e46ee2622dc77611702d874593b13", + "docs/architecture/tree_aggregation_strategy.rst": "cdc28440e3560170b20c8d600da96a3a3317f1c3ce285b5a72f8922081c4ffe9", + "docs/architecture/tree_state_sync_system.rst": "1fc2178f9f7f2171cc8a05d064ca3e8a8ff89c44ca9d735c67563286dc913d85", + "docs/architecture/ui_services_architecture.rst": "afa100e0281a8b93571771d2a78c85ce1d75c654268abedd4bfaac87eba19ccc", + "docs/architecture/widget_protocol_system.rst": "9382b7b91dbcd0953bf5e68e2bd93059c84d9b2337f9c6eef1ae0893322b361b", + "docs/architecture/window_code_documents.rst": "21d801e7e83e8d084144efc4a99b23acd48832783eb147f8d88fce39619ca834", + "docs/architecture/window_snapshot.rst": "2ae5ce2a50b165e79766c91f3efb09d55d6e14365de130bf646cfe4605fa97c3", + "docs/architecture/zmq_server_browser_widget.rst": "9b133796b0588362452be0c8ddb92e03a3f1a1578a0d2b0aadd96faf617b8e3c", + "docs/archive/IMPLEMENTATION_NOTES.md": "7ff23ba35575a35cab88851ed46075d9d92c47d34e87c9b9025aecf85b3e2fed", + "docs/archive/JOSS_READINESS.md": "395798c13b9764e131eb6a62fba73bce676f274e573b941cc1c6a1b04dbcb979", + "docs/archive/README.md": "34682a4046790ad3a59f328ed23cb88af9d34f4b649656847bf9863b340f337c", + "docs/conf.py": "2ef313507c9b6ce6941cbe82863a0373b818ea5627c9dec2824953ffc7f312d3", + "docs/development/index.rst": "fc0f4501f81b733702e21d79ca31d8971e9f2605620073b933f7c8147320c5c9", + "docs/development/ui-patterns.rst": "b017023d420458c9964406bfc050242d1f16a1032243492565db35c84dd2ded0", + "docs/development/window_manager_usage.rst": "8d4fdc1d8e3f7cd3d6ac9370680cd66d935f7338b6d249cb6401057feb86279f", + "docs/examples/index.rst": "89c204c6cae088698980aaa189fc2ca0b19f5f0eddbd818f9e8b042691e70fcd", + "docs/examples/ui.rst": "b3f370b8912e8e5ceb0f5510c46a53a5fab01de513b391cd3cfda2991839bc8b", + "docs/index.rst": "f14e5ddb3320bd277ab839925e63620c1f745c2dbbc0bb17460faaffe64cc464", + "docs/make.bat": "ed525cc4d41b62b8b96d4b62a44ef32d6ccfd9324a379a82d5f71b5fb6d57776", + "docs/plans/flash_performance_optimization_plan.md": "e7cc1c22050afed51b5fa908a4099a853e4cc62b86200ad46077b8ac9037ec60", + "docs/plans/opengl_flash_acceleration.md": "28fc4cacf5c19ae7990bcc7fd81a46e8172839ba880ad8a2d85ef2ce50d8afbc", + "docs/plans/opengl_multi_window_architecture.md": "4bf4e27a62cd9d3e61a0086d8b2edb1e6595df49ae3afe0ca379e38efafd383f", + "docs/plans/parameter_form_manager_live_context.md": "dea7242aaa7c9c4e30025a457e8e77927bb1725d8c31267be0634fb24a788aee", + "docs/plans/window_manager_usage.md": "7060816a81b449c2727b1f59cecf71cc7ca5cd536a372828b178104c3e394da6", + "docs/quickstart.md": "98777cb7438f6c72d7443227e92d9b1c4a079971c7e5c6b4ac51c53baecb0b9c", + "docs/quickstart.rst": "25e9faed76719ed6d0ed95ba2416f002e3f0adcb048a605d19b57867e5ec1469", + "docs/responsive_layout_widgets.rst": "96c737263e7ba05cc2e6f21be65ead024e0d894fe6880d30c9ceea351e329156", + "docs/state_management.rst": "c23255071cf550b481797dbc91a406219be4493faca7eb835b8f02651026650d", + "docs/tear_off_tabs.rst": "fea9c04ab60cecbd54aa3b43cffda6f26d6c29ebae2ada6e3999a859bca2ecd7", + "docs/undo_redo.rst": "0cb27f79befce8a209468c86aa120a03725d1bcbabbbf055d27af06ed88169c7", + "examples/tear_off_tabs_example.py": "5506bb39a1953d99d1a8b730851a53233dddd79aa0a4cc738f422fad10b2d640", + "paper.bib": "67e65471f9b4f38e0b4beecfd7cf8b7c2ed815f7b8abfdc680e63262c3652f91", + "paper.md": "b305c23c401bc8ee17d0b1049727c867d86f2bb5c44bc51a77640e74a6c7867a", + "pyproject.toml": "524865db6ac36de136ee2b8dd43b1c741152f5ade3f8195f637650d252dbf8c2", + "requirements-ci.txt": "7da9971ef9b437b35bd507d1e35e09f37d39b4c16b4ef09c9b9a6849d20fdb04", + "scripts/benchmark_form_construction.py": "a2597d87f99c5ad0859e66732f7f7e43a73b4c896b3733d2ee9d501227d1a3d9", + "scripts/check_ruff_added_lines.py": "67ed9e6064204caca990b7b7054cd0774f59b235e241a4fa46db28ad48213ad7", + "scripts/release.py": "09fa8c9c7ccd7f4936aa9a9994b6c47726ce27e8bf99e0cfdcf06d528ff4565f", + "scripts/update_and_release.py": "80896e49f856d6a193bb1dc3917f55d2878acf1476c8240333eda16b92e8e61a", + "scripts/update_version.py": "3f771c59e65b5f6674faef3dafa3b660f152b58ea61114ae0a37f840a9ce4f04", + "scripts/verify_release_ready.py": "7a023ed885a132d922f1fd3942dd56b66158958192f7e5371e838c537cd5d2b5", + "src/pyqt_reactive/__init__.py": "5b37a90f246987a98087428e80d2cbdcc030b80ae962c347482f21719054f68c", + "src/pyqt_reactive/animation/__init__.py": "f449133ede280b74aec90dc85e88a9a2800e38c45b239996d9abde51d0cee6d9", + "src/pyqt_reactive/animation/flash_config.py": "efc6859a2de5115775a940be0a9e1c5e58f7e60e068872f11a256060b045fdeb", + "src/pyqt_reactive/animation/flash_mixin.py": "37cd2b32047109fc16255a3f9a9938ae553d5f8bd5987cd10460c7ba500f1486", + "src/pyqt_reactive/animation/flash_overlay_opengl.py": "f6bc6452e56cae0a17b07244547b55820c091fa20615de3ab1a8159f638f1dd0", + "src/pyqt_reactive/animation/flash_trace.py": "9a2e71467be16a31e0abd1f7999253e4842447289400d15cd3ff995fd06af9a2", + "src/pyqt_reactive/core/__init__.py": "c111f382ba9945651f0b385131896ea2ae522141f7a91f7a1e1eae9657e97122", + "src/pyqt_reactive/core/background_task.py": "4afa0d07107479f028557d23f15a6c5146cdb9f33e253b81f856f9092824c2aa", + "src/pyqt_reactive/core/collapsible_splitter_helper.py": "8d959845294513e0240c994c1bd9142a968f682be994cb2e3fd02f38f0403c3b", + "src/pyqt_reactive/core/debounce_timer.py": "7c3bcef0d7dc0107df0d413f6188ece136e3be5cfea473e3e74b69496af95763", + "src/pyqt_reactive/core/deferred_callback.py": "b52167f36cef2e58bc0f6b38c15359cbfb28a12a71c3a41ad9ac62155f357803", + "src/pyqt_reactive/core/future_completion.py": "7ba6ef203bae81319004ccc4ddfe4226e0230b177df663cfb0d02c364e1dbc47", + "src/pyqt_reactive/core/log_utils.py": "8a2f67434497cf5bc3d637b945b75590c735ff8d97b8db56f9efe5bbaff5e351", + "src/pyqt_reactive/core/path_cache.py": "dfca58e2ae9deb036d4df4038ce8f78125cb5ddeb2e691293bb4d54ca673b586", + "src/pyqt_reactive/core/performance_monitor.py": "09299865cc6641b87bdc195442a297d982ee3909b35c8d2063859933180834eb", + "src/pyqt_reactive/core/reorderable_list_widget.py": "edbba72d7aa88362860b923c0b86715a8349dfec9a7d85660f12cf33d859429e", + "src/pyqt_reactive/core/rich_text_appender.py": "fce3d7be3654c988f6eb16117231e6032718b28608f99f625054ff60269768a2", + "src/pyqt_reactive/core/sort_utils.py": "ac9cb5bd209113980dc398197f461e19e6c9716a5110a889bfdd7bf7b85f3d81", + "src/pyqt_reactive/dialogs/__init__.py": "a9ab9bde099f50c796b1c29c77482f0bf771591fbb12514f1b9ab8dfbddeb4a9", + "src/pyqt_reactive/dialogs/group_by_selector_dialog.py": "a62fdc652c3ff9fe2ac3babce17968a5786877e38ff5b6c2a10ea0678d5a5e67", + "src/pyqt_reactive/flash_trace.py": "c0110553bed7908221c10d1a33e48f4324366b047eda75f5b2561b68f5855063", + "src/pyqt_reactive/forms/__init__.py": "5c9c1af2df09c479f1cfc50fb8d8ee7ff3e157a940d137fcde8af95c95d035a5", + "src/pyqt_reactive/forms/form_init_service.py": "4d34e5f2494a075f9aac68e40c07b07cdb06600d832bd5b510ee971db980b82d", + "src/pyqt_reactive/forms/form_value_validation.py": "ec3ca9d48168b651e8fe0b0ef6f90a67ad32f145332a8798f1cfad220c9fd597", + "src/pyqt_reactive/forms/inline_dataclass_chrome.py": "5d224ea256bffbb840f380d9ad75f9f98b7c3ed18fc4b1ba4db0b64f92a428a1", + "src/pyqt_reactive/forms/inline_dataclass_context.py": "c0d7a19651dc1b88e66b656a031b39a7aae67ff8998e50cc4e5962a184f4fb10", + "src/pyqt_reactive/forms/layout_constants.py": "a16ebe77ea6fb5d6c26d658bc586dd8357d18506c0935cb6426edbffc906ff98", + "src/pyqt_reactive/forms/object_form_document_renderer.py": "c47fada4032d685b6bf7dca4cb9f31e4e9240a25bd1039b165b045d5de541f1f", + "src/pyqt_reactive/forms/parameter_form_base.py": "f35bb8ddd6c630a47cc5095df93ffee608a384abadf755b2f0cf12bcc963b36b", + "src/pyqt_reactive/forms/parameter_form_chrome_sync.py": "94fda5faae9adaddb1cddd1b7a4d3b0452906828d94c582f6024ff72d89ca4a3", + "src/pyqt_reactive/forms/parameter_form_constants.py": "4d4ae05b91d525108342a10e9b2da7860b5a52b0028612f244339d4531d02097", + "src/pyqt_reactive/forms/parameter_form_manager.py": "a561e62e29af42630fa107b0929fc87b74007f7ed14ec8f0a6881c49070dc923", + "src/pyqt_reactive/forms/parameter_form_service.py": "0cbf305c99b0d7ab0c558162ba5d86dcd18f81eb8cce0ad271fbd4b3d15ebc89", + "src/pyqt_reactive/forms/parameter_form_tree_index.py": "e343c3ae5535bbd46dff964844225df13fad5431253eb3924b86f8c8d1dad273", + "src/pyqt_reactive/forms/parameter_info_types.py": "3f87562ecc9b1a4cbf541767ae39d53e1b2dcfe71d9a5e211456d8b34a0a75f8", + "src/pyqt_reactive/forms/parameter_type_utils.py": "c7fd2f17faa1e3d5c3027179135de51b859d204c4a2cb9f9be10837652530ea6", + "src/pyqt_reactive/forms/parameter_value_contracts.py": "109b82548f6a90e1d495d825eeb81309b555b6122db67867a2c91769e9c54f78", + "src/pyqt_reactive/forms/ui_utils.py": "96521f8a8b75f501ca9f2dd34f377025a7d5fdf543dcbed84ec17939875ca0ec", + "src/pyqt_reactive/forms/widget_creation_config.py": "01f32efb0dadc4d5e1a42344f43e7704c47468844b4a05bd13936e490ad4489a", + "src/pyqt_reactive/forms/widget_creation_types.py": "3b1c08a0a94334facb76afa273fef0d247a93f748ce86c3fb9e7026d46ef844f", + "src/pyqt_reactive/forms/widget_dispatcher.py": "5b13da9b2aee79344c343ddcbc296f125429c9780696ed35f996e982c3ee1562", + "src/pyqt_reactive/forms/widget_operations.py": "708bf6dfd51c01154e02210abe8840eeb496af51db57cfda425d51a365080b72", + "src/pyqt_reactive/forms/widget_registry.py": "6529d5879667827e7c6adf36129e6dfdfa18239c4e0ae32bec27eab7b03805c0", + "src/pyqt_reactive/forms/widget_strategies.py": "6eb7fc78526a247dc30c39493f36f54f2df5560b0af63d743d41b30b4f469384", + "src/pyqt_reactive/pattern_metadata.py": "7c2aa3f2660d530503acdbf8e122711cf7b3d1c0aae2d05bf6addb7091dcb4cd", + "src/pyqt_reactive/process_launch.py": "c324a6bcc3b5002bd4e6e5db184d4fd80bdcdeb7b130565ca52eb37bbaa08f9e", + "src/pyqt_reactive/process_signals.py": "8b4c44c98d6979fab6935485ea94d64bdfec6eb0143855078628451d4cd9ce82", + "src/pyqt_reactive/protocols/__init__.py": "2f59ae586807161ac8d019d904646684be0cc458b8b4bcef66f3d233002fd294", + "src/pyqt_reactive/protocols/codegen_provider.py": "98c030fbf5fc99ac8ce53bba0305f0591e0b1a12403b1cd22dd282d1df476fb3", + "src/pyqt_reactive/protocols/component_selection.py": "a68d8ca325a0972c7e911901a47521e44882699729f98bd4cfde57cda7b4d1fb", + "src/pyqt_reactive/protocols/form_config.py": "cfee9524e2e2c92fe1317d9cf1229580df1e1c04a45d9583c4b97fde1b3543e2", + "src/pyqt_reactive/protocols/log_providers.py": "c6602cec12dfa687a6f4e122aa62ebaf3ba7c5472a0d63b29ab0af9db3c18514", + "src/pyqt_reactive/protocols/preview_formatter.py": "05ed6999327cf4483a79d3bb5c9d1f1bc231fd3c0a33026e1e7069f1e8d3771c", + "src/pyqt_reactive/protocols/widget_adapters.py": "1ae6653bf3f2786eafa9f53f246e145ebfa34b81c190aaa8f41c19a1463a42f9", + "src/pyqt_reactive/protocols/widget_protocols.py": "4877e65746459f556954eb718d276748fd5211d244e15f1e92973e5ee01c24d4", + "src/pyqt_reactive/qt_types.py": "cca393ec5c0126b296c2462b414a84acd0cd1b5f63de9a2b6112a0b6593921b7", + "src/pyqt_reactive/services/__init__.py": "9ec1b77dc39cd6e0f550e7ca014c4e6a560ac0fa46f071c0f6ea47a6a34fe46a", + "src/pyqt_reactive/services/async_operation_executor.py": "f1252a0244f816b2187881bee484776ebd41529d1a17df08a1360967d4e03516", + "src/pyqt_reactive/services/coalesced_scan_requests.py": "5a565f9ed1bf34871f2802400fbe6b9ae7623cc612f07dbde44df10e92a1fe21", + "src/pyqt_reactive/services/enabled_field_styling_service.py": "0a16f22878c4ff68a3a75c937ad50314a0acf14014ceb39bf2420673a75e01ac", + "src/pyqt_reactive/services/enum_dispatch_service.py": "20b18b0ef51d7ecdab99e3fe0fb20fc38c605ce80995945f5e1033e24bb4bee4", + "src/pyqt_reactive/services/executable_action.py": "6942ff087473fc102c5395184aa74c8b6c8088cab5d7fa394bc5e103e41c5d28", + "src/pyqt_reactive/services/field_change_dispatcher.py": "0875f01a405b95de12cb0d4fc396d959a758d67a39c211d3056c512352d0f1c5", + "src/pyqt_reactive/services/flag_context_manager.py": "88b634b8aa899f82f6e9525101ade1f60b0be11763a33908ed3ad23ad3bfe147", + "src/pyqt_reactive/services/function_list_editor_actions.py": "68a0fe00e8b80cf1154aaa1545725b48b0c4b75e338afbcd23fed159d6d100d3", + "src/pyqt_reactive/services/function_navigation.py": "47664c983d2f515f2c4e6599eb4fbf269817e69f9abe68101872e6380ee60e85", + "src/pyqt_reactive/services/function_pattern_code_document.py": "bdf41b58bff009890e6e696cfc4f18313adfb1669566b2566f9e7b93d863c071", + "src/pyqt_reactive/services/help_document.py": "c0c1973e7ab02823c204dfd7003ac2a2b44acea36b895a82604ac31d0f4db1e3", + "src/pyqt_reactive/services/interval_snapshot_poller.py": "77fcd5b147bcf66782ebb1bbd6a9e9a8379c9e38672a47fd14fd2432eeeed11f", + "src/pyqt_reactive/services/manager_host_abc.py": "a9a3ffc9b2cc2c5d6f6b1224c89838f74bc9d41d2c8de8da39bf33f98483b90a", + "src/pyqt_reactive/services/parameter_help_service.py": "422f9e7b818f855f28979400512b4943524606827a74bf807bbf26afef1a589c", + "src/pyqt_reactive/services/parameter_ops_service.py": "8814b7c13bc56a2b0d3f69fbfb2a6153b4e2b5d0433779db6ffce5ba480890e7", + "src/pyqt_reactive/services/parameter_service_abc.py": "c5818d83e39444cbd88e135e2a075e45872d49f8c83c34e1d0e925e7de38d387", + "src/pyqt_reactive/services/pattern_data_manager.py": "ddcf9659dab6ee50ea3c155f57e1a4111a97e414ecf74b58151da1ef6557ac88", + "src/pyqt_reactive/services/persistent_system_monitor.py": "2041aaa91a3e242bd43e1686a65feed89078d18f8f7626bff00225895bde0007", + "src/pyqt_reactive/services/process_tracker.py": "5850b647c4c75ab2ced0ea91be34fe99b8e1a004cf3b2df597caa7769f7bc899", + "src/pyqt_reactive/services/scope_color_service.py": "b9d958c27205ca5a9eed16dd729a354642d90bcca96a519b01a0b19d94b1c822", + "src/pyqt_reactive/services/scope_token_service.py": "f84056a6b542d1d9a7df9e05c2ec344d6acb7cafd3301054158e89f04eb32b17", + "src/pyqt_reactive/services/scope_window_factory.py": "fc2a4606f89c85d44014ea6d08018e34921b8898816d8a09ca8febf80a448338", + "src/pyqt_reactive/services/scope_window_navigation.py": "39a0b4e95ce6e9a478c5882b91aa0822f53b683c9f2a706727bbf88922679331", + "src/pyqt_reactive/services/search_service.py": "e72ef88fdaf28d069bc80c2eec722ffa6921015613815929006fa35fd7de2054", + "src/pyqt_reactive/services/service_registry.py": "8f6dff4b7e6db9eb4ba2a0944d18cfa3c03b75e9cef85594b1e8bc7c5bd03e58", + "src/pyqt_reactive/services/signal_service.py": "04680bff5098b52edb1f4998356c1ef9543bcca96b3f37a7377ce4f98c1f18b1", + "src/pyqt_reactive/services/system_metrics_sampler.py": "7f0df0d9425a9998e371c86f55a27cc492fb71b36817ae07b6280f73e25b8ad6", + "src/pyqt_reactive/services/system_monitor_actions.py": "2aa205be430ff8b0429279a3ec44e5bc0c672b6da7a246a208f1ed40b79aded3", + "src/pyqt_reactive/services/system_monitor_config.py": "2f7259cafbdfd28f19d2a291afcd2deeef4e5eba2402bfb0e303a0aa643d6dd4", + "src/pyqt_reactive/services/system_monitor_core.py": "1712ed50c76e6303dcb96f65c8294922084bf2e3f90d21be56b766abca0dd39a", + "src/pyqt_reactive/services/tab_identity.py": "48274c530cd0792b3565c1becf1cef9c90d2f48b4e6ccec26cdd8807c51715ff", + "src/pyqt_reactive/services/tree_item_key.py": "e908f21bd6cb1621cd8356611f1ea0d7daa59d19171b211f3c3038598b8a5aef", + "src/pyqt_reactive/services/ui_thread_dispatch.py": "f2dbe7e8ce8ac0ad3116001d7dfcd91affd516a34615775ce4ce9921480e40bd", + "src/pyqt_reactive/services/value_collection_service.py": "33562f9b50e1080a26c28467ec31c3915e5f734bdc237cc04f4802db2b36b911", + "src/pyqt_reactive/services/widget_service.py": "cf3248353552db77b3257cbcf982987848fb16acd38ab2245dbef1fcf5e25223", + "src/pyqt_reactive/services/widget_tree_projection.py": "05d5221d64e74ff14483f203975f17543381d959c30ee5918c200fa8e9957547", + "src/pyqt_reactive/services/widget_tree_projection_config.py": "8f616aa3f2fe1dc88077dc612cb7c527970363692c6a8ace15b92ba56a806e4b", + "src/pyqt_reactive/services/window_code_document.py": "d0ab321af0eb2b14fac3ab2577c8c61672763d2f13a70a7ce8a35ee7bfab7c75", + "src/pyqt_reactive/services/window_manager.py": "84fff75ff74e59c5d7080f103ad1a4baa2c884aff3d2f87891a0afdae9a5c332", + "src/pyqt_reactive/services/window_navigation.py": "88da77ed07ea220b7c6874e71029b5bd50805fb2c3048701f9df773fe17257f2", + "src/pyqt_reactive/services/window_snapshot.py": "bced886e6bbfd69ae9bdebf950027b809e72c23eddadcaa5fcf7151adf7ae913", + "src/pyqt_reactive/services/zmq_server_info.py": "1050f0e9ada59580eba9a6c4a703678f0945f4a2cd83df4fb32251733911b81d", + "src/pyqt_reactive/services/zmq_server_scan_service.py": "ae12092dfd8b85a3354b87a708f3c32aef787c2f9fd0402158d32d14b654c7de", + "src/pyqt_reactive/strategies/__init__.py": "cab5cb18e271d822d459ab8b7f6427f03b8beee5ac9a4d04b4b73a0914d58e9b", + "src/pyqt_reactive/strategies/preview_formatting.py": "dc1a423246ca40f13633847d5d3ffde3916e53c1a8a8a92de893d3e80ad8fda7", + "src/pyqt_reactive/strategies/status_presentation.py": "435d97f7804e2db714cf60b236074c7a56fc87542b05a4d7a4b1722a340a7893", + "src/pyqt_reactive/strategies/tree_aggregation.py": "d28be44b8472fe1db805fb706485f02bae2c48d99e41f422dc534d24e0084c5f", + "src/pyqt_reactive/theming/__init__.py": "ddbd3f379805b6ebc01a86c86ba41999617b46498b4436563e5a427afea3866d", + "src/pyqt_reactive/theming/accent_chrome.py": "2ae2fd7cc5b3d2b60a99942792ed0621040339e117338107be01fc6128b36f86", + "src/pyqt_reactive/theming/color_scheme.py": "45f621f809accb5dd3fab03c1bbe95b43d680e6b4e03680e89ac2fe6400f16e4", + "src/pyqt_reactive/theming/color_scheme_resolution.py": "e8c9a7501268979d0fbb3e02f693b31a63e08688e80c3cb23abe0a856e1de09a", + "src/pyqt_reactive/theming/palette_manager.py": "00b81b76f39b561eb7a4bf37d0547bf2db6e7b63efa18ef752f614005f56be90", + "src/pyqt_reactive/theming/style_generator.py": "7433368f14efdefa05a401501122704c08f061412a343531fba5400a5807c885", + "src/pyqt_reactive/theming/themed_checkbox.py": "93426143261ca2c1da431264cec69e89ee76a35d7bf85d9e54db27e72c058ea3", + "src/pyqt_reactive/utils/__init__.py": "6b8f0030c2822411d7efb3433a2276320b985423ade229529196cf09fce17e3f", + "src/pyqt_reactive/utils/log_highlight_client.py": "db8e2fd014eedc85af1d0805250931f74257a402651edad2bedbc4588cc82f7b", + "src/pyqt_reactive/utils/log_highlighter.py": "e38237cfea9d757910a7b4ac84a8095068ea1c4531abd56c6fd15228b40e4703", + "src/pyqt_reactive/utils/log_loader.py": "c0cc1d6e4c7ac286562e2659b327e738f3cbed32686c09292b0d957ea61d159d", + "src/pyqt_reactive/utils/log_streamer.py": "ac195bf633e690695d61c1ea4cdfa7bcb45a4ecc20dc237f35bc220a87a08669", + "src/pyqt_reactive/utils/preview_formatters.py": "76a383c498300e2672d6b67ee0261e0dd90df0ed2fd64fc2ffd3513cdf097838", + "src/pyqt_reactive/utils/scroll_filter.py": "cb38375d28d5613f162dc020e2b8735824ceea767ae5cc1156c7086240e22fa8", + "src/pyqt_reactive/utils/styling_utils.py": "22d32d0e01fca8f575c15fa4a61b27cde2e46616cb86088733e8d15f312a1da6", + "src/pyqt_reactive/utils/window_utils.py": "11b222927102bc79d8a5f6a957bd99ab1e828bfb6586e1d647aebd564b99afb2", + "src/pyqt_reactive/weak_events.py": "446b5ea3e71eef459a2afd3663aac3e05a4242c6e9e21379f79fadf9563202c8", + "src/pyqt_reactive/widgets/__init__.py": "ddcf678b0dc5c03aaf11d2b6f12bb9cda681a29f0105925c51a5b9263d751716", + "src/pyqt_reactive/widgets/editors/__init__.py": "6fdb2746dd03af27487402eddb929f4f10664f6dab82726dba5894dee8d33878", + "src/pyqt_reactive/widgets/editors/simple_code_editor.py": "b84df51fd669c550dddfc5484e178f585d7b05f9ca3b230cab6bb82b3d0ecdab", + "src/pyqt_reactive/widgets/enhanced_path_widget.py": "5c72029a13fcf4e58a99ece7bb898afebab083f20c104f9255082b5f9ab1b232", + "src/pyqt_reactive/widgets/function_list_editor.py": "3a71a7af92cd6a3e304a030f7e821710af53cefb63c9e13cfb331c61b86d48b6", + "src/pyqt_reactive/widgets/function_pane.py": "da0f781f1948df80c856751fb6ca5f552583395d0f5b2d2beaa83d03738e1abf", + "src/pyqt_reactive/widgets/help_document_browser.py": "f8f0bb2e454ef458f2fd4f686f4d6814a717e8f1da0de1790ddb6f8a96795e8a", + "src/pyqt_reactive/widgets/log_viewer.py": "e68eda879c7cd3f5360dd1b4a08a481298cabf85cd72bdfda66b0efbd54d56f9", + "src/pyqt_reactive/widgets/mixins/__init__.py": "fc5176659b1c3239954ce3257c3615c5053c65e233ff350c869da5a4a356bfb5", + "src/pyqt_reactive/widgets/mixins/cross_window_preview_mixin.py": "663d644a603e6da4a07eb06faabc7f4eedc21ebab392094b3c76fa2f0abb3117", + "src/pyqt_reactive/widgets/mixins/selection_preservation_mixin.py": "94fc92d98854f4bbc611fe616033abccea19ea401ef9a3e9c53ea1017a77bd66", + "src/pyqt_reactive/widgets/no_scroll_spinbox.py": "f6be116d4976fc8a83ff576ef6ca0968ed95312b6333631a7705727dede10cfd", + "src/pyqt_reactive/widgets/shared/__init__.py": "e7525c16a67b93240ce3597d7f6e6b7b9bc9841d6e4b2de1084d10fd6aea2c4b", + "src/pyqt_reactive/widgets/shared/abstract_manager_widget.py": "92f8ede35a48392112c6c1aa17e959c3cc4a9450e69f5b1447cbc4ef5498dd5b", + "src/pyqt_reactive/widgets/shared/abstract_table_browser.py": "478feab4d742bfbc4170df25e5e3cc3bc0b409506192290817a064250dd9ff5d", + "src/pyqt_reactive/widgets/shared/action_tabbed_window_body.py": "246128cd317deb382bf830a67fc6468f768e6e5547ff0e17896b16e304371ecf", + "src/pyqt_reactive/widgets/shared/base_form_dialog.py": "9b5280ef06b1c8421b3889c1c477fb311dca3b5f960e8ecfb58a0a7812551369", + "src/pyqt_reactive/widgets/shared/base_managed_window.py": "3fda59f66502bfb9ce14565981f2c8738d074c78a08ae3afc9c8e00e93c882fe", + "src/pyqt_reactive/widgets/shared/button_factory.py": "78b69f821ad925773ca049d0c08715375a4d38eaf7ed075701417401b461a14c", + "src/pyqt_reactive/widgets/shared/button_panel.py": "280f904f101681461a8899b0dae53fd10e0f616e54511ee09c3324c2a589ee43", + "src/pyqt_reactive/widgets/shared/checkbox_group_widget.py": "593b9a2c1358556c710a9a3b406042e6e335cee5c46aff1e1ef42e5025c36a4f", + "src/pyqt_reactive/widgets/shared/clickable_help_components.py": "c480f45796f893e8f9431198a0d08f5acfee3ead9034764005587aae88902e4d", + "src/pyqt_reactive/widgets/shared/column_filter_widget.py": "7e492ba7cd8d2d91ead001be293bdd69dc6a98332102e30ed45d0bb6968be589", + "src/pyqt_reactive/widgets/shared/config_hierarchy_tree.py": "150062486b1e4d092ce703cee83a3d400097267dba3670d9a0120378f0045b34", + "src/pyqt_reactive/widgets/shared/config_tree_contracts.py": "8e6b4b0047219c2f7c8297de1baf7437b2571016bd2d82e1f2e1c520bc4a35e0", + "src/pyqt_reactive/widgets/shared/detachable_action_bar.py": "37157c0874e5495d3fc5c4b33042d6334b439a57d912e354ff48529e1d434ef1", + "src/pyqt_reactive/widgets/shared/dirty_window_presenter.py": "d0171ce0b9009780675f8eee0b528fe3fd2446c8b800934a476778e1c554a147", + "src/pyqt_reactive/widgets/shared/form_window_action_header.py": "18725af2a223d9c00b2496f298f745af1628c5e0cd07a2cbfc8e39b684b574c2", + "src/pyqt_reactive/widgets/shared/function_table_browser.py": "654c394929b744ca3fd6293fadfced3966d64626ddcf5f8b74f46e63cf026340", + "src/pyqt_reactive/widgets/shared/image_table_browser.py": "3a9b45805225021f6f17174e06985ab19f75b473bc0dfbf3ecfa7a5eef9931e2", + "src/pyqt_reactive/widgets/shared/list_item_delegate.py": "282c8fe0c88f9bfd51df7eb95c739a8d428d2e9d99478796bb073c698f5907a7", + "src/pyqt_reactive/widgets/shared/list_item_text_rendering.py": "0d997923c78dcb363748daf685cdc4e93ef5d6a4ee1f7d74100cd5266cdc5220", + "src/pyqt_reactive/widgets/shared/manager_action_controller.py": "e21b2407ec7cf6f891a7a67b2ae554e741f4a16aa35537b31e3b9992c009b317", + "src/pyqt_reactive/widgets/shared/manager_item_access.py": "21540ce53728a72028cc3c9af770bbca5210aa7c18bd4f697cad42bf5d27b276", + "src/pyqt_reactive/widgets/shared/manager_item_display_builder.py": "fe1d01ba449c69a052ed796e9c6901b080e2982b565f3ae0e0d73ad6599da45f", + "src/pyqt_reactive/widgets/shared/manager_item_hooks.py": "3dbb99e17114c9869db7a4cdf9284574921f4865e10f90a2161877c41da6c222", + "src/pyqt_reactive/widgets/shared/manager_list_updater.py": "c7036bb3f37198b06f5af6859c7bc6d9a0a85520da126286d31f00750a93b50b", + "src/pyqt_reactive/widgets/shared/manager_list_visual_state.py": "ba8a54d4b682d7bf61c2286439894d59eeddebf160102f4367038866cb54a2bd", + "src/pyqt_reactive/widgets/shared/manager_preview_formatting.py": "b9057f97f87f757272027baf402740db99da945fb04a4985ad0df5dc11f29b24", + "src/pyqt_reactive/widgets/shared/manager_reorder_controller.py": "64c829c64193e6cd1b604fc883fc0406fc43ecc329adc5066fa93196e2d67551", + "src/pyqt_reactive/widgets/shared/manager_selection_controller.py": "900fcec4c0a8e61b60130cc7a53ef8b0fd157d906182f96aa85fe57e5f008d46", + "src/pyqt_reactive/widgets/shared/manager_state_binding.py": "5fc9598ab1319cdf7048ab4e20c36c9d4c64d6ba7da584efc039e6c333cf888b", + "src/pyqt_reactive/widgets/shared/manager_status_controller.py": "b0e9fb4010775206b9b66889115be864d22f8e060b67bba2ef30dc0cccca4f9c", + "src/pyqt_reactive/widgets/shared/manager_time_travel_binding.py": "4cfeeef4badfe945c8ce2bd0e86254251fe79c5884261ac2d3f07c649ac3bda3", + "src/pyqt_reactive/widgets/shared/manager_ui_scaffold.py": "1332a8b69c8c562fd49146ea29a6b9aa5e156c90db06a00731e7716788e84589", + "src/pyqt_reactive/widgets/shared/manager_workflows.py": "e9e107b3129aa6f8725031abf35b2a67a52840643efdd120554ec78b13ce157a", + "src/pyqt_reactive/widgets/shared/reflowing_vertical_scroll_area.py": "7b04fd0dcd92ae470f9b6e7005bbae811ad3a614ddac86592381d840269c4387", + "src/pyqt_reactive/widgets/shared/responsive_groupbox_title.py": "a195a584afe51c456b35038a55d63c9e8cef708ca559df01d6dbbe42e399db0e", + "src/pyqt_reactive/widgets/shared/responsive_layout_widgets.py": "4adf600b914cf0769ca37c490523f744ac5fc2e5809028a6a24f21661e05359c", + "src/pyqt_reactive/widgets/shared/scope_border_renderer.py": "ab5a8246f3ca1d88bcd935f76fe59a33782e8ccb6944aff943386fe06fc46268", + "src/pyqt_reactive/widgets/shared/scope_color_receiver.py": "8b75714a16d6cf90d0f55c68f2d7d0935b0a1fa906ac2fd659c3409406568905", + "src/pyqt_reactive/widgets/shared/scope_color_strategy.py": "aa53231e9830e66721ef637177ae1470403cc9a13519015babdec8c824febffe", + "src/pyqt_reactive/widgets/shared/scope_color_utils.py": "d4c317df9c3d1391c3f8768b2bbd041435196cc876f16be2f929b63cab8aae10", + "src/pyqt_reactive/widgets/shared/scope_style_applier.py": "cd649a820631ceb367444c38ef3722489308147f9857f451cb95d5373d9ee763", + "src/pyqt_reactive/widgets/shared/scope_visual_config.py": "51286f8aa2f960e9d656f11f5ee57a11f1b2e1213511d0d17b46ad7be3b6fa4a", + "src/pyqt_reactive/widgets/shared/scoped_border_mixin.py": "f291c293302adf863574b6abf398605687d0325a8e3af16c37abb929d3fdbfad", + "src/pyqt_reactive/widgets/shared/scoped_table_widget.py": "cf81e6a8075ae89b10a46dc0e262de9f465cf5a0cd25a915dadb91dc0601a2b0", + "src/pyqt_reactive/widgets/shared/scrollable_form_body.py": "5a00352eda3b8e7932a878c18ef6ceae68a58358d15987dd8155702b70afd20c", + "src/pyqt_reactive/widgets/shared/scrollable_form_mixin.py": "e1ac397789a515097f464fb72b9378ba91e5dfbc6bfb6c316054049004fdcffe", + "src/pyqt_reactive/widgets/shared/styled_text_layout.py": "f174770e600b58e9d7b22f10db7a7e176d11207d534d090926e747af2ab594bd", + "src/pyqt_reactive/widgets/shared/tabbed_form_widget.py": "f2914db1586963f3dfe3cda7d6940d13b2bbb7ec1ffb4bb894c3844443b34a4d", + "src/pyqt_reactive/widgets/shared/tear_off_registry.py": "b44b1d391588d2290ff50b7f73379a875698e61de926e2ea153470744399091d", + "src/pyqt_reactive/widgets/shared/tear_off_tab_widget.py": "6b4fa8aebd7134cb2451135662f6b9aaee39a688c7b3ad8b37639985c7447fc7", + "src/pyqt_reactive/widgets/shared/tree_rebuild_coordinator.py": "deb28fea82fc963f999876dc54b37a4d0e310995bb16a1892befebdef79eccaa", + "src/pyqt_reactive/widgets/shared/tree_state_adapter.py": "ba4877d3431f4cfe344c530493b934b6d181254492070ca210fdcf2ed07f148c", + "src/pyqt_reactive/widgets/shared/tree_sync_adapter.py": "0031145c849a7ab6f2c4787bdc44692306073f08b2c17bea9b12932c45698f07", + "src/pyqt_reactive/widgets/shared/zmq_server_browser_widget.py": "35a7bc0ce56461336967a2a3f2e357edf8ccae122beb179d9dd438c86df105ae", + "src/pyqt_reactive/widgets/status_bar.py": "7acd1e194c1bdb350e2dd288adc9c55a37b1027fed97df0c5fb3e77ed794c940", + "src/pyqt_reactive/widgets/status_indicator.py": "96cd497e82336c02feec80dcc7c1bbf2e81336055e5b933f1cd1b96b240a0489", + "src/pyqt_reactive/widgets/structural_table.py": "4a757027ced7529f7b4f7737c09dbfa2d9dda48e7944b5375566299d3315f346", + "src/pyqt_reactive/widgets/system_monitor.py": "620f54ccd75eeeb0e370db4d461cfbf82f3625b898d343bb7c214de1cb5d671b", + "src/pyqt_reactive/windows/help_window_manager.py": "3946e3c1f7a99e75f86c87f44fab0af1282454dbf58dc95db14bb5a3fd66c7d2", + "tests/__init__.py": "db6cc46f8f6d69c35c72a39f4829527f661a63d906f091bc59a2055943a43281", + "tests/conftest.py": "911c65976a80aa48405b9c6bf0b18830599a2185c05434cbef8b7c25c4a48b39", + "tests/test_accent_chrome.py": "0862933afb738e2866611167a7c70e412d15e72ea46f9712a0b641587cadb709", + "tests/test_action_tabbed_window_body_lazy.py": "6f5b16efb53510e2a2806e1e412d89438c5e93c4efa5a9568439daf5a9daf9e8", + "tests/test_async_operation_executor.py": "2c8bc81bff7a3fd8879b6b79d2e9e09a3a22610fbb3785d970400e5e55dcd84e", + "tests/test_ci_action_pinning.py": "a636dd4d70e231d06c5de2802afc89c389f678b3b49a40ce8463eac5b0c308dd", + "tests/test_column_presentation.py": "aa83341b1443c131637e5b2b498b42cfed858927fa3f7ded00885e03f38e688a", + "tests/test_compact_dataclass_projection.py": "b765e0b8ced31a5cc351125bb2d86670e30cc973779c0b6931c75b026a14b271", + "tests/test_core.py": "a2aba8923fd176a75a9e94f5c3b1fa0a6d18f41b28935b0c4d39ed75892894fb", + "tests/test_deferred_callback.py": "1c59913d1b19a9725e5735bbd342dc115fdf4b555863427169b5001324e83b1c", + "tests/test_enabled_field_styling_ownership.py": "d831ab09cb4a0b92c3c33e4f2c368874a454c85eb8943d9acce48388ea961263", + "tests/test_enabled_title_row_ownership.py": "01052fea145b31698ec29319f521179adda5945ce324f3d976bdcc144aeb5be4", + "tests/test_explicit_function_pattern_overrides.py": "69179658cd4d89cdbf8bd469166e819f3421c39a6fcb6a38cc330dbbcb592a33", + "tests/test_field_mutation_authorization.py": "cab1faf400063e32df23249457738b9b28f59c760a6fe4d3cfcbba34884800ea", + "tests/test_flash_destruction_lifetime.py": "a567e8b978182773d316e9a7dc7934b80da2708e2804bd8e84898b4b1a030b37", + "tests/test_flash_mask_rendering.py": "9ca43be6bb9bb98a6950e9025688a6f40d8c7d050dec2bbe5721c215c47122f8", + "tests/test_flash_playback.py": "51438a64b08edec35a54447dbf3acd8aebd77a8dde92dfd7ccb3b0755bc196df", + "tests/test_flash_scroll_ownership.py": "f660469075d1c96e1fdce5bfaa0bd94857001d5e4f9ccf33fbae9ce9b2a51072", + "tests/test_form_build_transaction.py": "fc9860a115de764ee14d2a246fb5dd2d66bb60b159ae7f5853050d1e28442417", + "tests/test_function_list_editor_tokens.py": "5eea6d8a08f76c22fe81f4fca16b80d82ab8bb2ccc6f21428e5eed739065741b", + "tests/test_function_table_browser.py": "e0289caa47564647e1952a8592cda03840a58b11fb10fac6e6db9b35b1045541", + "tests/test_future_completion.py": "fddee2a4c4b210e43c137a24f5730c0e8303a38ecc67afec7a4ac5f39d2ad860", + "tests/test_help_document.py": "b28d3fb53b253372cdd4e5fa542faf5ef9a2cd7f6b42cd3a3694c2713f4f5768", + "tests/test_help_document_browser.py": "b04eca203a5d7be904ef86f490370bb71b598bc9f9d8f2ec441d118c4baa5d71", + "tests/test_host_provider_contracts.py": "ccc75dee1cd12eb05b29debe8da84a9b98a4714607bebdb9ad75c901f24f846e", + "tests/test_inline_dataclass_chrome.py": "e2c62d17ff58ad6dbe3dc2ec7e8caa1b8eeabc7e26f92c27a1a4489d1b12656b", + "tests/test_key_sequence_adapter_lifecycle.py": "bb4e57ee2548822f06252bdf07a9e3f36d569a01165f8707c2687150e4364824", + "tests/test_list_preview_wrapping.py": "60bfe5b16e9f17f3fed1f88213e69644ad2bcf278d7012b446689fbc75e181a2", + "tests/test_log_viewer_lifecycle.py": "4c7372276b7e65d84568c01489a544df7b9b2df791910c21cba11ad9c0eaff75", + "tests/test_manager_ui_scaffold.py": "cef43797060e94628d04fc581268ccd7e054cd5810b37105a68ce7930594eba6", + "tests/test_nominal_contract_architecture.py": "d02bb10514bab0bb58ad9585f986e208d88365838597eef520186f066685867a", + "tests/test_numeric_roundtrip.py": "5975b0ce8bd7bfcf1b21bf03593b72882c775a7982d834894081b6012c556566", + "tests/test_parameter_form_service.py": "30bb0cbb28b6edd5c144a58cc30a4e9fc068f9e56ee2dbe19e39f2b64fd1982d", + "tests/test_parameter_form_tree_index.py": "d28a29f77a68a22b3fce087de2c2679f2a291dd6a66cecf94f68ac700c1fded5", + "tests/test_parameter_help_service.py": "d41f813fbefd005003ab90a6e83d44727cc1adf925a9d521095068cbed2355b7", + "tests/test_parameter_ops_placeholder_capability.py": "8e4006e9b04df1efbcc4d878a68505a7057b83d6ac44e5b47dc1ea0bdd9dad6f", + "tests/test_path_name_roles.py": "86f5ef6cc8677dd92faa349d6e3254bbf6edc734e31fe0e13f8436dc4283c34a", + "tests/test_preview_configuration_imports.py": "7bec54d0815d88d2dce8dea9b73febbf23216b32c06666eab34e1487f0ec142b", + "tests/test_preview_formatter_registry.py": "9b62974f3e42be630f8f38a72d894f937affd6a694fe6f13c71629b5a38104ee", + "tests/test_preview_formatters.py": "4d6bbd9ada4ced6e6d2b49ff8c582d30b6341dd3403ee0c458a6bc4f0e595e49", + "tests/test_process_launch.py": "49c14b825f7fd3f7f7aa51f727c436c529cd2aaabefa3bee13e9f9e9d955e489", + "tests/test_process_signals.py": "de4d134edc1345bfe53df7f8b4ed362a24e4b3da35cfbc2132c5f6fb5107a662", + "tests/test_protocols.py": "3843eb80885957639b40d1cd260c87d0680df3a63d6ac448a084a25e8a37d8f2", + "tests/test_qt_types.py": "c24a5242ec6395b8c72723540e4b100e41f573d071444fc8c27eaac9a42de911", + "tests/test_reset_flash_changes.py": "3b901bd26e339f4585d90f25a70957fd949c7bdecbcfd56c0100c5a80f006d4b", + "tests/test_scoped_border_mixin.py": "9914504211aeaeb0cc713b9aa2c11619a00bfc53dc8dc6aa68d2d5ce3bd2f538", + "tests/test_scoped_table_widget.py": "764ed376f2e284682ddab7ab8379071d19ee703c391ea8196562b8f7b5b9a2fb", + "tests/test_scroll_area_content.py": "4b6f4a9e1fed02a267e2c707b1618ad3de8c451fe5e44b2f404360ef00e579ca", + "tests/test_scrollable_form_viewport_context.py": "d445d86f08bee9cc364868d4f50c976ee95bd85827b02790353c9f7439c9df7b", + "tests/test_status_indicator.py": "78f0e0b01548b8d676fd6ed75c79a800a4399826dcc5d2770ff3bb49a7e2a85e", + "tests/test_system_metrics_sampler.py": "524776fcf817233d461402b0f096623763f119a5d690a738434b390c6c752b07", + "tests/test_system_monitor_config.py": "2cc61be642ee7c9e26dab9e13497800bd3f85490a5253e5634a1374d4fe8287a", + "tests/test_theming.py": "bb811e5a73ee0a4fb95a0b87a40165442c39e3afdfa6c6ca6c0061590dae781c", + "tests/test_tree_state_adapter.py": "76d12b348ed6a015cb9b8f5bf3173968ca1b17a219df21aae82df23b12341907", + "tests/test_ui_thread_dispatch.py": "3478d122a45ee394edd3ab191f46636c62fe3b1ba1705d80e48c9e764b31e8d7", + "tests/test_weak_events.py": "d752129493c8cdd1d427024c64c7f02cd37d0e7a87bbf854b1ed332d174fa710", + "tests/test_widget_projection_safety.py": "f124cf36ca48fe51bae0aedad633f420bccd469ea8d9059d82d64dff3ca841e2", + "tests/test_widget_tree_projection.py": "3d6a1224caf0913ca194b13f4cf791cfcb3ce9e9c38b88281fe2dac4a0e222ef", + "tests/test_widgets.py": "f24b7bace49d7c6ce5357d38e9b5362ba0625b9f4421222788ab661ae278ed19", + "tests/test_window_code_document.py": "5c546e6151f19a8bcebfaa6a332a301b888416236baa982e2ae761e015326712", + "tests/test_window_navigation.py": "0f2bd021ca9d547f2b3d64e42cba1d13d0ffb1ed52e86bd07df836d5d3f649e3", + "tests/test_window_snapshot.py": "33fa1d5509217b0c16e926f7b4643ae1d5176ac77434f16099acd9b7cd52b8e2", + "tests/test_window_snapshot_bindings.py": "44af6189d6bf64bcfcad9e87150d2f01620e2a2c0b4877d581f64428176decf9", + "tests/test_zmq_server_browser_lifecycle.py": "2789e1a2cd5c81bddd37b62eb5fbe507228972e9f0dac0d1ea06b87dda066579" + } + } + }, + "native_binaries": { + "openhcs/core/_tabular_native.abi3.so": "2ce348417de70ad3f614962c82aed9c4977c32b3ba00e13531ecafb8c10d8d1d", + "openhcs/processing/backends/cellprofiler/_granularity_native.abi3.so": "6e45987a50d5c0588a8fb0b09a2232a63e72c122d6a3d583ae4d62830e3b4096" + }, + "inputs": { + "/home/ts/code/projects/openhcs/benchmark/reference_exports/official30_value_completion_20260914/ExampleIlluminationCorrection_Example3.cppipe": "f7ec9eb561730cc567986e6a50504a69f23a3ca78a1a033faba0b2fea52759fb", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/--W00001--P00001--Z00000--T00000--cherry.tif": "f073bc8f8102f05e6443226fcb986e7d30b3f9f0d7cd77d25c7c9f82ee11b782", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/ADSAStaphInfection2_A01_w2247376DD-6ADD-442D-AE47-F54A05F3EA94.tif": "5a57b7557bb0da5e241b48851b82d936c7ec36ede7aaca5e77b28ac4bfebf502", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O01f00d2.TIF": "5bfdeeb9e1dba87dc55220f71168af3d9949f38b8d59ba741b546619c2a49fd3", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O01f01d2.TIF": "8ddf231a2727fe0dd5e80d1747a968ecc67438def175dd2b4a5850bf54699c2b", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O01f02d2.TIF": "5a7bf7ff3504baaf787f004e2137059ea2ca890a37842df5360a035b78e49940", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O02f00d2.TIF": "57f0a36092341c746441c837c78b103f35ef6460a71df77f5ae9ee74cd82ad4e", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O02f01d2.TIF": "d1b6057f138d897c3dba0d055e90e17ca5239523264c138c863bd2c4c7e453fa", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O02f02d2.TIF": "4b52dc59a87b5230d2e8701971d42df4f0e96966cf1308ce6eb7dc4865c1000e", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O03f00d2.TIF": "269e5ab417a616ef55679321f56ee99e870abe4e519c5c24c911b39b1527e7fd", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O03f01d2.TIF": "0e95bb9ab0feeab2d0ddd1a5cc877475b5c8001ae4873b9ebcaaa44107acec78", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O03f02d2.TIF": "a26dbf0381c2404bb0f495e9c68d7f2ec8fa87eae6edc7c95b5a3fc55f548a97", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O04f00d2.TIF": "fce63090cdf6281b51ac538d7af3840610f2e275af45d1cf8dd59ee2bf92377a", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O04f01d2.TIF": "e27fd485ee359490f13efa73bf7bbaef2c6743ecadba05d21a22d156ed9b892e", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O04f02d2.TIF": "fa078664928f35b7b0d1a3a971e39602bbb775f78e9001c3dcd81e392c570bf5", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O05f00d2.TIF": "cb80c657237e9cbdadba93d49d9a10cf35531ea2cb7246c5cf15d6cac1a30651", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O05f01d2.TIF": "6035bce54914bc2ce236dd1c37eda3dbeb83752ad6c3c3746e57ae13041ec868", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O05f02d2.TIF": "64e64f69f7b6abd5ed2db49b1a39dcf4036706a2a7cebef48a5188c41e0598e2", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O06f00d2.TIF": "076a52b3f4e257d18f45b01a61bfeeac112531fb5036890f2f2aa44f2ea36fdf", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O06f01d2.TIF": "72e69058831189fb1e799209c6d8bfd90d52e2736d96352ecca08735238c8384", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O06f02d2.TIF": "3c1a864005429908707a07a7f26debc838b9fff9328953a2838b7b629b305d85", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O07f00d2.TIF": "e4adc0b64624c1e83deca015415473d77f323ed7d6cad0322472874cb32b2aa3", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O07f01d2.TIF": "ce3310b92a870a24abc9e81319d319fef07a6fe6a99961c174b1bc06bb65fc47", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O07f02d2.TIF": "0ada0de31dec60745bece90d3d67c5ca5dbec6fa0532d61afe621602eef95543", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O08f00d2.TIF": "ff903c458dbfdbdd076952533aa1f3b17aa71d6b2add8cb79ead0f1649d8a189", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O08f01d2.TIF": "0f3c0748ed5ec06b7e95e411a7744571e3338e3c37ff5b0336d707db997e939c", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O08f02d2.TIF": "97f926715e7ee9743e7b382808486de24a0b386db6712cf9b38a012fcb5b3e0e", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O09f00d2.TIF": "c60dd32928613a0905306b3697279138828520bc8a9420e662dbe79799cba89c", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O09f01d2.TIF": "917e37b5cd8d60c9e2caa89472246fb94d1c51f1a350554556cf826fae276437", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O09f02d2.TIF": "7f3750dd2ea324983f4ab1fcac59183a410267d1f8221f2963f7e74d19646450", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O10f00d2.TIF": "fe52a74223e5a46d3d2b434d7dacc3d2517f2c5b10f0d04b7a3cbf7fbf41e63d", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O10f01d2.TIF": "fc325b8baff83f25402f8398760df8b2bb72425a98077ede74fa05446b22ac88", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O10f02d2.TIF": "b763c7dc7a8a539f2eaa52517c60c39b0673b9777c4642555ba86b5774d6b0fd", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O11f00d2.TIF": "3f05a9e77c8cdf6c5c29c0af26a147bcc63c110bf0bc438abc27497501cfeda6", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O11f01d2.TIF": "93e08b9408c31d4317b2ef2db997c4df3efa7ae8d8d32738cb0ec0c5c9ec1d1f", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O11f02d2.TIF": "25304455c0b64544bcf09aed892c61cd37c3f6535db2447741f0fd0f08eea27c", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O12f00d2.TIF": "6876b895933a84d9dbe7d94e0db1862fdc19ae006a9be1ed76c0e1ec390a95cb", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O12f01d2.TIF": "b29ea362fcf4f1276977f5e09804b3caeca1dba4c030fa285ce69fb7f26b6044", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O12f02d2.TIF": "e086c6b414fa5345577bb9d1cbcfcfdbd183e639e9039b50f1c08b5b67a00f36", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O13f00d2.TIF": "cae644c4b99556fccddbab42098f8dbdaa723996c521557f3b59caf3430b82d7", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O13f01d2.TIF": "17e88f342e33075b08338cb191df919c85eb3a5fa8efb3ddfcae57e69e776be3", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O13f02d2.TIF": "7bfe66d604eeb2b996e368f6a0e36891f2dd0d6ba5d819b4104614d0f0236bd2", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O14f00d2.TIF": "844889a709a3326137fd67171c0b8ec018b397fe1ede836a9b7e5809e075f58d", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O14f01d2.TIF": "968ea530f2a3aab735664fff7936ebc4e406a7112fd84b89d92431ba27178c96", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O14f02d2.TIF": "5193e9ba72e56eaaff791c214c6be34766522b6aaab383ad8e9893f0734e60c3", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O15f00d2.TIF": "488149e5f50630d794c6c57340df6271a693035bbfa46142ed6422cbfa64c8ae", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O15f01d2.TIF": "3278f9402a8110bb622b2a8c62b8087d19b35736ae9a9e6361e675af67ecc13f", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O15f02d2.TIF": "25a40d29b3e2525c976b2288013bdbeb0a2eee7026f172d100586ff9a51ce348", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O16f00d2.TIF": "16fe3c9674e55150497d1d573ccc262419314ae62acb1c76dca858c40f72f744", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O16f01d2.TIF": "69133d455b367c919d5f2bcde19ab2c6223ef57b06d2c3011393e8c9f1a709c9", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O16f02d2.TIF": "b0c7dbcf259ad76e9fccb6de614b5d15f542317bb95c97a85233fbdcb73c9de3", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O17f00d2.TIF": "d049efceda2aea79923d4b8df69de9144ba104c77a06bf168184830cc30f30d4", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O17f01d2.TIF": "bae6ec7694d0868c74c079f5cd24534542f2835d4cab41ed8d82586c662ce4d1", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O17f02d2.TIF": "c991d219a21e6f1274b01bb6f370c4fb44addb122c1e292c36acd33def0787e2", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O18f00d2.TIF": "15e3dde0bdcd792bde186c6576cbb45d64723fb50b5d4c1841ad9ce3c6386f2d", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O18f01d2.TIF": "cf8e231352f5bf3f0b63aa29cf72a21c90a15ad2233e8495068a778399a056d0", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O18f02d2.TIF": "f67d7dba8a06dea16da609d350a98647d181c7b175109b940c74627e4c7fc4fd", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O19f00d2.TIF": "c370003080a53449570d1d780b9dd84626bd3cfa49c80c6db0ccdb493cbf6a63", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O19f01d2.TIF": "1a5b7ad836b7f86e187c52eb4e9f76dbc71b2057bf6ab8ff57d676314811a930", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O19f02d2.TIF": "e8e3774e2ad39eeb9dcfb25cb92d7c75c022f86de5fab772a36e60a332cc7cf1", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O20f00d2.TIF": "99cf977fccdc4cbdb1ba8a1a2992dbf4d1c26b7f6d822a18d0db323e842ace8e", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O20f01d2.TIF": "6847c82a3ea55a29c1f55c7dcf251e5b8a776eb207107f41aaabf3978a855c58", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O20f02d2.TIF": "2e0059c518aa222960520be791721a52837a948d22bf1d2fb4000b37ec89e881", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O21f00d2.TIF": "26fb12cc1228982b372da290eabe06897521db386800aca9518535fead716870", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O21f01d2.TIF": "1c59f7447309b5854ebcac27ed3cd10c564894b4cdb6510865b447bca4029c95", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O21f02d2.TIF": "9c0d1062e13d193427eb146b882e19c54ccbbba531df786d797e7d13756198b0", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O22f00d2.TIF": "fafa8607d475c46e645433036df14b58ec9ba7c850ef5ff37b8253bd8ea67f05", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O22f01d2.TIF": "2183fc92523891136905acf96fc2bdad04e00657f8070911ac3d4c1950ebf822", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O22f02d2.TIF": "5684cec26114f2813f41d4c42ba2bbe982b01bdcad78d80d73cfb78e07f9c790", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O23f00d2.TIF": "7e2420883575733a3d759752d633df10eec665b9d0575173063365366320a8b7", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O23f01d2.TIF": "f61467aadaf8e4c92cab7daff2cf5cf99b87783d5a055f69d9043c8b9b958554", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O23f02d2.TIF": "0a0839f901f76e8f11e85c94af74e0c8f1df302cc7fd88cd7429e83e694329c7", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O24f00d2.TIF": "ecd17866fa382365023790c9c874255e9248ce77fa374abfaec73a62f7cb898d", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O24f01d2.TIF": "8ac212dcc8b92fb953bd4a17f2b6a49a9b824c521b5c0fb62bfafacadd03a44d", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/AS_09047_050428030001_O24f02d2.TIF": "adf56aa932a3e04f19e5eb2b0f5d85a15b52fa2ffa0a0e57b6754c6de818eee0", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleWoundHealing/ExampleWoundHealing.cppipe": "61da2bdd29daec73813645fef978fe237ecd92229433106d80e9bb0c65a3c8e6", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleWoundHealing/images/DMSO_B5_t0.JPG": "1d91c175dd7aa433e63d218b9d352e6065c5c5c888631366f6d0716fa384f642", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleWoundHealing/images/DMSO_B5_t24.JPG": "fc83c19de66538f1619728cd52930b867fb87bbcfa39d85ab9838eae7e097198" + }, + "python": "edffa803e5c4d73a1357f7f2c6c9fd38e9693712b2c06793e6a5e5cc1090d03a", + "native_python": "84c920f304e265c53096e42d83309c6f7b829988f937a7dd15c24eebcb63f59a", + "native_pyvenv": "9adb0795d69940b55f3d8fb0a35b0dceff4f9388f4e0ac2c9efb11e6b4fe2cbc", + "java": "fc4c7fbe8b539370e4c435da65e562ad1c09e833a1767b0455249406ec1ca762", + "libjvm": "c8912093ef5e3f93f7409f4e9e475978ded9193ca06762d8ca6b047169af0d0a", + "pip_freeze": "abi3audit==0.0.26\nabi3info==2026.9.25\naiobotocore==3.9.1\naiohappyeyeballs==2.7.1\naiohttp==3.14.3\naioitertools==0.13.0\naiosignal==1.4.0\nannotated-doc==0.0.5\nannotated-types==0.8.0\nanyio==4.15.1\napp-model==0.5.1\narray-api-compat==1.15.0\n-e git+https://github.com/OpenHCSDev/arraybridge.git@1e53d03d9f468322a1c085c8be29485fb139caf2#egg=arraybridge&subdirectory=../../../external/arraybridge\nast_serialize==0.11.2\nasttokens==3.0.2\nattrs==26.1.0\nautopep8==2.3.2\nblack==26.5.1\nbotocore==1.43.75\nbuild==1.6.1\ncachey==0.2.1\ncattrs==26.2.1\ncentrosome==1.3.4\ncertifi==2026.7.22\ncffi==2.1.1\ncharset-normalizer==3.5.1\ncjdk==0.5.0\nclick==8.5.0\ncloudpickle==3.1.2\ncolorama==0.4.6\ncomm==0.2.3\ncontourpy==1.4.0\ncoverage==7.16.2\ncryptography==50.0.1\ncycler==0.12.1\ndask==2026.8.0\ndebugpy==1.8.22\ndefusedxml==0.7.1\nDeprecated==3.0.0\ndeprecation==2.1.0\ndill==0.4.1\ndistinctipy==1.3.4\ndocstring_parser==0.18.0\ndocutils==0.23\ndonfig==0.8.1.post1\net_xmlfile==2.0.0\nexecnet==2.1.2\nexecuting==2.2.1\nflexcache==0.3\nflexparser==0.4\nfonttools==4.66.1\nfreetype-py==2.5.1\nfrozenlist==1.8.0\nfsspec==2026.9.0\ngenbadge==1.1.3\ngoogle-crc32c==1.9.0\nGPUtil==1.4.0\nh11==0.16.0\nHeapDict==1.0.1\nhsluv==5.0.4\nhttpcore==1.0.9\nhttpx==0.28.1\nhttpx-sse==0.4.3\nidna==3.20\nimagecodecs==2026.8.16\nImageIO==2.38.0\nimglyb==2.1.0\nin-n-out==0.2.1\niniconfig==2.3.0\nipycanvas==0.14.3\nipyevents==2.0.4\nipykernel==6.31.0\nipympl==0.10.0\nipython==9.17.1\nipython_pygments_lexers==1.1.1\nipywidgets==8.1.9\njax==0.9.2\njaxlib==0.9.2\njedi==0.20.0\njgo==3.1.0\njmespath==1.1.0\njoblib==1.6.0\njpype1==1.7.1\njsonschema==4.26.0\njsonschema-specifications==2025.9.1\njupyter_client==8.10.0\njupyter_core==5.9.1\njupyterlab_widgets==3.0.17\nkaitaistruct==0.11\nkiwisolver==1.5.1\nlabeling==0.1.15\nlazy-loader==0.6\nlibrt==0.16.0\nllvmlite==0.49.0\nlocket==1.0.0\nlxml==6.1.3\nmagicgui==0.10.2\nmahotas==1.4.19\nmarkdown-it-py==4.2.0\nmatplotlib==3.11.2\nmatplotlib-inline==0.2.2\nmcp==1.30.0\nmdurl==0.1.2\n-e git+https://github.com/OpenHCSDev/metaclass-registry.git@393a7e03003cdc56df9013f932ed4f26e632d77a#egg=metaclass_registry&subdirectory=../../../external/metaclass-registry\nml_dtypes==0.6.0\nmsgspec==0.22.0\nMulti-Template-Matching==2.0.1\nmultidict==6.9.1\nmypy==2.3.1\nmypy_extensions==1.1.0\nnapari==0.9.2\nnapari-console==0.1.4\nnapari-crop==0.1.12\nnapari-plugin-engine==0.2.1\nnapari-resources==1.0.1\nnapari-svg==0.2.1\nnapari-tools-menu==0.1.20\nnapari-workflows==0.2.11\nnarwhals==2.26.0\nnest-asyncio==1.6.0\nnetworkx==3.7\nnpe2==0.9.0\nnumba==0.67.0\nnumcodecs==0.17.0\nnumpy==2.5.3\n-e git+https://github.com/OpenHCSDev/ObjectState.git@a01f8939b9bf4659502a33fe3febe62cab0f3c9a#egg=objectstate&subdirectory=../../../../../../openhcs-shared-runtime-plumbing/external/ObjectState\nome-zarr==0.19.2\nome-zarr-models==1.8.1\nopencv-python-headless==5.0.0.93\n-e git+https://github.com/OpenHCSDev/openhcs.git@902913616e19f5b242928d4e835b8c2e10ab2fce#egg=openhcs\nopenhcs-basicpy==1.3.1\nopenpyxl==3.1.5\nopt_einsum==3.4.0\npackaging==26.3\npandas==3.0.6\nparso==0.8.7\npartd==1.4.2\npathspec==1.1.1\npefile==2024.8.26\npexpect==4.9.0\npillow==11.3.0\nPint==0.26.1\npip==26.2.1\nplatformdirs==4.12.2\npluggy==1.6.0\n-e git+https://github.com/OpenHCSDev/PolyStore.git@84f322e46871de5ed47e7fd20976ad03e533c1c4#egg=polystore&subdirectory=../../../external/PolyStore\npooch==1.9.0\nportalocker==4.4.0\nprogressbar2==4.6.0\nprompt_toolkit==3.0.53\npropcache==0.5.4\npsutil==7.2.2\npsygnal==0.16.1\nptyprocess==0.7.0\npure_eval==0.2.4\npycodestyle==2.15.0\n-e git+https://github.com/OpenHCSDev/pycodify.git@792b03413331fdf107e369c924c257a2f0b16126#egg=pycodify&subdirectory=../../../external/pycodify\npyconify==0.2.1\npycparser==3.0\npydantic==2.12.5\npydantic-extra-types==2.11.1\npydantic-settings==2.15.0\npydantic-zarr==0.10.0\npydantic_core==2.41.5\npyelftools==0.33\nPygments==2.21.0\npyimagej==1.7.0\nPyJWT==2.15.1\nPyOpenGL==3.1.10\npyparsing==3.3.3\npyproject_hooks==1.3.3\n-e git+https://github.com/OpenHCSDev/PyQT-reactive.git@ad4948775ab81180a354d4b793d17ee5ddff3972#egg=pyqt_reactive&subdirectory=../../../external/pyqt-reactive\nPyQt6==6.11.0\nPyQt6-QScintilla==2.14.1\nPyQt6-Qt6==6.11.2\nPyQt6_sip==13.12.0\npyqtgraph==0.14.0\npytest==9.1.1\npytest-asyncio==1.4.0\npytest-cov==7.1.0\npytest-qt==4.5.0\npytest-xdist==3.8.0\npython-dateutil==2.9.0.post0\npython-dotenv==1.2.3\n-e git+https://github.com/OpenHCSDev/python-introspect.git@ed1e4eb15f7a0bf8315274d3e47858fa2b4372bb#egg=python_introspect&subdirectory=../../../../../../openhcs-shared-runtime-plumbing/external/python-introspect\npython-multipart==0.0.32\npython-utils==4.0.1\npytokens==0.4.1\nPyWavelets==1.10.0\nPyYAML==6.0.3\npyzmq==27.2.0\nqtconsole==5.7.2\nQtPy==2.4.3\nrangehttpserver==1.4.0\nreferencing==0.37.0\nrequests==2.34.2\nrequests-cache==1.1.1\nrich==15.0.0\nroifile==2026.9.22\nrpds-py==2026.6.3\nruff==0.16.9\ns3fs==2026.9.0\nscikit-image==0.26.0\nscikit-learn==1.9.1\nscipy==1.18.1\nscyjava==1.12.5\nsemver==3.1.0\nsetuptools==84.0.0\nshellingham==1.5.4\nsix==1.17.0\nskan==0.13.1\nsse-starlette==3.5.0\nstack-data==0.6.3\nstackview==0.19.1\nstarlette==1.7.0\nsuperqt==0.8.2\nthreadpoolctl==3.7.0\ntifffile==2026.9.20\ntomli_w==1.2.0\ntomlkit==0.15.1\ntoolz==1.1.0\ntornado==6.5.10\ntqdm==4.70.1\ntraitlets==5.16.1\ntransformnd==0.7.2\ntyper==0.27.2\ntyping-inspection==0.4.4\ntyping_extensions==4.16.0\nurl-normalize==3.0.1\nurllib3==2.8.0\nuvicorn==0.54.0\nvispy==0.17.0\nwatchdog==6.0.0\nwcag-contrast-ratio==0.9\nwcwidth==0.9.1\nwidgetsnbextension==4.0.16\nwordcloud==1.9.6\nwrapt==2.5.0\nxarray==2026.7.0\nxlsxwriter==3.2.9\nyarl==1.25.1\nzarr==3.4.0\n-e git+https://github.com/OpenHCSDev/ZMQRuntime.git@668edafcb5ee530a163377c936431ae1e8334e85#egg=zmqruntime&subdirectory=../../../external/zmqruntime\n", + "native_pip_freeze": "annotated-types==0.7.0\nboto3==1.42.97\nbotocore==1.42.97\ncellprofiler==4.2.8.1\ncellprofiler-core==4.2.8.1\ncentrosome==1.2.3\ncertifi==2026.7.22\ncharset-normalizer==3.5.1\ncontourpy==1.1.1\ncycler==0.12.1\ndeprecation==2.1.0\ndocutils==0.15.2\nfonttools==4.60.2\nfuture==1.0.0\nh5py==3.7.0\nidna==3.20\nImageIO==2.37.2\nimportlib_resources==6.5.2\ninflect==6.2.0\nJinja2==3.1.6\njmespath==1.1.0\njoblib==1.5.3\nkiwisolver==1.4.7\nmahotas==1.4.18\nMarkupSafe==3.0.3\nmatplotlib==3.7.5\nmysqlclient==1.4.6\nnetworkx==3.2.1\nnumpy==1.24.4\npackaging==26.3\npillow==11.3.0\npip==26.0.1\nprokaryote==2.4.4\npsutil==7.2.2\npydantic==2.13.5\npydantic_core==2.46.5\npyparsing==3.3.3\npython-bioformats==4.1.0\npython-dateutil==2.9.0.post0\npython-javabridge==4.0.5\nPyWavelets==1.4.1\npyzmq==22.3.0\nrequests==2.32.5\ns3transfer==0.16.1\nscikit-image==0.18.3\nscikit-learn==0.24.2\nscipy==1.9.0\nsentry-sdk==0.18.0\nsetuptools==80.9.0\nsix==1.17.0\nthreadpoolctl==3.7.0\ntifffile==2022.4.8\ntyping-inspection==0.4.2\ntyping_extensions==4.16.0\nurllib3==1.26.20\nwheel==0.48.0\nzipp==3.23.1\n", + "environment_sha256": "18b33cab3a61c45a940312d5ea4e1e108bc5d57261a520f3d9c5058db3ef3776", + "helpers": { + "/home/ts/.local/state/openhcs-maintenance/20261003/current-wound-illum3-paired-preparation-v1/controller.py": "0b7abed65ecc3d61761533a3a9a69e9b9a8acb220049175ff46fb5f004ade4aa", + "/var/tmp/run_narrow450_runtime_phase_probe_20261002.py": "93a4b1720d3d2c64e77b722c91597be42c7c9968bad42a4503e5588fc7fc4a55", + "/var/tmp/openhcs_measurement_sparse_inventory_v2_20261003.py": "481d6ee99045090e6dac0e1d287a70cd33698575e06375780c123c66ed0bf52b", + "/tmp/run_integrated_fields_ordinary_abba_20261002.py": "8a41db448a722d231777a90a3ae23091617c8ac1ba72cefcb91f72b2c7975554" + } + }, + "requests": { + "ExampleIlluminationCorrection_Example3": { + "request": { + "pipeline_path": "/home/ts/.local/state/openhcs-maintenance/20261003/current-wound-illum3-paired-v1/native/ExampleIlluminationCorrection_Example3/preparation/native_cellprofiler_headless/ExampleIlluminationCorrection_Example3.cppipe", + "input_dir": "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images", + "file_list_path": "/home/ts/.local/state/openhcs-maintenance/20261003/current-wound-illum3-paired-v1/native/ExampleIlluminationCorrection_Example3/preparation/native_cellprofiler_file_list.txt", + "output_root": "/home/ts/.local/state/openhcs-maintenance/20261003/current-wound-illum3-paired-v1/native/ExampleIlluminationCorrection_Example3/outputs", + "expected_image_sets": 1, + "repetitions": 2 + }, + "provenance": { + "native_input_domain_strategy": "selected_wells", + "native_source_workspace": "/home/ts/.local/state/openhcs-maintenance/20261003/current-wound-illum3-paired-v1/native/ExampleIlluminationCorrection_Example3/preparation/native_cellprofiler_selected_source_workspace", + "native_selected_wells": [ + "A01" + ], + "native_selected_source_file_count": 1, + "native_selected_source_mode": "file_list", + "native_selected_source_flattened": false, + "native_selected_source_staging_root": null + }, + "prepared_pipeline_sha256": "313e72af5e42332d46c8035ff72c25b6d18ac66bfe3426d72f8badfe8271d8f7", + "file_list_sha256": "84cdf25570fc4ed34acee7d8b83a456d2dbe7ba5f87d8c2d59f52501e2ff8e1b", + "expected_source_rows": [ + { + "virtual_path": "W001_s001_w1_z001_t001.tif", + "address": { + "site": "1", + "channel": "1", + "z_index": "1", + "timepoint": "1", + "well": "W001" + }, + "ref": { + "backend": "disk", + "backend_address": "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/ADSAStaphInfection2_A01_w2247376DD-6ADD-442D-AE47-F54A05F3EA94.tif", + "source_axis_indices": [] + }, + "projection_role": "primary_plane", + "source_alias": "OrigWorms", + "source_metadata": { + "OpenHCSSourceVoxelSpacingZYX": "1,1,1", + "OpenHCSSourceVoxelSpacingUnit": "relative", + "OpenHCSSourceFilterPaths": { + "0": "ADSAStaphInfection2_A01_w2247376DD-6ADD-442D-AE47-F54A05F3EA94.tif", + "1": "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/ADSAStaphInfection2_A01_w2247376DD-6ADD-442D-AE47-F54A05F3EA94.tif" + }, + "site": "1", + "channel": "1", + "z_index": "1", + "timepoint": "1", + "well": "W001" + }, + "component_labels": { + "channel": "OrigWorms" + } + } + ], + "expected_metadata_sha256": "9488f587c8b8e1098a137a851c12a61952a1b089be6af8faf41b6d83f61f9d1b", + "plane_members": [ + "channel" + ], + "native_worker_sha256": "b377740417fbb9b78839ec792b634246a168de16736224a5991e8fb1ae70be76" + }, + "ExampleWoundHealing": { + "request": { + "pipeline_path": "/home/ts/.local/state/openhcs-maintenance/20261003/current-wound-illum3-paired-v1/native/ExampleWoundHealing/preparation/native_cellprofiler_headless/ExampleWoundHealing.cppipe", + "input_dir": "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleWoundHealing/images", + "file_list_path": "/home/ts/.local/state/openhcs-maintenance/20261003/current-wound-illum3-paired-v1/native/ExampleWoundHealing/preparation/native_cellprofiler_file_list.txt", + "output_root": "/home/ts/.local/state/openhcs-maintenance/20261003/current-wound-illum3-paired-v1/native/ExampleWoundHealing/outputs", + "expected_image_sets": 2, + "repetitions": 2 + }, + "provenance": { + "native_input_domain_strategy": "selected_wells", + "native_source_workspace": "/home/ts/.local/state/openhcs-maintenance/20261003/current-wound-illum3-paired-v1/native/ExampleWoundHealing/preparation/native_cellprofiler_selected_source_workspace", + "native_selected_wells": [ + "A01" + ], + "native_selected_source_file_count": 2, + "native_selected_source_mode": "file_list", + "native_selected_source_flattened": false, + "native_selected_source_staging_root": null + }, + "prepared_pipeline_sha256": "492f8be03ef821ebf56ac43023a956f368fd89f03abfdf9e5ed5cefe3ac790fb", + "file_list_sha256": "f00beb9e827b95803f59725b3dd7b98817fdb815bd4c0361300daeb8b5e3f2ab", + "expected_source_rows": [ + { + "virtual_path": "W001_s001_w1_z001_t001.tif", + "address": { + "site": "1", + "channel": "1", + "z_index": "1", + "timepoint": "1", + "well": "W001" + }, + "ref": { + "backend": "disk", + "backend_address": "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleWoundHealing/images/DMSO_B5_t0.JPG", + "source_axis_indices": [] + }, + "projection_role": "primary_plane", + "source_alias": "OrigColor", + "source_metadata": { + "OpenHCSSourceVoxelSpacingZYX": "1,1,1", + "OpenHCSSourceVoxelSpacingUnit": "relative", + "OpenHCSSourceFilterPaths": { + "0": "DMSO_B5_t0.JPG", + "1": "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleWoundHealing/images/DMSO_B5_t0.JPG" + }, + "site": "1", + "channel": "1", + "z_index": "1", + "timepoint": "1", + "well": "W001" + }, + "component_labels": { + "channel": "OrigColor" + } + }, + { + "virtual_path": "W001_s002_w1_z001_t001.tif", + "address": { + "site": "2", + "channel": "1", + "z_index": "1", + "timepoint": "1", + "well": "W001" + }, + "ref": { + "backend": "disk", + "backend_address": "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleWoundHealing/images/DMSO_B5_t24.JPG", + "source_axis_indices": [] + }, + "projection_role": "primary_plane", + "source_alias": "OrigColor", + "source_metadata": { + "OpenHCSSourceVoxelSpacingZYX": "1,1,1", + "OpenHCSSourceVoxelSpacingUnit": "relative", + "OpenHCSSourceFilterPaths": { + "0": "DMSO_B5_t24.JPG", + "1": "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleWoundHealing/images/DMSO_B5_t24.JPG" + }, + "site": "2", + "channel": "1", + "z_index": "1", + "timepoint": "1", + "well": "W001" + }, + "component_labels": { + "channel": "OrigColor" + } + } + ], + "expected_metadata_sha256": "205410fd1df7c623f8e1b76d1cb859da191f953ea73ee3b723dd1ef47dd103f6", + "plane_members": [ + "channel" + ], + "native_worker_sha256": "b377740417fbb9b78839ec792b634246a168de16736224a5991e8fb1ae70be76" + } + }, + "cases": [ + "ExampleIlluminationCorrection_Example3", + "ExampleWoundHealing" + ], + "repetitions": 2, + "scope": "Current-source two-case paired descriptive ordinary/native comparison. Default OUTCOMES/RSS; READY/import/JVM/load/warmup excluded through existing harness clocks. No hooks/profiles/pixel captures or manual timing." +} diff --git a/benchmark/results/perf_current_wound_illum3_paired_20261003/strict-science.json b/benchmark/results/perf_current_wound_illum3_paired_20261003/strict-science.json new file mode 100644 index 0000000000..41d4d9868c --- /dev/null +++ b/benchmark/results/perf_current_wound_illum3_paired_20261003/strict-science.json @@ -0,0 +1,491 @@ +{ + "status": "PASS", + "comparisons": [ + { + "case": "ExampleIlluminationCorrection_Example3", + "ordinary_repeat": 0, + "native_repeat": 0, + "measurement_differences": 0, + "image_differences": 0, + "declared_export_comparisons": [ + { + "artifact": { + "artifact_name": "PolynomialCorrected", + "artifact_type": "ImageArtifactType", + "semantic_kind": "numeric_image_pixels", + "output_filename": "reference_image__PolynomialCorrected.npy", + "comparison": "float pixels: atol=1e-6, rtol=1e-6, zero mismatches" + }, + "reference_path": "/home/ts/.local/state/openhcs-maintenance/20261003/current-wound-illum3-paired-v1/native/ExampleIlluminationCorrection_Example3/outputs/0/reference_image__PolynomialCorrected.npy", + "candidate_path": "/home/ts/.local/state/openhcs-maintenance/20261003/current-wound-illum3-paired-v1/ordinary-0/ExampleIlluminationCorrection_Example3/wells_1/workers_1/images_ExampleIlluminationCorrection_Example3_source_workspace_well_throughput/results/reference_image__PolynomialCorrected.npy", + "reference_shape": [ + 463, + 461 + ], + "candidate_shape": [ + 463, + 461 + ], + "reference_dtype": "float32", + "candidate_dtype": "float32", + "reference_pixel_digest": "b5073cb872058f88bb250be9e7a39bedd2ef281f23dfedde5262e4431f1fb0fe", + "candidate_pixel_digest": "8aedbeab3f9868c1d1d46b0aafb3b20bb9dfd107dc08bb0882577c493f08173b", + "compared_pixel_count": 213443, + "different_pixel_count": null, + "out_of_tolerance_pixel_count": 0, + "max_abs_difference": 2.9802322387695312e-08, + "equivalent": true + }, + { + "artifact": { + "artifact_name": "ConvexHullCorrWorm", + "artifact_type": "ImageArtifactType", + "semantic_kind": "numeric_image_pixels", + "output_filename": "reference_image__ConvexHullCorrWorm.npy", + "comparison": "float pixels: atol=1e-6, rtol=1e-6, zero mismatches" + }, + "reference_path": "/home/ts/.local/state/openhcs-maintenance/20261003/current-wound-illum3-paired-v1/native/ExampleIlluminationCorrection_Example3/outputs/0/reference_image__ConvexHullCorrWorm.npy", + "candidate_path": "/home/ts/.local/state/openhcs-maintenance/20261003/current-wound-illum3-paired-v1/ordinary-0/ExampleIlluminationCorrection_Example3/wells_1/workers_1/images_ExampleIlluminationCorrection_Example3_source_workspace_well_throughput/results/reference_image__ConvexHullCorrWorm.npy", + "reference_shape": [ + 463, + 461 + ], + "candidate_shape": [ + 463, + 461 + ], + "reference_dtype": "float32", + "candidate_dtype": "float32", + "reference_pixel_digest": "fdc35df90fb97b2d2ab79e4acdaa00aef26d4d9c76fb53d6aa53351bd598dd9b", + "candidate_pixel_digest": "fdc35df90fb97b2d2ab79e4acdaa00aef26d4d9c76fb53d6aa53351bd598dd9b", + "compared_pixel_count": 213443, + "different_pixel_count": null, + "out_of_tolerance_pixel_count": 0, + "max_abs_difference": 0.0, + "equivalent": true + } + ], + "tables": [ + 0, + 0 + ], + "physical_images": [ + 2, + 2 + ], + "logical_images": [ + 2, + 2 + ], + "known_relationship_keys": [ + 0, + 0 + ], + "ordinary_receipt_sha256": "05161397be3c2b6ab87b13e8387080ba7f4de39af35e25b9882d9ca4591e4180", + "output_hashes": { + "/home/ts/.local/state/openhcs-maintenance/20261003/current-wound-illum3-paired-v1/native/ExampleIlluminationCorrection_Example3/outputs/0/reference_image__PolynomialCorrected.npy": "588e6f9951aa7ad220678dbb0053e98fb6d324e71aab089d1d828d891ee32f54", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-wound-illum3-paired-v1/native/ExampleIlluminationCorrection_Example3/outputs/0/reference_image__ConvexHullCorrWorm.npy": "9ba1259e4ca007c06f14be6946e32a86307ec2dfb9952b73fa2cc253ccae8b3a", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-wound-illum3-paired-v1/ordinary-0/ExampleIlluminationCorrection_Example3/wells_1/workers_1/images_ExampleIlluminationCorrection_Example3_source_workspace_well_throughput/results/reference_image__PolynomialCorrected.npy": "8875da63a072c8f2de4f5cb707d779a064b663bf69aa0f304fe6fa74d4ff57a6", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-wound-illum3-paired-v1/ordinary-0/ExampleIlluminationCorrection_Example3/wells_1/workers_1/images_ExampleIlluminationCorrection_Example3_source_workspace_well_throughput/openhcs_metadata.json": "579ac084b396dff5f7fbaa844139bf952c2576b6cb0242772c925ba9839c2267", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-wound-illum3-paired-v1/ordinary-0/ExampleIlluminationCorrection_Example3/wells_1/workers_1/images_ExampleIlluminationCorrection_Example3_source_workspace_well_throughput/results/reference_image__ConvexHullCorrWorm.npy": "9ba1259e4ca007c06f14be6946e32a86307ec2dfb9952b73fa2cc253ccae8b3a", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-wound-illum3-paired-v1/ordinary-0/ExampleIlluminationCorrection_Example3/wells_1/workers_1/images_ExampleIlluminationCorrection_Example3_source_workspace_well_throughput/openhcs_metadata.json.lock": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + } + }, + { + "case": "ExampleIlluminationCorrection_Example3", + "ordinary_repeat": 0, + "native_repeat": 1, + "measurement_differences": 0, + "image_differences": 0, + "declared_export_comparisons": [ + { + "artifact": { + "artifact_name": "PolynomialCorrected", + "artifact_type": "ImageArtifactType", + "semantic_kind": "numeric_image_pixels", + "output_filename": "reference_image__PolynomialCorrected.npy", + "comparison": "float pixels: atol=1e-6, rtol=1e-6, zero mismatches" + }, + "reference_path": "/home/ts/.local/state/openhcs-maintenance/20261003/current-wound-illum3-paired-v1/native/ExampleIlluminationCorrection_Example3/outputs/1/reference_image__PolynomialCorrected.npy", + "candidate_path": "/home/ts/.local/state/openhcs-maintenance/20261003/current-wound-illum3-paired-v1/ordinary-0/ExampleIlluminationCorrection_Example3/wells_1/workers_1/images_ExampleIlluminationCorrection_Example3_source_workspace_well_throughput/results/reference_image__PolynomialCorrected.npy", + "reference_shape": [ + 463, + 461 + ], + "candidate_shape": [ + 463, + 461 + ], + "reference_dtype": "float32", + "candidate_dtype": "float32", + "reference_pixel_digest": "b5073cb872058f88bb250be9e7a39bedd2ef281f23dfedde5262e4431f1fb0fe", + "candidate_pixel_digest": "8aedbeab3f9868c1d1d46b0aafb3b20bb9dfd107dc08bb0882577c493f08173b", + "compared_pixel_count": 213443, + "different_pixel_count": null, + "out_of_tolerance_pixel_count": 0, + "max_abs_difference": 2.9802322387695312e-08, + "equivalent": true + }, + { + "artifact": { + "artifact_name": "ConvexHullCorrWorm", + "artifact_type": "ImageArtifactType", + "semantic_kind": "numeric_image_pixels", + "output_filename": "reference_image__ConvexHullCorrWorm.npy", + "comparison": "float pixels: atol=1e-6, rtol=1e-6, zero mismatches" + }, + "reference_path": "/home/ts/.local/state/openhcs-maintenance/20261003/current-wound-illum3-paired-v1/native/ExampleIlluminationCorrection_Example3/outputs/1/reference_image__ConvexHullCorrWorm.npy", + "candidate_path": "/home/ts/.local/state/openhcs-maintenance/20261003/current-wound-illum3-paired-v1/ordinary-0/ExampleIlluminationCorrection_Example3/wells_1/workers_1/images_ExampleIlluminationCorrection_Example3_source_workspace_well_throughput/results/reference_image__ConvexHullCorrWorm.npy", + "reference_shape": [ + 463, + 461 + ], + "candidate_shape": [ + 463, + 461 + ], + "reference_dtype": "float32", + "candidate_dtype": "float32", + "reference_pixel_digest": "fdc35df90fb97b2d2ab79e4acdaa00aef26d4d9c76fb53d6aa53351bd598dd9b", + "candidate_pixel_digest": "fdc35df90fb97b2d2ab79e4acdaa00aef26d4d9c76fb53d6aa53351bd598dd9b", + "compared_pixel_count": 213443, + "different_pixel_count": null, + "out_of_tolerance_pixel_count": 0, + "max_abs_difference": 0.0, + "equivalent": true + } + ], + "tables": [ + 0, + 0 + ], + "physical_images": [ + 2, + 2 + ], + "logical_images": [ + 2, + 2 + ], + "known_relationship_keys": [ + 0, + 0 + ], + "ordinary_receipt_sha256": "05161397be3c2b6ab87b13e8387080ba7f4de39af35e25b9882d9ca4591e4180", + "output_hashes": { + "/home/ts/.local/state/openhcs-maintenance/20261003/current-wound-illum3-paired-v1/native/ExampleIlluminationCorrection_Example3/outputs/1/reference_image__PolynomialCorrected.npy": "588e6f9951aa7ad220678dbb0053e98fb6d324e71aab089d1d828d891ee32f54", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-wound-illum3-paired-v1/native/ExampleIlluminationCorrection_Example3/outputs/1/reference_image__ConvexHullCorrWorm.npy": "9ba1259e4ca007c06f14be6946e32a86307ec2dfb9952b73fa2cc253ccae8b3a", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-wound-illum3-paired-v1/ordinary-0/ExampleIlluminationCorrection_Example3/wells_1/workers_1/images_ExampleIlluminationCorrection_Example3_source_workspace_well_throughput/results/reference_image__PolynomialCorrected.npy": "8875da63a072c8f2de4f5cb707d779a064b663bf69aa0f304fe6fa74d4ff57a6", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-wound-illum3-paired-v1/ordinary-0/ExampleIlluminationCorrection_Example3/wells_1/workers_1/images_ExampleIlluminationCorrection_Example3_source_workspace_well_throughput/openhcs_metadata.json": "579ac084b396dff5f7fbaa844139bf952c2576b6cb0242772c925ba9839c2267", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-wound-illum3-paired-v1/ordinary-0/ExampleIlluminationCorrection_Example3/wells_1/workers_1/images_ExampleIlluminationCorrection_Example3_source_workspace_well_throughput/results/reference_image__ConvexHullCorrWorm.npy": "9ba1259e4ca007c06f14be6946e32a86307ec2dfb9952b73fa2cc253ccae8b3a", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-wound-illum3-paired-v1/ordinary-0/ExampleIlluminationCorrection_Example3/wells_1/workers_1/images_ExampleIlluminationCorrection_Example3_source_workspace_well_throughput/openhcs_metadata.json.lock": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + } + }, + { + "case": "ExampleWoundHealing", + "ordinary_repeat": 0, + "native_repeat": 0, + "measurement_differences": 0, + "image_differences": 0, + "declared_export_comparisons": [], + "tables": [ + 1, + 1 + ], + "physical_images": [ + 0, + 0 + ], + "logical_images": [ + 0, + 0 + ], + "known_relationship_keys": [ + 0, + 0 + ], + "ordinary_receipt_sha256": "d5e133d0c3a20eb14fdb324cfc380019e24ad44105303e7e413bccd96113ba62", + "output_hashes": { + "/home/ts/.local/state/openhcs-maintenance/20261003/current-wound-illum3-paired-v1/native/ExampleWoundHealing/outputs/0/Image.csv": "497700eb62ed0a557b902968c0fdb444eca8b748a772d8234f241c84f5dfad87", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-wound-illum3-paired-v1/ordinary-0/ExampleWoundHealing/wells_1/workers_1/images_ExampleWoundHealing_source_workspace_well_throughput/openhcs_metadata.json": "71582c62cabb2571ebf8a0de57f92fdf82c55a7ece3dac0bf2a6eca95cad84c9", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-wound-illum3-paired-v1/ordinary-0/ExampleWoundHealing/wells_1/workers_1/images_ExampleWoundHealing_source_workspace_well_throughput/results/Image.csv": "939735fa17a067137fea2adc77d57f9ce1df24bfcb6588c49023de1cc3998677", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-wound-illum3-paired-v1/ordinary-0/ExampleWoundHealing/wells_1/workers_1/images_ExampleWoundHealing_source_workspace_well_throughput/openhcs_metadata.json.lock": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + } + }, + { + "case": "ExampleWoundHealing", + "ordinary_repeat": 0, + "native_repeat": 1, + "measurement_differences": 0, + "image_differences": 0, + "declared_export_comparisons": [], + "tables": [ + 1, + 1 + ], + "physical_images": [ + 0, + 0 + ], + "logical_images": [ + 0, + 0 + ], + "known_relationship_keys": [ + 0, + 0 + ], + "ordinary_receipt_sha256": "d5e133d0c3a20eb14fdb324cfc380019e24ad44105303e7e413bccd96113ba62", + "output_hashes": { + "/home/ts/.local/state/openhcs-maintenance/20261003/current-wound-illum3-paired-v1/native/ExampleWoundHealing/outputs/1/Image.csv": "373f02427a4758051bfdd80efd7071774d8adcae60a2928c6d3bb67ad993155c", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-wound-illum3-paired-v1/ordinary-0/ExampleWoundHealing/wells_1/workers_1/images_ExampleWoundHealing_source_workspace_well_throughput/openhcs_metadata.json": "71582c62cabb2571ebf8a0de57f92fdf82c55a7ece3dac0bf2a6eca95cad84c9", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-wound-illum3-paired-v1/ordinary-0/ExampleWoundHealing/wells_1/workers_1/images_ExampleWoundHealing_source_workspace_well_throughput/results/Image.csv": "939735fa17a067137fea2adc77d57f9ce1df24bfcb6588c49023de1cc3998677", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-wound-illum3-paired-v1/ordinary-0/ExampleWoundHealing/wells_1/workers_1/images_ExampleWoundHealing_source_workspace_well_throughput/openhcs_metadata.json.lock": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + } + }, + { + "case": "ExampleIlluminationCorrection_Example3", + "ordinary_repeat": 1, + "native_repeat": 0, + "measurement_differences": 0, + "image_differences": 0, + "declared_export_comparisons": [ + { + "artifact": { + "artifact_name": "PolynomialCorrected", + "artifact_type": "ImageArtifactType", + "semantic_kind": "numeric_image_pixels", + "output_filename": "reference_image__PolynomialCorrected.npy", + "comparison": "float pixels: atol=1e-6, rtol=1e-6, zero mismatches" + }, + "reference_path": "/home/ts/.local/state/openhcs-maintenance/20261003/current-wound-illum3-paired-v1/native/ExampleIlluminationCorrection_Example3/outputs/0/reference_image__PolynomialCorrected.npy", + "candidate_path": "/home/ts/.local/state/openhcs-maintenance/20261003/current-wound-illum3-paired-v1/ordinary-1/ExampleIlluminationCorrection_Example3/wells_1/workers_1/images_ExampleIlluminationCorrection_Example3_source_workspace_well_throughput/results/reference_image__PolynomialCorrected.npy", + "reference_shape": [ + 463, + 461 + ], + "candidate_shape": [ + 463, + 461 + ], + "reference_dtype": "float32", + "candidate_dtype": "float32", + "reference_pixel_digest": "b5073cb872058f88bb250be9e7a39bedd2ef281f23dfedde5262e4431f1fb0fe", + "candidate_pixel_digest": "8aedbeab3f9868c1d1d46b0aafb3b20bb9dfd107dc08bb0882577c493f08173b", + "compared_pixel_count": 213443, + "different_pixel_count": null, + "out_of_tolerance_pixel_count": 0, + "max_abs_difference": 2.9802322387695312e-08, + "equivalent": true + }, + { + "artifact": { + "artifact_name": "ConvexHullCorrWorm", + "artifact_type": "ImageArtifactType", + "semantic_kind": "numeric_image_pixels", + "output_filename": "reference_image__ConvexHullCorrWorm.npy", + "comparison": "float pixels: atol=1e-6, rtol=1e-6, zero mismatches" + }, + "reference_path": "/home/ts/.local/state/openhcs-maintenance/20261003/current-wound-illum3-paired-v1/native/ExampleIlluminationCorrection_Example3/outputs/0/reference_image__ConvexHullCorrWorm.npy", + "candidate_path": "/home/ts/.local/state/openhcs-maintenance/20261003/current-wound-illum3-paired-v1/ordinary-1/ExampleIlluminationCorrection_Example3/wells_1/workers_1/images_ExampleIlluminationCorrection_Example3_source_workspace_well_throughput/results/reference_image__ConvexHullCorrWorm.npy", + "reference_shape": [ + 463, + 461 + ], + "candidate_shape": [ + 463, + 461 + ], + "reference_dtype": "float32", + "candidate_dtype": "float32", + "reference_pixel_digest": "fdc35df90fb97b2d2ab79e4acdaa00aef26d4d9c76fb53d6aa53351bd598dd9b", + "candidate_pixel_digest": "fdc35df90fb97b2d2ab79e4acdaa00aef26d4d9c76fb53d6aa53351bd598dd9b", + "compared_pixel_count": 213443, + "different_pixel_count": null, + "out_of_tolerance_pixel_count": 0, + "max_abs_difference": 0.0, + "equivalent": true + } + ], + "tables": [ + 0, + 0 + ], + "physical_images": [ + 2, + 2 + ], + "logical_images": [ + 2, + 2 + ], + "known_relationship_keys": [ + 0, + 0 + ], + "ordinary_receipt_sha256": "c8c926e9001f1c5d01ea1d45e88603122eb9a3cb82343e848d67c7e31d7d8de8", + "output_hashes": { + "/home/ts/.local/state/openhcs-maintenance/20261003/current-wound-illum3-paired-v1/native/ExampleIlluminationCorrection_Example3/outputs/0/reference_image__PolynomialCorrected.npy": "588e6f9951aa7ad220678dbb0053e98fb6d324e71aab089d1d828d891ee32f54", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-wound-illum3-paired-v1/native/ExampleIlluminationCorrection_Example3/outputs/0/reference_image__ConvexHullCorrWorm.npy": "9ba1259e4ca007c06f14be6946e32a86307ec2dfb9952b73fa2cc253ccae8b3a", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-wound-illum3-paired-v1/ordinary-1/ExampleIlluminationCorrection_Example3/wells_1/workers_1/images_ExampleIlluminationCorrection_Example3_source_workspace_well_throughput/results/reference_image__PolynomialCorrected.npy": "8875da63a072c8f2de4f5cb707d779a064b663bf69aa0f304fe6fa74d4ff57a6", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-wound-illum3-paired-v1/ordinary-1/ExampleIlluminationCorrection_Example3/wells_1/workers_1/images_ExampleIlluminationCorrection_Example3_source_workspace_well_throughput/results/reference_image__ConvexHullCorrWorm.npy": "9ba1259e4ca007c06f14be6946e32a86307ec2dfb9952b73fa2cc253ccae8b3a", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-wound-illum3-paired-v1/ordinary-1/ExampleIlluminationCorrection_Example3/wells_1/workers_1/images_ExampleIlluminationCorrection_Example3_source_workspace_well_throughput/openhcs_metadata.json.lock": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-wound-illum3-paired-v1/ordinary-1/ExampleIlluminationCorrection_Example3/wells_1/workers_1/images_ExampleIlluminationCorrection_Example3_source_workspace_well_throughput/openhcs_metadata.json": "579ac084b396dff5f7fbaa844139bf952c2576b6cb0242772c925ba9839c2267" + } + }, + { + "case": "ExampleIlluminationCorrection_Example3", + "ordinary_repeat": 1, + "native_repeat": 1, + "measurement_differences": 0, + "image_differences": 0, + "declared_export_comparisons": [ + { + "artifact": { + "artifact_name": "PolynomialCorrected", + "artifact_type": "ImageArtifactType", + "semantic_kind": "numeric_image_pixels", + "output_filename": "reference_image__PolynomialCorrected.npy", + "comparison": "float pixels: atol=1e-6, rtol=1e-6, zero mismatches" + }, + "reference_path": "/home/ts/.local/state/openhcs-maintenance/20261003/current-wound-illum3-paired-v1/native/ExampleIlluminationCorrection_Example3/outputs/1/reference_image__PolynomialCorrected.npy", + "candidate_path": "/home/ts/.local/state/openhcs-maintenance/20261003/current-wound-illum3-paired-v1/ordinary-1/ExampleIlluminationCorrection_Example3/wells_1/workers_1/images_ExampleIlluminationCorrection_Example3_source_workspace_well_throughput/results/reference_image__PolynomialCorrected.npy", + "reference_shape": [ + 463, + 461 + ], + "candidate_shape": [ + 463, + 461 + ], + "reference_dtype": "float32", + "candidate_dtype": "float32", + "reference_pixel_digest": "b5073cb872058f88bb250be9e7a39bedd2ef281f23dfedde5262e4431f1fb0fe", + "candidate_pixel_digest": "8aedbeab3f9868c1d1d46b0aafb3b20bb9dfd107dc08bb0882577c493f08173b", + "compared_pixel_count": 213443, + "different_pixel_count": null, + "out_of_tolerance_pixel_count": 0, + "max_abs_difference": 2.9802322387695312e-08, + "equivalent": true + }, + { + "artifact": { + "artifact_name": "ConvexHullCorrWorm", + "artifact_type": "ImageArtifactType", + "semantic_kind": "numeric_image_pixels", + "output_filename": "reference_image__ConvexHullCorrWorm.npy", + "comparison": "float pixels: atol=1e-6, rtol=1e-6, zero mismatches" + }, + "reference_path": "/home/ts/.local/state/openhcs-maintenance/20261003/current-wound-illum3-paired-v1/native/ExampleIlluminationCorrection_Example3/outputs/1/reference_image__ConvexHullCorrWorm.npy", + "candidate_path": "/home/ts/.local/state/openhcs-maintenance/20261003/current-wound-illum3-paired-v1/ordinary-1/ExampleIlluminationCorrection_Example3/wells_1/workers_1/images_ExampleIlluminationCorrection_Example3_source_workspace_well_throughput/results/reference_image__ConvexHullCorrWorm.npy", + "reference_shape": [ + 463, + 461 + ], + "candidate_shape": [ + 463, + 461 + ], + "reference_dtype": "float32", + "candidate_dtype": "float32", + "reference_pixel_digest": "fdc35df90fb97b2d2ab79e4acdaa00aef26d4d9c76fb53d6aa53351bd598dd9b", + "candidate_pixel_digest": "fdc35df90fb97b2d2ab79e4acdaa00aef26d4d9c76fb53d6aa53351bd598dd9b", + "compared_pixel_count": 213443, + "different_pixel_count": null, + "out_of_tolerance_pixel_count": 0, + "max_abs_difference": 0.0, + "equivalent": true + } + ], + "tables": [ + 0, + 0 + ], + "physical_images": [ + 2, + 2 + ], + "logical_images": [ + 2, + 2 + ], + "known_relationship_keys": [ + 0, + 0 + ], + "ordinary_receipt_sha256": "c8c926e9001f1c5d01ea1d45e88603122eb9a3cb82343e848d67c7e31d7d8de8", + "output_hashes": { + "/home/ts/.local/state/openhcs-maintenance/20261003/current-wound-illum3-paired-v1/native/ExampleIlluminationCorrection_Example3/outputs/1/reference_image__PolynomialCorrected.npy": "588e6f9951aa7ad220678dbb0053e98fb6d324e71aab089d1d828d891ee32f54", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-wound-illum3-paired-v1/native/ExampleIlluminationCorrection_Example3/outputs/1/reference_image__ConvexHullCorrWorm.npy": "9ba1259e4ca007c06f14be6946e32a86307ec2dfb9952b73fa2cc253ccae8b3a", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-wound-illum3-paired-v1/ordinary-1/ExampleIlluminationCorrection_Example3/wells_1/workers_1/images_ExampleIlluminationCorrection_Example3_source_workspace_well_throughput/results/reference_image__PolynomialCorrected.npy": "8875da63a072c8f2de4f5cb707d779a064b663bf69aa0f304fe6fa74d4ff57a6", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-wound-illum3-paired-v1/ordinary-1/ExampleIlluminationCorrection_Example3/wells_1/workers_1/images_ExampleIlluminationCorrection_Example3_source_workspace_well_throughput/results/reference_image__ConvexHullCorrWorm.npy": "9ba1259e4ca007c06f14be6946e32a86307ec2dfb9952b73fa2cc253ccae8b3a", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-wound-illum3-paired-v1/ordinary-1/ExampleIlluminationCorrection_Example3/wells_1/workers_1/images_ExampleIlluminationCorrection_Example3_source_workspace_well_throughput/openhcs_metadata.json.lock": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-wound-illum3-paired-v1/ordinary-1/ExampleIlluminationCorrection_Example3/wells_1/workers_1/images_ExampleIlluminationCorrection_Example3_source_workspace_well_throughput/openhcs_metadata.json": "579ac084b396dff5f7fbaa844139bf952c2576b6cb0242772c925ba9839c2267" + } + }, + { + "case": "ExampleWoundHealing", + "ordinary_repeat": 1, + "native_repeat": 0, + "measurement_differences": 0, + "image_differences": 0, + "declared_export_comparisons": [], + "tables": [ + 1, + 1 + ], + "physical_images": [ + 0, + 0 + ], + "logical_images": [ + 0, + 0 + ], + "known_relationship_keys": [ + 0, + 0 + ], + "ordinary_receipt_sha256": "42f967eef57d1f1f85168d225258b50c79225fcafef0f1137a4f7f6de0d9e02e", + "output_hashes": { + "/home/ts/.local/state/openhcs-maintenance/20261003/current-wound-illum3-paired-v1/native/ExampleWoundHealing/outputs/0/Image.csv": "497700eb62ed0a557b902968c0fdb444eca8b748a772d8234f241c84f5dfad87", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-wound-illum3-paired-v1/ordinary-1/ExampleWoundHealing/wells_1/workers_1/images_ExampleWoundHealing_source_workspace_well_throughput/openhcs_metadata.json.lock": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-wound-illum3-paired-v1/ordinary-1/ExampleWoundHealing/wells_1/workers_1/images_ExampleWoundHealing_source_workspace_well_throughput/openhcs_metadata.json": "71582c62cabb2571ebf8a0de57f92fdf82c55a7ece3dac0bf2a6eca95cad84c9", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-wound-illum3-paired-v1/ordinary-1/ExampleWoundHealing/wells_1/workers_1/images_ExampleWoundHealing_source_workspace_well_throughput/results/Image.csv": "939735fa17a067137fea2adc77d57f9ce1df24bfcb6588c49023de1cc3998677" + } + }, + { + "case": "ExampleWoundHealing", + "ordinary_repeat": 1, + "native_repeat": 1, + "measurement_differences": 0, + "image_differences": 0, + "declared_export_comparisons": [], + "tables": [ + 1, + 1 + ], + "physical_images": [ + 0, + 0 + ], + "logical_images": [ + 0, + 0 + ], + "known_relationship_keys": [ + 0, + 0 + ], + "ordinary_receipt_sha256": "42f967eef57d1f1f85168d225258b50c79225fcafef0f1137a4f7f6de0d9e02e", + "output_hashes": { + "/home/ts/.local/state/openhcs-maintenance/20261003/current-wound-illum3-paired-v1/native/ExampleWoundHealing/outputs/1/Image.csv": "373f02427a4758051bfdd80efd7071774d8adcae60a2928c6d3bb67ad993155c", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-wound-illum3-paired-v1/ordinary-1/ExampleWoundHealing/wells_1/workers_1/images_ExampleWoundHealing_source_workspace_well_throughput/openhcs_metadata.json.lock": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-wound-illum3-paired-v1/ordinary-1/ExampleWoundHealing/wells_1/workers_1/images_ExampleWoundHealing_source_workspace_well_throughput/openhcs_metadata.json": "71582c62cabb2571ebf8a0de57f92fdf82c55a7ece3dac0bf2a6eca95cad84c9", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-wound-illum3-paired-v1/ordinary-1/ExampleWoundHealing/wells_1/workers_1/images_ExampleWoundHealing_source_workspace_well_throughput/results/Image.csv": "939735fa17a067137fea2adc77d57f9ce1df24bfcb6588c49023de1cc3998677" + } + } + ], + "source_head": "293e04acb53156a0dd9ae71476703e24f66b196c", + "scope": "Both ordinary observations versus both native measured observations; full strict files/values/correlation policy; descriptive two-repeat clocks, not full30 acceptance." +} diff --git a/benchmark/results/perf_current_wound_illum3_paired_20261003/timing_summary.json b/benchmark/results/perf_current_wound_illum3_paired_20261003/timing_summary.json new file mode 100644 index 0000000000..30e150bebd --- /dev/null +++ b/benchmark/results/perf_current_wound_illum3_paired_20261003/timing_summary.json @@ -0,0 +1,145 @@ +{ + "source_head": "293e04acb53156a0dd9ae71476703e24f66b196c", + "cases": { + "ExampleIlluminationCorrection_Example3": { + "image_sets_per_full_invocation": 1, + "raw_samples": { + "compile_seconds": [ + 0.5973958969116211, + 0.5914797782897949 + ], + "execute_seconds": [ + 0.6867749691009521, + 0.38519740104675293 + ], + "total_seconds": [ + 1.7173079238273203, + 1.3618650771677494 + ], + "native_execution_seconds": [ + 0.5970225902274251, + 0.6568904407322407 + ], + "native_invocation_seconds": [ + 0.6704615103080869, + 0.7205826421268284 + ] + }, + "means": { + "compile_seconds": 0.594437837600708, + "execute_seconds": 0.5359861850738525, + "total_seconds": 1.5395865004975349, + "native_execution_seconds": 0.6269565154798329, + "native_invocation_seconds": 0.6955220762174577 + }, + "raw_ranges": { + "compile_seconds": [ + 0.5914797782897949, + 0.5973958969116211 + ], + "execute_seconds": [ + 0.38519740104675293, + 0.6867749691009521 + ], + "total_seconds": [ + 1.3618650771677494, + 1.7173079238273203 + ], + "native_execution_seconds": [ + 0.5970225902274251, + 0.6568904407322407 + ], + "native_invocation_seconds": [ + 0.6704615103080869, + 0.7205826421268284 + ] + }, + "warmup_excluded": { + "repetition": -1, + "output_root": "/home/ts/.local/state/openhcs-maintenance/20261003/current-wound-illum3-paired-v1/native/ExampleIlluminationCorrection_Example3/outputs/-1", + "image_set_count": 1, + "invocation_seconds": 1.3667851807549596, + "pre_first_module_seconds": 0.2952348357066512, + "first_module_through_post_run_seconds": 1.0715503450483084, + "invocation_started_monotonic_seconds": 3808405.732912145, + "first_module_started_monotonic_seconds": 3808406.028146981, + "completed_monotonic_seconds": 3808407.099697326 + }, + "other_total_seconds_mean": 0.4091624778229743, + "execution_ratio_of_means": 1.1697251401982418, + "total_ratio_of_means": 0.4072239625881526, + "native_report_sha256": "437f3943b29f3335831f934c0c308f51134df18096016431276f7c976fb8b458" + }, + "ExampleWoundHealing": { + "image_sets_per_full_invocation": 2, + "raw_samples": { + "compile_seconds": [ + 0.34695887565612793, + 0.34340977668762207 + ], + "execute_seconds": [ + 2.856407642364502, + 3.1452507972717285 + ], + "total_seconds": [ + 3.471247054170817, + 3.7725879549980164 + ], + "native_execution_seconds": [ + 4.377218026202172, + 4.129441360011697 + ], + "native_invocation_seconds": [ + 4.462228200864047, + 4.201918839942664 + ] + }, + "means": { + "compile_seconds": 0.345184326171875, + "execute_seconds": 3.0008292198181152, + "total_seconds": 3.6219175045844167, + "native_execution_seconds": 4.253329693106934, + "native_invocation_seconds": 4.332073520403355 + }, + "raw_ranges": { + "compile_seconds": [ + 0.34340977668762207, + 0.34695887565612793 + ], + "execute_seconds": [ + 2.856407642364502, + 3.1452507972717285 + ], + "total_seconds": [ + 3.471247054170817, + 3.7725879549980164 + ], + "native_execution_seconds": [ + 4.129441360011697, + 4.377218026202172 + ], + "native_invocation_seconds": [ + 4.201918839942664, + 4.462228200864047 + ] + }, + "warmup_excluded": { + "repetition": -1, + "output_root": "/home/ts/.local/state/openhcs-maintenance/20261003/current-wound-illum3-paired-v1/native/ExampleWoundHealing/outputs/-1", + "image_set_count": 2, + "invocation_seconds": 5.988651636987925, + "pre_first_module_seconds": 0.3156425580382347, + "first_module_through_post_run_seconds": 5.67300907894969, + "invocation_started_monotonic_seconds": 3808416.643831191, + "first_module_started_monotonic_seconds": 3808416.959473749, + "completed_monotonic_seconds": 3808422.632482828 + }, + "other_total_seconds_mean": 0.2759039585944265, + "execution_ratio_of_means": 1.4173847898497653, + "total_ratio_of_means": 1.174330913866291, + "native_report_sha256": "907c654a35ae3f5b4ad9ea898a1d60070c75b50dd8796cb61f58b0fcf462b8ab" + } + }, + "scope": "Descriptive two observations; no causal optimization gain or full30/scaling claim. Native execution is first module through post_run/close; invocation is retained separately. JVM/import/load/warmup and OH READY/startup/shutdown excluded. OH total includes compile/client wait/default OUTCOMES/RSS completion. Wound full two-image-set native invocation is compared with full OH well, without division. Bars are means; all raw observations and ranges retained, not confidence intervals.", + "science_sha256": "3d89dc4daaceb34535ceaab05100b80b88487e32e67180a99595035b66c67236" +} diff --git a/benchmark/results/perf_dependency_source_readiness_20261003/shared-environment-qualification.json b/benchmark/results/perf_dependency_source_readiness_20261003/shared-environment-qualification.json new file mode 100644 index 0000000000..d75a360aa3 --- /dev/null +++ b/benchmark/results/perf_dependency_source_readiness_20261003/shared-environment-qualification.json @@ -0,0 +1,836 @@ +{ + "status": "SELECTIVE_SHARED_EDITABLE_DEPENDENCY_UPDATE_QUALIFIED_FOR_OWNED_SOURCE", + "actual_OpenHCS_head": "60b2ac9b4d4fd91558f68aac85ae39b55e575fc8", + "actual_OpenHCS_status": "", + "installed_distribution_delta": { + "status": "ONLY_TWO_AUTHORIZED_DISTRIBUTIONS_CHANGED", + "changes": { + "objectstate": { + "before": "1.1.8", + "after": "1.1.9" + }, + "python-introspect": { + "before": "0.1.14", + "after": "0.1.15" + } + } + }, + "direct_isolated_import": { + "status": "LATEST_OWNED_IMPORT_METADATA_APIS_PASS", + "mode": "isolated-direct", + "rows": { + "objectstate": { + "metadata_version": "1.1.9", + "runtime_version": "1.1.9", + "module_file": "/home/ts/code/projects/openhcs-shared-runtime-plumbing/external/ObjectState/src/objectstate/__init__.py", + "direct_url": { + "dir_info": { + "editable": true + }, + "url": "file:///home/ts/code/projects/openhcs-shared-runtime-plumbing/external/ObjectState" + }, + "metadata_path": "/home/ts/code/projects/openhcs/.venv/lib/python3.12/site-packages/objectstate-1.1.9.dist-info", + "default_discovery_metadata_path": "/home/ts/code/projects/openhcs/.venv/lib/python3.12/site-packages/objectstate-1.1.9.dist-info", + "default_discovery_version": "1.1.9" + }, + "python-introspect": { + "metadata_version": "0.1.15", + "runtime_version": "0.1.15", + "module_file": "/home/ts/code/projects/openhcs-shared-runtime-plumbing/external/python-introspect/src/python_introspect/__init__.py", + "direct_url": { + "dir_info": { + "editable": true + }, + "url": "file:///home/ts/code/projects/openhcs-shared-runtime-plumbing/external/python-introspect" + }, + "metadata_path": "/home/ts/code/projects/openhcs/.venv/lib/python3.12/site-packages/python_introspect-0.1.15.dist-info", + "default_discovery_metadata_path": "/home/ts/code/projects/openhcs/.venv/lib/python3.12/site-packages/python_introspect-0.1.15.dist-info", + "default_discovery_version": "0.1.15" + } + }, + "factories_or_registry_ready_not_called": true + }, + "owned_source_first_import": { + "status": "LATEST_OWNED_IMPORT_METADATA_APIS_PASS", + "mode": "source-first", + "rows": { + "objectstate": { + "metadata_version": "1.1.9", + "runtime_version": "1.1.9", + "module_file": "/home/ts/code/projects/openhcs-shared-runtime-plumbing/external/ObjectState/src/objectstate/__init__.py", + "direct_url": { + "dir_info": { + "editable": true + }, + "url": "file:///home/ts/code/projects/openhcs-shared-runtime-plumbing/external/ObjectState" + }, + "metadata_path": "/home/ts/code/projects/openhcs/.venv/lib/python3.12/site-packages/objectstate-1.1.9.dist-info", + "default_discovery_metadata_path": "/home/ts/code/projects/openhcs/.venv/lib/python3.12/site-packages/objectstate-1.1.9.dist-info", + "default_discovery_version": "1.1.9" + }, + "python-introspect": { + "metadata_version": "0.1.15", + "runtime_version": "0.1.15", + "module_file": "/home/ts/code/projects/openhcs-shared-runtime-plumbing/external/python-introspect/src/python_introspect/__init__.py", + "direct_url": { + "dir_info": { + "editable": true + }, + "url": "file:///home/ts/code/projects/openhcs-shared-runtime-plumbing/external/python-introspect" + }, + "metadata_path": "/home/ts/code/projects/openhcs/.venv/lib/python3.12/site-packages/python_introspect-0.1.15.dist-info", + "default_discovery_metadata_path": "/home/ts/code/projects/openhcs-shared-runtime-plumbing/external/python-introspect/src/python_introspect.egg-info", + "default_discovery_version": "0.1.15" + } + }, + "factories_or_registry_ready_not_called": true + }, + "all8_actual_owned_import_roots_and_source_hashes": { + "ObjectState": { + "root": "/home/ts/code/projects/openhcs-shared-runtime-plumbing/external/ObjectState", + "head": "a01f8939b9bf4659502a33fe3febe62cab0f3c9a", + "status": "", + "tracked_code_metadata_hashes": { + "docs/conf.py": "bc49d86e265031fd39550513524727428685c836d73d5434a43031db4490301b", + "pyproject.toml": "a0d2835c65fe7c65b5f40259cc1d9527095bf4a3b87d1f70030df6ef9e7ef16a", + "scripts/check_ruff_added_lines.py": "e88118d5e1fb5db477cc11fb80f594ba213482614c565f3ed6383d992995c81d", + "scripts/release.py": "52abee369fee146ee8cf83fa266b5f1dbaacc31bb5934e967265054dbc7561ba", + "scripts/update_and_release.py": "80896e49f856d6a193bb1dc3917f55d2878acf1476c8240333eda16b92e8e61a", + "scripts/update_version.py": "63d0085d6b72ff34bf9560f60e4a91351ba21416b4eccd9b48aa30d40c49022a", + "scripts/verify_release_ready.py": "0a8d8fec9af999c3bba6281f2cafdadd06365090536580c8b168f43c96674dd2", + "src/objectstate/__init__.py": "b972d45dccc8143cf141b31582fc50d2a9a1f992f3fa374dac2b07e1183ccd73", + "src/objectstate/collection_containers.py": "a939d07f5dc391b7131f7ffaa7d1390b0449b4931d54ed5b09b27f59056b6e9b", + "src/objectstate/config.py": "6db2d9de077872009f1d6defe351cf8f40e441a0de31ff574b02741cefb4ffe3", + "src/objectstate/construction_binding.py": "9cfed94cad1cc9d5cf2cf0f7e8f534f72192168bdf3ba90b2b8d7ee57f4950d3", + "src/objectstate/context_manager.py": "a01b0fc8aeb9b5b0888346f725f92cbfd96b90963bf20001b5414a5e6cd6c0e6", + "src/objectstate/dual_axis_resolver.py": "17fcda62912050bdcdd018bee2fca5f81c2f4940c5f27f2af3dc19b7691e1fb0", + "src/objectstate/edit_session.py": "003cfaff8d3687b0fa115e051c3cf833a3cbb21ad9d9becfe16c59359d656350", + "src/objectstate/field_access.py": "77f483322a504c392c0ca41cc3ee6b691d258396f70f00a61b98d9f4bc03d43a", + "src/objectstate/global_config.py": "a8187811f87806579640a8147f287114e7127401530178dd37e8d28ed788a6ae", + "src/objectstate/history_migration.py": "1c24097040e38c159ea7e809424c0b94ec6c34efa3dc84cd664ff6a2f790815f", + "src/objectstate/lazy_factory.py": "64ae924c176757863a84eef19b9df0eff516e32443c2661134ec2ae72f234bf9", + "src/objectstate/live_context_resolver.py": "bd169b0bf2e9eea833ffc1d28331d320b2386193652fca041387f32bf018d71e", + "src/objectstate/object_state.py": "735ce860ab650b281534e24e3c7354f37b64bb06832cf186d6b1f626f87108fe", + "src/objectstate/object_state_metadata.py": "4c5be42e313e3f896f2db0d3f89ca18ca6ab09b9d25f202a7b2af9e59a099ddb", + "src/objectstate/object_state_registry.py": "f848746a9c2a023a616c37531691073ea7bdb8d28d7db3bca5c8a3dcb176107a", + "src/objectstate/parameter_owner.py": "908606ec2da70f223a93071e92ca24affb3f172f7df14c64dfd27974f1fbb85c", + "src/objectstate/parameter_structure.py": "00a786af17bca57b4e819d39c76a6523af3bec116d119c323dea8c2953c7be3d", + "src/objectstate/parametric_axes.py": "7229b518f8d5cca522a3020361c16a601f3084bc5a7d34ef92a2fef11619e40c", + "src/objectstate/placeholder.py": "4e057cf3225dd38ef3859f20fcd1305526829f044af45ef616381ea734df8f67", + "src/objectstate/reified_generics.py": "39ad0897ec45ba929c0fae694dd870df987c06e2b005644189212fe224eceab2", + "src/objectstate/snapshot_model.py": "001cc83d354b040763b2da9aad0014619fdee22c82dce622dbd93ecfba780681", + "src/objectstate/subfield_semantics.py": "97aa6a7f2659260b1950c068f47d9bccec15087ed1852f1dd182272c8230c14a", + "src/objectstate/time_travel_profile.py": "c59d157f9cb85ee29aa64e18393d916ded656c6ce88bb46782f44e2463fcd007", + "src/objectstate/token_cache.py": "d6b7cdb71c15e13e8bab7271d70e0b96ccbe0825004c45c4e88851ee30a9435f", + "src/objectstate/transaction_checkpoint.py": "4c105f2078bf23c9312c600543623b9456de256c7093b9cb8a9b753b49b67530", + "src/objectstate/ui_visibility.py": "be0c60b66b86ebb696583ee394c0d45b05fd1f68a609a6aa0c29aa1098dc2592", + "src/objectstate/value_semantics.py": "4b8a43ca8667c592b74f0d46b8507ef8331402e376230dd7cac217870b2ae2f9", + "tests/__init__.py": "b0f08e026c34c8ec04203081ad79f7ed1c6cbabd784cf475333965f279ea33ae", + "tests/conftest.py": "0fa840dddea79e86afe717e146ba7ac7ee713b032e0e398b0a9f56842e4a1d62", + "tests/test_callable_baseline.py": "638929e6eb97a7c899443272e307beaa62a12922debdc7594a45ec0a85da3356", + "tests/test_config.py": "973b08f470fd54a4990cf39c7f176b9f5d02ed0b808dbf8ea2549a01d7b30d77", + "tests/test_construction_history.py": "88469c8157d4010b9877f76b7a605bb7222222d614e1ea22aeec0c39870d1609", + "tests/test_context_manager.py": "c14d3ce760520544cda14273e76df66606e47ae1bba410f83746b216b4a6418c", + "tests/test_field_access.py": "7484f7b0127e1be332ac013ea5f5c61ec5da9f2cd7fef9fcde8a8e8ab1384c54", + "tests/test_global_config.py": "f4624ffd22cf4d09bc05466dac91cf952e81033b34ab475bd1442c3d96887833", + "tests/test_history_persistence.py": "547d0cba078c2caec8b6217ec0b8713aac1ac2efd69d143e6549b023e5cd4d33", + "tests/test_integration.py": "df082bcca0ee4d6cf1c3899b4e43ccd2a004891446a05480bcdb1930ed467c24", + "tests/test_lazy_factory.py": "b3f1602d85a6e91a1b4e42490dd5253d2d0c43371a193d7369fe149bc839ceb4", + "tests/test_object_state_metadata_contracts.py": "dbd555d1659a1dd79c8c93c1d5168282a8cfaa3d727ac3fcc4d7d913eea00360", + "tests/test_object_state_restore.py": "3319b7244e0be237896902955f4c49829d4135c057116885935791bd8f125a81", + "tests/test_object_state_update_instance.py": "aef1aa303a2f3d68246f87a1a6871c0e0e48cc12d5574ef105be5aa3202a7526", + "tests/test_parameter_owner.py": "b28675a55ab72d8fdf011f972e3c5154fc683fc8206a7195342ac0a774bd873d", + "tests/test_parametric_axes.py": "8717ac074d559294e00a3d33afaac6415230efcce78f38b1e296a11c9596dcce", + "tests/test_placeholder.py": "1b9d20e8931234622ef1cf726d12e8e4fa00328c0b1cb33e9eb0fdf7acc1631d", + "tests/test_registry_subscription.py": "c634b5e416a7ea3ca04abcab65679c2852595c595b6e23cde6424ba9f6c7643d", + "tests/test_reified_generics.py": "548f5b6a282fc26b73cb5211fc8a9eb92f37fe9cc57e37cf964597293fe98866", + "tests/test_resolved_change_notifications.py": "d0addec005be985da187845efba11e1dd03367b5b9557cc1fcc54a119e42c66a", + "tests/test_subfield_semantics.py": "f156d9666a909abe9c9dbb8f69823b1e88edab310248687c4e012ab97e5a43ec", + "tests/test_timeline_projection.py": "e02529d96f61f3601c91fe30e133c4f78107d3ea6f65c864198b232b8ad76780", + "tests/test_transaction_checkpoint.py": "531c4df6b3fa25a28ac17d020532179877d4f53d66f57af1bff7beb07d08f89d", + "tests/test_ui_visible_field_projection.py": "27e016e8755374e9322460b83344836f9a3f1f0e54e9303c4b16e6abf775baea", + "tests/test_undo_redo_cascade.py": "5f8cd61f70b966ac506b5a2ba4460d58c789137f7f992dd7537d572efdcefc67", + "tests/test_value_semantics.py": "fb98e8637abe45a981faae3b61fcc9ddc14ef84b4ef5e41b95fa5736bdae2968" + } + }, + "PolyStore": { + "root": "/home/ts/code/projects/openhcs-shared-runtime-plumbing/external/PolyStore", + "head": "84f322e46871de5ed47e7fd20976ad03e533c1c4", + "status": "", + "tracked_code_metadata_hashes": { + "docs/source/conf.py": "7cb4e271ad57f025b60ede742e8df94a095dea71e32aa44cc7527180d8d90bb7", + "pyproject.toml": "2f3edfdb1307f3300e3db056b2828814017270a9726f4d7bdac52caf84f96f8c", + "scripts/release.py": "25ef09845453b73a29ea84c303c6c77a79f291775bdba97347f296f35e8629d1", + "scripts/update_and_release.py": "80896e49f856d6a193bb1dc3917f55d2878acf1476c8240333eda16b92e8e61a", + "scripts/update_version.py": "e96bc7111806eb9a15b5d739329a6a41730fc0591e31f7975e52b17e67e1f721", + "scripts/verify_release_ready.py": "1c32aae8b7ab774eb0fb99d0a51ce6535ed7ee5020f44ca9dc8f6d3ae50af01a", + "src/polystore/__init__.py": "15dabedec6acd92b025d4a0b4e8151227a4496e8b7d5e87f28713f7799919b5a", + "src/polystore/array_payload.py": "3eb7e2cf8eb01a2b10b860778a8fd4ea47e7557fdbe28ab8adf31045088e145e", + "src/polystore/async_init.py": "21d9b8af54ff21247a2012d1ae759550ae0147cf75f667a73b4a5a8387bf3d0f", + "src/polystore/atomic.py": "5e412948fb919ce27f09971b0a5fdf0851499812e4c0ae8bd456abbd8ca86b90", + "src/polystore/backend_registry.py": "a4c4e73a79aa4363301f76727b35db2c8b55fa14107f8866a05f74da4fefb64c", + "src/polystore/base.py": "ae641affae21b61448816a14bd68b7f2f3fc0082f0f1fbe51079ed32520450b1", + "src/polystore/bioformats_java.py": "e7ee3fc888dfeebaab48681ac3e9dd2463cca693a0ff0d77ce274c72135666ff", + "src/polystore/bioformats_storage.py": "0f57d0b35619de4aa6fdad0839ae689ae6f91b0be099fd0b28742c28795f3b71", + "src/polystore/config.py": "62c8acad3da3abed8ccf7f1166fc6a0d094be1c3e842cec6446780541df292a0", + "src/polystore/constants.py": "246da078ce8a3aae6d1fdb76183f1ff724795014cbca4d670b80174f74084635", + "src/polystore/disk.py": "cf089b8c79f86099a7cea1b6cbe43ceaec6331196a44b43183f2e64b7746c219", + "src/polystore/exceptions.py": "0ecbd94af34ae3d1a37eab29e1f72be3e68c651c9a93bf52264a783a8fc65ab3", + "src/polystore/fiji_stream.py": "62a60a36f1da5668f60bc0b4e3a5d0e65008042b2361787f4909224dd9b51db9", + "src/polystore/filemanager.py": "877a2b10731b12904b1784a5b42c9e39688e3a84f7f86018c1c2beee96ea2296", + "src/polystore/formats.py": "6f7ec984549b45a31bb32b9051672e996a67d9caab3ce2030ddc7d50e17101c5", + "src/polystore/imagej_distribution.py": "29000b7f7d8067a8a1667fc8ee603d3c2f33fd87f0a318a21cf0093473df49b4", + "src/polystore/imagej_runtime.py": "150983b2da981b31f974ad384a0fbadf5804003fd59c085993701b876384276a", + "src/polystore/memory.py": "4ac155187a80c5b6f096b2170d6851e6ce119938222beef4bd99440cbccba9e8", + "src/polystore/metadata_migration.py": "4390dc79fd1f9dd3fa405b961ea15573037bc19c6db2b31b36a5bcb7170abc5e", + "src/polystore/metadata_writer.py": "987b8ff3cfb45b170656fb7dd405abc68c460381871ca26cc26cf82e0550e256", + "src/polystore/napari_stream.py": "29286154e37d7eeb2c75d9a48cd12fa696f40c02d5ac35865360b7673801f905", + "src/polystore/ome_zarr_metadata.py": "ed0e4a3de24a6f590404d98578e19b76c9c76b27e854639e68b521f49924fbbc", + "src/polystore/ome_zarr_storage.py": "005bdd6ce615ff115050e1853aab0c56c50c65d1361c31ef6219bb0d6c4852b7", + "src/polystore/omero_address.py": "8a3ae8789fceba0f099eef2ee983d858a8f83b764f19b70dfa7bb88f521c0c92", + "src/polystore/omero_local.py": "35d39564317510234c2a3ded00bb06a09417d1b6f7359e52e74c7bd0a086f642", + "src/polystore/omero_tables.py": "910aaa6bea75f40bae82df71dd414415278b1387b80c7f1bc11e8d681874451e", + "src/polystore/omero_text.py": "9f51daef3d96cf191994d8a9c7aacf6182941ec2b0ada3f5ba61e0cc4f9412f1", + "src/polystore/roi.py": "fa945e9a3f7272e72f3ea022c7a3ae6cd30520ed7924591dd3f3cad5d0e71fc0", + "src/polystore/roi_converters.py": "50c37e5b070db7cbe418a5a64576595ee3ea7e5bbcf014492f38958f4debbf07", + "src/polystore/source_tile_geometry.py": "ebe4a422ec76972f2318ba56910ba6ccaef28734764ed3b88a3ba478ed69d322", + "src/polystore/streaming/__init__.py": "e401faf53b6fb9a08e237535313e5b99d7e371372875182b76132921233e5adc", + "src/polystore/streaming/_streaming_backend.py": "7caf2252677a894a5a761b60c473b92184b83745608c2b50a75eb1733c77cd10", + "src/polystore/streaming/base.py": "353e87dc92ad8df2ccec0136ab8ef7de7729896522cf8b16c0ec79bde455c176", + "src/polystore/streaming/handlers/__init__.py": "78daf5078f1914dc5b646ebeeb79bea336036b3b4737e122865be41ab7b24f03", + "src/polystore/streaming/handlers/fiji_images.py": "b5f06390cfeaef6c6a10c06bf9af00eab29f90ce1bb2899794d2e516cf86c7d0", + "src/polystore/streaming/handlers/fiji_rois.py": "5edcdc8d7344c5793730beb5a1c3baea89e96b13e62b746cc1cbeded3217a978", + "src/polystore/streaming/identity.py": "a8e48d76c8fd222515121e2ebc879dccc820e0ebf5b576a8728c1a7ffd35dc4e", + "src/polystore/streaming/receivers/__init__.py": "07953a0ecae9f307b9a2706062c1f452648267887e8cd03fbdb87d4b301b4877", + "src/polystore/streaming/receivers/batching/__init__.py": "c045df607fc2c07983659caff8b191660dd2ce5e73aeceb89894be3a457926ec", + "src/polystore/streaming/receivers/core/__init__.py": "b61b9545e4e373556d5beb87a23c3f6475238361d0c3a4cf18a3a5e197dedcba", + "src/polystore/streaming/receivers/core/batch_engine.py": "36d1dd9a7a2beae134c6f149ca148dd4cc2921fa2feb37cbcb88c42312743055", + "src/polystore/streaming/receivers/core/contracts.py": "c89f3f2dfb3e23482112a6b98ae3238d1768b2f4a01b4b2d605b698bd307f561", + "src/polystore/streaming/receivers/core/image_presentation.py": "dbe1395afce5a280fc1ab0c66bf302e324577ff15c6dff7a1698f50f1fc72a73", + "src/polystore/streaming/receivers/core/layer_inspection.py": "e93f707de62516eb0d48d9fdb0f71862b4265389723ca92a05145fce99a28802", + "src/polystore/streaming/receivers/core/metadata_presentation.py": "5e021ff3659039856616a75b4e19918b709121ee4b8902d39430f110b1adc5e8", + "src/polystore/streaming/receivers/core/viewport_presentation.py": "936378683122ad28deba10d71e9561abfc904017582e345316bf1c760d2abfb0", + "src/polystore/streaming/receivers/core/window_projection.py": "e95d0ccda66aa866082c5afc5bf9908259c727ca33270d3f069384651e1783e3", + "src/polystore/streaming/receivers/fiji/__init__.py": "a86e999752d8212da5bd58f1a3db43ffa7ce867fb0ae1209bf0f148bfe5b4b50", + "src/polystore/streaming/receivers/fiji/fiji_batch_processor.py": "165919f2e36c37e221bdd6f17e4398795745a95da9ddd7bba0ab93d74b9bdab2", + "src/polystore/streaming/receivers/napari/__init__.py": "ab4ba3ba76e98365e67abf6f9d79c0be098a774bf9e17e8523fc430a0babb9f1", + "src/polystore/streaming/receivers/napari/image_presentation.py": "1abb2d4c33ea073deb415cf9a242baa64d0b9d73985b7920d72508f2a5998a8e", + "src/polystore/streaming/receivers/napari/layer_inspection.py": "6bb86202480b5aad55d6641e3a6891105c5284d4408ff1cb7f8cbb36929888cc", + "src/polystore/streaming/receivers/napari/layer_key.py": "650eba665a58130fd67c38b164f97f677d805e07e53c2c7f367f850ae6db4a8f", + "src/polystore/streaming/receivers/napari/napari_batch_processor.py": "c3ed3f9fb4d89f82cc887a4d7775db911c96fc7e67d437cdfe8c4b78e62a16e3", + "src/polystore/streaming/receivers/napari/viewport_presentation.py": "aef743171c8d27ac56b53217f8fb2352584d447b33791ee2ce3e1c8fa4ade356", + "src/polystore/streaming/viewer_transport.py": "3b883e3078ded6b8e9c80e135a2eab876f9399fb7813dcd1dc8dd8f6049a3537", + "src/polystore/streaming_constants.py": "645e1685a1cf23167b2f6f06d4807c76444c339fbde66f3b12de9bba3adbe170", + "src/polystore/tiff_header.py": "714c6ddd0ff3928df37b2e65775c2987c285538b2375ee17254ae0dee868fa6b", + "src/polystore/utils.py": "1dd12cb9742f58f9537f1e23832f44f90deaf4332de8ae9b97e8df711ed261c7", + "src/polystore/virtual_workspace.py": "b19fcda85369d812e70bfc1a0efc5d8861ae256f69e94372e2e9515c591d36af", + "src/polystore/zarr.py": "b9404235a3a7882dd6f64383c11aeb6073c8f3a6485bec74264ad6434a1ee35f", + "src/polystore/zarr_batch.py": "8ed86ac525b561e6557a8ac55c6cb0d3954311a31d3ae65ea84af196246d60d9", + "src/polystore/zmq_config.py": "14123ce6fe232144f8a4fa086cad164a0b29e3b014ab809810d622e39ac92854", + "tests/conftest.py": "5ca35c45b774ffda10030f950823eedb160628aad1076b805e401e277bf624f4", + "tests/imagej_cache_process_fixture.py": "bf04cebf8be7fb4e911ec1df75cc3e4fc311745981975620b2946b308c461d93", + "tests/integration/test_imagej_runtime_live.py": "bc1c16a755e12682b5b94b81b902068fb4a2e4b8f8b708a43c814b28ecd78bf5", + "tests/metadata_namespace_worker.py": "5db68ec70ba017d1b81cad2302788dbcf0a1cce5be019358259d3aec5ffd7ef5", + "tests/test_array_payload.py": "95a02bc11cd21f57da986ab8f90196a7343c70513d034e69dec581c413ee802c", + "tests/test_atomic_lock.py": "0ee06b9b53964df6777f72cd0ddf0faaa63d9316ec7edfdedb6e1b6b9087f736", + "tests/test_backend_registry.py": "6af08f5ca00bebde1a4190bb40cc2df99e025aa3465521770a22da0cc51b5651", + "tests/test_basic.py": "803e5643003e4bea60fb48c89cc84d732c77b2a3a68bccbdc6be3747ca053aba", + "tests/test_bioformats_java.py": "bf8b626c3081c26de73902822129ece5128549ec6544b604285dc9b1ac2ddc6d", + "tests/test_bioformats_storage.py": "e97642deacceab3348e8a337b34e79da235c1e1283fccfb844c0142f8632a35a", + "tests/test_ci_action_pinning.py": "a636dd4d70e231d06c5de2802afc89c389f678b3b49a40ce8463eac5b0c308dd", + "tests/test_disk_backend.py": "423c0bb9389cb002ad9c5384add0e08d4c8f99c4279ffa7d1d6621ff90ce9747", + "tests/test_disk_coverage.py": "8f0486f4611c3cfbc449e5cc7276a3cbd72f50de683eeea9647e68a0d2533be7", + "tests/test_disk_more.py": "78ae7241ab3a1d031bc733fa8f20368ba24b225c59cee47ab00624da8b77aab4", + "tests/test_filemanager_backends.py": "f506fde0e7aa4fac67c9682fcb7ed5c850c0a9ac069dd3a6ed7732427ab5578e", + "tests/test_filemanager_extended.py": "3b20c0038ba749f3d4a0f787d2e854bcd7c4e65ea58305231193f415fa734a4c", + "tests/test_imagej_cache_environment.py": "0c3b854542257e09ec13806048ceb5cc3deadf1a6302c621f44c3bc4e6efa9c7", + "tests/test_imagej_distribution.py": "fa7740c10975dfbc2e654ac3b7fc0df0f2f08599a98966e51c2c046f8cae01e1", + "tests/test_imagej_runtime.py": "fb5ce7c8d53354eb46756644d3d0c135bbeae10a21a76718f67e458f046bf480", + "tests/test_lazy_package_exports.py": "ee015f6ea3c2dc198f522db1f494f886b892540750ca3289f7f39909c4700460", + "tests/test_memory_backend.py": "ac68a5bb7c0cc4bf6a74bf3d54cc3a75df2986b9f73e92af5316d878f678b16b", + "tests/test_memory_coverage.py": "a53b737d7899f52ccc0f683ae0312094760e532be709c17a5accba7249a60542", + "tests/test_memory_type_authority.py": "ec326f948fa957b0cc8358629199442db397b9676c884d6e730e23048468cdd0", + "tests/test_metadata_namespace.py": "5a4809a6024b6eec30130ec1bc98cdd6a2541779496cea717f8a89a98d5ca5c9", + "tests/test_metadata_namespace_ownership.py": "175737cbf844b620132bea2c5e5827ffaacac01bf53de136ea49ab32727428f9", + "tests/test_napari_batch_processor.py": "a62c8875fdde0bac50059aebc3b54dfb736246ba7e1980301ebb9e7124592cd5", + "tests/test_ome_zarr_metadata.py": "7444723fcc0bd0cdedd6d8b9454be57ce929caa61698539da55c782f0b7fb420", + "tests/test_ome_zarr_storage.py": "b70a93d160cb0ba0acfd603c75ade965fbf1f95158d7c0cfc680e6a8ce907deb", + "tests/test_omero_address.py": "15d81321402ccf015f5d687b70c27e64d58ba97e719bb090efeea74821e7ffd0", + "tests/test_omero_image_plane_batch.py": "ea857b139476e127a0ee026c20cf5ca918a65f45a70bc1fe27787313d6e830b8", + "tests/test_omero_tables.py": "45ab6ce56b95dfcf9b2c202e2caa587a67bd0de4769e77b36a9986b482cea159", + "tests/test_omero_text.py": "ddf16ee95766440f5ec4d3b0e60e159cc70b2f7694e7136ec13a72c85117ca88", + "tests/test_png_format.py": "f74821025f5d962a45287d88ede69793601725f6f158fdd9cb4c9635ad75cc62", + "tests/test_receiver_layer_inspection.py": "b1b153e86978aa31e933a26072be6e3a19f4881408d10df9044fe351ad0483a8", + "tests/test_roi.py": "a2f256e55483b45ce54264fd667452230ec1024ddb7f57432711b6be7278912b", + "tests/test_roi_region_properties.py": "5cac0122893d4df5289b2e7a14018625333103a713c87ae8c559872958ba0743", + "tests/test_streaming_cleanup.py": "2edca13d06e25936076c624fd9ff6db3b66d0997c08c41082c822a0b7e8fe8ab", + "tests/test_streaming_identity.py": "7d0256ce52d48d944961bad8dff436197c45dd0ac93c8946bc354aec0cfcabff", + "tests/test_streaming_metadata.py": "806cf4998459d90ed532307a48d0f793bfada277c69537ec031fd4e28babcb46", + "tests/test_streaming_receiver_core.py": "c79e5a32d46c39b6974d421bef2ec90099e67d6b6e13d4baa5eaa48588781548", + "tests/test_streaming_return_route.py": "e20baf9443d034ab18bfff0bfc38d60af7d7245e94ec0b7e01f80d8ce403c120", + "tests/test_streaming_shared_memory.py": "c5ecc8e9c027f5fa14783ce9e568b07eb3f39ddd07254e5fa2f9847d1a86aff2", + "tests/test_viewer_transport.py": "35f4e6ffd0bb7de1c5ebb1163e2d46d71f8dcbd0544fe3494e197c2d1ac610be", + "tests/test_zarr_backend.py": "7896159c33ee7fefb89976291e35db507acf282e92361c1abd86eca54160e2fa", + "tests/test_zarr_batch.py": "883da1109c08c53ddb5e03397e5e43bdb0f878c2da8ec4c4158ee9a70520bb17" + } + }, + "arraybridge": { + "root": "/home/ts/code/projects/openhcs-shared-runtime-plumbing/external/arraybridge", + "head": "1e53d03d9f468322a1c085c8be29485fb139caf2", + "status": "", + "tracked_code_metadata_hashes": { + "docs/source/conf.py": "1b43c862dc93e51e93c0ef0435a9e5cf208665d84a2d0ed1c2477d5e4dbf3832", + "pyproject.toml": "8134c94077df2defe89328963c250e6defaa2ec2b5f49c190f0966e9e575661b", + "scripts/release.py": "3e9caa24fbfde769e347f52542a557610bb02249b81aaa71649bd579d081b69d", + "scripts/update_version.py": "9d57e7324469c34691c4561466cc4d3330485812ce1c14418d8034d30bd85a3c", + "scripts/verify_release_ready.py": "bff7cb1232eeceb6d6d235309cfc75866c7b6c1f44c48f5b2ab65f856830477e", + "src/arraybridge/__init__.py": "ae1b2dd87b91b191356e9e1fdb74a32ba7131cda6341402c4a7aa087d47a4140", + "src/arraybridge/array_geometry.py": "0a8a5f1a61552b057997e94e4c89a19b5615875f307949e0d11784179f2a94f2", + "src/arraybridge/array_operations.py": "7e9ebda3d058702cdf8662dc5ab1faf1254649f3cbde76fa0adcbe02677fa103", + "src/arraybridge/array_payload.py": "ebf8c9c0f4726b4307ad435203d9173e54c84a92dad06ef8aea0d56a51972b1e", + "src/arraybridge/converters.py": "ab8e04e8f835ac9cfccaae964083cb3993efd65aaa7147041b81a1e03e4cd7fa", + "src/arraybridge/converters_registry.py": "fe11ed6ddfb748c20a530f1fbcdbb7b703d6258eea1f237243f361569dde4874", + "src/arraybridge/decorators.py": "28f9bf4770bd4cc1ef34045fdef28065063ede029296f62b8a6c4140cc88e40e", + "src/arraybridge/dtype_scaling.py": "283818c82bf182c4172c9265fdbb399c7e3acd08a6b00edcd4e96feb1276cf5a", + "src/arraybridge/exceptions.py": "7e17a3e594b7f50701156ccd78d623a2a78b5673a0c30a7e7162267b6e63caea", + "src/arraybridge/framework_config.py": "e724d3b7d356730cca0cc5db73e7ea09d88597ea6228eb774949f19915d70909", + "src/arraybridge/framework_ops.py": "eac427f155ed3e7e10ae0f9cc603a9a17d7c3f54b30db339e23f33873c94fff4", + "src/arraybridge/gpu_cleanup.py": "003238c0c2e4f4620ef6b27a049b8d937b9923200da00a89ed51539cb273adb1", + "src/arraybridge/oom_recovery.py": "846bceb891d54a8a6222a6e5ce830596a5bcfe82ba66500617f978a5f1258de2", + "src/arraybridge/slice_processing.py": "e51d743a61d6f0149b245c13d5445dd92cf73f5e68e4485a236567554508be44", + "src/arraybridge/stack_utils.py": "1558a43745c6f97af2c3ed69f4c6924544d97adee42dccb48131044528dcf6be", + "src/arraybridge/types.py": "7b94760d57e54008d7adf4e4d37dca45d8a2c288a9dc8400be00c26148cf7624", + "src/arraybridge/utils.py": "46a4e1b5849c3c4384406e3dd5d03c6ff56f5138e07058702db8747ab42ee4db", + "tests/__init__.py": "a0ac3b43f372047f4b85b516a7e4471f98744cf549dbeec484ff3f79728f0257", + "tests/conftest.py": "6a2fe5d7206ac30e37e544ba8ff939ffa4576565b9c7559fd660f0e41db6f24c", + "tests/test_array_geometry.py": "f9c0e91d6275a940399418f2c0de810ca90c781c30219d720b745f1cf912f0a3", + "tests/test_callable_dtype_default.py": "52f343317d9d943bee46edf4edfa7e1dfd9afbe2e2ced2a297b9bc764bacedc7", + "tests/test_converters.py": "390edeb089747cc13a6378d715996f238ece1610f7aa4e9e0c3a6c932a23e315", + "tests/test_converters_registry.py": "f40974f61e55cc49fc31dd53af0dda1790301edc2218d5ec6dbcbda0c712365f", + "tests/test_decorators.py": "0b841b293e82b59133c895159c9773552dc4e7a508bbe7976da45aaa1e5d894d", + "tests/test_dtype_scaling.py": "7fcea155eede82781b9566166079a86e403afa075c5335118696a390c1ed531b", + "tests/test_durable_decorator_context.py": "53e4bfb9a2491b6d5a238ca4aaf24ffce5853346d46621e25ebf92adfdf70642", + "tests/test_exceptions.py": "441f10606ee9175814b01a243f8aea572f341bb53517c31c2c719ce41a36fe27", + "tests/test_framework_config.py": "4995b8649bef8ff4bfbf80dae282a6c8e008b0120f1a905f118903fa903e8d8c", + "tests/test_gpu_cleanup.py": "bcd6ef4f4f56850e1f12eaf9fc237d756b06841bd1c2d093ebbd81cf1a04a0bf", + "tests/test_integration.py": "e8d87ba83d8fec2ea7a9841c413277516bf665aa08f688b29da819a4c545edd2", + "tests/test_oom_recovery.py": "773b96e901e85663b6418d4deefbb28bb3ac9298b7b20589373cfa0de05e2bf4", + "tests/test_registry_integration.py": "49b88b4f692af569b66c298c8751a78b0e28a08f4db41034ef05684352df5418", + "tests/test_slice_processing.py": "b7f996dd6c38382148c1b48c5428d33775c3067f91562f082de9ec0ce20ebb5f", + "tests/test_stack_utils.py": "918e015e452b31adef93ceb829e949043390d22888daff9a295317940a58a6bd", + "tests/test_types.py": "ae1701b48c68c6f07bb23d83800ef3ca049545c254840ad5a7863db4213b3c16", + "tests/test_utils.py": "15a78a8269843d90b8dee4a2b4a50cd1b34bc791fcd1588260d45cae3956aab5" + } + }, + "metaclass-registry": { + "root": "/home/ts/code/projects/openhcs-shared-runtime-plumbing/external/metaclass-registry", + "head": "393a7e03003cdc56df9013f932ed4f26e632d77a", + "status": "", + "tracked_code_metadata_hashes": { + "docs/source/conf.py": "1d1618299bdaed818c3518ccc11dcd99f7277e4574b78a1db345c85fa2d949dd", + "pyproject.toml": "2bc5a1a364bb17b03a4220cc3595d7889bfad3f731de3fe78453b16908b291c2", + "scripts/release.py": "19344fc3616a3d63e035df687ac82e8a040d0f7b69d5fb934c6e801df0ed5947", + "scripts/update_and_release.py": "80896e49f856d6a193bb1dc3917f55d2878acf1476c8240333eda16b92e8e61a", + "scripts/update_version.py": "f15d84a33dce9188e36576b21a84b7423dc868fc5e7eea22f8528dca83c3a5ba", + "scripts/verify_release_ready.py": "8747b1de6233c106025abe5fc4cfbbdf2a8d07641566445f4151b6fe4b5a9e1f", + "src/metaclass_registry/__init__.py": "b7dd8d905bcac00f490a6155df09e68d148f3e7b8238fed2854f2e1b5de06567", + "src/metaclass_registry/_home.py": "6949afb54c145a8c58f680c61177e3aa7a04e9b432b73552f5beb4b1b92169e0", + "src/metaclass_registry/cache.py": "10ba153bbbd6a45388a47aa28f5b18ab77847a33acec4820d31cf909153fb6ca", + "src/metaclass_registry/core.py": "5fbfc22dee24ac7cf653209ca06ca511ddedfb2c9e96a5354d7d4d4600828493", + "src/metaclass_registry/discovery.py": "757958272d11633e7b854c7104c07f0d90845c37fee6ab0c3646fb14c2ed8daa", + "src/metaclass_registry/exceptions.py": "333ae9a5b87cb884213a1833fde35c178734f5e684a8f772d6c0e35a090ec987", + "tests/__init__.py": "dadf7fb5f53a6c573dffaecd51460f3d36c83fd4ed903a5ed7ed21da331dd9d3", + "tests/conftest.py": "a2ad838c1e90bcfa8c368c51f07f473a85cbe4a95d27134349f94bfb1a57f767", + "tests/test_cache.py": "c0d077f47be112b257abf7ad574ca2bb4dbb7e7f3fbbe0c8044b69b69bf5c7cb", + "tests/test_cache_path_projection.py": "8da2d89cb7e88bc838b0a0d59068afe4a6ffc0010e3d4fcc196f55519d730ced", + "tests/test_core.py": "26446d33fcdd012ecf12ff7e541ce434aa38fb8f1fb110ee4ce4c74cbf0bea00", + "tests/test_discovery.py": "f28535b526c4fe95d68a33386c4378237468fb160867dd9b07a55de920939d3f", + "tests/test_exceptions.py": "11dd2d86ec4baea6834b28d9f368bb71c90dd91f23a12dcf795fb821a29ebf1b", + "tests/test_selected_discovery.py": "b20e2ff2441a37fc2700223e18cde1d64d1eba314521a656d8be2376da2c0b0a" + } + }, + "pycodify": { + "root": "/home/ts/code/projects/openhcs-shared-runtime-plumbing/external/pycodify", + "head": "792b03413331fdf107e369c924c257a2f0b16126", + "status": "", + "tracked_code_metadata_hashes": { + "docs/conf.py": "3cacb5b7a11daa491ff739fe6df58494ed38e50fde40d6bd6fb7c9b4d4eb782c", + "pyproject.toml": "1103178d6661d94d66f6b43039d0961557e6d07861e46bbf8df18b6d40a0b1b5", + "scripts/release.py": "9027086b71a742b688bc984dd2fe50c4af2ad6e5ba1b1c564cf531a414e19f62", + "scripts/update_and_release.py": "80896e49f856d6a193bb1dc3917f55d2878acf1476c8240333eda16b92e8e61a", + "scripts/update_version.py": "f93a6a1ab4aa714f699edab98d36d3f610c7b7e14ff5748a22fc656214958d8d", + "scripts/verify_release_ready.py": "aa51d925335037158e0d34d0b198039e4d3833df564f01622ae4005bc7e9d6eb", + "src/pycodify/__init__.py": "b839bc2a7cd2afdfd8756eb39f22b791cb4f7aa55c0fc9c11099b7219c9c663b", + "src/pycodify/core.py": "b32dea495ceb8745c1b363f2e42aa62eaa28a1d54198a5d6541e0b1546facfb4", + "src/pycodify/formatters.py": "08791a7f3cb779889ef24a5bfb395a1acfb4d3320fe9a7cf037986c98a9d7faa", + "src/pycodify/imports.py": "17fc080d60ef168a9c211f27111b04da1d527d2bf87e2188c674e4de9d25bef1", + "tests/__init__.py": "efd53630f4e3c520366b8aa444fe2d4d33c07c7caa0e3841fbb43a04cfdd9183", + "tests/test_core.py": "164dd47f93e4adfd8fe9de851f5db74744509179f6eaaae877be879f22689e66", + "tests/test_imports.py": "ce63bc44d8fc24a02e3439a7b1504b4dacf21e64ac51f1581e60f0099664c3bb" + } + }, + "pyqt-reactive": { + "root": "/home/ts/code/projects/openhcs-shared-runtime-plumbing/external/pyqt-reactive", + "head": "ad4948775ab81180a354d4b793d17ee5ddff3972", + "status": "", + "tracked_code_metadata_hashes": { + "docs/conf.py": "2ef313507c9b6ce6941cbe82863a0373b818ea5627c9dec2824953ffc7f312d3", + "examples/tear_off_tabs_example.py": "5506bb39a1953d99d1a8b730851a53233dddd79aa0a4cc738f422fad10b2d640", + "pyproject.toml": "524865db6ac36de136ee2b8dd43b1c741152f5ade3f8195f637650d252dbf8c2", + "scripts/benchmark_form_construction.py": "a2597d87f99c5ad0859e66732f7f7e43a73b4c896b3733d2ee9d501227d1a3d9", + "scripts/check_ruff_added_lines.py": "67ed9e6064204caca990b7b7054cd0774f59b235e241a4fa46db28ad48213ad7", + "scripts/release.py": "09fa8c9c7ccd7f4936aa9a9994b6c47726ce27e8bf99e0cfdcf06d528ff4565f", + "scripts/update_and_release.py": "80896e49f856d6a193bb1dc3917f55d2878acf1476c8240333eda16b92e8e61a", + "scripts/update_version.py": "3f771c59e65b5f6674faef3dafa3b660f152b58ea61114ae0a37f840a9ce4f04", + "scripts/verify_release_ready.py": "7a023ed885a132d922f1fd3942dd56b66158958192f7e5371e838c537cd5d2b5", + "src/pyqt_reactive/__init__.py": "5b37a90f246987a98087428e80d2cbdcc030b80ae962c347482f21719054f68c", + "src/pyqt_reactive/animation/__init__.py": "f449133ede280b74aec90dc85e88a9a2800e38c45b239996d9abde51d0cee6d9", + "src/pyqt_reactive/animation/flash_config.py": "efc6859a2de5115775a940be0a9e1c5e58f7e60e068872f11a256060b045fdeb", + "src/pyqt_reactive/animation/flash_mixin.py": "37cd2b32047109fc16255a3f9a9938ae553d5f8bd5987cd10460c7ba500f1486", + "src/pyqt_reactive/animation/flash_overlay_opengl.py": "f6bc6452e56cae0a17b07244547b55820c091fa20615de3ab1a8159f638f1dd0", + "src/pyqt_reactive/animation/flash_trace.py": "9a2e71467be16a31e0abd1f7999253e4842447289400d15cd3ff995fd06af9a2", + "src/pyqt_reactive/core/__init__.py": "c111f382ba9945651f0b385131896ea2ae522141f7a91f7a1e1eae9657e97122", + "src/pyqt_reactive/core/background_task.py": "4afa0d07107479f028557d23f15a6c5146cdb9f33e253b81f856f9092824c2aa", + "src/pyqt_reactive/core/collapsible_splitter_helper.py": "8d959845294513e0240c994c1bd9142a968f682be994cb2e3fd02f38f0403c3b", + "src/pyqt_reactive/core/debounce_timer.py": "7c3bcef0d7dc0107df0d413f6188ece136e3be5cfea473e3e74b69496af95763", + "src/pyqt_reactive/core/deferred_callback.py": "b52167f36cef2e58bc0f6b38c15359cbfb28a12a71c3a41ad9ac62155f357803", + "src/pyqt_reactive/core/future_completion.py": "7ba6ef203bae81319004ccc4ddfe4226e0230b177df663cfb0d02c364e1dbc47", + "src/pyqt_reactive/core/log_utils.py": "8a2f67434497cf5bc3d637b945b75590c735ff8d97b8db56f9efe5bbaff5e351", + "src/pyqt_reactive/core/path_cache.py": "dfca58e2ae9deb036d4df4038ce8f78125cb5ddeb2e691293bb4d54ca673b586", + "src/pyqt_reactive/core/performance_monitor.py": "09299865cc6641b87bdc195442a297d982ee3909b35c8d2063859933180834eb", + "src/pyqt_reactive/core/reorderable_list_widget.py": "edbba72d7aa88362860b923c0b86715a8349dfec9a7d85660f12cf33d859429e", + "src/pyqt_reactive/core/rich_text_appender.py": "fce3d7be3654c988f6eb16117231e6032718b28608f99f625054ff60269768a2", + "src/pyqt_reactive/core/sort_utils.py": "ac9cb5bd209113980dc398197f461e19e6c9716a5110a889bfdd7bf7b85f3d81", + "src/pyqt_reactive/dialogs/__init__.py": "a9ab9bde099f50c796b1c29c77482f0bf771591fbb12514f1b9ab8dfbddeb4a9", + "src/pyqt_reactive/dialogs/group_by_selector_dialog.py": "a62fdc652c3ff9fe2ac3babce17968a5786877e38ff5b6c2a10ea0678d5a5e67", + "src/pyqt_reactive/flash_trace.py": "c0110553bed7908221c10d1a33e48f4324366b047eda75f5b2561b68f5855063", + "src/pyqt_reactive/forms/__init__.py": "5c9c1af2df09c479f1cfc50fb8d8ee7ff3e157a940d137fcde8af95c95d035a5", + "src/pyqt_reactive/forms/form_init_service.py": "4d34e5f2494a075f9aac68e40c07b07cdb06600d832bd5b510ee971db980b82d", + "src/pyqt_reactive/forms/form_value_validation.py": "ec3ca9d48168b651e8fe0b0ef6f90a67ad32f145332a8798f1cfad220c9fd597", + "src/pyqt_reactive/forms/inline_dataclass_chrome.py": "5d224ea256bffbb840f380d9ad75f9f98b7c3ed18fc4b1ba4db0b64f92a428a1", + "src/pyqt_reactive/forms/inline_dataclass_context.py": "c0d7a19651dc1b88e66b656a031b39a7aae67ff8998e50cc4e5962a184f4fb10", + "src/pyqt_reactive/forms/layout_constants.py": "a16ebe77ea6fb5d6c26d658bc586dd8357d18506c0935cb6426edbffc906ff98", + "src/pyqt_reactive/forms/object_form_document_renderer.py": "c47fada4032d685b6bf7dca4cb9f31e4e9240a25bd1039b165b045d5de541f1f", + "src/pyqt_reactive/forms/parameter_form_base.py": "f35bb8ddd6c630a47cc5095df93ffee608a384abadf755b2f0cf12bcc963b36b", + "src/pyqt_reactive/forms/parameter_form_chrome_sync.py": "94fda5faae9adaddb1cddd1b7a4d3b0452906828d94c582f6024ff72d89ca4a3", + "src/pyqt_reactive/forms/parameter_form_constants.py": "4d4ae05b91d525108342a10e9b2da7860b5a52b0028612f244339d4531d02097", + "src/pyqt_reactive/forms/parameter_form_manager.py": "a561e62e29af42630fa107b0929fc87b74007f7ed14ec8f0a6881c49070dc923", + "src/pyqt_reactive/forms/parameter_form_service.py": "0cbf305c99b0d7ab0c558162ba5d86dcd18f81eb8cce0ad271fbd4b3d15ebc89", + "src/pyqt_reactive/forms/parameter_form_tree_index.py": "e343c3ae5535bbd46dff964844225df13fad5431253eb3924b86f8c8d1dad273", + "src/pyqt_reactive/forms/parameter_info_types.py": "3f87562ecc9b1a4cbf541767ae39d53e1b2dcfe71d9a5e211456d8b34a0a75f8", + "src/pyqt_reactive/forms/parameter_type_utils.py": "c7fd2f17faa1e3d5c3027179135de51b859d204c4a2cb9f9be10837652530ea6", + "src/pyqt_reactive/forms/parameter_value_contracts.py": "109b82548f6a90e1d495d825eeb81309b555b6122db67867a2c91769e9c54f78", + "src/pyqt_reactive/forms/ui_utils.py": "96521f8a8b75f501ca9f2dd34f377025a7d5fdf543dcbed84ec17939875ca0ec", + "src/pyqt_reactive/forms/widget_creation_config.py": "01f32efb0dadc4d5e1a42344f43e7704c47468844b4a05bd13936e490ad4489a", + "src/pyqt_reactive/forms/widget_creation_types.py": "3b1c08a0a94334facb76afa273fef0d247a93f748ce86c3fb9e7026d46ef844f", + "src/pyqt_reactive/forms/widget_dispatcher.py": "5b13da9b2aee79344c343ddcbc296f125429c9780696ed35f996e982c3ee1562", + "src/pyqt_reactive/forms/widget_operations.py": "708bf6dfd51c01154e02210abe8840eeb496af51db57cfda425d51a365080b72", + "src/pyqt_reactive/forms/widget_registry.py": "6529d5879667827e7c6adf36129e6dfdfa18239c4e0ae32bec27eab7b03805c0", + "src/pyqt_reactive/forms/widget_strategies.py": "6eb7fc78526a247dc30c39493f36f54f2df5560b0af63d743d41b30b4f469384", + "src/pyqt_reactive/pattern_metadata.py": "7c2aa3f2660d530503acdbf8e122711cf7b3d1c0aae2d05bf6addb7091dcb4cd", + "src/pyqt_reactive/process_launch.py": "c324a6bcc3b5002bd4e6e5db184d4fd80bdcdeb7b130565ca52eb37bbaa08f9e", + "src/pyqt_reactive/process_signals.py": "8b4c44c98d6979fab6935485ea94d64bdfec6eb0143855078628451d4cd9ce82", + "src/pyqt_reactive/protocols/__init__.py": "2f59ae586807161ac8d019d904646684be0cc458b8b4bcef66f3d233002fd294", + "src/pyqt_reactive/protocols/codegen_provider.py": "98c030fbf5fc99ac8ce53bba0305f0591e0b1a12403b1cd22dd282d1df476fb3", + "src/pyqt_reactive/protocols/component_selection.py": "a68d8ca325a0972c7e911901a47521e44882699729f98bd4cfde57cda7b4d1fb", + "src/pyqt_reactive/protocols/form_config.py": "cfee9524e2e2c92fe1317d9cf1229580df1e1c04a45d9583c4b97fde1b3543e2", + "src/pyqt_reactive/protocols/log_providers.py": "c6602cec12dfa687a6f4e122aa62ebaf3ba7c5472a0d63b29ab0af9db3c18514", + "src/pyqt_reactive/protocols/preview_formatter.py": "05ed6999327cf4483a79d3bb5c9d1f1bc231fd3c0a33026e1e7069f1e8d3771c", + "src/pyqt_reactive/protocols/widget_adapters.py": "1ae6653bf3f2786eafa9f53f246e145ebfa34b81c190aaa8f41c19a1463a42f9", + "src/pyqt_reactive/protocols/widget_protocols.py": "4877e65746459f556954eb718d276748fd5211d244e15f1e92973e5ee01c24d4", + "src/pyqt_reactive/qt_types.py": "cca393ec5c0126b296c2462b414a84acd0cd1b5f63de9a2b6112a0b6593921b7", + "src/pyqt_reactive/services/__init__.py": "9ec1b77dc39cd6e0f550e7ca014c4e6a560ac0fa46f071c0f6ea47a6a34fe46a", + "src/pyqt_reactive/services/async_operation_executor.py": "f1252a0244f816b2187881bee484776ebd41529d1a17df08a1360967d4e03516", + "src/pyqt_reactive/services/coalesced_scan_requests.py": "5a565f9ed1bf34871f2802400fbe6b9ae7623cc612f07dbde44df10e92a1fe21", + "src/pyqt_reactive/services/enabled_field_styling_service.py": "0a16f22878c4ff68a3a75c937ad50314a0acf14014ceb39bf2420673a75e01ac", + "src/pyqt_reactive/services/enum_dispatch_service.py": "20b18b0ef51d7ecdab99e3fe0fb20fc38c605ce80995945f5e1033e24bb4bee4", + "src/pyqt_reactive/services/executable_action.py": "6942ff087473fc102c5395184aa74c8b6c8088cab5d7fa394bc5e103e41c5d28", + "src/pyqt_reactive/services/field_change_dispatcher.py": "0875f01a405b95de12cb0d4fc396d959a758d67a39c211d3056c512352d0f1c5", + "src/pyqt_reactive/services/flag_context_manager.py": "88b634b8aa899f82f6e9525101ade1f60b0be11763a33908ed3ad23ad3bfe147", + "src/pyqt_reactive/services/function_list_editor_actions.py": "68a0fe00e8b80cf1154aaa1545725b48b0c4b75e338afbcd23fed159d6d100d3", + "src/pyqt_reactive/services/function_navigation.py": "47664c983d2f515f2c4e6599eb4fbf269817e69f9abe68101872e6380ee60e85", + "src/pyqt_reactive/services/function_pattern_code_document.py": "bdf41b58bff009890e6e696cfc4f18313adfb1669566b2566f9e7b93d863c071", + "src/pyqt_reactive/services/help_document.py": "c0c1973e7ab02823c204dfd7003ac2a2b44acea36b895a82604ac31d0f4db1e3", + "src/pyqt_reactive/services/interval_snapshot_poller.py": "77fcd5b147bcf66782ebb1bbd6a9e9a8379c9e38672a47fd14fd2432eeeed11f", + "src/pyqt_reactive/services/manager_host_abc.py": "a9a3ffc9b2cc2c5d6f6b1224c89838f74bc9d41d2c8de8da39bf33f98483b90a", + "src/pyqt_reactive/services/parameter_help_service.py": "422f9e7b818f855f28979400512b4943524606827a74bf807bbf26afef1a589c", + "src/pyqt_reactive/services/parameter_ops_service.py": "8814b7c13bc56a2b0d3f69fbfb2a6153b4e2b5d0433779db6ffce5ba480890e7", + "src/pyqt_reactive/services/parameter_service_abc.py": "c5818d83e39444cbd88e135e2a075e45872d49f8c83c34e1d0e925e7de38d387", + "src/pyqt_reactive/services/pattern_data_manager.py": "ddcf9659dab6ee50ea3c155f57e1a4111a97e414ecf74b58151da1ef6557ac88", + "src/pyqt_reactive/services/persistent_system_monitor.py": "2041aaa91a3e242bd43e1686a65feed89078d18f8f7626bff00225895bde0007", + "src/pyqt_reactive/services/process_tracker.py": "5850b647c4c75ab2ced0ea91be34fe99b8e1a004cf3b2df597caa7769f7bc899", + "src/pyqt_reactive/services/scope_color_service.py": "b9d958c27205ca5a9eed16dd729a354642d90bcca96a519b01a0b19d94b1c822", + "src/pyqt_reactive/services/scope_token_service.py": "f84056a6b542d1d9a7df9e05c2ec344d6acb7cafd3301054158e89f04eb32b17", + "src/pyqt_reactive/services/scope_window_factory.py": "fc2a4606f89c85d44014ea6d08018e34921b8898816d8a09ca8febf80a448338", + "src/pyqt_reactive/services/scope_window_navigation.py": "39a0b4e95ce6e9a478c5882b91aa0822f53b683c9f2a706727bbf88922679331", + "src/pyqt_reactive/services/search_service.py": "e72ef88fdaf28d069bc80c2eec722ffa6921015613815929006fa35fd7de2054", + "src/pyqt_reactive/services/service_registry.py": "8f6dff4b7e6db9eb4ba2a0944d18cfa3c03b75e9cef85594b1e8bc7c5bd03e58", + "src/pyqt_reactive/services/signal_service.py": "04680bff5098b52edb1f4998356c1ef9543bcca96b3f37a7377ce4f98c1f18b1", + "src/pyqt_reactive/services/system_metrics_sampler.py": "7f0df0d9425a9998e371c86f55a27cc492fb71b36817ae07b6280f73e25b8ad6", + "src/pyqt_reactive/services/system_monitor_actions.py": "2aa205be430ff8b0429279a3ec44e5bc0c672b6da7a246a208f1ed40b79aded3", + "src/pyqt_reactive/services/system_monitor_config.py": "2f7259cafbdfd28f19d2a291afcd2deeef4e5eba2402bfb0e303a0aa643d6dd4", + "src/pyqt_reactive/services/system_monitor_core.py": "1712ed50c76e6303dcb96f65c8294922084bf2e3f90d21be56b766abca0dd39a", + "src/pyqt_reactive/services/tab_identity.py": "48274c530cd0792b3565c1becf1cef9c90d2f48b4e6ccec26cdd8807c51715ff", + "src/pyqt_reactive/services/tree_item_key.py": "e908f21bd6cb1621cd8356611f1ea0d7daa59d19171b211f3c3038598b8a5aef", + "src/pyqt_reactive/services/ui_thread_dispatch.py": "f2dbe7e8ce8ac0ad3116001d7dfcd91affd516a34615775ce4ce9921480e40bd", + "src/pyqt_reactive/services/value_collection_service.py": "33562f9b50e1080a26c28467ec31c3915e5f734bdc237cc04f4802db2b36b911", + "src/pyqt_reactive/services/widget_service.py": "cf3248353552db77b3257cbcf982987848fb16acd38ab2245dbef1fcf5e25223", + "src/pyqt_reactive/services/widget_tree_projection.py": "05d5221d64e74ff14483f203975f17543381d959c30ee5918c200fa8e9957547", + "src/pyqt_reactive/services/widget_tree_projection_config.py": "8f616aa3f2fe1dc88077dc612cb7c527970363692c6a8ace15b92ba56a806e4b", + "src/pyqt_reactive/services/window_code_document.py": "d0ab321af0eb2b14fac3ab2577c8c61672763d2f13a70a7ce8a35ee7bfab7c75", + "src/pyqt_reactive/services/window_manager.py": "84fff75ff74e59c5d7080f103ad1a4baa2c884aff3d2f87891a0afdae9a5c332", + "src/pyqt_reactive/services/window_navigation.py": "88da77ed07ea220b7c6874e71029b5bd50805fb2c3048701f9df773fe17257f2", + "src/pyqt_reactive/services/window_snapshot.py": "bced886e6bbfd69ae9bdebf950027b809e72c23eddadcaa5fcf7151adf7ae913", + "src/pyqt_reactive/services/zmq_server_info.py": "1050f0e9ada59580eba9a6c4a703678f0945f4a2cd83df4fb32251733911b81d", + "src/pyqt_reactive/services/zmq_server_scan_service.py": "ae12092dfd8b85a3354b87a708f3c32aef787c2f9fd0402158d32d14b654c7de", + "src/pyqt_reactive/strategies/__init__.py": "cab5cb18e271d822d459ab8b7f6427f03b8beee5ac9a4d04b4b73a0914d58e9b", + "src/pyqt_reactive/strategies/preview_formatting.py": "dc1a423246ca40f13633847d5d3ffde3916e53c1a8a8a92de893d3e80ad8fda7", + "src/pyqt_reactive/strategies/status_presentation.py": "435d97f7804e2db714cf60b236074c7a56fc87542b05a4d7a4b1722a340a7893", + "src/pyqt_reactive/strategies/tree_aggregation.py": "d28be44b8472fe1db805fb706485f02bae2c48d99e41f422dc534d24e0084c5f", + "src/pyqt_reactive/theming/__init__.py": "ddbd3f379805b6ebc01a86c86ba41999617b46498b4436563e5a427afea3866d", + "src/pyqt_reactive/theming/accent_chrome.py": "2ae2fd7cc5b3d2b60a99942792ed0621040339e117338107be01fc6128b36f86", + "src/pyqt_reactive/theming/color_scheme.py": "45f621f809accb5dd3fab03c1bbe95b43d680e6b4e03680e89ac2fe6400f16e4", + "src/pyqt_reactive/theming/color_scheme_resolution.py": "e8c9a7501268979d0fbb3e02f693b31a63e08688e80c3cb23abe0a856e1de09a", + "src/pyqt_reactive/theming/palette_manager.py": "00b81b76f39b561eb7a4bf37d0547bf2db6e7b63efa18ef752f614005f56be90", + "src/pyqt_reactive/theming/style_generator.py": "7433368f14efdefa05a401501122704c08f061412a343531fba5400a5807c885", + "src/pyqt_reactive/theming/themed_checkbox.py": "93426143261ca2c1da431264cec69e89ee76a35d7bf85d9e54db27e72c058ea3", + "src/pyqt_reactive/utils/__init__.py": "6b8f0030c2822411d7efb3433a2276320b985423ade229529196cf09fce17e3f", + "src/pyqt_reactive/utils/log_highlight_client.py": "db8e2fd014eedc85af1d0805250931f74257a402651edad2bedbc4588cc82f7b", + "src/pyqt_reactive/utils/log_highlighter.py": "e38237cfea9d757910a7b4ac84a8095068ea1c4531abd56c6fd15228b40e4703", + "src/pyqt_reactive/utils/log_loader.py": "c0cc1d6e4c7ac286562e2659b327e738f3cbed32686c09292b0d957ea61d159d", + "src/pyqt_reactive/utils/log_streamer.py": "ac195bf633e690695d61c1ea4cdfa7bcb45a4ecc20dc237f35bc220a87a08669", + "src/pyqt_reactive/utils/preview_formatters.py": "76a383c498300e2672d6b67ee0261e0dd90df0ed2fd64fc2ffd3513cdf097838", + "src/pyqt_reactive/utils/scroll_filter.py": "cb38375d28d5613f162dc020e2b8735824ceea767ae5cc1156c7086240e22fa8", + "src/pyqt_reactive/utils/styling_utils.py": "22d32d0e01fca8f575c15fa4a61b27cde2e46616cb86088733e8d15f312a1da6", + "src/pyqt_reactive/utils/window_utils.py": "11b222927102bc79d8a5f6a957bd99ab1e828bfb6586e1d647aebd564b99afb2", + "src/pyqt_reactive/weak_events.py": "446b5ea3e71eef459a2afd3663aac3e05a4242c6e9e21379f79fadf9563202c8", + "src/pyqt_reactive/widgets/__init__.py": "ddcf678b0dc5c03aaf11d2b6f12bb9cda681a29f0105925c51a5b9263d751716", + "src/pyqt_reactive/widgets/editors/__init__.py": "6fdb2746dd03af27487402eddb929f4f10664f6dab82726dba5894dee8d33878", + "src/pyqt_reactive/widgets/editors/simple_code_editor.py": "b84df51fd669c550dddfc5484e178f585d7b05f9ca3b230cab6bb82b3d0ecdab", + "src/pyqt_reactive/widgets/enhanced_path_widget.py": "5c72029a13fcf4e58a99ece7bb898afebab083f20c104f9255082b5f9ab1b232", + "src/pyqt_reactive/widgets/function_list_editor.py": "3a71a7af92cd6a3e304a030f7e821710af53cefb63c9e13cfb331c61b86d48b6", + "src/pyqt_reactive/widgets/function_pane.py": "da0f781f1948df80c856751fb6ca5f552583395d0f5b2d2beaa83d03738e1abf", + "src/pyqt_reactive/widgets/help_document_browser.py": "f8f0bb2e454ef458f2fd4f686f4d6814a717e8f1da0de1790ddb6f8a96795e8a", + "src/pyqt_reactive/widgets/log_viewer.py": "e68eda879c7cd3f5360dd1b4a08a481298cabf85cd72bdfda66b0efbd54d56f9", + "src/pyqt_reactive/widgets/mixins/__init__.py": "fc5176659b1c3239954ce3257c3615c5053c65e233ff350c869da5a4a356bfb5", + "src/pyqt_reactive/widgets/mixins/cross_window_preview_mixin.py": "663d644a603e6da4a07eb06faabc7f4eedc21ebab392094b3c76fa2f0abb3117", + "src/pyqt_reactive/widgets/mixins/selection_preservation_mixin.py": "94fc92d98854f4bbc611fe616033abccea19ea401ef9a3e9c53ea1017a77bd66", + "src/pyqt_reactive/widgets/no_scroll_spinbox.py": "f6be116d4976fc8a83ff576ef6ca0968ed95312b6333631a7705727dede10cfd", + "src/pyqt_reactive/widgets/shared/__init__.py": "e7525c16a67b93240ce3597d7f6e6b7b9bc9841d6e4b2de1084d10fd6aea2c4b", + "src/pyqt_reactive/widgets/shared/abstract_manager_widget.py": "92f8ede35a48392112c6c1aa17e959c3cc4a9450e69f5b1447cbc4ef5498dd5b", + "src/pyqt_reactive/widgets/shared/abstract_table_browser.py": "478feab4d742bfbc4170df25e5e3cc3bc0b409506192290817a064250dd9ff5d", + "src/pyqt_reactive/widgets/shared/action_tabbed_window_body.py": "246128cd317deb382bf830a67fc6468f768e6e5547ff0e17896b16e304371ecf", + "src/pyqt_reactive/widgets/shared/base_form_dialog.py": "9b5280ef06b1c8421b3889c1c477fb311dca3b5f960e8ecfb58a0a7812551369", + "src/pyqt_reactive/widgets/shared/base_managed_window.py": "3fda59f66502bfb9ce14565981f2c8738d074c78a08ae3afc9c8e00e93c882fe", + "src/pyqt_reactive/widgets/shared/button_factory.py": "78b69f821ad925773ca049d0c08715375a4d38eaf7ed075701417401b461a14c", + "src/pyqt_reactive/widgets/shared/button_panel.py": "280f904f101681461a8899b0dae53fd10e0f616e54511ee09c3324c2a589ee43", + "src/pyqt_reactive/widgets/shared/checkbox_group_widget.py": "593b9a2c1358556c710a9a3b406042e6e335cee5c46aff1e1ef42e5025c36a4f", + "src/pyqt_reactive/widgets/shared/clickable_help_components.py": "c480f45796f893e8f9431198a0d08f5acfee3ead9034764005587aae88902e4d", + "src/pyqt_reactive/widgets/shared/column_filter_widget.py": "7e492ba7cd8d2d91ead001be293bdd69dc6a98332102e30ed45d0bb6968be589", + "src/pyqt_reactive/widgets/shared/config_hierarchy_tree.py": "150062486b1e4d092ce703cee83a3d400097267dba3670d9a0120378f0045b34", + "src/pyqt_reactive/widgets/shared/config_tree_contracts.py": "8e6b4b0047219c2f7c8297de1baf7437b2571016bd2d82e1f2e1c520bc4a35e0", + "src/pyqt_reactive/widgets/shared/detachable_action_bar.py": "37157c0874e5495d3fc5c4b33042d6334b439a57d912e354ff48529e1d434ef1", + "src/pyqt_reactive/widgets/shared/dirty_window_presenter.py": "d0171ce0b9009780675f8eee0b528fe3fd2446c8b800934a476778e1c554a147", + "src/pyqt_reactive/widgets/shared/form_window_action_header.py": "18725af2a223d9c00b2496f298f745af1628c5e0cd07a2cbfc8e39b684b574c2", + "src/pyqt_reactive/widgets/shared/function_table_browser.py": "654c394929b744ca3fd6293fadfced3966d64626ddcf5f8b74f46e63cf026340", + "src/pyqt_reactive/widgets/shared/image_table_browser.py": "3a9b45805225021f6f17174e06985ab19f75b473bc0dfbf3ecfa7a5eef9931e2", + "src/pyqt_reactive/widgets/shared/list_item_delegate.py": "282c8fe0c88f9bfd51df7eb95c739a8d428d2e9d99478796bb073c698f5907a7", + "src/pyqt_reactive/widgets/shared/list_item_text_rendering.py": "0d997923c78dcb363748daf685cdc4e93ef5d6a4ee1f7d74100cd5266cdc5220", + "src/pyqt_reactive/widgets/shared/manager_action_controller.py": "e21b2407ec7cf6f891a7a67b2ae554e741f4a16aa35537b31e3b9992c009b317", + "src/pyqt_reactive/widgets/shared/manager_item_access.py": "21540ce53728a72028cc3c9af770bbca5210aa7c18bd4f697cad42bf5d27b276", + "src/pyqt_reactive/widgets/shared/manager_item_display_builder.py": "fe1d01ba449c69a052ed796e9c6901b080e2982b565f3ae0e0d73ad6599da45f", + "src/pyqt_reactive/widgets/shared/manager_item_hooks.py": "3dbb99e17114c9869db7a4cdf9284574921f4865e10f90a2161877c41da6c222", + "src/pyqt_reactive/widgets/shared/manager_list_updater.py": "c7036bb3f37198b06f5af6859c7bc6d9a0a85520da126286d31f00750a93b50b", + "src/pyqt_reactive/widgets/shared/manager_list_visual_state.py": "ba8a54d4b682d7bf61c2286439894d59eeddebf160102f4367038866cb54a2bd", + "src/pyqt_reactive/widgets/shared/manager_preview_formatting.py": "b9057f97f87f757272027baf402740db99da945fb04a4985ad0df5dc11f29b24", + "src/pyqt_reactive/widgets/shared/manager_reorder_controller.py": "64c829c64193e6cd1b604fc883fc0406fc43ecc329adc5066fa93196e2d67551", + "src/pyqt_reactive/widgets/shared/manager_selection_controller.py": "900fcec4c0a8e61b60130cc7a53ef8b0fd157d906182f96aa85fe57e5f008d46", + "src/pyqt_reactive/widgets/shared/manager_state_binding.py": "5fc9598ab1319cdf7048ab4e20c36c9d4c64d6ba7da584efc039e6c333cf888b", + "src/pyqt_reactive/widgets/shared/manager_status_controller.py": "b0e9fb4010775206b9b66889115be864d22f8e060b67bba2ef30dc0cccca4f9c", + "src/pyqt_reactive/widgets/shared/manager_time_travel_binding.py": "4cfeeef4badfe945c8ce2bd0e86254251fe79c5884261ac2d3f07c649ac3bda3", + "src/pyqt_reactive/widgets/shared/manager_ui_scaffold.py": "1332a8b69c8c562fd49146ea29a6b9aa5e156c90db06a00731e7716788e84589", + "src/pyqt_reactive/widgets/shared/manager_workflows.py": "e9e107b3129aa6f8725031abf35b2a67a52840643efdd120554ec78b13ce157a", + "src/pyqt_reactive/widgets/shared/reflowing_vertical_scroll_area.py": "7b04fd0dcd92ae470f9b6e7005bbae811ad3a614ddac86592381d840269c4387", + "src/pyqt_reactive/widgets/shared/responsive_groupbox_title.py": "a195a584afe51c456b35038a55d63c9e8cef708ca559df01d6dbbe42e399db0e", + "src/pyqt_reactive/widgets/shared/responsive_layout_widgets.py": "4adf600b914cf0769ca37c490523f744ac5fc2e5809028a6a24f21661e05359c", + "src/pyqt_reactive/widgets/shared/scope_border_renderer.py": "ab5a8246f3ca1d88bcd935f76fe59a33782e8ccb6944aff943386fe06fc46268", + "src/pyqt_reactive/widgets/shared/scope_color_receiver.py": "8b75714a16d6cf90d0f55c68f2d7d0935b0a1fa906ac2fd659c3409406568905", + "src/pyqt_reactive/widgets/shared/scope_color_strategy.py": "aa53231e9830e66721ef637177ae1470403cc9a13519015babdec8c824febffe", + "src/pyqt_reactive/widgets/shared/scope_color_utils.py": "d4c317df9c3d1391c3f8768b2bbd041435196cc876f16be2f929b63cab8aae10", + "src/pyqt_reactive/widgets/shared/scope_style_applier.py": "cd649a820631ceb367444c38ef3722489308147f9857f451cb95d5373d9ee763", + "src/pyqt_reactive/widgets/shared/scope_visual_config.py": "51286f8aa2f960e9d656f11f5ee57a11f1b2e1213511d0d17b46ad7be3b6fa4a", + "src/pyqt_reactive/widgets/shared/scoped_border_mixin.py": "f291c293302adf863574b6abf398605687d0325a8e3af16c37abb929d3fdbfad", + "src/pyqt_reactive/widgets/shared/scoped_table_widget.py": "cf81e6a8075ae89b10a46dc0e262de9f465cf5a0cd25a915dadb91dc0601a2b0", + "src/pyqt_reactive/widgets/shared/scrollable_form_body.py": "5a00352eda3b8e7932a878c18ef6ceae68a58358d15987dd8155702b70afd20c", + "src/pyqt_reactive/widgets/shared/scrollable_form_mixin.py": "e1ac397789a515097f464fb72b9378ba91e5dfbc6bfb6c316054049004fdcffe", + "src/pyqt_reactive/widgets/shared/styled_text_layout.py": "f174770e600b58e9d7b22f10db7a7e176d11207d534d090926e747af2ab594bd", + "src/pyqt_reactive/widgets/shared/tabbed_form_widget.py": "f2914db1586963f3dfe3cda7d6940d13b2bbb7ec1ffb4bb894c3844443b34a4d", + "src/pyqt_reactive/widgets/shared/tear_off_registry.py": "b44b1d391588d2290ff50b7f73379a875698e61de926e2ea153470744399091d", + "src/pyqt_reactive/widgets/shared/tear_off_tab_widget.py": "6b4fa8aebd7134cb2451135662f6b9aaee39a688c7b3ad8b37639985c7447fc7", + "src/pyqt_reactive/widgets/shared/tree_rebuild_coordinator.py": "deb28fea82fc963f999876dc54b37a4d0e310995bb16a1892befebdef79eccaa", + "src/pyqt_reactive/widgets/shared/tree_state_adapter.py": "ba4877d3431f4cfe344c530493b934b6d181254492070ca210fdcf2ed07f148c", + "src/pyqt_reactive/widgets/shared/tree_sync_adapter.py": "0031145c849a7ab6f2c4787bdc44692306073f08b2c17bea9b12932c45698f07", + "src/pyqt_reactive/widgets/shared/zmq_server_browser_widget.py": "35a7bc0ce56461336967a2a3f2e357edf8ccae122beb179d9dd438c86df105ae", + "src/pyqt_reactive/widgets/status_bar.py": "7acd1e194c1bdb350e2dd288adc9c55a37b1027fed97df0c5fb3e77ed794c940", + "src/pyqt_reactive/widgets/status_indicator.py": "96cd497e82336c02feec80dcc7c1bbf2e81336055e5b933f1cd1b96b240a0489", + "src/pyqt_reactive/widgets/structural_table.py": "4a757027ced7529f7b4f7737c09dbfa2d9dda48e7944b5375566299d3315f346", + "src/pyqt_reactive/widgets/system_monitor.py": "620f54ccd75eeeb0e370db4d461cfbf82f3625b898d343bb7c214de1cb5d671b", + "src/pyqt_reactive/windows/help_window_manager.py": "3946e3c1f7a99e75f86c87f44fab0af1282454dbf58dc95db14bb5a3fd66c7d2", + "tests/__init__.py": "db6cc46f8f6d69c35c72a39f4829527f661a63d906f091bc59a2055943a43281", + "tests/conftest.py": "911c65976a80aa48405b9c6bf0b18830599a2185c05434cbef8b7c25c4a48b39", + "tests/test_accent_chrome.py": "0862933afb738e2866611167a7c70e412d15e72ea46f9712a0b641587cadb709", + "tests/test_action_tabbed_window_body_lazy.py": "6f5b16efb53510e2a2806e1e412d89438c5e93c4efa5a9568439daf5a9daf9e8", + "tests/test_async_operation_executor.py": "2c8bc81bff7a3fd8879b6b79d2e9e09a3a22610fbb3785d970400e5e55dcd84e", + "tests/test_ci_action_pinning.py": "a636dd4d70e231d06c5de2802afc89c389f678b3b49a40ce8463eac5b0c308dd", + "tests/test_column_presentation.py": "aa83341b1443c131637e5b2b498b42cfed858927fa3f7ded00885e03f38e688a", + "tests/test_compact_dataclass_projection.py": "b765e0b8ced31a5cc351125bb2d86670e30cc973779c0b6931c75b026a14b271", + "tests/test_core.py": "a2aba8923fd176a75a9e94f5c3b1fa0a6d18f41b28935b0c4d39ed75892894fb", + "tests/test_deferred_callback.py": "1c59913d1b19a9725e5735bbd342dc115fdf4b555863427169b5001324e83b1c", + "tests/test_enabled_field_styling_ownership.py": "d831ab09cb4a0b92c3c33e4f2c368874a454c85eb8943d9acce48388ea961263", + "tests/test_enabled_title_row_ownership.py": "01052fea145b31698ec29319f521179adda5945ce324f3d976bdcc144aeb5be4", + "tests/test_explicit_function_pattern_overrides.py": "69179658cd4d89cdbf8bd469166e819f3421c39a6fcb6a38cc330dbbcb592a33", + "tests/test_field_mutation_authorization.py": "cab1faf400063e32df23249457738b9b28f59c760a6fe4d3cfcbba34884800ea", + "tests/test_flash_destruction_lifetime.py": "a567e8b978182773d316e9a7dc7934b80da2708e2804bd8e84898b4b1a030b37", + "tests/test_flash_mask_rendering.py": "9ca43be6bb9bb98a6950e9025688a6f40d8c7d050dec2bbe5721c215c47122f8", + "tests/test_flash_playback.py": "51438a64b08edec35a54447dbf3acd8aebd77a8dde92dfd7ccb3b0755bc196df", + "tests/test_flash_scroll_ownership.py": "f660469075d1c96e1fdce5bfaa0bd94857001d5e4f9ccf33fbae9ce9b2a51072", + "tests/test_form_build_transaction.py": "fc9860a115de764ee14d2a246fb5dd2d66bb60b159ae7f5853050d1e28442417", + "tests/test_function_list_editor_tokens.py": "5eea6d8a08f76c22fe81f4fca16b80d82ab8bb2ccc6f21428e5eed739065741b", + "tests/test_function_table_browser.py": "e0289caa47564647e1952a8592cda03840a58b11fb10fac6e6db9b35b1045541", + "tests/test_future_completion.py": "fddee2a4c4b210e43c137a24f5730c0e8303a38ecc67afec7a4ac5f39d2ad860", + "tests/test_help_document.py": "b28d3fb53b253372cdd4e5fa542faf5ef9a2cd7f6b42cd3a3694c2713f4f5768", + "tests/test_help_document_browser.py": "b04eca203a5d7be904ef86f490370bb71b598bc9f9d8f2ec441d118c4baa5d71", + "tests/test_host_provider_contracts.py": "ccc75dee1cd12eb05b29debe8da84a9b98a4714607bebdb9ad75c901f24f846e", + "tests/test_inline_dataclass_chrome.py": "e2c62d17ff58ad6dbe3dc2ec7e8caa1b8eeabc7e26f92c27a1a4489d1b12656b", + "tests/test_key_sequence_adapter_lifecycle.py": "bb4e57ee2548822f06252bdf07a9e3f36d569a01165f8707c2687150e4364824", + "tests/test_list_preview_wrapping.py": "60bfe5b16e9f17f3fed1f88213e69644ad2bcf278d7012b446689fbc75e181a2", + "tests/test_log_viewer_lifecycle.py": "4c7372276b7e65d84568c01489a544df7b9b2df791910c21cba11ad9c0eaff75", + "tests/test_manager_ui_scaffold.py": "cef43797060e94628d04fc581268ccd7e054cd5810b37105a68ce7930594eba6", + "tests/test_nominal_contract_architecture.py": "d02bb10514bab0bb58ad9585f986e208d88365838597eef520186f066685867a", + "tests/test_numeric_roundtrip.py": "5975b0ce8bd7bfcf1b21bf03593b72882c775a7982d834894081b6012c556566", + "tests/test_parameter_form_service.py": "30bb0cbb28b6edd5c144a58cc30a4e9fc068f9e56ee2dbe19e39f2b64fd1982d", + "tests/test_parameter_form_tree_index.py": "d28a29f77a68a22b3fce087de2c2679f2a291dd6a66cecf94f68ac700c1fded5", + "tests/test_parameter_help_service.py": "d41f813fbefd005003ab90a6e83d44727cc1adf925a9d521095068cbed2355b7", + "tests/test_parameter_ops_placeholder_capability.py": "8e4006e9b04df1efbcc4d878a68505a7057b83d6ac44e5b47dc1ea0bdd9dad6f", + "tests/test_path_name_roles.py": "86f5ef6cc8677dd92faa349d6e3254bbf6edc734e31fe0e13f8436dc4283c34a", + "tests/test_preview_configuration_imports.py": "7bec54d0815d88d2dce8dea9b73febbf23216b32c06666eab34e1487f0ec142b", + "tests/test_preview_formatter_registry.py": "9b62974f3e42be630f8f38a72d894f937affd6a694fe6f13c71629b5a38104ee", + "tests/test_preview_formatters.py": "4d6bbd9ada4ced6e6d2b49ff8c582d30b6341dd3403ee0c458a6bc4f0e595e49", + "tests/test_process_launch.py": "49c14b825f7fd3f7f7aa51f727c436c529cd2aaabefa3bee13e9f9e9d955e489", + "tests/test_process_signals.py": "de4d134edc1345bfe53df7f8b4ed362a24e4b3da35cfbc2132c5f6fb5107a662", + "tests/test_protocols.py": "3843eb80885957639b40d1cd260c87d0680df3a63d6ac448a084a25e8a37d8f2", + "tests/test_qt_types.py": "c24a5242ec6395b8c72723540e4b100e41f573d071444fc8c27eaac9a42de911", + "tests/test_reset_flash_changes.py": "3b901bd26e339f4585d90f25a70957fd949c7bdecbcfd56c0100c5a80f006d4b", + "tests/test_scoped_border_mixin.py": "9914504211aeaeb0cc713b9aa2c11619a00bfc53dc8dc6aa68d2d5ce3bd2f538", + "tests/test_scoped_table_widget.py": "764ed376f2e284682ddab7ab8379071d19ee703c391ea8196562b8f7b5b9a2fb", + "tests/test_scroll_area_content.py": "4b6f4a9e1fed02a267e2c707b1618ad3de8c451fe5e44b2f404360ef00e579ca", + "tests/test_scrollable_form_viewport_context.py": "d445d86f08bee9cc364868d4f50c976ee95bd85827b02790353c9f7439c9df7b", + "tests/test_status_indicator.py": "78f0e0b01548b8d676fd6ed75c79a800a4399826dcc5d2770ff3bb49a7e2a85e", + "tests/test_system_metrics_sampler.py": "524776fcf817233d461402b0f096623763f119a5d690a738434b390c6c752b07", + "tests/test_system_monitor_config.py": "2cc61be642ee7c9e26dab9e13497800bd3f85490a5253e5634a1374d4fe8287a", + "tests/test_theming.py": "bb811e5a73ee0a4fb95a0b87a40165442c39e3afdfa6c6ca6c0061590dae781c", + "tests/test_tree_state_adapter.py": "76d12b348ed6a015cb9b8f5bf3173968ca1b17a219df21aae82df23b12341907", + "tests/test_ui_thread_dispatch.py": "3478d122a45ee394edd3ab191f46636c62fe3b1ba1705d80e48c9e764b31e8d7", + "tests/test_weak_events.py": "d752129493c8cdd1d427024c64c7f02cd37d0e7a87bbf854b1ed332d174fa710", + "tests/test_widget_projection_safety.py": "f124cf36ca48fe51bae0aedad633f420bccd469ea8d9059d82d64dff3ca841e2", + "tests/test_widget_tree_projection.py": "3d6a1224caf0913ca194b13f4cf791cfcb3ce9e9c38b88281fe2dac4a0e222ef", + "tests/test_widgets.py": "f24b7bace49d7c6ce5357d38e9b5362ba0625b9f4421222788ab661ae278ed19", + "tests/test_window_code_document.py": "5c546e6151f19a8bcebfaa6a332a301b888416236baa982e2ae761e015326712", + "tests/test_window_navigation.py": "0f2bd021ca9d547f2b3d64e42cba1d13d0ffb1ed52e86bd07df836d5d3f649e3", + "tests/test_window_snapshot.py": "33fa1d5509217b0c16e926f7b4643ae1d5176ac77434f16099acd9b7cd52b8e2", + "tests/test_window_snapshot_bindings.py": "44af6189d6bf64bcfcad9e87150d2f01620e2a2c0b4877d581f64428176decf9", + "tests/test_zmq_server_browser_lifecycle.py": "2789e1a2cd5c81bddd37b62eb5fbe507228972e9f0dac0d1ea06b87dda066579" + } + }, + "python-introspect": { + "root": "/home/ts/code/projects/openhcs-shared-runtime-plumbing/external/python-introspect", + "head": "ed1e4eb15f7a0bf8315274d3e47858fa2b4372bb", + "status": "", + "tracked_code_metadata_hashes": { + ".github/actions/validate-python-release/validate_python_release.py": "96275b643ee03adac9a13996006cca803ec07a0f0d0835d47f559677af016fbc", + "docs/source/conf.py": "534c6205463a628d4d7d58b2793d95cffea83a6ec2c0085b012a29b046c398ea", + "pyproject.toml": "cd108ffbf3b756dbc3b8a1d85530cdeab0d2d0f452751c131db489a31178fff4", + "scripts/release.py": "f5ba54de5d2ef89ec7c75e536b63817989b8f9f17e3b2c10bb981b5bf8d08837", + "scripts/update_and_release.py": "80896e49f856d6a193bb1dc3917f55d2878acf1476c8240333eda16b92e8e61a", + "scripts/update_version.py": "303a09dca1b7374ed1d8e4aa26d76ec1bc76cfb6a769e002f2088927d51a6aa5", + "scripts/verify_release_ready.py": "5fe0aebbcaee7f60540f50221a1f8da1beab2b8b59d9b97f3b4a240f0e72211f", + "src/python_introspect/__init__.py": "d4e29e9b857a785f8ea1a1e26ea5317a39958a527df053677c335057671e4a94", + "src/python_introspect/annotation_types.py": "dc126879a8a581cea0758eec4df18ec20c47ca4b1e135abde23699b65b790bde", + "src/python_introspect/callable_declaration.py": "3bb8b474624fe6b2964a5c1f9a6aa540b2703500bfa124e7808995cb789d6951", + "src/python_introspect/dataclass_projection.py": "82662ff8eaa4f2aeb3b33edd61abae57020a7f139c3aa396d82dcecf8b801160", + "src/python_introspect/docstring_annotations.py": "444e8064f833f1a044208bd4a15107a6b688b597e36ab78ac58bee6996b51fc9", + "src/python_introspect/enableable.py": "025eadd64a6a6f1648bc36fbd1724f6049355a0b9b1a259443248d70170b8eb6", + "src/python_introspect/environment_projection.py": "8ab7d1e01e9a4529ea0b77d8996a5feeb94bdc2e905dd6263afb28d11bc217a0", + "src/python_introspect/exceptions.py": "4c6f15a3625d02b05b2fc8651e67e6b77d4bb442ad180b85121d91874ec3407b", + "src/python_introspect/runtime_parameter.py": "59fed2d467e751686447322f8e19a8633d964741d3d8afccb850dc504a619897", + "src/python_introspect/signature_analyzer.py": "7e25a0355159c86d361a21a7afc449ec758cbf8a32e9b72d06de66a924f04159", + "src/python_introspect/unified_parameter_analyzer.py": "ac52ab997fb385425920614451e8cc754fece0176bab4cc9b132eae8c930ab15", + "src/python_introspect/validation.py": "46fba78bd068c75c89b91baa4a5cbe8cdca9692e75a285eaf76311183df77b64", + "tests/__init__.py": "c752ad382f759406b1c9c102142aac7cc10a2693b8e5848536e44315567a034f", + "tests/test_annotation_types.py": "ae38706899ad48445224b09babff76496006576e7f188af7e27261521ea34ad9", + "tests/test_callable_declaration.py": "b8486dcca0c85805a14975c00987c7c3247c2c8abcb75545f89e04a01f738c32", + "tests/test_dataclass_projection.py": "6f662d0adcdd4531d8cbd94c2ffed55ced3a53c3ec481a9dce67979ac8489990", + "tests/test_dataclass_source_preparation.py": "c7438b14578eb59d53df2499c4db2004ff1b22d5e6d8350b0aa6ed2eb262a535", + "tests/test_environment_projection.py": "e11e2c180c605e761acd48103fcba10dada614a326e40a55d4777abcf0853899", + "tests/test_exceptions.py": "41f4a70df08a7718b4c9daa05569e6c491c0148abf975f0aeae78688e99d8744", + "tests/test_init.py": "7e9ca130ed8254034e32b991f8abd4624f6c1bfcdba65f911dc28c12d9cdfeca", + "tests/test_runtime_parameter.py": "b728307c8e6c7e50ca9b0befd1aaf154ad293eb18f332be544719d7ae9dd3fb4", + "tests/test_signature_analyzer.py": "0708fdcb848fe874eb4dae025c1c9fd9b0929e983cb1c1c53cb268af9fb37c2e", + "tests/test_unified_parameter_analyzer.py": "deb55bac9e31465c8368c6101a93e3c951e139c5c7ebd442a5f8cdc98842f1cd", + "tests/test_validate_python_release_action.py": "65fc7bdff5d20229e74e3abd44f936d7cfcaf9fa5881a7e9e65c59bbd65c6c12", + "tests/test_validation.py": "ce9cab31e33a001df0d40454a8d7de9e7a2ab6dc6296399adb234d06f7dfae39" + } + }, + "zmqruntime": { + "root": "/home/ts/code/projects/openhcs-shared-runtime-plumbing/external/zmqruntime", + "head": "668edafcb5ee530a163377c936431ae1e8334e85", + "status": "", + "tracked_code_metadata_hashes": { + "docs/source/conf.py": "e2224f5e41f473e9a9a213dfff036859c0834eee3561a9d6ce5415bc4487d126", + "pyproject.toml": "e2b56ba5b94418c99ee04142edf0fc4f14a06860fbecad7170d4a2e1e4be70c5", + "scripts/release.py": "109327ab88e002e4fdd56e6a50a8b5e265fda3723fb3c0ccc184c9d1b0539c2e", + "scripts/update_and_release.py": "80896e49f856d6a193bb1dc3917f55d2878acf1476c8240333eda16b92e8e61a", + "scripts/update_version.py": "d70feec0d50ca0a8d90f0105be3e85bf5a5b17a7bb0ca63a6178ad443f0ad60f", + "scripts/verify_release_ready.py": "e8190c4f79b1fae85af698b704b339564e77090f8adb7393f0079cf0d13bd844", + "src/zmqruntime/__init__.py": "37f3e14f58b4c1dda3d338a3a2fb075aefea215f6f25b69f44091891341755ef", + "src/zmqruntime/ack_listener.py": "da5aa8d1031f971c2621071a6da40b41f10dedf12839060db13d10153050cd6d", + "src/zmqruntime/client.py": "00757150b06b837b918153bc3c2752dbdba396569ebb4f4ed91cfbff7c23d25d", + "src/zmqruntime/config.py": "79840f3b72593042b6a56e3a703a1064e0d1faa19b12446d99e0903af494f2a3", + "src/zmqruntime/execution/__init__.py": "7a5d9f1636946d5fe6edcaaef181e8740e17d5b348d81e04b50a9fccf6fb16f9", + "src/zmqruntime/execution/batch_submit_wait.py": "c447b2ccbc372a5336f5a3b32844b896dc5d58566cb3de31640ae3be2379edee", + "src/zmqruntime/execution/client.py": "1b9453ea2be540b29849770cc3fe82f284f501e0e140797dd48c2c257ec36f12", + "src/zmqruntime/execution/lifecycle.py": "23596c31b9efe812f1ab66b4300ee1bb19125ea9bef6e51ddcd8acaafb0f4ed6", + "src/zmqruntime/execution/logs.py": "c7d1816835620a2b3e82a889bd36f2a97b80aad7c0f639a07c5c9d426c6ae803", + "src/zmqruntime/execution/progress_stream.py": "13b39fb4d256cd835302f7a8949e9e56bfe0b045e3e6fc1d197ce8ae40bc57a4", + "src/zmqruntime/execution/responses.py": "43ebbaf9451c34a5cb5a0c3182cb4de4c3745e13db8482ba1373becbfc8a2a03", + "src/zmqruntime/execution/server.py": "13663ba20e62326171ff8b43c2474419940729e90b2c0b25b04ea3514734d599", + "src/zmqruntime/execution/status_poller.py": "da0c7c304f293ba4f52aaefc4c722442b5a2859d1fcb806e8fccdcd3b4f6cdc6", + "src/zmqruntime/execution/wait_policy.py": "df4a9cad5a2fb74aa0c030def22dd8cc5b851983c3f04c26d479b607075ef922", + "src/zmqruntime/messages.py": "76018d6f6ac6795e076eabed9c6dd018b8c2fb9640e194a19086a013c0a50785", + "src/zmqruntime/progress/__init__.py": "1767a50989e4a19e4ae8a7ed4343b6be564740236cdcb4c5c56c06f55c21f68f", + "src/zmqruntime/progress/projection.py": "72b22f765dabbcf6983c619c8cc5404bc52518186ef72d85a6f6c6ab65cb426f", + "src/zmqruntime/progress/registry.py": "2943b28d1490688bddcba914db5aadd445cc8e6c9b6381230f0451366e98a0c2", + "src/zmqruntime/queue_tracker.py": "b2e380a93699f85e608d1ae7c03b5a20ee62d8beb82cc93272b050084156610f", + "src/zmqruntime/runner.py": "9f52b69f23b4626adb4e1394e0ed476624d2a38d9cd2c8ec656ae3b2e6816df9", + "src/zmqruntime/server.py": "a38ed80dfbbf9d738f4a96b4bcff8ca667f592b84413c33731550513dcc924d0", + "src/zmqruntime/shutdown.py": "67acebb3ac7a2c419320005931f0de44e28f5ab0b393e6bfbdc3f11207a2073f", + "src/zmqruntime/startup.py": "55118bc44633926434f0e0b057c167dc2948f2a632a902b5bdb60dcb92731d69", + "src/zmqruntime/streaming/__init__.py": "911cac6c1f747d77ec6614dd0961ebb799a7dbaa276e4259e1f38087e3b7320b", + "src/zmqruntime/streaming/process_manager.py": "8229c322c309969f89e2a51a3e416ea38a4990248776844dbcbb01ad9796b3e5", + "src/zmqruntime/streaming/server.py": "6a587842676bdd2f414d8df8f277e5e671a5f41a7b3c4615bf1ea2a5da182834", + "src/zmqruntime/subscription.py": "4a393bd94d8a3611ff7d7423ec4ea681df6f26cf906a77e2682c76cc0e762696", + "src/zmqruntime/timeouts.py": "bb5121a03070f0f2a0ed76170a2324512ed4a4d64536ecc7ba8bdc6a4b8961d0", + "src/zmqruntime/transport.py": "e486a4215d4b977553030e897589bccac637dfe4e9abb28cfb7594139b2196c2", + "src/zmqruntime/transport_modes.py": "12bec1c13d87bb8f05b049dc76d3cb7c130414c9e69d6220228ceeb0087f9ad8", + "src/zmqruntime/viewer_protocol.py": "5580efffddca2f723b11a652f482fbdb52ebae657620fad95217b313997b9fc9", + "src/zmqruntime/viewer_state.py": "f3dd0b35c3c75b0537bf8e50624b8f05a6dce02b40f1700a878189c3312ae30c", + "tests/diagnostics/check_ack_startup_failure.py": "08856fa0ca60e4b00c8577ce2ed3bb82e6e3fbbe16eb2876b69a03500ff130ad", + "tests/test_ack_listener.py": "a616052e042aa145d4eb2b9bca6b153633662bbd54588038730c9d8a2551f70d", + "tests/test_ack_return_route.py": "4519ccf21b0d6bc892d43405541308326a8a7ae885e0ec8942e3596eda3078bd", + "tests/test_ci_action_pinning.py": "a636dd4d70e231d06c5de2802afc89c389f678b3b49a40ce8463eac5b0c308dd", + "tests/test_cold_start_activity.py": "3e0486f8e520e3bb2a767f1aca49df0ffc269476cea0f29594cb08bfce1d7896", + "tests/test_config.py": "f9a16ae6cdb8c9d1dce74bcbc95ff59e853245b219ce848d8aca9704eadfb95a", + "tests/test_endpoint_ownership.py": "e37ddca59beb48b4c1ccca4d1feee1793728cfc54b2aef69870e120bf17098e5", + "tests/test_execution.py": "7b547a68e912b012144519216097bde868264fcf7bb0ad20b3223862701bea0c", + "tests/test_execution_logs.py": "3136e1cf250b02d89e9da9be06b90ecab59fe34ba58e2e22145fd1b0e9fe2a90", + "tests/test_messages.py": "8223e0a5b461e7dd3fc6392c9f652cd74180c8de1b07fef9d28305ffffb2f229", + "tests/test_owned_close.py": "92c3149704b88278ce6771c0c2c064aa897948bd7303b8100f24f99e97d9ac84", + "tests/test_owned_startup.py": "95d3997eaf5d627925108b85dbbe5937abe448c666f26caa43f2bad5586bf73a", + "tests/test_process_manager.py": "b21d1eedd0f98549a7b0c235cca43fbea35afb3c041df81b362d94f3fde9439d", + "tests/test_progress_annotation.py": "27b237877b660d6699402a091dc7843201a4fc0636e4b9f0fc1e25d16cddee75", + "tests/test_progress_projection.py": "e56b49ba046b7c459cee386076201b252d3c831a3d8eca535eafbe0ff6affced", + "tests/test_progress_registry.py": "bf80de2da039272700a366884e5aee4163f04b156fe5c8f58912d4c7f42e7ef4", + "tests/test_progress_stream.py": "27d056146596e7e7c4f2a15ae7e7f7e01e9b4882f3258fa48108d799ecb19698", + "tests/test_queue_tracker.py": "85257cf345a02532441f188242134a2fcb4b60f793eead2f21a6bda360529a29", + "tests/test_shutdown.py": "ffff454475abed18dc520b8629a2799d5a30d0e83abd0292c5acb916d3e63eee", + "tests/test_startup.py": "3e5441886d22921b255de1016bedefd74e87e57f7099bc9e72f8021d1b115148", + "tests/test_startup_callback_scope.py": "06c9dfe205fef9aa293ca0a5dfbaaa8d5083da02fb7c2e06bc9895dea607760b", + "tests/test_timeouts.py": "8c4c95ce4c2d02d5210ef4ccfd4d0cbd1850535c8d5793b87380e995c126babb", + "tests/test_transport.py": "02072b46ca87c082eeedccb02f4b85a1ba02bc51a4c24ebfc6930a6b8b2a21f9", + "tests/test_viewer_process_ownership.py": "972bf0988a9b3b49371ddbd8e1ba7ce965c9fa9a37f04ece70fa93905335b348", + "tests/test_viewer_protocol.py": "26adaa73cc3a39cefc4c797880fb5b2e52082adaa980e479e318fa3805e7fe28", + "tests/test_viewer_state.py": "2f7b0dabbed227db35fbac5321f85b84352aafe19e33c879a50b3aee0fc9d8ea" + } + } + }, + "protected_canonical_source_first_boundary": { + "status": "CANONICAL_SOURCE_BOOTSTRAP_POLICY_OBSERVATION_NOT_LATEST_API_QUALIFICATION", + "openhcs": "/home/ts/code/projects/openhcs/openhcs/__init__.py", + "objectstate": { + "module_file": "/home/ts/code/projects/openhcs/external/ObjectState/src/objectstate/__init__.py", + "runtime_version": "1.1.8", + "default_metadata_version": "1.1.9", + "installed_metadata_version": "1.1.9", + "registered_type_pairs_available": false + }, + "python-introspect": { + "module_file": "/home/ts/code/projects/openhcs/external/python-introspect/src/python_introspect/__init__.py", + "runtime_version": "0.1.12", + "default_metadata_version": "0.1.14", + "installed_metadata_version": "0.1.15", + "prepare_dataclass_declaration_available": false + }, + "scope": "Existing canonical OpenHCS bootstrap selects canonical external gitlinks before shared editables. No path bypass or protected canonical mutation. Current owned source-first qualification is separate." + }, + "primary_tests": { + "python-introspect source preparation": { + "passed": 9, + "log": "python-introspect-readiness-tests.log" + }, + "ObjectState lazy factory": { + "passed": 25, + "log": "objectstate-readiness-tests.log" + }, + "main514 registered source readiness": { + "passed": 1, + "log": "openhcs-main514-readiness-tests.log" + } + }, + "primary_total_passed": 35, + "additional_started_before_selector_clarification": { + "ObjectState_lazy_global_context": { + "passed": 40, + "log": "objectstate-required40-controls.log" + }, + "python_introspect_source_release": { + "passed": 13, + "log": "python-introspect-required13-controls.log" + }, + "scope": "Supplementary historical-selector equivalent checks; not substituted for primary actual35 or claimed additionalunique total." + }, + "pip_check": "PASS", + "only_two_authorized_owned_git_checkouts_changed": true, + "protected_canonical_two_and_other_six_source_roots_heads_status_unchanged": true, + "no_other_installed_distribution_versions_changed": true, + "temporary_build_prefixes_disposed": true, + "all_command_handles_terminal": true, + "no_new_venv_or_public_jobs_or_tags_or_PyPI_publish": true, + "parent_OpenHCS_gitlinks_and_floors": "Owned by ROOT/PR518; this agent did not edit parent worktree/index or refs.", + "retained_failures": [ + "source-first-import-probe-v1-RED.json: metadata discovery selected valid generated source .egg-info, not installed .dist-info; corrected diagnostic reports both.", + "focused-readiness-tests.log: combined repository conftest namespace collision beforetests; corrected by authoritative separate repository processes, no test/import policy alteration." + ], + "scope_limit": "Shared default direct dependency imports and the owned benchmark source-first environment use releasedversions/currentAPIs. Canonical OpenHCS-first source bootstrap intentionally selects protected oldcanonical gitlinks, so canonical application latest-dependency readiness is NOT claimed. No path bypass/canonicalmutation applied.", + "evidence_sha256": { + "import_readiness_probe.py": "b8efb1e905340134b84ba4419da18b015083359ecfded16bff9b0dbbeda9dde7", + "source-first-import-probe.json": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "source-first-import-probe-v1-RED.json": "5dc1783943f57940ee0e4a482c96cacff9a87a061cb0f6fd54a55f4f5e8d5def", + "objectstate-required40-controls.log": "272ee4e3e3a343e21d77a7423ecab8c1d3fdc4d033eb16315e2edfdf698a5edb", + "canonical-openhcs-first-order-policy.json": "0263509945dd322084d3cdb2ec6f8404c7219b2e1fff006fdcd7cf30887eefa0", + "openhcs-main514-readiness-tests.log": "fb9f4833ec108937050465e52b6621ab8e602a363b84195e69739696eeb7595e", + "installed-distributions-after.json": "4adc2f61f621c5a648e486c12aaba2e97d5c89512a50235b05deb0c2bdd49b10", + "objectstate-readiness-tests.log": "c4aafe1937f5b1840f2797549da35341a66d98c4dae55daa3c3f284ed5dec096", + "all8-source-first-imports.json": "a0cd99d45ddccb08c9a125ff14a1bdd113a91ea12e1546b76a74a1d1a392d8ab", + "direct-import-probe.json": "570c855676a911125a5b4e6ea2ddcbf4493b13a7682e0182f2a1e5b701d9b917", + "pip-install.log": "66fec4e76d20efb1a34400b16aa6c20cbf0b46849b5c598e45330365a7c2ed23", + "python-introspect-readiness-tests.log": "d938a7e650a474cb5ffb80088da3912024873000d2f9feb357c9cb6ca67d85e6", + "installed-distributions-before.json": "4301dd81c9d1b48801751497a7812d3e79a1df71593bc875f8f9b60f602054fe", + "focused-readiness-tests.log": "c9d0387d883174c4c81e5f70d91b232effd9cff1f113a6737f1d5d4d7115030d", + "installed-distribution-delta.json": "8f90c46e3c520a576ba42d478df290b63a795420677357a29e19f0601c4157a9", + "source-first-import-probe-v2.json": "aad43dd8758c41b060fe734b66e04d08c1e0fc95728c770850b8964f17c23fc3", + "pip-check.log": "9261363b733079a641c2e4cc9bc46ffa1d8336945a87f807b6cf68847dbc9b09", + "direct-import-probe-v2.json": "74b1826b4053200898401781051e882b3c414764bea38d37a660df8a78c8a8f3", + "python-introspect-required13-controls.log": "72928e7c8f0d61d67b0bf821e3eaa5c47f1a9a3ee8d00ac0294fdfe54b94bc30", + "import_readiness_probe_v2.py": "2b9060564efe6dcbc49a083488351e28f1f47cb58842295b8d25748dc648c069" + } +} diff --git a/benchmark/results/perf_illum3_runtime_ledger_20261003/assessment.json b/benchmark/results/perf_illum3_runtime_ledger_20261003/assessment.json new file mode 100644 index 0000000000..fbc1756fae --- /dev/null +++ b/benchmark/results/perf_illum3_runtime_ledger_20261003/assessment.json @@ -0,0 +1,152 @@ +{ + "status": "DIAGNOSTIC_AND_SCIENCE_PASS_NO_NEW_PRODUCTION_SPEEDUP", + "source_head": "4c0d62e45c8afb85e34b69d7279cd00710f519b5", + "source_freeze": { + "path": "/home/ts/.local/state/openhcs-maintenance/20261003/illum3-compiler-runtime-ledger-v2/output/source-freeze.json", + "sha256": "86646806122c73d38de2e9d42efa0bffd471ad0a1db36d7d33ea83dfcbfeb0fc" + }, + "actual_import_dependencies": { + "external/ObjectState": { + "head": "a01f8939b9bf4659502a33fe3febe62cab0f3c9a", + "status": "" + }, + "external/python-introspect": { + "head": "ed1e4eb15f7a0bf8315274d3e47858fa2b4372bb", + "status": "" + }, + "external/arraybridge": { + "head": "1e53d03d9f468322a1c085c8be29485fb139caf2", + "status": "" + }, + "external/metaclass-registry": { + "head": "393a7e03003cdc56df9013f932ed4f26e632d77a", + "status": "" + }, + "external/zmqruntime": { + "head": "668edafcb5ee530a163377c936431ae1e8334e85", + "status": "" + }, + "external/pycodify": { + "head": "792b03413331fdf107e369c924c257a2f0b16126", + "status": "" + }, + "external/PolyStore": { + "head": "84f322e46871de5ed47e7fd20976ad03e533c1c4", + "status": "" + }, + "external/pyqt-reactive": { + "head": "ad4948775ab81180a354d4b793d17ee5ddff3972", + "status": "" + } + }, + "installed_versions": { + "python": "3.12.14 (main, Sep 24 2026, 17:57:43) [Clang 22.1.3 ]", + "versions": { + "openhcs": "0.8.7", + "numpy": "2.5.3", + "scipy": "1.18.1", + "arraybridge": "0.3.6", + "polystore": "0.3.0", + "python-introspect": "0.1.15", + "metaclass-registry": "0.2.2", + "zmqruntime": "0.3.0" + } + }, + "originals_retained_byte_identical": { + "qualification.json": { + "original_path": "/home/ts/.local/state/openhcs-maintenance/20261003/illum3-compiler-runtime-ledger-v2/qualification.json", + "sha256": "89f786ef58cd1c31c2418b66eb15e25a55018c53fbf06c7516a76ed76bada615", + "bytes": 17768 + }, + "observations.json": { + "original_path": "/home/ts/.local/state/openhcs-maintenance/20261003/illum3-compiler-runtime-ledger-v2/output/observations.json", + "sha256": "c8b1e3f0704682e2cad20b7a5e27b1651e38b677e74f31d6477eb163185106fd", + "bytes": 4831 + }, + "controls.json": { + "original_path": "/home/ts/.local/state/openhcs-maintenance/20261003/illum3-compiler-runtime-ledger-v2/controls.json", + "sha256": "358cd70c391cdaae89d5f2ba8514de606ccabcf43be3507dadeba7ae2341f7d1", + "bytes": 1520 + }, + "science.json": { + "original_path": "/home/ts/.local/state/openhcs-maintenance/20261003/illum3-compiler-runtime-ledger-v2/science-v3.json", + "sha256": "607c68f213baddf4c5dbec97b39efee87451ac16188eadf1ebdea578d5bee9e5", + "bytes": 15478 + }, + "reader-first-red.json": { + "original_path": "/home/ts/.local/state/openhcs-maintenance/20261003/illum3-compiler-runtime-ledger-v2/science-first-red.json", + "sha256": "de6ae869a4f1fe6eabfa4fc5b5ee87ba052462f26302d0a7a334c7b2c4276c80", + "bytes": 872 + }, + "reader-environment-audit.json": { + "original_path": "/home/ts/.local/state/openhcs-maintenance/20261003/illum3-compiler-runtime-ledger-v2/science-first-red-environment-audit.json", + "sha256": "4fa0497da2158f883c3af73aaea0b906a63f0d3887d7f82ee89e9c8afc03db20", + "bytes": 1285 + }, + "render-retention-decision.json": { + "original_path": "/tmp/openhcs-render-retention-4c0d62/decision-v1.json", + "sha256": "905e189541015681fb58b42da8d28453f76710fbf088156b27260de90239bf94", + "bytes": 3626 + }, + "render-retention-replay.json": { + "original_path": "/tmp/openhcs-render-retention-4c0d62/result-v3.json", + "sha256": "28c79034129b4ea13aa7236c842b7b43bb0d6a5e67d84c22c6aca720d6bbed08", + "bytes": 29211 + }, + "render-retention-class-census.json": { + "original_path": "/tmp/openhcs-render-retention-4c0d62/census.json", + "sha256": "16f23b40d587e3d9e2005fd6e66d47e4d3264ed90e655b676c425095dfbd02d5", + "bytes": 25635 + }, + "compile_only-region.json": { + "original_path": "/home/ts/.local/state/openhcs-maintenance/20261003/illum3-compiler-runtime-ledger-v2/output/regions/region-2078682-140361443509952-0001.json", + "sha256": "cc69523fdae5fe92c4e96ec59609a19eb889fe744316b6ed8419ed0398313ab9", + "bytes": 15563 + }, + "execution-region.json": { + "original_path": "/home/ts/.local/state/openhcs-maintenance/20261003/illum3-compiler-runtime-ledger-v2/output/regions/region-2078682-140361443509952-0002.json", + "sha256": "f3c9e01926b069a0103ebb9c70d638a4944c1f429b809b3a7b2e9755efbf80e5", + "bytes": 25031 + }, + "numba-events-1.json": { + "original_path": "/home/ts/.local/state/openhcs-maintenance/20261003/illum3-compiler-runtime-ledger-v2/output/regions/numba-events-2078555-0001.json", + "sha256": "df39cc4538c692418c9590759ee2be67c03e712d31b38e59909a2acc414299da", + "bytes": 712 + }, + "numba-events-2.json": { + "original_path": "/home/ts/.local/state/openhcs-maintenance/20261003/illum3-compiler-runtime-ledger-v2/output/regions/numba-events-2078682-0001.json", + "sha256": "0cc87c64a35b572441cac162e7a953685af095892641222cef4b52a71d7ace03", + "bytes": 843 + }, + "numba-events-3.json": { + "original_path": "/home/ts/.local/state/openhcs-maintenance/20261003/illum3-compiler-runtime-ledger-v2/output/regions/numba-events-2078682-0002.json", + "sha256": "a80829256ff2e4f13f8cb14257b45138aacefb6e2726339b64be55d585c90fde", + "bytes": 840 + }, + "numba-events-4.json": { + "original_path": "/home/ts/.local/state/openhcs-maintenance/20261003/illum3-compiler-runtime-ledger-v2/output/regions/numba-events-2078682-0003.json", + "sha256": "c615a8d1c29b5da41bba3237cd1ee02e6f8eba72af2f73290f11ec684571661b", + "bytes": 712 + }, + "compiler-config-owner-decision.json": { + "original_path": "/tmp/openhcs-compile-config-owner-4c0d62/decision.json", + "sha256": "f99964708cfe2efa219dc0e254d780dd156f6c29ef720a08215cc29c2470a109", + "bytes": 8494 + }, + "compiler-config-class-census.json": { + "original_path": "/tmp/openhcs-compile-config-owner-4c0d62/census.json", + "sha256": "3b89e381bf150b66800e73439e6caecbc33170455ded87d67eb0dfbfdbbec855", + "bytes": 27972 + } + }, + "execution_outside_callable_fraction": 0.7307817861504636, + "raw_callable_count": 11, + "scope": "One 41-hook ordinary-path diagnostic, READY/startup/shutdown excluded, original OUTCOMES/memory/CPU5/official lease, no cProfile or runtime profiler. Both retained native outputs compared; no fresh native timing or paired performance gain.", + "qualification_corrections": [ + "The qualification late-getter label refers to all ten effective-config reads, including pre-capture reads; .192388s is an inclusive subset of state costs, not additional time or an eligible saving.", + "Installed owned ObjectState/python-introspect editables are distinguished from separately frozen canonical dependency source copies. The original 731-module AST census is a different epoch; no current global ownership proof is inferred.", + "Framework outside-callable time is an investigation envelope, not an assertion that all work is removable.", + "Zero native compile events applies to this observation; disk-cache loading and prior timing variance remain separate questions." + ], + "ownership_scope": "Current selected13modules71originalClassDefs refreshed through existingNRA, source/countmappingonly; no callback/alias/lifecycle equivalence or eligible wall implied." +} diff --git a/benchmark/results/perf_illum3_runtime_ledger_20261003/compile_only-region.json b/benchmark/results/perf_illum3_runtime_ledger_20261003/compile_only-region.json new file mode 100644 index 0000000000..8b1a510ab7 --- /dev/null +++ b/benchmark/results/perf_illum3_runtime_ledger_20261003/compile_only-region.json @@ -0,0 +1,430 @@ +{ + "pid": 2078682, + "thread": 140361443509952, + "region": "ZMQExecutionServer._execute_with_orchestrator", + "root_dimensions": "{\"case\": \"ExampleIlluminationCorrection_Example3\", \"compile_artifact_id\": null, \"execution_id\": \"78250d97-e324-4dbd-a014-62f28444b8a3\", \"kind\": \"compile_only\", \"plate\": \"/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images\"}", + "seconds": 0.5882621230557561, + "revision": "4c0d62e45c8afb85e34b69d7279cd00710f519b5", + "source": "/home/ts/code/projects/openhcs-shared-runtime-plumbing", + "stats": { + "ObjectState._compute_resolved_snapshot": { + "owner": "ObjectState._compute_resolved_snapshot", + "dimensions": "", + "phase": "compiler_config:_compute_resolved_snapshot", + "calls": 46, + "inclusive": 0.2531436877325177, + "exclusive": 0.2531436877325177 + }, + "ObjectState.__init__": { + "owner": "ObjectState.__init__", + "dimensions": "", + "phase": "compiler_config:__init__", + "calls": 23, + "inclusive": 0.35587291372939944, + "exclusive": 0.10272922599688172 + }, + "ObjectState._reconstruct_from_resolved": { + "owner": "ObjectState._reconstruct_from_resolved", + "dimensions": "", + "phase": "compiler_config:_reconstruct_from_resolved", + "calls": 343, + "inclusive": 0.05295955156907439, + "exclusive": 0.027533238753676414 + }, + "ObjectState.to_saved_resolved_object": { + "owner": "ObjectState.to_saved_resolved_object", + "dimensions": "", + "phase": "compiler_config:to_saved_resolved_object", + "calls": 21, + "inclusive": 0.027600623667240143, + "exclusive": 6.738491356372833e-05 + }, + "PipelineOrchestrator.get_effective_config": { + "owner": "PipelineOrchestrator.get_effective_config", + "dimensions": "", + "phase": "compiler_config:get_effective_config", + "calls": 10, + "inclusive": 0.19238800555467606, + "exclusive": 8.529284968972206e-05 + }, + "PipelineOrchestrator.create_context": { + "owner": "PipelineOrchestrator.create_context", + "dimensions": "", + "phase": "compiler_config:create_context", + "calls": 3, + "inclusive": 0.04923866596072912, + "exclusive": 0.0002901456318795681 + }, + "ZMQExecutionServer._initialize_orchestrator": { + "owner": "ZMQExecutionServer._initialize_orchestrator", + "dimensions": "", + "phase": "_initialize_orchestrator", + "calls": 1, + "inclusive": 0.1088466951623559, + "exclusive": 0.003273043315857649 + }, + "PipelineCompiler._axis_values_to_process": { + "owner": "PipelineCompiler._axis_values_to_process", + "dimensions": "", + "phase": "compiler_config:_axis_values_to_process", + "calls": 1, + "inclusive": 0.014383771922439337, + "exclusive": 7.574260234832764e-05 + }, + "PipelineCompiler._register_and_resolve_pipeline_once": { + "owner": "PipelineCompiler._register_and_resolve_pipeline_once", + "dimensions": "", + "phase": "compiler_config:_register_and_resolve_pipeline_once", + "calls": 1, + "inclusive": 0.19153947802260518, + "exclusive": 0.0021261521615087986 + }, + "PipelineCompiler._capture_pipeline_config": { + "owner": "PipelineCompiler._capture_pipeline_config", + "dimensions": "", + "phase": "compiler_config:_capture_pipeline_config", + "calls": 1, + "inclusive": 0.0017600241117179394, + "exclusive": 2.52528116106987e-06 + }, + "PipelineCompiler._resolve_global_step_axis_filters": { + "owner": "PipelineCompiler._resolve_global_step_axis_filters", + "dimensions": "", + "phase": "compiler_config:_resolve_global_step_axis_filters", + "calls": 1, + "inclusive": 0.013955585192888975, + "exclusive": 0.00047726836055517197 + }, + "AxisCompilationRequest.context_for": { + "owner": "AxisCompilationRequest.context_for", + "dimensions": "", + "phase": "compiler_config:context_for", + "calls": 1, + "inclusive": 0.018960938788950443, + "exclusive": 0.00017500855028629303 + }, + "CompilationSession.from_context": { + "owner": "CompilationSession.from_context", + "dimensions": "", + "phase": "compiler_config:from_context", + "calls": 1, + "inclusive": 1.70818530023098e-05, + "exclusive": 1.70818530023098e-05 + }, + "PipelineCompiler._configure_input_conversion_if_needed": { + "owner": "PipelineCompiler._configure_input_conversion_if_needed", + "dimensions": "", + "phase": "compiler_config:_configure_input_conversion_if_needed", + "calls": 1, + "inclusive": 0.013350545894354582, + "exclusive": 4.2282044887542725e-06 + }, + "PipelineCompiler.initialize_step_plans_for_context": { + "owner": "PipelineCompiler.initialize_step_plans_for_context", + "dimensions": "", + "phase": "compiler_config:initialize_step_plans_for_context", + "calls": 1, + "inclusive": 0.14918227866292, + "exclusive": 0.1358146509155631 + }, + "PipelineCompiler.declare_zarr_stores": { + "owner": "PipelineCompiler.declare_zarr_stores", + "dimensions": "", + "phase": "compiler_config:declare_zarr_stores", + "calls": 1, + "inclusive": 0.013443371281027794, + "exclusive": 4.089716821908951e-05 + }, + "PipelineCompiler._finalize_compilation": { + "owner": "PipelineCompiler._finalize_compilation", + "dimensions": "", + "phase": "compiler_config:_finalize_compilation", + "calls": 1, + "inclusive": 0.013896864838898182, + "exclusive": 0.00011343369260430336 + }, + "PipelineCompiler.compile_pipelines": { + "owner": "PipelineCompiler.compile_pipelines", + "dimensions": "", + "phase": "compiler_config:compile_pipelines", + "calls": 1, + "inclusive": 0.437725986354053, + "exclusive": 0.02060367353260517 + }, + "ZMQExecutionServer._execute_with_orchestrator | {\"case\": \"ExampleIlluminationCorrection_Example3\", \"compile_artifact_id\": null, \"execution_id\": \"78250d97-e324-4dbd-a014-62f28444b8a3\", \"kind\": \"compile_only\", \"plate\": \"/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images\"}": { + "owner": "ZMQExecutionServer._execute_with_orchestrator", + "dimensions": "{\"case\": \"ExampleIlluminationCorrection_Example3\", \"compile_artifact_id\": null, \"execution_id\": \"78250d97-e324-4dbd-a014-62f28444b8a3\", \"kind\": \"compile_only\", \"plate\": \"/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images\"}", + "phase": "_execute_with_orchestrator", + "calls": 1, + "inclusive": 0.5882621230557561, + "exclusive": 0.04168944153934717 + } + }, + "hooks_installed": [ + { + "module": "objectstate.object_state", + "owner": "ObjectState", + "method": "__init__", + "descriptor_kind": "function" + }, + { + "module": "objectstate.object_state", + "owner": "ObjectState", + "method": "_compute_resolved_snapshot", + "descriptor_kind": "function" + }, + { + "module": "objectstate.object_state", + "owner": "ObjectState", + "method": "_reconstruct_from_resolved", + "descriptor_kind": "function" + }, + { + "module": "objectstate.object_state", + "owner": "ObjectState", + "method": "to_saved_resolved_object", + "descriptor_kind": "function" + }, + { + "module": "openhcs.core.aligned_image_payload", + "owner": "", + "method": "stack_image_payload_context", + "descriptor_kind": "function" + }, + { + "module": "openhcs.core.aligned_image_payload", + "owner": "", + "method": "unstack_image_payload_context", + "descriptor_kind": "function" + }, + { + "module": "openhcs.core.measurement_feature_queries", + "owner": "MeasurementFeatureValueIndex", + "method": "from_columnar_table_by_object", + "descriptor_kind": "classmethod" + }, + { + "module": "openhcs.core.virtual_workspace_metadata", + "owner": "AtomicMetadataWriter", + "method": "publish_source_projection_metadata", + "descriptor_kind": "function" + }, + { + "module": "openhcs.core.runtime_stack_cache", + "owner": "RuntimeImageStackCache", + "method": "get", + "descriptor_kind": "function" + }, + { + "module": "openhcs.core.runtime_stack_cache", + "owner": "RuntimeImageStackCache", + "method": "store", + "descriptor_kind": "function" + }, + { + "module": "openhcs.core.steps.function_outputs", + "owner": "", + "method": "finalize_function_step_outputs", + "descriptor_kind": "function" + }, + { + "module": "openhcs.core.steps.function_outputs", + "owner": "OpenHCSMetadataWriter", + "method": "finalize_completed_plate", + "descriptor_kind": "classmethod" + }, + { + "module": "openhcs.core.steps.function_outputs", + "owner": "RuntimeArtifactMetadataTarget", + "method": "reconciliation_targets", + "descriptor_kind": "function" + }, + { + "module": "openhcs.core.steps.function_runtime", + "owner": "FunctionCoreExecutor", + "method": "execute", + "descriptor_kind": "function" + }, + { + "module": "openhcs.core.steps.function_runtime", + "owner": "PatternGroupRuntime", + "method": "_load_input_stack", + "descriptor_kind": "function" + }, + { + "module": "openhcs.core.steps.function_runtime", + "owner": "PatternGroupRuntime", + "method": "_validate_and_unstack", + "descriptor_kind": "function" + }, + { + "module": "openhcs.core.steps.function_runtime", + "owner": "PatternGroupRuntime", + "method": "_save_outputs", + "descriptor_kind": "function" + }, + { + "module": "openhcs.core.pipeline.compilation_session", + "owner": "CompilationSession", + "method": "from_context", + "descriptor_kind": "classmethod" + }, + { + "module": "openhcs.core.pipeline.compiler", + "owner": "PipelineCompiler", + "method": "compile_pipelines", + "descriptor_kind": "staticmethod" + }, + { + "module": "openhcs.core.pipeline.compiler", + "owner": "PipelineCompiler", + "method": "_register_and_resolve_pipeline_once", + "descriptor_kind": "staticmethod" + }, + { + "module": "openhcs.core.pipeline.compiler", + "owner": "PipelineCompiler", + "method": "initialize_step_plans_for_context", + "descriptor_kind": "staticmethod" + }, + { + "module": "openhcs.core.pipeline.compiler", + "owner": "PipelineCompiler", + "method": "_capture_pipeline_config", + "descriptor_kind": "staticmethod" + }, + { + "module": "openhcs.core.pipeline.compiler", + "owner": "PipelineCompiler", + "method": "_resolve_global_step_axis_filters", + "descriptor_kind": "staticmethod" + }, + { + "module": "openhcs.core.pipeline.compiler", + "owner": "PipelineCompiler", + "method": "_configure_input_conversion_if_needed", + "descriptor_kind": "staticmethod" + }, + { + "module": "openhcs.core.pipeline.compiler", + "owner": "PipelineCompiler", + "method": "declare_zarr_stores", + "descriptor_kind": "staticmethod" + }, + { + "module": "openhcs.core.pipeline.compiler", + "owner": "PipelineCompiler", + "method": "_finalize_compilation", + "descriptor_kind": "staticmethod" + }, + { + "module": "openhcs.core.pipeline.compiler", + "owner": "PipelineCompiler", + "method": "_axis_values_to_process", + "descriptor_kind": "staticmethod" + }, + { + "module": "openhcs.core.pipeline.compiler", + "owner": "AxisCompilationRequest", + "method": "context_for", + "descriptor_kind": "function" + }, + { + "module": "openhcs.processing.backends.lib_registry.unified_registry", + "owner": "RuntimeCallableInvocation", + "method": "call", + "descriptor_kind": "function" + }, + { + "module": "openhcs.core.orchestrator.analysis_consolidation", + "owner": "", + "method": "consolidate_analysis_outputs", + "descriptor_kind": "function" + }, + { + "module": "openhcs.core.orchestrator.worker_execution", + "owner": "", + "method": "execute_worker_lane", + "descriptor_kind": "function" + }, + { + "module": "openhcs.core.orchestrator.orchestrator", + "owner": "PipelineOrchestrator", + "method": "create_context", + "descriptor_kind": "function" + }, + { + "module": "openhcs.core.orchestrator.orchestrator", + "owner": "PipelineOrchestrator", + "method": "get_effective_config", + "descriptor_kind": "function" + }, + { + "module": "openhcs.runtime.zmq_execution_server", + "owner": "ZMQExecutionServer", + "method": "_execute_with_orchestrator", + "descriptor_kind": "function" + }, + { + "module": "openhcs.runtime.zmq_execution_server", + "owner": "ZMQExecutionServer", + "method": "_initialize_orchestrator", + "descriptor_kind": "function" + }, + { + "module": "openhcs.runtime.zmq_execution_server", + "owner": "ZMQExecutionServer", + "method": "_export_runtime_observation", + "descriptor_kind": "function" + }, + { + "module": "openhcs.interop.cellprofiler.runtime.function_contract_execution", + "owner": "CellProfilerFunctionContractExecutor", + "method": "execute", + "descriptor_kind": "function" + }, + { + "module": "openhcs.interop.cellprofiler.runtime.measurement_execution_support", + "owner": "ObjectMeasurementOutputRecorder", + "method": "record", + "descriptor_kind": "function" + }, + { + "module": "openhcs.interop.cellprofiler.runtime.output_recording", + "owner": "CellProfilerOutputRecorder", + "method": "record_module_outputs", + "descriptor_kind": "classmethod" + }, + { + "module": "openhcs.interop.cellprofiler.runtime.module_execution", + "owner": "CellProfilerModuleExecutor", + "method": "__call__", + "descriptor_kind": "function" + }, + { + "module": "openhcs.interop.cellprofiler.runtime.module_execution", + "owner": "CellProfilerModuleExecutor", + "method": "_image_request", + "descriptor_kind": "function" + } + ], + "profiling_enabled": false, + "runtime_profiling_enabled": false, + "diagnostic_errors": [], + "captures": false, + "root_started_monotonic_ns": 3816282952668134, + "root_ended_monotonic_ns": 3816283540961927, + "numba_events": { + "installed": true, + "counts": {}, + "record_count": 0, + "pending_record_count": 0, + "flushed_record_count": 0, + "refused_records": 0, + "errors": [], + "error_count": 0, + "record_bytes": 0, + "cap": 262144 + }, + "scope": "coarse same-run nested exclusive timing partition on the exact source revision recorded in this region. Diagnostic wrappers, no scientific or memory-observer substitutions. Not accepted performance comparison. Declared callable boundary includes filtering/decorated processing/metadata; not pure numerical kernels. Both existing profilers are disabled. These wrappers still add diagnostic overhead; no scaling to uninstrumented clocks or causal performance claims. Compiler/state boundaries and query boundary are nested under actual parents and excluded from parent-exclusive elapsed. This is a NEW 41-hook diagnostic version; inherited 24 boundary labels remain, site bytes are changed. ObjectState is verified against the actual source dependency path, not assumed inside the OpenHCS package." +} diff --git a/benchmark/results/perf_illum3_runtime_ledger_20261003/compiler-config-class-census.json b/benchmark/results/perf_illum3_runtime_ledger_20261003/compiler-config-class-census.json new file mode 100644 index 0000000000..9e1ddb4a74 --- /dev/null +++ b/benchmark/results/perf_illum3_runtime_ledger_20261003/compiler-config-class-census.json @@ -0,0 +1 @@ +{"head":"4c0d62e45c8afb85e34b69d7279cd00710f519b5","dependency_heads":{"ObjectState":"a01f8939b9bf4659502a33fe3febe62cab0f3c9a","python-introspect":"ed1e4eb15f7a0bf8315274d3e47858fa2b4372bb"},"original_global_census":{"path":"/home/ts/.local/state/openhcs-maintenance/20261003/compiler-config-transaction-map-v1/census.json","sha256":"60541e7bc14f20f6e9d698ac25ea6f094b5503a0670df2f893d83bb5564d3868","head":"480aed49b30448de4380af5c9274e48084e67b63","modules":731,"original_classes":5302,"canonical_classes":5290,"epoch":"ORIGINAL; not a universally current inventory"},"current_selected_modules":13,"current_selected_original_classes":71,"current_selected_canonical_classes":71,"source":[{"path":"openhcs/core/pipeline/compiler.py","sha256":"f9c368f046fd338ae51ee46251ecc24f4b246b00971db423a1f14fb4d8ca4a10","original_731_module_census_sha256":"f9c368f046fd338ae51ee46251ecc24f4b246b00971db423a1f14fb4d8ca4a10"},{"path":"openhcs/core/pipeline/compilation_session.py","sha256":"3c840a89baccc8665d415175458280fd904c1a837b7fd879e303d7dbca129a1c","original_731_module_census_sha256":"3c840a89baccc8665d415175458280fd904c1a837b7fd879e303d7dbca129a1c"},{"path":"openhcs/core/orchestrator/orchestrator.py","sha256":"ae64fbf28c96f7672fd389b4647b96b11b0b90caccd28e542984692e82e2baf9","original_731_module_census_sha256":"ae64fbf28c96f7672fd389b4647b96b11b0b90caccd28e542984692e82e2baf9"},{"path":"openhcs/core/context/processing_context.py","sha256":"fa587f726d3baac27f17b064db7230d58162408e4230d426f08acc91568b1c75","original_731_module_census_sha256":"fa587f726d3baac27f17b064db7230d58162408e4230d426f08acc91568b1c75"},{"path":"openhcs/core/config.py","sha256":"47d54358521bd7c7abfea1b3bd2cb4b8c24fd9a85826498437a6970122d59d74","original_731_module_census_sha256":"47d54358521bd7c7abfea1b3bd2cb4b8c24fd9a85826498437a6970122d59d74"},{"path":"openhcs/runtime/zmq_execution_server.py","sha256":"738450e5af28b1b54595d21685d43e3961273c0d3284ec8dae7161a558353f5d","original_731_module_census_sha256":"738450e5af28b1b54595d21685d43e3961273c0d3284ec8dae7161a558353f5d"},{"path":"openhcs/runtime/zmq_execution_signature.py","sha256":"41dcdb0a40446947a42a87482f27da051408015eec972e11e4d3329464db11ac","original_731_module_census_sha256":"41dcdb0a40446947a42a87482f27da051408015eec972e11e4d3329464db11ac"},{"path":"openhcs/runtime/zmq_compilation.py","sha256":"ad958c78ec9a26b778ad231501751f38ec6dd3d0c73ca2c1082207031fc6781f","original_731_module_census_sha256":"ad958c78ec9a26b778ad231501751f38ec6dd3d0c73ca2c1082207031fc6781f"},{"path":"external/ObjectState/src/objectstate/object_state.py","sha256":"735ce860ab650b281534e24e3c7354f37b64bb06832cf186d6b1f626f87108fe","original_731_module_census_sha256":"735ce860ab650b281534e24e3c7354f37b64bb06832cf186d6b1f626f87108fe"},{"path":"external/ObjectState/src/objectstate/object_state_registry.py","sha256":"f848746a9c2a023a616c37531691073ea7bdb8d28d7db3bca5c8a3dcb176107a","original_731_module_census_sha256":"f848746a9c2a023a616c37531691073ea7bdb8d28d7db3bca5c8a3dcb176107a"},{"path":"external/ObjectState/src/objectstate/context_manager.py","sha256":"a01b0fc8aeb9b5b0888346f725f92cbfd96b90963bf20001b5414a5e6cd6c0e6","original_731_module_census_sha256":"a01b0fc8aeb9b5b0888346f725f92cbfd96b90963bf20001b5414a5e6cd6c0e6"},{"path":"external/ObjectState/src/objectstate/lazy_factory.py","sha256":"64ae924c176757863a84eef19b9df0eff516e32443c2661134ec2ae72f234bf9","original_731_module_census_sha256":"f81ce722695dbab98fd02658f2015e5cb93c1e1e69547d24249e62d896e2a828"},{"path":"external/ObjectState/src/objectstate/global_config.py","sha256":"a8187811f87806579640a8147f287114e7127401530178dd37e8d28ed788a6ae","original_731_module_census_sha256":"a8187811f87806579640a8147f287114e7127401530178dd37e8d28ed788a6ae"}],"classes":[{"file":"openhcs/core/pipeline/compiler.py","name":"AxisCompilationRequest","line":194,"canonical":true,"symbol":"home.ts.code.projects.openhcs-shared-runtime-plumbing.openhcs.core.pipeline.compiler.AxisCompilationRequest","bases":[],"resolved_bases":[]},{"file":"openhcs/core/pipeline/compiler.py","name":"PipelineCompiler","line":223,"canonical":true,"symbol":"home.ts.code.projects.openhcs-shared-runtime-plumbing.openhcs.core.pipeline.compiler.PipelineCompiler","bases":[],"resolved_bases":[]},{"file":"openhcs/core/pipeline/compilation_session.py","name":"CompilationPlateScope","line":34,"canonical":true,"symbol":"home.ts.code.projects.openhcs-shared-runtime-plumbing.openhcs.core.pipeline.compilation_session.CompilationPlateScope","bases":[],"resolved_bases":[]},{"file":"openhcs/core/pipeline/compilation_session.py","name":"CompilationPathResolver","line":86,"canonical":true,"symbol":"home.ts.code.projects.openhcs-shared-runtime-plumbing.openhcs.core.pipeline.compilation_session.CompilationPathResolver","bases":[],"resolved_bases":[]},{"file":"openhcs/core/pipeline/compilation_session.py","name":"CompilationSession","line":160,"canonical":true,"symbol":"home.ts.code.projects.openhcs-shared-runtime-plumbing.openhcs.core.pipeline.compilation_session.CompilationSession","bases":[],"resolved_bases":[]},{"file":"openhcs/core/pipeline/compilation_session.py","name":"ResolvedPipelineDefinition","line":331,"canonical":true,"symbol":"home.ts.code.projects.openhcs-shared-runtime-plumbing.openhcs.core.pipeline.compilation_session.ResolvedPipelineDefinition","bases":[],"resolved_bases":[]},{"file":"openhcs/core/orchestrator/orchestrator.py","name":"PipelineOrchestrator","line":79,"canonical":true,"symbol":"home.ts.code.projects.openhcs-shared-runtime-plumbing.openhcs.core.orchestrator.orchestrator.PipelineOrchestrator","bases":[],"resolved_bases":[]},{"file":"openhcs/core/context/processing_context.py","name":"RequiredVisualizer","line":49,"canonical":true,"symbol":"home.ts.code.projects.openhcs-shared-runtime-plumbing.openhcs.core.context.processing_context.RequiredVisualizer","bases":[],"resolved_bases":[]},{"file":"openhcs/core/context/processing_context.py","name":"ProcessingContext","line":67,"canonical":true,"symbol":"home.ts.code.projects.openhcs-shared-runtime-plumbing.openhcs.core.context.processing_context.ProcessingContext","bases":[],"resolved_bases":[]},{"file":"openhcs/core/config.py","name":"StreamingConfigMeta","line":53,"canonical":true,"symbol":"home.ts.code.projects.openhcs-shared-runtime-plumbing.openhcs.core.config.StreamingConfigMeta","bases":["EnableableMeta","AutoRegisterMeta"],"resolved_bases":[]},{"file":"openhcs/core/config.py","name":"MaterializationBackend","line":75,"canonical":true,"symbol":"home.ts.code.projects.openhcs-shared-runtime-plumbing.openhcs.core.config.MaterializationBackend","bases":["Enum"],"resolved_bases":[]},{"file":"openhcs/core/config.py","name":"WellFilterMode","line":84,"canonical":true,"symbol":"home.ts.code.projects.openhcs-shared-runtime-plumbing.openhcs.core.config.WellFilterMode","bases":["Enum"],"resolved_bases":[]},{"file":"openhcs/core/config.py","name":"NormalizationMethod","line":102,"canonical":true,"symbol":"home.ts.code.projects.openhcs-shared-runtime-plumbing.openhcs.core.config.NormalizationMethod","bases":["Enum"],"resolved_bases":[]},{"file":"openhcs/core/config.py","name":"MultiprocessingStartMethod","line":145,"canonical":true,"symbol":"home.ts.code.projects.openhcs-shared-runtime-plumbing.openhcs.core.config.MultiprocessingStartMethod","bases":["Enum"],"resolved_bases":[]},{"file":"openhcs/core/config.py","name":"GlobalPipelineConfig","line":156,"canonical":true,"symbol":"home.ts.code.projects.openhcs-shared-runtime-plumbing.openhcs.core.config.GlobalPipelineConfig","bases":["AnnotatedDataclassValidationMixin"],"resolved_bases":[]},{"file":"openhcs/core/config.py","name":"NapariDimensionMode","line":240,"canonical":true,"symbol":"home.ts.code.projects.openhcs-shared-runtime-plumbing.openhcs.core.config.NapariDimensionMode","bases":["Enum"],"resolved_bases":[]},{"file":"openhcs/core/config.py","name":"NapariVariableSizeHandling","line":247,"canonical":true,"symbol":"home.ts.code.projects.openhcs-shared-runtime-plumbing.openhcs.core.config.NapariVariableSizeHandling","bases":["Enum"],"resolved_bases":[]},{"file":"openhcs/core/config.py","name":"NapariDisplayConfig","line":257,"canonical":true,"symbol":"home.ts.code.projects.openhcs-shared-runtime-plumbing.openhcs.core.config.NapariDisplayConfig","bases":["ViewerDisplayConfigABC","AnnotatedDataclassValidationMixin"],"resolved_bases":[]},{"file":"openhcs/core/config.py","name":"FijiDimensionMode","line":394,"canonical":true,"symbol":"home.ts.code.projects.openhcs-shared-runtime-plumbing.openhcs.core.config.FijiDimensionMode","bases":["Enum"],"resolved_bases":[]},{"file":"openhcs/core/config.py","name":"FijiDisplayConfig","line":414,"canonical":true,"symbol":"home.ts.code.projects.openhcs-shared-runtime-plumbing.openhcs.core.config.FijiDisplayConfig","bases":["ViewerDisplayConfigABC","AnnotatedDataclassValidationMixin"],"resolved_bases":[]},{"file":"openhcs/core/config.py","name":"WellFilterConfig","line":552,"canonical":true,"symbol":"home.ts.code.projects.openhcs-shared-runtime-plumbing.openhcs.core.config.WellFilterConfig","bases":["AnnotatedDataclassValidationMixin"],"resolved_bases":[]},{"file":"openhcs/core/config.py","name":"ZarrConfig","line":613,"canonical":true,"symbol":"home.ts.code.projects.openhcs-shared-runtime-plumbing.openhcs.core.config.ZarrConfig","bases":["AnnotatedDataclassValidationMixin","_polystore_config.ZarrConfig"],"resolved_bases":[]},{"file":"openhcs/core/config.py","name":"TiffConfig","line":627,"canonical":true,"symbol":"home.ts.code.projects.openhcs-shared-runtime-plumbing.openhcs.core.config.TiffConfig","bases":["AnnotatedDataclassValidationMixin","_polystore_config.TiffConfig"],"resolved_bases":[]},{"file":"openhcs/core/config.py","name":"VFSConfig","line":634,"canonical":true,"symbol":"home.ts.code.projects.openhcs-shared-runtime-plumbing.openhcs.core.config.VFSConfig","bases":["AnnotatedDataclassValidationMixin"],"resolved_bases":[]},{"file":"openhcs/core/config.py","name":"DtypeConfig","line":666,"canonical":true,"symbol":"home.ts.code.projects.openhcs-shared-runtime-plumbing.openhcs.core.config.DtypeConfig","bases":["AnnotatedDataclassValidationMixin","RuntimeSliceInvariantValue","DtypeConversionConfig"],"resolved_bases":[]},{"file":"openhcs/core/config.py","name":"ProcessingConfig","line":699,"canonical":true,"symbol":"home.ts.code.projects.openhcs-shared-runtime-plumbing.openhcs.core.config.ProcessingConfig","bases":["AnnotatedDataclassValidationMixin"],"resolved_bases":[]},{"file":"openhcs/core/config.py","name":"SequentialProcessingConfig","line":751,"canonical":true,"symbol":"home.ts.code.projects.openhcs-shared-runtime-plumbing.openhcs.core.config.SequentialProcessingConfig","bases":["AnnotatedDataclassValidationMixin"],"resolved_bases":[]},{"file":"openhcs/core/config.py","name":"AnalysisConsolidationConfig","line":774,"canonical":true,"symbol":"home.ts.code.projects.openhcs-shared-runtime-plumbing.openhcs.core.config.AnalysisConsolidationConfig","bases":["AnnotatedDataclassValidationMixin","Enableable"],"resolved_bases":[]},{"file":"openhcs/core/config.py","name":"PlateMetadataConfig","line":815,"canonical":true,"symbol":"home.ts.code.projects.openhcs-shared-runtime-plumbing.openhcs.core.config.PlateMetadataConfig","bases":["AnnotatedDataclassValidationMixin"],"resolved_bases":[]},{"file":"openhcs/core/config.py","name":"ExperimentalAnalysisConfig","line":838,"canonical":true,"symbol":"home.ts.code.projects.openhcs-shared-runtime-plumbing.openhcs.core.config.ExperimentalAnalysisConfig","bases":["AnnotatedDataclassValidationMixin"],"resolved_bases":[]},{"file":"openhcs/core/config.py","name":"PathPlanningConfig","line":891,"canonical":true,"symbol":"home.ts.code.projects.openhcs-shared-runtime-plumbing.openhcs.core.config.PathPlanningConfig","bases":["WellFilterConfig"],"resolved_bases":["home.ts.code.projects.openhcs-shared-runtime-plumbing.openhcs.core.config.WellFilterConfig"]},{"file":"openhcs/core/config.py","name":"StepWellFilterConfig","line":931,"canonical":true,"symbol":"home.ts.code.projects.openhcs-shared-runtime-plumbing.openhcs.core.config.StepWellFilterConfig","bases":["WellFilterConfig"],"resolved_bases":["home.ts.code.projects.openhcs-shared-runtime-plumbing.openhcs.core.config.WellFilterConfig"]},{"file":"openhcs/core/config.py","name":"StepMaterializationConfig","line":942,"canonical":true,"symbol":"home.ts.code.projects.openhcs-shared-runtime-plumbing.openhcs.core.config.StepMaterializationConfig","bases":["Enableable","StepWellFilterConfig","PathPlanningConfig"],"resolved_bases":["home.ts.code.projects.openhcs-shared-runtime-plumbing.openhcs.core.config.StepWellFilterConfig","home.ts.code.projects.openhcs-shared-runtime-plumbing.openhcs.core.config.PathPlanningConfig"]},{"file":"openhcs/core/config.py","name":"StreamingDefaults","line":983,"canonical":true,"symbol":"home.ts.code.projects.openhcs-shared-runtime-plumbing.openhcs.core.config.StreamingDefaults","bases":["Enableable","StepWellFilterConfig"],"resolved_bases":["home.ts.code.projects.openhcs-shared-runtime-plumbing.openhcs.core.config.StepWellFilterConfig"]},{"file":"openhcs/core/config.py","name":"StreamingConfig","line":1037,"canonical":true,"symbol":"home.ts.code.projects.openhcs-shared-runtime-plumbing.openhcs.core.config.StreamingConfig","bases":["StreamingDefaults","ABC"],"resolved_bases":["home.ts.code.projects.openhcs-shared-runtime-plumbing.openhcs.core.config.StreamingDefaults"]},{"file":"openhcs/core/config.py","name":"NapariStreamingConfig","line":1156,"canonical":true,"symbol":"home.ts.code.projects.openhcs-shared-runtime-plumbing.openhcs.core.config.NapariStreamingConfig","bases":["StreamingConfigBehaviorMixin","StreamingConfig","NapariDisplayConfig"],"resolved_bases":["home.ts.code.projects.openhcs-shared-runtime-plumbing.openhcs.core.config.StreamingConfig","home.ts.code.projects.openhcs-shared-runtime-plumbing.openhcs.core.config.NapariDisplayConfig"]},{"file":"openhcs/core/config.py","name":"FijiStreamingConfig","line":1188,"canonical":true,"symbol":"home.ts.code.projects.openhcs-shared-runtime-plumbing.openhcs.core.config.FijiStreamingConfig","bases":["StreamingConfigBehaviorMixin","StreamingConfig","FijiDisplayConfig"],"resolved_bases":["home.ts.code.projects.openhcs-shared-runtime-plumbing.openhcs.core.config.StreamingConfig","home.ts.code.projects.openhcs-shared-runtime-plumbing.openhcs.core.config.FijiDisplayConfig"]},{"file":"openhcs/core/config.py","name":"CompilationDebugConfig","line":1206,"canonical":true,"symbol":"home.ts.code.projects.openhcs-shared-runtime-plumbing.openhcs.core.config.CompilationDebugConfig","bases":["AnnotatedDataclassValidationMixin","Enableable"],"resolved_bases":[]},{"file":"openhcs/runtime/zmq_execution_server.py","name":"ZMQExecutionContext","line":60,"canonical":true,"symbol":"home.ts.code.projects.openhcs-shared-runtime-plumbing.openhcs.runtime.zmq_execution_server.ZMQExecutionContext","bases":[],"resolved_bases":[]},{"file":"openhcs/runtime/zmq_execution_server.py","name":"FunctionCatalogExecutionServer","line":126,"canonical":true,"symbol":"home.ts.code.projects.openhcs-shared-runtime-plumbing.openhcs.runtime.zmq_execution_server.FunctionCatalogExecutionServer","bases":["ExecutionServer"],"resolved_bases":[]},{"file":"openhcs/runtime/zmq_execution_server.py","name":"ZMQExecutionServer","line":161,"canonical":true,"symbol":"home.ts.code.projects.openhcs-shared-runtime-plumbing.openhcs.runtime.zmq_execution_server.ZMQExecutionServer","bases":["FunctionCatalogExecutionServer"],"resolved_bases":["home.ts.code.projects.openhcs-shared-runtime-plumbing.openhcs.runtime.zmq_execution_server.FunctionCatalogExecutionServer"]},{"file":"openhcs/runtime/zmq_execution_signature.py","name":"ZMQAuxiliaryParamField","line":36,"canonical":true,"symbol":"home.ts.code.projects.openhcs-shared-runtime-plumbing.openhcs.runtime.zmq_execution_signature.ZMQAuxiliaryParamField","bases":["Enum"],"resolved_bases":[]},{"file":"openhcs/runtime/zmq_execution_signature.py","name":"ZMQRuntimeObservationExportScope","line":44,"canonical":true,"symbol":"home.ts.code.projects.openhcs-shared-runtime-plumbing.openhcs.runtime.zmq_execution_signature.ZMQRuntimeObservationExportScope","bases":["Enum"],"resolved_bases":[]},{"file":"openhcs/runtime/zmq_execution_signature.py","name":"ZMQAuxiliaryExecutionParams","line":52,"canonical":true,"symbol":"home.ts.code.projects.openhcs-shared-runtime-plumbing.openhcs.runtime.zmq_execution_signature.ZMQAuxiliaryExecutionParams","bases":[],"resolved_bases":[]},{"file":"openhcs/runtime/zmq_execution_signature.py","name":"OpenHCSExecutionConfigBundle","line":206,"canonical":true,"symbol":"home.ts.code.projects.openhcs-shared-runtime-plumbing.openhcs.runtime.zmq_execution_signature.OpenHCSExecutionConfigBundle","bases":[],"resolved_bases":[]},{"file":"openhcs/runtime/zmq_execution_signature.py","name":"ZMQExecutionIdentity","line":214,"canonical":true,"symbol":"home.ts.code.projects.openhcs-shared-runtime-plumbing.openhcs.runtime.zmq_execution_signature.ZMQExecutionIdentity","bases":[],"resolved_bases":[]},{"file":"openhcs/runtime/zmq_execution_signature.py","name":"ZMQExecutionCompileControl","line":240,"canonical":true,"symbol":"home.ts.code.projects.openhcs-shared-runtime-plumbing.openhcs.runtime.zmq_execution_signature.ZMQExecutionCompileControl","bases":[],"resolved_bases":[]},{"file":"openhcs/runtime/zmq_execution_signature.py","name":"ZMQExecutionConfigTransport","line":283,"canonical":true,"symbol":"home.ts.code.projects.openhcs-shared-runtime-plumbing.openhcs.runtime.zmq_execution_signature.ZMQExecutionConfigTransport","bases":[],"resolved_bases":[]},{"file":"openhcs/runtime/zmq_execution_signature.py","name":"ZMQExecutionRequestPayload","line":307,"canonical":true,"symbol":"home.ts.code.projects.openhcs-shared-runtime-plumbing.openhcs.runtime.zmq_execution_signature.ZMQExecutionRequestPayload","bases":[],"resolved_bases":[]},{"file":"openhcs/runtime/zmq_compilation.py","name":"ZMQCompilationResult","line":53,"canonical":true,"symbol":"home.ts.code.projects.openhcs-shared-runtime-plumbing.openhcs.runtime.zmq_compilation.ZMQCompilationResult","bases":[],"resolved_bases":[]},{"file":"openhcs/runtime/zmq_compilation.py","name":"ZMQCompilationRequest","line":69,"canonical":true,"symbol":"home.ts.code.projects.openhcs-shared-runtime-plumbing.openhcs.runtime.zmq_compilation.ZMQCompilationRequest","bases":[],"resolved_bases":[]},{"file":"openhcs/runtime/zmq_compilation.py","name":"ZMQCompileArtifactRecord","line":219,"canonical":true,"symbol":"home.ts.code.projects.openhcs-shared-runtime-plumbing.openhcs.runtime.zmq_compilation.ZMQCompileArtifactRecord","bases":[],"resolved_bases":[]},{"file":"external/ObjectState/src/objectstate/object_state.py","name":"FieldProxy","line":48,"canonical":true,"symbol":"home.ts.code.projects.openhcs-shared-runtime-plumbing.external.ObjectState.src.objectstate.object_state.FieldProxy","bases":[],"resolved_bases":[]},{"file":"external/ObjectState/src/objectstate/object_state.py","name":"ObjectState","line":120,"canonical":true,"symbol":"home.ts.code.projects.openhcs-shared-runtime-plumbing.external.ObjectState.src.objectstate.object_state.ObjectState","bases":[],"resolved_bases":[]},{"file":"external/ObjectState/src/objectstate/object_state_registry.py","name":"ObjectStateRegistrySubscription","line":46,"canonical":true,"symbol":"home.ts.code.projects.openhcs-shared-runtime-plumbing.external.ObjectState.src.objectstate.object_state_registry.ObjectStateRegistrySubscription","bases":[],"resolved_bases":[]},{"file":"external/ObjectState/src/objectstate/object_state_registry.py","name":"TimeTravelTransaction","line":63,"canonical":true,"symbol":"home.ts.code.projects.openhcs-shared-runtime-plumbing.external.ObjectState.src.objectstate.object_state_registry.TimeTravelTransaction","bases":[],"resolved_bases":[]},{"file":"external/ObjectState/src/objectstate/object_state_registry.py","name":"TimeTravelScopeReconciliation","line":74,"canonical":true,"symbol":"home.ts.code.projects.openhcs-shared-runtime-plumbing.external.ObjectState.src.objectstate.object_state_registry.TimeTravelScopeReconciliation","bases":[],"resolved_bases":[]},{"file":"external/ObjectState/src/objectstate/object_state_registry.py","name":"PreparedStateRestore","line":82,"canonical":true,"symbol":"home.ts.code.projects.openhcs-shared-runtime-plumbing.external.ObjectState.src.objectstate.object_state_registry.PreparedStateRestore","bases":[],"resolved_bases":[]},{"file":"external/ObjectState/src/objectstate/object_state_registry.py","name":"TimeTravelScopeChange","line":94,"canonical":true,"symbol":"home.ts.code.projects.openhcs-shared-runtime-plumbing.external.ObjectState.src.objectstate.object_state_registry.TimeTravelScopeChange","bases":[],"resolved_bases":[]},{"file":"external/ObjectState/src/objectstate/object_state_registry.py","name":"TimeTravelStateDiff","line":109,"canonical":true,"symbol":"home.ts.code.projects.openhcs-shared-runtime-plumbing.external.ObjectState.src.objectstate.object_state_registry.TimeTravelStateDiff","bases":[],"resolved_bases":[]},{"file":"external/ObjectState/src/objectstate/object_state_registry.py","name":"TimeTravelChangeSet","line":133,"canonical":true,"symbol":"home.ts.code.projects.openhcs-shared-runtime-plumbing.external.ObjectState.src.objectstate.object_state_registry.TimeTravelChangeSet","bases":[],"resolved_bases":[]},{"file":"external/ObjectState/src/objectstate/object_state_registry.py","name":"DeferredFieldInvalidation","line":149,"canonical":true,"symbol":"home.ts.code.projects.openhcs-shared-runtime-plumbing.external.ObjectState.src.objectstate.object_state_registry.DeferredFieldInvalidation","bases":[],"resolved_bases":[]},{"file":"external/ObjectState/src/objectstate/object_state_registry.py","name":"ObjectStateRegistry","line":159,"canonical":true,"symbol":"home.ts.code.projects.openhcs-shared-runtime-plumbing.external.ObjectState.src.objectstate.object_state_registry.ObjectStateRegistry","bases":[],"resolved_bases":[]},{"file":"external/ObjectState/src/objectstate/lazy_factory.py","name":"GlobalConfigMeta","line":340,"canonical":true,"symbol":"home.ts.code.projects.openhcs-shared-runtime-plumbing.external.ObjectState.src.objectstate.lazy_factory.GlobalConfigMeta","bases":["type"],"resolved_bases":[]},{"file":"external/ObjectState/src/objectstate/lazy_factory.py","name":"GlobalConfigBase","line":352,"canonical":true,"symbol":"home.ts.code.projects.openhcs-shared-runtime-plumbing.external.ObjectState.src.objectstate.lazy_factory.GlobalConfigBase","bases":[],"resolved_bases":[]},{"file":"external/ObjectState/src/objectstate/lazy_factory.py","name":"LazyResolutionDataclass","line":368,"canonical":true,"symbol":"home.ts.code.projects.openhcs-shared-runtime-plumbing.external.ObjectState.src.objectstate.lazy_factory.LazyResolutionDataclass","bases":["ABC"],"resolved_bases":[]},{"file":"external/ObjectState/src/objectstate/lazy_factory.py","name":"LazyDataclass","line":372,"canonical":true,"symbol":"home.ts.code.projects.openhcs-shared-runtime-plumbing.external.ObjectState.src.objectstate.lazy_factory.LazyDataclass","bases":["LazyResolutionDataclass"],"resolved_bases":["home.ts.code.projects.openhcs-shared-runtime-plumbing.external.ObjectState.src.objectstate.lazy_factory.LazyResolutionDataclass"]},{"file":"external/ObjectState/src/objectstate/lazy_factory.py","name":"LazyMethodBindings","line":561,"canonical":true,"symbol":"home.ts.code.projects.openhcs-shared-runtime-plumbing.external.ObjectState.src.objectstate.lazy_factory.LazyMethodBindings","bases":[],"resolved_bases":[]},{"file":"external/ObjectState/src/objectstate/lazy_factory.py","name":"LazyDataclassFactory","line":795,"canonical":true,"symbol":"home.ts.code.projects.openhcs-shared-runtime-plumbing.external.ObjectState.src.objectstate.lazy_factory.LazyDataclassFactory","bases":[],"resolved_bases":[]},{"file":"external/ObjectState/src/objectstate/lazy_factory.py","name":"abbreviation","line":1336,"canonical":true,"symbol":"home.ts.code.projects.openhcs-shared-runtime-plumbing.external.ObjectState.src.objectstate.lazy_factory.abbreviation","bases":[],"resolved_bases":[]},{"file":"external/ObjectState/src/objectstate/global_config.py","name":"GlobalContextValues","line":53,"canonical":true,"symbol":"home.ts.code.projects.openhcs-shared-runtime-plumbing.external.ObjectState.src.objectstate.global_config.GlobalContextValues","bases":[],"resolved_bases":[]}],"calls":[{"file":"openhcs/core/pipeline/compiler.py","line":206,"owner":"AxisCompilationRequest.context_for","call":"self.orchestrator.create_context(axis_id)"},{"file":"openhcs/core/pipeline/compiler.py","line":373,"owner":"PipelineCompiler._configure_input_conversion_if_needed","call":"orchestrator.get_effective_config()"},{"file":"openhcs/core/pipeline/compiler.py","line":607,"owner":"PipelineCompiler.declare_zarr_stores","call":"orchestrator.get_effective_config()"},{"file":"openhcs/core/pipeline/compiler.py","line":1028,"owner":"PipelineCompiler._axis_values_to_process","call":"orchestrator.get_effective_config()"},{"file":"openhcs/core/pipeline/compiler.py","line":1197,"owner":"PipelineCompiler._replace_pipeline_with_resolved_steps","call":"step_state.to_saved_resolved_object()"},{"file":"openhcs/core/pipeline/compiler.py","line":1232,"owner":"PipelineCompiler._capture_pipeline_config","call":"pipeline_config_state.to_saved_resolved_object()"},{"file":"openhcs/core/pipeline/compiler.py","line":1246,"owner":"PipelineCompiler._resolve_global_step_axis_filters","call":"orchestrator.create_context('temp')"},{"file":"openhcs/core/pipeline/compiler.py","line":1749,"owner":"PipelineCompiler._finalize_compilation","call":"orchestrator.get_effective_config()"},{"file":"openhcs/core/pipeline/compiler.py","line":1860,"owner":"PipelineCompiler.compile_pipelines","call":"orchestrator.get_effective_config()"},{"file":"openhcs/core/pipeline/compiler.py","line":1890,"owner":"PipelineCompiler.compile_pipelines","call":"orchestrator.get_effective_config()"},{"file":"openhcs/core/pipeline/compiler.py","line":2052,"owner":"_resolve_step_axis_filters","call":"step_state.get_provenance(f'{field_name}.well_filter')"},{"file":"openhcs/core/orchestrator/orchestrator.py","line":204,"owner":"PipelineOrchestrator.__init__","call":"self.get_effective_config()"},{"file":"openhcs/core/orchestrator/orchestrator.py","line":319,"owner":"PipelineOrchestrator.initialize_microscope_handler","call":"self.get_effective_config()"},{"file":"openhcs/core/orchestrator/orchestrator.py","line":438,"owner":"PipelineOrchestrator.initialize","call":"self.get_effective_config()"},{"file":"openhcs/core/orchestrator/orchestrator.py","line":510,"owner":"PipelineOrchestrator._ensure_openhcs_metadata","call":"self.create_context(axis_id='metadata_init')"},{"file":"openhcs/core/orchestrator/orchestrator.py","line":541,"owner":"PipelineOrchestrator.get_results_path","call":"self.get_effective_config()"},{"file":"openhcs/core/orchestrator/orchestrator.py","line":569,"owner":"PipelineOrchestrator.create_context","call":"self.get_effective_config()"},{"file":"openhcs/core/orchestrator/orchestrator.py","line":961,"owner":"PipelineOrchestrator.apply_pipeline_config","call":"ObjectState(previous_config).to_saved_resolved_object()"},{"file":"openhcs/core/orchestrator/orchestrator.py","line":966,"owner":"PipelineOrchestrator.apply_pipeline_config","call":"ObjectState(pipeline_config).to_saved_resolved_object()"},{"file":"openhcs/core/orchestrator/orchestrator.py","line":1023,"owner":"PipelineOrchestrator.get_effective_config","call":"ObjectState(self.pipeline_config).to_saved_resolved_object()"}],"authority":"Existing NRA SourceModule/ModuleSyntaxIndex/build_class_family_index; no handwritten class/schema roster, no production imports or execution. Selected syntax/class binding refreshed against actual owned dependency sources; external family MRO/extension callback purity OPEN."} diff --git a/benchmark/results/perf_illum3_runtime_ledger_20261003/compiler-config-owner-decision.json b/benchmark/results/perf_illum3_runtime_ledger_20261003/compiler-config-owner-decision.json new file mode 100644 index 0000000000..ae49796286 --- /dev/null +++ b/benchmark/results/perf_illum3_runtime_ledger_20261003/compiler-config-owner-decision.json @@ -0,0 +1,122 @@ +{ + "status": "READ_ONLY; CONDITIONAL_POSTCAPTURE_ROUTE_UNQUALIFIED; NO_IMPLEMENTATION", + "source_head": "4c0d62e45c8afb85e34b69d7279cd00710f519b5", + "actual_dependency_heads": { + "ObjectState": "a01f8939b9bf4659502a33fe3febe62cab0f3c9a", + "python-introspect": "ed1e4eb15f7a0bf8315274d3e47858fa2b4372bb" + }, + "current_selected_NRA_class_census": "71 original/71 canonical classes in13 actual owned determining modules; whole731-module census remains historical. Only lazy_factory differs among selected modules from that original census. Unrefreshed external/MRO and future-head bindings OPEN.", + "diagnostic": { + "observations": "/home/ts/.local/state/openhcs-maintenance/20261003/illum3-compiler-runtime-ledger-v2/output/observations.json", + "sha256": "c8b1e3f0704682e2cad20b7a5e27b1651e38b677e74f31d6477eb163185106fd", + "regions": [ + { + "path": "/home/ts/.local/state/openhcs-maintenance/20261003/illum3-compiler-runtime-ledger-v2/output/regions/region-2078682-140361443509952-0001.json", + "sha256": "cc69523fdae5fe92c4e96ec59609a19eb889fe744316b6ed8419ed0398313ab9" + }, + { + "path": "/home/ts/.local/state/openhcs-maintenance/20261003/illum3-compiler-runtime-ledger-v2/output/regions/region-2078682-140361443509952-0002.json", + "sha256": "f3c9e01926b069a0103ebb9c70d638a4944c1f429b809b3a7b2e9755efbf80e5" + } + ], + "compile_root_seconds": 0.5882621230557561, + "ObjectState_disjoint_seconds": 0.3834735373966396, + "all10_getter_inclusive_seconds": 0.19238800555467606, + "counts": { + "PipelineCompiler.compile_pipelines": 1, + "PipelineCompiler._register_and_resolve_pipeline_once": 1, + "PipelineCompiler._capture_pipeline_config": 1, + "AxisCompilationRequest.context_for": 1, + "CompilationSession.from_context": 1, + "PipelineOrchestrator.create_context": 3, + "PipelineOrchestrator.get_effective_config": 10, + "ObjectState.__init__": 23, + "ObjectState._compute_resolved_snapshot": 46, + "ObjectState._reconstruct_from_resolved": 343, + "ObjectState.to_saved_resolved_object": 21 + }, + "execution_ObjectState_disjoint_seconds": 0.05523737985640764, + "attribution_law": "Owner aggregate only; no percall timing/source frames. Normal source path reconciles counts, not proof of individual event provenance or equal cost." + }, + "before_captured_pipeline_config": [ + { + "consumer": "orchestrator Zarr registry setup", + "source": "orchestrator.py:204" + }, + { + "consumer": "microscope initialization", + "source": "orchestrator.py:319" + }, + { + "consumer": "workspace VFS logging", + "source": "orchestrator.py:438" + }, + { + "consumer": "metadata_init context", + "source": "orchestrator.py:510 -> :569" + }, + { + "consumer": "axis selection", + "source": "compiler.py:1028" + } + ], + "after_captured_pipeline_config": [ + { + "consumer": "temp axis-filter context", + "source": "compiler.py:1246 -> orchestrator.py:569" + }, + { + "consumer": "actual axis context", + "source": "compiler.py:206 -> orchestrator.py:569" + }, + { + "consumer": "input-conversion VFS", + "source": "compiler.py:373" + }, + { + "consumer": "Zarr-declaration VFS", + "source": "compiler.py:607" + }, + { + "consumer": "final worker log after cleanup/stripping/COMPILED", + "source": "compiler.py:1749" + } + ], + "source_count_reconciliation": "Normal10-step1-axis path:13 registered compiler states(global,pipeline,delegated orchestrator,10steps)+10 ephemeral getters=23; two initial live/saved snapshots each=46. Three contexts are metadata_init/temp/axis. Arbitrary extension paths with coincident aggregate counts remain OPEN.", + "owners": [ + "ZMQExecutionContext.configs/OpenHCSExecutionConfigBundle retains decoded global_pipeline and authored lazy plate_pipeline. These are not a captured concrete merged effective config; passing either directly is wrong.", + "Server installs request global context and initializes orchestrator before registered compiler capture. Early reads can observe handler/default/validator callback epochs.", + "PipelineCompiler registers named saved hierarchy and resolves submitted steps once, retaining step ObjectStates for actual live inherited-field provenance.", + "_capture_pipeline_config produces saved concrete GlobalPipelineConfig. resolve_declared_dataclass_paths normalizes its paths; local effective_config then feeds AxisCompilationRequest.global_config and CompilationSession.global_config.", + "AxisCompilationRequest.context_for creates fresh context then overwrites captured policy/filters/analysis/plate fields. TIFF and auto-add are currently fresh. CompilationSession already owns captured VFS/runtime configuration." + ], + "strongest_existing_nominal_route": "A common PipelineOrchestrator context-construction algorithm can accept explicit existing captured compiler config while its public fresh context path stays current. Local effective_config supplies temp context before AxisCompilationRequest exists; AxisCompilationRequest/CompilationSession supply axis/VFS consumers. Finalization would need its same saved-source/late-validation law admitted separately. This is the previously conditional snapshot-owner route, not a new proved fast path/cache/wrapper.", + "counterexamples": [ + "Saved registered state has scoped ancestor sources; fresh getter creates scope-less state resolving current saved global context. Sharing authored object does not prove equal answers.", + "test_compiler_captures_scoped_worker_count changes global context after capture and proves captured worker count remains old. Fresh getter can instead read changed global values for TIFF/auto-add/VFS. Signature equality cannot prove same internal config epoch.", + "Handler get_component_keys/get_available_backends and extension planning callbacks can replace global/orchestrator config after capture. Changed source is rejected on future client submissions, but an internal callback may change effective values without changing request strings.", + "_reconstruct_from_resolved invokes real actual subtype constructors/validators every read. A later callback-only error is presently observable. Finalization cleans scopes, strips steps and sets COMPILED before its fresh getter; moving/removing it changes partial effects and first errors.", + "GlobalPipelineConfig and built-in TiffConfig are frozen; prior blanket mutable-TIFF claim is false. ProcessingContext attributes are independently replaceable. Mutable extension/container values, subtype behavior and constructor/error epochs still need controls.", + "_resolve_step_axis_filters still invokes step_state.get_provenance; live provenance is a production consumer. Unconditional live=saved collapse or deleting live snapshots remains invalid.", + "Captured config paths are normalized while fresh/early reads may preserve authored relative values. Do not silently substitute field authorities or add a synchronized field mirror." + ], + "signature_law": "Independent client compile and execution builder renders remain; mutated authored pipeline/config changes compilation_signature and reuse_artifact rejects mismatches. This protects external next-request epochs, not callback mutations inside a compile transaction.", + "maximum_payoff": { + "all10_getter_upper_envelope_seconds": 0.19238800555467606, + "eligible5_postcapture_seconds": "UNKNOWN; no average division or nested-clock sums permitted.", + "entire_family_upper_envelope_seconds": 0.3834735373966396, + "mandatory_in_entire_family": "Registered hierarchy+saved resolution+live provenance+value validation+early initialization. Not a removable cost.", + "Illum3_total_2x_gap_seconds": 1.22610824, + "all10_getter_fraction_of_total_gap": 0.15690947934146177, + "execution_gain_claim": 0, + "decision": "No current qualified route materially removes the0.383s family. Five-read capture migration cannot claim0.192s either. Do not polish: source-law/control qualification and same-phase eligible timing would be necessary before whole compiler prototype." + }, + "custody": { + "production_edits": false, + "OpenHCS_or_dependency_runtime_imports": false, + "config_replays_or_scientific_runs": false, + "new_environment_checkout_capture": false, + "original_artifacts_copied": false, + "only_NRA_static_indexes_executed": true + } +} diff --git a/benchmark/results/perf_illum3_runtime_ledger_20261003/controls.json b/benchmark/results/perf_illum3_runtime_ledger_20261003/controls.json new file mode 100644 index 0000000000..a25727674b --- /dev/null +++ b/benchmark/results/perf_illum3_runtime_ledger_20261003/controls.json @@ -0,0 +1,37 @@ +{ + "status": "PASS", + "controls": [ + "original_called_once", + "argument_mutation_and_result_identity", + "signature_wrapped_code", + "nested_exclusive_conservation", + "error_identity_and_mutation", + "finally_restores_nested_state", + "root_namespace_no_overwrite", + "outside_root_ready_passthrough", + "fork_tls_reset", + "source_loader_real_declaring_path", + "instance_descriptor", + "classmethod_descriptor", + "staticmethod_descriptor", + "source_hash_drift_refusal", + "native_listener_startup_events", + "no_signature_repr_or_str", + "native_error_and_mutation_identity", + "timed_root_start_end_classification", + "between_roots_separate_from_startup", + "bounded_refusal_preserves_counts_and_red", + "other_thread_active_root_join", + "root_end_flush_without_atexit", + "no_repeated_or_discarded_event_prefix", + "cumulative_counts_survive_flush", + "flush_namespace_and_serialized_cap", + "no_native_receiver_or_argument_retention", + "installed_event_loader_original_module_then_listener", + "unchanged_storage_caps_and_41_hook_roster" + ], + "count": 28, + "site_sha256": "1a30063decce3e67ef2e0f3c033fb4f4cb9e6acf7e4c2b43b114c433f62c1bbe", + "controller_sha256": "e00e1cb2e195842f780ed289e97700db9fd52d7046414079fb186f90a7f98df5", + "scope": "Temporary test-owned source only, original result/error/mutation and descriptor/path/hash laws; no candidate pipeline import, compile, execution, profiler, snapshot or processing callback invocation." +} diff --git a/benchmark/results/perf_illum3_runtime_ledger_20261003/execution-region.json b/benchmark/results/perf_illum3_runtime_ledger_20261003/execution-region.json new file mode 100644 index 0000000000..c8f4dcb7b3 --- /dev/null +++ b/benchmark/results/perf_illum3_runtime_ledger_20261003/execution-region.json @@ -0,0 +1,630 @@ +{ + "pid": 2078682, + "thread": 140361443509952, + "region": "ZMQExecutionServer._execute_with_orchestrator", + "root_dimensions": "{\"case\": \"ExampleIlluminationCorrection_Example3\", \"compile_artifact_id\": \"78250d97-e324-4dbd-a014-62f28444b8a3\", \"execution_id\": \"6df21ea1-70f5-4fa0-9fac-ef5e7963204d\", \"kind\": \"execution\", \"plate\": \"/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images\"}", + "seconds": 0.4150526160374284, + "revision": "4c0d62e45c8afb85e34b69d7279cd00710f519b5", + "source": "/home/ts/code/projects/openhcs-shared-runtime-plumbing", + "stats": { + "ObjectState._compute_resolved_snapshot": { + "owner": "ObjectState._compute_resolved_snapshot", + "dimensions": "", + "phase": "compiler_config:_compute_resolved_snapshot", + "calls": 8, + "inclusive": 0.038815660402178764, + "exclusive": 0.038815660402178764 + }, + "ObjectState.__init__": { + "owner": "ObjectState.__init__", + "dimensions": "", + "phase": "compiler_config:__init__", + "calls": 4, + "inclusive": 0.0482184044085443, + "exclusive": 0.009402744006365538 + }, + "ObjectState._reconstruct_from_resolved": { + "owner": "ObjectState._reconstruct_from_resolved", + "dimensions": "", + "phase": "compiler_config:_reconstruct_from_resolved", + "calls": 92, + "inclusive": 0.013413879089057446, + "exclusive": 0.0070056007243692875 + }, + "ObjectState.to_saved_resolved_object": { + "owner": "ObjectState.to_saved_resolved_object", + "dimensions": "", + "phase": "compiler_config:to_saved_resolved_object", + "calls": 4, + "inclusive": 0.00701897544786334, + "exclusive": 1.3374723494052887e-05 + }, + "PipelineOrchestrator.get_effective_config": { + "owner": "PipelineOrchestrator.get_effective_config", + "dimensions": "", + "phase": "compiler_config:get_effective_config", + "calls": 4, + "inclusive": 0.055267936550080776, + "exclusive": 3.055669367313385e-05 + }, + "PipelineOrchestrator.create_context": { + "owner": "PipelineOrchestrator.create_context", + "dimensions": "", + "phase": "compiler_config:create_context", + "calls": 1, + "inclusive": 0.01351372292265296, + "exclusive": 6.313808262348175e-05 + }, + "ZMQExecutionServer._initialize_orchestrator": { + "owner": "ZMQExecutionServer._initialize_orchestrator", + "dimensions": "", + "phase": "_initialize_orchestrator", + "calls": 1, + "inclusive": 0.0607714201323688, + "exclusive": 0.005440345499664545 + }, + "RuntimeImageStackCache.get": { + "owner": "RuntimeImageStackCache.get", + "dimensions": "", + "phase": "get", + "calls": 10, + "inclusive": 4.8863235861063004e-05, + "exclusive": 4.8863235861063004e-05 + }, + "stack_image_payload_context": { + "owner": "stack_image_payload_context", + "dimensions": "", + "phase": "stack_image_payload_context", + "calls": 10, + "inclusive": 0.0036861514672636986, + "exclusive": 0.0036861514672636986 + }, + "PatternGroupRuntime._load_input_stack": { + "owner": "PatternGroupRuntime._load_input_stack", + "dimensions": "", + "phase": "_load_input_stack", + "calls": 10, + "inclusive": 0.023979938589036465, + "exclusive": 0.021657294128090143 + }, + "CellProfilerModuleExecutor._image_request": { + "owner": "CellProfilerModuleExecutor._image_request", + "dimensions": "", + "phase": "_image_request", + "calls": 9, + "inclusive": 0.006721616256982088, + "exclusive": 0.006721616256982088 + }, + "RuntimeCallableInvocation.call | function=openhcs.processing.backends.cellprofiler.primary_objects.identify_primary_objects;view=1": { + "owner": "RuntimeCallableInvocation.call", + "dimensions": "function=openhcs.processing.backends.cellprofiler.primary_objects.identify_primary_objects;view=1", + "phase": "declared_callable_boundary", + "calls": 1, + "inclusive": 0.02976729581132531, + "exclusive": 0.02976729581132531 + }, + "CellProfilerFunctionContractExecutor.execute | function=openhcs.processing.backends.cellprofiler.primary_objects.identify_primary_objects": { + "owner": "CellProfilerFunctionContractExecutor.execute", + "dimensions": "function=openhcs.processing.backends.cellprofiler.primary_objects.identify_primary_objects", + "phase": "execute", + "calls": 1, + "inclusive": 0.03761508176103234, + "exclusive": 0.007847785949707031 + }, + "CellProfilerOutputRecorder.record_module_outputs": { + "owner": "CellProfilerOutputRecorder.record_module_outputs", + "dimensions": "", + "phase": "record_module_outputs", + "calls": 9, + "inclusive": 0.04083343083038926, + "exclusive": 0.04083343083038926 + }, + "CellProfilerModuleExecutor.__call__": { + "owner": "CellProfilerModuleExecutor.__call__", + "dimensions": "", + "phase": "__call__", + "calls": 9, + "inclusive": 0.19400596152991056, + "exclusive": 0.01576411724090576 + }, + "FunctionCoreExecutor.execute | function=identify_primary_objects": { + "owner": "FunctionCoreExecutor.execute", + "dimensions": "function=identify_primary_objects", + "phase": "execute", + "calls": 1, + "inclusive": 0.06343830097466707, + "exclusive": 0.0014636460691690445 + }, + "PatternGroupRuntime._validate_and_unstack": { + "owner": "PatternGroupRuntime._validate_and_unstack", + "dimensions": "", + "phase": "_validate_and_unstack", + "calls": 10, + "inclusive": 0.003616310190409422, + "exclusive": 0.002203939948230982 + }, + "RuntimeImageStackCache.store": { + "owner": "RuntimeImageStackCache.store", + "dimensions": "", + "phase": "store", + "calls": 10, + "inclusive": 5.160598084330559e-05, + "exclusive": 5.160598084330559e-05 + }, + "PatternGroupRuntime._save_outputs": { + "owner": "PatternGroupRuntime._save_outputs", + "dimensions": "", + "phase": "_save_outputs", + "calls": 10, + "inclusive": 0.007888393010944128, + "exclusive": 0.007836787030100822 + }, + "finalize_function_step_outputs": { + "owner": "finalize_function_step_outputs", + "dimensions": "", + "phase": "finalize_function_step_outputs", + "calls": 10, + "inclusive": 0.033279507886618376, + "exclusive": 0.025323559064418077 + }, + "RuntimeCallableInvocation.call | function=openhcs.processing.backends.cellprofiler.morphology.expand_or_shrink_objects;view=1": { + "owner": "RuntimeCallableInvocation.call", + "dimensions": "function=openhcs.processing.backends.cellprofiler.morphology.expand_or_shrink_objects;view=1", + "phase": "declared_callable_boundary", + "calls": 1, + "inclusive": 0.02096757711842656, + "exclusive": 0.02096757711842656 + }, + "CellProfilerFunctionContractExecutor.execute | function=openhcs.processing.backends.cellprofiler.morphology.expand_or_shrink_objects": { + "owner": "CellProfilerFunctionContractExecutor.execute", + "dimensions": "function=openhcs.processing.backends.cellprofiler.morphology.expand_or_shrink_objects", + "phase": "execute", + "calls": 1, + "inclusive": 0.022361161187291145, + "exclusive": 0.001393584068864584 + }, + "FunctionCoreExecutor.execute | function=expand_or_shrink_objects": { + "owner": "FunctionCoreExecutor.execute", + "dimensions": "function=expand_or_shrink_objects", + "phase": "execute", + "calls": 1, + "inclusive": 0.030518849845975637, + "exclusive": 0.0009220358915627003 + }, + "RuntimeCallableInvocation.call | function=openhcs.processing.backends.cellprofiler.image_math.image_math;view=1": { + "owner": "RuntimeCallableInvocation.call", + "dimensions": "function=openhcs.processing.backends.cellprofiler.image_math.image_math;view=1", + "phase": "declared_callable_boundary", + "calls": 1, + "inclusive": 0.001754844095557928, + "exclusive": 0.001754844095557928 + }, + "CellProfilerFunctionContractExecutor.execute | function=openhcs.processing.backends.cellprofiler.image_math.image_math": { + "owner": "CellProfilerFunctionContractExecutor.execute", + "dimensions": "function=openhcs.processing.backends.cellprofiler.image_math.image_math", + "phase": "execute", + "calls": 1, + "inclusive": 0.005336186848580837, + "exclusive": 0.003581342753022909 + }, + "FunctionCoreExecutor.execute | function=image_math": { + "owner": "FunctionCoreExecutor.execute", + "dimensions": "function=image_math", + "phase": "execute", + "calls": 1, + "inclusive": 0.011326035019010305, + "exclusive": 0.0001370580866932869 + }, + "RuntimeCallableInvocation.call | function=openhcs.processing.backends.cellprofiler.image_geometry.mask_image;view=1": { + "owner": "RuntimeCallableInvocation.call", + "dimensions": "function=openhcs.processing.backends.cellprofiler.image_geometry.mask_image;view=1", + "phase": "declared_callable_boundary", + "calls": 2, + "inclusive": 0.0009737634100019932, + "exclusive": 0.0009737634100019932 + }, + "CellProfilerFunctionContractExecutor.execute | function=openhcs.processing.backends.cellprofiler.image_geometry.mask_image": { + "owner": "CellProfilerFunctionContractExecutor.execute", + "dimensions": "function=openhcs.processing.backends.cellprofiler.image_geometry.mask_image", + "phase": "execute", + "calls": 2, + "inclusive": 0.002802106086164713, + "exclusive": 0.0018283426761627197 + }, + "FunctionCoreExecutor.execute | function=mask_image": { + "owner": "FunctionCoreExecutor.execute", + "dimensions": "function=mask_image", + "phase": "execute", + "calls": 2, + "inclusive": 0.010034974198788404, + "exclusive": 0.00037863291800022125 + }, + "RuntimeCallableInvocation.call | function=openhcs.processing.backends.cellprofiler.illumination.correct_illumination_calculate;view=1": { + "owner": "RuntimeCallableInvocation.call", + "dimensions": "function=openhcs.processing.backends.cellprofiler.illumination.correct_illumination_calculate;view=1", + "phase": "declared_callable_boundary", + "calls": 2, + "inclusive": 0.05728212045505643, + "exclusive": 0.05728212045505643 + }, + "CellProfilerFunctionContractExecutor.execute | function=openhcs.processing.backends.cellprofiler.illumination.correct_illumination_calculate": { + "owner": "CellProfilerFunctionContractExecutor.execute", + "dimensions": "function=openhcs.processing.backends.cellprofiler.illumination.correct_illumination_calculate", + "phase": "execute", + "calls": 2, + "inclusive": 0.05979563295841217, + "exclusive": 0.0025135125033557415 + }, + "FunctionCoreExecutor.execute | function=correct_illumination_calculate": { + "owner": "FunctionCoreExecutor.execute", + "dimensions": "function=correct_illumination_calculate", + "phase": "execute", + "calls": 2, + "inclusive": 0.07384366216138005, + "exclusive": 0.002233616542071104 + }, + "RuntimeCallableInvocation.call | function=openhcs.processing.backends.cellprofiler.illumination.correct_illumination_apply;view=1": { + "owner": "RuntimeCallableInvocation.call", + "dimensions": "function=openhcs.processing.backends.cellprofiler.illumination.correct_illumination_apply;view=1", + "phase": "declared_callable_boundary", + "calls": 2, + "inclusive": 0.0008326279930770397, + "exclusive": 0.0008326279930770397 + }, + "CellProfilerFunctionContractExecutor.execute | function=openhcs.processing.backends.cellprofiler.illumination.correct_illumination_apply": { + "owner": "CellProfilerFunctionContractExecutor.execute", + "dimensions": "function=openhcs.processing.backends.cellprofiler.illumination.correct_illumination_apply", + "phase": "execute", + "calls": 2, + "inclusive": 0.0027766283601522446, + "exclusive": 0.0019440003670752048 + }, + "FunctionCoreExecutor.execute | function=correct_illumination_apply": { + "owner": "FunctionCoreExecutor.execute", + "dimensions": "function=correct_illumination_apply", + "phase": "execute", + "calls": 2, + "inclusive": 0.012327289674431086, + "exclusive": 0.0023481608368456364 + }, + "RuntimeCallableInvocation.call | function=openhcs.processing.backends.cellprofiler.save_images.save_images;view=1": { + "owner": "RuntimeCallableInvocation.call", + "dimensions": "function=openhcs.processing.backends.cellprofiler.save_images.save_images;view=1", + "phase": "declared_callable_boundary", + "calls": 2, + "inclusive": 0.00016149505972862244, + "exclusive": 0.00016149505972862244 + }, + "FunctionCoreExecutor.execute | function=save_images": { + "owner": "FunctionCoreExecutor.execute", + "dimensions": "function=save_images", + "phase": "execute", + "calls": 2, + "inclusive": 0.005585906561464071, + "exclusive": 0.005424411501735449 + }, + "AtomicMetadataWriter.publish_source_projection_metadata": { + "owner": "AtomicMetadataWriter.publish_source_projection_metadata", + "dimensions": "", + "phase": "publish_source_projection_metadata", + "calls": 2, + "inclusive": 0.017186708748340607, + "exclusive": 0.017186708748340607 + }, + "execute_worker_lane | {\"execution_id\": \"6df21ea1-70f5-4fa0-9fac-ef5e7963204d\", \"kind\": \"worker_lane\", \"plate\": \"/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images\", \"worker_slot\": \"worker_0\"}": { + "owner": "execute_worker_lane", + "dimensions": "{\"execution_id\": \"6df21ea1-70f5-4fa0-9fac-ef5e7963204d\", \"kind\": \"worker_lane\", \"plate\": \"/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images\", \"worker_slot\": \"worker_0\"}", + "phase": "execute_worker_lane", + "calls": 1, + "inclusive": 0.2973959231749177, + "exclusive": 0.02155675506219268 + }, + "consolidate_analysis_outputs": { + "owner": "consolidate_analysis_outputs", + "dimensions": "", + "phase": "consolidate_analysis_outputs", + "calls": 1, + "inclusive": 7.935333997011185e-06, + "exclusive": 7.935333997011185e-06 + }, + "RuntimeArtifactMetadataTarget.reconciliation_targets": { + "owner": "RuntimeArtifactMetadataTarget.reconciliation_targets", + "dimensions": "", + "phase": "reconciliation_targets", + "calls": 1, + "inclusive": 0.021559111773967743, + "exclusive": 0.021559111773967743 + }, + "OpenHCSMetadataWriter.finalize_completed_plate": { + "owner": "OpenHCSMetadataWriter.finalize_completed_plate", + "dimensions": "", + "phase": "finalize_completed_plate", + "calls": 1, + "inclusive": 0.031200694851577282, + "exclusive": 0.00041082315146923065 + }, + "ZMQExecutionServer._export_runtime_observation": { + "owner": "ZMQExecutionServer._export_runtime_observation", + "dimensions": "", + "phase": "_export_runtime_observation", + "calls": 1, + "inclusive": 0.004840843845158815, + "exclusive": 0.004840843845158815 + }, + "ZMQExecutionServer._execute_with_orchestrator | {\"case\": \"ExampleIlluminationCorrection_Example3\", \"compile_artifact_id\": \"78250d97-e324-4dbd-a014-62f28444b8a3\", \"execution_id\": \"6df21ea1-70f5-4fa0-9fac-ef5e7963204d\", \"kind\": \"execution\", \"plate\": \"/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images\"}": { + "owner": "ZMQExecutionServer._execute_with_orchestrator", + "dimensions": "{\"case\": \"ExampleIlluminationCorrection_Example3\", \"compile_artifact_id\": \"78250d97-e324-4dbd-a014-62f28444b8a3\", \"execution_id\": \"6df21ea1-70f5-4fa0-9fac-ef5e7963204d\", \"kind\": \"execution\", \"plate\": \"/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images\"}", + "phase": "_execute_with_orchestrator", + "calls": 1, + "inclusive": 0.4150526160374284, + "exclusive": 0.02083579869940877 + } + }, + "hooks_installed": [ + { + "module": "objectstate.object_state", + "owner": "ObjectState", + "method": "__init__", + "descriptor_kind": "function" + }, + { + "module": "objectstate.object_state", + "owner": "ObjectState", + "method": "_compute_resolved_snapshot", + "descriptor_kind": "function" + }, + { + "module": "objectstate.object_state", + "owner": "ObjectState", + "method": "_reconstruct_from_resolved", + "descriptor_kind": "function" + }, + { + "module": "objectstate.object_state", + "owner": "ObjectState", + "method": "to_saved_resolved_object", + "descriptor_kind": "function" + }, + { + "module": "openhcs.core.aligned_image_payload", + "owner": "", + "method": "stack_image_payload_context", + "descriptor_kind": "function" + }, + { + "module": "openhcs.core.aligned_image_payload", + "owner": "", + "method": "unstack_image_payload_context", + "descriptor_kind": "function" + }, + { + "module": "openhcs.core.measurement_feature_queries", + "owner": "MeasurementFeatureValueIndex", + "method": "from_columnar_table_by_object", + "descriptor_kind": "classmethod" + }, + { + "module": "openhcs.core.virtual_workspace_metadata", + "owner": "AtomicMetadataWriter", + "method": "publish_source_projection_metadata", + "descriptor_kind": "function" + }, + { + "module": "openhcs.core.runtime_stack_cache", + "owner": "RuntimeImageStackCache", + "method": "get", + "descriptor_kind": "function" + }, + { + "module": "openhcs.core.runtime_stack_cache", + "owner": "RuntimeImageStackCache", + "method": "store", + "descriptor_kind": "function" + }, + { + "module": "openhcs.core.steps.function_outputs", + "owner": "", + "method": "finalize_function_step_outputs", + "descriptor_kind": "function" + }, + { + "module": "openhcs.core.steps.function_outputs", + "owner": "OpenHCSMetadataWriter", + "method": "finalize_completed_plate", + "descriptor_kind": "classmethod" + }, + { + "module": "openhcs.core.steps.function_outputs", + "owner": "RuntimeArtifactMetadataTarget", + "method": "reconciliation_targets", + "descriptor_kind": "function" + }, + { + "module": "openhcs.core.steps.function_runtime", + "owner": "FunctionCoreExecutor", + "method": "execute", + "descriptor_kind": "function" + }, + { + "module": "openhcs.core.steps.function_runtime", + "owner": "PatternGroupRuntime", + "method": "_load_input_stack", + "descriptor_kind": "function" + }, + { + "module": "openhcs.core.steps.function_runtime", + "owner": "PatternGroupRuntime", + "method": "_validate_and_unstack", + "descriptor_kind": "function" + }, + { + "module": "openhcs.core.steps.function_runtime", + "owner": "PatternGroupRuntime", + "method": "_save_outputs", + "descriptor_kind": "function" + }, + { + "module": "openhcs.core.pipeline.compilation_session", + "owner": "CompilationSession", + "method": "from_context", + "descriptor_kind": "classmethod" + }, + { + "module": "openhcs.core.pipeline.compiler", + "owner": "PipelineCompiler", + "method": "compile_pipelines", + "descriptor_kind": "staticmethod" + }, + { + "module": "openhcs.core.pipeline.compiler", + "owner": "PipelineCompiler", + "method": "_register_and_resolve_pipeline_once", + "descriptor_kind": "staticmethod" + }, + { + "module": "openhcs.core.pipeline.compiler", + "owner": "PipelineCompiler", + "method": "initialize_step_plans_for_context", + "descriptor_kind": "staticmethod" + }, + { + "module": "openhcs.core.pipeline.compiler", + "owner": "PipelineCompiler", + "method": "_capture_pipeline_config", + "descriptor_kind": "staticmethod" + }, + { + "module": "openhcs.core.pipeline.compiler", + "owner": "PipelineCompiler", + "method": "_resolve_global_step_axis_filters", + "descriptor_kind": "staticmethod" + }, + { + "module": "openhcs.core.pipeline.compiler", + "owner": "PipelineCompiler", + "method": "_configure_input_conversion_if_needed", + "descriptor_kind": "staticmethod" + }, + { + "module": "openhcs.core.pipeline.compiler", + "owner": "PipelineCompiler", + "method": "declare_zarr_stores", + "descriptor_kind": "staticmethod" + }, + { + "module": "openhcs.core.pipeline.compiler", + "owner": "PipelineCompiler", + "method": "_finalize_compilation", + "descriptor_kind": "staticmethod" + }, + { + "module": "openhcs.core.pipeline.compiler", + "owner": "PipelineCompiler", + "method": "_axis_values_to_process", + "descriptor_kind": "staticmethod" + }, + { + "module": "openhcs.core.pipeline.compiler", + "owner": "AxisCompilationRequest", + "method": "context_for", + "descriptor_kind": "function" + }, + { + "module": "openhcs.processing.backends.lib_registry.unified_registry", + "owner": "RuntimeCallableInvocation", + "method": "call", + "descriptor_kind": "function" + }, + { + "module": "openhcs.core.orchestrator.analysis_consolidation", + "owner": "", + "method": "consolidate_analysis_outputs", + "descriptor_kind": "function" + }, + { + "module": "openhcs.core.orchestrator.worker_execution", + "owner": "", + "method": "execute_worker_lane", + "descriptor_kind": "function" + }, + { + "module": "openhcs.core.orchestrator.orchestrator", + "owner": "PipelineOrchestrator", + "method": "create_context", + "descriptor_kind": "function" + }, + { + "module": "openhcs.core.orchestrator.orchestrator", + "owner": "PipelineOrchestrator", + "method": "get_effective_config", + "descriptor_kind": "function" + }, + { + "module": "openhcs.runtime.zmq_execution_server", + "owner": "ZMQExecutionServer", + "method": "_execute_with_orchestrator", + "descriptor_kind": "function" + }, + { + "module": "openhcs.runtime.zmq_execution_server", + "owner": "ZMQExecutionServer", + "method": "_initialize_orchestrator", + "descriptor_kind": "function" + }, + { + "module": "openhcs.runtime.zmq_execution_server", + "owner": "ZMQExecutionServer", + "method": "_export_runtime_observation", + "descriptor_kind": "function" + }, + { + "module": "openhcs.interop.cellprofiler.runtime.function_contract_execution", + "owner": "CellProfilerFunctionContractExecutor", + "method": "execute", + "descriptor_kind": "function" + }, + { + "module": "openhcs.interop.cellprofiler.runtime.measurement_execution_support", + "owner": "ObjectMeasurementOutputRecorder", + "method": "record", + "descriptor_kind": "function" + }, + { + "module": "openhcs.interop.cellprofiler.runtime.output_recording", + "owner": "CellProfilerOutputRecorder", + "method": "record_module_outputs", + "descriptor_kind": "classmethod" + }, + { + "module": "openhcs.interop.cellprofiler.runtime.module_execution", + "owner": "CellProfilerModuleExecutor", + "method": "__call__", + "descriptor_kind": "function" + }, + { + "module": "openhcs.interop.cellprofiler.runtime.module_execution", + "owner": "CellProfilerModuleExecutor", + "method": "_image_request", + "descriptor_kind": "function" + } + ], + "profiling_enabled": false, + "runtime_profiling_enabled": false, + "diagnostic_errors": [], + "captures": false, + "root_started_monotonic_ns": 3816283657684912, + "root_ended_monotonic_ns": 3816284072767004, + "numba_events": { + "installed": true, + "counts": {}, + "record_count": 0, + "pending_record_count": 0, + "flushed_record_count": 0, + "refused_records": 0, + "errors": [], + "error_count": 0, + "record_bytes": 0, + "cap": 262144 + }, + "scope": "coarse same-run nested exclusive timing partition on the exact source revision recorded in this region. Diagnostic wrappers, no scientific or memory-observer substitutions. Not accepted performance comparison. Declared callable boundary includes filtering/decorated processing/metadata; not pure numerical kernels. Both existing profilers are disabled. These wrappers still add diagnostic overhead; no scaling to uninstrumented clocks or causal performance claims. Compiler/state boundaries and query boundary are nested under actual parents and excluded from parent-exclusive elapsed. This is a NEW 41-hook diagnostic version; inherited 24 boundary labels remain, site bytes are changed. ObjectState is verified against the actual source dependency path, not assumed inside the OpenHCS package." +} diff --git a/benchmark/results/perf_illum3_runtime_ledger_20261003/numba-events-1.json b/benchmark/results/perf_illum3_runtime_ledger_20261003/numba-events-1.json new file mode 100644 index 0000000000..ad31fc24db --- /dev/null +++ b/benchmark/results/perf_illum3_runtime_ledger_20261003/numba-events-1.json @@ -0,0 +1 @@ +{"installed":true,"counts":{},"record_count":0,"pending_record_count":0,"flushed_record_count":0,"refused_records":0,"errors":[],"error_count":0,"record_bytes":0,"cap":262144,"pid":2078555,"records":[],"complete":true,"scope":"Passive original numba:compile START/END events; startup before first root, same-thread timed kind, other active root IDs, outside-root events separately retained. No dispatcher/data/signature references or repr/str callbacks. Compile events do not include cache loads that emit no native compile event; no policy/warmup change. Durations remain original 41-hook intervals, not listener-generated benchmark clocks.","flush_boundary":{"kind":"atexit_supplementary"},"flush_sequence":1} diff --git a/benchmark/results/perf_illum3_runtime_ledger_20261003/numba-events-2.json b/benchmark/results/perf_illum3_runtime_ledger_20261003/numba-events-2.json new file mode 100644 index 0000000000..c3ef477413 --- /dev/null +++ b/benchmark/results/perf_illum3_runtime_ledger_20261003/numba-events-2.json @@ -0,0 +1 @@ +{"installed":true,"counts":{},"record_count":0,"pending_record_count":0,"flushed_record_count":0,"refused_records":0,"errors":[],"error_count":0,"record_bytes":0,"cap":262144,"pid":2078682,"records":[],"complete":true,"scope":"Passive original numba:compile START/END events; startup before first root, same-thread timed kind, other active root IDs, outside-root events separately retained. No dispatcher/data/signature references or repr/str callbacks. Compile events do not include cache loads that emit no native compile event; no policy/warmup change. Durations remain original 41-hook intervals, not listener-generated benchmark clocks.","flush_boundary":{"kind":"compile_only","root_thread_id":140361443509952,"root_sequence":1,"root_started_monotonic_ns":3816282952668134,"root_ended_monotonic_ns":3816283540961927},"flush_sequence":1} diff --git a/benchmark/results/perf_illum3_runtime_ledger_20261003/numba-events-3.json b/benchmark/results/perf_illum3_runtime_ledger_20261003/numba-events-3.json new file mode 100644 index 0000000000..23c35fb55a --- /dev/null +++ b/benchmark/results/perf_illum3_runtime_ledger_20261003/numba-events-3.json @@ -0,0 +1 @@ +{"installed":true,"counts":{},"record_count":0,"pending_record_count":0,"flushed_record_count":0,"refused_records":0,"errors":[],"error_count":0,"record_bytes":0,"cap":262144,"pid":2078682,"records":[],"complete":true,"scope":"Passive original numba:compile START/END events; startup before first root, same-thread timed kind, other active root IDs, outside-root events separately retained. No dispatcher/data/signature references or repr/str callbacks. Compile events do not include cache loads that emit no native compile event; no policy/warmup change. Durations remain original 41-hook intervals, not listener-generated benchmark clocks.","flush_boundary":{"kind":"execution","root_thread_id":140361443509952,"root_sequence":2,"root_started_monotonic_ns":3816283657684912,"root_ended_monotonic_ns":3816284072767004},"flush_sequence":2} diff --git a/benchmark/results/perf_illum3_runtime_ledger_20261003/numba-events-4.json b/benchmark/results/perf_illum3_runtime_ledger_20261003/numba-events-4.json new file mode 100644 index 0000000000..607b666767 --- /dev/null +++ b/benchmark/results/perf_illum3_runtime_ledger_20261003/numba-events-4.json @@ -0,0 +1 @@ +{"installed":true,"counts":{},"record_count":0,"pending_record_count":0,"flushed_record_count":0,"refused_records":0,"errors":[],"error_count":0,"record_bytes":0,"cap":262144,"pid":2078682,"records":[],"complete":true,"scope":"Passive original numba:compile START/END events; startup before first root, same-thread timed kind, other active root IDs, outside-root events separately retained. No dispatcher/data/signature references or repr/str callbacks. Compile events do not include cache loads that emit no native compile event; no policy/warmup change. Durations remain original 41-hook intervals, not listener-generated benchmark clocks.","flush_boundary":{"kind":"atexit_supplementary"},"flush_sequence":3} diff --git a/benchmark/results/perf_illum3_runtime_ledger_20261003/observations.json b/benchmark/results/perf_illum3_runtime_ledger_20261003/observations.json new file mode 100644 index 0000000000..32d102b1f2 --- /dev/null +++ b/benchmark/results/perf_illum3_runtime_ledger_20261003/observations.json @@ -0,0 +1,93 @@ +{ + "returncode": 0, + "diagnostic_admission": true, + "public_rows": [ + { + "case_name": "ExampleIlluminationCorrection_Example3", + "mode_name": "1w_1t", + "worker_count": "1", + "well_count": "1", + "compile_seconds": "0.5973687171936035", + "prepare_seconds": "0.0", + "execute_seconds": "0.42289090156555176", + "total_seconds": "1.419051312841475", + "wells_per_second": "2.3646760814620915", + "successful_wells": "1", + "native_single_sample_execution_seconds": "", + "projected_native_execution_seconds": "", + "projected_execution_speedup": "", + "peak_memory_mb": "1007.28515625", + "status": "success", + "memory_limit_mb": "", + "error_message": "", + "execution_route": "ordinary-zmq-outcomes-v1", + "server_lifecycle": "reused-per-sweep", + "run_input_sha256": "53cbf79d64350e46b2692cfd3b96a8bb1be943d75193a52d3fb5a2f98cfa91df" + } + ], + "regions": [ + { + "path": "/home/ts/.local/state/openhcs-maintenance/20261003/illum3-compiler-runtime-ledger-v2/output/regions/region-2078682-140361443509952-0001.json", + "sha256": "cc69523fdae5fe92c4e96ec59609a19eb889fe744316b6ed8419ed0398313ab9" + }, + { + "path": "/home/ts/.local/state/openhcs-maintenance/20261003/illum3-compiler-runtime-ledger-v2/output/regions/region-2078682-140361443509952-0002.json", + "sha256": "f3c9e01926b069a0103ebb9c70d638a4944c1f429b809b3a7b2e9755efbf80e5" + } + ], + "numba_event_admission": true, + "numba_root_flushes_complete": true, + "numba_event_total_bytes": 3107, + "numba_event_aggregate_cap": 262144, + "numba_event_files": [ + { + "path": "/home/ts/.local/state/openhcs-maintenance/20261003/illum3-compiler-runtime-ledger-v2/output/regions/numba-events-2078555-0001.json", + "sha256": "df39cc4538c692418c9590759ee2be67c03e712d31b38e59909a2acc414299da", + "counts": {}, + "complete": true + }, + { + "path": "/home/ts/.local/state/openhcs-maintenance/20261003/illum3-compiler-runtime-ledger-v2/output/regions/numba-events-2078682-0001.json", + "sha256": "0cc87c64a35b572441cac162e7a953685af095892641222cef4b52a71d7ace03", + "counts": {}, + "complete": true + }, + { + "path": "/home/ts/.local/state/openhcs-maintenance/20261003/illum3-compiler-runtime-ledger-v2/output/regions/numba-events-2078682-0002.json", + "sha256": "a80829256ff2e4f13f8cb14257b45138aacefb6e2726339b64be55d585c90fde", + "counts": {}, + "complete": true + }, + { + "path": "/home/ts/.local/state/openhcs-maintenance/20261003/illum3-compiler-runtime-ledger-v2/output/regions/numba-events-2078682-0003.json", + "sha256": "c615a8d1c29b5da41bba3237cd1ee02e6f8eba72af2f73290f11ec684571661b", + "counts": {}, + "complete": true + } + ], + "root_sequence_complete": true, + "actual_index_calls": 0, + "actual_declared_calls": 11, + "compile_only_actual_calls": { + "PipelineCompiler.compile_pipelines": 1, + "PipelineCompiler._register_and_resolve_pipeline_once": 1, + "PipelineCompiler._capture_pipeline_config": 1, + "AxisCompilationRequest.context_for": 1, + "CompilationSession.from_context": 1, + "PipelineOrchestrator.create_context": 3, + "PipelineOrchestrator.get_effective_config": 10, + "ObjectState.__init__": 23, + "ObjectState._compute_resolved_snapshot": 46, + "ObjectState._reconstruct_from_resolved": 343, + "ObjectState.to_saved_resolved_object": 21 + }, + "all_required_compiler_boundaries_reached": true, + "all41_hooks_installed": true, + "retained_json_bytes": 40594, + "generated_output_bytes": 2993187, + "public_log_bytes": 438, + "profiler_artifacts_absent": true, + "source_env_native_input_freeze": "PASS", + "science": "NOT_RUN: original declared2NPY/fullphysicalinventory/numerical/nativeinput witness separate gate. No exclusions or missing outputs waived.", + "scope": "One source-pinned ordinary IlluminationCorrection Example3 1w1t compiler/runtime diagnostic with NEW41 coarse nominal hooks: inherited24 plus17 compiler/state boundaries. Site is versioned/changed, not byte-identical. cProfile and runtime profiler OFF, no captures/percell hooks. Existing defaultOUTCOMES/memory observers/READY clocks unchanged. Same-thread nested exclusive clocks exclude query from its real ancestors; worker independent roots are not added to parent waits. Nearordinary diagnostic only; wrapper overhead remains, no scale factors/causal performance promotion. Full2NPY image-only declared export science/native source witness independently required. Passive installed-native Numba compile events distinguish startup and timed roots; bounded event batches flush AFTER original root elapsed is measured, cumulative counts retained, atexit supplementary only; event cap/refusal stays diagnostic RED, no dispatcher/signature retention." +} diff --git a/benchmark/results/perf_illum3_runtime_ledger_20261003/qualification.json b/benchmark/results/perf_illum3_runtime_ledger_20261003/qualification.json new file mode 100644 index 0000000000..9f857ae0f1 --- /dev/null +++ b/benchmark/results/perf_illum3_runtime_ledger_20261003/qualification.json @@ -0,0 +1,403 @@ +{ + "status": "ONE_CURRENT_ILLUM3_DIAGNOSTIC_AND_STRICT_SCIENCE_PASS", + "source_head": "4c0d62e45c8afb85e34b69d7279cd00710f519b5", + "all_handles_terminal": true, + "pipeline_runs": 1, + "driver_session": 79456, + "science_v3_session": 72671, + "original_reader_red_session": 84897, + "public_diagnostic_seconds": { + "compile_seconds": 0.5973687171936035, + "execute_seconds": 0.42289090156555176, + "total_seconds": 1.419051312841475, + "other_seconds": 0.39879169408231974 + }, + "raw_callable_boundary_seconds": 0.11173972394317389, + "execution_outside_raw_seconds": 0.3033128920942545, + "raw_callables": [ + { + "owner": "RuntimeCallableInvocation.call", + "dimensions": "function=openhcs.processing.backends.cellprofiler.primary_objects.identify_primary_objects;view=1", + "phase": "declared_callable_boundary", + "calls": 1, + "inclusive": 0.02976729581132531, + "exclusive": 0.02976729581132531 + }, + { + "owner": "RuntimeCallableInvocation.call", + "dimensions": "function=openhcs.processing.backends.cellprofiler.morphology.expand_or_shrink_objects;view=1", + "phase": "declared_callable_boundary", + "calls": 1, + "inclusive": 0.02096757711842656, + "exclusive": 0.02096757711842656 + }, + { + "owner": "RuntimeCallableInvocation.call", + "dimensions": "function=openhcs.processing.backends.cellprofiler.image_math.image_math;view=1", + "phase": "declared_callable_boundary", + "calls": 1, + "inclusive": 0.001754844095557928, + "exclusive": 0.001754844095557928 + }, + { + "owner": "RuntimeCallableInvocation.call", + "dimensions": "function=openhcs.processing.backends.cellprofiler.image_geometry.mask_image;view=1", + "phase": "declared_callable_boundary", + "calls": 2, + "inclusive": 0.0009737634100019932, + "exclusive": 0.0009737634100019932 + }, + { + "owner": "RuntimeCallableInvocation.call", + "dimensions": "function=openhcs.processing.backends.cellprofiler.illumination.correct_illumination_calculate;view=1", + "phase": "declared_callable_boundary", + "calls": 2, + "inclusive": 0.05728212045505643, + "exclusive": 0.05728212045505643 + }, + { + "owner": "RuntimeCallableInvocation.call", + "dimensions": "function=openhcs.processing.backends.cellprofiler.illumination.correct_illumination_apply;view=1", + "phase": "declared_callable_boundary", + "calls": 2, + "inclusive": 0.0008326279930770397, + "exclusive": 0.0008326279930770397 + }, + { + "owner": "RuntimeCallableInvocation.call", + "dimensions": "function=openhcs.processing.backends.cellprofiler.save_images.save_images;view=1", + "phase": "declared_callable_boundary", + "calls": 2, + "inclusive": 0.00016149505972862244, + "exclusive": 0.00016149505972862244 + } + ], + "compile_and_execution_source_owner_partition": { + "compile_only": { + "seconds": 0.5882621230557561, + "sum_exclusive": 0.5882621230557561, + "ObjectState_disjoint_exclusive": 0.3834735373966396, + "owners": [ + { + "owner": "ObjectState._compute_resolved_snapshot", + "dimensions": "", + "phase": "compiler_config:_compute_resolved_snapshot", + "calls": 46, + "inclusive": 0.2531436877325177, + "exclusive": 0.2531436877325177 + }, + { + "owner": "ObjectState.__init__", + "dimensions": "", + "phase": "compiler_config:__init__", + "calls": 23, + "inclusive": 0.35587291372939944, + "exclusive": 0.10272922599688172 + }, + { + "owner": "ObjectState._reconstruct_from_resolved", + "dimensions": "", + "phase": "compiler_config:_reconstruct_from_resolved", + "calls": 343, + "inclusive": 0.05295955156907439, + "exclusive": 0.027533238753676414 + }, + { + "owner": "ObjectState.to_saved_resolved_object", + "dimensions": "", + "phase": "compiler_config:to_saved_resolved_object", + "calls": 21, + "inclusive": 0.027600623667240143, + "exclusive": 6.738491356372833e-05 + }, + { + "owner": "PipelineOrchestrator.get_effective_config", + "dimensions": "", + "phase": "compiler_config:get_effective_config", + "calls": 10, + "inclusive": 0.19238800555467606, + "exclusive": 8.529284968972206e-05 + }, + { + "owner": "PipelineOrchestrator.create_context", + "dimensions": "", + "phase": "compiler_config:create_context", + "calls": 3, + "inclusive": 0.04923866596072912, + "exclusive": 0.0002901456318795681 + }, + { + "owner": "PipelineCompiler._axis_values_to_process", + "dimensions": "", + "phase": "compiler_config:_axis_values_to_process", + "calls": 1, + "inclusive": 0.014383771922439337, + "exclusive": 7.574260234832764e-05 + }, + { + "owner": "PipelineCompiler._register_and_resolve_pipeline_once", + "dimensions": "", + "phase": "compiler_config:_register_and_resolve_pipeline_once", + "calls": 1, + "inclusive": 0.19153947802260518, + "exclusive": 0.0021261521615087986 + }, + { + "owner": "PipelineCompiler._capture_pipeline_config", + "dimensions": "", + "phase": "compiler_config:_capture_pipeline_config", + "calls": 1, + "inclusive": 0.0017600241117179394, + "exclusive": 2.52528116106987e-06 + }, + { + "owner": "PipelineCompiler._resolve_global_step_axis_filters", + "dimensions": "", + "phase": "compiler_config:_resolve_global_step_axis_filters", + "calls": 1, + "inclusive": 0.013955585192888975, + "exclusive": 0.00047726836055517197 + }, + { + "owner": "PipelineCompiler._configure_input_conversion_if_needed", + "dimensions": "", + "phase": "compiler_config:_configure_input_conversion_if_needed", + "calls": 1, + "inclusive": 0.013350545894354582, + "exclusive": 4.2282044887542725e-06 + }, + { + "owner": "PipelineCompiler.initialize_step_plans_for_context", + "dimensions": "", + "phase": "compiler_config:initialize_step_plans_for_context", + "calls": 1, + "inclusive": 0.14918227866292, + "exclusive": 0.1358146509155631 + }, + { + "owner": "PipelineCompiler.declare_zarr_stores", + "dimensions": "", + "phase": "compiler_config:declare_zarr_stores", + "calls": 1, + "inclusive": 0.013443371281027794, + "exclusive": 4.089716821908951e-05 + }, + { + "owner": "PipelineCompiler._finalize_compilation", + "dimensions": "", + "phase": "compiler_config:_finalize_compilation", + "calls": 1, + "inclusive": 0.013896864838898182, + "exclusive": 0.00011343369260430336 + }, + { + "owner": "PipelineCompiler.compile_pipelines", + "dimensions": "", + "phase": "compiler_config:compile_pipelines", + "calls": 1, + "inclusive": 0.437725986354053, + "exclusive": 0.02060367353260517 + } + ] + }, + "execution": { + "seconds": 0.4150526160374284, + "sum_exclusive": 0.4150526160374284, + "ObjectState_disjoint_exclusive": 0.05523737985640764, + "owners": [ + { + "owner": "ObjectState._compute_resolved_snapshot", + "dimensions": "", + "phase": "compiler_config:_compute_resolved_snapshot", + "calls": 8, + "inclusive": 0.038815660402178764, + "exclusive": 0.038815660402178764 + }, + { + "owner": "ObjectState.__init__", + "dimensions": "", + "phase": "compiler_config:__init__", + "calls": 4, + "inclusive": 0.0482184044085443, + "exclusive": 0.009402744006365538 + }, + { + "owner": "ObjectState._reconstruct_from_resolved", + "dimensions": "", + "phase": "compiler_config:_reconstruct_from_resolved", + "calls": 92, + "inclusive": 0.013413879089057446, + "exclusive": 0.0070056007243692875 + }, + { + "owner": "ObjectState.to_saved_resolved_object", + "dimensions": "", + "phase": "compiler_config:to_saved_resolved_object", + "calls": 4, + "inclusive": 0.00701897544786334, + "exclusive": 1.3374723494052887e-05 + }, + { + "owner": "PipelineOrchestrator.get_effective_config", + "dimensions": "", + "phase": "compiler_config:get_effective_config", + "calls": 4, + "inclusive": 0.055267936550080776, + "exclusive": 3.055669367313385e-05 + }, + { + "owner": "PipelineOrchestrator.create_context", + "dimensions": "", + "phase": "compiler_config:create_context", + "calls": 1, + "inclusive": 0.01351372292265296, + "exclusive": 6.313808262348175e-05 + } + ] + } + }, + "numba": { + "native_event_authority": { + "path": "/home/ts/code/projects/openhcs/.venv/lib/python3.12/site-packages/numba/core/event.py", + "version": "0.67.0", + "sha256": "ab878d495f8532794bfe36f39b9d6c4e256abb669c8fa7bbe2a88f06d0b4a278", + "dispatcher_path": "/home/ts/code/projects/openhcs/.venv/lib/python3.12/site-packages/numba/core/dispatcher.py", + "dispatcher_sha256": "9fd050b1095cd6a9fef90772aa065d51328583b167b52393f7be6b615b99953b" + }, + "event_admission": true, + "root_flushes_complete": true, + "aggregate_bytes": 3107, + "native_compile_start_events": 0, + "actual_cumulative_counts_by_file": [ + { + "path": "/home/ts/.local/state/openhcs-maintenance/20261003/illum3-compiler-runtime-ledger-v2/output/regions/numba-events-2078555-0001.json", + "counts": {}, + "complete": true + }, + { + "path": "/home/ts/.local/state/openhcs-maintenance/20261003/illum3-compiler-runtime-ledger-v2/output/regions/numba-events-2078682-0001.json", + "counts": {}, + "complete": true + }, + { + "path": "/home/ts/.local/state/openhcs-maintenance/20261003/illum3-compiler-runtime-ledger-v2/output/regions/numba-events-2078682-0002.json", + "counts": {}, + "complete": true + }, + { + "path": "/home/ts/.local/state/openhcs-maintenance/20261003/illum3-compiler-runtime-ledger-v2/output/regions/numba-events-2078682-0003.json", + "counts": {}, + "complete": true + } + ], + "scope": "NO original numba:compile START/END events observed in either process/startup/timed roots/outside roots in THIS run. Cache loads emit no native compile event. Does not establish prior timing-variance cause or missing polynomial warmup." + }, + "science": { + "comparisons": 2, + "image_nonvacuity": "All2authored ReferenceExportPlan artifacts compared with positive pixel counts to both retainednative reps", + "measurement_differences": 0, + "image_differences": 0, + "inventory": "ALLactualfiles accounted via unchanged nominal policy; no unknown exclusions", + "native_scope": "TRANSITIVE retainednative reps, not rerun/currentnativeclocks", + "reader_only_environment_effect_key_names": [ + "KMP_DUPLICATE_LIB_OK", + "SPARSE_AUTO_DENSIFY", + "TF_FORCE_GPU_ALLOW_GROWTH", + "XLA_PYTHON_CLIENT_PREALLOCATE" + ], + "source_env_guard": "Exact original full controller --prepare guard before/after using original raw launch env isolated from reader-only imports; no key filters/rewrite or bypass. Original failed in-reader custody invocation retained." + }, + "custody": { + "/home/ts/.local/state/openhcs-maintenance/20261003/illum3-compiler-runtime-ledger-v2/handoff.json": { + "sha256": "7f8f1e5d977bd4fabc5b785be7181be4bfe28b1000b8a9d00b7491673e506787", + "bytes": 5211 + }, + "/home/ts/.local/state/openhcs-maintenance/20261003/illum3-compiler-runtime-ledger-v2/controller.py": { + "sha256": "e00e1cb2e195842f780ed289e97700db9fd52d7046414079fb186f90a7f98df5", + "bytes": 19881 + }, + "/home/ts/.local/state/openhcs-maintenance/20261003/illum3-compiler-runtime-ledger-v2/controls.json": { + "sha256": "358cd70c391cdaae89d5f2ba8514de606ccabcf43be3507dadeba7ae2341f7d1", + "bytes": 1520 + }, + "/home/ts/.local/state/openhcs-maintenance/20261003/illum3-compiler-runtime-ledger-v2/controls-v2.log": { + "sha256": "d4c3a95ea114ad14b9f1d4759b8959f1bdf67ffb520bd391efe2758ca2d30072", + "bytes": 1390 + }, + "/home/ts/.local/state/openhcs-maintenance/20261003/illum3-compiler-runtime-ledger-v2/site/sitecustomize.py": { + "sha256": "1a30063decce3e67ef2e0f3c033fb4f4cb9e6acf7e4c2b43b114c433f62c1bbe", + "bytes": 14423 + }, + "/home/ts/.local/state/openhcs-maintenance/20261003/illum3-compiler-runtime-ledger-v2/site/openhcs_numba_compile_events_v1.py": { + "sha256": "2e6863e7d78709cabddf6b34cb5fba1a8e27daeb39f0ae3e9134c15a3c45f421", + "bytes": 4548 + }, + "/home/ts/.local/state/openhcs-maintenance/20261003/illum3-compiler-runtime-ledger-v2/output/source-freeze.json": { + "sha256": "86646806122c73d38de2e9d42efa0bffd471ad0a1db36d7d33ea83dfcbfeb0fc", + "bytes": 1185307 + }, + "/home/ts/.local/state/openhcs-maintenance/20261003/illum3-compiler-runtime-ledger-v2/output/observations.json": { + "sha256": "c8b1e3f0704682e2cad20b7a5e27b1651e38b677e74f31d6477eb163185106fd", + "bytes": 4831 + }, + "/home/ts/.local/state/openhcs-maintenance/20261003/illum3-compiler-runtime-ledger-v2/science_validator.py": { + "sha256": "710f87213f2ebff207aa9c0c629cdb59639479c96a32656f1f3ec4adfd57d669", + "bytes": 5552 + }, + "/home/ts/.local/state/openhcs-maintenance/20261003/illum3-compiler-runtime-ledger-v2/science_validator_v3.py": { + "sha256": "e71981fd54cc6a3f6e3d03c797badff250cc5c7e3fdddf1401fb3378e17b8aa4", + "bytes": 7616 + }, + "/home/ts/.local/state/openhcs-maintenance/20261003/illum3-compiler-runtime-ledger-v2/science-first-red.json": { + "sha256": "de6ae869a4f1fe6eabfa4fc5b5ee87ba052462f26302d0a7a334c7b2c4276c80", + "bytes": 872 + }, + "/home/ts/.local/state/openhcs-maintenance/20261003/illum3-compiler-runtime-ledger-v2/science-first-red-environment-audit.json": { + "sha256": "4fa0497da2158f883c3af73aaea0b906a63f0d3887d7f82ee89e9c8afc03db20", + "bytes": 1285 + }, + "/home/ts/.local/state/openhcs-maintenance/20261003/illum3-compiler-runtime-ledger-v2/science-v3.json": { + "sha256": "607c68f213baddf4c5dbec97b39efee87451ac16188eadf1ebdea578d5bee9e5", + "bytes": 15478 + }, + "/home/ts/.local/state/openhcs-maintenance/20261003/illum3-compiler-runtime-ledger-v2/science-v3-controller-checkpoint-1.log": { + "sha256": "04a54993c97b3c3f46659e451ec5e2f8cd944fae12ab9f35abf49ffef1707c00", + "bytes": 1145 + }, + "/home/ts/.local/state/openhcs-maintenance/20261003/illum3-compiler-runtime-ledger-v2/science-v3-controller-checkpoint-2.log": { + "sha256": "04a54993c97b3c3f46659e451ec5e2f8cd944fae12ab9f35abf49ffef1707c00", + "bytes": 1145 + }, + "/home/ts/.local/state/openhcs-maintenance/20261003/illum3-compiler-runtime-ledger-v2/output/regions/region-2078682-140361443509952-0001.json": { + "sha256": "cc69523fdae5fe92c4e96ec59609a19eb889fe744316b6ed8419ed0398313ab9", + "bytes": 15563 + }, + "/home/ts/.local/state/openhcs-maintenance/20261003/illum3-compiler-runtime-ledger-v2/output/regions/region-2078682-140361443509952-0002.json": { + "sha256": "f3c9e01926b069a0103ebb9c70d638a4944c1f429b809b3a7b2e9755efbf80e5", + "bytes": 25031 + }, + "/home/ts/.local/state/openhcs-maintenance/20261003/illum3-compiler-runtime-ledger-v2/output/regions/numba-events-2078555-0001.json": { + "sha256": "df39cc4538c692418c9590759ee2be67c03e712d31b38e59909a2acc414299da", + "bytes": 712 + }, + "/home/ts/.local/state/openhcs-maintenance/20261003/illum3-compiler-runtime-ledger-v2/output/regions/numba-events-2078682-0001.json": { + "sha256": "0cc87c64a35b572441cac162e7a953685af095892641222cef4b52a71d7ace03", + "bytes": 843 + }, + "/home/ts/.local/state/openhcs-maintenance/20261003/illum3-compiler-runtime-ledger-v2/output/regions/numba-events-2078682-0002.json": { + "sha256": "a80829256ff2e4f13f8cb14257b45138aacefb6e2726339b64be55d585c90fde", + "bytes": 840 + }, + "/home/ts/.local/state/openhcs-maintenance/20261003/illum3-compiler-runtime-ledger-v2/output/regions/numba-events-2078682-0003.json": { + "sha256": "c615a8d1c29b5da41bba3237cd1ee02e6f8eba72af2f73290f11ec684571661b", + "bytes": 712 + } + }, + "determining_limits": [ + "One instrumented diagnostic, no causal code gain/speedup ratio or replacement of qualified two-repeat means.", + "Current compile .588262 root: state owners .383474s disjoint absolute envelope, includes mandatory distinct live/saved resolution and reconstruction. Late effective context reads .192388s inclusive subset; cannot claim both.", + "Execution outside RAW .303313s has actual init/config/record/publication/finalization/worker work; source-state .055237s separate. No single small lane closes existing qualified total gap.", + "Prior Illum execution .686775/.385197 spread .301578 remains UNATTRIBUTED; zero native compile events here cannot explain that historical difference.", + "No source changes, numerical algorithm patch, environment install, fresh native run, callback/validation/cache policy change, or benchmark clock exclusions." + ] +} diff --git a/benchmark/results/perf_illum3_runtime_ledger_20261003/reader-environment-audit.json b/benchmark/results/perf_illum3_runtime_ledger_20261003/reader-environment-audit.json new file mode 100644 index 0000000000..269ccbbb0b --- /dev/null +++ b/benchmark/results/perf_illum3_runtime_ledger_20261003/reader-environment-audit.json @@ -0,0 +1,35 @@ +{ + "status": "READER_IMPORT_ENVIRONMENT_EFFECT_IDENTIFIED", + "initial_full_environment_matches_driver_freeze": true, + "changes": [ + { + "import": "benchmark.adapters.openhcs", + "changed_key_names": [ + "KMP_DUPLICATE_LIB_OK", + "SPARSE_AUTO_DENSIFY", + "TF_FORCE_GPU_ALLOW_GROWTH", + "XLA_PYTHON_CLIENT_PREALLOCATE" + ] + } + ], + "source_environment_remains_driver_authoritative": "Actual driver pre/post full environment gate PASS; scientific reader changes cannot be treated as driver changes. No raw values disclosed.", + "per_key_hashes": { + "KMP_DUPLICATE_LIB_OK": { + "before": null, + "after": "3cbc87c7681f34db4617feaa2c8801931bc5e42d8d0f560e756dd4cd92885f18" + }, + "SPARSE_AUTO_DENSIFY": { + "before": null, + "after": "6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b" + }, + "TF_FORCE_GPU_ALLOW_GROWTH": { + "before": null, + "after": "b5bea41b6c623f7c09f1bf24dcae58ebab3c0cdd90ad966bc43a45b44867e12b" + }, + "XLA_PYTHON_CLIENT_PREALLOCATE": { + "before": null, + "after": "fcbcf165908dd18a9e49f7ff27810176db8e9f63b4352213741664245224f8aa" + } + }, + "after_reader_import_environment_sha256": "4415a2780ee53da969d5dc39ef698b0e50675d444afc6629d8a68dca42b1b514" +} diff --git a/benchmark/results/perf_illum3_runtime_ledger_20261003/reader-first-red.json b/benchmark/results/perf_illum3_runtime_ledger_20261003/reader-first-red.json new file mode 100644 index 0000000000..7910967dd7 --- /dev/null +++ b/benchmark/results/perf_illum3_runtime_ledger_20261003/reader-first-red.json @@ -0,0 +1,13 @@ +{ + "status": "ORIGINAL_READER_CUSTODY_RED_RETAINED", + "process_session": 84897, + "returncode": 1, + "original_reader": "/home/ts/.local/state/openhcs-maintenance/20261003/illum3-compiler-runtime-ledger-v2/science_validator.py", + "original_reader_sha256": "710f87213f2ebff207aa9c0c629cdb59639479c96a32656f1f3ec4adfd57d669", + "error": "AssertionError: Effective ordinary environment changed.", + "first_failure_boundary": "Original comparator final validate after comparison assertions, before science report write; FULLSCIENCEPASS was not claimed.", + "environment_audit": "/home/ts/.local/state/openhcs-maintenance/20261003/illum3-compiler-runtime-ledger-v2/science-first-red-environment-audit.json", + "environment_audit_sha256": "4fa0497da2158f883c3af73aaea0b906a63f0d3887d7f82ee89e9c8afc03db20", + "driver_admission_unchanged": true, + "no_pipeline_rerun": true +} diff --git a/benchmark/results/perf_illum3_runtime_ledger_20261003/render-retention-class-census.json b/benchmark/results/perf_illum3_runtime_ledger_20261003/render-retention-class-census.json new file mode 100644 index 0000000000..0714383a44 --- /dev/null +++ b/benchmark/results/perf_illum3_runtime_ledger_20261003/render-retention-class-census.json @@ -0,0 +1,671 @@ +{ + "source_head": "4c0d62e45c8afb85e34b69d7279cd00710f519b5", + "nra_head": "0844525ecaba93e090a064a4ae4914466b2dae60", + "scope": "All original classes in11 determining benchmark/document/transport modules, joined to actual canonical NRA family; reused731module global inventory for retrieval, unresolvedexternal/MRO effects OPEN. No source edits/importingproduction/metaclass execution.", + "source_hashes": { + "openhcs/core/pipeline_document.py": "0849800b3e6474b8176fe35bc4aaebc63cfa85bd77251000c50da5f4c928b1b2", + "openhcs/core/config_document.py": "37f66fd971806e059da6194c003e20a7ad08f69066eec4af7ebb11b4b70a08db", + "openhcs/core/function_step_transport.py": "b4c89539ace519926d178eb85a7909b4a7894203bf340213279e4f2a11e1152f", + "openhcs/runtime/zmq_execution_client.py": "8f98169438b1f9d65dd2a4f1517b5901e5d2ffd944fce4b0779a8f9b17d01db3", + "openhcs/runtime/zmq_compilation.py": "ad958c78ec9a26b778ad231501751f38ec6dd3d0c73ca2c1082207031fc6781f", + "openhcs/runtime/zmq_execution_signature.py": "41dcdb0a40446947a42a87482f27da051408015eec972e11e4d3329464db11ac", + "openhcs/serialization/source_path_factoring.py": "d8dd55b7d45882e067f9fddbe87327000a7e226dbc531a90fc543f201ea665ab", + "openhcs/serialization/pycodify_formatters.py": "b86d8a18b32084839667ebeb1322fd2e86ccb5fd8bea0365f01c03bc56042e9f", + "benchmark/openhcs_measured_run.py": "1e0cccc518fb6bec9c92ea8057dd7adfc7305b2d90a6da8f152c1b97601878ab", + "benchmark/well_throughput_scaling.py": "bcb58517c9c699be96d87027725a1fe299082874002cf0dc1032c6b267283e35", + "benchmark/metrics/memory.py": "bc049ff424564b876b82d79f5a34f49a3d5dc7f374804b23d53eed1dd729e25e" + }, + "modules": 11, + "classes": [ + { + "path": "openhcs/core/pipeline_document.py", + "line": 15, + "name": "PipelineDocument", + "canonical": true, + "symbol": "home.ts.code.projects.openhcs-shared-runtime-plumbing.openhcs.core.pipeline_document.PipelineDocument", + "bases": [] + }, + { + "path": "openhcs/core/pipeline_document.py", + "line": 23, + "name": "PipelineDocumentAuthority", + "canonical": true, + "symbol": "home.ts.code.projects.openhcs-shared-runtime-plumbing.openhcs.core.pipeline_document.PipelineDocumentAuthority", + "bases": [] + }, + { + "path": "openhcs/core/config_document.py", + "line": 15, + "name": "ConfigDocumentField", + "canonical": true, + "symbol": "home.ts.code.projects.openhcs-shared-runtime-plumbing.openhcs.core.config_document.ConfigDocumentField", + "bases": [ + "str", + "Enum" + ] + }, + { + "path": "openhcs/core/config_document.py", + "line": 21, + "name": "ConfigDocumentAuthority", + "canonical": true, + "symbol": "home.ts.code.projects.openhcs-shared-runtime-plumbing.openhcs.core.config_document.ConfigDocumentAuthority", + "bases": [] + }, + { + "path": "openhcs/core/function_step_transport.py", + "line": 23, + "name": "FunctionStepTransportAuthority", + "canonical": true, + "symbol": "home.ts.code.projects.openhcs-shared-runtime-plumbing.openhcs.core.function_step_transport.FunctionStepTransportAuthority", + "bases": [] + }, + { + "path": "openhcs/runtime/zmq_execution_client.py", + "line": 97, + "name": "ExecutionRuntimeLaunchPlan", + "canonical": true, + "symbol": "home.ts.code.projects.openhcs-shared-runtime-plumbing.openhcs.runtime.zmq_execution_client.ExecutionRuntimeLaunchPlan", + "bases": [] + }, + { + "path": "openhcs/runtime/zmq_execution_client.py", + "line": 218, + "name": "ExecutionSubmissionPreparationTimeoutError", + "canonical": true, + "symbol": "home.ts.code.projects.openhcs-shared-runtime-plumbing.openhcs.runtime.zmq_execution_client.ExecutionSubmissionPreparationTimeoutError", + "bases": [ + "TimeoutError" + ] + }, + { + "path": "openhcs/runtime/zmq_execution_client.py", + "line": 229, + "name": "OpenHCSExecutionSubmission", + "canonical": true, + "symbol": "home.ts.code.projects.openhcs-shared-runtime-plumbing.openhcs.runtime.zmq_execution_client.OpenHCSExecutionSubmission", + "bases": [] + }, + { + "path": "openhcs/runtime/zmq_execution_client.py", + "line": 401, + "name": "ZMQPipelineRunPhase", + "canonical": true, + "symbol": "home.ts.code.projects.openhcs-shared-runtime-plumbing.openhcs.runtime.zmq_execution_client.ZMQPipelineRunPhase", + "bases": [ + "Enum" + ] + }, + { + "path": "openhcs/runtime/zmq_execution_client.py", + "line": 411, + "name": "ZMQCompiledPipelineRun", + "canonical": true, + "symbol": "home.ts.code.projects.openhcs-shared-runtime-plumbing.openhcs.runtime.zmq_execution_client.ZMQCompiledPipelineRun", + "bases": [] + }, + { + "path": "openhcs/runtime/zmq_execution_client.py", + "line": 507, + "name": "ZMQExecutionRequestBuilder", + "canonical": true, + "symbol": "home.ts.code.projects.openhcs-shared-runtime-plumbing.openhcs.runtime.zmq_execution_client.ZMQExecutionRequestBuilder", + "bases": [] + }, + { + "path": "openhcs/runtime/zmq_execution_client.py", + "line": 545, + "name": "ZMQRequest", + "canonical": true, + "symbol": "home.ts.code.projects.openhcs-shared-runtime-plumbing.openhcs.runtime.zmq_execution_client.ZMQRequest", + "bases": [] + }, + { + "path": "openhcs/runtime/zmq_execution_client.py", + "line": 570, + "name": "ZMQConfigParamsBoundary", + "canonical": true, + "symbol": "home.ts.code.projects.openhcs-shared-runtime-plumbing.openhcs.runtime.zmq_execution_client.ZMQConfigParamsBoundary", + "bases": [] + }, + { + "path": "openhcs/runtime/zmq_execution_client.py", + "line": 600, + "name": "ZMQConfigSourceFields", + "canonical": true, + "symbol": "home.ts.code.projects.openhcs-shared-runtime-plumbing.openhcs.runtime.zmq_execution_client.ZMQConfigSourceFields", + "bases": [] + }, + { + "path": "openhcs/runtime/zmq_execution_client.py", + "line": 611, + "name": "ZMQConfigProjection", + "canonical": true, + "symbol": "home.ts.code.projects.openhcs-shared-runtime-plumbing.openhcs.runtime.zmq_execution_client.ZMQConfigProjection", + "bases": [] + }, + { + "path": "openhcs/runtime/zmq_execution_client.py", + "line": 657, + "name": "ZMQClientResponseView", + "canonical": true, + "symbol": "home.ts.code.projects.openhcs-shared-runtime-plumbing.openhcs.runtime.zmq_execution_client.ZMQClientResponseView", + "bases": [] + }, + { + "path": "openhcs/runtime/zmq_execution_client.py", + "line": 674, + "name": "FunctionCatalogEndpointUnavailableError", + "canonical": true, + "symbol": "home.ts.code.projects.openhcs-shared-runtime-plumbing.openhcs.runtime.zmq_execution_client.FunctionCatalogEndpointUnavailableError", + "bases": [ + "AgentFacingErrorMixin", + "RuntimeError" + ] + }, + { + "path": "openhcs/runtime/zmq_execution_client.py", + "line": 685, + "name": "FunctionCatalogExecutionClient", + "canonical": true, + "symbol": "home.ts.code.projects.openhcs-shared-runtime-plumbing.openhcs.runtime.zmq_execution_client.FunctionCatalogExecutionClient", + "bases": [ + "ExecutionClient", + "EndpointCompatibilityClientABC" + ] + }, + { + "path": "openhcs/runtime/zmq_execution_client.py", + "line": 953, + "name": "ZMQExecutionClient", + "canonical": true, + "symbol": "home.ts.code.projects.openhcs-shared-runtime-plumbing.openhcs.runtime.zmq_execution_client.ZMQExecutionClient", + "bases": [ + "FunctionCatalogExecutionClient" + ] + }, + { + "path": "openhcs/runtime/zmq_compilation.py", + "line": 53, + "name": "ZMQCompilationResult", + "canonical": true, + "symbol": "home.ts.code.projects.openhcs-shared-runtime-plumbing.openhcs.runtime.zmq_compilation.ZMQCompilationResult", + "bases": [] + }, + { + "path": "openhcs/runtime/zmq_compilation.py", + "line": 69, + "name": "ZMQCompilationRequest", + "canonical": true, + "symbol": "home.ts.code.projects.openhcs-shared-runtime-plumbing.openhcs.runtime.zmq_compilation.ZMQCompilationRequest", + "bases": [] + }, + { + "path": "openhcs/runtime/zmq_compilation.py", + "line": 219, + "name": "ZMQCompileArtifactRecord", + "canonical": true, + "symbol": "home.ts.code.projects.openhcs-shared-runtime-plumbing.openhcs.runtime.zmq_compilation.ZMQCompileArtifactRecord", + "bases": [] + }, + { + "path": "openhcs/runtime/zmq_execution_signature.py", + "line": 36, + "name": "ZMQAuxiliaryParamField", + "canonical": true, + "symbol": "home.ts.code.projects.openhcs-shared-runtime-plumbing.openhcs.runtime.zmq_execution_signature.ZMQAuxiliaryParamField", + "bases": [ + "Enum" + ] + }, + { + "path": "openhcs/runtime/zmq_execution_signature.py", + "line": 44, + "name": "ZMQRuntimeObservationExportScope", + "canonical": true, + "symbol": "home.ts.code.projects.openhcs-shared-runtime-plumbing.openhcs.runtime.zmq_execution_signature.ZMQRuntimeObservationExportScope", + "bases": [ + "Enum" + ] + }, + { + "path": "openhcs/runtime/zmq_execution_signature.py", + "line": 52, + "name": "ZMQAuxiliaryExecutionParams", + "canonical": true, + "symbol": "home.ts.code.projects.openhcs-shared-runtime-plumbing.openhcs.runtime.zmq_execution_signature.ZMQAuxiliaryExecutionParams", + "bases": [] + }, + { + "path": "openhcs/runtime/zmq_execution_signature.py", + "line": 206, + "name": "OpenHCSExecutionConfigBundle", + "canonical": true, + "symbol": "home.ts.code.projects.openhcs-shared-runtime-plumbing.openhcs.runtime.zmq_execution_signature.OpenHCSExecutionConfigBundle", + "bases": [] + }, + { + "path": "openhcs/runtime/zmq_execution_signature.py", + "line": 214, + "name": "ZMQExecutionIdentity", + "canonical": true, + "symbol": "home.ts.code.projects.openhcs-shared-runtime-plumbing.openhcs.runtime.zmq_execution_signature.ZMQExecutionIdentity", + "bases": [] + }, + { + "path": "openhcs/runtime/zmq_execution_signature.py", + "line": 240, + "name": "ZMQExecutionCompileControl", + "canonical": true, + "symbol": "home.ts.code.projects.openhcs-shared-runtime-plumbing.openhcs.runtime.zmq_execution_signature.ZMQExecutionCompileControl", + "bases": [] + }, + { + "path": "openhcs/runtime/zmq_execution_signature.py", + "line": 283, + "name": "ZMQExecutionConfigTransport", + "canonical": true, + "symbol": "home.ts.code.projects.openhcs-shared-runtime-plumbing.openhcs.runtime.zmq_execution_signature.ZMQExecutionConfigTransport", + "bases": [] + }, + { + "path": "openhcs/runtime/zmq_execution_signature.py", + "line": 307, + "name": "ZMQExecutionRequestPayload", + "canonical": true, + "symbol": "home.ts.code.projects.openhcs-shared-runtime-plumbing.openhcs.runtime.zmq_execution_signature.ZMQExecutionRequestPayload", + "bases": [] + }, + { + "path": "openhcs/serialization/source_path_factoring.py", + "line": 23, + "name": "SourcePathOccurrenceCollector", + "canonical": true, + "symbol": "home.ts.code.projects.openhcs-shared-runtime-plumbing.openhcs.serialization.source_path_factoring.SourcePathOccurrenceCollector", + "bases": [] + }, + { + "path": "openhcs/serialization/source_path_factoring.py", + "line": 33, + "name": "FactoredPathSourceLiteral", + "canonical": true, + "symbol": "home.ts.code.projects.openhcs-shared-runtime-plumbing.openhcs.serialization.source_path_factoring.FactoredPathSourceLiteral", + "bases": [ + "PythonSourceLiteral" + ] + }, + { + "path": "openhcs/serialization/source_path_factoring.py", + "line": 47, + "name": "SourcePathFactoringPlan", + "canonical": true, + "symbol": "home.ts.code.projects.openhcs-shared-runtime-plumbing.openhcs.serialization.source_path_factoring.SourcePathFactoringPlan", + "bases": [] + }, + { + "path": "openhcs/serialization/source_path_factoring.py", + "line": 126, + "name": "OpenHCSPythonSourceDocument", + "canonical": true, + "symbol": "home.ts.code.projects.openhcs-shared-runtime-plumbing.openhcs.serialization.source_path_factoring.OpenHCSPythonSourceDocument", + "bases": [] + }, + { + "path": "openhcs/serialization/pycodify_formatters.py", + "line": 25, + "name": "NameMappingLookup", + "canonical": true, + "symbol": "home.ts.code.projects.openhcs-shared-runtime-plumbing.openhcs.serialization.pycodify_formatters.NameMappingLookup", + "bases": [] + }, + { + "path": "openhcs/serialization/pycodify_formatters.py", + "line": 37, + "name": "OpenHCSCallableFormatter", + "canonical": true, + "symbol": "home.ts.code.projects.openhcs-shared-runtime-plumbing.openhcs.serialization.pycodify_formatters.OpenHCSCallableFormatter", + "bases": [ + "SourceFormatter" + ] + }, + { + "path": "openhcs/serialization/pycodify_formatters.py", + "line": 54, + "name": "OpenHCSImportableTypeFormatter", + "canonical": true, + "symbol": "home.ts.code.projects.openhcs-shared-runtime-plumbing.openhcs.serialization.pycodify_formatters.OpenHCSImportableTypeFormatter", + "bases": [ + "OpenHCSCallableFormatter" + ] + }, + { + "path": "openhcs/serialization/pycodify_formatters.py", + "line": 69, + "name": "PythonSourceLiteralFormatter", + "canonical": true, + "symbol": "home.ts.code.projects.openhcs-shared-runtime-plumbing.openhcs.serialization.pycodify_formatters.PythonSourceLiteralFormatter", + "bases": [ + "SourceFormatter" + ] + }, + { + "path": "openhcs/serialization/pycodify_formatters.py", + "line": 84, + "name": "OpenHCSPathFormatter", + "canonical": true, + "symbol": "home.ts.code.projects.openhcs-shared-runtime-plumbing.openhcs.serialization.pycodify_formatters.OpenHCSPathFormatter", + "bases": [ + "SourceFormatter" + ] + }, + { + "path": "openhcs/serialization/pycodify_formatters.py", + "line": 115, + "name": "EnumMemberFormatter", + "canonical": true, + "symbol": "home.ts.code.projects.openhcs-shared-runtime-plumbing.openhcs.serialization.pycodify_formatters.EnumMemberFormatter", + "bases": [ + "SourceFormatter" + ] + }, + { + "path": "openhcs/serialization/pycodify_formatters.py", + "line": 136, + "name": "MaterializationSpecFormatter", + "canonical": true, + "symbol": "home.ts.code.projects.openhcs-shared-runtime-plumbing.openhcs.serialization.pycodify_formatters.MaterializationSpecFormatter", + "bases": [ + "SourceFormatter" + ] + }, + { + "path": "openhcs/serialization/pycodify_formatters.py", + "line": 221, + "name": "FunctionPatternTupleFormatter", + "canonical": true, + "symbol": "home.ts.code.projects.openhcs-shared-runtime-plumbing.openhcs.serialization.pycodify_formatters.FunctionPatternTupleFormatter", + "bases": [ + "SourceFormatter" + ] + }, + { + "path": "openhcs/serialization/pycodify_formatters.py", + "line": 273, + "name": "FunctionPatternListFormatter", + "canonical": true, + "symbol": "home.ts.code.projects.openhcs-shared-runtime-plumbing.openhcs.serialization.pycodify_formatters.FunctionPatternListFormatter", + "bases": [ + "SourceFormatter" + ] + }, + { + "path": "openhcs/serialization/pycodify_formatters.py", + "line": 296, + "name": "LazyDataclassFieldEmissionState", + "canonical": true, + "symbol": "home.ts.code.projects.openhcs-shared-runtime-plumbing.openhcs.serialization.pycodify_formatters.LazyDataclassFieldEmissionState", + "bases": [] + }, + { + "path": "openhcs/serialization/pycodify_formatters.py", + "line": 401, + "name": "LazyDataclassSerializedField", + "canonical": true, + "symbol": "home.ts.code.projects.openhcs-shared-runtime-plumbing.openhcs.serialization.pycodify_formatters.LazyDataclassSerializedField", + "bases": [] + }, + { + "path": "openhcs/serialization/pycodify_formatters.py", + "line": 407, + "name": "LazyDataclassSerializationPlan", + "canonical": true, + "symbol": "home.ts.code.projects.openhcs-shared-runtime-plumbing.openhcs.serialization.pycodify_formatters.LazyDataclassSerializationPlan", + "bases": [] + }, + { + "path": "openhcs/serialization/pycodify_formatters.py", + "line": 454, + "name": "LazyDataclassFormatEligibility", + "canonical": true, + "symbol": "home.ts.code.projects.openhcs-shared-runtime-plumbing.openhcs.serialization.pycodify_formatters.LazyDataclassFormatEligibility", + "bases": [] + }, + { + "path": "openhcs/serialization/pycodify_formatters.py", + "line": 460, + "name": "FunctionStepCleanModeFieldPolicy", + "canonical": true, + "symbol": "home.ts.code.projects.openhcs-shared-runtime-plumbing.openhcs.serialization.pycodify_formatters.FunctionStepCleanModeFieldPolicy", + "bases": [] + }, + { + "path": "openhcs/serialization/pycodify_formatters.py", + "line": 489, + "name": "LazyDataclassFormatter", + "canonical": true, + "symbol": "home.ts.code.projects.openhcs-shared-runtime-plumbing.openhcs.serialization.pycodify_formatters.LazyDataclassFormatter", + "bases": [ + "SourceFormatter" + ] + }, + { + "path": "openhcs/serialization/pycodify_formatters.py", + "line": 517, + "name": "FunctionStepFormatter", + "canonical": true, + "symbol": "home.ts.code.projects.openhcs-shared-runtime-plumbing.openhcs.serialization.pycodify_formatters.FunctionStepFormatter", + "bases": [ + "SourceFormatter" + ] + }, + { + "path": "benchmark/openhcs_measured_run.py", + "line": 99, + "name": "_ZMQOpenHCSExecution", + "canonical": true, + "symbol": "home.ts.code.projects.openhcs-shared-runtime-plumbing.benchmark.openhcs_measured_run._ZMQOpenHCSExecution", + "bases": [] + }, + { + "path": "benchmark/openhcs_measured_run.py", + "line": 131, + "name": "_ZMQProgressTimingObserver", + "canonical": true, + "symbol": "home.ts.code.projects.openhcs-shared-runtime-plumbing.benchmark.openhcs_measured_run._ZMQProgressTimingObserver", + "bases": [] + }, + { + "path": "benchmark/well_throughput_scaling.py", + "line": 90, + "name": "WellThroughputExecutionRoute", + "canonical": true, + "symbol": "home.ts.code.projects.openhcs-shared-runtime-plumbing.benchmark.well_throughput_scaling.WellThroughputExecutionRoute", + "bases": [ + "StrEnum" + ] + }, + { + "path": "benchmark/well_throughput_scaling.py", + "line": 103, + "name": "WellThroughputServerLifecycle", + "canonical": true, + "symbol": "home.ts.code.projects.openhcs-shared-runtime-plumbing.benchmark.well_throughput_scaling.WellThroughputServerLifecycle", + "bases": [ + "StrEnum" + ] + }, + { + "path": "benchmark/well_throughput_scaling.py", + "line": 111, + "name": "WellThroughputMode", + "canonical": true, + "symbol": "home.ts.code.projects.openhcs-shared-runtime-plumbing.benchmark.well_throughput_scaling.WellThroughputMode", + "bases": [] + }, + { + "path": "benchmark/well_throughput_scaling.py", + "line": 131, + "name": "WellThroughputObservationKey", + "canonical": true, + "symbol": "home.ts.code.projects.openhcs-shared-runtime-plumbing.benchmark.well_throughput_scaling.WellThroughputObservationKey", + "bases": [] + }, + { + "path": "benchmark/well_throughput_scaling.py", + "line": 138, + "name": "WellThroughputPreset", + "canonical": true, + "symbol": "home.ts.code.projects.openhcs-shared-runtime-plumbing.benchmark.well_throughput_scaling.WellThroughputPreset", + "bases": [ + "StrEnum" + ] + }, + { + "path": "benchmark/well_throughput_scaling.py", + "line": 183, + "name": "WellThroughputModeOrder", + "canonical": true, + "symbol": "home.ts.code.projects.openhcs-shared-runtime-plumbing.benchmark.well_throughput_scaling.WellThroughputModeOrder", + "bases": [] + }, + { + "path": "benchmark/well_throughput_scaling.py", + "line": 210, + "name": "WellThroughputBenchmarkPlan", + "canonical": true, + "symbol": "home.ts.code.projects.openhcs-shared-runtime-plumbing.benchmark.well_throughput_scaling.WellThroughputBenchmarkPlan", + "bases": [] + }, + { + "path": "benchmark/well_throughput_scaling.py", + "line": 288, + "name": "WellThroughputPresentationSources", + "canonical": true, + "symbol": "home.ts.code.projects.openhcs-shared-runtime-plumbing.benchmark.well_throughput_scaling.WellThroughputPresentationSources", + "bases": [] + }, + { + "path": "benchmark/well_throughput_scaling.py", + "line": 299, + "name": "WellThroughputPresentationMode", + "canonical": true, + "symbol": "home.ts.code.projects.openhcs-shared-runtime-plumbing.benchmark.well_throughput_scaling.WellThroughputPresentationMode", + "bases": [] + }, + { + "path": "benchmark/well_throughput_scaling.py", + "line": 308, + "name": "ModuleAbstractionCoverageKind", + "canonical": true, + "symbol": "home.ts.code.projects.openhcs-shared-runtime-plumbing.benchmark.well_throughput_scaling.ModuleAbstractionCoverageKind", + "bases": [ + "StrEnum" + ] + }, + { + "path": "benchmark/well_throughput_scaling.py", + "line": 350, + "name": "ModuleAbstractionCoverageRow", + "canonical": true, + "symbol": "home.ts.code.projects.openhcs-shared-runtime-plumbing.benchmark.well_throughput_scaling.ModuleAbstractionCoverageRow", + "bases": [] + }, + { + "path": "benchmark/well_throughput_scaling.py", + "line": 365, + "name": "ModuleAbstractionCoverageTable", + "canonical": true, + "symbol": "home.ts.code.projects.openhcs-shared-runtime-plumbing.benchmark.well_throughput_scaling.ModuleAbstractionCoverageTable", + "bases": [] + }, + { + "path": "benchmark/well_throughput_scaling.py", + "line": 417, + "name": "PresentationAxisBand", + "canonical": true, + "symbol": "home.ts.code.projects.openhcs-shared-runtime-plumbing.benchmark.well_throughput_scaling.PresentationAxisBand", + "bases": [] + }, + { + "path": "benchmark/well_throughput_scaling.py", + "line": 441, + "name": "PresentationAxisBandPolicy", + "canonical": true, + "symbol": "home.ts.code.projects.openhcs-shared-runtime-plumbing.benchmark.well_throughput_scaling.PresentationAxisBandPolicy", + "bases": [] + }, + { + "path": "benchmark/well_throughput_scaling.py", + "line": 491, + "name": "WellThroughputPresentationReport", + "canonical": true, + "symbol": "home.ts.code.projects.openhcs-shared-runtime-plumbing.benchmark.well_throughput_scaling.WellThroughputPresentationReport", + "bases": [] + }, + { + "path": "benchmark/well_throughput_scaling.py", + "line": 1860, + "name": "WellsPerCoreSummaryRow", + "canonical": true, + "symbol": "home.ts.code.projects.openhcs-shared-runtime-plumbing.benchmark.well_throughput_scaling.WellsPerCoreSummaryRow", + "bases": [] + }, + { + "path": "benchmark/well_throughput_scaling.py", + "line": 1898, + "name": "NativeCellProfilerExecutionBaseline", + "canonical": true, + "symbol": "home.ts.code.projects.openhcs-shared-runtime-plumbing.benchmark.well_throughput_scaling.NativeCellProfilerExecutionBaseline", + "bases": [] + }, + { + "path": "benchmark/well_throughput_scaling.py", + "line": 1909, + "name": "WellThroughputStatus", + "canonical": true, + "symbol": "home.ts.code.projects.openhcs-shared-runtime-plumbing.benchmark.well_throughput_scaling.WellThroughputStatus", + "bases": [ + "StrEnum" + ] + }, + { + "path": "benchmark/well_throughput_scaling.py", + "line": 1918, + "name": "ChildProcessTerminator", + "canonical": true, + "symbol": "home.ts.code.projects.openhcs-shared-runtime-plumbing.benchmark.well_throughput_scaling.ChildProcessTerminator", + "bases": [] + }, + { + "path": "benchmark/well_throughput_scaling.py", + "line": 1947, + "name": "WorkerLaneEventPhase", + "canonical": true, + "symbol": "home.ts.code.projects.openhcs-shared-runtime-plumbing.benchmark.well_throughput_scaling.WorkerLaneEventPhase", + "bases": [ + "str", + "Enum" + ] + }, + { + "path": "benchmark/well_throughput_scaling.py", + "line": 2017, + "name": "WellThroughputResult", + "canonical": true, + "symbol": "home.ts.code.projects.openhcs-shared-runtime-plumbing.benchmark.well_throughput_scaling.WellThroughputResult", + "bases": [] + }, + { + "path": "benchmark/metrics/memory.py", + "line": 15, + "name": "MemoryMetric", + "canonical": true, + "symbol": "home.ts.code.projects.openhcs-shared-runtime-plumbing.benchmark.metrics.memory.MemoryMetric", + "bases": [ + "MetricCollector" + ] + } + ], + "original_class_count": 74, + "canonical_count": 74 +} diff --git a/benchmark/results/perf_illum3_runtime_ledger_20261003/render-retention-decision.json b/benchmark/results/perf_illum3_runtime_ledger_20261003/render-retention-decision.json new file mode 100644 index 0000000000..5a63b2105a --- /dev/null +++ b/benchmark/results/perf_illum3_runtime_ledger_20261003/render-retention-decision.json @@ -0,0 +1,72 @@ +{ + "status": "STOP_AS_DOMINANT_PERFORMANCE_ROUTE", + "source_head": "4c0d62e45c8afb85e34b69d7279cd00710f519b5", + "source_unchanged": true, + "actual_import_root": "/home/ts/code/projects/openhcs-shared-runtime-plumbing/openhcs/__init__.py", + "repetitions": 6, + "alternating_observation_order": true, + "mandatory_submit_builder_medians_seconds": { + "submit_compile_total": 0.04574766173027456, + "submit_execution_total": 0.04563480010256171 + }, + "optional_completion_render_medians_seconds": { + "completion_pipeline": 0.04025681456550956, + "completion_config": 0.005451454082503915, + "returned_pipeline": 0.04034627298824489 + }, + "optional_combined_removal_ceiling_seconds": { + "median_all6": 0.08608636120334268, + "minimum_all6": 0.08512948034331203, + "maximum_all6": 0.08700018096715212, + "median_steady5": 0.08606792613863945 + }, + "actual_payload_read_median_seconds": 1.0470394045114517e-06, + "current_Illum3_total_2x_gap_seconds": 1.22610824, + "local_ceiling_fraction_of_total_gap": 0.07021106162971605, + "execution_gain_claim": null, + "NRA_census": { + "modules": 11, + "original_classes": 74, + "canonical_classes": 74, + "NRA_head": "0844525ecaba93e090a064a4ae4914466b2dae60" + }, + "controls": [ + { + "name": "actual_FunctionStep_constructor_callbacks_at_both_submit_epochs", + "status": "PASS" + }, + { + "name": "original_first_constructor_error_order", + "status": "PASS" + }, + { + "name": "nested_kwargs_mutation_changes_real_compilation_signature", + "status": "PASS" + }, + { + "name": "lawful_submission_config_replacement_changes_real_compilation_signature", + "status": "PASS" + }, + { + "name": "actual_execution_payload_snapshot_survives_later_authoring_mutation", + "status": "PASS" + }, + { + "name": "reviewed_source_public_contract", + "status": "PASS" + } + ], + "original_invocation_failure": { + "path": "/tmp/openhcs-render-retention-4c0d62/failure-v1.json", + "reason": "Controller attempted direct mutation of the genuinely frozen GlobalPipelineConfig. Preserved failure; corrected control uses lawful config replacement on mutable submission and explicitly retains frozen-assignment rejection." + }, + "production_plan_if_correctness_repair_authorized": "Carry actual execution request payload from existing ZMQExecutionRequestBuilder through existing ZMQCompiledPipelineRun and use its sent pipeline/config strings for retain_measured_openhcs_completion and final return. Keep independently rebuilt compile and execution submissions and mismatch rejection. No new wrapper, mutable-object render cache, or compile-to-execution source reuse. Root owns implementation.", + "evidence_hashes": { + "replay.py": "ae8d5785adb7caa44efd753dc338ed7cee4ef2de276dc638b714ed1642eaa3f0", + "census.py": "5ebc7845157055e6859a58e4f444dd1ad7536b7b2b7e35bea2d291ccc385cc2f", + "census.json": "16f23b40d587e3d9e2005fd6e66d47e4d3264ed90e655b676c425095dfbd02d5", + "result-v3.json": "28c79034129b4ea13aa7236c842b7b43bb0d6a5e67d84c22c6aca720d6bbed08", + "failure-v1.json": "efd6c37a49510503990f6127494207141d2f26ee36246a43c535cba3569395bd" + }, + "boundaries": "Public retained-source loaders reconstruct authored typed objects outside timers; real 10-step Illum3 source/config bytes match exactly. Source-only replay; no network, pipeline/server execution, evidence IO or scientific artifact recapture. All source hashes and clean HEAD unchanged. Pure declaration preparation retains original constructor/default-factory epochs; first reflection analysis labeled separately." +} diff --git a/benchmark/results/perf_illum3_runtime_ledger_20261003/render-retention-replay.json b/benchmark/results/perf_illum3_runtime_ledger_20261003/render-retention-replay.json new file mode 100644 index 0000000000..4c862bfc36 --- /dev/null +++ b/benchmark/results/perf_illum3_runtime_ledger_20261003/render-retention-replay.json @@ -0,0 +1,817 @@ +{ + "status": "PASS", + "head": "4c0d62e45c8afb85e34b69d7279cd00710f519b5", + "source_unchanged": true, + "source_hashes": { + "openhcs/core/pipeline_document.py": "0849800b3e6474b8176fe35bc4aaebc63cfa85bd77251000c50da5f4c928b1b2", + "openhcs/core/config_document.py": "37f66fd971806e059da6194c003e20a7ad08f69066eec4af7ebb11b4b70a08db", + "openhcs/core/function_step_transport.py": "b4c89539ace519926d178eb85a7909b4a7894203bf340213279e4f2a11e1152f", + "openhcs/runtime/zmq_execution_client.py": "8f98169438b1f9d65dd2a4f1517b5901e5d2ffd944fce4b0779a8f9b17d01db3", + "openhcs/runtime/zmq_compilation.py": "ad958c78ec9a26b778ad231501751f38ec6dd3d0c73ca2c1082207031fc6781f", + "openhcs/runtime/zmq_execution_signature.py": "41dcdb0a40446947a42a87482f27da051408015eec972e11e4d3329464db11ac", + "openhcs/serialization/source_path_factoring.py": "d8dd55b7d45882e067f9fddbe87327000a7e226dbc531a90fc543f201ea665ab", + "openhcs/serialization/pycodify_formatters.py": "b86d8a18b32084839667ebeb1322fd2e86ccb5fd8bea0365f01c03bc56042e9f", + "benchmark/openhcs_measured_run.py": "1e0cccc518fb6bec9c92ea8057dd7adfc7305b2d90a6da8f152c1b97601878ab", + "benchmark/well_throughput_scaling.py": "bcb58517c9c699be96d87027725a1fe299082874002cf0dc1032c6b267283e35", + "benchmark/metrics/memory.py": "bc049ff424564b876b82d79f5a34f49a3d5dc7f374804b23d53eed1dd729e25e" + }, + "actual_import_root": "/home/ts/code/projects/openhcs-shared-runtime-plumbing/openhcs/__init__.py", + "retained_source_paths": { + "pipeline": "/home/ts/.local/state/openhcs-maintenance/20261003/current-wound-illum3-paired-v1/ordinary-1/ExampleIlluminationCorrection_Example3/wells_1/workers_1/ordinary_run_evidence/ExampleIlluminationCorrection_Example3-1w_1t-1791013778142438710/submitted_pipeline.py", + "config": "/home/ts/.local/state/openhcs-maintenance/20261003/current-wound-illum3-paired-v1/ordinary-1/ExampleIlluminationCorrection_Example3/wells_1/workers_1/ordinary_run_evidence/ExampleIlluminationCorrection_Example3-1w_1t-1791013778142438710/submitted_global_config.py" + }, + "retained_source_hashes": { + "pipeline": "c313ff0830e45c62dc23d7ce5a013c490383a007a65a633c3c5df973a5edc687", + "config": "2e2cf95d87a9465d20ecbb8c88629ce615b64de6e5843319f9b51599f343c1c3" + }, + "preparation": { + "actual_registered_declarations": 44, + "entry_point": "SignatureAnalyzer.prepare_dataclass_declaration over existing LazyDataclassFactory.registered_type_pairs", + "FunctionStep_constructors_during_pure_preparation": 0, + "law": "No default factory/formatter memo introduced. First reflection-analysis epoch remains separately labeled, not hidden in preparation." + }, + "runs": [ + { + "index": 0, + "first_reflection_analysis_epoch": true, + "alternating_observation_order": [ + "original_render", + "actual_payload_read" + ], + "completion_observations": { + "original_render": { + "seconds": 0.08703801175579429, + "hashes": [ + "c313ff0830e45c62dc23d7ce5a013c490383a007a65a633c3c5df973a5edc687", + "2e2cf95d87a9465d20ecbb8c88629ce615b64de6e5843319f9b51599f343c1c3", + "c313ff0830e45c62dc23d7ce5a013c490383a007a65a633c3c5df973a5edc687" + ] + }, + "actual_payload_read": { + "seconds": 3.3262185752391815e-06, + "hashes": [ + "c313ff0830e45c62dc23d7ce5a013c490383a007a65a633c3c5df973a5edc687", + "2e2cf95d87a9465d20ecbb8c88629ce615b64de6e5843319f9b51599f343c1c3", + "c313ff0830e45c62dc23d7ce5a013c490383a007a65a633c3c5df973a5edc687" + ] + } + }, + "submit_compile_total": 0.06521604722365737, + "submit_execution_total": 0.04581552976742387, + "original_render_events": [ + { + "epoch": "0:submit_compile", + "owner": "pipeline", + "seconds": 0.05955396592617035, + "sha256": "c313ff0830e45c62dc23d7ce5a013c490383a007a65a633c3c5df973a5edc687", + "bytes": 10647 + }, + { + "epoch": "0:submit_compile", + "owner": "config", + "seconds": 0.005617266055196524, + "sha256": "2e2cf95d87a9465d20ecbb8c88629ce615b64de6e5843319f9b51599f343c1c3", + "bytes": 407 + }, + { + "epoch": "0:submit_execution", + "owner": "pipeline", + "seconds": 0.040430141147226095, + "sha256": "c313ff0830e45c62dc23d7ce5a013c490383a007a65a633c3c5df973a5edc687", + "bytes": 10647 + }, + { + "epoch": "0:submit_execution", + "owner": "config", + "seconds": 0.005347607657313347, + "sha256": "2e2cf95d87a9465d20ecbb8c88629ce615b64de6e5843319f9b51599f343c1c3", + "bytes": 407 + }, + { + "epoch": "0:completion_pipeline", + "owner": "pipeline", + "seconds": 0.04034718498587608, + "sha256": "c313ff0830e45c62dc23d7ce5a013c490383a007a65a633c3c5df973a5edc687", + "bytes": 10647 + }, + { + "epoch": "0:completion_config", + "owner": "config", + "seconds": 0.005629708990454674, + "sha256": "2e2cf95d87a9465d20ecbb8c88629ce615b64de6e5843319f9b51599f343c1c3", + "bytes": 407 + }, + { + "epoch": "0:returned_pipeline", + "owner": "pipeline", + "seconds": 0.04102328699082136, + "sha256": "c313ff0830e45c62dc23d7ce5a013c490383a007a65a633c3c5df973a5edc687", + "bytes": 10647 + } + ], + "maximum_retention_return_removal_seconds": 0.08700018096715212, + "signature": "7b48f26c01b7c75e705c8fcaf0ccc83dabeeced6a14b0b74ef3f582be72aeabe" + }, + { + "index": 1, + "first_reflection_analysis_epoch": false, + "alternating_observation_order": [ + "actual_payload_read", + "original_render" + ], + "completion_observations": { + "actual_payload_read": { + "seconds": 1.0421499609947205e-06, + "hashes": [ + "c313ff0830e45c62dc23d7ce5a013c490383a007a65a633c3c5df973a5edc687", + "2e2cf95d87a9465d20ecbb8c88629ce615b64de6e5843319f9b51599f343c1c3", + "c313ff0830e45c62dc23d7ce5a013c490383a007a65a633c3c5df973a5edc687" + ] + }, + "original_render": { + "seconds": 0.08516591787338257, + "hashes": [ + "c313ff0830e45c62dc23d7ce5a013c490383a007a65a633c3c5df973a5edc687", + "2e2cf95d87a9465d20ecbb8c88629ce615b64de6e5843319f9b51599f343c1c3", + "c313ff0830e45c62dc23d7ce5a013c490383a007a65a633c3c5df973a5edc687" + ] + } + }, + "submit_compile_total": 0.04546358669176698, + "submit_execution_total": 0.04510248685255647, + "original_render_events": [ + { + "epoch": "1:submit_compile", + "owner": "pipeline", + "seconds": 0.04016154492273927, + "sha256": "c313ff0830e45c62dc23d7ce5a013c490383a007a65a633c3c5df973a5edc687", + "bytes": 10647 + }, + { + "epoch": "1:submit_compile", + "owner": "config", + "seconds": 0.005269180051982403, + "sha256": "2e2cf95d87a9465d20ecbb8c88629ce615b64de6e5843319f9b51599f343c1c3", + "bytes": 407 + }, + { + "epoch": "1:submit_execution", + "owner": "pipeline", + "seconds": 0.039719612803310156, + "sha256": "c313ff0830e45c62dc23d7ce5a013c490383a007a65a633c3c5df973a5edc687", + "bytes": 10647 + }, + { + "epoch": "1:submit_execution", + "owner": "config", + "seconds": 0.005344413220882416, + "sha256": "2e2cf95d87a9465d20ecbb8c88629ce615b64de6e5843319f9b51599f343c1c3", + "bytes": 407 + }, + { + "epoch": "1:completion_pipeline", + "owner": "pipeline", + "seconds": 0.03979505505412817, + "sha256": "c313ff0830e45c62dc23d7ce5a013c490383a007a65a633c3c5df973a5edc687", + "bytes": 10647 + }, + { + "epoch": "1:completion_config", + "owner": "config", + "seconds": 0.005292725283652544, + "sha256": "2e2cf95d87a9465d20ecbb8c88629ce615b64de6e5843319f9b51599f343c1c3", + "bytes": 407 + }, + { + "epoch": "1:returned_pipeline", + "owner": "pipeline", + "seconds": 0.04004170000553131, + "sha256": "c313ff0830e45c62dc23d7ce5a013c490383a007a65a633c3c5df973a5edc687", + "bytes": 10647 + } + ], + "maximum_retention_return_removal_seconds": 0.08512948034331203, + "signature": "7b48f26c01b7c75e705c8fcaf0ccc83dabeeced6a14b0b74ef3f582be72aeabe" + }, + { + "index": 2, + "first_reflection_analysis_epoch": false, + "alternating_observation_order": [ + "original_render", + "actual_payload_read" + ], + "completion_observations": { + "original_render": { + "seconds": 0.08613781817257404, + "hashes": [ + "c313ff0830e45c62dc23d7ce5a013c490383a007a65a633c3c5df973a5edc687", + "2e2cf95d87a9465d20ecbb8c88629ce615b64de6e5843319f9b51599f343c1c3", + "c313ff0830e45c62dc23d7ce5a013c490383a007a65a633c3c5df973a5edc687" + ] + }, + "actual_payload_read": { + "seconds": 1.0421499609947205e-06, + "hashes": [ + "c313ff0830e45c62dc23d7ce5a013c490383a007a65a633c3c5df973a5edc687", + "2e2cf95d87a9465d20ecbb8c88629ce615b64de6e5843319f9b51599f343c1c3", + "c313ff0830e45c62dc23d7ce5a013c490383a007a65a633c3c5df973a5edc687" + ] + } + }, + "submit_compile_total": 0.04603173676878214, + "submit_execution_total": 0.045378165785223246, + "original_render_events": [ + { + "epoch": "2:submit_compile", + "owner": "pipeline", + "seconds": 0.04065810004249215, + "sha256": "c313ff0830e45c62dc23d7ce5a013c490383a007a65a633c3c5df973a5edc687", + "bytes": 10647 + }, + { + "epoch": "2:submit_compile", + "owner": "config", + "seconds": 0.005338640883564949, + "sha256": "2e2cf95d87a9465d20ecbb8c88629ce615b64de6e5843319f9b51599f343c1c3", + "bytes": 407 + }, + { + "epoch": "2:submit_execution", + "owner": "pipeline", + "seconds": 0.040114596020430326, + "sha256": "c313ff0830e45c62dc23d7ce5a013c490383a007a65a633c3c5df973a5edc687", + "bytes": 10647 + }, + { + "epoch": "2:submit_execution", + "owner": "config", + "seconds": 0.005215710029006004, + "sha256": "2e2cf95d87a9465d20ecbb8c88629ce615b64de6e5843319f9b51599f343c1c3", + "bytes": 407 + }, + { + "epoch": "2:completion_pipeline", + "owner": "pipeline", + "seconds": 0.04045192198827863, + "sha256": "c313ff0830e45c62dc23d7ce5a013c490383a007a65a633c3c5df973a5edc687", + "bytes": 10647 + }, + { + "epoch": "2:completion_config", + "owner": "config", + "seconds": 0.005408914294093847, + "sha256": "2e2cf95d87a9465d20ecbb8c88629ce615b64de6e5843319f9b51599f343c1c3", + "bytes": 407 + }, + { + "epoch": "2:returned_pipeline", + "owner": "pipeline", + "seconds": 0.04024395998567343, + "sha256": "c313ff0830e45c62dc23d7ce5a013c490383a007a65a633c3c5df973a5edc687", + "bytes": 10647 + } + ], + "maximum_retention_return_removal_seconds": 0.0861047962680459, + "signature": "7b48f26c01b7c75e705c8fcaf0ccc83dabeeced6a14b0b74ef3f582be72aeabe" + }, + { + "index": 3, + "first_reflection_analysis_epoch": false, + "alternating_observation_order": [ + "actual_payload_read", + "original_render" + ], + "completion_observations": { + "actual_payload_read": { + "seconds": 1.051928848028183e-06, + "hashes": [ + "c313ff0830e45c62dc23d7ce5a013c490383a007a65a633c3c5df973a5edc687", + "2e2cf95d87a9465d20ecbb8c88629ce615b64de6e5843319f9b51599f343c1c3", + "c313ff0830e45c62dc23d7ce5a013c490383a007a65a633c3c5df973a5edc687" + ] + }, + "original_render": { + "seconds": 0.08610337320715189, + "hashes": [ + "c313ff0830e45c62dc23d7ce5a013c490383a007a65a633c3c5df973a5edc687", + "2e2cf95d87a9465d20ecbb8c88629ce615b64de6e5843319f9b51599f343c1c3", + "c313ff0830e45c62dc23d7ce5a013c490383a007a65a633c3c5df973a5edc687" + ] + } + }, + "submit_compile_total": 0.04541486594825983, + "submit_execution_total": 0.04553820798173547, + "original_render_events": [ + { + "epoch": "3:submit_compile", + "owner": "pipeline", + "seconds": 0.0400394550524652, + "sha256": "c313ff0830e45c62dc23d7ce5a013c490383a007a65a633c3c5df973a5edc687", + "bytes": 10647 + }, + { + "epoch": "3:submit_compile", + "owner": "config", + "seconds": 0.005345273297280073, + "sha256": "2e2cf95d87a9465d20ecbb8c88629ce615b64de6e5843319f9b51599f343c1c3", + "bytes": 407 + }, + { + "epoch": "3:submit_execution", + "owner": "pipeline", + "seconds": 0.04022560594603419, + "sha256": "c313ff0830e45c62dc23d7ce5a013c490383a007a65a633c3c5df973a5edc687", + "bytes": 10647 + }, + { + "epoch": "3:submit_execution", + "owner": "config", + "seconds": 0.005268760025501251, + "sha256": "2e2cf95d87a9465d20ecbb8c88629ce615b64de6e5843319f9b51599f343c1c3", + "bytes": 407 + }, + { + "epoch": "3:completion_pipeline", + "owner": "pipeline", + "seconds": 0.04016644414514303, + "sha256": "c313ff0830e45c62dc23d7ce5a013c490383a007a65a633c3c5df973a5edc687", + "bytes": 10647 + }, + { + "epoch": "3:completion_config", + "owner": "config", + "seconds": 0.005493993870913982, + "sha256": "2e2cf95d87a9465d20ecbb8c88629ce615b64de6e5843319f9b51599f343c1c3", + "bytes": 407 + }, + { + "epoch": "3:returned_pipeline", + "owner": "pipeline", + "seconds": 0.040407488122582436, + "sha256": "c313ff0830e45c62dc23d7ce5a013c490383a007a65a633c3c5df973a5edc687", + "bytes": 10647 + } + ], + "maximum_retention_return_removal_seconds": 0.08606792613863945, + "signature": "7b48f26c01b7c75e705c8fcaf0ccc83dabeeced6a14b0b74ef3f582be72aeabe" + }, + { + "index": 4, + "first_reflection_analysis_epoch": false, + "alternating_observation_order": [ + "original_render", + "actual_payload_read" + ], + "completion_observations": { + "original_render": { + "seconds": 0.08702337462455034, + "hashes": [ + "c313ff0830e45c62dc23d7ce5a013c490383a007a65a633c3c5df973a5edc687", + "2e2cf95d87a9465d20ecbb8c88629ce615b64de6e5843319f9b51599f343c1c3", + "c313ff0830e45c62dc23d7ce5a013c490383a007a65a633c3c5df973a5edc687" + ] + }, + "actual_payload_read": { + "seconds": 1.2721866369247437e-06, + "hashes": [ + "c313ff0830e45c62dc23d7ce5a013c490383a007a65a633c3c5df973a5edc687", + "2e2cf95d87a9465d20ecbb8c88629ce615b64de6e5843319f9b51599f343c1c3", + "c313ff0830e45c62dc23d7ce5a013c490383a007a65a633c3c5df973a5edc687" + ] + } + }, + "submit_compile_total": 0.04540669033303857, + "submit_execution_total": 0.04590281518176198, + "original_render_events": [ + { + "epoch": "4:submit_compile", + "owner": "pipeline", + "seconds": 0.040172276087105274, + "sha256": "c313ff0830e45c62dc23d7ce5a013c490383a007a65a633c3c5df973a5edc687", + "bytes": 10647 + }, + { + "epoch": "4:submit_compile", + "owner": "config", + "seconds": 0.005201412830501795, + "sha256": "2e2cf95d87a9465d20ecbb8c88629ce615b64de6e5843319f9b51599f343c1c3", + "bytes": 407 + }, + { + "epoch": "4:submit_execution", + "owner": "pipeline", + "seconds": 0.040503378957509995, + "sha256": "c313ff0830e45c62dc23d7ce5a013c490383a007a65a633c3c5df973a5edc687", + "bytes": 10647 + }, + { + "epoch": "4:submit_execution", + "owner": "config", + "seconds": 0.005346857011318207, + "sha256": "2e2cf95d87a9465d20ecbb8c88629ce615b64de6e5843319f9b51599f343c1c3", + "bytes": 407 + }, + { + "epoch": "4:completion_pipeline", + "owner": "pipeline", + "seconds": 0.04052451904863119, + "sha256": "c313ff0830e45c62dc23d7ce5a013c490383a007a65a633c3c5df973a5edc687", + "bytes": 10647 + }, + { + "epoch": "4:completion_config", + "owner": "config", + "seconds": 0.005857598967850208, + "sha256": "2e2cf95d87a9465d20ecbb8c88629ce615b64de6e5843319f9b51599f343c1c3", + "bytes": 407 + }, + { + "epoch": "4:returned_pipeline", + "owner": "pipeline", + "seconds": 0.040605089627206326, + "sha256": "c313ff0830e45c62dc23d7ce5a013c490383a007a65a633c3c5df973a5edc687", + "bytes": 10647 + } + ], + "maximum_retention_return_removal_seconds": 0.08698720764368773, + "signature": "7b48f26c01b7c75e705c8fcaf0ccc83dabeeced6a14b0b74ef3f582be72aeabe" + }, + { + "index": 5, + "first_reflection_analysis_epoch": false, + "alternating_observation_order": [ + "actual_payload_read", + "original_render" + ], + "completion_observations": { + "actual_payload_read": { + "seconds": 6.118789315223694e-07, + "hashes": [ + "c313ff0830e45c62dc23d7ce5a013c490383a007a65a633c3c5df973a5edc687", + "2e2cf95d87a9465d20ecbb8c88629ce615b64de6e5843319f9b51599f343c1c3", + "c313ff0830e45c62dc23d7ce5a013c490383a007a65a633c3c5df973a5edc687" + ] + }, + "original_render": { + "seconds": 0.08574638096615672, + "hashes": [ + "c313ff0830e45c62dc23d7ce5a013c490383a007a65a633c3c5df973a5edc687", + "2e2cf95d87a9465d20ecbb8c88629ce615b64de6e5843319f9b51599f343c1c3", + "c313ff0830e45c62dc23d7ce5a013c490383a007a65a633c3c5df973a5edc687" + ] + } + }, + "submit_compile_total": 0.0462398286908865, + "submit_execution_total": 0.04573139222338796, + "original_render_events": [ + { + "epoch": "5:submit_compile", + "owner": "pipeline", + "seconds": 0.040598487947136164, + "sha256": "c313ff0830e45c62dc23d7ce5a013c490383a007a65a633c3c5df973a5edc687", + "bytes": 10647 + }, + { + "epoch": "5:submit_compile", + "owner": "config", + "seconds": 0.0056106531992554665, + "sha256": "2e2cf95d87a9465d20ecbb8c88629ce615b64de6e5843319f9b51599f343c1c3", + "bytes": 407 + }, + { + "epoch": "5:submit_execution", + "owner": "pipeline", + "seconds": 0.04038529610261321, + "sha256": "c313ff0830e45c62dc23d7ce5a013c490383a007a65a633c3c5df973a5edc687", + "bytes": 10647 + }, + { + "epoch": "5:submit_execution", + "owner": "config", + "seconds": 0.005311900749802589, + "sha256": "2e2cf95d87a9465d20ecbb8c88629ce615b64de6e5843319f9b51599f343c1c3", + "bytes": 407 + }, + { + "epoch": "5:completion_pipeline", + "owner": "pipeline", + "seconds": 0.040041168220341206, + "sha256": "c313ff0830e45c62dc23d7ce5a013c490383a007a65a633c3c5df973a5edc687", + "bytes": 10647 + }, + { + "epoch": "5:completion_config", + "owner": "config", + "seconds": 0.0053860098123550415, + "sha256": "2e2cf95d87a9465d20ecbb8c88629ce615b64de6e5843319f9b51599f343c1c3", + "bytes": 407 + }, + { + "epoch": "5:returned_pipeline", + "owner": "pipeline", + "seconds": 0.04028505785390735, + "sha256": "c313ff0830e45c62dc23d7ce5a013c490383a007a65a633c3c5df973a5edc687", + "bytes": 10647 + } + ], + "maximum_retention_return_removal_seconds": 0.0857122358866036, + "signature": "7b48f26c01b7c75e705c8fcaf0ccc83dabeeced6a14b0b74ef3f582be72aeabe" + } + ], + "maximum_removed_summary": { + "median_all6": 0.08608636120334268, + "minimum_all6": 0.08512948034331203, + "maximum_all6": 0.08700018096715212, + "median_steady5": 0.08606792613863945 + }, + "controls": [ + { + "name": "actual_FunctionStep_constructor_callbacks_at_both_submit_epochs", + "status": "PASS", + "counts": { + "required_submit_compile": 30, + "required_submit_execution": 30 + }, + "events": [ + { + "epoch": "required_submit_compile", + "called_original": true + }, + { + "epoch": "required_submit_compile", + "called_original": true + }, + { + "epoch": "required_submit_compile", + "called_original": true + }, + { + "epoch": "required_submit_compile", + "called_original": true + }, + { + "epoch": "required_submit_compile", + "called_original": true + }, + { + "epoch": "required_submit_compile", + "called_original": true + }, + { + "epoch": "required_submit_compile", + "called_original": true + }, + { + "epoch": "required_submit_compile", + "called_original": true + }, + { + "epoch": "required_submit_compile", + "called_original": true + }, + { + "epoch": "required_submit_compile", + "called_original": true + }, + { + "epoch": "required_submit_compile", + "called_original": true + }, + { + "epoch": "required_submit_compile", + "called_original": true + }, + { + "epoch": "required_submit_compile", + "called_original": true + }, + { + "epoch": "required_submit_compile", + "called_original": true + }, + { + "epoch": "required_submit_compile", + "called_original": true + }, + { + "epoch": "required_submit_compile", + "called_original": true + }, + { + "epoch": "required_submit_compile", + "called_original": true + }, + { + "epoch": "required_submit_compile", + "called_original": true + }, + { + "epoch": "required_submit_compile", + "called_original": true + }, + { + "epoch": "required_submit_compile", + "called_original": true + }, + { + "epoch": "required_submit_compile", + "called_original": true + }, + { + "epoch": "required_submit_compile", + "called_original": true + }, + { + "epoch": "required_submit_compile", + "called_original": true + }, + { + "epoch": "required_submit_compile", + "called_original": true + }, + { + "epoch": "required_submit_compile", + "called_original": true + }, + { + "epoch": "required_submit_compile", + "called_original": true + }, + { + "epoch": "required_submit_compile", + "called_original": true + }, + { + "epoch": "required_submit_compile", + "called_original": true + }, + { + "epoch": "required_submit_compile", + "called_original": true + }, + { + "epoch": "required_submit_compile", + "called_original": true + }, + { + "epoch": "required_submit_execution", + "called_original": true + }, + { + "epoch": "required_submit_execution", + "called_original": true + }, + { + "epoch": "required_submit_execution", + "called_original": true + }, + { + "epoch": "required_submit_execution", + "called_original": true + }, + { + "epoch": "required_submit_execution", + "called_original": true + }, + { + "epoch": "required_submit_execution", + "called_original": true + }, + { + "epoch": "required_submit_execution", + "called_original": true + }, + { + "epoch": "required_submit_execution", + "called_original": true + }, + { + "epoch": "required_submit_execution", + "called_original": true + }, + { + "epoch": "required_submit_execution", + "called_original": true + }, + { + "epoch": "required_submit_execution", + "called_original": true + }, + { + "epoch": "required_submit_execution", + "called_original": true + }, + { + "epoch": "required_submit_execution", + "called_original": true + }, + { + "epoch": "required_submit_execution", + "called_original": true + }, + { + "epoch": "required_submit_execution", + "called_original": true + }, + { + "epoch": "required_submit_execution", + "called_original": true + }, + { + "epoch": "required_submit_execution", + "called_original": true + }, + { + "epoch": "required_submit_execution", + "called_original": true + }, + { + "epoch": "required_submit_execution", + "called_original": true + }, + { + "epoch": "required_submit_execution", + "called_original": true + }, + { + "epoch": "required_submit_execution", + "called_original": true + }, + { + "epoch": "required_submit_execution", + "called_original": true + }, + { + "epoch": "required_submit_execution", + "called_original": true + }, + { + "epoch": "required_submit_execution", + "called_original": true + }, + { + "epoch": "required_submit_execution", + "called_original": true + }, + { + "epoch": "required_submit_execution", + "called_original": true + }, + { + "epoch": "required_submit_execution", + "called_original": true + }, + { + "epoch": "required_submit_execution", + "called_original": true + }, + { + "epoch": "required_submit_execution", + "called_original": true + }, + { + "epoch": "required_submit_execution", + "called_original": true + } + ] + }, + { + "name": "original_first_constructor_error_order", + "status": "PASS", + "events": [ + 1, + 2, + 3 + ] + }, + { + "name": "nested_kwargs_mutation_changes_real_compilation_signature", + "status": "PASS", + "before": "7b48f26c01b7c75e705c8fcaf0ccc83dabeeced6a14b0b74ef3f582be72aeabe", + "after": "ee83d723591705cf2adf6c65e572d18d33993121e8642346f3d205d0233cf352", + "scope": "Actual request signature changes; no locally retained compiled execution artifact exists, so no fake artifact/server receiver was constructed." + }, + { + "name": "lawful_submission_config_replacement_changes_real_compilation_signature", + "status": "PASS", + "before": "7b48f26c01b7c75e705c8fcaf0ccc83dabeeced6a14b0b74ef3f582be72aeabe", + "after": "9f26d2c15fa6857faa197e5f7f2c49cc87375809f45addb44dad52d5bd71dadd" + }, + { + "name": "actual_execution_payload_snapshot_survives_later_authoring_mutation", + "status": "PASS", + "actual_sha": "c313ff0830e45c62dc23d7ce5a013c490383a007a65a633c3c5df973a5edc687" + }, + { + "name": "reviewed_source_public_contract", + "status": "PASS" + } + ], + "limits": [ + "Original API renders only, no client network/server/pipeline job or completion evidence IO was executed.", + "Each repetition executes original two submit builders plus all third/fourth pipeline and third config renders, alternating original render versus actual sent-payload read order. Payload reads are an offline observation only; no production path was implemented.", + "Timing callbacks add bounded attribution overhead and current unprofiled interpreter may differ from an ordinary reused client; savings are a local removal ceiling, not end-to-end gain.", + "No actual compiled artifact was fabricated; actual changed signature refusal must remain exercised by existing receiver tests or later authorized full transaction gate." + ], + "decision": "Local immutable source replay supplies actual removed-render ceiling only; no production caching or implementation." +} diff --git a/benchmark/results/perf_illum3_runtime_ledger_20261003/report.rst b/benchmark/results/perf_illum3_runtime_ledger_20261003/report.rst new file mode 100644 index 0000000000..40b945e71c --- /dev/null +++ b/benchmark/results/perf_illum3_runtime_ledger_20261003/report.rst @@ -0,0 +1,97 @@ +Illumination 3 compiler and runtime diagnostic +============================================= + +The weakest retained single-thread native comparison is still dominated by +framework work. On unchanged production source 4c0d62e45, one fresh ordinary-path +diagnostic records 0.422891s execution, 0.597369s compilation and 1.419051s total. +The measured execution root is 0.415053s: 11 raw callable invocations account for +0.111740s; the remaining 0.303313s is 73.08% of that root. These are diagnostic +observations, not an optimization, an ordinary paired speedup, or a replacement +for the two-repeat native comparison. The objective remains unfinished. + +The original public driver uses one well and one worker on CPU5, mandatory +library/kernel readiness before pipeline clocks, default OUTCOMES and the +original memory observer. Startup and shutdown are excluded. The official +benchmark lease, source/native/environment/input custody and bounded artifact +controls pass. Both profilers are disabled. All 41 coarse hooks preserve the +original call, result/error identity, descriptor and argument mutation; 28 +controls pass. Exclusive clocks sum exactly to each root. Original interval +JSON files are retained rather than reconstructed from percentages. + +No event-emitting Numba compilation was observed +---------------------------------------------- + +A passive listener is installed after the original installed ``numba.core.event`` +module executes, before readiness. There are zero native ``numba:compile`` START +or END events in the retained startup and measured roots. Original module and +dispatcher bytes are pinned. Unique bounded event batches flush after each +measured root stops, so forced shutdown cannot erase its evidence. All required +root flushes pass; the four event files total 3,107 bytes with no refusals/errors. + +This observation rules out event-emitting dispatcher compilation as its pipeline +cost. It does not measure cache loads or explain the older 0.686775/0.385197s +execution spread. The existing polynomial preparation already covers its +declared masked/unmasked and writable/read-only families; no missing warmup is +inferred from a truncated source excerpt or the old variance. + +The dominant compiler term is state construction and resolution +------------------------------------------------------------- + +Compilation's root is 0.588262s. Twenty-three ObjectState constructions, +46 distinct live/saved snapshots and 343 reconstruction calls consume 0.383406s +in disjoint exclusive clocks; saved-object reads add 0.000067s. Ten effective +configuration reads take 0.192388s inclusively, already inside those costs. +That is neither an additional cost nor a removable-work estimate. The reads +span before and after the compiler captures its concrete configuration. + +Execution has four state constructions and eight snapshots, totaling 0.055237s +exclusive including reconstruction and saved reads. Other measured costs include +output recording 0.040833s, finalization 0.025324s, loading 0.021657s, +reconciliation 0.021559s, worker residual 0.021557s and publication 0.017187s. +These describe separate production consumers. No entire lane is claimed removable. +The source map identifies five reads before capture and five afterward, without +per-call timing. Existing requests and contexts are the strongest candidate +owners for later reads, but callback mutation and late errors prevent blind +substitution. No saved configuration optimization is qualified yet. Live/saved +baselines cannot be collapsed unconditionally or late edits ignored. + +The installed ObjectState and python-introspect editables are the owned external +trees at a01f8939b9 and ed1e4eb15f. The separately frozen canonical dependency +copies have different revisions. Assessment pins distinguish them. The earlier +731-module AST census is a different epoch; this report does not promote it as +a current global architecture proof. The selected 13 current modules have a +refreshed 71-class NRA census, retained with the determining source map. + +Science and rejected route +-------------------------- + +Both authored float32 NPY outputs, each 463 by 461 pixels, pass the original +comparison against both retained native repetitions. Polynomial correction's +maximum difference is 2.98e-8 under the existing 1e-6 tolerances; convex-hull +correction is exact. Full physical inventory, source identities, correlations, +input/native witnesses and before/after custody pass. Native was not rerun, so +there is no fresh native timing or new paired performance ratio. + +The first science-reader invocation failed its final environment guard because +dependency imports added four reader-local environment defaults. Its failure and +per-key hash audit are preserved. The corrected reader runs the unchanged full +controller guard in fresh interpreters with the exact original launch environment +before and after comparison. No keys are filtered or rewritten; both checkpoints +pass. The scientific comparison and tolerances are unchanged. + +Separately, six actual-source render replays find only 0.086086s median removable +completion/return rendering, versus the retained Illum3 total target gap of +1.226108s. Mandatory compile/execution render epochs remain independent, and +mutation/callback/error controls pass. Reject this as the dominant performance +route. Retaining the actual executed request remains a separate provenance repair. + +Custody and reproduction +------------------------ + +``assessment.json`` pins every byte-identical compact original receipt and the +full local freeze. Frozen controller/site/reader recipes remain at their pinned +maintenance paths; the full effective environment intentionally includes the +original controller agent identity. This is not a portable turnkey replay bundle. +No environment, scientific output, saved graph or source worktree is copied into +this report. The receipts total approximately 191KB. Existing PR #394 / issues +#384 and #496 carry this investigation; no new production speedup is claimed. diff --git a/benchmark/results/perf_illum3_runtime_ledger_20261003/science.json b/benchmark/results/perf_illum3_runtime_ledger_20261003/science.json new file mode 100644 index 0000000000..36d90aeb51 --- /dev/null +++ b/benchmark/results/perf_illum3_runtime_ledger_20261003/science.json @@ -0,0 +1,237 @@ +{ + "status": "PASS", + "comparisons": [ + { + "case": "ExampleIlluminationCorrection_Example3", + "ordinary_repeat": 0, + "native_repeat": 0, + "measurement_differences": 0, + "image_differences": 0, + "declared_export_comparisons": [ + { + "artifact": { + "artifact_name": "PolynomialCorrected", + "artifact_type": "ImageArtifactType", + "semantic_kind": "numeric_image_pixels", + "output_filename": "reference_image__PolynomialCorrected.npy", + "comparison": "float pixels: atol=1e-6, rtol=1e-6, zero mismatches" + }, + "reference_path": "/home/ts/.local/state/openhcs-maintenance/20261003/current-wound-illum3-paired-v1/native/ExampleIlluminationCorrection_Example3/outputs/0/reference_image__PolynomialCorrected.npy", + "candidate_path": "/home/ts/.local/state/openhcs-maintenance/20261003/illum3-compiler-runtime-ledger-v2/output/public/ExampleIlluminationCorrection_Example3/wells_1/workers_1/images_ExampleIlluminationCorrection_Example3_source_workspace_well_throughput/results/reference_image__PolynomialCorrected.npy", + "reference_shape": [ + 463, + 461 + ], + "candidate_shape": [ + 463, + 461 + ], + "reference_dtype": "float32", + "candidate_dtype": "float32", + "reference_pixel_digest": "b5073cb872058f88bb250be9e7a39bedd2ef281f23dfedde5262e4431f1fb0fe", + "candidate_pixel_digest": "8aedbeab3f9868c1d1d46b0aafb3b20bb9dfd107dc08bb0882577c493f08173b", + "compared_pixel_count": 213443, + "different_pixel_count": null, + "out_of_tolerance_pixel_count": 0, + "max_abs_difference": 2.9802322387695312e-08, + "equivalent": true + }, + { + "artifact": { + "artifact_name": "ConvexHullCorrWorm", + "artifact_type": "ImageArtifactType", + "semantic_kind": "numeric_image_pixels", + "output_filename": "reference_image__ConvexHullCorrWorm.npy", + "comparison": "float pixels: atol=1e-6, rtol=1e-6, zero mismatches" + }, + "reference_path": "/home/ts/.local/state/openhcs-maintenance/20261003/current-wound-illum3-paired-v1/native/ExampleIlluminationCorrection_Example3/outputs/0/reference_image__ConvexHullCorrWorm.npy", + "candidate_path": "/home/ts/.local/state/openhcs-maintenance/20261003/illum3-compiler-runtime-ledger-v2/output/public/ExampleIlluminationCorrection_Example3/wells_1/workers_1/images_ExampleIlluminationCorrection_Example3_source_workspace_well_throughput/results/reference_image__ConvexHullCorrWorm.npy", + "reference_shape": [ + 463, + 461 + ], + "candidate_shape": [ + 463, + 461 + ], + "reference_dtype": "float32", + "candidate_dtype": "float32", + "reference_pixel_digest": "fdc35df90fb97b2d2ab79e4acdaa00aef26d4d9c76fb53d6aa53351bd598dd9b", + "candidate_pixel_digest": "fdc35df90fb97b2d2ab79e4acdaa00aef26d4d9c76fb53d6aa53351bd598dd9b", + "compared_pixel_count": 213443, + "different_pixel_count": null, + "out_of_tolerance_pixel_count": 0, + "max_abs_difference": 0.0, + "equivalent": true + } + ], + "tables": [ + 0, + 0 + ], + "physical_images": [ + 2, + 2 + ], + "logical_images": [ + 2, + 2 + ], + "known_relationship_keys": [ + 0, + 0 + ], + "ordinary_receipt_sha256": "8157ccac4f4940243f4ad96970eaad64e43a38c9b339887a3ef7c8aa7f6a0b44", + "output_hashes": { + "/home/ts/.local/state/openhcs-maintenance/20261003/current-wound-illum3-paired-v1/native/ExampleIlluminationCorrection_Example3/outputs/0/reference_image__ConvexHullCorrWorm.npy": "9ba1259e4ca007c06f14be6946e32a86307ec2dfb9952b73fa2cc253ccae8b3a", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-wound-illum3-paired-v1/native/ExampleIlluminationCorrection_Example3/outputs/0/reference_image__PolynomialCorrected.npy": "588e6f9951aa7ad220678dbb0053e98fb6d324e71aab089d1d828d891ee32f54", + "/home/ts/.local/state/openhcs-maintenance/20261003/illum3-compiler-runtime-ledger-v2/output/public/ExampleIlluminationCorrection_Example3/wells_1/workers_1/images_ExampleIlluminationCorrection_Example3_source_workspace_well_throughput/results/reference_image__PolynomialCorrected.npy": "8875da63a072c8f2de4f5cb707d779a064b663bf69aa0f304fe6fa74d4ff57a6", + "/home/ts/.local/state/openhcs-maintenance/20261003/illum3-compiler-runtime-ledger-v2/output/public/ExampleIlluminationCorrection_Example3/wells_1/workers_1/images_ExampleIlluminationCorrection_Example3_source_workspace_well_throughput/results/reference_image__ConvexHullCorrWorm.npy": "9ba1259e4ca007c06f14be6946e32a86307ec2dfb9952b73fa2cc253ccae8b3a", + "/home/ts/.local/state/openhcs-maintenance/20261003/illum3-compiler-runtime-ledger-v2/output/public/ExampleIlluminationCorrection_Example3/wells_1/workers_1/images_ExampleIlluminationCorrection_Example3_source_workspace_well_throughput/openhcs_metadata.json.lock": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "/home/ts/.local/state/openhcs-maintenance/20261003/illum3-compiler-runtime-ledger-v2/output/public/ExampleIlluminationCorrection_Example3/wells_1/workers_1/images_ExampleIlluminationCorrection_Example3_source_workspace_well_throughput/openhcs_metadata.json": "579ac084b396dff5f7fbaa844139bf952c2576b6cb0242772c925ba9839c2267" + } + }, + { + "case": "ExampleIlluminationCorrection_Example3", + "ordinary_repeat": 0, + "native_repeat": 1, + "measurement_differences": 0, + "image_differences": 0, + "declared_export_comparisons": [ + { + "artifact": { + "artifact_name": "PolynomialCorrected", + "artifact_type": "ImageArtifactType", + "semantic_kind": "numeric_image_pixels", + "output_filename": "reference_image__PolynomialCorrected.npy", + "comparison": "float pixels: atol=1e-6, rtol=1e-6, zero mismatches" + }, + "reference_path": "/home/ts/.local/state/openhcs-maintenance/20261003/current-wound-illum3-paired-v1/native/ExampleIlluminationCorrection_Example3/outputs/1/reference_image__PolynomialCorrected.npy", + "candidate_path": "/home/ts/.local/state/openhcs-maintenance/20261003/illum3-compiler-runtime-ledger-v2/output/public/ExampleIlluminationCorrection_Example3/wells_1/workers_1/images_ExampleIlluminationCorrection_Example3_source_workspace_well_throughput/results/reference_image__PolynomialCorrected.npy", + "reference_shape": [ + 463, + 461 + ], + "candidate_shape": [ + 463, + 461 + ], + "reference_dtype": "float32", + "candidate_dtype": "float32", + "reference_pixel_digest": "b5073cb872058f88bb250be9e7a39bedd2ef281f23dfedde5262e4431f1fb0fe", + "candidate_pixel_digest": "8aedbeab3f9868c1d1d46b0aafb3b20bb9dfd107dc08bb0882577c493f08173b", + "compared_pixel_count": 213443, + "different_pixel_count": null, + "out_of_tolerance_pixel_count": 0, + "max_abs_difference": 2.9802322387695312e-08, + "equivalent": true + }, + { + "artifact": { + "artifact_name": "ConvexHullCorrWorm", + "artifact_type": "ImageArtifactType", + "semantic_kind": "numeric_image_pixels", + "output_filename": "reference_image__ConvexHullCorrWorm.npy", + "comparison": "float pixels: atol=1e-6, rtol=1e-6, zero mismatches" + }, + "reference_path": "/home/ts/.local/state/openhcs-maintenance/20261003/current-wound-illum3-paired-v1/native/ExampleIlluminationCorrection_Example3/outputs/1/reference_image__ConvexHullCorrWorm.npy", + "candidate_path": "/home/ts/.local/state/openhcs-maintenance/20261003/illum3-compiler-runtime-ledger-v2/output/public/ExampleIlluminationCorrection_Example3/wells_1/workers_1/images_ExampleIlluminationCorrection_Example3_source_workspace_well_throughput/results/reference_image__ConvexHullCorrWorm.npy", + "reference_shape": [ + 463, + 461 + ], + "candidate_shape": [ + 463, + 461 + ], + "reference_dtype": "float32", + "candidate_dtype": "float32", + "reference_pixel_digest": "fdc35df90fb97b2d2ab79e4acdaa00aef26d4d9c76fb53d6aa53351bd598dd9b", + "candidate_pixel_digest": "fdc35df90fb97b2d2ab79e4acdaa00aef26d4d9c76fb53d6aa53351bd598dd9b", + "compared_pixel_count": 213443, + "different_pixel_count": null, + "out_of_tolerance_pixel_count": 0, + "max_abs_difference": 0.0, + "equivalent": true + } + ], + "tables": [ + 0, + 0 + ], + "physical_images": [ + 2, + 2 + ], + "logical_images": [ + 2, + 2 + ], + "known_relationship_keys": [ + 0, + 0 + ], + "ordinary_receipt_sha256": "8157ccac4f4940243f4ad96970eaad64e43a38c9b339887a3ef7c8aa7f6a0b44", + "output_hashes": { + "/home/ts/.local/state/openhcs-maintenance/20261003/current-wound-illum3-paired-v1/native/ExampleIlluminationCorrection_Example3/outputs/1/reference_image__ConvexHullCorrWorm.npy": "9ba1259e4ca007c06f14be6946e32a86307ec2dfb9952b73fa2cc253ccae8b3a", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-wound-illum3-paired-v1/native/ExampleIlluminationCorrection_Example3/outputs/1/reference_image__PolynomialCorrected.npy": "588e6f9951aa7ad220678dbb0053e98fb6d324e71aab089d1d828d891ee32f54", + "/home/ts/.local/state/openhcs-maintenance/20261003/illum3-compiler-runtime-ledger-v2/output/public/ExampleIlluminationCorrection_Example3/wells_1/workers_1/images_ExampleIlluminationCorrection_Example3_source_workspace_well_throughput/results/reference_image__PolynomialCorrected.npy": "8875da63a072c8f2de4f5cb707d779a064b663bf69aa0f304fe6fa74d4ff57a6", + "/home/ts/.local/state/openhcs-maintenance/20261003/illum3-compiler-runtime-ledger-v2/output/public/ExampleIlluminationCorrection_Example3/wells_1/workers_1/images_ExampleIlluminationCorrection_Example3_source_workspace_well_throughput/results/reference_image__ConvexHullCorrWorm.npy": "9ba1259e4ca007c06f14be6946e32a86307ec2dfb9952b73fa2cc253ccae8b3a", + "/home/ts/.local/state/openhcs-maintenance/20261003/illum3-compiler-runtime-ledger-v2/output/public/ExampleIlluminationCorrection_Example3/wells_1/workers_1/images_ExampleIlluminationCorrection_Example3_source_workspace_well_throughput/openhcs_metadata.json.lock": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "/home/ts/.local/state/openhcs-maintenance/20261003/illum3-compiler-runtime-ledger-v2/output/public/ExampleIlluminationCorrection_Example3/wells_1/workers_1/images_ExampleIlluminationCorrection_Example3_source_workspace_well_throughput/openhcs_metadata.json": "579ac084b396dff5f7fbaa844139bf952c2576b6cb0242772c925ba9839c2267" + } + } + ], + "source_head": "4c0d62e45c8afb85e34b69d7279cd00710f519b5", + "scope": "One current41-hook diagnostic versus both retained qualified native repetitions. Original image/table/correlation/inventory authorities and existing declared ReferenceExportPlan; 2NPY positive pixel nonvacuity. Native not rerun; no causal timing or current-native ratio claim. Only input receipt namespace/outer cardinality/current freeze custody adapted. Reader import environment effects retained; original full controller guard runs before/after in fresh interpreters with exact original raw launch environment. First in-reader final environment RED preserved separately; no full-driver guard bypass or environment rewrites.", + "reader_environment_effects": { + "KMP_DUPLICATE_LIB_OK": { + "before": null, + "after": "3cbc87c7681f34db4617feaa2c8801931bc5e42d8d0f560e756dd4cd92885f18" + }, + "SPARSE_AUTO_DENSIFY": { + "before": null, + "after": "6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b" + }, + "TF_FORCE_GPU_ALLOW_GROWTH": { + "before": null, + "after": "b5bea41b6c623f7c09f1bf24dcae58ebab3c0cdd90ad966bc43a45b44867e12b" + }, + "XLA_PYTHON_CLIENT_PREALLOCATE": { + "before": null, + "after": "fcbcf165908dd18a9e49f7ff27810176db8e9f63b4352213741664245224f8aa" + } + }, + "reader_isolation_checkpoints": [ + { + "index": 1, + "log": "/home/ts/.local/state/openhcs-maintenance/20261003/illum3-compiler-runtime-ledger-v2/science-v3-controller-checkpoint-1.log", + "sha256": "04a54993c97b3c3f46659e451ec5e2f8cd944fae12ab9f35abf49ffef1707c00", + "source_freeze_sha256": "86646806122c73d38de2e9d42efa0bffd471ad0a1db36d7d33ea83dfcbfeb0fc", + "scope": "Original unchanged full controller source/env/native/input/sparse guard in fresh interpreter using exact original raw launch environment held only in memory; no values filtered or rewritten." + }, + { + "index": 2, + "log": "/home/ts/.local/state/openhcs-maintenance/20261003/illum3-compiler-runtime-ledger-v2/science-v3-controller-checkpoint-2.log", + "sha256": "04a54993c97b3c3f46659e451ec5e2f8cd944fae12ab9f35abf49ffef1707c00", + "source_freeze_sha256": "86646806122c73d38de2e9d42efa0bffd471ad0a1db36d7d33ea83dfcbfeb0fc", + "scope": "Original unchanged full controller source/env/native/input/sparse guard in fresh interpreter using exact original raw launch environment held only in memory; no values filtered or rewritten." + } + ], + "validator_sha256": "e71981fd54cc6a3f6e3d03c797badff250cc5c7e3fdddf1401fb3378e17b8aa4", + "diagnostic_admission": true, + "native_witness": { + "files": { + "/home/ts/.local/state/openhcs-maintenance/20261003/current-wound-illum3-paired-v1/native/ExampleIlluminationCorrection_Example3/outputs/0/reference_image__ConvexHullCorrWorm.npy": "9ba1259e4ca007c06f14be6946e32a86307ec2dfb9952b73fa2cc253ccae8b3a", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-wound-illum3-paired-v1/native/ExampleIlluminationCorrection_Example3/outputs/0/reference_image__PolynomialCorrected.npy": "588e6f9951aa7ad220678dbb0053e98fb6d324e71aab089d1d828d891ee32f54", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-wound-illum3-paired-v1/native/ExampleIlluminationCorrection_Example3/outputs/1/reference_image__ConvexHullCorrWorm.npy": "9ba1259e4ca007c06f14be6946e32a86307ec2dfb9952b73fa2cc253ccae8b3a", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-wound-illum3-paired-v1/native/ExampleIlluminationCorrection_Example3/outputs/1/reference_image__PolynomialCorrected.npy": "588e6f9951aa7ad220678dbb0053e98fb6d324e71aab089d1d828d891ee32f54" + }, + "strict_science_sha256": "3d89dc4daaceb34535ceaab05100b80b88487e32e67180a99595035b66c67236", + "source_freeze_sha256": "7719484a567283a9427cd9a3742b8ca4f25b26c0678f2d8858073d5666adb284", + "native_report_sha256": "437f3943b29f3335831f934c0c308f51134df18096016431276f7c976fb8b458", + "native_request_sha256": "a2ab2cf68ad3afaf8af31652ced4c8d23ea398dc91cc915132b5562b1dbd386e" + }, + "original_comparator_sha256": "0b7abed65ecc3d61761533a3a9a69e9b9a8acb220049175ff46fb5f004ade4aa", + "diagnostic_source_freeze_sha256": "86646806122c73d38de2e9d42efa0bffd471ad0a1db36d7d33ea83dfcbfeb0fc" +} diff --git a/benchmark/results/perf_invocation_owner_paired_20261003/README.rst b/benchmark/results/perf_invocation_owner_paired_20261003/README.rst new file mode 100644 index 0000000000..ad7037234f --- /dev/null +++ b/benchmark/results/perf_invocation_owner_paired_20261003/README.rst @@ -0,0 +1,34 @@ +Fresh invocation-owner paired checkpoint +======================================== + +Source ``c59eaa55fe3d3e49f3ecb727a14a91e56e2957f6`` contains the six +carrier removals and checkpoint correction. It precedes the output-record +binding specialization merged as PR #544. Both ordinary repetitions and two +fresh measured native repetitions are retained in ``timing_summary.json``. + +3D mean OpenHCS execution is 9.021577s, total 11.020390s, and native warm +invocation 14.793260s: 1.63976x execution and 1.34235x total. Speckles means +are 1.554196s execution, 2.433450s total and 1.964025s native: 1.26369x +execution and 0.807095x total. The two 3D execution observations are 9.616797s +and 8.426356s; Speckles observations are 1.810366s and 1.298026s. This +spread and two observations do not establish causal improvement or regression. + +All eight cross-comparisons pass the existing strict scientific image, +measurement, nonempty-domain, correlation and complete-inventory gates. Native +CP 3.9/JVM 11 import, loading and full warmup are outside its invocation clock. +Mandatory OpenHCS READY preparation and server startup/shutdown are outside +pipeline clocks. OpenHCS execution excludes compilation; total includes it +and ordinary OUTCOMES completion. One well, one inline worker and one native +CPU thread are used, with the ordinary memory observer. + +``qualification.json`` pins the original controller, source/dependency/input +joins, full strict-science report and verified lossless scientific custody +archive. The archive is 1,766,472 bytes for all 377 scientific files; its +SHA-256 is ``1cf533efca21da3638ae43931b5f5685a8790e3c45ae812622d10efcbcbfa6e8``. +Full strict report SHA-256 is +``08710272d7e7cbb14d6d12ab184532573267c777b68d86bfddd3d226a4270e3b``. +All original outputs remain retained. The local artifact paths are custody +references, not a claim that this directory is a standalone runnable bundle. + +This is a current two-case descriptive checkpoint. Full30, scaling, fresh +scaling figures and the performance goal remain unfinished. diff --git a/benchmark/results/perf_invocation_owner_paired_20261003/qualification.json b/benchmark/results/perf_invocation_owner_paired_20261003/qualification.json new file mode 100644 index 0000000000..fd439f7f15 --- /dev/null +++ b/benchmark/results/perf_invocation_owner_paired_20261003/qualification.json @@ -0,0 +1,64 @@ +{ + "status": "PASS", + "source_head": "c59eaa55fe3d3e49f3ecb727a14a91e56e2957f6", + "source": "/var/tmp/openhcs-owner-benchmark-c59eaa55f", + "source_clean": true, + "source_freeze": { + "path": "/home/ts/.local/state/openhcs-maintenance/20261003/invocation-owner-c59-paired-v2/source-freeze.json", + "sha256": "71d4df68c1755f372b4096c468dddc4c03acf60e538e64c63a1272aef61b606f" + }, + "science": { + "path": "/home/ts/.local/state/openhcs-maintenance/20261003/invocation-owner-c59-paired-v2/strict-science.json", + "sha256": "08710272d7e7cbb14d6d12ab184532573267c777b68d86bfddd3d226a4270e3b", + "comparisons": 8, + "gate": "Existing strict runtime measurement/image/correlation/inventory authorities; exact3D images, originalCPnumericpolicy,nonvacuousCSVdomain." + }, + "timing_summary": { + "path": "/home/ts/.local/state/openhcs-maintenance/20261003/invocation-owner-c59-paired-v2/timing_summary.json", + "sha256": "2b8caa5b22cc877f1c77a7ab882d6fdd18dc2efec7c6727a032d87093cc46ede" + }, + "custody_archive": { + "manifest": "/home/ts/.local/state/openhcs-maintenance/20261003/invocation-owner-c59-paired-v2-preparation/scientific-custody-archive-v1.json", + "manifest_sha256": "fca4765c1bc339f707010d31a9acb145e04b18927a2a1928eed3292277ae5ec2", + "path": "/home/ts/.local/state/openhcs-maintenance/20261003/invocation-owner-c59-paired-v2.scientific-custody.tar.gz", + "sha256": "1cf533efca21da3638ae43931b5f5685a8790e3c45ae812622d10efcbcbfa6e8", + "bytes": 1766472, + "files": 377, + "original_output_bytes": 37850708 + }, + "controller": { + "path": "/home/ts/.local/state/openhcs-maintenance/20261003/invocation-owner-c59-paired-v2-preparation/controller.py", + "sha256": "7a2d2265a391c2e8ebdbbb057fdebaab2b46f39024d6d9ad8ce3602f30bd56ec", + "baseline": "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-preparation-v2/controller.py", + "scope": "Reviewed original driver/native/science implementation retained; changes only detachedsource,custodyactualeditableimportowner discovery and currentmissingGitblobdocumentation supplement." + }, + "source_input_refs": { + "cp_tutorial_3d_monolayer": 180, + "ExampleSpeckles": 2 + }, + "physical_inputs_sha256": "980311696da713abd37ba7588dc21d06e0552ec4e5e76a72e7fcf2e636ce255e", + "all_handles_terminal": { + "prepare": { + "session": 87187, + "code": 0 + }, + "ordinary": { + "session": 23481, + "code": 0 + }, + "native": { + "session": 82103, + "code": 0 + }, + "compare": { + "session": 19497, + "code": 0 + } + }, + "retained_failure": { + "session": 26868, + "code": 1, + "reason": "Oldsparsecustody lacked7currentunexecuteddocs; no driver launched; V1 source/controller/log/output preserved." + }, + "scope": "Fresh descriptive2repetitions1well1workerCPU5/defaultOUTCOMES/RSS,READY/startupoutsideclocks; nativeCP39/JVM11 import/load/warmup excluded. No causal gain/full30/scalingclaim. Mutable root source notexecuted; only frozen detachedc59 and exactinstalled8editables used. Scientificoutputs retainedimmutable; no captures/newenv." +} diff --git a/benchmark/results/perf_invocation_owner_paired_20261003/timing_summary.json b/benchmark/results/perf_invocation_owner_paired_20261003/timing_summary.json new file mode 100644 index 0000000000..9de0ca741f --- /dev/null +++ b/benchmark/results/perf_invocation_owner_paired_20261003/timing_summary.json @@ -0,0 +1,73 @@ +{ + "status": "QUALIFIED_DESCRIPTIVE_TWO_REPEATS", + "source_head": "c59eaa55fe3d3e49f3ecb727a14a91e56e2957f6", + "cases": { + "cp_tutorial_3d_monolayer": { + "ordinary_observations": { + "compile_seconds": [ + 1.1835861206054688, + 1.1569459438323975 + ], + "execute_seconds": [ + 9.616796970367432, + 8.426356315612793 + ], + "total_seconds": [ + 11.650369129143655, + 10.390410478692502 + ] + }, + "native_invocation_observations": [ + 14.520403317175806, + 15.06611712090671 + ], + "means": { + "compile_seconds": 1.170266032218933, + "execute_seconds": 9.021576642990112, + "total_seconds": 11.020389803918079, + "native_invocation_seconds": 14.793260219041258 + }, + "execution_speedup": 1.6397644008861603, + "total_speedup": 1.3423536265279665, + "remaining_2x_execution_gap": 1.6249465334694833, + "source_head": "c59eaa55fe3d3e49f3ecb727a14a91e56e2957f6", + "well_count": 1, + "image_sets": 1, + "science": "ALL4_PAIR_COMPARISONS_PASS" + }, + "ExampleSpeckles": { + "ordinary_observations": { + "compile_seconds": [ + 0.5536556243896484, + 0.5043470859527588 + ], + "execute_seconds": [ + 1.810366153717041, + 1.2980256080627441 + ], + "total_seconds": [ + 2.7351605952717364, + 2.1317388960160315 + ] + }, + "native_invocation_observations": [ + 1.9850073368288577, + 1.9430433670058846 + ], + "means": { + "compile_seconds": 0.5290013551712036, + "execute_seconds": 1.5541958808898926, + "total_seconds": 2.433449745643884, + "native_invocation_seconds": 1.9640253519173712 + }, + "execution_speedup": 1.2636922900560132, + "total_speedup": 0.8070950942928536, + "remaining_2x_execution_gap": 0.572183204931207, + "source_head": "c59eaa55fe3d3e49f3ecb727a14a91e56e2957f6", + "well_count": 1, + "image_sets": 1, + "science": "ALL4_PAIR_COMPARISONS_PASS" + } + }, + "scope": "Two ordinary observations versus two fresh measured native warm observations. READY/serverstartup/shutdown and nativeimports/JVM/pipelineload/fullwarmup excluded by existing clocks. DefaultOUTCOMES/RSS. No causal optimization/full30/scaling claim. Native invocation clock covers full selected well; no division by plane/image-set count." +} diff --git a/benchmark/results/perf_rejected_metadata_owner_20261003/baseline-compile_only-region.json b/benchmark/results/perf_rejected_metadata_owner_20261003/baseline-compile_only-region.json new file mode 100644 index 0000000000..8ff5e63f99 --- /dev/null +++ b/benchmark/results/perf_rejected_metadata_owner_20261003/baseline-compile_only-region.json @@ -0,0 +1,178 @@ +{ + "pid": 1677824, + "thread": 140643152090816, + "region": "ZMQExecutionServer._execute_with_orchestrator", + "root_dimensions": "{\"case\": \"3d_monolayer_final\", \"compile_artifact_id\": null, \"execution_id\": \"9b5738f2-c0e7-413c-9d58-7aae0b6af48d\", \"kind\": \"compile_only\", \"plate\": \"/home/ts/.cache/openhcs/benchmark_datasets/CellProfiler_tutorials/data/3d_monolayer/images\"}", + "seconds": 1.2939568259753287, + "revision": "e8587bd7eb0c4aa283bc300c5eb9f2294f24890f", + "source": "/home/ts/code/projects/openhcs-shared-runtime-plumbing", + "stats": { + "ZMQExecutionServer._initialize_orchestrator": { + "owner": "ZMQExecutionServer._initialize_orchestrator", + "dimensions": "", + "phase": "_initialize_orchestrator", + "calls": 1, + "inclusive": 0.1277877571992576, + "exclusive": 0.1277877571992576 + }, + "ZMQExecutionServer._execute_with_orchestrator | {\"case\": \"3d_monolayer_final\", \"compile_artifact_id\": null, \"execution_id\": \"9b5738f2-c0e7-413c-9d58-7aae0b6af48d\", \"kind\": \"compile_only\", \"plate\": \"/home/ts/.cache/openhcs/benchmark_datasets/CellProfiler_tutorials/data/3d_monolayer/images\"}": { + "owner": "ZMQExecutionServer._execute_with_orchestrator", + "dimensions": "{\"case\": \"3d_monolayer_final\", \"compile_artifact_id\": null, \"execution_id\": \"9b5738f2-c0e7-413c-9d58-7aae0b6af48d\", \"kind\": \"compile_only\", \"plate\": \"/home/ts/.cache/openhcs/benchmark_datasets/CellProfiler_tutorials/data/3d_monolayer/images\"}", + "phase": "_execute_with_orchestrator", + "calls": 1, + "inclusive": 1.2939568259753287, + "exclusive": 1.166169068776071 + } + }, + "hooks_installed": [ + { + "module": "openhcs.core.aligned_image_payload", + "owner": "", + "method": "stack_image_payload_context", + "descriptor_kind": "function" + }, + { + "module": "openhcs.core.aligned_image_payload", + "owner": "", + "method": "unstack_image_payload_context", + "descriptor_kind": "function" + }, + { + "module": "openhcs.core.measurement_feature_queries", + "owner": "MeasurementFeatureValueIndex", + "method": "from_columnar_table_by_object", + "descriptor_kind": "classmethod" + }, + { + "module": "openhcs.core.virtual_workspace_metadata", + "owner": "AtomicMetadataWriter", + "method": "publish_source_projection_metadata", + "descriptor_kind": "function" + }, + { + "module": "openhcs.core.runtime_stack_cache", + "owner": "RuntimeImageStackCache", + "method": "get", + "descriptor_kind": "function" + }, + { + "module": "openhcs.core.runtime_stack_cache", + "owner": "RuntimeImageStackCache", + "method": "store", + "descriptor_kind": "function" + }, + { + "module": "openhcs.core.steps.function_outputs", + "owner": "", + "method": "finalize_function_step_outputs", + "descriptor_kind": "function" + }, + { + "module": "openhcs.core.steps.function_outputs", + "owner": "OpenHCSMetadataWriter", + "method": "finalize_completed_plate", + "descriptor_kind": "classmethod" + }, + { + "module": "openhcs.core.steps.function_outputs", + "owner": "RuntimeArtifactMetadataTarget", + "method": "reconciliation_targets", + "descriptor_kind": "function" + }, + { + "module": "openhcs.core.steps.function_runtime", + "owner": "FunctionCoreExecutor", + "method": "execute", + "descriptor_kind": "function" + }, + { + "module": "openhcs.core.steps.function_runtime", + "owner": "PatternGroupRuntime", + "method": "_load_input_stack", + "descriptor_kind": "function" + }, + { + "module": "openhcs.core.steps.function_runtime", + "owner": "PatternGroupRuntime", + "method": "_validate_and_unstack", + "descriptor_kind": "function" + }, + { + "module": "openhcs.core.steps.function_runtime", + "owner": "PatternGroupRuntime", + "method": "_save_outputs", + "descriptor_kind": "function" + }, + { + "module": "openhcs.processing.backends.lib_registry.unified_registry", + "owner": "RuntimeCallableInvocation", + "method": "call", + "descriptor_kind": "function" + }, + { + "module": "openhcs.core.orchestrator.analysis_consolidation", + "owner": "", + "method": "consolidate_analysis_outputs", + "descriptor_kind": "function" + }, + { + "module": "openhcs.core.orchestrator.worker_execution", + "owner": "", + "method": "execute_worker_lane", + "descriptor_kind": "function" + }, + { + "module": "openhcs.runtime.zmq_execution_server", + "owner": "ZMQExecutionServer", + "method": "_execute_with_orchestrator", + "descriptor_kind": "function" + }, + { + "module": "openhcs.runtime.zmq_execution_server", + "owner": "ZMQExecutionServer", + "method": "_initialize_orchestrator", + "descriptor_kind": "function" + }, + { + "module": "openhcs.runtime.zmq_execution_server", + "owner": "ZMQExecutionServer", + "method": "_export_runtime_observation", + "descriptor_kind": "function" + }, + { + "module": "openhcs.interop.cellprofiler.runtime.function_contract_execution", + "owner": "CellProfilerFunctionContractExecutor", + "method": "execute", + "descriptor_kind": "function" + }, + { + "module": "openhcs.interop.cellprofiler.runtime.measurement_execution_support", + "owner": "ObjectMeasurementOutputRecorder", + "method": "record", + "descriptor_kind": "function" + }, + { + "module": "openhcs.interop.cellprofiler.runtime.output_recording", + "owner": "CellProfilerOutputRecorder", + "method": "record_module_outputs", + "descriptor_kind": "classmethod" + }, + { + "module": "openhcs.interop.cellprofiler.runtime.module_execution", + "owner": "CellProfilerModuleExecutor", + "method": "__call__", + "descriptor_kind": "function" + }, + { + "module": "openhcs.interop.cellprofiler.runtime.module_execution", + "owner": "CellProfilerModuleExecutor", + "method": "_image_request", + "descriptor_kind": "function" + } + ], + "profiling_enabled": false, + "runtime_profiling_enabled": false, + "diagnostic_errors": [], + "captures": false, + "scope": "coarse same-run nested exclusive timing partition on the exact source revision recorded in this region. Diagnostic wrappers, no scientific or memory-observer substitutions. Not accepted performance comparison. Declared callable boundary includes filtering/decorated processing/metadata; not pure numerical kernels. Both existing profilers are disabled. These wrappers still add diagnostic overhead; no scaling to uninstrumented clocks or causal performance claims. Query boundary is nested under its actual parent and excluded from parent-exclusive elapsed." +} diff --git a/benchmark/results/perf_rejected_metadata_owner_20261003/baseline-execution-region.json b/benchmark/results/perf_rejected_metadata_owner_20261003/baseline-execution-region.json new file mode 100644 index 0000000000..642dc4c637 --- /dev/null +++ b/benchmark/results/perf_rejected_metadata_owner_20261003/baseline-execution-region.json @@ -0,0 +1,714 @@ +{ + "pid": 1677824, + "thread": 140643152090816, + "region": "ZMQExecutionServer._execute_with_orchestrator", + "root_dimensions": "{\"case\": \"3d_monolayer_final\", \"compile_artifact_id\": \"9b5738f2-c0e7-413c-9d58-7aae0b6af48d\", \"execution_id\": \"c1c82c64-ace1-4d05-a31f-e33c194659b3\", \"kind\": \"execution\", \"plate\": \"/home/ts/.cache/openhcs/benchmark_datasets/CellProfiler_tutorials/data/3d_monolayer/images\"}", + "seconds": 8.26425674976781, + "revision": "e8587bd7eb0c4aa283bc300c5eb9f2294f24890f", + "source": "/home/ts/code/projects/openhcs-shared-runtime-plumbing", + "stats": { + "ZMQExecutionServer._initialize_orchestrator": { + "owner": "ZMQExecutionServer._initialize_orchestrator", + "dimensions": "", + "phase": "_initialize_orchestrator", + "calls": 1, + "inclusive": 0.08023449825122952, + "exclusive": 0.08023449825122952 + }, + "RuntimeImageStackCache.get": { + "owner": "RuntimeImageStackCache.get", + "dimensions": "", + "phase": "get", + "calls": 32, + "inclusive": 0.0003536404110491276, + "exclusive": 0.0003536404110491276 + }, + "stack_image_payload_context": { + "owner": "stack_image_payload_context", + "dimensions": "", + "phase": "stack_image_payload_context", + "calls": 28, + "inclusive": 0.04427314409986138, + "exclusive": 0.04427314409986138 + }, + "PatternGroupRuntime._load_input_stack": { + "owner": "PatternGroupRuntime._load_input_stack", + "dimensions": "", + "phase": "_load_input_stack", + "calls": 32, + "inclusive": 0.8063831464387476, + "exclusive": 0.7971521429717541 + }, + "CellProfilerModuleExecutor._image_request": { + "owner": "CellProfilerModuleExecutor._image_request", + "dimensions": "", + "phase": "_image_request", + "calls": 30, + "inclusive": 0.2785968668758869, + "exclusive": 0.2785968668758869 + }, + "RuntimeCallableInvocation.call | function=openhcs.processing.backends.cellprofiler.intensity.rescale_intensity;view=1": { + "owner": "RuntimeCallableInvocation.call", + "dimensions": "function=openhcs.processing.backends.cellprofiler.intensity.rescale_intensity;view=1", + "phase": "declared_callable_boundary", + "calls": 2, + "inclusive": 0.013981282711029053, + "exclusive": 0.013981282711029053 + }, + "CellProfilerFunctionContractExecutor.execute | function=openhcs.processing.backends.cellprofiler.intensity.rescale_intensity": { + "owner": "CellProfilerFunctionContractExecutor.execute", + "dimensions": "function=openhcs.processing.backends.cellprofiler.intensity.rescale_intensity", + "phase": "execute", + "calls": 2, + "inclusive": 0.01470567611977458, + "exclusive": 0.0007243934087455273 + }, + "CellProfilerOutputRecorder.record_module_outputs": { + "owner": "CellProfilerOutputRecorder.record_module_outputs", + "dimensions": "", + "phase": "record_module_outputs", + "calls": 26, + "inclusive": 0.3608029861934483, + "exclusive": 0.3608029861934483 + }, + "CellProfilerModuleExecutor.__call__": { + "owner": "CellProfilerModuleExecutor.__call__", + "dimensions": "", + "phase": "__call__", + "calls": 32, + "inclusive": 4.476683502551168, + "exclusive": 0.12689677299931645 + }, + "FunctionCoreExecutor.execute | function=rescale_intensity": { + "owner": "FunctionCoreExecutor.execute", + "dimensions": "function=rescale_intensity", + "phase": "execute", + "calls": 2, + "inclusive": 0.10122189205139875, + "exclusive": 0.00037510739639401436 + }, + "PatternGroupRuntime._validate_and_unstack": { + "owner": "PatternGroupRuntime._validate_and_unstack", + "dimensions": "", + "phase": "_validate_and_unstack", + "calls": 28, + "inclusive": 0.2180978236719966, + "exclusive": 0.18270204262807965 + }, + "RuntimeImageStackCache.store": { + "owner": "RuntimeImageStackCache.store", + "dimensions": "", + "phase": "store", + "calls": 28, + "inclusive": 0.00022991374135017395, + "exclusive": 0.00022991374135017395 + }, + "PatternGroupRuntime._save_outputs": { + "owner": "PatternGroupRuntime._save_outputs", + "dimensions": "", + "phase": "_save_outputs", + "calls": 28, + "inclusive": 0.656574668828398, + "exclusive": 0.6563447550870478 + }, + "finalize_function_step_outputs": { + "owner": "finalize_function_step_outputs", + "dimensions": "", + "phase": "finalize_function_step_outputs", + "calls": 30, + "inclusive": 0.7433224944397807, + "exclusive": 0.20995302312076092 + }, + "RuntimeCallableInvocation.call | function=openhcs.processing.backends.cellprofiler.image_geometry.resize_volumetric;view=1": { + "owner": "RuntimeCallableInvocation.call", + "dimensions": "function=openhcs.processing.backends.cellprofiler.image_geometry.resize_volumetric;view=1", + "phase": "declared_callable_boundary", + "calls": 3, + "inclusive": 0.1333684236742556, + "exclusive": 0.1333684236742556 + }, + "CellProfilerFunctionContractExecutor.execute | function=openhcs.processing.backends.cellprofiler.image_geometry.resize_volumetric": { + "owner": "CellProfilerFunctionContractExecutor.execute", + "dimensions": "function=openhcs.processing.backends.cellprofiler.image_geometry.resize_volumetric", + "phase": "execute", + "calls": 3, + "inclusive": 0.13415974332019687, + "exclusive": 0.0007913196459412575 + }, + "FunctionCoreExecutor.execute | function=resize_volumetric": { + "owner": "FunctionCoreExecutor.execute", + "dimensions": "function=resize_volumetric", + "phase": "execute", + "calls": 3, + "inclusive": 0.19819467328488827, + "exclusive": 0.0007455325685441494 + }, + "RuntimeCallableInvocation.call | function=openhcs.processing.backends.cellprofiler.median_filter.medianfilter;view=1": { + "owner": "RuntimeCallableInvocation.call", + "dimensions": "function=openhcs.processing.backends.cellprofiler.median_filter.medianfilter;view=1", + "phase": "declared_callable_boundary", + "calls": 1, + "inclusive": 0.4704591277986765, + "exclusive": 0.4704591277986765 + }, + "CellProfilerFunctionContractExecutor.execute | function=openhcs.processing.backends.cellprofiler.median_filter.medianfilter": { + "owner": "CellProfilerFunctionContractExecutor.execute", + "dimensions": "function=openhcs.processing.backends.cellprofiler.median_filter.medianfilter", + "phase": "execute", + "calls": 1, + "inclusive": 0.4713046411052346, + "exclusive": 0.0008455133065581322 + }, + "FunctionCoreExecutor.execute | function=medianfilter": { + "owner": "FunctionCoreExecutor.execute", + "dimensions": "function=medianfilter", + "phase": "execute", + "calls": 1, + "inclusive": 0.501043249387294, + "exclusive": 0.0009696455672383308 + }, + "RuntimeCallableInvocation.call | function=openhcs.processing.backends.cellprofiler.thresholding.threshold;view=1": { + "owner": "RuntimeCallableInvocation.call", + "dimensions": "function=openhcs.processing.backends.cellprofiler.thresholding.threshold;view=1", + "phase": "declared_callable_boundary", + "calls": 3, + "inclusive": 0.4494844200089574, + "exclusive": 0.4494844200089574 + }, + "CellProfilerFunctionContractExecutor.execute | function=openhcs.processing.backends.cellprofiler.thresholding.threshold": { + "owner": "CellProfilerFunctionContractExecutor.execute", + "dimensions": "function=openhcs.processing.backends.cellprofiler.thresholding.threshold", + "phase": "execute", + "calls": 3, + "inclusive": 0.4505709954537451, + "exclusive": 0.0010865754447877407 + }, + "FunctionCoreExecutor.execute | function=threshold": { + "owner": "FunctionCoreExecutor.execute", + "dimensions": "function=threshold", + "phase": "execute", + "calls": 3, + "inclusive": 0.5448138085193932, + "exclusive": 0.003549575340002775 + }, + "RuntimeCallableInvocation.call | function=openhcs.processing.backends.cellprofiler.morphology.remove_holes_3d;view=1": { + "owner": "RuntimeCallableInvocation.call", + "dimensions": "function=openhcs.processing.backends.cellprofiler.morphology.remove_holes_3d;view=1", + "phase": "declared_callable_boundary", + "calls": 2, + "inclusive": 0.1073335069231689, + "exclusive": 0.1073335069231689 + }, + "CellProfilerFunctionContractExecutor.execute | function=openhcs.processing.backends.cellprofiler.morphology.remove_holes_3d": { + "owner": "CellProfilerFunctionContractExecutor.execute", + "dimensions": "function=openhcs.processing.backends.cellprofiler.morphology.remove_holes_3d", + "phase": "execute", + "calls": 2, + "inclusive": 0.10756895132362843, + "exclusive": 0.00023544440045952797 + }, + "FunctionCoreExecutor.execute | function=remove_holes_3d": { + "owner": "FunctionCoreExecutor.execute", + "dimensions": "function=remove_holes_3d", + "phase": "execute", + "calls": 2, + "inclusive": 0.11626771930605173, + "exclusive": 0.0005331146530807018 + }, + "RuntimeCallableInvocation.call | function=openhcs.processing.backends.cellprofiler.watershed.watershed_cellprofiler4;view=1": { + "owner": "RuntimeCallableInvocation.call", + "dimensions": "function=openhcs.processing.backends.cellprofiler.watershed.watershed_cellprofiler4;view=1", + "phase": "declared_callable_boundary", + "calls": 2, + "inclusive": 0.4769804459065199, + "exclusive": 0.4769804459065199 + }, + "CellProfilerFunctionContractExecutor.execute | function=openhcs.processing.backends.cellprofiler.watershed.watershed_cellprofiler4": { + "owner": "CellProfilerFunctionContractExecutor.execute", + "dimensions": "function=openhcs.processing.backends.cellprofiler.watershed.watershed_cellprofiler4", + "phase": "execute", + "calls": 2, + "inclusive": 0.47757716896012425, + "exclusive": 0.0005967230536043644 + }, + "FunctionCoreExecutor.execute | function=watershed_cellprofiler4": { + "owner": "FunctionCoreExecutor.execute", + "dimensions": "function=watershed_cellprofiler4", + "phase": "execute", + "calls": 2, + "inclusive": 0.5291692218743265, + "exclusive": 0.003626206424087286 + }, + "RuntimeCallableInvocation.call | function=openhcs.processing.backends.cellprofiler.morphology.resize_objects_3d;view=1": { + "owner": "RuntimeCallableInvocation.call", + "dimensions": "function=openhcs.processing.backends.cellprofiler.morphology.resize_objects_3d;view=1", + "phase": "declared_callable_boundary", + "calls": 2, + "inclusive": 0.13164904806762934, + "exclusive": 0.13164904806762934 + }, + "CellProfilerFunctionContractExecutor.execute | function=openhcs.processing.backends.cellprofiler.morphology.resize_objects_3d": { + "owner": "CellProfilerFunctionContractExecutor.execute", + "dimensions": "function=openhcs.processing.backends.cellprofiler.morphology.resize_objects_3d", + "phase": "execute", + "calls": 2, + "inclusive": 0.132229870185256, + "exclusive": 0.000580822117626667 + }, + "FunctionCoreExecutor.execute | function=resize_objects_3d": { + "owner": "FunctionCoreExecutor.execute", + "dimensions": "function=resize_objects_3d", + "phase": "execute", + "calls": 2, + "inclusive": 0.15821923222392797, + "exclusive": 0.0009479965083301067 + }, + "RuntimeCallableInvocation.call | function=openhcs.processing.backends.cellprofiler.morphology.erode_objects;view=1": { + "owner": "RuntimeCallableInvocation.call", + "dimensions": "function=openhcs.processing.backends.cellprofiler.morphology.erode_objects;view=1", + "phase": "declared_callable_boundary", + "calls": 1, + "inclusive": 0.056926466058939695, + "exclusive": 0.056926466058939695 + }, + "CellProfilerFunctionContractExecutor.execute | function=openhcs.processing.backends.cellprofiler.morphology.erode_objects": { + "owner": "CellProfilerFunctionContractExecutor.execute", + "dimensions": "function=openhcs.processing.backends.cellprofiler.morphology.erode_objects", + "phase": "execute", + "calls": 1, + "inclusive": 0.057448259089142084, + "exclusive": 0.0005217930302023888 + }, + "FunctionCoreExecutor.execute | function=erode_objects": { + "owner": "FunctionCoreExecutor.execute", + "dimensions": "function=erode_objects", + "phase": "execute", + "calls": 1, + "inclusive": 0.06930378871038556, + "exclusive": 0.0004508676938712597 + }, + "RuntimeCallableInvocation.call | function=openhcs.processing.backends.cellprofiler.object_images.convert_objects_to_image;view=1": { + "owner": "RuntimeCallableInvocation.call", + "dimensions": "function=openhcs.processing.backends.cellprofiler.object_images.convert_objects_to_image;view=1", + "phase": "declared_callable_boundary", + "calls": 3, + "inclusive": 0.007349567022174597, + "exclusive": 0.007349567022174597 + }, + "CellProfilerFunctionContractExecutor.execute | function=openhcs.processing.backends.cellprofiler.object_images.convert_objects_to_image": { + "owner": "CellProfilerFunctionContractExecutor.execute", + "dimensions": "function=openhcs.processing.backends.cellprofiler.object_images.convert_objects_to_image", + "phase": "execute", + "calls": 3, + "inclusive": 0.00814954238012433, + "exclusive": 0.0007999753579497337 + }, + "FunctionCoreExecutor.execute | function=convert_objects_to_image": { + "owner": "FunctionCoreExecutor.execute", + "dimensions": "function=convert_objects_to_image", + "phase": "execute", + "calls": 3, + "inclusive": 0.03970423201099038, + "exclusive": 0.0010002129711210728 + }, + "RuntimeCallableInvocation.call | function=openhcs.processing.backends.cellprofiler.image_math.image_math;view=1": { + "owner": "RuntimeCallableInvocation.call", + "dimensions": "function=openhcs.processing.backends.cellprofiler.image_math.image_math;view=1", + "phase": "declared_callable_boundary", + "calls": 120, + "inclusive": 0.0643215891905129, + "exclusive": 0.0643215891905129 + }, + "CellProfilerFunctionContractExecutor.execute | function=openhcs.processing.backends.cellprofiler.image_math.image_math": { + "owner": "CellProfilerFunctionContractExecutor.execute", + "dimensions": "function=openhcs.processing.backends.cellprofiler.image_math.image_math", + "phase": "execute", + "calls": 2, + "inclusive": 0.09143648901954293, + "exclusive": 0.027114899829030037 + }, + "FunctionCoreExecutor.execute | function=image_math": { + "owner": "FunctionCoreExecutor.execute", + "dimensions": "function=image_math", + "phase": "execute", + "calls": 2, + "inclusive": 0.3179855141788721, + "exclusive": 0.0005593728274106979 + }, + "RuntimeCallableInvocation.call | function=openhcs.processing.backends.cellprofiler.morphology.closing;view=1": { + "owner": "RuntimeCallableInvocation.call", + "dimensions": "function=openhcs.processing.backends.cellprofiler.morphology.closing;view=1", + "phase": "declared_callable_boundary", + "calls": 1, + "inclusive": 0.2726345621049404, + "exclusive": 0.2726345621049404 + }, + "CellProfilerFunctionContractExecutor.execute | function=openhcs.processing.backends.cellprofiler.morphology.closing": { + "owner": "CellProfilerFunctionContractExecutor.execute", + "dimensions": "function=openhcs.processing.backends.cellprofiler.morphology.closing", + "phase": "execute", + "calls": 1, + "inclusive": 0.2727289702743292, + "exclusive": 9.440816938877106e-05 + }, + "FunctionCoreExecutor.execute | function=closing": { + "owner": "FunctionCoreExecutor.execute", + "dimensions": "function=closing", + "phase": "execute", + "calls": 1, + "inclusive": 0.2932825358584523, + "exclusive": 0.00026117172092199326 + }, + "RuntimeCallableInvocation.call | function=openhcs.processing.backends.cellprofiler.image_geometry.mask_image;view=1": { + "owner": "RuntimeCallableInvocation.call", + "dimensions": "function=openhcs.processing.backends.cellprofiler.image_geometry.mask_image;view=1", + "phase": "declared_callable_boundary", + "calls": 60, + "inclusive": 0.017262772656977177, + "exclusive": 0.017262772656977177 + }, + "CellProfilerFunctionContractExecutor.execute | function=openhcs.processing.backends.cellprofiler.image_geometry.mask_image": { + "owner": "CellProfilerFunctionContractExecutor.execute", + "dimensions": "function=openhcs.processing.backends.cellprofiler.image_geometry.mask_image", + "phase": "execute", + "calls": 1, + "inclusive": 0.0316482950001955, + "exclusive": 0.014385522343218327 + }, + "FunctionCoreExecutor.execute | function=mask_image": { + "owner": "FunctionCoreExecutor.execute", + "dimensions": "function=mask_image", + "phase": "execute", + "calls": 1, + "inclusive": 0.053500546142458916, + "exclusive": 0.00037759123370051384 + }, + "RuntimeCallableInvocation.call | function=openhcs.processing.backends.cellprofiler.morphology.erode_image;view=1": { + "owner": "RuntimeCallableInvocation.call", + "dimensions": "function=openhcs.processing.backends.cellprofiler.morphology.erode_image;view=1", + "phase": "declared_callable_boundary", + "calls": 1, + "inclusive": 0.028324457351118326, + "exclusive": 0.028324457351118326 + }, + "CellProfilerFunctionContractExecutor.execute | function=openhcs.processing.backends.cellprofiler.morphology.erode_image": { + "owner": "CellProfilerFunctionContractExecutor.execute", + "dimensions": "function=openhcs.processing.backends.cellprofiler.morphology.erode_image", + "phase": "execute", + "calls": 1, + "inclusive": 0.028424454852938652, + "exclusive": 9.999750182032585e-05 + }, + "FunctionCoreExecutor.execute | function=erode_image": { + "owner": "FunctionCoreExecutor.execute", + "dimensions": "function=erode_image", + "phase": "execute", + "calls": 1, + "inclusive": 0.03319434495642781, + "exclusive": 0.0002447301521897316 + }, + "RuntimeCallableInvocation.call | function=openhcs.processing.backends.cellprofiler.intensity.measure_object_intensity;view=1": { + "owner": "RuntimeCallableInvocation.call", + "dimensions": "function=openhcs.processing.backends.cellprofiler.intensity.measure_object_intensity;view=1", + "phase": "declared_callable_boundary", + "calls": 4, + "inclusive": 0.6384402797557414, + "exclusive": 0.6384402797557414 + }, + "CellProfilerFunctionContractExecutor.execute | function=openhcs.processing.backends.cellprofiler.intensity.measure_object_intensity": { + "owner": "CellProfilerFunctionContractExecutor.execute", + "dimensions": "function=openhcs.processing.backends.cellprofiler.intensity.measure_object_intensity", + "phase": "execute", + "calls": 4, + "inclusive": 0.6391628603450954, + "exclusive": 0.0007225805893540382 + }, + "ObjectMeasurementOutputRecorder.record": { + "owner": "ObjectMeasurementOutputRecorder.record", + "dimensions": "", + "phase": "record", + "calls": 6, + "inclusive": 0.0037819184362888336, + "exclusive": 0.0037819184362888336 + }, + "FunctionCoreExecutor.execute | function=measure_object_intensity": { + "owner": "FunctionCoreExecutor.execute", + "dimensions": "function=measure_object_intensity", + "phase": "execute", + "calls": 4, + "inclusive": 0.7307992740534246, + "exclusive": 0.0043295701034367085 + }, + "RuntimeCallableInvocation.call | function=openhcs.processing.backends.cellprofiler.shape.measure_object_size_shape;view=1": { + "owner": "RuntimeCallableInvocation.call", + "dimensions": "function=openhcs.processing.backends.cellprofiler.shape.measure_object_size_shape;view=1", + "phase": "declared_callable_boundary", + "calls": 2, + "inclusive": 0.4818841591477394, + "exclusive": 0.4818841591477394 + }, + "CellProfilerFunctionContractExecutor.execute | function=openhcs.processing.backends.cellprofiler.shape.measure_object_size_shape": { + "owner": "CellProfilerFunctionContractExecutor.execute", + "dimensions": "function=openhcs.processing.backends.cellprofiler.shape.measure_object_size_shape", + "phase": "execute", + "calls": 2, + "inclusive": 0.4831168404780328, + "exclusive": 0.001232681330293417 + }, + "FunctionCoreExecutor.execute | function=measure_object_size_shape": { + "owner": "FunctionCoreExecutor.execute", + "dimensions": "function=measure_object_size_shape", + "phase": "execute", + "calls": 2, + "inclusive": 0.4943189197219908, + "exclusive": 0.00211262796074152 + }, + "RuntimeCallableInvocation.call | function=openhcs.processing.backends.cellprofiler.outlines.overlay_objects;view=1": { + "owner": "RuntimeCallableInvocation.call", + "dimensions": "function=openhcs.processing.backends.cellprofiler.outlines.overlay_objects;view=1", + "phase": "declared_callable_boundary", + "calls": 2, + "inclusive": 0.3061672244220972, + "exclusive": 0.3061672244220972 + }, + "CellProfilerFunctionContractExecutor.execute | function=openhcs.processing.backends.cellprofiler.outlines.overlay_objects": { + "owner": "CellProfilerFunctionContractExecutor.execute", + "dimensions": "function=openhcs.processing.backends.cellprofiler.outlines.overlay_objects", + "phase": "execute", + "calls": 2, + "inclusive": 0.3063722001388669, + "exclusive": 0.00020497571676969528 + }, + "FunctionCoreExecutor.execute | function=overlay_objects": { + "owner": "FunctionCoreExecutor.execute", + "dimensions": "function=overlay_objects", + "phase": "execute", + "calls": 2, + "inclusive": 0.32670215563848615, + "exclusive": 0.010954282246530056 + }, + "RuntimeCallableInvocation.call | function=openhcs.processing.backends.cellprofiler.save_images.save_images;view=1": { + "owner": "RuntimeCallableInvocation.call", + "dimensions": "function=openhcs.processing.backends.cellprofiler.save_images.save_images;view=1", + "phase": "declared_callable_boundary", + "calls": 2, + "inclusive": 0.0001477571204304695, + "exclusive": 0.0001477571204304695 + }, + "FunctionCoreExecutor.execute | function=save_images": { + "owner": "FunctionCoreExecutor.execute", + "dimensions": "function=save_images", + "phase": "execute", + "calls": 2, + "inclusive": 0.16580111486837268, + "exclusive": 0.1656533577479422 + }, + "AtomicMetadataWriter.publish_source_projection_metadata": { + "owner": "AtomicMetadataWriter.publish_source_projection_metadata", + "dimensions": "", + "phase": "publish_source_projection_metadata", + "calls": 5, + "inclusive": 0.7686110232025385, + "exclusive": 0.7686110232025385 + }, + "execute_worker_lane | {\"execution_id\": \"c1c82c64-ace1-4d05-a31f-e33c194659b3\", \"kind\": \"worker_lane\", \"plate\": \"/home/ts/.cache/openhcs/benchmark_datasets/CellProfiler_tutorials/data/3d_monolayer/images\", \"worker_slot\": \"worker_0\"}": { + "owner": "execute_worker_lane", + "dimensions": "{\"execution_id\": \"c1c82c64-ace1-4d05-a31f-e33c194659b3\", \"kind\": \"worker_lane\", \"plate\": \"/home/ts/.cache/openhcs/benchmark_datasets/CellProfiler_tutorials/data/3d_monolayer/images\", \"worker_slot\": \"worker_0\"}", + "phase": "execute_worker_lane", + "calls": 1, + "inclusive": 7.582170368172228, + "exclusive": 0.4842700120061636 + }, + "consolidate_analysis_outputs": { + "owner": "consolidate_analysis_outputs", + "dimensions": "", + "phase": "consolidate_analysis_outputs", + "calls": 1, + "inclusive": 1.02287158370018e-05, + "exclusive": 1.02287158370018e-05 + }, + "RuntimeArtifactMetadataTarget.reconciliation_targets": { + "owner": "RuntimeArtifactMetadataTarget.reconciliation_targets", + "dimensions": "", + "phase": "reconciliation_targets", + "calls": 1, + "inclusive": 0.3009079131297767, + "exclusive": 0.3009079131297767 + }, + "OpenHCSMetadataWriter.finalize_completed_plate": { + "owner": "OpenHCSMetadataWriter.finalize_completed_plate", + "dimensions": "", + "phase": "finalize_completed_plate", + "calls": 1, + "inclusive": 0.5221393280662596, + "exclusive": 0.00812348397448659 + }, + "ZMQExecutionServer._export_runtime_observation": { + "owner": "ZMQExecutionServer._export_runtime_observation", + "dimensions": "", + "phase": "_export_runtime_observation", + "calls": 1, + "inclusive": 0.007673155982047319, + "exclusive": 0.007673155982047319 + }, + "ZMQExecutionServer._execute_with_orchestrator | {\"case\": \"3d_monolayer_final\", \"compile_artifact_id\": \"9b5738f2-c0e7-413c-9d58-7aae0b6af48d\", \"execution_id\": \"c1c82c64-ace1-4d05-a31f-e33c194659b3\", \"kind\": \"execution\", \"plate\": \"/home/ts/.cache/openhcs/benchmark_datasets/CellProfiler_tutorials/data/3d_monolayer/images\"}": { + "owner": "ZMQExecutionServer._execute_with_orchestrator", + "dimensions": "{\"case\": \"3d_monolayer_final\", \"compile_artifact_id\": \"9b5738f2-c0e7-413c-9d58-7aae0b6af48d\", \"execution_id\": \"c1c82c64-ace1-4d05-a31f-e33c194659b3\", \"kind\": \"execution\", \"plate\": \"/home/ts/.cache/openhcs/benchmark_datasets/CellProfiler_tutorials/data/3d_monolayer/images\"}", + "phase": "_execute_with_orchestrator", + "calls": 1, + "inclusive": 8.26425674976781, + "exclusive": 0.04989554965868592 + } + }, + "hooks_installed": [ + { + "module": "openhcs.core.aligned_image_payload", + "owner": "", + "method": "stack_image_payload_context", + "descriptor_kind": "function" + }, + { + "module": "openhcs.core.aligned_image_payload", + "owner": "", + "method": "unstack_image_payload_context", + "descriptor_kind": "function" + }, + { + "module": "openhcs.core.measurement_feature_queries", + "owner": "MeasurementFeatureValueIndex", + "method": "from_columnar_table_by_object", + "descriptor_kind": "classmethod" + }, + { + "module": "openhcs.core.virtual_workspace_metadata", + "owner": "AtomicMetadataWriter", + "method": "publish_source_projection_metadata", + "descriptor_kind": "function" + }, + { + "module": "openhcs.core.runtime_stack_cache", + "owner": "RuntimeImageStackCache", + "method": "get", + "descriptor_kind": "function" + }, + { + "module": "openhcs.core.runtime_stack_cache", + "owner": "RuntimeImageStackCache", + "method": "store", + "descriptor_kind": "function" + }, + { + "module": "openhcs.core.steps.function_outputs", + "owner": "", + "method": "finalize_function_step_outputs", + "descriptor_kind": "function" + }, + { + "module": "openhcs.core.steps.function_outputs", + "owner": "OpenHCSMetadataWriter", + "method": "finalize_completed_plate", + "descriptor_kind": "classmethod" + }, + { + "module": "openhcs.core.steps.function_outputs", + "owner": "RuntimeArtifactMetadataTarget", + "method": "reconciliation_targets", + "descriptor_kind": "function" + }, + { + "module": "openhcs.core.steps.function_runtime", + "owner": "FunctionCoreExecutor", + "method": "execute", + "descriptor_kind": "function" + }, + { + "module": "openhcs.core.steps.function_runtime", + "owner": "PatternGroupRuntime", + "method": "_load_input_stack", + "descriptor_kind": "function" + }, + { + "module": "openhcs.core.steps.function_runtime", + "owner": "PatternGroupRuntime", + "method": "_validate_and_unstack", + "descriptor_kind": "function" + }, + { + "module": "openhcs.core.steps.function_runtime", + "owner": "PatternGroupRuntime", + "method": "_save_outputs", + "descriptor_kind": "function" + }, + { + "module": "openhcs.processing.backends.lib_registry.unified_registry", + "owner": "RuntimeCallableInvocation", + "method": "call", + "descriptor_kind": "function" + }, + { + "module": "openhcs.core.orchestrator.analysis_consolidation", + "owner": "", + "method": "consolidate_analysis_outputs", + "descriptor_kind": "function" + }, + { + "module": "openhcs.core.orchestrator.worker_execution", + "owner": "", + "method": "execute_worker_lane", + "descriptor_kind": "function" + }, + { + "module": "openhcs.runtime.zmq_execution_server", + "owner": "ZMQExecutionServer", + "method": "_execute_with_orchestrator", + "descriptor_kind": "function" + }, + { + "module": "openhcs.runtime.zmq_execution_server", + "owner": "ZMQExecutionServer", + "method": "_initialize_orchestrator", + "descriptor_kind": "function" + }, + { + "module": "openhcs.runtime.zmq_execution_server", + "owner": "ZMQExecutionServer", + "method": "_export_runtime_observation", + "descriptor_kind": "function" + }, + { + "module": "openhcs.interop.cellprofiler.runtime.function_contract_execution", + "owner": "CellProfilerFunctionContractExecutor", + "method": "execute", + "descriptor_kind": "function" + }, + { + "module": "openhcs.interop.cellprofiler.runtime.measurement_execution_support", + "owner": "ObjectMeasurementOutputRecorder", + "method": "record", + "descriptor_kind": "function" + }, + { + "module": "openhcs.interop.cellprofiler.runtime.output_recording", + "owner": "CellProfilerOutputRecorder", + "method": "record_module_outputs", + "descriptor_kind": "classmethod" + }, + { + "module": "openhcs.interop.cellprofiler.runtime.module_execution", + "owner": "CellProfilerModuleExecutor", + "method": "__call__", + "descriptor_kind": "function" + }, + { + "module": "openhcs.interop.cellprofiler.runtime.module_execution", + "owner": "CellProfilerModuleExecutor", + "method": "_image_request", + "descriptor_kind": "function" + } + ], + "profiling_enabled": false, + "runtime_profiling_enabled": false, + "diagnostic_errors": [], + "captures": false, + "scope": "coarse same-run nested exclusive timing partition on the exact source revision recorded in this region. Diagnostic wrappers, no scientific or memory-observer substitutions. Not accepted performance comparison. Declared callable boundary includes filtering/decorated processing/metadata; not pure numerical kernels. Both existing profilers are disabled. These wrappers still add diagnostic overhead; no scaling to uninstrumented clocks or causal performance claims. Query boundary is nested under its actual parent and excluded from parent-exclusive elapsed." +} diff --git a/benchmark/results/perf_rejected_metadata_owner_20261003/baseline-observations.json b/benchmark/results/perf_rejected_metadata_owner_20261003/baseline-observations.json new file mode 100644 index 0000000000..37736f25f1 --- /dev/null +++ b/benchmark/results/perf_rejected_metadata_owner_20261003/baseline-observations.json @@ -0,0 +1,48 @@ +{ + "returncode": 0, + "diagnostic_admission": true, + "public_rows": [ + { + "case_name": "cp_tutorial_3d_monolayer", + "mode_name": "1w_1t", + "worker_count": "1", + "well_count": "1", + "compile_seconds": "1.5337145328521729", + "prepare_seconds": "0.0", + "execute_seconds": "8.276516675949097", + "total_seconds": "10.606972666922957", + "wells_per_second": "0.12082377637272465", + "successful_wells": "1", + "native_single_sample_execution_seconds": "", + "projected_native_execution_seconds": "", + "projected_execution_speedup": "", + "peak_memory_mb": "1692.34375", + "status": "success", + "memory_limit_mb": "", + "error_message": "", + "execution_route": "ordinary-zmq-outcomes-v1", + "server_lifecycle": "reused-per-sweep", + "run_input_sha256": "7f66dd478c9a56033495f056335a0eaadb9fd5facd953b504f0e1f8f7eaa57d5" + } + ], + "regions": [ + { + "path": "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/regions/region-1677824-140643152090816-0001.json", + "sha256": "d4cf4157156de4e7a41949e36ee4daed69665ea7b8c6e2ddf5b00613300b6e5a" + }, + { + "path": "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/regions/region-1677824-140643152090816-0002.json", + "sha256": "eda84c30eb19709e0fc37a35550a0e5a8e27e97ddd818e9296904203cd9e9e0b" + } + ], + "root_sequence_complete": true, + "actual_index_calls": 0, + "actual_declared_calls": 211, + "retained_json_bytes": 38057, + "generated_output_bytes": 18163301, + "public_log_bytes": 538, + "profiler_artifacts_absent": true, + "source_env_native_input_freeze": "PASS", + "science": "NOT_RUN: original full saved-output126file/schema/discrete/numerical/nativeinput witness separate gate. No exclusions or missing outputs waived.", + "scope": "One source-pinned whole ordinary3D Monolayer1w1t candidate falsification with24 unchanged coarse nominal hooks: inherited23 plus actual MeasurementFeatureValueIndex index classmethod. cProfile and runtime profiler OFF, no captures/percell hooks. Existing defaultOUTCOMES/memory observers/READY clocks unchanged. Same-thread nested exclusive clocks exclude query from its real ancestors; worker independent roots are not added to parent waits. Nearordinary diagnostic only; wrapper overhead remains, no scale factors/causal performance promotion. Full saved126file (6CSV120TIFF) science/native source witness independently required." +} diff --git a/benchmark/results/perf_rejected_metadata_owner_20261003/baseline-source-pins.json b/benchmark/results/perf_rejected_metadata_owner_20261003/baseline-source-pins.json new file mode 100644 index 0000000000..a3450e2f7c --- /dev/null +++ b/benchmark/results/perf_rejected_metadata_owner_20261003/baseline-source-pins.json @@ -0,0 +1,116 @@ +{ + "revision": "e8587bd7eb0c4aa283bc300c5eb9f2294f24890f", + "source": "/home/ts/code/projects/openhcs-shared-runtime-plumbing", + "physical_inputs": { + "dataset_path": { + "path": "/home/ts/.cache/openhcs/benchmark_datasets/CellProfiler_tutorials/data/3d_monolayer/images", + "files": { + "3d_monolayer_xy1_ch0.tif": "63114f614fec95664f718a39cddac58449f0edb5cc31b57584e4ba5b1f4994c7", + "3d_monolayer_xy1_ch1.tif": "a7d9abf632850875c22613c4b740fc01153cf60e9773c16d4a670a97b46e5751", + "3d_monolayer_xy1_ch2.tif": "191754bc7f43856223180483e2737ea93bab4d0cf98b1b2a4c27425e9908147d" + } + }, + "cppipe_path": { + "path": "/home/ts/.cache/openhcs/benchmark_datasets/CellProfiler_tutorials/data/3d_monolayer/3d_monolayer_final.cppipe", + "files": { + "3d_monolayer_final.cppipe": "9fcd24a1be8372b5c2e87637a055032c3362b9ad8729e361095f93d8bbe71838" + } + } + }, + "shared_dependency_heads": "b0004daf3223326ac78689ba7b2e68abc18ae298 external/ObjectState (v1.1.8)\n 84f322e46871de5ed47e7fd20976ad03e533c1c4 external/PolyStore (v0.2.19-34-g84f322e)\n 1e53d03d9f468322a1c085c8be29485fb139caf2 external/arraybridge (v0.3.6)\n 393a7e03003cdc56df9013f932ed4f26e632d77a external/metaclass-registry (v0.2.2)\n 792b03413331fdf107e369c924c257a2f0b16126 external/pycodify (v0.1.3)\n ad4948775ab81180a354d4b793d17ee5ddff3972 external/pyqt-reactive (v0.3.24-9-gad49487)\n 4e8f8bde5f750d9a50eacac80acd3806123addd8 external/python-introspect (v0.1.14-1-g4e8f8bd)\n 668edafcb5ee530a163377c936431ae1e8334e85 external/zmqruntime (v0.2.24-40-g668edaf)", + "native_binaries": { + "openhcs/core/_tabular_native.abi3.so": { + "path": "/home/ts/code/projects/openhcs-shared-runtime-plumbing/openhcs/core/_tabular_native.abi3.so", + "sha256": "2ce348417de70ad3f614962c82aed9c4977c32b3ba00e13531ecafb8c10d8d1d" + }, + "openhcs/processing/backends/cellprofiler/_granularity_native.abi3.so": { + "path": "/home/ts/code/projects/openhcs-shared-runtime-plumbing/openhcs/processing/backends/cellprofiler/_granularity_native.abi3.so", + "sha256": "6e45987a50d5c0588a8fb0b09a2232a63e72c122d6a3d583ae4d62830e3b4096" + } + }, + "python_binary": { + "path": "/home/ts/.local/share/uv/python/cpython-3.12.14-linux-x86_64-gnu/bin/python3.12", + "sha256": "edffa803e5c4d73a1357f7f2c6c9fd38e9693712b2c06793e6a5e5cc1090d03a" + }, + "installed_versions": { + "python": "3.12.14 (main, Sep 24 2026, 17:57:43) [Clang 22.1.3 ]", + "versions": { + "openhcs": "0.8.7", + "numpy": "2.5.3", + "scipy": "1.18.1", + "arraybridge": "0.3.6", + "polystore": "0.3.0", + "python-introspect": "0.1.15", + "metaclass-registry": "0.2.2", + "zmqruntime": "0.3.0" + } + }, + "installed_freeze_sha256": "b7e5bbb9b5171476dfeb1692378419bfa157bb620028e1b91c8969eef2498b41", + "site_sha256": "391dc438b0d9d253e3467674c19d37b2670d5d7197400aa45f3c251e84f948c0", + "ordinary_helper_sha256": "8a41db448a722d231777a90a3ae23091617c8ac1ba72cefcb91f72b2c7975554", + "driver_sha256": "73b30d0cc3174c04cb479a72e97fe094ef6ad9fcfdacbfb37e43fbaad53560c3", + "manifest_sha256": "4c302e136b427cb9968eef82d7ede4a6c5b65cbcb4f8e5490fd5125c2e7ab2a8", + "ledger_controller_sha256": "c140695473eadb961b245c24344acc79778904920ba3725945ec9235354fbb9b", + "command": [ + "/usr/bin/taskset", + "-c", + "5", + "/home/ts/code/projects/openhcs/.venv/bin/python", + "-c", + "import runpy,sys;from dataclasses import replace;import openhcs.runtime.zmq_config as configuration;configuration.OPENHCS_ZMQ_CONFIG=replace(configuration.OPENHCS_ZMQ_CONFIG,client_connect_timeout_seconds=180.0);sys.argv=sys.argv[1:];runpy.run_path(sys.argv[0],run_name='__main__')", + "/home/ts/code/projects/openhcs-shared-runtime-plumbing/scripts/benchmark_cppipe_well_throughput.py", + "--manifest", + "/home/ts/code/projects/openhcs-shared-runtime-plumbing/benchmark/manifests/official30_portable_axis1.json", + "--mode", + "1w_1t", + "--output-dir", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public", + "--case", + "cp_tutorial_3d_monolayer" + ], + "scope": "One source-pinned whole ordinary3D Monolayer1w1t candidate falsification with24 unchanged coarse nominal hooks: inherited23 plus actual MeasurementFeatureValueIndex index classmethod. cProfile and runtime profiler OFF, no captures/percell hooks. Existing defaultOUTCOMES/memory observers/READY clocks unchanged. Same-thread nested exclusive clocks exclude query from its real ancestors; worker independent roots are not added to parent waits. Nearordinary diagnostic only; wrapper overhead remains, no scale factors/causal performance promotion. Full saved126file (6CSV120TIFF) science/native source witness independently required.", + "original_full_freeze_path": "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/source-freeze.json", + "original_full_freeze_sha256": "55ee41e2e0f09553de9c2be7dab5beedf0f4f2baf7245f2778c2dcedc38a092e", + "actual_import_dependency_pins": { + "external/ObjectState": { + "head": "a01f8939b9bf4659502a33fe3febe62cab0f3c9a", + "status": "", + "full_tracked_source_sha256": "511b83d27f0c0cffe973cb16e0cfce016405250185000d909e41f6343472dca1" + }, + "external/python-introspect": { + "head": "ed1e4eb15f7a0bf8315274d3e47858fa2b4372bb", + "status": "", + "full_tracked_source_sha256": "74b3a98b0ed51d505b50e828c5096aaab8d019d18b7619e7dfdcb0f923a54f7d" + }, + "external/arraybridge": { + "head": "1e53d03d9f468322a1c085c8be29485fb139caf2", + "status": "", + "full_tracked_source_sha256": "cc3300a4462a89363003190d00228618c8bc33545d445ae72359c1fb7440a931" + }, + "external/metaclass-registry": { + "head": "393a7e03003cdc56df9013f932ed4f26e632d77a", + "status": "", + "full_tracked_source_sha256": "a660ae17d4e4c03f5298ff8c2a8183635b53bf24558be6ff69b435476461e6bc" + }, + "external/zmqruntime": { + "head": "668edafcb5ee530a163377c936431ae1e8334e85", + "status": "", + "full_tracked_source_sha256": "bd020f39e177c038aa31d4579090694aede119aee668029a039dba249d311ec7" + }, + "external/pycodify": { + "head": "792b03413331fdf107e369c924c257a2f0b16126", + "status": "", + "full_tracked_source_sha256": "66f24bee56cbccc5baa5b1347a0c27bd6c9a6cc13598f679adba9668f2b54f3a" + }, + "external/PolyStore": { + "head": "84f322e46871de5ed47e7fd20976ad03e533c1c4", + "status": "", + "full_tracked_source_sha256": "47d2c21a32560e9d22581017e569846fb17f4f88a82a8ade0352eabaedea738b" + }, + "external/pyqt-reactive": { + "head": "ad4948775ab81180a354d4b793d17ee5ddff3972", + "status": "", + "full_tracked_source_sha256": "968cc99264a04019b724c11b47d53976f0f1341c50c8a86366aa7d3ef1ffe6fd" + } + } +} diff --git a/benchmark/results/perf_rejected_metadata_owner_20261003/candidate-compile_only-region.json b/benchmark/results/perf_rejected_metadata_owner_20261003/candidate-compile_only-region.json new file mode 100644 index 0000000000..aef19eceaa --- /dev/null +++ b/benchmark/results/perf_rejected_metadata_owner_20261003/candidate-compile_only-region.json @@ -0,0 +1,178 @@ +{ + "pid": 1697815, + "thread": 139997494724288, + "region": "ZMQExecutionServer._execute_with_orchestrator", + "root_dimensions": "{\"case\": \"3d_monolayer_final\", \"compile_artifact_id\": null, \"execution_id\": \"f3a82019-5257-4583-940c-4dfd40925dfb\", \"kind\": \"compile_only\", \"plate\": \"/home/ts/.cache/openhcs/benchmark_datasets/CellProfiler_tutorials/data/3d_monolayer/images\"}", + "seconds": 1.2573879919946194, + "revision": "9eee98265c939859d49f0c60bd5b3a2168cb29fe", + "source": "/home/ts/code/projects/openhcs-shared-runtime-plumbing", + "stats": { + "ZMQExecutionServer._initialize_orchestrator": { + "owner": "ZMQExecutionServer._initialize_orchestrator", + "dimensions": "", + "phase": "_initialize_orchestrator", + "calls": 1, + "inclusive": 0.12586374813690782, + "exclusive": 0.12586374813690782 + }, + "ZMQExecutionServer._execute_with_orchestrator | {\"case\": \"3d_monolayer_final\", \"compile_artifact_id\": null, \"execution_id\": \"f3a82019-5257-4583-940c-4dfd40925dfb\", \"kind\": \"compile_only\", \"plate\": \"/home/ts/.cache/openhcs/benchmark_datasets/CellProfiler_tutorials/data/3d_monolayer/images\"}": { + "owner": "ZMQExecutionServer._execute_with_orchestrator", + "dimensions": "{\"case\": \"3d_monolayer_final\", \"compile_artifact_id\": null, \"execution_id\": \"f3a82019-5257-4583-940c-4dfd40925dfb\", \"kind\": \"compile_only\", \"plate\": \"/home/ts/.cache/openhcs/benchmark_datasets/CellProfiler_tutorials/data/3d_monolayer/images\"}", + "phase": "_execute_with_orchestrator", + "calls": 1, + "inclusive": 1.2573879919946194, + "exclusive": 1.1315242438577116 + } + }, + "hooks_installed": [ + { + "module": "openhcs.core.aligned_image_payload", + "owner": "", + "method": "stack_image_payload_context", + "descriptor_kind": "function" + }, + { + "module": "openhcs.core.aligned_image_payload", + "owner": "", + "method": "unstack_image_payload_context", + "descriptor_kind": "function" + }, + { + "module": "openhcs.core.measurement_feature_queries", + "owner": "MeasurementFeatureValueIndex", + "method": "from_columnar_table_by_object", + "descriptor_kind": "classmethod" + }, + { + "module": "openhcs.core.virtual_workspace_metadata", + "owner": "AtomicMetadataWriter", + "method": "publish_source_projection_metadata", + "descriptor_kind": "function" + }, + { + "module": "openhcs.core.runtime_stack_cache", + "owner": "RuntimeImageStackCache", + "method": "get", + "descriptor_kind": "function" + }, + { + "module": "openhcs.core.runtime_stack_cache", + "owner": "RuntimeImageStackCache", + "method": "store", + "descriptor_kind": "function" + }, + { + "module": "openhcs.core.steps.function_outputs", + "owner": "", + "method": "finalize_function_step_outputs", + "descriptor_kind": "function" + }, + { + "module": "openhcs.core.steps.function_outputs", + "owner": "OpenHCSMetadataWriter", + "method": "finalize_completed_plate", + "descriptor_kind": "classmethod" + }, + { + "module": "openhcs.core.steps.function_outputs", + "owner": "RuntimeArtifactMetadataTarget", + "method": "reconciliation_targets", + "descriptor_kind": "function" + }, + { + "module": "openhcs.core.steps.function_runtime", + "owner": "FunctionCoreExecutor", + "method": "execute", + "descriptor_kind": "function" + }, + { + "module": "openhcs.core.steps.function_runtime", + "owner": "PatternGroupRuntime", + "method": "_load_input_stack", + "descriptor_kind": "function" + }, + { + "module": "openhcs.core.steps.function_runtime", + "owner": "PatternGroupRuntime", + "method": "_validate_and_unstack", + "descriptor_kind": "function" + }, + { + "module": "openhcs.core.steps.function_runtime", + "owner": "PatternGroupRuntime", + "method": "_save_outputs", + "descriptor_kind": "function" + }, + { + "module": "openhcs.processing.backends.lib_registry.unified_registry", + "owner": "RuntimeCallableInvocation", + "method": "call", + "descriptor_kind": "function" + }, + { + "module": "openhcs.core.orchestrator.analysis_consolidation", + "owner": "", + "method": "consolidate_analysis_outputs", + "descriptor_kind": "function" + }, + { + "module": "openhcs.core.orchestrator.worker_execution", + "owner": "", + "method": "execute_worker_lane", + "descriptor_kind": "function" + }, + { + "module": "openhcs.runtime.zmq_execution_server", + "owner": "ZMQExecutionServer", + "method": "_execute_with_orchestrator", + "descriptor_kind": "function" + }, + { + "module": "openhcs.runtime.zmq_execution_server", + "owner": "ZMQExecutionServer", + "method": "_initialize_orchestrator", + "descriptor_kind": "function" + }, + { + "module": "openhcs.runtime.zmq_execution_server", + "owner": "ZMQExecutionServer", + "method": "_export_runtime_observation", + "descriptor_kind": "function" + }, + { + "module": "openhcs.interop.cellprofiler.runtime.function_contract_execution", + "owner": "CellProfilerFunctionContractExecutor", + "method": "execute", + "descriptor_kind": "function" + }, + { + "module": "openhcs.interop.cellprofiler.runtime.measurement_execution_support", + "owner": "ObjectMeasurementOutputRecorder", + "method": "record", + "descriptor_kind": "function" + }, + { + "module": "openhcs.interop.cellprofiler.runtime.output_recording", + "owner": "CellProfilerOutputRecorder", + "method": "record_module_outputs", + "descriptor_kind": "classmethod" + }, + { + "module": "openhcs.interop.cellprofiler.runtime.module_execution", + "owner": "CellProfilerModuleExecutor", + "method": "__call__", + "descriptor_kind": "function" + }, + { + "module": "openhcs.interop.cellprofiler.runtime.module_execution", + "owner": "CellProfilerModuleExecutor", + "method": "_image_request", + "descriptor_kind": "function" + } + ], + "profiling_enabled": false, + "runtime_profiling_enabled": false, + "diagnostic_errors": [], + "captures": false, + "scope": "coarse same-run nested exclusive timing partition on the exact source revision recorded in this region. Diagnostic wrappers, no scientific or memory-observer substitutions. Not accepted performance comparison. Declared callable boundary includes filtering/decorated processing/metadata; not pure numerical kernels. Both existing profilers are disabled. These wrappers still add diagnostic overhead; no scaling to uninstrumented clocks or causal performance claims. Query boundary is nested under its actual parent and excluded from parent-exclusive elapsed." +} diff --git a/benchmark/results/perf_rejected_metadata_owner_20261003/candidate-execution-region.json b/benchmark/results/perf_rejected_metadata_owner_20261003/candidate-execution-region.json new file mode 100644 index 0000000000..b76eb63690 --- /dev/null +++ b/benchmark/results/perf_rejected_metadata_owner_20261003/candidate-execution-region.json @@ -0,0 +1,714 @@ +{ + "pid": 1697815, + "thread": 139997494724288, + "region": "ZMQExecutionServer._execute_with_orchestrator", + "root_dimensions": "{\"case\": \"3d_monolayer_final\", \"compile_artifact_id\": \"f3a82019-5257-4583-940c-4dfd40925dfb\", \"execution_id\": \"51ebb3de-fae0-4cd1-80bc-c03eb3ecf311\", \"kind\": \"execution\", \"plate\": \"/home/ts/.cache/openhcs/benchmark_datasets/CellProfiler_tutorials/data/3d_monolayer/images\"}", + "seconds": 8.966167135164142, + "revision": "9eee98265c939859d49f0c60bd5b3a2168cb29fe", + "source": "/home/ts/code/projects/openhcs-shared-runtime-plumbing", + "stats": { + "ZMQExecutionServer._initialize_orchestrator": { + "owner": "ZMQExecutionServer._initialize_orchestrator", + "dimensions": "", + "phase": "_initialize_orchestrator", + "calls": 1, + "inclusive": 0.08220752514898777, + "exclusive": 0.08220752514898777 + }, + "RuntimeImageStackCache.get": { + "owner": "RuntimeImageStackCache.get", + "dimensions": "", + "phase": "get", + "calls": 32, + "inclusive": 0.00034267501905560493, + "exclusive": 0.00034267501905560493 + }, + "stack_image_payload_context": { + "owner": "stack_image_payload_context", + "dimensions": "", + "phase": "stack_image_payload_context", + "calls": 28, + "inclusive": 0.04168135765939951, + "exclusive": 0.04168135765939951 + }, + "PatternGroupRuntime._load_input_stack": { + "owner": "PatternGroupRuntime._load_input_stack", + "dimensions": "", + "phase": "_load_input_stack", + "calls": 32, + "inclusive": 0.8401167313568294, + "exclusive": 0.8310769814997911 + }, + "CellProfilerModuleExecutor._image_request": { + "owner": "CellProfilerModuleExecutor._image_request", + "dimensions": "", + "phase": "_image_request", + "calls": 30, + "inclusive": 0.3633091449737549, + "exclusive": 0.3633091449737549 + }, + "RuntimeCallableInvocation.call | function=openhcs.processing.backends.cellprofiler.intensity.rescale_intensity;view=1": { + "owner": "RuntimeCallableInvocation.call", + "dimensions": "function=openhcs.processing.backends.cellprofiler.intensity.rescale_intensity;view=1", + "phase": "declared_callable_boundary", + "calls": 2, + "inclusive": 0.029291327111423016, + "exclusive": 0.029291327111423016 + }, + "CellProfilerFunctionContractExecutor.execute | function=openhcs.processing.backends.cellprofiler.intensity.rescale_intensity": { + "owner": "CellProfilerFunctionContractExecutor.execute", + "dimensions": "function=openhcs.processing.backends.cellprofiler.intensity.rescale_intensity", + "phase": "execute", + "calls": 2, + "inclusive": 0.030176815576851368, + "exclusive": 0.0008854884654283524 + }, + "CellProfilerOutputRecorder.record_module_outputs": { + "owner": "CellProfilerOutputRecorder.record_module_outputs", + "dimensions": "", + "phase": "record_module_outputs", + "calls": 26, + "inclusive": 0.4135434296913445, + "exclusive": 0.4135434296913445 + }, + "CellProfilerModuleExecutor.__call__": { + "owner": "CellProfilerModuleExecutor.__call__", + "dimensions": "", + "phase": "__call__", + "calls": 32, + "inclusive": 5.029390189331025, + "exclusive": 0.22105292789638042 + }, + "FunctionCoreExecutor.execute | function=rescale_intensity": { + "owner": "FunctionCoreExecutor.execute", + "dimensions": "function=rescale_intensity", + "phase": "execute", + "calls": 2, + "inclusive": 0.14369932608678937, + "exclusive": 0.0003861561417579651 + }, + "PatternGroupRuntime._validate_and_unstack": { + "owner": "PatternGroupRuntime._validate_and_unstack", + "dimensions": "", + "phase": "_validate_and_unstack", + "calls": 28, + "inclusive": 0.2781928963959217, + "exclusive": 0.24520861357450485 + }, + "RuntimeImageStackCache.store": { + "owner": "RuntimeImageStackCache.store", + "dimensions": "", + "phase": "store", + "calls": 28, + "inclusive": 0.00023655686527490616, + "exclusive": 0.00023655686527490616 + }, + "PatternGroupRuntime._save_outputs": { + "owner": "PatternGroupRuntime._save_outputs", + "dimensions": "", + "phase": "_save_outputs", + "calls": 28, + "inclusive": 0.6775184879079461, + "exclusive": 0.6772819310426712 + }, + "finalize_function_step_outputs": { + "owner": "finalize_function_step_outputs", + "dimensions": "", + "phase": "finalize_function_step_outputs", + "calls": 30, + "inclusive": 0.7491098740138113, + "exclusive": 0.48047462571412325 + }, + "RuntimeCallableInvocation.call | function=openhcs.processing.backends.cellprofiler.image_geometry.resize_volumetric;view=1": { + "owner": "RuntimeCallableInvocation.call", + "dimensions": "function=openhcs.processing.backends.cellprofiler.image_geometry.resize_volumetric;view=1", + "phase": "declared_callable_boundary", + "calls": 3, + "inclusive": 0.12918777717277408, + "exclusive": 0.12918777717277408 + }, + "CellProfilerFunctionContractExecutor.execute | function=openhcs.processing.backends.cellprofiler.image_geometry.resize_volumetric": { + "owner": "CellProfilerFunctionContractExecutor.execute", + "dimensions": "function=openhcs.processing.backends.cellprofiler.image_geometry.resize_volumetric", + "phase": "execute", + "calls": 3, + "inclusive": 0.1298334114253521, + "exclusive": 0.0006456342525780201 + }, + "FunctionCoreExecutor.execute | function=resize_volumetric": { + "owner": "FunctionCoreExecutor.execute", + "dimensions": "function=resize_volumetric", + "phase": "execute", + "calls": 3, + "inclusive": 0.19873877195641398, + "exclusive": 0.0007655806839466095 + }, + "RuntimeCallableInvocation.call | function=openhcs.processing.backends.cellprofiler.median_filter.medianfilter;view=1": { + "owner": "RuntimeCallableInvocation.call", + "dimensions": "function=openhcs.processing.backends.cellprofiler.median_filter.medianfilter;view=1", + "phase": "declared_callable_boundary", + "calls": 1, + "inclusive": 0.5357745480723679, + "exclusive": 0.5357745480723679 + }, + "CellProfilerFunctionContractExecutor.execute | function=openhcs.processing.backends.cellprofiler.median_filter.medianfilter": { + "owner": "CellProfilerFunctionContractExecutor.execute", + "dimensions": "function=openhcs.processing.backends.cellprofiler.median_filter.medianfilter", + "phase": "execute", + "calls": 1, + "inclusive": 0.5364011479541659, + "exclusive": 0.000626599881798029 + }, + "FunctionCoreExecutor.execute | function=medianfilter": { + "owner": "FunctionCoreExecutor.execute", + "dimensions": "function=medianfilter", + "phase": "execute", + "calls": 1, + "inclusive": 0.5587063231505454, + "exclusive": 0.0010953620076179504 + }, + "RuntimeCallableInvocation.call | function=openhcs.processing.backends.cellprofiler.thresholding.threshold;view=1": { + "owner": "RuntimeCallableInvocation.call", + "dimensions": "function=openhcs.processing.backends.cellprofiler.thresholding.threshold;view=1", + "phase": "declared_callable_boundary", + "calls": 3, + "inclusive": 0.48295382084324956, + "exclusive": 0.48295382084324956 + }, + "CellProfilerFunctionContractExecutor.execute | function=openhcs.processing.backends.cellprofiler.thresholding.threshold": { + "owner": "CellProfilerFunctionContractExecutor.execute", + "dimensions": "function=openhcs.processing.backends.cellprofiler.thresholding.threshold", + "phase": "execute", + "calls": 3, + "inclusive": 0.4840805730782449, + "exclusive": 0.0011267522349953651 + }, + "FunctionCoreExecutor.execute | function=threshold": { + "owner": "FunctionCoreExecutor.execute", + "dimensions": "function=threshold", + "phase": "execute", + "calls": 3, + "inclusive": 0.6010923348367214, + "exclusive": 0.003914329688996077 + }, + "RuntimeCallableInvocation.call | function=openhcs.processing.backends.cellprofiler.morphology.remove_holes_3d;view=1": { + "owner": "RuntimeCallableInvocation.call", + "dimensions": "function=openhcs.processing.backends.cellprofiler.morphology.remove_holes_3d;view=1", + "phase": "declared_callable_boundary", + "calls": 2, + "inclusive": 0.10115541890263557, + "exclusive": 0.10115541890263557 + }, + "CellProfilerFunctionContractExecutor.execute | function=openhcs.processing.backends.cellprofiler.morphology.remove_holes_3d": { + "owner": "CellProfilerFunctionContractExecutor.execute", + "dimensions": "function=openhcs.processing.backends.cellprofiler.morphology.remove_holes_3d", + "phase": "execute", + "calls": 2, + "inclusive": 0.10138663509860635, + "exclusive": 0.0002312161959707737 + }, + "FunctionCoreExecutor.execute | function=remove_holes_3d": { + "owner": "FunctionCoreExecutor.execute", + "dimensions": "function=remove_holes_3d", + "phase": "execute", + "calls": 2, + "inclusive": 0.10958591010421515, + "exclusive": 0.0005047591403126717 + }, + "RuntimeCallableInvocation.call | function=openhcs.processing.backends.cellprofiler.watershed.watershed_cellprofiler4;view=1": { + "owner": "RuntimeCallableInvocation.call", + "dimensions": "function=openhcs.processing.backends.cellprofiler.watershed.watershed_cellprofiler4;view=1", + "phase": "declared_callable_boundary", + "calls": 2, + "inclusive": 0.535675251390785, + "exclusive": 0.535675251390785 + }, + "CellProfilerFunctionContractExecutor.execute | function=openhcs.processing.backends.cellprofiler.watershed.watershed_cellprofiler4": { + "owner": "CellProfilerFunctionContractExecutor.execute", + "dimensions": "function=openhcs.processing.backends.cellprofiler.watershed.watershed_cellprofiler4", + "phase": "execute", + "calls": 2, + "inclusive": 0.5362195959314704, + "exclusive": 0.0005443445406854153 + }, + "FunctionCoreExecutor.execute | function=watershed_cellprofiler4": { + "owner": "FunctionCoreExecutor.execute", + "dimensions": "function=watershed_cellprofiler4", + "phase": "execute", + "calls": 2, + "inclusive": 0.5789050222374499, + "exclusive": 0.002408776432275772 + }, + "RuntimeCallableInvocation.call | function=openhcs.processing.backends.cellprofiler.morphology.resize_objects_3d;view=1": { + "owner": "RuntimeCallableInvocation.call", + "dimensions": "function=openhcs.processing.backends.cellprofiler.morphology.resize_objects_3d;view=1", + "phase": "declared_callable_boundary", + "calls": 2, + "inclusive": 0.10566109092906117, + "exclusive": 0.10566109092906117 + }, + "CellProfilerFunctionContractExecutor.execute | function=openhcs.processing.backends.cellprofiler.morphology.resize_objects_3d": { + "owner": "CellProfilerFunctionContractExecutor.execute", + "dimensions": "function=openhcs.processing.backends.cellprofiler.morphology.resize_objects_3d", + "phase": "execute", + "calls": 2, + "inclusive": 0.10626277374103665, + "exclusive": 0.0006016828119754791 + }, + "FunctionCoreExecutor.execute | function=resize_objects_3d": { + "owner": "FunctionCoreExecutor.execute", + "dimensions": "function=resize_objects_3d", + "phase": "execute", + "calls": 2, + "inclusive": 0.14153605420142412, + "exclusive": 0.0009483452886343002 + }, + "RuntimeCallableInvocation.call | function=openhcs.processing.backends.cellprofiler.morphology.erode_objects;view=1": { + "owner": "RuntimeCallableInvocation.call", + "dimensions": "function=openhcs.processing.backends.cellprofiler.morphology.erode_objects;view=1", + "phase": "declared_callable_boundary", + "calls": 1, + "inclusive": 0.0506745669990778, + "exclusive": 0.0506745669990778 + }, + "CellProfilerFunctionContractExecutor.execute | function=openhcs.processing.backends.cellprofiler.morphology.erode_objects": { + "owner": "CellProfilerFunctionContractExecutor.execute", + "dimensions": "function=openhcs.processing.backends.cellprofiler.morphology.erode_objects", + "phase": "execute", + "calls": 1, + "inclusive": 0.051196648739278316, + "exclusive": 0.0005220817402005196 + }, + "FunctionCoreExecutor.execute | function=erode_objects": { + "owner": "FunctionCoreExecutor.execute", + "dimensions": "function=erode_objects", + "phase": "execute", + "calls": 1, + "inclusive": 0.06009216699749231, + "exclusive": 0.0004721791483461857 + }, + "RuntimeCallableInvocation.call | function=openhcs.processing.backends.cellprofiler.object_images.convert_objects_to_image;view=1": { + "owner": "RuntimeCallableInvocation.call", + "dimensions": "function=openhcs.processing.backends.cellprofiler.object_images.convert_objects_to_image;view=1", + "phase": "declared_callable_boundary", + "calls": 3, + "inclusive": 0.007585550658404827, + "exclusive": 0.007585550658404827 + }, + "CellProfilerFunctionContractExecutor.execute | function=openhcs.processing.backends.cellprofiler.object_images.convert_objects_to_image": { + "owner": "CellProfilerFunctionContractExecutor.execute", + "dimensions": "function=openhcs.processing.backends.cellprofiler.object_images.convert_objects_to_image", + "phase": "execute", + "calls": 3, + "inclusive": 0.008365179877728224, + "exclusive": 0.0007796292193233967 + }, + "FunctionCoreExecutor.execute | function=convert_objects_to_image": { + "owner": "FunctionCoreExecutor.execute", + "dimensions": "function=convert_objects_to_image", + "phase": "execute", + "calls": 3, + "inclusive": 0.04295764910057187, + "exclusive": 0.0015249010175466537 + }, + "RuntimeCallableInvocation.call | function=openhcs.processing.backends.cellprofiler.image_math.image_math;view=1": { + "owner": "RuntimeCallableInvocation.call", + "dimensions": "function=openhcs.processing.backends.cellprofiler.image_math.image_math;view=1", + "phase": "declared_callable_boundary", + "calls": 120, + "inclusive": 0.056871647015213966, + "exclusive": 0.056871647015213966 + }, + "CellProfilerFunctionContractExecutor.execute | function=openhcs.processing.backends.cellprofiler.image_math.image_math": { + "owner": "CellProfilerFunctionContractExecutor.execute", + "dimensions": "function=openhcs.processing.backends.cellprofiler.image_math.image_math", + "phase": "execute", + "calls": 2, + "inclusive": 0.0808364930562675, + "exclusive": 0.023964846041053534 + }, + "FunctionCoreExecutor.execute | function=image_math": { + "owner": "FunctionCoreExecutor.execute", + "dimensions": "function=image_math", + "phase": "execute", + "calls": 2, + "inclusive": 0.35451433481648564, + "exclusive": 0.00045528681948781013 + }, + "RuntimeCallableInvocation.call | function=openhcs.processing.backends.cellprofiler.morphology.closing;view=1": { + "owner": "RuntimeCallableInvocation.call", + "dimensions": "function=openhcs.processing.backends.cellprofiler.morphology.closing;view=1", + "phase": "declared_callable_boundary", + "calls": 1, + "inclusive": 0.2598985880613327, + "exclusive": 0.2598985880613327 + }, + "CellProfilerFunctionContractExecutor.execute | function=openhcs.processing.backends.cellprofiler.morphology.closing": { + "owner": "CellProfilerFunctionContractExecutor.execute", + "dimensions": "function=openhcs.processing.backends.cellprofiler.morphology.closing", + "phase": "execute", + "calls": 1, + "inclusive": 0.2600078550167382, + "exclusive": 0.00010926695540547371 + }, + "FunctionCoreExecutor.execute | function=closing": { + "owner": "FunctionCoreExecutor.execute", + "dimensions": "function=closing", + "phase": "execute", + "calls": 1, + "inclusive": 0.2873692591674626, + "exclusive": 0.0002643684856593609 + }, + "RuntimeCallableInvocation.call | function=openhcs.processing.backends.cellprofiler.image_geometry.mask_image;view=1": { + "owner": "RuntimeCallableInvocation.call", + "dimensions": "function=openhcs.processing.backends.cellprofiler.image_geometry.mask_image;view=1", + "phase": "declared_callable_boundary", + "calls": 60, + "inclusive": 0.013158110901713371, + "exclusive": 0.013158110901713371 + }, + "CellProfilerFunctionContractExecutor.execute | function=openhcs.processing.backends.cellprofiler.image_geometry.mask_image": { + "owner": "CellProfilerFunctionContractExecutor.execute", + "dimensions": "function=openhcs.processing.backends.cellprofiler.image_geometry.mask_image", + "phase": "execute", + "calls": 1, + "inclusive": 0.03377221338450909, + "exclusive": 0.020614102482795715 + }, + "FunctionCoreExecutor.execute | function=mask_image": { + "owner": "FunctionCoreExecutor.execute", + "dimensions": "function=mask_image", + "phase": "execute", + "calls": 1, + "inclusive": 0.06323254993185401, + "exclusive": 0.00040600355714559555 + }, + "RuntimeCallableInvocation.call | function=openhcs.processing.backends.cellprofiler.morphology.erode_image;view=1": { + "owner": "RuntimeCallableInvocation.call", + "dimensions": "function=openhcs.processing.backends.cellprofiler.morphology.erode_image;view=1", + "phase": "declared_callable_boundary", + "calls": 1, + "inclusive": 0.03734732512384653, + "exclusive": 0.03734732512384653 + }, + "CellProfilerFunctionContractExecutor.execute | function=openhcs.processing.backends.cellprofiler.morphology.erode_image": { + "owner": "CellProfilerFunctionContractExecutor.execute", + "dimensions": "function=openhcs.processing.backends.cellprofiler.morphology.erode_image", + "phase": "execute", + "calls": 1, + "inclusive": 0.037452553398907185, + "exclusive": 0.00010522827506065369 + }, + "FunctionCoreExecutor.execute | function=erode_image": { + "owner": "FunctionCoreExecutor.execute", + "dimensions": "function=erode_image", + "phase": "execute", + "calls": 1, + "inclusive": 0.04374082200229168, + "exclusive": 0.0002591479569673538 + }, + "RuntimeCallableInvocation.call | function=openhcs.processing.backends.cellprofiler.intensity.measure_object_intensity;view=1": { + "owner": "RuntimeCallableInvocation.call", + "dimensions": "function=openhcs.processing.backends.cellprofiler.intensity.measure_object_intensity;view=1", + "phase": "declared_callable_boundary", + "calls": 4, + "inclusive": 0.8341215569525957, + "exclusive": 0.8341215569525957 + }, + "CellProfilerFunctionContractExecutor.execute | function=openhcs.processing.backends.cellprofiler.intensity.measure_object_intensity": { + "owner": "CellProfilerFunctionContractExecutor.execute", + "dimensions": "function=openhcs.processing.backends.cellprofiler.intensity.measure_object_intensity", + "phase": "execute", + "calls": 4, + "inclusive": 0.834825670812279, + "exclusive": 0.0007041138596832752 + }, + "ObjectMeasurementOutputRecorder.record": { + "owner": "ObjectMeasurementOutputRecorder.record", + "dimensions": "", + "phase": "record", + "calls": 6, + "inclusive": 0.0037249731831252575, + "exclusive": 0.0037249731831252575 + }, + "FunctionCoreExecutor.execute | function=measure_object_intensity": { + "owner": "FunctionCoreExecutor.execute", + "dimensions": "function=measure_object_intensity", + "phase": "execute", + "calls": 4, + "inclusive": 1.0454286388121545, + "exclusive": 0.004520548973232508 + }, + "RuntimeCallableInvocation.call | function=openhcs.processing.backends.cellprofiler.shape.measure_object_size_shape;view=1": { + "owner": "RuntimeCallableInvocation.call", + "dimensions": "function=openhcs.processing.backends.cellprofiler.shape.measure_object_size_shape;view=1", + "phase": "declared_callable_boundary", + "calls": 2, + "inclusive": 0.5032332427799702, + "exclusive": 0.5032332427799702 + }, + "CellProfilerFunctionContractExecutor.execute | function=openhcs.processing.backends.cellprofiler.shape.measure_object_size_shape": { + "owner": "CellProfilerFunctionContractExecutor.execute", + "dimensions": "function=openhcs.processing.backends.cellprofiler.shape.measure_object_size_shape", + "phase": "execute", + "calls": 2, + "inclusive": 0.5039996360428631, + "exclusive": 0.0007663932628929615 + }, + "FunctionCoreExecutor.execute | function=measure_object_size_shape": { + "owner": "FunctionCoreExecutor.execute", + "dimensions": "function=measure_object_size_shape", + "phase": "execute", + "calls": 2, + "inclusive": 0.5173229603096843, + "exclusive": 0.002118128351867199 + }, + "RuntimeCallableInvocation.call | function=openhcs.processing.backends.cellprofiler.outlines.overlay_objects;view=1": { + "owner": "RuntimeCallableInvocation.call", + "dimensions": "function=openhcs.processing.backends.cellprofiler.outlines.overlay_objects;view=1", + "phase": "declared_callable_boundary", + "calls": 2, + "inclusive": 0.2927272063679993, + "exclusive": 0.2927272063679993 + }, + "CellProfilerFunctionContractExecutor.execute | function=openhcs.processing.backends.cellprofiler.outlines.overlay_objects": { + "owner": "CellProfilerFunctionContractExecutor.execute", + "dimensions": "function=openhcs.processing.backends.cellprofiler.outlines.overlay_objects", + "phase": "execute", + "calls": 2, + "inclusive": 0.2929425104521215, + "exclusive": 0.00021530408412218094 + }, + "FunctionCoreExecutor.execute | function=overlay_objects": { + "owner": "FunctionCoreExecutor.execute", + "dimensions": "function=overlay_objects", + "phase": "execute", + "calls": 2, + "inclusive": 0.3159721801057458, + "exclusive": 0.013460240792483091 + }, + "RuntimeCallableInvocation.call | function=openhcs.processing.backends.cellprofiler.save_images.save_images;view=1": { + "owner": "RuntimeCallableInvocation.call", + "dimensions": "function=openhcs.processing.backends.cellprofiler.save_images.save_images;view=1", + "phase": "declared_callable_boundary", + "calls": 2, + "inclusive": 0.0001816130243241787, + "exclusive": 0.0001816130243241787 + }, + "FunctionCoreExecutor.execute | function=save_images": { + "owner": "FunctionCoreExecutor.execute", + "dimensions": "function=save_images", + "phase": "execute", + "calls": 2, + "inclusive": 0.17626022081822157, + "exclusive": 0.1760786077938974 + }, + "AtomicMetadataWriter.publish_source_projection_metadata": { + "owner": "AtomicMetadataWriter.publish_source_projection_metadata", + "dimensions": "", + "phase": "publish_source_projection_metadata", + "calls": 5, + "inclusive": 0.5068132942542434, + "exclusive": 0.5068132942542434 + }, + "execute_worker_lane | {\"execution_id\": \"51ebb3de-fae0-4cd1-80bc-c03eb3ecf311\", \"kind\": \"worker_lane\", \"plate\": \"/home/ts/.cache/openhcs/benchmark_datasets/CellProfiler_tutorials/data/3d_monolayer/images\", \"worker_slot\": \"worker_0\"}": { + "owner": "execute_worker_lane", + "dimensions": "{\"execution_id\": \"51ebb3de-fae0-4cd1-80bc-c03eb3ecf311\", \"kind\": \"worker_lane\", \"plate\": \"/home/ts/.cache/openhcs/benchmark_datasets/CellProfiler_tutorials/data/3d_monolayer/images\", \"worker_slot\": \"worker_0\"}", + "phase": "execute_worker_lane", + "calls": 1, + "inclusive": 8.292205615900457, + "exclusive": 0.5081131015904248 + }, + "consolidate_analysis_outputs": { + "owner": "consolidate_analysis_outputs", + "dimensions": "", + "phase": "consolidate_analysis_outputs", + "calls": 1, + "inclusive": 1.1913012713193893e-05, + "exclusive": 1.1913012713193893e-05 + }, + "RuntimeArtifactMetadataTarget.reconciliation_targets": { + "owner": "RuntimeArtifactMetadataTarget.reconciliation_targets", + "dimensions": "", + "phase": "reconciliation_targets", + "calls": 1, + "inclusive": 0.2939795549027622, + "exclusive": 0.2939795549027622 + }, + "OpenHCSMetadataWriter.finalize_completed_plate": { + "owner": "OpenHCSMetadataWriter.finalize_completed_plate", + "dimensions": "", + "phase": "finalize_completed_plate", + "calls": 1, + "inclusive": 0.5114067010581493, + "exclusive": 0.007927724625915289 + }, + "ZMQExecutionServer._export_runtime_observation": { + "owner": "ZMQExecutionServer._export_runtime_observation", + "dimensions": "", + "phase": "_export_runtime_observation", + "calls": 1, + "inclusive": 0.010043779853731394, + "exclusive": 0.010043779853731394 + }, + "ZMQExecutionServer._execute_with_orchestrator | {\"case\": \"3d_monolayer_final\", \"compile_artifact_id\": \"f3a82019-5257-4583-940c-4dfd40925dfb\", \"execution_id\": \"51ebb3de-fae0-4cd1-80bc-c03eb3ecf311\", \"kind\": \"execution\", \"plate\": \"/home/ts/.cache/openhcs/benchmark_datasets/CellProfiler_tutorials/data/3d_monolayer/images\"}": { + "owner": "ZMQExecutionServer._execute_with_orchestrator", + "dimensions": "{\"case\": \"3d_monolayer_final\", \"compile_artifact_id\": \"f3a82019-5257-4583-940c-4dfd40925dfb\", \"execution_id\": \"51ebb3de-fae0-4cd1-80bc-c03eb3ecf311\", \"kind\": \"execution\", \"plate\": \"/home/ts/.cache/openhcs/benchmark_datasets/CellProfiler_tutorials/data/3d_monolayer/images\"}", + "phase": "_execute_with_orchestrator", + "calls": 1, + "inclusive": 8.966167135164142, + "exclusive": 0.041612975765019655 + } + }, + "hooks_installed": [ + { + "module": "openhcs.core.aligned_image_payload", + "owner": "", + "method": "stack_image_payload_context", + "descriptor_kind": "function" + }, + { + "module": "openhcs.core.aligned_image_payload", + "owner": "", + "method": "unstack_image_payload_context", + "descriptor_kind": "function" + }, + { + "module": "openhcs.core.measurement_feature_queries", + "owner": "MeasurementFeatureValueIndex", + "method": "from_columnar_table_by_object", + "descriptor_kind": "classmethod" + }, + { + "module": "openhcs.core.virtual_workspace_metadata", + "owner": "AtomicMetadataWriter", + "method": "publish_source_projection_metadata", + "descriptor_kind": "function" + }, + { + "module": "openhcs.core.runtime_stack_cache", + "owner": "RuntimeImageStackCache", + "method": "get", + "descriptor_kind": "function" + }, + { + "module": "openhcs.core.runtime_stack_cache", + "owner": "RuntimeImageStackCache", + "method": "store", + "descriptor_kind": "function" + }, + { + "module": "openhcs.core.steps.function_outputs", + "owner": "", + "method": "finalize_function_step_outputs", + "descriptor_kind": "function" + }, + { + "module": "openhcs.core.steps.function_outputs", + "owner": "OpenHCSMetadataWriter", + "method": "finalize_completed_plate", + "descriptor_kind": "classmethod" + }, + { + "module": "openhcs.core.steps.function_outputs", + "owner": "RuntimeArtifactMetadataTarget", + "method": "reconciliation_targets", + "descriptor_kind": "function" + }, + { + "module": "openhcs.core.steps.function_runtime", + "owner": "FunctionCoreExecutor", + "method": "execute", + "descriptor_kind": "function" + }, + { + "module": "openhcs.core.steps.function_runtime", + "owner": "PatternGroupRuntime", + "method": "_load_input_stack", + "descriptor_kind": "function" + }, + { + "module": "openhcs.core.steps.function_runtime", + "owner": "PatternGroupRuntime", + "method": "_validate_and_unstack", + "descriptor_kind": "function" + }, + { + "module": "openhcs.core.steps.function_runtime", + "owner": "PatternGroupRuntime", + "method": "_save_outputs", + "descriptor_kind": "function" + }, + { + "module": "openhcs.processing.backends.lib_registry.unified_registry", + "owner": "RuntimeCallableInvocation", + "method": "call", + "descriptor_kind": "function" + }, + { + "module": "openhcs.core.orchestrator.analysis_consolidation", + "owner": "", + "method": "consolidate_analysis_outputs", + "descriptor_kind": "function" + }, + { + "module": "openhcs.core.orchestrator.worker_execution", + "owner": "", + "method": "execute_worker_lane", + "descriptor_kind": "function" + }, + { + "module": "openhcs.runtime.zmq_execution_server", + "owner": "ZMQExecutionServer", + "method": "_execute_with_orchestrator", + "descriptor_kind": "function" + }, + { + "module": "openhcs.runtime.zmq_execution_server", + "owner": "ZMQExecutionServer", + "method": "_initialize_orchestrator", + "descriptor_kind": "function" + }, + { + "module": "openhcs.runtime.zmq_execution_server", + "owner": "ZMQExecutionServer", + "method": "_export_runtime_observation", + "descriptor_kind": "function" + }, + { + "module": "openhcs.interop.cellprofiler.runtime.function_contract_execution", + "owner": "CellProfilerFunctionContractExecutor", + "method": "execute", + "descriptor_kind": "function" + }, + { + "module": "openhcs.interop.cellprofiler.runtime.measurement_execution_support", + "owner": "ObjectMeasurementOutputRecorder", + "method": "record", + "descriptor_kind": "function" + }, + { + "module": "openhcs.interop.cellprofiler.runtime.output_recording", + "owner": "CellProfilerOutputRecorder", + "method": "record_module_outputs", + "descriptor_kind": "classmethod" + }, + { + "module": "openhcs.interop.cellprofiler.runtime.module_execution", + "owner": "CellProfilerModuleExecutor", + "method": "__call__", + "descriptor_kind": "function" + }, + { + "module": "openhcs.interop.cellprofiler.runtime.module_execution", + "owner": "CellProfilerModuleExecutor", + "method": "_image_request", + "descriptor_kind": "function" + } + ], + "profiling_enabled": false, + "runtime_profiling_enabled": false, + "diagnostic_errors": [], + "captures": false, + "scope": "coarse same-run nested exclusive timing partition on the exact source revision recorded in this region. Diagnostic wrappers, no scientific or memory-observer substitutions. Not accepted performance comparison. Declared callable boundary includes filtering/decorated processing/metadata; not pure numerical kernels. Both existing profilers are disabled. These wrappers still add diagnostic overhead; no scaling to uninstrumented clocks or causal performance claims. Query boundary is nested under its actual parent and excluded from parent-exclusive elapsed." +} diff --git a/benchmark/results/perf_rejected_metadata_owner_20261003/candidate-observations.json b/benchmark/results/perf_rejected_metadata_owner_20261003/candidate-observations.json new file mode 100644 index 0000000000..17f04a11e2 --- /dev/null +++ b/benchmark/results/perf_rejected_metadata_owner_20261003/candidate-observations.json @@ -0,0 +1,48 @@ +{ + "returncode": 0, + "diagnostic_admission": true, + "public_rows": [ + { + "case_name": "cp_tutorial_3d_monolayer", + "mode_name": "1w_1t", + "worker_count": "1", + "well_count": "1", + "compile_seconds": "1.2758193016052246", + "prepare_seconds": "0.0", + "execute_seconds": "8.977409839630127", + "total_seconds": "11.01210141601041", + "wells_per_second": "0.11139070376241177", + "successful_wells": "1", + "native_single_sample_execution_seconds": "", + "projected_native_execution_seconds": "", + "projected_execution_speedup": "", + "peak_memory_mb": "1663.19140625", + "status": "success", + "memory_limit_mb": "", + "error_message": "", + "execution_route": "ordinary-zmq-outcomes-v1", + "server_lifecycle": "reused-per-sweep", + "run_input_sha256": "1a217329c4ff9cc7e7328fe99edcd0bc9a6a292a9f3a116d3a23c7e05610aa36" + } + ], + "regions": [ + { + "path": "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/regions/region-1697815-139997494724288-0001.json", + "sha256": "6dd3985b2d0d394e5e796d7304b03b208657e7d161484c13b3110d6451ff8bdd" + }, + { + "path": "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/regions/region-1697815-139997494724288-0002.json", + "sha256": "7ec1f4e50610629ec55dc925de3b6a6b32b8b9337729b5117fa7eb57ff5f657f" + } + ], + "root_sequence_complete": true, + "actual_index_calls": 0, + "actual_declared_calls": 211, + "retained_json_bytes": 38075, + "generated_output_bytes": 18164103, + "public_log_bytes": 539, + "profiler_artifacts_absent": true, + "source_env_native_input_freeze": "PASS", + "science": "NOT_RUN: original full saved-output126file/schema/discrete/numerical/nativeinput witness separate gate. No exclusions or missing outputs waived.", + "scope": "One source-pinned whole ordinary3D Monolayer1w1t candidate falsification with24 unchanged coarse nominal hooks: inherited23 plus actual MeasurementFeatureValueIndex index classmethod. cProfile and runtime profiler OFF, no captures/percell hooks. Existing defaultOUTCOMES/memory observers/READY clocks unchanged. Same-thread nested exclusive clocks exclude query from its real ancestors; worker independent roots are not added to parent waits. Nearordinary diagnostic only; wrapper overhead remains, no scale factors/causal performance promotion. Full saved126file (6CSV120TIFF) science/native source witness independently required." +} diff --git a/benchmark/results/perf_rejected_metadata_owner_20261003/candidate-source-pins.json b/benchmark/results/perf_rejected_metadata_owner_20261003/candidate-source-pins.json new file mode 100644 index 0000000000..36ab6b78b3 --- /dev/null +++ b/benchmark/results/perf_rejected_metadata_owner_20261003/candidate-source-pins.json @@ -0,0 +1,116 @@ +{ + "revision": "9eee98265c939859d49f0c60bd5b3a2168cb29fe", + "source": "/home/ts/code/projects/openhcs-shared-runtime-plumbing", + "physical_inputs": { + "dataset_path": { + "path": "/home/ts/.cache/openhcs/benchmark_datasets/CellProfiler_tutorials/data/3d_monolayer/images", + "files": { + "3d_monolayer_xy1_ch0.tif": "63114f614fec95664f718a39cddac58449f0edb5cc31b57584e4ba5b1f4994c7", + "3d_monolayer_xy1_ch1.tif": "a7d9abf632850875c22613c4b740fc01153cf60e9773c16d4a670a97b46e5751", + "3d_monolayer_xy1_ch2.tif": "191754bc7f43856223180483e2737ea93bab4d0cf98b1b2a4c27425e9908147d" + } + }, + "cppipe_path": { + "path": "/home/ts/.cache/openhcs/benchmark_datasets/CellProfiler_tutorials/data/3d_monolayer/3d_monolayer_final.cppipe", + "files": { + "3d_monolayer_final.cppipe": "9fcd24a1be8372b5c2e87637a055032c3362b9ad8729e361095f93d8bbe71838" + } + } + }, + "shared_dependency_heads": "b0004daf3223326ac78689ba7b2e68abc18ae298 external/ObjectState (v1.1.8)\n 84f322e46871de5ed47e7fd20976ad03e533c1c4 external/PolyStore (v0.2.19-34-g84f322e)\n 1e53d03d9f468322a1c085c8be29485fb139caf2 external/arraybridge (v0.3.6)\n 393a7e03003cdc56df9013f932ed4f26e632d77a external/metaclass-registry (v0.2.2)\n 792b03413331fdf107e369c924c257a2f0b16126 external/pycodify (v0.1.3)\n ad4948775ab81180a354d4b793d17ee5ddff3972 external/pyqt-reactive (v0.3.24-9-gad49487)\n 4e8f8bde5f750d9a50eacac80acd3806123addd8 external/python-introspect (v0.1.14-1-g4e8f8bd)\n 668edafcb5ee530a163377c936431ae1e8334e85 external/zmqruntime (v0.2.24-40-g668edaf)", + "native_binaries": { + "openhcs/core/_tabular_native.abi3.so": { + "path": "/home/ts/code/projects/openhcs-shared-runtime-plumbing/openhcs/core/_tabular_native.abi3.so", + "sha256": "2ce348417de70ad3f614962c82aed9c4977c32b3ba00e13531ecafb8c10d8d1d" + }, + "openhcs/processing/backends/cellprofiler/_granularity_native.abi3.so": { + "path": "/home/ts/code/projects/openhcs-shared-runtime-plumbing/openhcs/processing/backends/cellprofiler/_granularity_native.abi3.so", + "sha256": "6e45987a50d5c0588a8fb0b09a2232a63e72c122d6a3d583ae4d62830e3b4096" + } + }, + "python_binary": { + "path": "/home/ts/.local/share/uv/python/cpython-3.12.14-linux-x86_64-gnu/bin/python3.12", + "sha256": "edffa803e5c4d73a1357f7f2c6c9fd38e9693712b2c06793e6a5e5cc1090d03a" + }, + "installed_versions": { + "python": "3.12.14 (main, Sep 24 2026, 17:57:43) [Clang 22.1.3 ]", + "versions": { + "openhcs": "0.8.7", + "numpy": "2.5.3", + "scipy": "1.18.1", + "arraybridge": "0.3.6", + "polystore": "0.3.0", + "python-introspect": "0.1.15", + "metaclass-registry": "0.2.2", + "zmqruntime": "0.3.0" + } + }, + "installed_freeze_sha256": "b7e5bbb9b5171476dfeb1692378419bfa157bb620028e1b91c8969eef2498b41", + "site_sha256": "391dc438b0d9d253e3467674c19d37b2670d5d7197400aa45f3c251e84f948c0", + "ordinary_helper_sha256": "8a41db448a722d231777a90a3ae23091617c8ac1ba72cefcb91f72b2c7975554", + "driver_sha256": "73b30d0cc3174c04cb479a72e97fe094ef6ad9fcfdacbfb37e43fbaad53560c3", + "manifest_sha256": "4c302e136b427cb9968eef82d7ede4a6c5b65cbcb4f8e5490fd5125c2e7ab2a8", + "ledger_controller_sha256": "c140695473eadb961b245c24344acc79778904920ba3725945ec9235354fbb9b", + "command": [ + "/usr/bin/taskset", + "-c", + "5", + "/home/ts/code/projects/openhcs/.venv/bin/python", + "-c", + "import runpy,sys;from dataclasses import replace;import openhcs.runtime.zmq_config as configuration;configuration.OPENHCS_ZMQ_CONFIG=replace(configuration.OPENHCS_ZMQ_CONFIG,client_connect_timeout_seconds=180.0);sys.argv=sys.argv[1:];runpy.run_path(sys.argv[0],run_name='__main__')", + "/home/ts/code/projects/openhcs-shared-runtime-plumbing/scripts/benchmark_cppipe_well_throughput.py", + "--manifest", + "/home/ts/code/projects/openhcs-shared-runtime-plumbing/benchmark/manifests/official30_portable_axis1.json", + "--mode", + "1w_1t", + "--output-dir", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public", + "--case", + "cp_tutorial_3d_monolayer" + ], + "scope": "One source-pinned whole ordinary3D Monolayer1w1t candidate falsification with24 unchanged coarse nominal hooks: inherited23 plus actual MeasurementFeatureValueIndex index classmethod. cProfile and runtime profiler OFF, no captures/percell hooks. Existing defaultOUTCOMES/memory observers/READY clocks unchanged. Same-thread nested exclusive clocks exclude query from its real ancestors; worker independent roots are not added to parent waits. Nearordinary diagnostic only; wrapper overhead remains, no scale factors/causal performance promotion. Full saved126file (6CSV120TIFF) science/native source witness independently required.", + "original_full_freeze_path": "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/source-freeze.json", + "original_full_freeze_sha256": "20c7690c2346a7e33625823ca1456b1774ec76192708a61aaf9f4b1170dc5d16", + "actual_import_dependency_pins": { + "external/ObjectState": { + "head": "a01f8939b9bf4659502a33fe3febe62cab0f3c9a", + "status": "", + "full_tracked_source_sha256": "511b83d27f0c0cffe973cb16e0cfce016405250185000d909e41f6343472dca1" + }, + "external/python-introspect": { + "head": "ed1e4eb15f7a0bf8315274d3e47858fa2b4372bb", + "status": "", + "full_tracked_source_sha256": "74b3a98b0ed51d505b50e828c5096aaab8d019d18b7619e7dfdcb0f923a54f7d" + }, + "external/arraybridge": { + "head": "1e53d03d9f468322a1c085c8be29485fb139caf2", + "status": "", + "full_tracked_source_sha256": "cc3300a4462a89363003190d00228618c8bc33545d445ae72359c1fb7440a931" + }, + "external/metaclass-registry": { + "head": "393a7e03003cdc56df9013f932ed4f26e632d77a", + "status": "", + "full_tracked_source_sha256": "a660ae17d4e4c03f5298ff8c2a8183635b53bf24558be6ff69b435476461e6bc" + }, + "external/zmqruntime": { + "head": "668edafcb5ee530a163377c936431ae1e8334e85", + "status": "", + "full_tracked_source_sha256": "bd020f39e177c038aa31d4579090694aede119aee668029a039dba249d311ec7" + }, + "external/pycodify": { + "head": "792b03413331fdf107e369c924c257a2f0b16126", + "status": "", + "full_tracked_source_sha256": "66f24bee56cbccc5baa5b1347a0c27bd6c9a6cc13598f679adba9668f2b54f3a" + }, + "external/PolyStore": { + "head": "84f322e46871de5ed47e7fd20976ad03e533c1c4", + "status": "", + "full_tracked_source_sha256": "47d2c21a32560e9d22581017e569846fb17f4f88a82a8ade0352eabaedea738b" + }, + "external/pyqt-reactive": { + "head": "ad4948775ab81180a354d4b793d17ee5ddff3972", + "status": "", + "full_tracked_source_sha256": "968cc99264a04019b724c11b47d53976f0f1341c50c8a86366aa7d3ef1ffe6fd" + } + } +} diff --git a/benchmark/results/perf_rejected_metadata_owner_20261003/consumer-controls.json b/benchmark/results/perf_rejected_metadata_owner_20261003/consumer-controls.json new file mode 100644 index 0000000000..03686eceb5 --- /dev/null +++ b/benchmark/results/perf_rejected_metadata_owner_20261003/consumer-controls.json @@ -0,0 +1,6 @@ +{ + "exit_code": 0, + "wall_seconds": 11.490860110148787, + "source_unchanged": true, + "log": "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-root-consumer-controls-v3/pytest.log" +} diff --git a/benchmark/results/perf_rejected_metadata_owner_20261003/extended-controls.json b/benchmark/results/perf_rejected_metadata_owner_20261003/extended-controls.json new file mode 100644 index 0000000000..97a1264ae2 --- /dev/null +++ b/benchmark/results/perf_rejected_metadata_owner_20261003/extended-controls.json @@ -0,0 +1,5 @@ +{ + "exit_code": 1, + "seconds": 40.09915372915566, + "source_unchanged": true +} diff --git a/benchmark/results/perf_rejected_metadata_owner_20261003/falsification.json b/benchmark/results/perf_rejected_metadata_owner_20261003/falsification.json new file mode 100644 index 0000000000..3f8d81de41 --- /dev/null +++ b/benchmark/results/perf_rejected_metadata_owner_20261003/falsification.json @@ -0,0 +1,495 @@ +{ + "decision": "REJECT_CURRENT_FLAT_NAMESPACE_ROUTE", + "scope": "One matched near-ordinary diagnostic pair; descriptive, not causal significance or full30 acceptance. No further polishing or performance promotion. Shared controls fixed; full science gate pending.", + "controls_equal": { + "physical_inputs": true, + "shared_dependency_heads": true, + "shared_dependency_sources": true, + "native_binaries": true, + "python_binary": true, + "installed_versions": true, + "installed_freeze_sha256": true, + "site_sha256": true, + "ordinary_helper_sha256": true, + "driver_sha256": true, + "manifest_sha256": true, + "actual_import_dependencies": true, + "ledger_controller_sha256": true, + "profiling_environment": true + }, + "cohorts": { + "baseline": { + "revision": "e8587bd7eb0c4aa283bc300c5eb9f2294f24890f", + "row": { + "case_name": "cp_tutorial_3d_monolayer", + "mode_name": "1w_1t", + "worker_count": "1", + "well_count": "1", + "compile_seconds": "1.5337145328521729", + "prepare_seconds": "0.0", + "execute_seconds": "8.276516675949097", + "total_seconds": "10.606972666922957", + "wells_per_second": "0.12082377637272465", + "successful_wells": "1", + "native_single_sample_execution_seconds": "", + "projected_native_execution_seconds": "", + "projected_execution_speedup": "", + "peak_memory_mb": "1692.34375", + "status": "success", + "memory_limit_mb": "", + "error_message": "", + "execution_route": "ordinary-zmq-outcomes-v1", + "server_lifecycle": "reused-per-sweep", + "run_input_sha256": "7f66dd478c9a56033495f056335a0eaadb9fd5facd953b504f0e1f8f7eaa57d5" + }, + "execution_root_seconds": 8.26425674976781, + "raw_callable_seconds": 3.656715089920908, + "outside_callable_seconds": 4.607541659846902, + "exclusive_phases": { + "ZMQExecutionServer._initialize_orchestrator": 0.08023449825122952, + "RuntimeImageStackCache.get": 0.0003536404110491276, + "stack_image_payload_context": 0.04427314409986138, + "PatternGroupRuntime._load_input_stack": 0.7971521429717541, + "CellProfilerModuleExecutor._image_request": 0.2785968668758869, + "CellProfilerFunctionContractExecutor.execute | function=openhcs.processing.backends.cellprofiler.intensity.rescale_intensity": 0.0007243934087455273, + "CellProfilerOutputRecorder.record_module_outputs": 0.3608029861934483, + "CellProfilerModuleExecutor.__call__": 0.12689677299931645, + "FunctionCoreExecutor.execute | function=rescale_intensity": 0.00037510739639401436, + "PatternGroupRuntime._validate_and_unstack": 0.18270204262807965, + "RuntimeImageStackCache.store": 0.00022991374135017395, + "PatternGroupRuntime._save_outputs": 0.6563447550870478, + "finalize_function_step_outputs": 0.20995302312076092, + "CellProfilerFunctionContractExecutor.execute | function=openhcs.processing.backends.cellprofiler.image_geometry.resize_volumetric": 0.0007913196459412575, + "FunctionCoreExecutor.execute | function=resize_volumetric": 0.0007455325685441494, + "CellProfilerFunctionContractExecutor.execute | function=openhcs.processing.backends.cellprofiler.median_filter.medianfilter": 0.0008455133065581322, + "FunctionCoreExecutor.execute | function=medianfilter": 0.0009696455672383308, + "CellProfilerFunctionContractExecutor.execute | function=openhcs.processing.backends.cellprofiler.thresholding.threshold": 0.0010865754447877407, + "FunctionCoreExecutor.execute | function=threshold": 0.003549575340002775, + "CellProfilerFunctionContractExecutor.execute | function=openhcs.processing.backends.cellprofiler.morphology.remove_holes_3d": 0.00023544440045952797, + "FunctionCoreExecutor.execute | function=remove_holes_3d": 0.0005331146530807018, + "CellProfilerFunctionContractExecutor.execute | function=openhcs.processing.backends.cellprofiler.watershed.watershed_cellprofiler4": 0.0005967230536043644, + "FunctionCoreExecutor.execute | function=watershed_cellprofiler4": 0.003626206424087286, + "CellProfilerFunctionContractExecutor.execute | function=openhcs.processing.backends.cellprofiler.morphology.resize_objects_3d": 0.000580822117626667, + "FunctionCoreExecutor.execute | function=resize_objects_3d": 0.0009479965083301067, + "CellProfilerFunctionContractExecutor.execute | function=openhcs.processing.backends.cellprofiler.morphology.erode_objects": 0.0005217930302023888, + "FunctionCoreExecutor.execute | function=erode_objects": 0.0004508676938712597, + "CellProfilerFunctionContractExecutor.execute | function=openhcs.processing.backends.cellprofiler.object_images.convert_objects_to_image": 0.0007999753579497337, + "FunctionCoreExecutor.execute | function=convert_objects_to_image": 0.0010002129711210728, + "CellProfilerFunctionContractExecutor.execute | function=openhcs.processing.backends.cellprofiler.image_math.image_math": 0.027114899829030037, + "FunctionCoreExecutor.execute | function=image_math": 0.0005593728274106979, + "CellProfilerFunctionContractExecutor.execute | function=openhcs.processing.backends.cellprofiler.morphology.closing": 9.440816938877106e-05, + "FunctionCoreExecutor.execute | function=closing": 0.00026117172092199326, + "CellProfilerFunctionContractExecutor.execute | function=openhcs.processing.backends.cellprofiler.image_geometry.mask_image": 0.014385522343218327, + "FunctionCoreExecutor.execute | function=mask_image": 0.00037759123370051384, + "CellProfilerFunctionContractExecutor.execute | function=openhcs.processing.backends.cellprofiler.morphology.erode_image": 9.999750182032585e-05, + "FunctionCoreExecutor.execute | function=erode_image": 0.0002447301521897316, + "CellProfilerFunctionContractExecutor.execute | function=openhcs.processing.backends.cellprofiler.intensity.measure_object_intensity": 0.0007225805893540382, + "ObjectMeasurementOutputRecorder.record": 0.0037819184362888336, + "FunctionCoreExecutor.execute | function=measure_object_intensity": 0.0043295701034367085, + "CellProfilerFunctionContractExecutor.execute | function=openhcs.processing.backends.cellprofiler.shape.measure_object_size_shape": 0.001232681330293417, + "FunctionCoreExecutor.execute | function=measure_object_size_shape": 0.00211262796074152, + "CellProfilerFunctionContractExecutor.execute | function=openhcs.processing.backends.cellprofiler.outlines.overlay_objects": 0.00020497571676969528, + "FunctionCoreExecutor.execute | function=overlay_objects": 0.010954282246530056, + "FunctionCoreExecutor.execute | function=save_images": 0.1656533577479422, + "AtomicMetadataWriter.publish_source_projection_metadata": 0.7686110232025385, + "consolidate_analysis_outputs": 1.02287158370018e-05, + "RuntimeArtifactMetadataTarget.reconciliation_targets": 0.3009079131297767, + "OpenHCSMetadataWriter.finalize_completed_plate": 0.00812348397448659, + "ZMQExecutionServer._export_runtime_observation": 0.007673155982047319 + }, + "source_freeze_sha256": "55ee41e2e0f09553de9c2be7dab5beedf0f4f2baf7245f2778c2dcedc38a092e" + }, + "candidate": { + "revision": "9eee98265c939859d49f0c60bd5b3a2168cb29fe", + "row": { + "case_name": "cp_tutorial_3d_monolayer", + "mode_name": "1w_1t", + "worker_count": "1", + "well_count": "1", + "compile_seconds": "1.2758193016052246", + "prepare_seconds": "0.0", + "execute_seconds": "8.977409839630127", + "total_seconds": "11.01210141601041", + "wells_per_second": "0.11139070376241177", + "successful_wells": "1", + "native_single_sample_execution_seconds": "", + "projected_native_execution_seconds": "", + "projected_execution_speedup": "", + "peak_memory_mb": "1663.19140625", + "status": "success", + "memory_limit_mb": "", + "error_message": "", + "execution_route": "ordinary-zmq-outcomes-v1", + "server_lifecycle": "reused-per-sweep", + "run_input_sha256": "1a217329c4ff9cc7e7328fe99edcd0bc9a6a292a9f3a116d3a23c7e05610aa36" + }, + "execution_root_seconds": 8.966167135164142, + "raw_callable_seconds": 3.975498642306775, + "outside_callable_seconds": 4.990668492857367, + "exclusive_phases": { + "ZMQExecutionServer._initialize_orchestrator": 0.08220752514898777, + "RuntimeImageStackCache.get": 0.00034267501905560493, + "stack_image_payload_context": 0.04168135765939951, + "PatternGroupRuntime._load_input_stack": 0.8310769814997911, + "CellProfilerModuleExecutor._image_request": 0.3633091449737549, + "CellProfilerFunctionContractExecutor.execute | function=openhcs.processing.backends.cellprofiler.intensity.rescale_intensity": 0.0008854884654283524, + "CellProfilerOutputRecorder.record_module_outputs": 0.4135434296913445, + "CellProfilerModuleExecutor.__call__": 0.22105292789638042, + "FunctionCoreExecutor.execute | function=rescale_intensity": 0.0003861561417579651, + "PatternGroupRuntime._validate_and_unstack": 0.24520861357450485, + "RuntimeImageStackCache.store": 0.00023655686527490616, + "PatternGroupRuntime._save_outputs": 0.6772819310426712, + "finalize_function_step_outputs": 0.48047462571412325, + "CellProfilerFunctionContractExecutor.execute | function=openhcs.processing.backends.cellprofiler.image_geometry.resize_volumetric": 0.0006456342525780201, + "FunctionCoreExecutor.execute | function=resize_volumetric": 0.0007655806839466095, + "CellProfilerFunctionContractExecutor.execute | function=openhcs.processing.backends.cellprofiler.median_filter.medianfilter": 0.000626599881798029, + "FunctionCoreExecutor.execute | function=medianfilter": 0.0010953620076179504, + "CellProfilerFunctionContractExecutor.execute | function=openhcs.processing.backends.cellprofiler.thresholding.threshold": 0.0011267522349953651, + "FunctionCoreExecutor.execute | function=threshold": 0.003914329688996077, + "CellProfilerFunctionContractExecutor.execute | function=openhcs.processing.backends.cellprofiler.morphology.remove_holes_3d": 0.0002312161959707737, + "FunctionCoreExecutor.execute | function=remove_holes_3d": 0.0005047591403126717, + "CellProfilerFunctionContractExecutor.execute | function=openhcs.processing.backends.cellprofiler.watershed.watershed_cellprofiler4": 0.0005443445406854153, + "FunctionCoreExecutor.execute | function=watershed_cellprofiler4": 0.002408776432275772, + "CellProfilerFunctionContractExecutor.execute | function=openhcs.processing.backends.cellprofiler.morphology.resize_objects_3d": 0.0006016828119754791, + "FunctionCoreExecutor.execute | function=resize_objects_3d": 0.0009483452886343002, + "CellProfilerFunctionContractExecutor.execute | function=openhcs.processing.backends.cellprofiler.morphology.erode_objects": 0.0005220817402005196, + "FunctionCoreExecutor.execute | function=erode_objects": 0.0004721791483461857, + "CellProfilerFunctionContractExecutor.execute | function=openhcs.processing.backends.cellprofiler.object_images.convert_objects_to_image": 0.0007796292193233967, + "FunctionCoreExecutor.execute | function=convert_objects_to_image": 0.0015249010175466537, + "CellProfilerFunctionContractExecutor.execute | function=openhcs.processing.backends.cellprofiler.image_math.image_math": 0.023964846041053534, + "FunctionCoreExecutor.execute | function=image_math": 0.00045528681948781013, + "CellProfilerFunctionContractExecutor.execute | function=openhcs.processing.backends.cellprofiler.morphology.closing": 0.00010926695540547371, + "FunctionCoreExecutor.execute | function=closing": 0.0002643684856593609, + "CellProfilerFunctionContractExecutor.execute | function=openhcs.processing.backends.cellprofiler.image_geometry.mask_image": 0.020614102482795715, + "FunctionCoreExecutor.execute | function=mask_image": 0.00040600355714559555, + "CellProfilerFunctionContractExecutor.execute | function=openhcs.processing.backends.cellprofiler.morphology.erode_image": 0.00010522827506065369, + "FunctionCoreExecutor.execute | function=erode_image": 0.0002591479569673538, + "CellProfilerFunctionContractExecutor.execute | function=openhcs.processing.backends.cellprofiler.intensity.measure_object_intensity": 0.0007041138596832752, + "ObjectMeasurementOutputRecorder.record": 0.0037249731831252575, + "FunctionCoreExecutor.execute | function=measure_object_intensity": 0.004520548973232508, + "CellProfilerFunctionContractExecutor.execute | function=openhcs.processing.backends.cellprofiler.shape.measure_object_size_shape": 0.0007663932628929615, + "FunctionCoreExecutor.execute | function=measure_object_size_shape": 0.002118128351867199, + "CellProfilerFunctionContractExecutor.execute | function=openhcs.processing.backends.cellprofiler.outlines.overlay_objects": 0.00021530408412218094, + "FunctionCoreExecutor.execute | function=overlay_objects": 0.013460240792483091, + "FunctionCoreExecutor.execute | function=save_images": 0.1760786077938974, + "AtomicMetadataWriter.publish_source_projection_metadata": 0.5068132942542434, + "consolidate_analysis_outputs": 1.1913012713193893e-05, + "RuntimeArtifactMetadataTarget.reconciliation_targets": 0.2939795549027622, + "OpenHCSMetadataWriter.finalize_completed_plate": 0.007927724625915289, + "ZMQExecutionServer._export_runtime_observation": 0.010043779853731394 + }, + "source_freeze_sha256": "20c7690c2346a7e33625823ca1456b1774ec76192708a61aaf9f4b1170dc5d16" + } + }, + "deltas": { + "execution_seconds": 0.7008931636810303, + "total_seconds": 0.4051287490874529, + "raw_callable_seconds": 0.31878355238586664, + "outside_callable_seconds": 0.3831268330104649 + }, + "exclusive_phase_changes": [ + { + "phase": "finalize_function_step_outputs", + "baseline": 0.20995302312076092, + "candidate": 0.48047462571412325, + "delta": 0.27052160259336233 + }, + { + "phase": "CellProfilerModuleExecutor.__call__", + "baseline": 0.12689677299931645, + "candidate": 0.22105292789638042, + "delta": 0.09415615489706397 + }, + { + "phase": "CellProfilerModuleExecutor._image_request", + "baseline": 0.2785968668758869, + "candidate": 0.3633091449737549, + "delta": 0.08471227809786797 + }, + { + "phase": "PatternGroupRuntime._validate_and_unstack", + "baseline": 0.18270204262807965, + "candidate": 0.24520861357450485, + "delta": 0.0625065709464252 + }, + { + "phase": "CellProfilerOutputRecorder.record_module_outputs", + "baseline": 0.3608029861934483, + "candidate": 0.4135434296913445, + "delta": 0.052740443497896194 + }, + { + "phase": "PatternGroupRuntime._load_input_stack", + "baseline": 0.7971521429717541, + "candidate": 0.8310769814997911, + "delta": 0.03392483852803707 + }, + { + "phase": "PatternGroupRuntime._save_outputs", + "baseline": 0.6563447550870478, + "candidate": 0.6772819310426712, + "delta": 0.02093717595562339 + }, + { + "phase": "FunctionCoreExecutor.execute | function=save_images", + "baseline": 0.1656533577479422, + "candidate": 0.1760786077938974, + "delta": 0.010425250045955181 + }, + { + "phase": "CellProfilerFunctionContractExecutor.execute | function=openhcs.processing.backends.cellprofiler.image_geometry.mask_image", + "baseline": 0.014385522343218327, + "candidate": 0.020614102482795715, + "delta": 0.006228580139577389 + }, + { + "phase": "FunctionCoreExecutor.execute | function=overlay_objects", + "baseline": 0.010954282246530056, + "candidate": 0.013460240792483091, + "delta": 0.0025059585459530354 + }, + { + "phase": "ZMQExecutionServer._export_runtime_observation", + "baseline": 0.007673155982047319, + "candidate": 0.010043779853731394, + "delta": 0.0023706238716840744 + }, + { + "phase": "ZMQExecutionServer._initialize_orchestrator", + "baseline": 0.08023449825122952, + "candidate": 0.08220752514898777, + "delta": 0.0019730268977582455 + }, + { + "phase": "FunctionCoreExecutor.execute | function=convert_objects_to_image", + "baseline": 0.0010002129711210728, + "candidate": 0.0015249010175466537, + "delta": 0.000524688046425581 + }, + { + "phase": "FunctionCoreExecutor.execute | function=threshold", + "baseline": 0.003549575340002775, + "candidate": 0.003914329688996077, + "delta": 0.0003647543489933014 + }, + { + "phase": "FunctionCoreExecutor.execute | function=measure_object_intensity", + "baseline": 0.0043295701034367085, + "candidate": 0.004520548973232508, + "delta": 0.00019097886979579926 + }, + { + "phase": "CellProfilerFunctionContractExecutor.execute | function=openhcs.processing.backends.cellprofiler.intensity.rescale_intensity", + "baseline": 0.0007243934087455273, + "candidate": 0.0008854884654283524, + "delta": 0.0001610950566828251 + }, + { + "phase": "FunctionCoreExecutor.execute | function=medianfilter", + "baseline": 0.0009696455672383308, + "candidate": 0.0010953620076179504, + "delta": 0.0001257164403796196 + }, + { + "phase": "CellProfilerFunctionContractExecutor.execute | function=openhcs.processing.backends.cellprofiler.thresholding.threshold", + "baseline": 0.0010865754447877407, + "candidate": 0.0011267522349953651, + "delta": 4.0176790207624435e-05 + }, + { + "phase": "FunctionCoreExecutor.execute | function=mask_image", + "baseline": 0.00037759123370051384, + "candidate": 0.00040600355714559555, + "delta": 2.841232344508171e-05 + }, + { + "phase": "FunctionCoreExecutor.execute | function=erode_objects", + "baseline": 0.0004508676938712597, + "candidate": 0.0004721791483461857, + "delta": 2.1311454474925995e-05 + }, + { + "phase": "CellProfilerFunctionContractExecutor.execute | function=openhcs.processing.backends.cellprofiler.morphology.resize_objects_3d", + "baseline": 0.000580822117626667, + "candidate": 0.0006016828119754791, + "delta": 2.0860694348812103e-05 + }, + { + "phase": "FunctionCoreExecutor.execute | function=resize_volumetric", + "baseline": 0.0007455325685441494, + "candidate": 0.0007655806839466095, + "delta": 2.0048115402460098e-05 + }, + { + "phase": "CellProfilerFunctionContractExecutor.execute | function=openhcs.processing.backends.cellprofiler.morphology.closing", + "baseline": 9.440816938877106e-05, + "candidate": 0.00010926695540547371, + "delta": 1.4858786016702652e-05 + }, + { + "phase": "FunctionCoreExecutor.execute | function=erode_image", + "baseline": 0.0002447301521897316, + "candidate": 0.0002591479569673538, + "delta": 1.4417804777622223e-05 + }, + { + "phase": "FunctionCoreExecutor.execute | function=rescale_intensity", + "baseline": 0.00037510739639401436, + "candidate": 0.0003861561417579651, + "delta": 1.104874536395073e-05 + }, + { + "phase": "CellProfilerFunctionContractExecutor.execute | function=openhcs.processing.backends.cellprofiler.outlines.overlay_objects", + "baseline": 0.00020497571676969528, + "candidate": 0.00021530408412218094, + "delta": 1.0328367352485657e-05 + }, + { + "phase": "RuntimeImageStackCache.store", + "baseline": 0.00022991374135017395, + "candidate": 0.00023655686527490616, + "delta": 6.643123924732208e-06 + }, + { + "phase": "FunctionCoreExecutor.execute | function=measure_object_size_shape", + "baseline": 0.00211262796074152, + "candidate": 0.002118128351867199, + "delta": 5.500391125679016e-06 + }, + { + "phase": "CellProfilerFunctionContractExecutor.execute | function=openhcs.processing.backends.cellprofiler.morphology.erode_image", + "baseline": 9.999750182032585e-05, + "candidate": 0.00010522827506065369, + "delta": 5.230773240327835e-06 + }, + { + "phase": "FunctionCoreExecutor.execute | function=closing", + "baseline": 0.00026117172092199326, + "candidate": 0.0002643684856593609, + "delta": 3.19676473736763e-06 + }, + { + "phase": "consolidate_analysis_outputs", + "baseline": 1.02287158370018e-05, + "candidate": 1.1913012713193893e-05, + "delta": 1.684296876192093e-06 + }, + { + "phase": "FunctionCoreExecutor.execute | function=resize_objects_3d", + "baseline": 0.0009479965083301067, + "candidate": 0.0009483452886343002, + "delta": 3.487803041934967e-07 + }, + { + "phase": "CellProfilerFunctionContractExecutor.execute | function=openhcs.processing.backends.cellprofiler.morphology.erode_objects", + "baseline": 0.0005217930302023888, + "candidate": 0.0005220817402005196, + "delta": 2.8870999813079834e-07 + }, + { + "phase": "CellProfilerFunctionContractExecutor.execute | function=openhcs.processing.backends.cellprofiler.morphology.remove_holes_3d", + "baseline": 0.00023544440045952797, + "candidate": 0.0002312161959707737, + "delta": -4.2282044887542725e-06 + }, + { + "phase": "RuntimeImageStackCache.get", + "baseline": 0.0003536404110491276, + "candidate": 0.00034267501905560493, + "delta": -1.0965391993522644e-05 + }, + { + "phase": "CellProfilerFunctionContractExecutor.execute | function=openhcs.processing.backends.cellprofiler.intensity.measure_object_intensity", + "baseline": 0.0007225805893540382, + "candidate": 0.0007041138596832752, + "delta": -1.8466729670763016e-05 + }, + { + "phase": "CellProfilerFunctionContractExecutor.execute | function=openhcs.processing.backends.cellprofiler.object_images.convert_objects_to_image", + "baseline": 0.0007999753579497337, + "candidate": 0.0007796292193233967, + "delta": -2.034613862633705e-05 + }, + { + "phase": "FunctionCoreExecutor.execute | function=remove_holes_3d", + "baseline": 0.0005331146530807018, + "candidate": 0.0005047591403126717, + "delta": -2.8355512768030167e-05 + }, + { + "phase": "CellProfilerFunctionContractExecutor.execute | function=openhcs.processing.backends.cellprofiler.watershed.watershed_cellprofiler4", + "baseline": 0.0005967230536043644, + "candidate": 0.0005443445406854153, + "delta": -5.237851291894913e-05 + }, + { + "phase": "ObjectMeasurementOutputRecorder.record", + "baseline": 0.0037819184362888336, + "candidate": 0.0037249731831252575, + "delta": -5.6945253163576126e-05 + }, + { + "phase": "FunctionCoreExecutor.execute | function=image_math", + "baseline": 0.0005593728274106979, + "candidate": 0.00045528681948781013, + "delta": -0.0001040860079228878 + }, + { + "phase": "CellProfilerFunctionContractExecutor.execute | function=openhcs.processing.backends.cellprofiler.image_geometry.resize_volumetric", + "baseline": 0.0007913196459412575, + "candidate": 0.0006456342525780201, + "delta": -0.00014568539336323738 + }, + { + "phase": "OpenHCSMetadataWriter.finalize_completed_plate", + "baseline": 0.00812348397448659, + "candidate": 0.007927724625915289, + "delta": -0.0001957593485713005 + }, + { + "phase": "CellProfilerFunctionContractExecutor.execute | function=openhcs.processing.backends.cellprofiler.median_filter.medianfilter", + "baseline": 0.0008455133065581322, + "candidate": 0.000626599881798029, + "delta": -0.00021891342476010323 + }, + { + "phase": "CellProfilerFunctionContractExecutor.execute | function=openhcs.processing.backends.cellprofiler.shape.measure_object_size_shape", + "baseline": 0.001232681330293417, + "candidate": 0.0007663932628929615, + "delta": -0.0004662880674004555 + }, + { + "phase": "FunctionCoreExecutor.execute | function=watershed_cellprofiler4", + "baseline": 0.003626206424087286, + "candidate": 0.002408776432275772, + "delta": -0.001217429991811514 + }, + { + "phase": "stack_image_payload_context", + "baseline": 0.04427314409986138, + "candidate": 0.04168135765939951, + "delta": -0.002591786440461874 + }, + { + "phase": "CellProfilerFunctionContractExecutor.execute | function=openhcs.processing.backends.cellprofiler.image_math.image_math", + "baseline": 0.027114899829030037, + "candidate": 0.023964846041053534, + "delta": -0.0031500537879765034 + }, + { + "phase": "RuntimeArtifactMetadataTarget.reconciliation_targets", + "baseline": 0.3009079131297767, + "candidate": 0.2939795549027622, + "delta": -0.006928358227014542 + }, + { + "phase": "AtomicMetadataWriter.publish_source_projection_metadata", + "baseline": 0.7686110232025385, + "candidate": 0.5068132942542434, + "delta": -0.2617977289482951 + } + ], + "science_status": "PASS_FULL_FOUR_NATIVE_COMPARISONS", + "science_sha256": "b9a35a8504dc4a2dc96d4e8e4263335be9f8c70f0b14b45e1f92aa3c8d3c6b45", + "candidate_source_reverted": true +} diff --git a/benchmark/results/perf_rejected_metadata_owner_20261003/inventory.json b/benchmark/results/perf_rejected_metadata_owner_20261003/inventory.json new file mode 100644 index 0000000000..7c0643f638 --- /dev/null +++ b/benchmark/results/perf_rejected_metadata_owner_20261003/inventory.json @@ -0,0 +1,85 @@ +{ + "files": { + "report.rst": { + "sha256": "11de21974ade24d126e635e554c9c9ad984d45aab788780b628361b0d22dafa8", + "bytes": 4714 + }, + "saved-v10-qualification.json": { + "sha256": "c9632c56a642b13a36bec564f2e128ac2a2fadf05d3a86a2e3c5b8b604a4500b", + "bytes": 16243 + }, + "metrics.csv": { + "sha256": "844b51828eafbea34153f1c4d9bcd29f752403fcd297275bc99bea296f1a360c", + "bytes": 396 + }, + "science-terminal.json": { + "sha256": "a9871f40c946d17cd2c5df275dfafe2c058e6270732e0cd51e5b2fb3cd3c5805", + "bytes": 2108 + }, + "baseline-execution-region.json": { + "sha256": "eda84c30eb19709e0fc37a35550a0e5a8e27e97ddd818e9296904203cd9e9e0b", + "bytes": 31183 + }, + "falsification.json": { + "sha256": "4a2010cca8476065b814bc7247ee80737cd29878c023930d8757033bd5f03171", + "bytes": 25432 + }, + "strict-science.json": { + "sha256": "b9a35a8504dc4a2dc96d4e8e4263335be9f8c70f0b14b45e1f92aa3c8d3c6b45", + "bytes": 268580 + }, + "baseline-compile_only-region.json": { + "sha256": "d4cf4157156de4e7a41949e36ee4daed69665ea7b8c6e2ddf5b00613300b6e5a", + "bytes": 6874 + }, + "original-nine-failures.json": { + "sha256": "06ef7de5b4dbaee2784d4233734ae90749802d38b802d66f6622eed4b3ecbbb1", + "bytes": 6093 + }, + "extended-controls.json": { + "sha256": "a7abdc5fdde8525351ab8ce0636d00963793cce71bd2f0d756deb9deb7aec945", + "bytes": 81 + }, + "consumer-controls.json": { + "sha256": "828575a11f53ac5c23865f5d47825874593c1cbd07109a7d4bf57443aa28c2fa", + "bytes": 199 + }, + "candidate-execution-region.json": { + "sha256": "7ec1f4e50610629ec55dc925de3b6a6b32b8b9337729b5117fa7eb57ff5f657f", + "bytes": 31198 + }, + "candidate-compile_only-region.json": { + "sha256": "6dd3985b2d0d394e5e796d7304b03b208657e7d161484c13b3110d6451ff8bdd", + "bytes": 6877 + }, + "baseline-source-pins.json": { + "sha256": "05f6be9206a59e4c392ef3994049287009fbcaa6937799d2fc3c53c2ba3b58be", + "bytes": 6814 + }, + "candidate-observations.json": { + "sha256": "6594071a580a83a5abd4cdb58c399899d046c84eaa52ed1c4f5dc0faab2bf88d", + "bytes": 2522 + }, + "whole-driver-controller.py": { + "sha256": "c140695473eadb961b245c24344acc79778904920ba3725945ec9235354fbb9b", + "bytes": 11489 + }, + "baseline-observations.json": { + "sha256": "a9558f52b6d74972c4244b9af73e03cfe66ecada108d1d2131db5af56c868260", + "bytes": 2518 + }, + "submitted-input-controls.json": { + "sha256": "ab65cac76f849b16a4ad67bf4e9c39818bd82b50c7a55173da42c112a50ecb33", + "bytes": 1733 + }, + "whole-driver-site.py": { + "sha256": "391dc438b0d9d253e3467674c19d37b2670d5d7197400aa45f3c251e84f948c0", + "bytes": 10930 + }, + "candidate-source-pins.json": { + "sha256": "39de2a5b69a560525666431b10b576e9de0e3c08d21ecf1f715bd22d429f541f", + "bytes": 6816 + } + }, + "scope": "Compact rejection/behavior evidence; full warm-state witness is preserved by original byte pin, no copied scientific outputs/environments" +} diff --git a/benchmark/results/perf_rejected_metadata_owner_20261003/metrics.csv b/benchmark/results/perf_rejected_metadata_owner_20261003/metrics.csv new file mode 100644 index 0000000000..f9fd7ecb36 --- /dev/null +++ b/benchmark/results/perf_rejected_metadata_owner_20261003/metrics.csv @@ -0,0 +1,3 @@ +variant,source,compile_seconds,execution_seconds,total_seconds,raw_callable_seconds,outside_callable_seconds +baseline,e8587bd7eb0c4aa283bc300c5eb9f2294f24890f,1.5337145328521729,8.276516675949097,10.606972666922957,3.656715089920908,4.607541659846902 +candidate,9eee98265c939859d49f0c60bd5b3a2168cb29fe,1.2758193016052246,8.977409839630127,11.01210141601041,3.975498642306775,4.990668492857367 diff --git a/benchmark/results/perf_rejected_metadata_owner_20261003/original-nine-failures.json b/benchmark/results/perf_rejected_metadata_owner_20261003/original-nine-failures.json new file mode 100644 index 0000000000..d8d899c767 --- /dev/null +++ b/benchmark/results/perf_rejected_metadata_owner_20261003/original-nine-failures.json @@ -0,0 +1,113 @@ +{ + "conclusion": "All nine original assertion/error signatures recur against original Git blobs. No candidate-caused failure among these nine is demonstrated.", + "original_source_revision": "e8587bd7eb0c4aa283bc300c5eb9f2294f24890f", + "baseline_scope": "Original 27 changed production modules, all loaded; other source and shared dependencies/environment unchanged current installation, not reconstruction of a historical whole environment.", + "original_result": { + "failed": 9, + "passed": 0, + "seconds": 5.89, + "exit_code": 1 + }, + "candidate_result": { + "failed": 9, + "passed": 700, + "seconds": 37.58 + }, + "test_files_byte_equal_to_original_git_before_and_unchanged_after": { + "tests/unit/test_cellprofiler_runtime_adapter.py": "e4c1e9a86e2dc93a0af24088855caf3c12566e4bd99b9852c9ad3d152e2531a0", + "tests/unit/test_cellprofiler_runtime_binding_identity.py": "ff7ce51901b7d2f6838f19c454c0ecd32c219f82fafcb56748d6a8988ec73629", + "tests/unit/test_cellprofiler_module_execution.py": "5d28dcb3645197772b77d5f8eb4dc07e729bc4b2094322e20efd6a7468f5993f" + }, + "all_27_loaded_original_hashes_match": true, + "candidate_disk_modules_unchanged_since_each_overlay_import": true, + "error_lines_equal": true, + "error_line_comparison": "Exact E-line text except replacing process-specific 0x object repr addresses. Full raw logs retained.", + "error_lines": [ + "E assert [2] == [1, 2]", + "E ", + "E At index 0 diff: 2 != 1", + "E Right contains one more item: 2", + "E Use -v to get more diff", + "E assert np.float64(nan) == 30.0", + "E AssertionError: assert is ", + "E + where = object_identity()", + "E + where object_identity = >.object_identity", + "E + where > = runtime_object_measurement_row_policy()", + "E + where runtime_object_measurement_row_policy = MeasureObjectSizeShapeModule.runtime_object_measurement_row_policy", + "E + and = MeasurementObjectRowIdentity.ROW_SEQUENCE", + "E assert nan == 16.0", + "E assert [1, 2, 3, 4, 5] == [1, 2, 3]", + "E ", + "E Left contains 2 more items, first extra item: 4", + "E Use -v to get more diff", + "E AssertionError: assert CallableContr...pingproxy({})) == CallableContr...pingproxy({}))", + "E ", + "E Omitting 4 identical items, use -vv to show", + "E Differing attributes:", + "E ['metadata']", + "E ", + "E Drill down into differing attribute metadata:", + "E metadata: CallableMetadata(input_memory_type='numpy', output_memory_type='numpy', execution_memory_type='numpy', artifact_inputs=(ArtifactSpec(name='Worms', artifact_type=, parameter_name=None, materialization=None, viewer_streaming=, required=True, sidecar_role=None, relations=(), plan_type=, measuremen...", + "E ", + "E ...Full output truncated (11 lines hidden), use '-vv' to show", + "E RuntimeError: Missing dynamic grouped artifact input 'Nuclei' (object_labels) on axis 'A01' for producer component 'channel'.", + "E RuntimeError: Missing dynamic grouped artifact input 'Cells' (object_labels) on axis 'A01' for producer component 'channel'.", + "E RuntimeError: Missing dynamic grouped artifact input 'DNA' (image) on axis 'A01' for producer component 'site'." + ], + "failure_groups": [ + { + "count": 5, + "group": "Shape row-domain controls", + "failures": [ + "projected IDs [2] versus [1,2]", + "NaN versus 30", + "ROW_ORDINAL versus ROW_SEQUENCE policy", + "NaN Zernike versus 16", + "backend IDs [1,2,3,4,5] versus [1,2,3]" + ] + }, + { + "count": 1, + "group": "Crop settings contract", + "failure": "CallableContract metadata comparison differs" + }, + { + "count": 3, + "group": "Dynamic grouped artifact discovery", + "failure": "Missing Nuclei/Cells channel-grouped labels and DNA site-grouped images on A01" + } + ], + "artifacts": [ + { + "path": "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-original-nine-boundary-controls-v1/selection.json", + "bytes": 2743, + "sha256": "73e2ee370c4b0c16223d7fa82777da1ddd67e1aff32c0362f0e8213a3b583fef" + }, + { + "path": "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-original-nine-boundary-controls-v1/run_original.py", + "bytes": 3048, + "sha256": "53e37ff4a439bbe7e6732b5e1c45fc6ecf9207a98128337a12f40ad3c26f727c" + }, + { + "path": "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-original-nine-boundary-controls-v1/imports-and-source.json", + "bytes": 15390, + "sha256": "29627098d5d59fd02c1d2a383b1cc3b03e60c08ba91b18edee441a6000b1486f" + }, + { + "path": "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-original-nine-boundary-controls-v1/pytest.log", + "bytes": 31083, + "sha256": "76045c7dbfc544cff33a9ad6deacf75d8d3617605431ad65b3c069a043960aff" + }, + { + "path": "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-runtime-boundary-controls-v1/pytest.log", + "bytes": 32104, + "sha256": "a9ac9e60f3f7892299f182bd839bb9ccc5d56b5d0a9d86a4c14eeed7019b37b5" + } + ], + "production_changes": false, + "new_environment_or_checkout": false, + "pipeline_or_native_run": false, + "all_handles_terminal": [ + 90981 + ] +} diff --git a/benchmark/results/perf_rejected_metadata_owner_20261003/report.rst b/benchmark/results/perf_rejected_metadata_owner_20261003/report.rst new file mode 100644 index 0000000000..d2d2b04f1d --- /dev/null +++ b/benchmark/results/perf_rejected_metadata_owner_20261003/report.rst @@ -0,0 +1,83 @@ +Rejected flat metadata owner prototype +====================================== + +The prototype did not reduce representative 3D runtime enough to justify its +additional storage and dispatch machinery. It is reverted from the final source. +Rejected source 9eee98265c939859d49f0c60bd5b3a2168cb29fe remains in Git history; +baseline e8587bd7eb0c4aa283bc300c5eb9f2294f24890f and restored production/tests +are byte-identical. This is evidence for #384 / PR #394, not a completed goal. + +One matched near-ordinary 1w_1t diagnostic pair on CPU5, 24 unchanged coarse +hooks, no cProfile/runtime profiler/captures, existing OUTCOMES and memory +observer. Server/library/kernel readiness and shutdown precede/follow pipeline +clocks. Shared dependency sources, physical inputs, native/Python binaries, +manifest/driver/site/controller and installed versions match. Submission bytes +match after the sole fresh-output-directory change. No environments or source +worktrees were duplicated. Generated outputs were 18.16 MB per variant. + + Baseline Candidate +Compilation seconds 1.533715 1.275819 +Execution seconds 8.276517 8.977410 +Total seconds 10.606973 11.012101 +Raw callable seconds 3.656715 3.975499 +Outside callable seconds 4.607542 4.990668 + +The candidate misses the required 0.7--1s execution payoff: observed execution +increased 0.700893s and outside-callable time increased 0.383127s. Finalization +exclusive time changed 0.209953 -> 0.480475s. These single observations are +falsification evidence, not statistical proof of a causal regression. The lower +compilation observation is not promoted as a gain. No full30/scaling acceptance +or new native clock is inferred. + +Full behavior controls +---------------------- + +The coherent consumer gate passed 570 tests; extended runtime boundaries passed +700 with nine failures. All nine exact original tests reproduce the same errors +on all 27 original e858 Git-blob modules with the same current dependencies; +none is waived or silently rewritten. The initial source-stem owner interface +failures were fixed before these gates. + +Both representative saved V10 edges preserve complete values, metadata, pixels, +masks, store/cache state and aliases: producer60records/123array roles and +loader104roles. A qualified offline dataclass-state decoder transfers original +stored references without constructor/capture/copy. Its instrumentation and +public realization occur outside different subclocks; edge timings are not +compared as whole-pipeline speedup evidence. + +Four complete comparisons (fresh baseline and candidate against each retained +native repetition) pass unchanged CellProfiler numerical tolerances and exact +image controls: six CSVs, 120 TIFFs (two logical volumes), schema, relationships, +full physical inventory and 180 ordered source references. Native witnesses, +inputs, source and outputs are hash-checked before and after. No scientific +output or earlier failed receipt is replaced. + +Architecture decision +--------------------- + +Flattening fields did not remove the semantic normalization lifecycle. Scalar +derivation still normalizes once and births provenance/identity plus two owner +allocations; leading-plane capture retains three normalizations and four +provenance/identity births. Public realization defers a real namespace allocation. +One source-context fusion removed a redundant normalization, but that narrow +route cannot materially close the full target gap alone. The earlier saved +normalization envelope is only 0.318s and contains mandatory work. + +Stop this representation route rather than polish namespace deferral. Next +inventory the existing authorities and production data flow for repeated graph +projection/validation/serialization and manifest/store/workspace derivation. +Fresh baseline publication 0.768611s, reconciliation 0.300908s, load 0.797152s, +save 0.656345s are investigation envelopes, not claimed removable time. Prefer +one existing nominal authority and derived views, retaining public mutable +namespace epochs, raw schema/order, alias/pixel ownership and first errors. + +Reproduction and custody +------------------------ + +Controller and site are retained byte-identically. Full local source/env freezes +remain at the absolute paths and SHA256 pins in baseline/candidate-source-pins. +Original helper scripts and native witness paths remain pinned there and in +strict-science. The saved V10 qualification preserves original graph/helper +hashes; its 1.027 GB capture is reused, not copied into this report. Exact rejected +production and tests remain reachable through the rejected Git commit. Run fresh +outputs only; finished evidence directories are immutable. diff --git a/benchmark/results/perf_rejected_metadata_owner_20261003/saved-v10-qualification.json b/benchmark/results/perf_rejected_metadata_owner_20261003/saved-v10-qualification.json new file mode 100644 index 0000000000..8e75749e5c --- /dev/null +++ b/benchmark/results/perf_rejected_metadata_owner_20261003/saved-v10-qualification.json @@ -0,0 +1,277 @@ +{ + "status": "SAVED_EDGE_PARITY_PASS", + "capture_source": "4c636a281de4da7341f4f9f6bb8f718c75644a1d", + "current_candidate_head": "e8587bd7eb0c4aa283bc300c5eb9f2294f24890f", + "current_candidate_dirty_status": " M openhcs/core/aligned_image_payload.py\n M openhcs/core/artifacts.py\n M openhcs/core/image_file_serialization.py\n M openhcs/core/measurement_image_alignment.py\n M openhcs/core/runtime_adapters.py\n M openhcs/core/runtime_image_loading.py\n M openhcs/core/runtime_image_values.py\n M openhcs/core/runtime_object_labels.py\n M openhcs/core/runtime_slice_projection.py\n M openhcs/core/source_image_semantics.py\n M openhcs/core/source_plane_alignment.py\n M openhcs/core/source_workspace_projection.py\n M openhcs/core/steps/function_artifact_materialization.py\n M openhcs/core/steps/function_io.py\n M openhcs/core/steps/function_output_identity.py\n M openhcs/core/steps/function_output_manifest.py\n M openhcs/core/steps/function_outputs.py\n M openhcs/core/steps/function_runtime.py\n M openhcs/interop/cellprofiler/module_artifact_declarations.py\n M openhcs/interop/cellprofiler/runtime/artifact_binding.py\n M openhcs/interop/cellprofiler/runtime/function_contract_execution.py\n M openhcs/interop/cellprofiler/runtime/invocation.py\n M openhcs/interop/cellprofiler/runtime/main_flow.py\n M openhcs/interop/cellprofiler/runtime/measurement_recording.py\n M openhcs/interop/cellprofiler/runtime/module_execution.py\n M openhcs/interop/cellprofiler/runtime/output_record_request.py\n M openhcs/processing/materialization/core.py\n?? tests/unit/test_cellprofiler_metadata_projection_consumers.py\n?? tests/unit/test_function_output_metadata_projection.py\n?? tests/unit/test_image_metadata_owner_consumers.py\n?? tests/unit/test_image_metadata_projection_owner.py\n?? tests/unit/test_metadata_stage2_closure.py\n", + "current_candidate_source_pin_sha256": "096287ee7e010297806ffbccdf50b6a28287f5575cb59059ab079c27855c104b", + "current_candidate_source_pin_in": "/home/ts/.local/state/openhcs-maintenance/20261003/v10-current-carrier-transfer-v1/producer13-current-replay-v1.json", + "source_before_after_unchanged_both_replays": true, + "tiny_gate": { + "status": "PASS", + "scope": "Exact retained list state, original dataclass setter, stored-path order; pixels/mask/namespace/provenance/identity/birthday/cache refs borrowed unchanged; shared namespace mutation preserved; no production compatibility", + "types": [ + "ImageMetadataPayload", + "MaskedImagePayload", + "ProducedOutputSemantics" + ], + "field_order": { + "ImageMetadataPayload": [ + "data", + "metadata" + ], + "MaskedImagePayload": [ + "data", + "mask", + "metadata" + ], + "ProducedOutputSemantics": [ + "component_values", + "extension", + "source", + "filename_component_values", + "filename_qualifier", + "producer_identity", + "output_path", + "relative_output_path", + "image_metadata", + "main_flow_plane_axis" + ] + }, + "provenance_births_during_transfer": 0, + "pixel_strides": [ + 24, + -4 + ], + "mask_writeable": false, + "adapter_sha256": "3d9b67a2e59966352cf222c577437a86ea17ad5e3a5bde5de787c06474547be6" + }, + "artifacts": { + "adapter.py": { + "path": "/home/ts/.local/state/openhcs-maintenance/20261003/v10-current-carrier-transfer-v1/adapter.py", + "bytes": 2798, + "sha256": "3d9b67a2e59966352cf222c577437a86ea17ad5e3a5bde5de787c06474547be6" + }, + "qualify_tiny.py": { + "path": "/home/ts/.local/state/openhcs-maintenance/20261003/v10-current-carrier-transfer-v1/qualify_tiny.py", + "bytes": 4018, + "sha256": "9752d3033c558d39e533a3d3f1dab25b6350f65f42edefc04a6ac52a3237f316" + }, + "qualify_tiny-first-red.py": { + "path": "/home/ts/.local/state/openhcs-maintenance/20261003/v10-current-carrier-transfer-v1/qualify_tiny-first-red.py", + "bytes": 4025, + "sha256": "9d47c0f66837d3f01cdbfaef9177ad103ff45bf01cf47dbec3dfd806c3af847f" + }, + "tiny-qualification.json": { + "path": "/home/ts/.local/state/openhcs-maintenance/20261003/v10-current-carrier-transfer-v1/tiny-qualification.json", + "bytes": 1023, + "sha256": "b5ecdd2b006c641a0718e12448a8779723e21376fde2e749f538587ace6939fb" + }, + "replay.py": { + "path": "/home/ts/.local/state/openhcs-maintenance/20261003/v10-current-carrier-transfer-v1/replay.py", + "bytes": 4672, + "sha256": "d16609418f6e436c3e84ff5f8e640acc26f076fafdac216ac0c3ab5d59ab3740" + }, + "producer13-current-replay-v1.json": { + "path": "/home/ts/.local/state/openhcs-maintenance/20261003/v10-current-carrier-transfer-v1/producer13-current-replay-v1.json", + "bytes": 214799, + "sha256": "da77685ccf6dcfa984a605182243ca9e0b67bdf412e7a77e94037be5b57cc022" + }, + "producer13-current-replay-v1.log": { + "path": "/home/ts/.local/state/openhcs-maintenance/20261003/v10-current-carrier-transfer-v1/producer13-current-replay-v1.log", + "bytes": 1806, + "sha256": "e8b99fb4533034b391cfd7afa86cdeab80ef845ac0837eea87835ff6784b153a" + }, + "loader14-current-replay-v1.json": { + "path": "/home/ts/.local/state/openhcs-maintenance/20261003/v10-current-carrier-transfer-v1/loader14-current-replay-v1.json", + "bytes": 214721, + "sha256": "7651099dbe290ee91e85c9d9019a68faaa1fd28bddc6e4a81dc2878b40ab80f1" + }, + "loader14-current-replay-v1.log": { + "path": "/home/ts/.local/state/openhcs-maintenance/20261003/v10-current-carrier-transfer-v1/loader14-current-replay-v1.log", + "bytes": 1736, + "sha256": "9008c60ad1ac5ead5d5aa163a8fc8f5f9746234d0a9a9c323e74e9a64aa73e0f" + }, + "immediate_producer.py": { + "path": "/home/ts/.local/state/openhcs-maintenance/20261003/v10-current-carrier-transfer-v1/immediate_producer.py", + "bytes": 1058, + "sha256": "4a67fdba8238acf915bbbb4ca1f11b4e62811458a0dae1998c6be8077cc43bda" + }, + "producer13-full-immediate-effects-v1.json": { + "path": "/home/ts/.local/state/openhcs-maintenance/20261003/v10-current-carrier-transfer-v1/producer13-full-immediate-effects-v1.json", + "bytes": 1263, + "sha256": "5770905b2918cca5b9ab722e6dd712a469937f161ef4892e389b660d575c155b" + }, + "producer13-full-immediate-effects-v1.log": { + "path": "/home/ts/.local/state/openhcs-maintenance/20261003/v10-current-carrier-transfer-v1/producer13-full-immediate-effects-v1.log", + "bytes": 1227, + "sha256": "fbe470fe158facb1072cc385ca3f31e237854bc9744271bd88e88d6b0f36f5fa" + }, + "inspect_layout.py": { + "path": "/home/ts/.local/state/openhcs-maintenance/20261003/v10-current-carrier-transfer-v1/inspect_layout.py", + "bytes": 2129, + "sha256": "94b649935213c706fe338e493192ac8e63f908a86fdff929fb938f0c1dae66e6" + }, + "finalize.py": { + "path": "/home/ts/.local/state/openhcs-maintenance/20261003/v10-current-carrier-transfer-v1/finalize.py", + "bytes": 5170, + "sha256": "3ef583b07f244fa068decc921c88eecd8998d90289f2417eac1ce6b088092d05" + } + }, + "original_helper_hashes": { + "original_replay_v10.py": "7001af6479a05e0dd1afc52a1509a44fed45ce1d0c1151dee3b832dc7a96a74a", + "immediate_original_effects_v10.py": "66848b5c5f5dcf0ccf7552420754aaab2005dc1a2c563961c6b6bc8d49748728", + "site/openhcs_cohort_snapshot_transport_v6_20261002.py": "a8b11cf6401aa0f80617e6734ae67bbbffcecc74ad4f7a59041523e42b850763", + "site/nested_cache_retention.py": "7e6d9ca3e7dce0da18a603610576cc9eea2d8038ad936fe2599e5b87d94bf3b1", + "site/ordered_array_role_oracle.py": "cf6b799a8ade0dbf82185fdc2a80f242111b784e1e643f4e91ea3456a6c5718b", + "site/openhcs_current_cohort_capture_v10_20261003.py": "ec9af29df043c9f465ba410c7317b6668d903fca3d3308f70716a350e096c98a", + "output/source-freeze.json": "6d4f4a59e62acbebbd6e21fcff66fa5806f45d99778264e7f5399b666bb3171f", + "output/observations.json": "1559ae44e06fed622816b1518132fd738f56e0355faadf9e15cdd2159052f491" + }, + "actual_captures": [ + { + "key": "13-PatternGroupRuntime-_validate_and_unstack-before", + "path": "/home/ts/.local/state/openhcs-maintenance/20261003/current-cohort-capture-v10/output/saved-inputs/root-813175-139641010583232-0002/cohort-13-PatternGroupRuntime-_validate_and_unstack-before.pkl", + "bytes": 272201079, + "array_count": 1184, + "sha256": "3c49c2ebc3050c4bd9e62052d7a6e9acd6c095f23849f80f86a115041c544519", + "sidecar_sha256": "3ca071d05e7516eda02f3d0cbb6f6f77d6d3defee63991af3f147247eef5bd0b", + "inventory_canonical_json_sha256": "af1e5133dd2b47972c2a624eff9e004c12cdc2b54b35ab3701ce19cada83881b", + "nested_cache_witness_canonical_json_sha256": "987bdfb47a6e95c9afedf23a716af99c9319a3990f95f4d6b5b69f94659dc9bb" + }, + { + "key": "13-save-oracle", + "path": "/home/ts/.local/state/openhcs-maintenance/20261003/current-cohort-capture-v10/output/saved-inputs/root-813175-139641010583232-0002/cohort-13-save-oracle.pkl", + "bytes": 194819278, + "array_count": 1234, + "sha256": "c9ed3ce36c322a5d32aeb03f65b1d8d2697775e61231a6d433dae66e7d290542", + "sidecar_sha256": "dec76667df2aa673785cc176e23d309ca3fc6a552adbdd67ce957d4e0194e8c0", + "inventory_canonical_json_sha256": "2176c9eb60971f28a8f9ed04fbd4a7cb9b212468669ae798e85072b370eb2aa8", + "nested_cache_witness_canonical_json_sha256": "88629f21cd2376e902be7d548ae21f5f06c8c603b4087fb6b0b3d5b008ffc131" + }, + { + "key": "14-PatternGroupRuntime-_load_input_stack-before", + "path": "/home/ts/.local/state/openhcs-maintenance/20261003/current-cohort-capture-v10/output/saved-inputs/root-813175-139641010583232-0002/cohort-14-PatternGroupRuntime-_load_input_stack-before.pkl", + "bytes": 280297985, + "array_count": 1244, + "sha256": "2a48c08fdf3eecfdd5af13b0052ce985a21469dbbe5e5c4f97be69682a933780", + "sidecar_sha256": "8b6f277dc8d1765e3d6b68f816a91b0b762df72f3128b3294de0f5b513455d26", + "inventory_canonical_json_sha256": "266deec29a18a1410cdc1d06f3ccf1a960e12712052d7125983a1be4a3c60dbe", + "nested_cache_witness_canonical_json_sha256": "ac01f6a886bac198005c953bc4fed12a2cd5f54892ac59ce4db98f7b1d0bc416" + }, + { + "key": "14-load-oracle", + "path": "/home/ts/.local/state/openhcs-maintenance/20261003/current-cohort-capture-v10/output/saved-inputs/root-813175-139641010583232-0002/cohort-14-load-oracle.pkl", + "bytes": 280362714, + "array_count": 1244, + "sha256": "20c4d2721789d5c9dfdce4e6ff789cbcfb59d49e87ba53e042deb75be5c3bde7", + "sidecar_sha256": "67f9015dde0043870494880620dabbb8e5ea17feb08a1da1ad21398b032228b6", + "inventory_canonical_json_sha256": "24536b96aff10ad624c19a6048d0dfab0683a6aee23d54d91252f7866b73f124", + "nested_cache_witness_canonical_json_sha256": "bc4f64d6dd34c4730db6b8c0ab6b55da459f4259efa31161b8acf8ae8bafaefb" + } + ], + "producer": { + "kind": "producer13", + "status": "PASS", + "original_call_started": true, + "original_nested_owner_count": 1054, + "original_nonempty_views": 677, + "nested_exact_capture_refs_restored": true, + "captured_external_manifest_available": true, + "input_fixture": "/home/ts/.local/state/openhcs-maintenance/20261003/current-cohort-capture-v10/output/saved-inputs/root-813175-139641010583232-0002/cohort-13-PatternGroupRuntime-_validate_and_unstack-before.pkl", + "transport": { + "root_type": null, + "array_count": 1184, + "strict_snapshot_restore": true + }, + "original_declaring_method_counts": {}, + "records": 60, + "unstack_seconds": 0.02488934900611639, + "save_seconds": 1.2471533310599625, + "full_outputdata_records_planes_named_whole_equal": true, + "complete_array_alias_graph": true, + "array_roles": 123 + }, + "loader": { + "kind": "loader14", + "status": "PASS", + "original_call_started": true, + "original_nested_owner_count": 1115, + "original_nonempty_views": 738, + "nested_exact_capture_refs_restored": true, + "captured_external_manifest_available": true, + "input_fixture": "/home/ts/.local/state/openhcs-maintenance/20261003/current-cohort-capture-v10/output/saved-inputs/root-813175-139641010583232-0002/cohort-14-PatternGroupRuntime-_load_input_stack-before.pkl", + "transport": { + "root_type": null, + "array_count": 1244, + "strict_snapshot_restore": true + }, + "original_declaring_method_counts": {}, + "load_seconds": 1.1413843147456646, + "full_loaded_metadata_store_cache_equal": true, + "complete_array_alias_graph": true, + "array_roles": 104 + }, + "immediate_owner_effects": { + "producer13": [ + { + "method": "_save_outputs", + "actual_method_seconds": 0.12108967360109091, + "before_owners": 1054, + "before_nonempty_views": 677, + "before_view_entries": 4286, + "after_owners": 1115, + "changed_before_owner_fields": [], + "new_reachable_owner_count": 61 + } + ], + "loader14": [ + { + "method": "_load_input_stack", + "actual_method_seconds": 0.011172774713486433, + "before_owners": 1115, + "before_nonempty_views": 738, + "before_view_entries": 4408, + "after_owners": 1116, + "changed_before_owner_fields": [], + "new_reachable_owner_count": 1 + } + ] + }, + "supplemental_whole_producer_immediate": { + "receipt": "/home/ts/.local/state/openhcs-maintenance/20261003/v10-current-carrier-transfer-v1/producer13-full-immediate-effects-v1.json", + "status": "IMMEDIATE_RETAINED_OWNER_EFFECTS_PASS", + "scope": "Original immediate-effects algorithm across both unstack/save, observed before equality. No independent source-before/after hash check on this extra supplemental run; do not extend the pinned decisive gate from it." + }, + "timing_scope": { + "performance_claim": false, + "producer_unstack_outer_seconds": 0.02488934900611639, + "producer_save_actual_method_seconds": 0.12108967360109091, + "loader_actual_method_seconds": 0.011172774713486433, + "public_oracle_equality_realization_seconds": { + "producer13": 0.47686423640698195, + "loader14": 0.8740706979297101 + }, + "warning": "Not a matched original-vs-candidate timing experiment. Passive graph witness observation contaminates outer harness save/load clocks; inner method timings exclude witness but may include normal GC and cold process/global caches. Public realization/equality occurs after method timers and is recorded separately. No extrapolation to whole-driver gain or earlier edge clocks." + }, + "first_harness_failure": { + "script": "/home/ts/.local/state/openhcs-maintenance/20261003/v10-current-carrier-transfer-v1/qualify_tiny-first-red.py", + "error": "AttributeError SourceImageIdentity.source_component_metadata; corrected diagnostic member to actual component_metadata. No production failure or source change." + }, + "limits": { + "existing_snapshot_item_MiB": 384, + "existing_snapshot_total_MiB": 1024, + "new_graph_captures": 0, + "new_environments": 0, + "source_edits": 0, + "scratch_limit_MiB": 20, + "actual_artifact_bytes": 460445 + }, + "processes": "All own replay handles terminal/closed; no further source reads/imports while root baseline executes.", + "qualification_scope": "Exact independent producer13 and loader14 original saved receivers and oracles. Stdlib old dataclass list assignment only into same current nominal carrier types; original warm retained owner references and caches restored, no default fabrication, graph union, pixel/mask copies, or production compatibility layer. Full saved role values/arrays/masks/source metadata/store/cache/nonmutation/alias gates passed under current dirty candidate. Does not cover whole upstream request/record path or end-to-end performance.", + "original_full_qualification": { + "path": "/home/ts/.local/state/openhcs-maintenance/20261003/v10-current-carrier-transfer-v1/qualification.json", + "sha256": "39902e79c6197d21eb1a469c4ec35024f1081e05a443fe55c8ad4800b10dc712", + "bytes": 10930144, + "note": "Full capture inventories and nested warm-state witnesses remain immutable in original qualification/capture sidecars. This compact report derives pins rather than duplicating those rosters." + } +} diff --git a/benchmark/results/perf_rejected_metadata_owner_20261003/science-terminal.json b/benchmark/results/perf_rejected_metadata_owner_20261003/science-terminal.json new file mode 100644 index 0000000000..8261fa4fd9 --- /dev/null +++ b/benchmark/results/perf_rejected_metadata_owner_20261003/science-terminal.json @@ -0,0 +1,39 @@ +{ + "status": "STRICT_SCIENCE_PASS_PERFORMANCE_ROUTE_REJECTED", + "session": 68950, + "returncode": 0, + "source": "9eee98265c939859d49f0c60bd5b3a2168cb29fe", + "comparisons": 4, + "scope": "Fresh baseline and candidate vs both existing native repetitions, original compare function, original policies; no native rerun and no performance promotion.", + "gates": "Exact120 candidate TIFFs against2 native volume TIFFs through existing logical owners; six candidate CSV vs existing native7-table representation; strict schema/discrete/numerical/relationship correlations/full physical inventory; 180 ordered source references; all input/native/output/source hashes unchanged.", + "performance_parent_observations": { + "baseline_execute_seconds": 8.27651668, + "candidate_execute_seconds": 8.97740984, + "decision": "STOPPED by root; single source pair descriptive only" + }, + "files": [ + { + "path": "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-science-v1/compare.py", + "sha256": "b28035313a58a2c90d0824a71483f575db9c28c830f9d11f2d962f4ffc978b06", + "bytes": 8186 + }, + { + "path": "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-science-v1/prep.json", + "sha256": "99d0f1996e262bb15ed0a2160b29d4f4c0fff42ef1d95ac1a6395cca325a7051", + "bytes": 7092 + }, + { + "path": "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-science-v1/compare.log", + "sha256": "7e25cd2d6d31fefea7e748430aef4769062f2220a201c0564c5d67dd8143d624", + "bytes": 366 + }, + { + "path": "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-science-v1/strict-science.json", + "sha256": "b9a35a8504dc4a2dc96d4e8e4263335be9f8c70f0b14b45e1f92aa3c8d3c6b45", + "bytes": 268580 + } + ], + "print_notice": "Original comparator prints its original strict-science destination; write adapter actually stores ONLY this directory strict-science.json. Old native qualification file SHA checked unchanged.", + "all_handles_terminal": true, + "scratch_bytes": 284224 +} diff --git a/benchmark/results/perf_rejected_metadata_owner_20261003/strict-science.json b/benchmark/results/perf_rejected_metadata_owner_20261003/strict-science.json new file mode 100644 index 0000000000..51a8fce09d --- /dev/null +++ b/benchmark/results/perf_rejected_metadata_owner_20261003/strict-science.json @@ -0,0 +1,1023 @@ +{ + "status": "PASS", + "comparisons": [ + { + "case": "cp_tutorial_3d_monolayer", + "ordinary_repeat": 0, + "native_repeat": 0, + "measurement_differences": 0, + "image_differences": 0, + "tables": [ + 7, + 6 + ], + "physical_images": [ + 2, + 120 + ], + "logical_images": [ + 2, + 2 + ], + "known_relationship_keys": [ + 3, + 3 + ], + "ordinary_receipt_sha256": "da9430eb33c8e5724edc9c28431ff22848bef9a0eda94da59139b20a3349058e", + "output_hashes": { + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/native/cp_tutorial_3d_monolayer/outputs/0/3d_monolayer_downsizedNuclei.csv": "2c66bc7b17de52147d5a875403f9a9746019ac61371c08157979044c6ed818dd", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/native/cp_tutorial_3d_monolayer/outputs/0/3d_monolayer_Cells.csv": "cc34681db8a66c38ca77bc47db496b26703f21e4d7c7628dd74e30c33250859f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/native/cp_tutorial_3d_monolayer/outputs/0/3d_monolayer_xy1_ch2_NucleiLabels.tiff": "340bbd795541e4031749d1fff767fa4fcdcac10f5b97879056b25dac9fd7674b", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/native/cp_tutorial_3d_monolayer/outputs/0/3d_monolayer_xy1_ch0_CellsLabels.tiff": "aaed9ed23179a162ee7f5a7e8d1d88f1fa342ca55172b7fccd4cbf67f7841d81", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/native/cp_tutorial_3d_monolayer/outputs/0/3d_monolayer_erodedDownsizedNuclei.csv": "527a0cce497d2a618478be84d1a0bf174049f58aa2a666e37626a990fdca0116", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/native/cp_tutorial_3d_monolayer/outputs/0/3d_monolayer_erodedResizedNuclei.csv": "66a58f78cab0cfdbe907468e8ba383fc59fab49025b84b589855bdfa04854609", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/native/cp_tutorial_3d_monolayer/outputs/0/3d_monolayer_Nuclei.csv": "440c33edc7e8cb5611910a835454db62390301a7af617a542349f60aece57561", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/native/cp_tutorial_3d_monolayer/outputs/0/3d_monolayer_Image.csv": "1f3dec653b6909c8a81ac109ce1faf91380886ac9a18e56fafc91102d419904e", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/native/cp_tutorial_3d_monolayer/outputs/0/3d_monolayer_Experiment.csv": "c05f0a11f43a5bda943e9f739ff257216f8ab3f65d8988a0d3d0c612c1db6997", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z017_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z037_t001_NucleiLabels.tiff": "927d52441c57cb3a4014effaca3e3c23c76275fb264c26e1942a9c58b85ee6d2", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z044_t001_NucleiLabels.tiff": "a78264f2f5e245a3913a69f89105e94df30048b1aaef4eb80fc5c3235e78b196", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z052_t001_NucleiLabels.tiff": "0daf51526658e23b7c9ab8872e992ebe9322399286f95741d0ccdbd357e5d631", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z007_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z047_t001_NucleiLabels.tiff": "995d5ce77cbf61a9be8590f34987ef3f1dd698ae6ed393cac4d0960bc9e7a66a", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z019_t001_CellsLabels.tiff": "ec6ef1d319f2732c47b06f5cf02775c8cd94540f2f30a6c002f0aace1d317955", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z032_t001_CellsLabels.tiff": "8a2c5774044326ae722e41aae517266197fbebb0e4dd5eab4b22414fbfea309f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z045_t001_CellsLabels.tiff": "c678f2100c7431e5a43c391af86a79e3436d4cf13f050f98c25f62682e4632fe", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z028_t001_NucleiLabels.tiff": "1676f21bd3b7e105601c83f206890507c32ba2447988be2a75d0e8153d069b65", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z039_t001_NucleiLabels.tiff": "f93e8293a37886a36844b8748083a1f8e717efab092652755263e797f12f0364", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z055_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z047_t001_CellsLabels.tiff": "b926aa64e1fa8aa52279a69d91dc23cf14bf0ae76107f9b360c7ae77bdf53719", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z054_t001_NucleiLabels.tiff": "b841c5d901c65a6138d9ff2b0ec4aa04f00765b1dd21bcd6fc9f8dc974c6035d", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z054_t001_CellsLabels.tiff": "25ff2ec586a568e42286f73713d64aab1208c38c016099299211f04368ac49c8", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z048_t001_CellsLabels.tiff": "133a58f6fac8b07f79bfed9634867ccb5428b83e63682031a1def16c6a694568", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z019_t001_NucleiLabels.tiff": "250cb56a8054c28cea894bc3d9edaddcdce01f5151a05da78da20157c3c3be9f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z005_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z023_t001_NucleiLabels.tiff": "ecb7f78c8ca0bad2b9d0495659609b9023781b6a936d6afb0a04653eac176555", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z040_t001_CellsLabels.tiff": "1635ea20dd80ce99f0e86494666825a52a66645837d598fd3a3fa91f0bb77d53", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z046_t001_NucleiLabels.tiff": "c1250e060d32f2cfc07fc7e1594fdb1d6cbb4d0483fa94a8113efa695397963c", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z003_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z010_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z022_t001_NucleiLabels.tiff": "50aef20e28a2f9e18ca2e28eabf6d87ec2ad20c79898e56f8d63a959ba5bb507", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z010_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z026_t001_NucleiLabels.tiff": "ad22809ff3f43d15c838f697061c263070dbf1da1031da39900681cdfbf9d54c", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z041_t001_CellsLabels.tiff": "be7762756eb65f08cb337904165c6f43b5351f39405461f65ad28669abfe3899", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z027_t001_NucleiLabels.tiff": "8c8f402d3a7c65c04e7f1575dd34de0427eeeb433ff2956d20e07d06eb48fb8d", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z042_t001_NucleiLabels.tiff": "e07252ca1a55c5195c99666d8d3f0d70db636b4ef4b99e1a0049ca22b182d87a", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z029_t001_NucleiLabels.tiff": "34bce0f06f674e20667554eed0075fde8d9d33c9c0eaeffd88a1c558499cc432", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z001_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z051_t001_NucleiLabels.tiff": "f0f36ccaf744d42da036948682cfd226e6dd4a3cfb94aed38729b2d25ede5dff", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z024_t001_CellsLabels.tiff": "39899adabca74b10b9950d1f97e8b0b3bbaf136d75e7a46ef4a6e86896e3119f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z003_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z035_t001_CellsLabels.tiff": "eedeb489b46abf1eafbd9c81491cb3f85ce1cb3ce877844ad22e72547fc3c438", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z038_t001_NucleiLabels.tiff": "e2852ea83c62ab30d77681b4e39f88d3cee74ae052f1c948675ae3581c9fc28a", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z009_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z056_t001_NucleiLabels.tiff": "ca0723c8b9764d5b77034719bb75a2940be35da2e04119af4c0e6d3552c08718", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z020_t001_NucleiLabels.tiff": "b0cd031b448d8bd2075e65710bd76c064161b25242f85ee150da7cd139fcc1a8", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z039_t001_CellsLabels.tiff": "22fa79a76e64013f10373be2ca2af98a2173275c5d43c9cad33135acdc376d14", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z007_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z021_t001_NucleiLabels.tiff": "71a10b0539f3fc4cba600b275b7e948258c6a435ba33ef522faa0869ac085518", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z026_t001_CellsLabels.tiff": "5b433d931fa6637fc793b23880199c01000ef6d9e610903bb38bb8cea5574563", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z037_t001_CellsLabels.tiff": "aa1f449f1769b27cd9f1076e70f49f0242e2549f288a77984ca159cb07cf6a40", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z050_t001_NucleiLabels.tiff": "565b4f08f7503086c1f2f8e631d19063129e02a5767d2f979c0cec8fdec23601", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z032_t001_NucleiLabels.tiff": "97b09fe5444ad439c3c2007d75971dce2766d94c93268eccfee9ae49b8a04aa1", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z001_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z046_t001_CellsLabels.tiff": "dc081df050be6cd19b5d5bbfe21c96c350eecf9bc6f10f608dc361a36056632a", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z020_t001_CellsLabels.tiff": "e8105a4f04198ac75de9831247030084d6f65bf98691d7444ead7e178072fa22", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z033_t001_NucleiLabels.tiff": "512a3a0ed8025d14b0556a72ebfc13b173d14f7046817ca09876242ab63b9d6b", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z025_t001_NucleiLabels.tiff": "9cc33676a0177130609ab1331feab1722bbde8d55b2f49031730fd5a2a40029c", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z015_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z018_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z036_t001_CellsLabels.tiff": "28b68d1300cf7b08e21dbcd4858447862520dded5c27f2d84cf223513a119eed", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z008_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z030_t001_CellsLabels.tiff": "b71a2e05d270ae0cd237d6c0d97ea82a63e5ad3633723e7255c35d34e585ec80", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z031_t001_CellsLabels.tiff": "1b14aab71bf3623458ea9373852b0baf28be9727877b32f894407927ecfb6d65", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z016_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z015_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z055_t001_NucleiLabels.tiff": "44e02416cc94a70528165a4b6c42b9e19b205f9c91528076796272cb1a8504ea", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z056_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z021_t001_CellsLabels.tiff": "daa31cb1e537e5c32b1936ab7647c5690741d2bc1d0e15c60b59ba1310a8c0ce", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z022_t001_CellsLabels.tiff": "7d7ec170ed3652efa99e43d8db546c51b696821dca7727d0ff4d2f2ead7fdbaa", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z027_t001_CellsLabels.tiff": "ee9056587a19e581f5feb6078b41fa1004d923a5ddf1725aefc4b8b8c5201ad6", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z057_t001_NucleiLabels.tiff": "695517641e9fe4b8421d4a7db56b24c755b6957c98ce32bb24ad5b25f52661eb", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z057_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z041_t001_NucleiLabels.tiff": "744eab7cd170d5af8d2f72ced3893dd939c4e1b0f415afab799a37ded5d046c7", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z042_t001_CellsLabels.tiff": "88d2e9964455459499656c4f0a762cd86376c678756635aaa6b6c8d98be01852", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z013_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z008_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/openhcs_metadata.json": "b683f94e72c5c8a1f41b7680379e158dfc1caaea6659391cf24e0ee8e470e008", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z049_t001_NucleiLabels.tiff": "e92e493078672a0e0d90e31409612e215bf8486300d5c765d0e0504ff8888e7a", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z043_t001_NucleiLabels.tiff": "81a705d05b0a5bfa8783df28990c1d70634c1f4aa2bca23e02cfa8a4bc861b86", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z052_t001_CellsLabels.tiff": "7bb98f0587062e01b965e486fc687872651d7d90d271a2fdf0d35d67b464b233", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z031_t001_NucleiLabels.tiff": "247490c261fecc26c7379ab2eebaa01e4bea523218b3cc5491d2fe2b9aadfe11", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z011_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z014_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z016_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z058_t001_NucleiLabels.tiff": "a37c63c6052e40d73db918a014e6f2a18be4d0cbfbeeef65a9c26096a38a4c09", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/results/3d_monolayer_Image.csv": "75ac32ff5ef57bc285ec4eae1c9b501c27a35b486bf35435af5d499d856d34a4", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z036_t001_NucleiLabels.tiff": "4fa967c78709aa400246a50528a36b24ca366e825dd0e64561643369e814906b", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z060_t001_NucleiLabels.tiff": "7cc3c6c6a22f558e62194277090bdea2deb79475dd91fe7d0e49eac3c0187388", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z006_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z029_t001_CellsLabels.tiff": "b3bdde5f751b8f5d41ca8b5219a3427e450cb1b8795401d0ec638940d1ad7bd9", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z025_t001_CellsLabels.tiff": "03aabe5528198cfd6ec23a058dab540fb8be0870207c6dc94a62d9b621d1f2f9", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z004_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z060_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z013_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z014_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z024_t001_NucleiLabels.tiff": "9e96a05ed9860cac9c57c618db2f4fe5e4b769a9d235aac6fd1d628486317df0", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/openhcs_metadata.json.lock": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z005_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z044_t001_CellsLabels.tiff": "e03946d94c789ee787cc29a3c8f5e5d9c56b37a0044b297ba8f403abc98eb55e", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z002_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z034_t001_CellsLabels.tiff": "3f6c1d8cdbce20aac8f70e7315bea70b147b7b6a034432845b27eeb6cfba083c", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z038_t001_CellsLabels.tiff": "6ac8fd9c95acc1f261e96a8fb9332e5d6a403548842f9b85ecb977e6213b4c9b", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z033_t001_CellsLabels.tiff": "a320b99ee129d97b99f9fac66aabb89fc1652930b3bb8b2b3fbba7b57e994f85", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z049_t001_CellsLabels.tiff": "28d83dfbf5bbf7e4da9c3e4806353e9fd0a89680dcdab4b43ca2fd19b80f669c", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z053_t001_CellsLabels.tiff": "ff17f538baaf179752412026a250bdbee016e3101037bf4e0dbb81199fc4c8ed", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z009_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z043_t001_CellsLabels.tiff": "bd0df007524ea4e555e4d2fdbebe6a274caa03bc360a1cf90d601659155984b2", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z030_t001_NucleiLabels.tiff": "c54c8b98a5c38a47e0cf9391a1afab09b4c8c58e06294cdb650a15add4a32b58", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z002_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z023_t001_CellsLabels.tiff": "2f06989618050934c73473f9342c2fe3410fd834a0ddb976cf602fe6198db7a6", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z006_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/results/3d_monolayer_Nuclei.csv": "17500f5d4321bbf255df31f7a3503339029c2b077045a6c10e4d4f6f0db9ad1e", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z040_t001_NucleiLabels.tiff": "e0bd66b166e9f92120dbee183973849eda0afbbe6fed9d03fc4cfd2c56a96280", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z017_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z012_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z058_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/results/3d_monolayer_Cells.csv": "6f6e7431171ed5ea73a01784105147eca0e43a6e3e41f8720df93106353c9c79", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z059_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z035_t001_NucleiLabels.tiff": "13e69afc324152bb91329fa758d131d849127e8fd346078d94c6adc25582b3a6", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z045_t001_NucleiLabels.tiff": "94bd6a65795ad6395cc18a4fd63dc591354bef612ee49fffd2d9f63e4ed9db84", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z050_t001_CellsLabels.tiff": "ea7654a6fe1f92ad274a54935420923eec4bec5ad030187afc0ac7af02690af5", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z051_t001_CellsLabels.tiff": "73483bd10a0f37990084013ad054768086d6d3c929da6bc7e74f4aee37e9dbf2", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/results/3d_monolayer_erodedDownsizedNuclei.csv": "ee507fb9c2387f86fc768184baf2596ebe1f8e40f7fc5eb24f252345fee63ae6", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z012_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z011_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/results/3d_monolayer_erodedResizedNuclei.csv": "cca23f86a85bb3ee7a5c3a1d174c34b5f026ca7f399be98458e1a8c6e12d5c77", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z059_t001_NucleiLabels.tiff": "76c785cf0f481c73ad3cf34ccb576eaa19dd1bdd9c74f9eaf92adfbde5d44b97", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z028_t001_CellsLabels.tiff": "fef31040e0c54501c3bf965eb98f055cdb1d42c96f91cf1c239033d0a9a06534", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z034_t001_NucleiLabels.tiff": "08af61857cfb97fd95fcb08d1ce18139ce7087b192044c63452bee533c5b1aa4", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z053_t001_NucleiLabels.tiff": "b8613192175a4615b58aed607474657668429cb6ac635cd012569b19667f2d3d", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/results/3d_monolayer_downsizedNuclei.csv": "a7b998c5a524e11747fc5452fd763fc3d9abe16f46e961f62e09e9393b6a8adf", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z004_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z018_t001_NucleiLabels.tiff": "03ba7a4d6ae53e6c84aab5926ae1e2592b5f8ca24a839a256c82f08544df4270", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z048_t001_NucleiLabels.tiff": "325478230529e94ba372f38f0bf512292f131d337b6ac09ce5a91b0266724e02" + }, + "cohort": "plane-facts-whole-driver-baseline-v1" + }, + { + "case": "cp_tutorial_3d_monolayer", + "ordinary_repeat": 0, + "native_repeat": 1, + "measurement_differences": 0, + "image_differences": 0, + "tables": [ + 7, + 6 + ], + "physical_images": [ + 2, + 120 + ], + "logical_images": [ + 2, + 2 + ], + "known_relationship_keys": [ + 3, + 3 + ], + "ordinary_receipt_sha256": "da9430eb33c8e5724edc9c28431ff22848bef9a0eda94da59139b20a3349058e", + "output_hashes": { + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/native/cp_tutorial_3d_monolayer/outputs/1/3d_monolayer_downsizedNuclei.csv": "2c66bc7b17de52147d5a875403f9a9746019ac61371c08157979044c6ed818dd", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/native/cp_tutorial_3d_monolayer/outputs/1/3d_monolayer_xy1_ch0_CellsLabels.tiff": "aaed9ed23179a162ee7f5a7e8d1d88f1fa342ca55172b7fccd4cbf67f7841d81", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/native/cp_tutorial_3d_monolayer/outputs/1/3d_monolayer_Image.csv": "4cde74a38ef73b892dd9012708a3ac7d71fab206a7903f525b39e84493dcfe17", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/native/cp_tutorial_3d_monolayer/outputs/1/3d_monolayer_Cells.csv": "cc34681db8a66c38ca77bc47db496b26703f21e4d7c7628dd74e30c33250859f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/native/cp_tutorial_3d_monolayer/outputs/1/3d_monolayer_erodedResizedNuclei.csv": "66a58f78cab0cfdbe907468e8ba383fc59fab49025b84b589855bdfa04854609", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/native/cp_tutorial_3d_monolayer/outputs/1/3d_monolayer_Experiment.csv": "65f1f124e99f13ddc73b71d01732262cd353f24f0bd4697a776b274a39eaecc5", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/native/cp_tutorial_3d_monolayer/outputs/1/3d_monolayer_Nuclei.csv": "440c33edc7e8cb5611910a835454db62390301a7af617a542349f60aece57561", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/native/cp_tutorial_3d_monolayer/outputs/1/3d_monolayer_erodedDownsizedNuclei.csv": "527a0cce497d2a618478be84d1a0bf174049f58aa2a666e37626a990fdca0116", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/native/cp_tutorial_3d_monolayer/outputs/1/3d_monolayer_xy1_ch2_NucleiLabels.tiff": "340bbd795541e4031749d1fff767fa4fcdcac10f5b97879056b25dac9fd7674b", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z017_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z037_t001_NucleiLabels.tiff": "927d52441c57cb3a4014effaca3e3c23c76275fb264c26e1942a9c58b85ee6d2", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z044_t001_NucleiLabels.tiff": "a78264f2f5e245a3913a69f89105e94df30048b1aaef4eb80fc5c3235e78b196", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z052_t001_NucleiLabels.tiff": "0daf51526658e23b7c9ab8872e992ebe9322399286f95741d0ccdbd357e5d631", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z007_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z047_t001_NucleiLabels.tiff": "995d5ce77cbf61a9be8590f34987ef3f1dd698ae6ed393cac4d0960bc9e7a66a", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z019_t001_CellsLabels.tiff": "ec6ef1d319f2732c47b06f5cf02775c8cd94540f2f30a6c002f0aace1d317955", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z032_t001_CellsLabels.tiff": "8a2c5774044326ae722e41aae517266197fbebb0e4dd5eab4b22414fbfea309f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z045_t001_CellsLabels.tiff": "c678f2100c7431e5a43c391af86a79e3436d4cf13f050f98c25f62682e4632fe", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z028_t001_NucleiLabels.tiff": "1676f21bd3b7e105601c83f206890507c32ba2447988be2a75d0e8153d069b65", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z039_t001_NucleiLabels.tiff": "f93e8293a37886a36844b8748083a1f8e717efab092652755263e797f12f0364", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z055_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z047_t001_CellsLabels.tiff": "b926aa64e1fa8aa52279a69d91dc23cf14bf0ae76107f9b360c7ae77bdf53719", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z054_t001_NucleiLabels.tiff": "b841c5d901c65a6138d9ff2b0ec4aa04f00765b1dd21bcd6fc9f8dc974c6035d", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z054_t001_CellsLabels.tiff": "25ff2ec586a568e42286f73713d64aab1208c38c016099299211f04368ac49c8", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z048_t001_CellsLabels.tiff": "133a58f6fac8b07f79bfed9634867ccb5428b83e63682031a1def16c6a694568", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z019_t001_NucleiLabels.tiff": "250cb56a8054c28cea894bc3d9edaddcdce01f5151a05da78da20157c3c3be9f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z005_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z023_t001_NucleiLabels.tiff": "ecb7f78c8ca0bad2b9d0495659609b9023781b6a936d6afb0a04653eac176555", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z040_t001_CellsLabels.tiff": "1635ea20dd80ce99f0e86494666825a52a66645837d598fd3a3fa91f0bb77d53", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z046_t001_NucleiLabels.tiff": "c1250e060d32f2cfc07fc7e1594fdb1d6cbb4d0483fa94a8113efa695397963c", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z003_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z010_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z022_t001_NucleiLabels.tiff": "50aef20e28a2f9e18ca2e28eabf6d87ec2ad20c79898e56f8d63a959ba5bb507", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z010_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z026_t001_NucleiLabels.tiff": "ad22809ff3f43d15c838f697061c263070dbf1da1031da39900681cdfbf9d54c", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z041_t001_CellsLabels.tiff": "be7762756eb65f08cb337904165c6f43b5351f39405461f65ad28669abfe3899", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z027_t001_NucleiLabels.tiff": "8c8f402d3a7c65c04e7f1575dd34de0427eeeb433ff2956d20e07d06eb48fb8d", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z042_t001_NucleiLabels.tiff": "e07252ca1a55c5195c99666d8d3f0d70db636b4ef4b99e1a0049ca22b182d87a", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z029_t001_NucleiLabels.tiff": "34bce0f06f674e20667554eed0075fde8d9d33c9c0eaeffd88a1c558499cc432", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z001_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z051_t001_NucleiLabels.tiff": "f0f36ccaf744d42da036948682cfd226e6dd4a3cfb94aed38729b2d25ede5dff", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z024_t001_CellsLabels.tiff": "39899adabca74b10b9950d1f97e8b0b3bbaf136d75e7a46ef4a6e86896e3119f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z003_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z035_t001_CellsLabels.tiff": "eedeb489b46abf1eafbd9c81491cb3f85ce1cb3ce877844ad22e72547fc3c438", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z038_t001_NucleiLabels.tiff": "e2852ea83c62ab30d77681b4e39f88d3cee74ae052f1c948675ae3581c9fc28a", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z009_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z056_t001_NucleiLabels.tiff": "ca0723c8b9764d5b77034719bb75a2940be35da2e04119af4c0e6d3552c08718", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z020_t001_NucleiLabels.tiff": "b0cd031b448d8bd2075e65710bd76c064161b25242f85ee150da7cd139fcc1a8", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z039_t001_CellsLabels.tiff": "22fa79a76e64013f10373be2ca2af98a2173275c5d43c9cad33135acdc376d14", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z007_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z021_t001_NucleiLabels.tiff": "71a10b0539f3fc4cba600b275b7e948258c6a435ba33ef522faa0869ac085518", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z026_t001_CellsLabels.tiff": "5b433d931fa6637fc793b23880199c01000ef6d9e610903bb38bb8cea5574563", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z037_t001_CellsLabels.tiff": "aa1f449f1769b27cd9f1076e70f49f0242e2549f288a77984ca159cb07cf6a40", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z050_t001_NucleiLabels.tiff": "565b4f08f7503086c1f2f8e631d19063129e02a5767d2f979c0cec8fdec23601", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z032_t001_NucleiLabels.tiff": "97b09fe5444ad439c3c2007d75971dce2766d94c93268eccfee9ae49b8a04aa1", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z001_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z046_t001_CellsLabels.tiff": "dc081df050be6cd19b5d5bbfe21c96c350eecf9bc6f10f608dc361a36056632a", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z020_t001_CellsLabels.tiff": "e8105a4f04198ac75de9831247030084d6f65bf98691d7444ead7e178072fa22", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z033_t001_NucleiLabels.tiff": "512a3a0ed8025d14b0556a72ebfc13b173d14f7046817ca09876242ab63b9d6b", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z025_t001_NucleiLabels.tiff": "9cc33676a0177130609ab1331feab1722bbde8d55b2f49031730fd5a2a40029c", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z015_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z018_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z036_t001_CellsLabels.tiff": "28b68d1300cf7b08e21dbcd4858447862520dded5c27f2d84cf223513a119eed", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z008_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z030_t001_CellsLabels.tiff": "b71a2e05d270ae0cd237d6c0d97ea82a63e5ad3633723e7255c35d34e585ec80", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z031_t001_CellsLabels.tiff": "1b14aab71bf3623458ea9373852b0baf28be9727877b32f894407927ecfb6d65", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z016_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z015_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z055_t001_NucleiLabels.tiff": "44e02416cc94a70528165a4b6c42b9e19b205f9c91528076796272cb1a8504ea", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z056_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z021_t001_CellsLabels.tiff": "daa31cb1e537e5c32b1936ab7647c5690741d2bc1d0e15c60b59ba1310a8c0ce", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z022_t001_CellsLabels.tiff": "7d7ec170ed3652efa99e43d8db546c51b696821dca7727d0ff4d2f2ead7fdbaa", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z027_t001_CellsLabels.tiff": "ee9056587a19e581f5feb6078b41fa1004d923a5ddf1725aefc4b8b8c5201ad6", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z057_t001_NucleiLabels.tiff": "695517641e9fe4b8421d4a7db56b24c755b6957c98ce32bb24ad5b25f52661eb", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z057_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z041_t001_NucleiLabels.tiff": "744eab7cd170d5af8d2f72ced3893dd939c4e1b0f415afab799a37ded5d046c7", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z042_t001_CellsLabels.tiff": "88d2e9964455459499656c4f0a762cd86376c678756635aaa6b6c8d98be01852", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z013_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z008_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/openhcs_metadata.json": "b683f94e72c5c8a1f41b7680379e158dfc1caaea6659391cf24e0ee8e470e008", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z049_t001_NucleiLabels.tiff": "e92e493078672a0e0d90e31409612e215bf8486300d5c765d0e0504ff8888e7a", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z043_t001_NucleiLabels.tiff": "81a705d05b0a5bfa8783df28990c1d70634c1f4aa2bca23e02cfa8a4bc861b86", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z052_t001_CellsLabels.tiff": "7bb98f0587062e01b965e486fc687872651d7d90d271a2fdf0d35d67b464b233", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z031_t001_NucleiLabels.tiff": "247490c261fecc26c7379ab2eebaa01e4bea523218b3cc5491d2fe2b9aadfe11", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z011_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z014_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z016_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z058_t001_NucleiLabels.tiff": "a37c63c6052e40d73db918a014e6f2a18be4d0cbfbeeef65a9c26096a38a4c09", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/results/3d_monolayer_Image.csv": "75ac32ff5ef57bc285ec4eae1c9b501c27a35b486bf35435af5d499d856d34a4", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z036_t001_NucleiLabels.tiff": "4fa967c78709aa400246a50528a36b24ca366e825dd0e64561643369e814906b", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z060_t001_NucleiLabels.tiff": "7cc3c6c6a22f558e62194277090bdea2deb79475dd91fe7d0e49eac3c0187388", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z006_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z029_t001_CellsLabels.tiff": "b3bdde5f751b8f5d41ca8b5219a3427e450cb1b8795401d0ec638940d1ad7bd9", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z025_t001_CellsLabels.tiff": "03aabe5528198cfd6ec23a058dab540fb8be0870207c6dc94a62d9b621d1f2f9", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z004_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z060_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z013_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z014_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z024_t001_NucleiLabels.tiff": "9e96a05ed9860cac9c57c618db2f4fe5e4b769a9d235aac6fd1d628486317df0", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/openhcs_metadata.json.lock": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z005_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z044_t001_CellsLabels.tiff": "e03946d94c789ee787cc29a3c8f5e5d9c56b37a0044b297ba8f403abc98eb55e", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z002_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z034_t001_CellsLabels.tiff": "3f6c1d8cdbce20aac8f70e7315bea70b147b7b6a034432845b27eeb6cfba083c", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z038_t001_CellsLabels.tiff": "6ac8fd9c95acc1f261e96a8fb9332e5d6a403548842f9b85ecb977e6213b4c9b", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z033_t001_CellsLabels.tiff": "a320b99ee129d97b99f9fac66aabb89fc1652930b3bb8b2b3fbba7b57e994f85", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z049_t001_CellsLabels.tiff": "28d83dfbf5bbf7e4da9c3e4806353e9fd0a89680dcdab4b43ca2fd19b80f669c", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z053_t001_CellsLabels.tiff": "ff17f538baaf179752412026a250bdbee016e3101037bf4e0dbb81199fc4c8ed", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z009_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z043_t001_CellsLabels.tiff": "bd0df007524ea4e555e4d2fdbebe6a274caa03bc360a1cf90d601659155984b2", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z030_t001_NucleiLabels.tiff": "c54c8b98a5c38a47e0cf9391a1afab09b4c8c58e06294cdb650a15add4a32b58", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z002_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z023_t001_CellsLabels.tiff": "2f06989618050934c73473f9342c2fe3410fd834a0ddb976cf602fe6198db7a6", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z006_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/results/3d_monolayer_Nuclei.csv": "17500f5d4321bbf255df31f7a3503339029c2b077045a6c10e4d4f6f0db9ad1e", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z040_t001_NucleiLabels.tiff": "e0bd66b166e9f92120dbee183973849eda0afbbe6fed9d03fc4cfd2c56a96280", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z017_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z012_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z058_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/results/3d_monolayer_Cells.csv": "6f6e7431171ed5ea73a01784105147eca0e43a6e3e41f8720df93106353c9c79", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z059_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z035_t001_NucleiLabels.tiff": "13e69afc324152bb91329fa758d131d849127e8fd346078d94c6adc25582b3a6", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z045_t001_NucleiLabels.tiff": "94bd6a65795ad6395cc18a4fd63dc591354bef612ee49fffd2d9f63e4ed9db84", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z050_t001_CellsLabels.tiff": "ea7654a6fe1f92ad274a54935420923eec4bec5ad030187afc0ac7af02690af5", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z051_t001_CellsLabels.tiff": "73483bd10a0f37990084013ad054768086d6d3c929da6bc7e74f4aee37e9dbf2", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/results/3d_monolayer_erodedDownsizedNuclei.csv": "ee507fb9c2387f86fc768184baf2596ebe1f8e40f7fc5eb24f252345fee63ae6", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z012_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z011_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/results/3d_monolayer_erodedResizedNuclei.csv": "cca23f86a85bb3ee7a5c3a1d174c34b5f026ca7f399be98458e1a8c6e12d5c77", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z059_t001_NucleiLabels.tiff": "76c785cf0f481c73ad3cf34ccb576eaa19dd1bdd9c74f9eaf92adfbde5d44b97", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z028_t001_CellsLabels.tiff": "fef31040e0c54501c3bf965eb98f055cdb1d42c96f91cf1c239033d0a9a06534", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z034_t001_NucleiLabels.tiff": "08af61857cfb97fd95fcb08d1ce18139ce7087b192044c63452bee533c5b1aa4", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z053_t001_NucleiLabels.tiff": "b8613192175a4615b58aed607474657668429cb6ac635cd012569b19667f2d3d", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/results/3d_monolayer_downsizedNuclei.csv": "a7b998c5a524e11747fc5452fd763fc3d9abe16f46e961f62e09e9393b6a8adf", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z004_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z018_t001_NucleiLabels.tiff": "03ba7a4d6ae53e6c84aab5926ae1e2592b5f8ca24a839a256c82f08544df4270", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z048_t001_NucleiLabels.tiff": "325478230529e94ba372f38f0bf512292f131d337b6ac09ce5a91b0266724e02" + }, + "cohort": "plane-facts-whole-driver-baseline-v1" + }, + { + "case": "cp_tutorial_3d_monolayer", + "ordinary_repeat": 1, + "native_repeat": 0, + "measurement_differences": 0, + "image_differences": 0, + "tables": [ + 7, + 6 + ], + "physical_images": [ + 2, + 120 + ], + "logical_images": [ + 2, + 2 + ], + "known_relationship_keys": [ + 3, + 3 + ], + "ordinary_receipt_sha256": "49db7f2e2cfda0c0fd7dc3a4fa6a7542e70038fde080dbf73f5498f1a506ae34", + "output_hashes": { + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/native/cp_tutorial_3d_monolayer/outputs/0/3d_monolayer_downsizedNuclei.csv": "2c66bc7b17de52147d5a875403f9a9746019ac61371c08157979044c6ed818dd", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/native/cp_tutorial_3d_monolayer/outputs/0/3d_monolayer_Cells.csv": "cc34681db8a66c38ca77bc47db496b26703f21e4d7c7628dd74e30c33250859f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/native/cp_tutorial_3d_monolayer/outputs/0/3d_monolayer_xy1_ch2_NucleiLabels.tiff": "340bbd795541e4031749d1fff767fa4fcdcac10f5b97879056b25dac9fd7674b", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/native/cp_tutorial_3d_monolayer/outputs/0/3d_monolayer_xy1_ch0_CellsLabels.tiff": "aaed9ed23179a162ee7f5a7e8d1d88f1fa342ca55172b7fccd4cbf67f7841d81", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/native/cp_tutorial_3d_monolayer/outputs/0/3d_monolayer_erodedDownsizedNuclei.csv": "527a0cce497d2a618478be84d1a0bf174049f58aa2a666e37626a990fdca0116", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/native/cp_tutorial_3d_monolayer/outputs/0/3d_monolayer_erodedResizedNuclei.csv": "66a58f78cab0cfdbe907468e8ba383fc59fab49025b84b589855bdfa04854609", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/native/cp_tutorial_3d_monolayer/outputs/0/3d_monolayer_Nuclei.csv": "440c33edc7e8cb5611910a835454db62390301a7af617a542349f60aece57561", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/native/cp_tutorial_3d_monolayer/outputs/0/3d_monolayer_Image.csv": "1f3dec653b6909c8a81ac109ce1faf91380886ac9a18e56fafc91102d419904e", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/native/cp_tutorial_3d_monolayer/outputs/0/3d_monolayer_Experiment.csv": "c05f0a11f43a5bda943e9f739ff257216f8ab3f65d8988a0d3d0c612c1db6997", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z025_t001_CellsLabels.tiff": "03aabe5528198cfd6ec23a058dab540fb8be0870207c6dc94a62d9b621d1f2f9", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z039_t001_NucleiLabels.tiff": "f93e8293a37886a36844b8748083a1f8e717efab092652755263e797f12f0364", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z010_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z051_t001_NucleiLabels.tiff": "f0f36ccaf744d42da036948682cfd226e6dd4a3cfb94aed38729b2d25ede5dff", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z014_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z013_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z016_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z060_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z004_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z056_t001_NucleiLabels.tiff": "ca0723c8b9764d5b77034719bb75a2940be35da2e04119af4c0e6d3552c08718", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z045_t001_NucleiLabels.tiff": "94bd6a65795ad6395cc18a4fd63dc591354bef612ee49fffd2d9f63e4ed9db84", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z017_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z046_t001_NucleiLabels.tiff": "c1250e060d32f2cfc07fc7e1594fdb1d6cbb4d0483fa94a8113efa695397963c", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z058_t001_NucleiLabels.tiff": "a37c63c6052e40d73db918a014e6f2a18be4d0cbfbeeef65a9c26096a38a4c09", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z047_t001_NucleiLabels.tiff": "995d5ce77cbf61a9be8590f34987ef3f1dd698ae6ed393cac4d0960bc9e7a66a", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z024_t001_CellsLabels.tiff": "39899adabca74b10b9950d1f97e8b0b3bbaf136d75e7a46ef4a6e86896e3119f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/results/3d_monolayer_Nuclei.csv": "17500f5d4321bbf255df31f7a3503339029c2b077045a6c10e4d4f6f0db9ad1e", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z054_t001_CellsLabels.tiff": "25ff2ec586a568e42286f73713d64aab1208c38c016099299211f04368ac49c8", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z055_t001_NucleiLabels.tiff": "44e02416cc94a70528165a4b6c42b9e19b205f9c91528076796272cb1a8504ea", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z007_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z031_t001_NucleiLabels.tiff": "247490c261fecc26c7379ab2eebaa01e4bea523218b3cc5491d2fe2b9aadfe11", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z051_t001_CellsLabels.tiff": "73483bd10a0f37990084013ad054768086d6d3c929da6bc7e74f4aee37e9dbf2", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z049_t001_CellsLabels.tiff": "28d83dfbf5bbf7e4da9c3e4806353e9fd0a89680dcdab4b43ca2fd19b80f669c", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z028_t001_NucleiLabels.tiff": "1676f21bd3b7e105601c83f206890507c32ba2447988be2a75d0e8153d069b65", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z016_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z005_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z053_t001_CellsLabels.tiff": "ff17f538baaf179752412026a250bdbee016e3101037bf4e0dbb81199fc4c8ed", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z044_t001_NucleiLabels.tiff": "a78264f2f5e245a3913a69f89105e94df30048b1aaef4eb80fc5c3235e78b196", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z055_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z045_t001_CellsLabels.tiff": "c678f2100c7431e5a43c391af86a79e3436d4cf13f050f98c25f62682e4632fe", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/results/3d_monolayer_downsizedNuclei.csv": "a7b998c5a524e11747fc5452fd763fc3d9abe16f46e961f62e09e9393b6a8adf", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z027_t001_CellsLabels.tiff": "ee9056587a19e581f5feb6078b41fa1004d923a5ddf1725aefc4b8b8c5201ad6", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z049_t001_NucleiLabels.tiff": "e92e493078672a0e0d90e31409612e215bf8486300d5c765d0e0504ff8888e7a", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z032_t001_CellsLabels.tiff": "8a2c5774044326ae722e41aae517266197fbebb0e4dd5eab4b22414fbfea309f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z010_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z031_t001_CellsLabels.tiff": "1b14aab71bf3623458ea9373852b0baf28be9727877b32f894407927ecfb6d65", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z056_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z047_t001_CellsLabels.tiff": "b926aa64e1fa8aa52279a69d91dc23cf14bf0ae76107f9b360c7ae77bdf53719", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z041_t001_NucleiLabels.tiff": "744eab7cd170d5af8d2f72ced3893dd939c4e1b0f415afab799a37ded5d046c7", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z006_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z033_t001_CellsLabels.tiff": "a320b99ee129d97b99f9fac66aabb89fc1652930b3bb8b2b3fbba7b57e994f85", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z023_t001_NucleiLabels.tiff": "ecb7f78c8ca0bad2b9d0495659609b9023781b6a936d6afb0a04653eac176555", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z060_t001_NucleiLabels.tiff": "7cc3c6c6a22f558e62194277090bdea2deb79475dd91fe7d0e49eac3c0187388", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z003_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z038_t001_CellsLabels.tiff": "6ac8fd9c95acc1f261e96a8fb9332e5d6a403548842f9b85ecb977e6213b4c9b", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z009_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z002_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z042_t001_CellsLabels.tiff": "88d2e9964455459499656c4f0a762cd86376c678756635aaa6b6c8d98be01852", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z054_t001_NucleiLabels.tiff": "b841c5d901c65a6138d9ff2b0ec4aa04f00765b1dd21bcd6fc9f8dc974c6035d", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z018_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z024_t001_NucleiLabels.tiff": "9e96a05ed9860cac9c57c618db2f4fe5e4b769a9d235aac6fd1d628486317df0", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z052_t001_CellsLabels.tiff": "7bb98f0587062e01b965e486fc687872651d7d90d271a2fdf0d35d67b464b233", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z041_t001_CellsLabels.tiff": "be7762756eb65f08cb337904165c6f43b5351f39405461f65ad28669abfe3899", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z048_t001_CellsLabels.tiff": "133a58f6fac8b07f79bfed9634867ccb5428b83e63682031a1def16c6a694568", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z043_t001_CellsLabels.tiff": "bd0df007524ea4e555e4d2fdbebe6a274caa03bc360a1cf90d601659155984b2", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z012_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z004_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z038_t001_NucleiLabels.tiff": "e2852ea83c62ab30d77681b4e39f88d3cee74ae052f1c948675ae3581c9fc28a", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z021_t001_CellsLabels.tiff": "daa31cb1e537e5c32b1936ab7647c5690741d2bc1d0e15c60b59ba1310a8c0ce", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z019_t001_NucleiLabels.tiff": "250cb56a8054c28cea894bc3d9edaddcdce01f5151a05da78da20157c3c3be9f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z026_t001_CellsLabels.tiff": "5b433d931fa6637fc793b23880199c01000ef6d9e610903bb38bb8cea5574563", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z029_t001_CellsLabels.tiff": "b3bdde5f751b8f5d41ca8b5219a3427e450cb1b8795401d0ec638940d1ad7bd9", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z001_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z030_t001_CellsLabels.tiff": "b71a2e05d270ae0cd237d6c0d97ea82a63e5ad3633723e7255c35d34e585ec80", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/openhcs_metadata.json.lock": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z034_t001_NucleiLabels.tiff": "08af61857cfb97fd95fcb08d1ce18139ce7087b192044c63452bee533c5b1aa4", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z012_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z005_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z022_t001_NucleiLabels.tiff": "50aef20e28a2f9e18ca2e28eabf6d87ec2ad20c79898e56f8d63a959ba5bb507", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z035_t001_CellsLabels.tiff": "eedeb489b46abf1eafbd9c81491cb3f85ce1cb3ce877844ad22e72547fc3c438", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z032_t001_NucleiLabels.tiff": "97b09fe5444ad439c3c2007d75971dce2766d94c93268eccfee9ae49b8a04aa1", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z011_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z002_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z003_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z035_t001_NucleiLabels.tiff": "13e69afc324152bb91329fa758d131d849127e8fd346078d94c6adc25582b3a6", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z028_t001_CellsLabels.tiff": "fef31040e0c54501c3bf965eb98f055cdb1d42c96f91cf1c239033d0a9a06534", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z020_t001_NucleiLabels.tiff": "b0cd031b448d8bd2075e65710bd76c064161b25242f85ee150da7cd139fcc1a8", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z014_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z025_t001_NucleiLabels.tiff": "9cc33676a0177130609ab1331feab1722bbde8d55b2f49031730fd5a2a40029c", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z037_t001_CellsLabels.tiff": "aa1f449f1769b27cd9f1076e70f49f0242e2549f288a77984ca159cb07cf6a40", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z008_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z036_t001_NucleiLabels.tiff": "4fa967c78709aa400246a50528a36b24ca366e825dd0e64561643369e814906b", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z039_t001_CellsLabels.tiff": "22fa79a76e64013f10373be2ca2af98a2173275c5d43c9cad33135acdc376d14", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z020_t001_CellsLabels.tiff": "e8105a4f04198ac75de9831247030084d6f65bf98691d7444ead7e178072fa22", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z015_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z046_t001_CellsLabels.tiff": "dc081df050be6cd19b5d5bbfe21c96c350eecf9bc6f10f608dc361a36056632a", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z022_t001_CellsLabels.tiff": "7d7ec170ed3652efa99e43d8db546c51b696821dca7727d0ff4d2f2ead7fdbaa", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z026_t001_NucleiLabels.tiff": "ad22809ff3f43d15c838f697061c263070dbf1da1031da39900681cdfbf9d54c", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z001_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z036_t001_CellsLabels.tiff": "28b68d1300cf7b08e21dbcd4858447862520dded5c27f2d84cf223513a119eed", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z050_t001_NucleiLabels.tiff": "565b4f08f7503086c1f2f8e631d19063129e02a5767d2f979c0cec8fdec23601", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z034_t001_CellsLabels.tiff": "3f6c1d8cdbce20aac8f70e7315bea70b147b7b6a034432845b27eeb6cfba083c", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z037_t001_NucleiLabels.tiff": "927d52441c57cb3a4014effaca3e3c23c76275fb264c26e1942a9c58b85ee6d2", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z040_t001_NucleiLabels.tiff": "e0bd66b166e9f92120dbee183973849eda0afbbe6fed9d03fc4cfd2c56a96280", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z050_t001_CellsLabels.tiff": "ea7654a6fe1f92ad274a54935420923eec4bec5ad030187afc0ac7af02690af5", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z053_t001_NucleiLabels.tiff": "b8613192175a4615b58aed607474657668429cb6ac635cd012569b19667f2d3d", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z015_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z058_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z044_t001_CellsLabels.tiff": "e03946d94c789ee787cc29a3c8f5e5d9c56b37a0044b297ba8f403abc98eb55e", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z042_t001_NucleiLabels.tiff": "e07252ca1a55c5195c99666d8d3f0d70db636b4ef4b99e1a0049ca22b182d87a", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z030_t001_NucleiLabels.tiff": "c54c8b98a5c38a47e0cf9391a1afab09b4c8c58e06294cdb650a15add4a32b58", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z011_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z059_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/results/3d_monolayer_erodedResizedNuclei.csv": "cca23f86a85bb3ee7a5c3a1d174c34b5f026ca7f399be98458e1a8c6e12d5c77", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z017_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z023_t001_CellsLabels.tiff": "2f06989618050934c73473f9342c2fe3410fd834a0ddb976cf602fe6198db7a6", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z040_t001_CellsLabels.tiff": "1635ea20dd80ce99f0e86494666825a52a66645837d598fd3a3fa91f0bb77d53", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z027_t001_NucleiLabels.tiff": "8c8f402d3a7c65c04e7f1575dd34de0427eeeb433ff2956d20e07d06eb48fb8d", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z021_t001_NucleiLabels.tiff": "71a10b0539f3fc4cba600b275b7e948258c6a435ba33ef522faa0869ac085518", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z048_t001_NucleiLabels.tiff": "325478230529e94ba372f38f0bf512292f131d337b6ac09ce5a91b0266724e02", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z057_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z013_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z059_t001_NucleiLabels.tiff": "76c785cf0f481c73ad3cf34ccb576eaa19dd1bdd9c74f9eaf92adfbde5d44b97", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z018_t001_NucleiLabels.tiff": "03ba7a4d6ae53e6c84aab5926ae1e2592b5f8ca24a839a256c82f08544df4270", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z057_t001_NucleiLabels.tiff": "695517641e9fe4b8421d4a7db56b24c755b6957c98ce32bb24ad5b25f52661eb", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/openhcs_metadata.json": "9ff815827f4a4a5cec301260e570ffc7f1b56a9f6422e08309c08e3ed34e01ac", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z019_t001_CellsLabels.tiff": "ec6ef1d319f2732c47b06f5cf02775c8cd94540f2f30a6c002f0aace1d317955", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/results/3d_monolayer_erodedDownsizedNuclei.csv": "ee507fb9c2387f86fc768184baf2596ebe1f8e40f7fc5eb24f252345fee63ae6", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z043_t001_NucleiLabels.tiff": "81a705d05b0a5bfa8783df28990c1d70634c1f4aa2bca23e02cfa8a4bc861b86", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/results/3d_monolayer_Image.csv": "75ac32ff5ef57bc285ec4eae1c9b501c27a35b486bf35435af5d499d856d34a4", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z052_t001_NucleiLabels.tiff": "0daf51526658e23b7c9ab8872e992ebe9322399286f95741d0ccdbd357e5d631", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z033_t001_NucleiLabels.tiff": "512a3a0ed8025d14b0556a72ebfc13b173d14f7046817ca09876242ab63b9d6b", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z029_t001_NucleiLabels.tiff": "34bce0f06f674e20667554eed0075fde8d9d33c9c0eaeffd88a1c558499cc432", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/results/3d_monolayer_Cells.csv": "6f6e7431171ed5ea73a01784105147eca0e43a6e3e41f8720df93106353c9c79", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z008_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z007_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z009_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z006_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f" + }, + "cohort": "plane-facts-whole-driver-candidate-v1" + }, + { + "case": "cp_tutorial_3d_monolayer", + "ordinary_repeat": 1, + "native_repeat": 1, + "measurement_differences": 0, + "image_differences": 0, + "tables": [ + 7, + 6 + ], + "physical_images": [ + 2, + 120 + ], + "logical_images": [ + 2, + 2 + ], + "known_relationship_keys": [ + 3, + 3 + ], + "ordinary_receipt_sha256": "49db7f2e2cfda0c0fd7dc3a4fa6a7542e70038fde080dbf73f5498f1a506ae34", + "output_hashes": { + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/native/cp_tutorial_3d_monolayer/outputs/1/3d_monolayer_downsizedNuclei.csv": "2c66bc7b17de52147d5a875403f9a9746019ac61371c08157979044c6ed818dd", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/native/cp_tutorial_3d_monolayer/outputs/1/3d_monolayer_xy1_ch0_CellsLabels.tiff": "aaed9ed23179a162ee7f5a7e8d1d88f1fa342ca55172b7fccd4cbf67f7841d81", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/native/cp_tutorial_3d_monolayer/outputs/1/3d_monolayer_Image.csv": "4cde74a38ef73b892dd9012708a3ac7d71fab206a7903f525b39e84493dcfe17", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/native/cp_tutorial_3d_monolayer/outputs/1/3d_monolayer_Cells.csv": "cc34681db8a66c38ca77bc47db496b26703f21e4d7c7628dd74e30c33250859f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/native/cp_tutorial_3d_monolayer/outputs/1/3d_monolayer_erodedResizedNuclei.csv": "66a58f78cab0cfdbe907468e8ba383fc59fab49025b84b589855bdfa04854609", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/native/cp_tutorial_3d_monolayer/outputs/1/3d_monolayer_Experiment.csv": "65f1f124e99f13ddc73b71d01732262cd353f24f0bd4697a776b274a39eaecc5", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/native/cp_tutorial_3d_monolayer/outputs/1/3d_monolayer_Nuclei.csv": "440c33edc7e8cb5611910a835454db62390301a7af617a542349f60aece57561", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/native/cp_tutorial_3d_monolayer/outputs/1/3d_monolayer_erodedDownsizedNuclei.csv": "527a0cce497d2a618478be84d1a0bf174049f58aa2a666e37626a990fdca0116", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/native/cp_tutorial_3d_monolayer/outputs/1/3d_monolayer_xy1_ch2_NucleiLabels.tiff": "340bbd795541e4031749d1fff767fa4fcdcac10f5b97879056b25dac9fd7674b", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z025_t001_CellsLabels.tiff": "03aabe5528198cfd6ec23a058dab540fb8be0870207c6dc94a62d9b621d1f2f9", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z039_t001_NucleiLabels.tiff": "f93e8293a37886a36844b8748083a1f8e717efab092652755263e797f12f0364", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z010_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z051_t001_NucleiLabels.tiff": "f0f36ccaf744d42da036948682cfd226e6dd4a3cfb94aed38729b2d25ede5dff", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z014_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z013_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z016_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z060_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z004_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z056_t001_NucleiLabels.tiff": "ca0723c8b9764d5b77034719bb75a2940be35da2e04119af4c0e6d3552c08718", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z045_t001_NucleiLabels.tiff": "94bd6a65795ad6395cc18a4fd63dc591354bef612ee49fffd2d9f63e4ed9db84", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z017_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z046_t001_NucleiLabels.tiff": "c1250e060d32f2cfc07fc7e1594fdb1d6cbb4d0483fa94a8113efa695397963c", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z058_t001_NucleiLabels.tiff": "a37c63c6052e40d73db918a014e6f2a18be4d0cbfbeeef65a9c26096a38a4c09", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z047_t001_NucleiLabels.tiff": "995d5ce77cbf61a9be8590f34987ef3f1dd698ae6ed393cac4d0960bc9e7a66a", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z024_t001_CellsLabels.tiff": "39899adabca74b10b9950d1f97e8b0b3bbaf136d75e7a46ef4a6e86896e3119f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/results/3d_monolayer_Nuclei.csv": "17500f5d4321bbf255df31f7a3503339029c2b077045a6c10e4d4f6f0db9ad1e", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z054_t001_CellsLabels.tiff": "25ff2ec586a568e42286f73713d64aab1208c38c016099299211f04368ac49c8", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z055_t001_NucleiLabels.tiff": "44e02416cc94a70528165a4b6c42b9e19b205f9c91528076796272cb1a8504ea", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z007_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z031_t001_NucleiLabels.tiff": "247490c261fecc26c7379ab2eebaa01e4bea523218b3cc5491d2fe2b9aadfe11", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z051_t001_CellsLabels.tiff": "73483bd10a0f37990084013ad054768086d6d3c929da6bc7e74f4aee37e9dbf2", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z049_t001_CellsLabels.tiff": "28d83dfbf5bbf7e4da9c3e4806353e9fd0a89680dcdab4b43ca2fd19b80f669c", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z028_t001_NucleiLabels.tiff": "1676f21bd3b7e105601c83f206890507c32ba2447988be2a75d0e8153d069b65", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z016_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z005_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z053_t001_CellsLabels.tiff": "ff17f538baaf179752412026a250bdbee016e3101037bf4e0dbb81199fc4c8ed", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z044_t001_NucleiLabels.tiff": "a78264f2f5e245a3913a69f89105e94df30048b1aaef4eb80fc5c3235e78b196", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z055_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z045_t001_CellsLabels.tiff": "c678f2100c7431e5a43c391af86a79e3436d4cf13f050f98c25f62682e4632fe", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/results/3d_monolayer_downsizedNuclei.csv": "a7b998c5a524e11747fc5452fd763fc3d9abe16f46e961f62e09e9393b6a8adf", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z027_t001_CellsLabels.tiff": "ee9056587a19e581f5feb6078b41fa1004d923a5ddf1725aefc4b8b8c5201ad6", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z049_t001_NucleiLabels.tiff": "e92e493078672a0e0d90e31409612e215bf8486300d5c765d0e0504ff8888e7a", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z032_t001_CellsLabels.tiff": "8a2c5774044326ae722e41aae517266197fbebb0e4dd5eab4b22414fbfea309f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z010_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z031_t001_CellsLabels.tiff": "1b14aab71bf3623458ea9373852b0baf28be9727877b32f894407927ecfb6d65", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z056_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z047_t001_CellsLabels.tiff": "b926aa64e1fa8aa52279a69d91dc23cf14bf0ae76107f9b360c7ae77bdf53719", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z041_t001_NucleiLabels.tiff": "744eab7cd170d5af8d2f72ced3893dd939c4e1b0f415afab799a37ded5d046c7", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z006_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z033_t001_CellsLabels.tiff": "a320b99ee129d97b99f9fac66aabb89fc1652930b3bb8b2b3fbba7b57e994f85", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z023_t001_NucleiLabels.tiff": "ecb7f78c8ca0bad2b9d0495659609b9023781b6a936d6afb0a04653eac176555", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z060_t001_NucleiLabels.tiff": "7cc3c6c6a22f558e62194277090bdea2deb79475dd91fe7d0e49eac3c0187388", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z003_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z038_t001_CellsLabels.tiff": "6ac8fd9c95acc1f261e96a8fb9332e5d6a403548842f9b85ecb977e6213b4c9b", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z009_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z002_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z042_t001_CellsLabels.tiff": "88d2e9964455459499656c4f0a762cd86376c678756635aaa6b6c8d98be01852", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z054_t001_NucleiLabels.tiff": "b841c5d901c65a6138d9ff2b0ec4aa04f00765b1dd21bcd6fc9f8dc974c6035d", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z018_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z024_t001_NucleiLabels.tiff": "9e96a05ed9860cac9c57c618db2f4fe5e4b769a9d235aac6fd1d628486317df0", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z052_t001_CellsLabels.tiff": "7bb98f0587062e01b965e486fc687872651d7d90d271a2fdf0d35d67b464b233", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z041_t001_CellsLabels.tiff": "be7762756eb65f08cb337904165c6f43b5351f39405461f65ad28669abfe3899", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z048_t001_CellsLabels.tiff": "133a58f6fac8b07f79bfed9634867ccb5428b83e63682031a1def16c6a694568", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z043_t001_CellsLabels.tiff": "bd0df007524ea4e555e4d2fdbebe6a274caa03bc360a1cf90d601659155984b2", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z012_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z004_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z038_t001_NucleiLabels.tiff": "e2852ea83c62ab30d77681b4e39f88d3cee74ae052f1c948675ae3581c9fc28a", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z021_t001_CellsLabels.tiff": "daa31cb1e537e5c32b1936ab7647c5690741d2bc1d0e15c60b59ba1310a8c0ce", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z019_t001_NucleiLabels.tiff": "250cb56a8054c28cea894bc3d9edaddcdce01f5151a05da78da20157c3c3be9f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z026_t001_CellsLabels.tiff": "5b433d931fa6637fc793b23880199c01000ef6d9e610903bb38bb8cea5574563", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z029_t001_CellsLabels.tiff": "b3bdde5f751b8f5d41ca8b5219a3427e450cb1b8795401d0ec638940d1ad7bd9", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z001_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z030_t001_CellsLabels.tiff": "b71a2e05d270ae0cd237d6c0d97ea82a63e5ad3633723e7255c35d34e585ec80", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/openhcs_metadata.json.lock": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z034_t001_NucleiLabels.tiff": "08af61857cfb97fd95fcb08d1ce18139ce7087b192044c63452bee533c5b1aa4", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z012_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z005_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z022_t001_NucleiLabels.tiff": "50aef20e28a2f9e18ca2e28eabf6d87ec2ad20c79898e56f8d63a959ba5bb507", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z035_t001_CellsLabels.tiff": "eedeb489b46abf1eafbd9c81491cb3f85ce1cb3ce877844ad22e72547fc3c438", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z032_t001_NucleiLabels.tiff": "97b09fe5444ad439c3c2007d75971dce2766d94c93268eccfee9ae49b8a04aa1", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z011_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z002_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z003_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z035_t001_NucleiLabels.tiff": "13e69afc324152bb91329fa758d131d849127e8fd346078d94c6adc25582b3a6", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z028_t001_CellsLabels.tiff": "fef31040e0c54501c3bf965eb98f055cdb1d42c96f91cf1c239033d0a9a06534", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z020_t001_NucleiLabels.tiff": "b0cd031b448d8bd2075e65710bd76c064161b25242f85ee150da7cd139fcc1a8", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z014_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z025_t001_NucleiLabels.tiff": "9cc33676a0177130609ab1331feab1722bbde8d55b2f49031730fd5a2a40029c", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z037_t001_CellsLabels.tiff": "aa1f449f1769b27cd9f1076e70f49f0242e2549f288a77984ca159cb07cf6a40", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z008_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z036_t001_NucleiLabels.tiff": "4fa967c78709aa400246a50528a36b24ca366e825dd0e64561643369e814906b", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z039_t001_CellsLabels.tiff": "22fa79a76e64013f10373be2ca2af98a2173275c5d43c9cad33135acdc376d14", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z020_t001_CellsLabels.tiff": "e8105a4f04198ac75de9831247030084d6f65bf98691d7444ead7e178072fa22", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z015_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z046_t001_CellsLabels.tiff": "dc081df050be6cd19b5d5bbfe21c96c350eecf9bc6f10f608dc361a36056632a", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z022_t001_CellsLabels.tiff": "7d7ec170ed3652efa99e43d8db546c51b696821dca7727d0ff4d2f2ead7fdbaa", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z026_t001_NucleiLabels.tiff": "ad22809ff3f43d15c838f697061c263070dbf1da1031da39900681cdfbf9d54c", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z001_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z036_t001_CellsLabels.tiff": "28b68d1300cf7b08e21dbcd4858447862520dded5c27f2d84cf223513a119eed", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z050_t001_NucleiLabels.tiff": "565b4f08f7503086c1f2f8e631d19063129e02a5767d2f979c0cec8fdec23601", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z034_t001_CellsLabels.tiff": "3f6c1d8cdbce20aac8f70e7315bea70b147b7b6a034432845b27eeb6cfba083c", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z037_t001_NucleiLabels.tiff": "927d52441c57cb3a4014effaca3e3c23c76275fb264c26e1942a9c58b85ee6d2", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z040_t001_NucleiLabels.tiff": "e0bd66b166e9f92120dbee183973849eda0afbbe6fed9d03fc4cfd2c56a96280", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z050_t001_CellsLabels.tiff": "ea7654a6fe1f92ad274a54935420923eec4bec5ad030187afc0ac7af02690af5", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z053_t001_NucleiLabels.tiff": "b8613192175a4615b58aed607474657668429cb6ac635cd012569b19667f2d3d", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z015_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z058_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z044_t001_CellsLabels.tiff": "e03946d94c789ee787cc29a3c8f5e5d9c56b37a0044b297ba8f403abc98eb55e", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z042_t001_NucleiLabels.tiff": "e07252ca1a55c5195c99666d8d3f0d70db636b4ef4b99e1a0049ca22b182d87a", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z030_t001_NucleiLabels.tiff": "c54c8b98a5c38a47e0cf9391a1afab09b4c8c58e06294cdb650a15add4a32b58", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z011_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z059_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/results/3d_monolayer_erodedResizedNuclei.csv": "cca23f86a85bb3ee7a5c3a1d174c34b5f026ca7f399be98458e1a8c6e12d5c77", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z017_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z023_t001_CellsLabels.tiff": "2f06989618050934c73473f9342c2fe3410fd834a0ddb976cf602fe6198db7a6", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z040_t001_CellsLabels.tiff": "1635ea20dd80ce99f0e86494666825a52a66645837d598fd3a3fa91f0bb77d53", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z027_t001_NucleiLabels.tiff": "8c8f402d3a7c65c04e7f1575dd34de0427eeeb433ff2956d20e07d06eb48fb8d", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z021_t001_NucleiLabels.tiff": "71a10b0539f3fc4cba600b275b7e948258c6a435ba33ef522faa0869ac085518", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z048_t001_NucleiLabels.tiff": "325478230529e94ba372f38f0bf512292f131d337b6ac09ce5a91b0266724e02", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z057_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z013_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z059_t001_NucleiLabels.tiff": "76c785cf0f481c73ad3cf34ccb576eaa19dd1bdd9c74f9eaf92adfbde5d44b97", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z018_t001_NucleiLabels.tiff": "03ba7a4d6ae53e6c84aab5926ae1e2592b5f8ca24a839a256c82f08544df4270", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z057_t001_NucleiLabels.tiff": "695517641e9fe4b8421d4a7db56b24c755b6957c98ce32bb24ad5b25f52661eb", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/openhcs_metadata.json": "9ff815827f4a4a5cec301260e570ffc7f1b56a9f6422e08309c08e3ed34e01ac", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z019_t001_CellsLabels.tiff": "ec6ef1d319f2732c47b06f5cf02775c8cd94540f2f30a6c002f0aace1d317955", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/results/3d_monolayer_erodedDownsizedNuclei.csv": "ee507fb9c2387f86fc768184baf2596ebe1f8e40f7fc5eb24f252345fee63ae6", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z043_t001_NucleiLabels.tiff": "81a705d05b0a5bfa8783df28990c1d70634c1f4aa2bca23e02cfa8a4bc861b86", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/results/3d_monolayer_Image.csv": "75ac32ff5ef57bc285ec4eae1c9b501c27a35b486bf35435af5d499d856d34a4", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z052_t001_NucleiLabels.tiff": "0daf51526658e23b7c9ab8872e992ebe9322399286f95741d0ccdbd357e5d631", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z033_t001_NucleiLabels.tiff": "512a3a0ed8025d14b0556a72ebfc13b173d14f7046817ca09876242ab63b9d6b", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z029_t001_NucleiLabels.tiff": "34bce0f06f674e20667554eed0075fde8d9d33c9c0eaeffd88a1c558499cc432", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/results/3d_monolayer_Cells.csv": "6f6e7431171ed5ea73a01784105147eca0e43a6e3e41f8720df93106353c9c79", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z008_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z007_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z009_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z006_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f" + }, + "cohort": "plane-facts-whole-driver-candidate-v1" + } + ], + "source_head": "9eee98265c939859d49f0c60bd5b3a2168cb29fe", + "scope": "Fresh whole-driver baseline and candidate versus both retained qualified native repetitions; original comparator and all strict policies; no runtime/native rerun or timing promotion.", + "source_revision": "9eee98265c939859d49f0c60bd5b3a2168cb29fe", + "source_diff_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "native_witness": { + "outputs": { + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/native/cp_tutorial_3d_monolayer/outputs/0/3d_monolayer_erodedResizedNuclei.csv": "66a58f78cab0cfdbe907468e8ba383fc59fab49025b84b589855bdfa04854609", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/native/cp_tutorial_3d_monolayer/outputs/0/3d_monolayer_xy1_ch2_NucleiLabels.tiff": "340bbd795541e4031749d1fff767fa4fcdcac10f5b97879056b25dac9fd7674b", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/native/cp_tutorial_3d_monolayer/outputs/0/3d_monolayer_Experiment.csv": "c05f0a11f43a5bda943e9f739ff257216f8ab3f65d8988a0d3d0c612c1db6997", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/native/cp_tutorial_3d_monolayer/outputs/0/3d_monolayer_Cells.csv": "cc34681db8a66c38ca77bc47db496b26703f21e4d7c7628dd74e30c33250859f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/native/cp_tutorial_3d_monolayer/outputs/0/3d_monolayer_downsizedNuclei.csv": "2c66bc7b17de52147d5a875403f9a9746019ac61371c08157979044c6ed818dd", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/native/cp_tutorial_3d_monolayer/outputs/0/3d_monolayer_Nuclei.csv": "440c33edc7e8cb5611910a835454db62390301a7af617a542349f60aece57561", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/native/cp_tutorial_3d_monolayer/outputs/0/3d_monolayer_xy1_ch0_CellsLabels.tiff": "aaed9ed23179a162ee7f5a7e8d1d88f1fa342ca55172b7fccd4cbf67f7841d81", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/native/cp_tutorial_3d_monolayer/outputs/0/3d_monolayer_Image.csv": "1f3dec653b6909c8a81ac109ce1faf91380886ac9a18e56fafc91102d419904e", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/native/cp_tutorial_3d_monolayer/outputs/0/3d_monolayer_erodedDownsizedNuclei.csv": "527a0cce497d2a618478be84d1a0bf174049f58aa2a666e37626a990fdca0116", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/native/cp_tutorial_3d_monolayer/outputs/1/3d_monolayer_erodedResizedNuclei.csv": "66a58f78cab0cfdbe907468e8ba383fc59fab49025b84b589855bdfa04854609", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/native/cp_tutorial_3d_monolayer/outputs/1/3d_monolayer_xy1_ch2_NucleiLabels.tiff": "340bbd795541e4031749d1fff767fa4fcdcac10f5b97879056b25dac9fd7674b", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/native/cp_tutorial_3d_monolayer/outputs/1/3d_monolayer_Experiment.csv": "65f1f124e99f13ddc73b71d01732262cd353f24f0bd4697a776b274a39eaecc5", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/native/cp_tutorial_3d_monolayer/outputs/1/3d_monolayer_Cells.csv": "cc34681db8a66c38ca77bc47db496b26703f21e4d7c7628dd74e30c33250859f", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/native/cp_tutorial_3d_monolayer/outputs/1/3d_monolayer_downsizedNuclei.csv": "2c66bc7b17de52147d5a875403f9a9746019ac61371c08157979044c6ed818dd", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/native/cp_tutorial_3d_monolayer/outputs/1/3d_monolayer_Nuclei.csv": "440c33edc7e8cb5611910a835454db62390301a7af617a542349f60aece57561", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/native/cp_tutorial_3d_monolayer/outputs/1/3d_monolayer_xy1_ch0_CellsLabels.tiff": "aaed9ed23179a162ee7f5a7e8d1d88f1fa342ca55172b7fccd4cbf67f7841d81", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/native/cp_tutorial_3d_monolayer/outputs/1/3d_monolayer_Image.csv": "4cde74a38ef73b892dd9012708a3ac7d71fab206a7903f525b39e84493dcfe17", + "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/native/cp_tutorial_3d_monolayer/outputs/1/3d_monolayer_erodedDownsizedNuclei.csv": "527a0cce497d2a618478be84d1a0bf174049f58aa2a666e37626a990fdca0116" + }, + "inputs": { + "/home/ts/.cache/openhcs/benchmark_datasets/CellProfiler_tutorials/data/3d_monolayer/3d_monolayer_final.cppipe": "9fcd24a1be8372b5c2e87637a055032c3362b9ad8729e361095f93d8bbe71838", + "/home/ts/.cache/openhcs/benchmark_datasets/CellProfiler_tutorials/data/3d_monolayer/images/3d_monolayer_xy1_ch0.tif": "63114f614fec95664f718a39cddac58449f0edb5cc31b57584e4ba5b1f4994c7", + "/home/ts/.cache/openhcs/benchmark_datasets/CellProfiler_tutorials/data/3d_monolayer/images/3d_monolayer_xy1_ch1.tif": "a7d9abf632850875c22613c4b740fc01153cf60e9773c16d4a670a97b46e5751", + "/home/ts/.cache/openhcs/benchmark_datasets/CellProfiler_tutorials/data/3d_monolayer/images/3d_monolayer_xy1_ch2.tif": "191754bc7f43856223180483e2737ea93bab4d0cf98b1b2a4c27425e9908147d", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleSpeckles/ExampleSpeckles.cppipe": "6f1f0a6c2a26c99ade3a258b8dfe1cbbd741757400f632960f66bded1a7fb11c", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleSpeckles/images/1-162hrh2ax2.tif": "24cc92ed76482639161711b1ae7fc57779d7cdb723be887b4d6a887b04dda680", + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleSpeckles/images/1-162hrhoe2.tif": "ea1874927a1448b6973d1689a694d29abaad62062fae83a8a58f8d790ad6d7c1" + }, + "receipts": [ + { + "path": "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/source-freeze.json", + "sha256": "72e1b4f14c8c7bf03517c8d99329a1a49182fefa4b128d87326abd5b3ed829b8", + "bytes": 1431168 + }, + { + "path": "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/strict-science.json", + "sha256": "77ab1a1e88d52502c633b646efe0d032ad87f117fc403298cb8b5742a0510190", + "bytes": 184689 + }, + { + "path": "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/paired-qualification.json", + "sha256": "3db0f60d3ef04aa0ce846eaef70e746031442422cc693ba943bf78ac8db1ab32", + "bytes": 100305 + } + ], + "native_report": { + "path": "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/native/cp_tutorial_3d_monolayer/native_report.json", + "sha256": "f1f5804eaef6af43b73f0608071ff57c62691bbd9172b33fa45ca633a4593654", + "bytes": 3230 + }, + "native_request": { + "path": "/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-v2/native/cp_tutorial_3d_monolayer/native_request.json", + "sha256": "dfcc3c97846c1714a81ae1bb904683e03319c37f3f996d8789575f706497c484", + "bytes": 837 + } + }, + "driver_witnesses": [ + { + "cohort": "plane-facts-whole-driver-baseline-v1", + "outputs": { + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/openhcs_metadata.json": "b683f94e72c5c8a1f41b7680379e158dfc1caaea6659391cf24e0ee8e470e008", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/openhcs_metadata.json.lock": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/results/3d_monolayer_erodedResizedNuclei.csv": "cca23f86a85bb3ee7a5c3a1d174c34b5f026ca7f399be98458e1a8c6e12d5c77", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/results/3d_monolayer_Cells.csv": "6f6e7431171ed5ea73a01784105147eca0e43a6e3e41f8720df93106353c9c79", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/results/3d_monolayer_downsizedNuclei.csv": "a7b998c5a524e11747fc5452fd763fc3d9abe16f46e961f62e09e9393b6a8adf", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/results/3d_monolayer_Nuclei.csv": "17500f5d4321bbf255df31f7a3503339029c2b077045a6c10e4d4f6f0db9ad1e", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/results/3d_monolayer_Image.csv": "75ac32ff5ef57bc285ec4eae1c9b501c27a35b486bf35435af5d499d856d34a4", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/results/3d_monolayer_erodedDownsizedNuclei.csv": "ee507fb9c2387f86fc768184baf2596ebe1f8e40f7fc5eb24f252345fee63ae6", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z052_t001_NucleiLabels.tiff": "0daf51526658e23b7c9ab8872e992ebe9322399286f95741d0ccdbd357e5d631", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z008_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z060_t001_NucleiLabels.tiff": "7cc3c6c6a22f558e62194277090bdea2deb79475dd91fe7d0e49eac3c0187388", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z015_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z057_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z021_t001_CellsLabels.tiff": "daa31cb1e537e5c32b1936ab7647c5690741d2bc1d0e15c60b59ba1310a8c0ce", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z047_t001_CellsLabels.tiff": "b926aa64e1fa8aa52279a69d91dc23cf14bf0ae76107f9b360c7ae77bdf53719", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z022_t001_NucleiLabels.tiff": "50aef20e28a2f9e18ca2e28eabf6d87ec2ad20c79898e56f8d63a959ba5bb507", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z027_t001_CellsLabels.tiff": "ee9056587a19e581f5feb6078b41fa1004d923a5ddf1725aefc4b8b8c5201ad6", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z029_t001_NucleiLabels.tiff": "34bce0f06f674e20667554eed0075fde8d9d33c9c0eaeffd88a1c558499cc432", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z007_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z018_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z047_t001_NucleiLabels.tiff": "995d5ce77cbf61a9be8590f34987ef3f1dd698ae6ed393cac4d0960bc9e7a66a", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z046_t001_CellsLabels.tiff": "dc081df050be6cd19b5d5bbfe21c96c350eecf9bc6f10f608dc361a36056632a", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z042_t001_CellsLabels.tiff": "88d2e9964455459499656c4f0a762cd86376c678756635aaa6b6c8d98be01852", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z024_t001_NucleiLabels.tiff": "9e96a05ed9860cac9c57c618db2f4fe5e4b769a9d235aac6fd1d628486317df0", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z035_t001_NucleiLabels.tiff": "13e69afc324152bb91329fa758d131d849127e8fd346078d94c6adc25582b3a6", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z055_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z050_t001_CellsLabels.tiff": "ea7654a6fe1f92ad274a54935420923eec4bec5ad030187afc0ac7af02690af5", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z014_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z031_t001_NucleiLabels.tiff": "247490c261fecc26c7379ab2eebaa01e4bea523218b3cc5491d2fe2b9aadfe11", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z020_t001_NucleiLabels.tiff": "b0cd031b448d8bd2075e65710bd76c064161b25242f85ee150da7cd139fcc1a8", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z051_t001_CellsLabels.tiff": "73483bd10a0f37990084013ad054768086d6d3c929da6bc7e74f4aee37e9dbf2", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z028_t001_CellsLabels.tiff": "fef31040e0c54501c3bf965eb98f055cdb1d42c96f91cf1c239033d0a9a06534", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z022_t001_CellsLabels.tiff": "7d7ec170ed3652efa99e43d8db546c51b696821dca7727d0ff4d2f2ead7fdbaa", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z033_t001_CellsLabels.tiff": "a320b99ee129d97b99f9fac66aabb89fc1652930b3bb8b2b3fbba7b57e994f85", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z038_t001_CellsLabels.tiff": "6ac8fd9c95acc1f261e96a8fb9332e5d6a403548842f9b85ecb977e6213b4c9b", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z051_t001_NucleiLabels.tiff": "f0f36ccaf744d42da036948682cfd226e6dd4a3cfb94aed38729b2d25ede5dff", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z023_t001_CellsLabels.tiff": "2f06989618050934c73473f9342c2fe3410fd834a0ddb976cf602fe6198db7a6", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z010_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z004_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z046_t001_NucleiLabels.tiff": "c1250e060d32f2cfc07fc7e1594fdb1d6cbb4d0483fa94a8113efa695397963c", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z003_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z026_t001_NucleiLabels.tiff": "ad22809ff3f43d15c838f697061c263070dbf1da1031da39900681cdfbf9d54c", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z054_t001_CellsLabels.tiff": "25ff2ec586a568e42286f73713d64aab1208c38c016099299211f04368ac49c8", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z039_t001_CellsLabels.tiff": "22fa79a76e64013f10373be2ca2af98a2173275c5d43c9cad33135acdc376d14", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z057_t001_NucleiLabels.tiff": "695517641e9fe4b8421d4a7db56b24c755b6957c98ce32bb24ad5b25f52661eb", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z020_t001_CellsLabels.tiff": "e8105a4f04198ac75de9831247030084d6f65bf98691d7444ead7e178072fa22", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z008_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z037_t001_NucleiLabels.tiff": "927d52441c57cb3a4014effaca3e3c23c76275fb264c26e1942a9c58b85ee6d2", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z011_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z043_t001_NucleiLabels.tiff": "81a705d05b0a5bfa8783df28990c1d70634c1f4aa2bca23e02cfa8a4bc861b86", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z015_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z041_t001_NucleiLabels.tiff": "744eab7cd170d5af8d2f72ced3893dd939c4e1b0f415afab799a37ded5d046c7", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z060_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z055_t001_NucleiLabels.tiff": "44e02416cc94a70528165a4b6c42b9e19b205f9c91528076796272cb1a8504ea", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z033_t001_NucleiLabels.tiff": "512a3a0ed8025d14b0556a72ebfc13b173d14f7046817ca09876242ab63b9d6b", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z050_t001_NucleiLabels.tiff": "565b4f08f7503086c1f2f8e631d19063129e02a5767d2f979c0cec8fdec23601", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z009_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z036_t001_CellsLabels.tiff": "28b68d1300cf7b08e21dbcd4858447862520dded5c27f2d84cf223513a119eed", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z049_t001_NucleiLabels.tiff": "e92e493078672a0e0d90e31409612e215bf8486300d5c765d0e0504ff8888e7a", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z040_t001_NucleiLabels.tiff": "e0bd66b166e9f92120dbee183973849eda0afbbe6fed9d03fc4cfd2c56a96280", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z016_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z012_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z001_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z053_t001_NucleiLabels.tiff": "b8613192175a4615b58aed607474657668429cb6ac635cd012569b19667f2d3d", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z017_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z006_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z032_t001_CellsLabels.tiff": "8a2c5774044326ae722e41aae517266197fbebb0e4dd5eab4b22414fbfea309f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z032_t001_NucleiLabels.tiff": "97b09fe5444ad439c3c2007d75971dce2766d94c93268eccfee9ae49b8a04aa1", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z058_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z048_t001_NucleiLabels.tiff": "325478230529e94ba372f38f0bf512292f131d337b6ac09ce5a91b0266724e02", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z006_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z038_t001_NucleiLabels.tiff": "e2852ea83c62ab30d77681b4e39f88d3cee74ae052f1c948675ae3581c9fc28a", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z052_t001_CellsLabels.tiff": "7bb98f0587062e01b965e486fc687872651d7d90d271a2fdf0d35d67b464b233", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z041_t001_CellsLabels.tiff": "be7762756eb65f08cb337904165c6f43b5351f39405461f65ad28669abfe3899", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z005_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z011_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z044_t001_NucleiLabels.tiff": "a78264f2f5e245a3913a69f89105e94df30048b1aaef4eb80fc5c3235e78b196", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z029_t001_CellsLabels.tiff": "b3bdde5f751b8f5d41ca8b5219a3427e450cb1b8795401d0ec638940d1ad7bd9", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z059_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z056_t001_NucleiLabels.tiff": "ca0723c8b9764d5b77034719bb75a2940be35da2e04119af4c0e6d3552c08718", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z019_t001_CellsLabels.tiff": "ec6ef1d319f2732c47b06f5cf02775c8cd94540f2f30a6c002f0aace1d317955", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z002_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z036_t001_NucleiLabels.tiff": "4fa967c78709aa400246a50528a36b24ca366e825dd0e64561643369e814906b", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z039_t001_NucleiLabels.tiff": "f93e8293a37886a36844b8748083a1f8e717efab092652755263e797f12f0364", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z044_t001_CellsLabels.tiff": "e03946d94c789ee787cc29a3c8f5e5d9c56b37a0044b297ba8f403abc98eb55e", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z025_t001_CellsLabels.tiff": "03aabe5528198cfd6ec23a058dab540fb8be0870207c6dc94a62d9b621d1f2f9", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z045_t001_NucleiLabels.tiff": "94bd6a65795ad6395cc18a4fd63dc591354bef612ee49fffd2d9f63e4ed9db84", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z026_t001_CellsLabels.tiff": "5b433d931fa6637fc793b23880199c01000ef6d9e610903bb38bb8cea5574563", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z016_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z027_t001_NucleiLabels.tiff": "8c8f402d3a7c65c04e7f1575dd34de0427eeeb433ff2956d20e07d06eb48fb8d", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z018_t001_NucleiLabels.tiff": "03ba7a4d6ae53e6c84aab5926ae1e2592b5f8ca24a839a256c82f08544df4270", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z010_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z040_t001_CellsLabels.tiff": "1635ea20dd80ce99f0e86494666825a52a66645837d598fd3a3fa91f0bb77d53", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z013_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z003_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z024_t001_CellsLabels.tiff": "39899adabca74b10b9950d1f97e8b0b3bbaf136d75e7a46ef4a6e86896e3119f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z014_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z007_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z002_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z056_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z042_t001_NucleiLabels.tiff": "e07252ca1a55c5195c99666d8d3f0d70db636b4ef4b99e1a0049ca22b182d87a", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z017_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z025_t001_NucleiLabels.tiff": "9cc33676a0177130609ab1331feab1722bbde8d55b2f49031730fd5a2a40029c", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z031_t001_CellsLabels.tiff": "1b14aab71bf3623458ea9373852b0baf28be9727877b32f894407927ecfb6d65", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z035_t001_CellsLabels.tiff": "eedeb489b46abf1eafbd9c81491cb3f85ce1cb3ce877844ad22e72547fc3c438", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z021_t001_NucleiLabels.tiff": "71a10b0539f3fc4cba600b275b7e948258c6a435ba33ef522faa0869ac085518", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z019_t001_NucleiLabels.tiff": "250cb56a8054c28cea894bc3d9edaddcdce01f5151a05da78da20157c3c3be9f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z043_t001_CellsLabels.tiff": "bd0df007524ea4e555e4d2fdbebe6a274caa03bc360a1cf90d601659155984b2", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z001_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z059_t001_NucleiLabels.tiff": "76c785cf0f481c73ad3cf34ccb576eaa19dd1bdd9c74f9eaf92adfbde5d44b97", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z048_t001_CellsLabels.tiff": "133a58f6fac8b07f79bfed9634867ccb5428b83e63682031a1def16c6a694568", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z005_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z058_t001_NucleiLabels.tiff": "a37c63c6052e40d73db918a014e6f2a18be4d0cbfbeeef65a9c26096a38a4c09", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z013_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z037_t001_CellsLabels.tiff": "aa1f449f1769b27cd9f1076e70f49f0242e2549f288a77984ca159cb07cf6a40", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z004_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z030_t001_CellsLabels.tiff": "b71a2e05d270ae0cd237d6c0d97ea82a63e5ad3633723e7255c35d34e585ec80", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z054_t001_NucleiLabels.tiff": "b841c5d901c65a6138d9ff2b0ec4aa04f00765b1dd21bcd6fc9f8dc974c6035d", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z023_t001_NucleiLabels.tiff": "ecb7f78c8ca0bad2b9d0495659609b9023781b6a936d6afb0a04653eac176555", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z053_t001_CellsLabels.tiff": "ff17f538baaf179752412026a250bdbee016e3101037bf4e0dbb81199fc4c8ed", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z034_t001_CellsLabels.tiff": "3f6c1d8cdbce20aac8f70e7315bea70b147b7b6a034432845b27eeb6cfba083c", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z045_t001_CellsLabels.tiff": "c678f2100c7431e5a43c391af86a79e3436d4cf13f050f98c25f62682e4632fe", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z034_t001_NucleiLabels.tiff": "08af61857cfb97fd95fcb08d1ce18139ce7087b192044c63452bee533c5b1aa4", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z009_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z028_t001_NucleiLabels.tiff": "1676f21bd3b7e105601c83f206890507c32ba2447988be2a75d0e8153d069b65", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z012_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z030_t001_NucleiLabels.tiff": "c54c8b98a5c38a47e0cf9391a1afab09b4c8c58e06294cdb650a15add4a32b58", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z049_t001_CellsLabels.tiff": "28d83dfbf5bbf7e4da9c3e4806353e9fd0a89680dcdab4b43ca2fd19b80f669c" + }, + "observations": { + "path": "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/observations.json", + "sha256": "a9558f52b6d74972c4244b9af73e03cfe66ecada108d1d2131db5af56c868260", + "bytes": 2518 + }, + "source_freeze": { + "path": "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/source-freeze.json", + "sha256": "55ee41e2e0f09553de9c2be7dab5beedf0f4f2baf7245f2778c2dcedc38a092e", + "bytes": 1161129 + }, + "measured_receipt": { + "path": "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/ordinary_run_evidence/cp_tutorial_3d_monolayer-1w_1t-1791017734852071625/measured_pipeline_receipt.json", + "sha256": "da9430eb33c8e5724edc9c28431ff22848bef9a0eda94da59139b20a3349058e", + "bytes": 23182 + } + }, + { + "cohort": "plane-facts-whole-driver-candidate-v1", + "outputs": { + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/openhcs_metadata.json": "9ff815827f4a4a5cec301260e570ffc7f1b56a9f6422e08309c08e3ed34e01ac", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/openhcs_metadata.json.lock": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/results/3d_monolayer_erodedResizedNuclei.csv": "cca23f86a85bb3ee7a5c3a1d174c34b5f026ca7f399be98458e1a8c6e12d5c77", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/results/3d_monolayer_Cells.csv": "6f6e7431171ed5ea73a01784105147eca0e43a6e3e41f8720df93106353c9c79", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/results/3d_monolayer_downsizedNuclei.csv": "a7b998c5a524e11747fc5452fd763fc3d9abe16f46e961f62e09e9393b6a8adf", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/results/3d_monolayer_Nuclei.csv": "17500f5d4321bbf255df31f7a3503339029c2b077045a6c10e4d4f6f0db9ad1e", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/results/3d_monolayer_Image.csv": "75ac32ff5ef57bc285ec4eae1c9b501c27a35b486bf35435af5d499d856d34a4", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/results/3d_monolayer_erodedDownsizedNuclei.csv": "ee507fb9c2387f86fc768184baf2596ebe1f8e40f7fc5eb24f252345fee63ae6", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z052_t001_NucleiLabels.tiff": "0daf51526658e23b7c9ab8872e992ebe9322399286f95741d0ccdbd357e5d631", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z008_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z060_t001_NucleiLabels.tiff": "7cc3c6c6a22f558e62194277090bdea2deb79475dd91fe7d0e49eac3c0187388", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z015_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z057_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z021_t001_CellsLabels.tiff": "daa31cb1e537e5c32b1936ab7647c5690741d2bc1d0e15c60b59ba1310a8c0ce", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z047_t001_CellsLabels.tiff": "b926aa64e1fa8aa52279a69d91dc23cf14bf0ae76107f9b360c7ae77bdf53719", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z022_t001_NucleiLabels.tiff": "50aef20e28a2f9e18ca2e28eabf6d87ec2ad20c79898e56f8d63a959ba5bb507", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z027_t001_CellsLabels.tiff": "ee9056587a19e581f5feb6078b41fa1004d923a5ddf1725aefc4b8b8c5201ad6", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z029_t001_NucleiLabels.tiff": "34bce0f06f674e20667554eed0075fde8d9d33c9c0eaeffd88a1c558499cc432", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z007_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z018_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z047_t001_NucleiLabels.tiff": "995d5ce77cbf61a9be8590f34987ef3f1dd698ae6ed393cac4d0960bc9e7a66a", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z046_t001_CellsLabels.tiff": "dc081df050be6cd19b5d5bbfe21c96c350eecf9bc6f10f608dc361a36056632a", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z042_t001_CellsLabels.tiff": "88d2e9964455459499656c4f0a762cd86376c678756635aaa6b6c8d98be01852", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z024_t001_NucleiLabels.tiff": "9e96a05ed9860cac9c57c618db2f4fe5e4b769a9d235aac6fd1d628486317df0", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z035_t001_NucleiLabels.tiff": "13e69afc324152bb91329fa758d131d849127e8fd346078d94c6adc25582b3a6", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z055_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z050_t001_CellsLabels.tiff": "ea7654a6fe1f92ad274a54935420923eec4bec5ad030187afc0ac7af02690af5", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z014_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z031_t001_NucleiLabels.tiff": "247490c261fecc26c7379ab2eebaa01e4bea523218b3cc5491d2fe2b9aadfe11", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z020_t001_NucleiLabels.tiff": "b0cd031b448d8bd2075e65710bd76c064161b25242f85ee150da7cd139fcc1a8", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z051_t001_CellsLabels.tiff": "73483bd10a0f37990084013ad054768086d6d3c929da6bc7e74f4aee37e9dbf2", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z028_t001_CellsLabels.tiff": "fef31040e0c54501c3bf965eb98f055cdb1d42c96f91cf1c239033d0a9a06534", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z022_t001_CellsLabels.tiff": "7d7ec170ed3652efa99e43d8db546c51b696821dca7727d0ff4d2f2ead7fdbaa", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z033_t001_CellsLabels.tiff": "a320b99ee129d97b99f9fac66aabb89fc1652930b3bb8b2b3fbba7b57e994f85", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z038_t001_CellsLabels.tiff": "6ac8fd9c95acc1f261e96a8fb9332e5d6a403548842f9b85ecb977e6213b4c9b", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z051_t001_NucleiLabels.tiff": "f0f36ccaf744d42da036948682cfd226e6dd4a3cfb94aed38729b2d25ede5dff", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z023_t001_CellsLabels.tiff": "2f06989618050934c73473f9342c2fe3410fd834a0ddb976cf602fe6198db7a6", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z010_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z004_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z046_t001_NucleiLabels.tiff": "c1250e060d32f2cfc07fc7e1594fdb1d6cbb4d0483fa94a8113efa695397963c", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z003_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z026_t001_NucleiLabels.tiff": "ad22809ff3f43d15c838f697061c263070dbf1da1031da39900681cdfbf9d54c", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z054_t001_CellsLabels.tiff": "25ff2ec586a568e42286f73713d64aab1208c38c016099299211f04368ac49c8", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z039_t001_CellsLabels.tiff": "22fa79a76e64013f10373be2ca2af98a2173275c5d43c9cad33135acdc376d14", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z057_t001_NucleiLabels.tiff": "695517641e9fe4b8421d4a7db56b24c755b6957c98ce32bb24ad5b25f52661eb", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z020_t001_CellsLabels.tiff": "e8105a4f04198ac75de9831247030084d6f65bf98691d7444ead7e178072fa22", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z008_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z037_t001_NucleiLabels.tiff": "927d52441c57cb3a4014effaca3e3c23c76275fb264c26e1942a9c58b85ee6d2", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z011_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z043_t001_NucleiLabels.tiff": "81a705d05b0a5bfa8783df28990c1d70634c1f4aa2bca23e02cfa8a4bc861b86", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z015_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z041_t001_NucleiLabels.tiff": "744eab7cd170d5af8d2f72ced3893dd939c4e1b0f415afab799a37ded5d046c7", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z060_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z055_t001_NucleiLabels.tiff": "44e02416cc94a70528165a4b6c42b9e19b205f9c91528076796272cb1a8504ea", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z033_t001_NucleiLabels.tiff": "512a3a0ed8025d14b0556a72ebfc13b173d14f7046817ca09876242ab63b9d6b", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z050_t001_NucleiLabels.tiff": "565b4f08f7503086c1f2f8e631d19063129e02a5767d2f979c0cec8fdec23601", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z009_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z036_t001_CellsLabels.tiff": "28b68d1300cf7b08e21dbcd4858447862520dded5c27f2d84cf223513a119eed", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z049_t001_NucleiLabels.tiff": "e92e493078672a0e0d90e31409612e215bf8486300d5c765d0e0504ff8888e7a", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z040_t001_NucleiLabels.tiff": "e0bd66b166e9f92120dbee183973849eda0afbbe6fed9d03fc4cfd2c56a96280", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z016_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z012_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z001_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z053_t001_NucleiLabels.tiff": "b8613192175a4615b58aed607474657668429cb6ac635cd012569b19667f2d3d", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z017_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z006_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z032_t001_CellsLabels.tiff": "8a2c5774044326ae722e41aae517266197fbebb0e4dd5eab4b22414fbfea309f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z032_t001_NucleiLabels.tiff": "97b09fe5444ad439c3c2007d75971dce2766d94c93268eccfee9ae49b8a04aa1", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z058_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z048_t001_NucleiLabels.tiff": "325478230529e94ba372f38f0bf512292f131d337b6ac09ce5a91b0266724e02", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z006_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z038_t001_NucleiLabels.tiff": "e2852ea83c62ab30d77681b4e39f88d3cee74ae052f1c948675ae3581c9fc28a", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z052_t001_CellsLabels.tiff": "7bb98f0587062e01b965e486fc687872651d7d90d271a2fdf0d35d67b464b233", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z041_t001_CellsLabels.tiff": "be7762756eb65f08cb337904165c6f43b5351f39405461f65ad28669abfe3899", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z005_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z011_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z044_t001_NucleiLabels.tiff": "a78264f2f5e245a3913a69f89105e94df30048b1aaef4eb80fc5c3235e78b196", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z029_t001_CellsLabels.tiff": "b3bdde5f751b8f5d41ca8b5219a3427e450cb1b8795401d0ec638940d1ad7bd9", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z059_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z056_t001_NucleiLabels.tiff": "ca0723c8b9764d5b77034719bb75a2940be35da2e04119af4c0e6d3552c08718", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z019_t001_CellsLabels.tiff": "ec6ef1d319f2732c47b06f5cf02775c8cd94540f2f30a6c002f0aace1d317955", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z002_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z036_t001_NucleiLabels.tiff": "4fa967c78709aa400246a50528a36b24ca366e825dd0e64561643369e814906b", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z039_t001_NucleiLabels.tiff": "f93e8293a37886a36844b8748083a1f8e717efab092652755263e797f12f0364", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z044_t001_CellsLabels.tiff": "e03946d94c789ee787cc29a3c8f5e5d9c56b37a0044b297ba8f403abc98eb55e", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z025_t001_CellsLabels.tiff": "03aabe5528198cfd6ec23a058dab540fb8be0870207c6dc94a62d9b621d1f2f9", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z045_t001_NucleiLabels.tiff": "94bd6a65795ad6395cc18a4fd63dc591354bef612ee49fffd2d9f63e4ed9db84", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z026_t001_CellsLabels.tiff": "5b433d931fa6637fc793b23880199c01000ef6d9e610903bb38bb8cea5574563", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z016_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z027_t001_NucleiLabels.tiff": "8c8f402d3a7c65c04e7f1575dd34de0427eeeb433ff2956d20e07d06eb48fb8d", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z018_t001_NucleiLabels.tiff": "03ba7a4d6ae53e6c84aab5926ae1e2592b5f8ca24a839a256c82f08544df4270", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z010_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z040_t001_CellsLabels.tiff": "1635ea20dd80ce99f0e86494666825a52a66645837d598fd3a3fa91f0bb77d53", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z013_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z003_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z024_t001_CellsLabels.tiff": "39899adabca74b10b9950d1f97e8b0b3bbaf136d75e7a46ef4a6e86896e3119f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z014_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z007_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z002_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z056_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z042_t001_NucleiLabels.tiff": "e07252ca1a55c5195c99666d8d3f0d70db636b4ef4b99e1a0049ca22b182d87a", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z017_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z025_t001_NucleiLabels.tiff": "9cc33676a0177130609ab1331feab1722bbde8d55b2f49031730fd5a2a40029c", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z031_t001_CellsLabels.tiff": "1b14aab71bf3623458ea9373852b0baf28be9727877b32f894407927ecfb6d65", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z035_t001_CellsLabels.tiff": "eedeb489b46abf1eafbd9c81491cb3f85ce1cb3ce877844ad22e72547fc3c438", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z021_t001_NucleiLabels.tiff": "71a10b0539f3fc4cba600b275b7e948258c6a435ba33ef522faa0869ac085518", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z019_t001_NucleiLabels.tiff": "250cb56a8054c28cea894bc3d9edaddcdce01f5151a05da78da20157c3c3be9f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z043_t001_CellsLabels.tiff": "bd0df007524ea4e555e4d2fdbebe6a274caa03bc360a1cf90d601659155984b2", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z001_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z059_t001_NucleiLabels.tiff": "76c785cf0f481c73ad3cf34ccb576eaa19dd1bdd9c74f9eaf92adfbde5d44b97", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z048_t001_CellsLabels.tiff": "133a58f6fac8b07f79bfed9634867ccb5428b83e63682031a1def16c6a694568", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z005_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z058_t001_NucleiLabels.tiff": "a37c63c6052e40d73db918a014e6f2a18be4d0cbfbeeef65a9c26096a38a4c09", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z013_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z037_t001_CellsLabels.tiff": "aa1f449f1769b27cd9f1076e70f49f0242e2549f288a77984ca159cb07cf6a40", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z004_t001_NucleiLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z030_t001_CellsLabels.tiff": "b71a2e05d270ae0cd237d6c0d97ea82a63e5ad3633723e7255c35d34e585ec80", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z054_t001_NucleiLabels.tiff": "b841c5d901c65a6138d9ff2b0ec4aa04f00765b1dd21bcd6fc9f8dc974c6035d", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z023_t001_NucleiLabels.tiff": "ecb7f78c8ca0bad2b9d0495659609b9023781b6a936d6afb0a04653eac176555", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z053_t001_CellsLabels.tiff": "ff17f538baaf179752412026a250bdbee016e3101037bf4e0dbb81199fc4c8ed", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z034_t001_CellsLabels.tiff": "3f6c1d8cdbce20aac8f70e7315bea70b147b7b6a034432845b27eeb6cfba083c", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z045_t001_CellsLabels.tiff": "c678f2100c7431e5a43c391af86a79e3436d4cf13f050f98c25f62682e4632fe", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z034_t001_NucleiLabels.tiff": "08af61857cfb97fd95fcb08d1ce18139ce7087b192044c63452bee533c5b1aa4", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z009_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z028_t001_NucleiLabels.tiff": "1676f21bd3b7e105601c83f206890507c32ba2447988be2a75d0e8153d069b65", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z012_t001_CellsLabels.tiff": "abfe34a68285c9292a8b8ffce8d8ab1a3cf4fe8d09258071ed888461a454000f", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z030_t001_NucleiLabels.tiff": "c54c8b98a5c38a47e0cf9391a1afab09b4c8c58e06294cdb650a15add4a32b58", + "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z049_t001_CellsLabels.tiff": "28d83dfbf5bbf7e4da9c3e4806353e9fd0a89680dcdab4b43ca2fd19b80f669c" + }, + "observations": { + "path": "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/observations.json", + "sha256": "6594071a580a83a5abd4cdb58c399899d046c84eaa52ed1c4f5dc0faab2bf88d", + "bytes": 2522 + }, + "source_freeze": { + "path": "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/source-freeze.json", + "sha256": "20c7690c2346a7e33625823ca1456b1774ec76192708a61aaf9f4b1170dc5d16", + "bytes": 1161766 + }, + "measured_receipt": { + "path": "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/ordinary_run_evidence/cp_tutorial_3d_monolayer-1w_1t-1791017860408836180/measured_pipeline_receipt.json", + "sha256": "49db7f2e2cfda0c0fd7dc3a4fa6a7542e70038fde080dbf73f5498f1a506ae34", + "bytes": 23189 + } + } + ], + "comparator_sha256": "b772d231196eaf23d9a150ffa491f95426cb6e074470ac3febd508afd1d3ad18", + "source_tracked_hashes_sha256": "185dea17cd6233c369ce1b9145978d19e9a0394d310d38b3a360c28faa7874a1" +} diff --git a/benchmark/results/perf_rejected_metadata_owner_20261003/submitted-input-controls.json b/benchmark/results/perf_rejected_metadata_owner_20261003/submitted-input-controls.json new file mode 100644 index 0000000000..da10d0840e --- /dev/null +++ b/benchmark/results/perf_rejected_metadata_owner_20261003/submitted-input-controls.json @@ -0,0 +1,22 @@ +{ + "normalized_submissions_equal": true, + "only_pipeline_difference": "Fresh output directory baseline-v1 versus candidate-v1; original global config bytes identical.", + "files": { + "baseline-submitted_pipeline.py": { + "sha256": "722a76ce2eecbfbe409df3599d4b44841862d33dc3a24b828e8ad2d1e381f47e", + "path": "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/ordinary_run_evidence/cp_tutorial_3d_monolayer-1w_1t-1791017734852071625/submitted_pipeline.py" + }, + "candidate-submitted_pipeline.py": { + "sha256": "1db8114e4c171af265fb58b76268c8576d00a974c0eea7b17bb5ba80ca5f4ad3", + "path": "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/ordinary_run_evidence/cp_tutorial_3d_monolayer-1w_1t-1791017860408836180/submitted_pipeline.py" + }, + "baseline-submitted_global_config.py": { + "sha256": "2e2cf95d87a9465d20ecbb8c88629ce615b64de6e5843319f9b51599f343c1c3", + "path": "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-baseline-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/ordinary_run_evidence/cp_tutorial_3d_monolayer-1w_1t-1791017734852071625/submitted_global_config.py" + }, + "candidate-submitted_global_config.py": { + "sha256": "2e2cf95d87a9465d20ecbb8c88629ce615b64de6e5843319f9b51599f343c1c3", + "path": "/home/ts/.local/state/openhcs-maintenance/20261003/plane-facts-whole-driver-candidate-v1/public/cp_tutorial_3d_monolayer/wells_1/workers_1/ordinary_run_evidence/cp_tutorial_3d_monolayer-1w_1t-1791017860408836180/submitted_global_config.py" + } + } +} diff --git a/benchmark/results/perf_rejected_metadata_owner_20261003/whole-driver-controller.py b/benchmark/results/perf_rejected_metadata_owner_20261003/whole-driver-controller.py new file mode 100644 index 0000000000..77d51c2449 --- /dev/null +++ b/benchmark/results/perf_rejected_metadata_owner_20261003/whole-driver-controller.py @@ -0,0 +1,128 @@ +"""Prepare-only near-ordinary nested boundary ledger; both profilers disabled.""" +import argparse,ast,csv,fcntl,hashlib,importlib.util,json,os,shutil,subprocess +from pathlib import Path +BASE=Path('/var/tmp/run_narrow450_runtime_phase_probe_20261002.py') +SPARSE=Path('/var/tmp/openhcs_measurement_sparse_inventory_v2_20261003.py') +SUPPLEMENT=Path('/home/ts/.local/state/openhcs-maintenance/20261003/current-3d-speckles-paired-preparation-v2/sparse-supplement') +ORIGINAL_SITE=Path('/var/tmp/openhcs-current-generic-job-profile-site-v1-20261002/sitecustomize.py') +SITE=Path(__file__).parent/'site' +OUTPUT=Path(__file__).parent/'output' +JSON_CAP=40*1024**2 +OUTPUT_CAP=64*1024**2 +LOG_CAP=1024**2 +HOME_RESERVE=1024**3 +MIN_FREE=512*1024**2 +INDEX='MeasurementFeatureValueIndex.from_columnar_table_by_object' + +def load_module(name,path): + spec=importlib.util.spec_from_file_location(name,path) + module=importlib.util.module_from_spec(spec);spec.loader.exec_module(module);return module + +def controller(source,revision): + m=load_module('original_phase_controller',BASE) + m.SOURCE=Path(source).resolve();m.REVISION=revision;m.SITE=SITE;m.OUTPUT=OUTPUT + m.CASES=('cp_tutorial_3d_monolayer',) + return m + +def environment(m): + env=m.ordinary_helper().environment(m.SOURCE) + for key in tuple(env): + if key.startswith('OPENHCS_DIAGNOSTIC_') or key.startswith('OPENHCS_PROFILE_FUNCTION_RUNTIME') or key=='OPENHCS_WORKER_PROFILE_DIR':del env[key] + env.update(PYTHONDONTWRITEBYTECODE='1',PYTHONPATH=str(SITE)+':'+str(m.SOURCE), + OPENHCS_DIAGNOSTIC_SOURCE=str(m.SOURCE),OPENHCS_DIAGNOSTIC_OUTPUT=str(OUTPUT/'regions'), + OPENHCS_DIAGNOSTIC_FREEZE=str(OUTPUT/'source-freeze.json'),TMPDIR=str(OUTPUT/'tmp')) + return env + +def env_hash(env): + return hashlib.sha256(json.dumps(env,sort_keys=True).encode()).hexdigest() + +def prepare_or_validate(m): + sparse=load_module('preserved_sparse_source_controller',SPARSE) + sparse.SUPPLEMENT=SUPPLEMENT + inventory=sparse.sparse_source_inventory(m.SOURCE) + freeze_path=OUTPUT/'source-freeze.json' + env=environment(m) + if freeze_path.exists(): + freeze=json.loads(freeze_path.read_text()) + assert freeze['revision']==m.REVISION and freeze['source']==str(m.SOURCE) + else: + ast.parse((SITE/'sitecustomize.py').read_text()) + freeze=m.prepare() + freeze.update(sparse_source_inventory=inventory,ledger_controller_sha256=m.digest(Path(__file__)), + original_phase_controller_sha256=m.digest(BASE),sparse_source_controller_sha256=m.digest(SPARSE), + declaring_ledger_controller_sha256=m.digest(Path('/var/tmp/run_current_3d_runtime_ledger_v1_20261003.py')), + declaring_ledger_site_sha256=m.digest(Path('/var/tmp/openhcs-current-3d-runtime-ledger-site-v1-20261003/sitecustomize.py')), + supplemental_custody_root=str(SUPPLEMENT), + actual_import_dependencies={r:{'head':m.git((m.SOURCE/r).resolve(),'rev-parse','HEAD'), + 'status':m.git((m.SOURCE/r).resolve(),'status','--porcelain'), + 'files':m.tracked_source_hashes((m.SOURCE/r).resolve())} for r in freeze['shared_dependency_sources']}, + original_profile_site_sha256=m.digest(ORIGINAL_SITE),effective_environment_sha256=env_hash(env), + profiling_environment={'worker_cprofile':'DISABLED: directory unset','runtime_profiler':'DISABLED: enable/path unset'}, + storage={'minimum_free':MIN_FREE,'available_at_prepare':shutil.disk_usage('/var/tmp').free,'retained_json_cap':JSON_CAP,'generated_output_cap':OUTPUT_CAP,'public_log_cap':LOG_CAP,'captures':False}, + scope='One source-pinned whole ordinary3D Monolayer1w1t candidate falsification with24 unchanged coarse nominal hooks: inherited23 plus actual MeasurementFeatureValueIndex index classmethod. cProfile and runtime profiler OFF, no captures/percell hooks. Existing defaultOUTCOMES/memory observers/READY clocks unchanged. Same-thread nested exclusive clocks exclude query from its real ancestors; worker independent roots are not added to parent waits. Nearordinary diagnostic only; wrapper overhead remains, no scale factors/causal performance promotion. Full saved126file (6CSV120TIFF) science/native source witness independently required.', + controls='Original callable once/result/error identity; argument mutation preserved; TLS/fork reset; exact source/descriptor/signature/declaring-code checks; both profilers disabled; no class metadata mutation. Original512MiB preflight and900s subprocess timeout retained; JSON aggregate40MiB cap; overwrite refusal; existing reviewed sparse projection admitted only after original preserved copy/current Git blob validation; exact8gitlink child context. No production omission or new source authority. Site/code for all24hooks retained byte-identical; current sparse inventory V2 checks every absent tracked byte against current Git blobs including existing supplemental custody, not old V1. Source revision must be sealed/clean before prepare; no candidate import at offline construction. All24hooks retained byte-identical; feature-query hook remains installed with zero calls admitted for a workload having no such query, while actual declared callable calls must be nonempty.') + freeze_path.write_text(json.dumps(freeze,indent=2)+'\n') + sparse.validate_sparse_source_inventory(m.SOURCE,freeze['sparse_source_inventory']) + m.validate_freeze(freeze) + assert m.digest(Path(__file__))==freeze['ledger_controller_sha256'] + assert m.digest(BASE)==freeze['original_phase_controller_sha256'] + assert m.digest(SPARSE)==freeze['sparse_source_controller_sha256'] + assert m.digest(ORIGINAL_SITE)==freeze['original_profile_site_sha256'] + assert str(SUPPLEMENT)==freeze['supplemental_custody_root'] + assert m.digest(Path('/var/tmp/run_current_3d_runtime_ledger_v1_20261003.py'))==freeze['declaring_ledger_controller_sha256'] + assert m.digest(Path('/var/tmp/openhcs-current-3d-runtime-ledger-site-v1-20261003/sitecustomize.py'))==freeze['declaring_ledger_site_sha256']==freeze['site_sha256'] + assert len(freeze['actual_import_dependencies'])==8 + for relative,expected in freeze['actual_import_dependencies'].items(): + actual=(m.SOURCE/relative).resolve() + assert not expected['status'] + assert {'head':m.git(actual,'rev-parse','HEAD'),'status':m.git(actual,'status','--porcelain'),'files':m.tracked_source_hashes(actual)}==expected + assert env_hash(env)==freeze['effective_environment_sha256'],'Effective ordinary environment changed.' + assert len(freeze['declared_hooks'])==24 + assert any(r['owner']=='MeasurementFeatureValueIndex' and r['method']=='from_columnar_table_by_object' for r in freeze['declared_hooks']) + return freeze,env + +def main(source,revision,run): + assert OUTPUT.is_relative_to(Path('/home/ts/.local/state/openhcs-maintenance/20261003')),'Owned output only' + assert shutil.disk_usage(OUTPUT.parent).free>=HOME_RESERVE,'Home reserve' + available=shutil.disk_usage('/var/tmp').free + assert available>=MIN_FREE,f'Original512MiB storage preflight refused: {available} bytes free; no pipeline started.' + m=controller(source,revision);freeze,env=prepare_or_validate(m) + (OUTPUT/'tmp').mkdir(exist_ok=True) + assert sum(p.stat().st_size for p in OUTPUT.rglob('*') if p.is_file())<=OUTPUT_CAP + if not run: + print(json.dumps({'status':'PREPARED_NOT_RUN','revision':revision,'source':str(m.SOURCE),'freeze':str(OUTPUT/'source-freeze.json'),'command':freeze['command'],'hooks':len(freeze['declared_hooks']),'profilers':'BOTH_OFF'}),flush=True);return + assert not (OUTPUT/'observations.json').exists(),'Never overwrite retained diagnostic.' + assert not list((OUTPUT/'regions').glob('*.json')),'Never rerun retained regions.' + lock=Path('/tmp/openhcs-benchmark-xdg-cache/openhcs/official30-runtime.lock') + with lock.open('a+') as lease: + fcntl.flock(lease,fcntl.LOCK_EX|fcntl.LOCK_NB);prepare_or_validate(m) + with (OUTPUT/'public.log').open('w') as stream: + result=subprocess.run(freeze['command'],cwd=OUTPUT/'tmp',env=env,stdout=stream,stderr=subprocess.STDOUT,timeout=900) + prepare_or_validate(m) + region_paths=sorted((OUTPUT/'regions').glob('*.json'));regions=[json.loads(p.read_text()) for p in region_paths] + dimensions=[json.loads(r['root_dimensions']) for r in regions] + root_sequence_complete=sum(d['kind']=='compile_only' for d in dimensions)==1 and sum(d['kind']=='execution' for d in dimensions)==1 + execution=[r for r in regions if json.loads(r['root_dimensions'])['kind']=='execution'] + rows=list(csv.DictReader((OUTPUT/'public/well_throughput.csv').open())) if (OUTPUT/'public/well_throughput.csv').exists() else [] + index_calls=sum(row['calls'] for r in execution for row in r['stats'].values() if row['owner']==INDEX) + declared_calls=sum(row['calls'] for r in execution for row in r['stats'].values() if row['owner']=='RuntimeCallableInvocation.call') + retained=sum(p.stat().st_size for p in region_paths) + output_bytes=sum(p.stat().st_size for p in OUTPUT.rglob('*') if p.is_file()) + log_bytes=(OUTPUT/'public.log').stat().st_size + disabled=not list(OUTPUT.rglob('*.prof')) and not (OUTPUT/'runtime-profile.log').exists() + admission=bool(result.returncode==0 and len(rows)==1 and rows[0]['status']=='success' and rows[0]['successful_wells']=='1' + and rows[0]['execution_route']=='ordinary-zmq-outcomes-v1' and root_sequence_complete and execution and declared_calls>0 and disabled and retained<=JSON_CAP and output_bytes<=OUTPUT_CAP and log_bytes<=LOG_CAP + and all(r['revision']==revision and not r['captures'] and not r['profiling_enabled'] and not r['runtime_profiling_enabled'] + and not r['diagnostic_errors'] and abs(sum(v['exclusive'] for v in r['stats'].values())-r['seconds'])<1e-6 for r in regions)) + evidence={'returncode':result.returncode,'diagnostic_admission':admission,'public_rows':rows,'regions':[{ 'path':str(p),'sha256':m.digest(p)} for p in region_paths], + 'root_sequence_complete':root_sequence_complete,'actual_index_calls':index_calls,'actual_declared_calls':declared_calls,'retained_json_bytes':retained,'generated_output_bytes':output_bytes,'public_log_bytes':log_bytes,'profiler_artifacts_absent':disabled,'source_env_native_input_freeze':'PASS', + 'science':'NOT_RUN: original full saved-output126file/schema/discrete/numerical/nativeinput witness separate gate. No exclusions or missing outputs waived.', + 'scope':freeze['scope']} + (OUTPUT/'observations.json').write_text(json.dumps(evidence,indent=2)+'\n');print(json.dumps(evidence),flush=True) + assert admission,'Retained original ledger admission RED.' + +if __name__=='__main__': + p=argparse.ArgumentParser();p.add_argument('--source',required=True);p.add_argument('--revision',required=True);p.add_argument('--run',action='store_true');p.add_argument('--prepare',action='store_true') + p.add_argument('--output',type=Path,default=OUTPUT);a=p.parse_args();OUTPUT=a.output.resolve() + if a.prepare or a.run:main(a.source,a.revision,a.run) + else:print(json.dumps({'status':'CODE_PREPARED_NOT_FROZEN_NOT_RUN','source':a.source,'revision':a.revision,'case':'cp_tutorial_3d_monolayer','output':str(OUTPUT),'controller':str(Path(__file__)),'instruction':'ROOT reviews then --prepare and --run same source/revision/env; no freeze created by default.'})) diff --git a/benchmark/results/perf_rejected_metadata_owner_20261003/whole-driver-site.py b/benchmark/results/perf_rejected_metadata_owner_20261003/whole-driver-site.py new file mode 100644 index 0000000000..1410ea73a8 --- /dev/null +++ b/benchmark/results/perf_rejected_metadata_owner_20261003/whole-driver-site.py @@ -0,0 +1,118 @@ +import functools, hashlib, importlib.abc, importlib.machinery, inspect, json, os, sys, threading, time +from pathlib import Path +SOURCE=Path(os.environ['OPENHCS_DIAGNOSTIC_SOURCE']).resolve() +OUT=Path(os.environ['OPENHCS_DIAGNOSTIC_OUTPUT']) +freeze=json.loads(Path(os.environ['OPENHCS_DIAGNOSTIC_FREEZE']).read_text()) +assert not os.environ.get('OPENHCS_WORKER_PROFILE_DIR'), 'Worker profiler must be disabled.' +assert os.environ.get('OPENHCS_PROFILE_FUNCTION_RUNTIME','').lower() not in {'1','true','yes'}, 'Runtime profiler must be disabled.' +assert not os.environ.get('OPENHCS_PROFILE_FUNCTION_RUNTIME_PATH'), 'No runtime profiler sink.' +active=threading.local() +installed=[] +TARGETS = {'openhcs.runtime.zmq_execution_server': {'ZMQExecutionServer': ('_execute_with_orchestrator', '_initialize_orchestrator', '_export_runtime_observation')}, 'openhcs.core.orchestrator.worker_execution': {'': ('execute_worker_lane',)}, 'openhcs.core.steps.function_runtime': {'FunctionCoreExecutor': ('execute',), 'PatternGroupRuntime': ('_load_input_stack', '_validate_and_unstack', '_save_outputs')}, 'openhcs.processing.backends.lib_registry.unified_registry': {'RuntimeCallableInvocation': ('call',)}, 'openhcs.interop.cellprofiler.runtime.module_execution': {'CellProfilerModuleExecutor': ('__call__', '_image_request')}, 'openhcs.interop.cellprofiler.runtime.function_contract_execution': {'CellProfilerFunctionContractExecutor': ('execute',)}, 'openhcs.interop.cellprofiler.runtime.output_recording': {'CellProfilerOutputRecorder': ('record_module_outputs',)}, 'openhcs.interop.cellprofiler.runtime.measurement_execution_support': {'ObjectMeasurementOutputRecorder': ('record',)}, 'openhcs.core.steps.function_outputs': {'': ('finalize_function_step_outputs',), 'OpenHCSMetadataWriter': ('finalize_completed_plate',), 'RuntimeArtifactMetadataTarget': ('reconciliation_targets',)}, 'openhcs.core.virtual_workspace_metadata': {'AtomicMetadataWriter': ('publish_source_projection_metadata',)}, 'openhcs.core.runtime_stack_cache': {'RuntimeImageStackCache': ('get', 'store')}, 'openhcs.core.aligned_image_payload': {'': ('stack_image_payload_context', 'unstack_image_payload_context')}, 'openhcs.core.orchestrator.analysis_consolidation': {'': ('consolidate_analysis_outputs',)}, 'openhcs.core.measurement_feature_queries': {'MeasurementFeatureValueIndex': ('from_columnar_table_by_object',)}} +PHASES = {'ZMQExecutionServer._execute_with_orchestrator': '_execute_with_orchestrator', 'ZMQExecutionServer._initialize_orchestrator': '_initialize_orchestrator', 'ZMQExecutionServer._export_runtime_observation': '_export_runtime_observation', 'execute_worker_lane': 'execute_worker_lane', 'FunctionCoreExecutor.execute': 'execute', 'PatternGroupRuntime._load_input_stack': '_load_input_stack', 'PatternGroupRuntime._validate_and_unstack': '_validate_and_unstack', 'PatternGroupRuntime._save_outputs': '_save_outputs', 'RuntimeCallableInvocation.call': 'declared_callable_boundary', 'CellProfilerModuleExecutor.__call__': '__call__', 'CellProfilerModuleExecutor._image_request': '_image_request', 'CellProfilerFunctionContractExecutor.execute': 'execute', 'CellProfilerOutputRecorder.record_module_outputs': 'record_module_outputs', 'ObjectMeasurementOutputRecorder.record': 'record', 'finalize_function_step_outputs': 'finalize_function_step_outputs', 'OpenHCSMetadataWriter.finalize_completed_plate': 'finalize_completed_plate', 'RuntimeArtifactMetadataTarget.reconciliation_targets': 'reconciliation_targets', 'AtomicMetadataWriter.publish_source_projection_metadata': 'publish_source_projection_metadata', 'RuntimeImageStackCache.get': 'get', 'RuntimeImageStackCache.store': 'store', 'stack_image_payload_context': 'stack_image_payload_context', 'unstack_image_payload_context': 'unstack_image_payload_context', 'consolidate_analysis_outputs': 'consolidate_analysis_outputs', 'MeasurementFeatureValueIndex.from_columnar_table_by_object': 'measurement_feature_index'} +ROOTS = {'ZMQExecutionServer._execute_with_orchestrator', 'execute_worker_lane'} +def detail(label, args, kwargs): + if label == "ZMQExecutionServer._execute_with_orchestrator": + request = kwargs.get("request_context") if "request_context" in kwargs else args[1] + selected = request.request_payload.selected_pipeline_path + return json.dumps({"kind": "compile_only" if request.compile_only else "execution", "plate": str(request.plate_id), "case": None if selected is None else Path(selected).stem, "execution_id": request.execution_id, "compile_artifact_id": request.compile_artifact_id}, sort_keys=True) + if label == "execute_worker_lane": + lane = kwargs.get("lane_context") if "lane_context" in kwargs else args[2] + return json.dumps({"kind": "worker_lane", "plate": str(lane.plate_id), "worker_slot": lane.worker_slot, "execution_id": lane.execution_id}, sort_keys=True) + if label.startswith('FunctionStepExecutor.'): + plan = args[0].plan + return f'step={plan.step_index}:{plan.step_name}' + if label.startswith('FunctionCoreExecutor.'): + return 'function=' + args[0].function_name + if label == 'CellProfilerFunctionContractExecutor.execute': + contract = kwargs.get('callable_contract') if 'callable_contract' in kwargs else args[1] + return 'function=' + contract.module_name + '.' + contract.function_name + if label == 'RuntimeCallableInvocation.call': + invocation = args[0] + func = invocation.func + return 'function=' + func.__module__ + '.' + func.__qualname__ + ';view=' + str(invocation.callable_view.value) + return '' + +def safe_detail(label,args,kwargs): + try:return detail(label,args,kwargs) + except Exception as error: + active.diagnostic_errors.append({'owner':label,'type':type(error).__name__,'message':str(error)}) + return 'DIAGNOSTIC_DETAIL_UNAVAILABLE' + +def reset_fork(): + global active + active=threading.local() +os.register_at_fork(after_in_child=reset_fork) +def instrument(original, label): + @functools.wraps(original) + def wrapped(*args, **kwargs): + root=not getattr(active, 'enabled', False) + if root and label not in ROOTS: + return original(*args, **kwargs) + if root: + active.enabled=True; active.stats={}; active.stack=[]; active.diagnostic_errors=[]; active.root_dimensions=safe_detail(label,args,kwargs) + dimensions=safe_detail(label,args,kwargs) + name=label+(' | '+dimensions if dimensions else '') + frame={'start':time.perf_counter(), 'children':0.} + active.stack.append(frame) + try: + return original(*args,**kwargs) + finally: + elapsed=time.perf_counter()-frame['start'] + assert active.stack.pop() is frame + row=active.stats.setdefault(name, {'owner':label,'dimensions':dimensions,'phase':PHASES[label],'calls':0,'inclusive':0.,'exclusive':0.}) + row['calls']+=1; row['inclusive']+=elapsed; row['exclusive']+=elapsed-frame['children'] + if active.stack: + active.stack[-1]['children']+=elapsed + if root: + active.enabled=False + sequence=getattr(active,'sequence',0)+1;active.sequence=sequence + path=OUT/f'region-{os.getpid()}-{threading.get_ident()}-{sequence:04}.json' + assert not path.exists() + value={'pid':os.getpid(),'thread':threading.get_ident(),'region':label,'root_dimensions':active.root_dimensions,'seconds':elapsed,'revision':freeze['revision'],'source':str(SOURCE),'stats':active.stats,'hooks_installed':installed,'profiling_enabled':False,'runtime_profiling_enabled':False,'diagnostic_errors':active.diagnostic_errors,'captures':False,'scope':'coarse same-run nested exclusive timing partition on the exact source revision recorded in this region. Diagnostic wrappers, no scientific or memory-observer substitutions. Not accepted performance comparison. Declared callable boundary includes filtering/decorated processing/metadata; not pure numerical kernels. Both existing profilers are disabled. These wrappers still add diagnostic overhead; no scaling to uninstrumented clocks or causal performance claims. Query boundary is nested under its actual parent and excluded from parent-exclusive elapsed.'} + assert abs(sum(r['exclusive'] for r in active.stats.values())-elapsed)<1e-6 + path.write_text(json.dumps(value,indent=2)+'\n') + return wrapped +class Loader(importlib.abc.InspectLoader): + def __init__(self, loader): self.loader=loader + def create_module(self,spec): return self.loader.create_module(spec) + def get_code(self,fullname): return self.loader.get_code(fullname) + def get_source(self,fullname): return self.loader.get_source(fullname) + def is_package(self,fullname): return self.loader.is_package(fullname) + def get_filename(self,fullname): return self.loader.get_filename(fullname) + def exec_module(self,module): + self.loader.exec_module(module) + path=Path(module.__file__).resolve();relative=str(path.relative_to(SOURCE)) + assert hashlib.sha256(path.read_bytes()).hexdigest()==freeze['files'][relative] + for owner_path,names in TARGETS[module.__name__].items(): + owner=module + for part in owner_path.split('.') if owner_path else (): owner=getattr(owner,part) + for name in names: + descriptor=inspect.getattr_static(owner,name) + declared_original=descriptor.__func__ if isinstance(descriptor,(classmethod,staticmethod)) else descriptor + original_signature=inspect.signature(declared_original) + original_code=declared_original.__code__ + source_declared=inspect.unwrap(declared_original) + assert Path(source_declared.__code__.co_filename).resolve()==path,(module.__name__,owner_path,name,source_declared.__code__.co_filename) + label=(owner_path+'.' if owner_path else '')+name + if isinstance(descriptor,classmethod): replacement=classmethod(instrument(descriptor.__func__,label));kind='classmethod' + elif isinstance(descriptor,staticmethod):replacement=staticmethod(instrument(descriptor.__func__,label));kind='staticmethod' + else: + assert callable(descriptor),(owner_path,name) + replacement=instrument(descriptor,label);kind='function' + setattr(owner,name,replacement) + assert type(inspect.getattr_static(owner,name)) is type(replacement) + wrapped_descriptor=inspect.getattr_static(owner,name) + wrapped_function=wrapped_descriptor.__func__ if isinstance(wrapped_descriptor,(classmethod,staticmethod)) else wrapped_descriptor + assert wrapped_function.__wrapped__ is declared_original + assert inspect.signature(wrapped_function)==original_signature + assert wrapped_function.__wrapped__.__code__ is original_code + installed.append({'module':module.__name__,'owner':owner_path,'method':name,'descriptor_kind':kind}) +class Finder(importlib.abc.MetaPathFinder): + def find_spec(self,fullname,path=None,target=None): + if fullname not in TARGETS:return None + spec=importlib.machinery.PathFinder.find_spec(fullname,path,target) + assert spec is not None and isinstance(spec.loader,importlib.machinery.SourceFileLoader) + spec.loader=Loader(spec.loader) + return spec +sys.meta_path.insert(0,Finder()) diff --git a/benchmark/results/perf_schema_source_readiness_20261003/README.rst b/benchmark/results/perf_schema_source_readiness_20261003/README.rst new file mode 100644 index 0000000000..e450fc5dc8 --- /dev/null +++ b/benchmark/results/perf_schema_source_readiness_20261003/README.rst @@ -0,0 +1,53 @@ +Registered source readiness: ordinary Illumination ABBA +==================================================== + +``receipt.json`` contains public observations, the exact variant hashes and full +science-qualification links. The original local experiment scripts remain in +Git history and the maintenance directory named below. Their redundant tracked +copies were removed because they require absolute local helper, source-variant, +freeze and physical dataset/native paths. They are historical evidence, not +turnkey portable benchmark commands. The public benchmark driver and strict +scientific comparison authorities remain unchanged. Do not rerun into a +completed output directory. + +Only three source files vary. Their baseline bytes are derived from the recorded +Git revisions in ``receipt.json``. Candidate registry bytes are available at +OpenHCS commit ``7258826d7198f2bb7010763276dba02320d62142``; candidate dependency +bytes are available at python-introspect merge +``6f5ac0b79d6cef163df6a8389e72a889a91ed548`` and ObjectState merge +``55e71df39a05aa08d00bc1bb06c2be174ad2c522``. The original maintenance directory +retains all six variant files, source freezes and four immutable output trees. +No dependency source, benchmark images or environments are duplicated here. + +Immutable recipe custody +----------------------- + +The byte-identical originals remain under +``/home/ts/.local/state/openhcs-maintenance/20261003/schema-source-readiness-ordinary-abba-v1``. +All six referenced A/B source files there match the hashes in ``receipt.json``; +the source freezes and four completed output trees remain intact. The following +links identify the removed copies at immutable commit +``986f6a917ecfed38f121158201ea902e091d2992``: + +* `controller.py `_ + (maintenance basename ``controller.py``). + SHA-256: ``6fcf1cb1008ac32ee3ceaff8fd61f6db1fdba87544e1ffee1e4b3d484ce30b90``. + Git blob: ``effe202bcd36777cc6af76bd66376a15e8a0ed24``. +* `validate_science.py `_ + (maintenance basename ``validate_science.py``). + SHA-256: ``86fd34f0ca552309a453c5c169a97b949304aa37fb642a66972f4d12f9940684``. + Git blob: ``fcbe65f2a69c22cba0c057adc67d18d53a0da45b``. +* `variants.json `_ + (maintenance basename ``variants.json``). + SHA-256: ``d65bf31aacafae16045118722bd68b0cc55c454f9ebd50df7713ade3a7858fcf``. + Git blob: ``3cbd1f0ed47ac2840e0297d381c1ea7f93bff8ff``. + +Measured scope +-------------- + +Mean compilation is 0.962152 → 0.587605 seconds; total is +1.693765 → 1.363694 seconds, excluding mandatory server READY/startup and +shutdown. Execution has no demonstrated improvement. All four complete authored +image inventories pass exact byte parity and the retained native physical input +qualification; no new native CP timing is claimed. Other workloads and scaling +remain unmeasured for this change. diff --git a/benchmark/results/perf_schema_source_readiness_20261003/receipt.json b/benchmark/results/perf_schema_source_readiness_20261003/receipt.json new file mode 100644 index 0000000000..817e85e994 --- /dev/null +++ b/benchmark/results/perf_schema_source_readiness_20261003/receipt.json @@ -0,0 +1,261 @@ +{ + "status": "ALL4_ORDINARY_AUTHORED_IMAGES_EXACT_AND_RETAINED_NATIVE_INPUT_PARITY_PASS", + "case": "ExampleIlluminationCorrection_Example3", + "mode": "1w_1t", + "cpu": 5, + "candidate_openhcs_commit": "7258826d7198f2bb7010763276dba02320d62142", + "variants": [ + { + "path": "/home/ts/code/projects/openhcs-shared-runtime-plumbing/openhcs/processing/backends/lib_registry/registry_service.py", + "baseline_revision": "4eaacf17e5de3dba59ec217f133fa6e1821c8641", + "repository": "/home/ts/code/projects/openhcs-shared-runtime-plumbing", + "relative": "openhcs/processing/backends/lib_registry/registry_service.py", + "A": "/home/ts/.local/state/openhcs-maintenance/20261003/schema-source-readiness-ordinary-abba-v1/0-A.source", + "B": "/home/ts/.local/state/openhcs-maintenance/20261003/schema-source-readiness-ordinary-abba-v1/0-B.source", + "A_sha256": "73e0d41f98d7ea5bb3fe076b97b97d9980b621c54f2d23b808550e00bae481d4", + "B_sha256": "d9e6e30b627fae7b01e08872c58ad26ee060919b6b6bd9fd9174223f2ec5a95b" + }, + { + "path": "/home/ts/code/projects/openhcs-shared-runtime-plumbing/external/python-introspect/src/python_introspect/signature_analyzer.py", + "baseline_revision": "13f6ff3b43aaa430f5e771848f08d99faf941158", + "repository": "/home/ts/code/projects/openhcs-shared-runtime-plumbing/external/python-introspect", + "relative": "src/python_introspect/signature_analyzer.py", + "A": "/home/ts/.local/state/openhcs-maintenance/20261003/schema-source-readiness-ordinary-abba-v1/1-A.source", + "B": "/home/ts/.local/state/openhcs-maintenance/20261003/schema-source-readiness-ordinary-abba-v1/1-B.source", + "A_sha256": "51f4729861062ab857153c57d64b01bd7b0f47daa6f18fc4443819fb75c77b45", + "B_sha256": "7e25a0355159c86d361a21a7afc449ec758cbf8a32e9b72d06de66a924f04159" + }, + { + "path": "/home/ts/code/projects/openhcs-shared-runtime-plumbing/external/ObjectState/src/objectstate/lazy_factory.py", + "baseline_revision": "b0004daf3223326ac78689ba7b2e68abc18ae298", + "repository": "/home/ts/code/projects/openhcs-shared-runtime-plumbing/external/ObjectState", + "relative": "src/objectstate/lazy_factory.py", + "A": "/home/ts/.local/state/openhcs-maintenance/20261003/schema-source-readiness-ordinary-abba-v1/2-A.source", + "B": "/home/ts/.local/state/openhcs-maintenance/20261003/schema-source-readiness-ordinary-abba-v1/2-B.source", + "A_sha256": "f81ce722695dbab98fd02658f2015e5cb93c1e1e69547d24249e62d896e2a828", + "B_sha256": "90637bdad398bae1348168e62533d69618ec965341b1b27057292e709c2a1f85" + } + ], + "means": { + "A": { + "compile_seconds": 0.9621515274047852, + "execute_seconds": 0.38265538215637207, + "total_seconds": 1.693764767376706 + }, + "B": { + "compile_seconds": 0.5876049995422363, + "execute_seconds": 0.40058863162994385, + "total_seconds": 1.3636944827158004 + } + }, + "saved_seconds": { + "compile_seconds": 0.37454652786254883, + "execute_seconds": -0.017933249473571777, + "total_seconds": 0.3300702846609056 + }, + "runs": [ + { + "label": "A", + "public_rows": [ + { + "case_name": "ExampleIlluminationCorrection_Example3", + "mode_name": "1w_1t", + "worker_count": "1", + "well_count": "1", + "compile_seconds": "0.9799041748046875", + "prepare_seconds": "0.0", + "execute_seconds": "0.38725757598876953", + "total_seconds": "1.7173671890050173", + "wells_per_second": "2.5822606502835725", + "successful_wells": "1", + "native_single_sample_execution_seconds": "", + "projected_native_execution_seconds": "", + "projected_execution_speedup": "", + "peak_memory_mb": "1011.84765625", + "status": "success", + "memory_limit_mb": "", + "error_message": "", + "execution_route": "ordinary-zmq-outcomes-v1", + "server_lifecycle": "reused-per-sweep", + "run_input_sha256": "a37695e774a71b04c3e2a390df76245c973458380fca25a9aac513dbf5e8be8e" + } + ], + "receipt_sha256": "6805ee89e2872aea6199e959e53b956ef144e2ff82516fbf6ac68042450d6fd2", + "source_freeze_sha256": "d71dcaef08a9eb2ac12a00b5e004aedfcd9b9606d860e6a8bca5da73baa9900b" + }, + { + "label": "B", + "public_rows": [ + { + "case_name": "ExampleIlluminationCorrection_Example3", + "mode_name": "1w_1t", + "worker_count": "1", + "well_count": "1", + "compile_seconds": "0.593247652053833", + "prepare_seconds": "0.0", + "execute_seconds": "0.42087531089782715", + "total_seconds": "1.4185294113121927", + "wells_per_second": "2.3760006208650304", + "successful_wells": "1", + "native_single_sample_execution_seconds": "", + "projected_native_execution_seconds": "", + "projected_execution_speedup": "", + "peak_memory_mb": "1043.54296875", + "status": "success", + "memory_limit_mb": "", + "error_message": "", + "execution_route": "ordinary-zmq-outcomes-v1", + "server_lifecycle": "reused-per-sweep", + "run_input_sha256": "3c135c9fa72e1a8ec100dca796e96c7f6721cccfab82316b3836236b6b4e75b0" + } + ], + "receipt_sha256": "c8f76ce4b6acaa60f5bbfe13c5a5ca924e299d5c8834e249f757dd53adc434c7", + "source_freeze_sha256": "ac0a8d0ad5938927dbddf01b937ef15387a15c6701d87d292ed486fbcbec7870" + }, + { + "label": "B", + "public_rows": [ + { + "case_name": "ExampleIlluminationCorrection_Example3", + "mode_name": "1w_1t", + "worker_count": "1", + "well_count": "1", + "compile_seconds": "0.5819623470306396", + "prepare_seconds": "0.0", + "execute_seconds": "0.38030195236206055", + "total_seconds": "1.3088595541194081", + "wells_per_second": "2.629489524807818", + "successful_wells": "1", + "native_single_sample_execution_seconds": "", + "projected_native_execution_seconds": "", + "projected_execution_speedup": "", + "peak_memory_mb": "1043.19140625", + "status": "success", + "memory_limit_mb": "", + "error_message": "", + "execution_route": "ordinary-zmq-outcomes-v1", + "server_lifecycle": "reused-per-sweep", + "run_input_sha256": "3c135c9fa72e1a8ec100dca796e96c7f6721cccfab82316b3836236b6b4e75b0" + } + ], + "receipt_sha256": "8a7f0ecb3274b47312e8ee1431b4bd75f9aaba713fd76d3e9ec28ab038aa93da", + "source_freeze_sha256": "d6608b629bb37ecb89d30797258d674d816857671e77fcf580bec3d62910a7a2" + }, + { + "label": "A", + "public_rows": [ + { + "case_name": "ExampleIlluminationCorrection_Example3", + "mode_name": "1w_1t", + "worker_count": "1", + "well_count": "1", + "compile_seconds": "0.9443988800048828", + "prepare_seconds": "0.0", + "execute_seconds": "0.3780531883239746", + "total_seconds": "1.6701623457483947", + "wells_per_second": "2.6451304495891326", + "successful_wells": "1", + "native_single_sample_execution_seconds": "", + "projected_native_execution_seconds": "", + "projected_execution_speedup": "", + "peak_memory_mb": "1012.59375", + "status": "success", + "memory_limit_mb": "", + "error_message": "", + "execution_route": "ordinary-zmq-outcomes-v1", + "server_lifecycle": "reused-per-sweep", + "run_input_sha256": "a37695e774a71b04c3e2a390df76245c973458380fca25a9aac513dbf5e8be8e" + } + ], + "receipt_sha256": "4a804982debefcd6cd075ac16520e85036281b3eddd78cabaf86f41f2841b4c6", + "source_freeze_sha256": "6b40a27bf359bb67febc0af967221829a7719cac0d965704609c0d36991f608e" + } + ], + "tests": { + "python_introspect": 136, + "objectstate_lazy_factory": 25, + "openhcs_readiness": 119 + }, + "upstream_prs": [ + "https://github.com/OpenHCSDev/python-introspect/pull/6", + "https://github.com/OpenHCSDev/ObjectState/pull/9" + ], + "science_runs": [ + { + "label": "A", + "directory": "/home/ts/.local/state/openhcs-maintenance/20261003/schema-source-readiness-ordinary-abba-v1/0-A", + "receipt_sha256": "6805ee89e2872aea6199e959e53b956ef144e2ff82516fbf6ac68042450d6fd2", + "scientific_npy_bytes": { + "results/reference_image__PolynomialCorrected.npy": "8875da63a072c8f2de4f5cb707d779a064b663bf69aa0f304fe6fa74d4ff57a6", + "results/reference_image__ConvexHullCorrWorm.npy": "9ba1259e4ca007c06f14be6946e32a86307ec2dfb9952b73fa2cc253ccae8b3a" + }, + "physical_selected_inputs": { + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/ADSAStaphInfection2_A01_w2247376DD-6ADD-442D-AE47-F54A05F3EA94.tif": "5a57b7557bb0da5e241b48851b82d936c7ec36ede7aaca5e77b28ac4bfebf502" + }, + "image_differences": [], + "table_differences": [], + "full_physical_inventory": "PASS" + }, + { + "label": "B", + "directory": "/home/ts/.local/state/openhcs-maintenance/20261003/schema-source-readiness-ordinary-abba-v1/1-B", + "receipt_sha256": "c8f76ce4b6acaa60f5bbfe13c5a5ca924e299d5c8834e249f757dd53adc434c7", + "scientific_npy_bytes": { + "results/reference_image__ConvexHullCorrWorm.npy": "9ba1259e4ca007c06f14be6946e32a86307ec2dfb9952b73fa2cc253ccae8b3a", + "results/reference_image__PolynomialCorrected.npy": "8875da63a072c8f2de4f5cb707d779a064b663bf69aa0f304fe6fa74d4ff57a6" + }, + "physical_selected_inputs": { + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/ADSAStaphInfection2_A01_w2247376DD-6ADD-442D-AE47-F54A05F3EA94.tif": "5a57b7557bb0da5e241b48851b82d936c7ec36ede7aaca5e77b28ac4bfebf502" + }, + "image_differences": [], + "table_differences": [], + "full_physical_inventory": "PASS" + }, + { + "label": "B", + "directory": "/home/ts/.local/state/openhcs-maintenance/20261003/schema-source-readiness-ordinary-abba-v1/2-B", + "receipt_sha256": "8a7f0ecb3274b47312e8ee1431b4bd75f9aaba713fd76d3e9ec28ab038aa93da", + "scientific_npy_bytes": { + "results/reference_image__PolynomialCorrected.npy": "8875da63a072c8f2de4f5cb707d779a064b663bf69aa0f304fe6fa74d4ff57a6", + "results/reference_image__ConvexHullCorrWorm.npy": "9ba1259e4ca007c06f14be6946e32a86307ec2dfb9952b73fa2cc253ccae8b3a" + }, + "physical_selected_inputs": { + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/ADSAStaphInfection2_A01_w2247376DD-6ADD-442D-AE47-F54A05F3EA94.tif": "5a57b7557bb0da5e241b48851b82d936c7ec36ede7aaca5e77b28ac4bfebf502" + }, + "image_differences": [], + "table_differences": [], + "full_physical_inventory": "PASS" + }, + { + "label": "A", + "directory": "/home/ts/.local/state/openhcs-maintenance/20261003/schema-source-readiness-ordinary-abba-v1/3-A", + "receipt_sha256": "4a804982debefcd6cd075ac16520e85036281b3eddd78cabaf86f41f2841b4c6", + "scientific_npy_bytes": { + "results/reference_image__ConvexHullCorrWorm.npy": "9ba1259e4ca007c06f14be6946e32a86307ec2dfb9952b73fa2cc253ccae8b3a", + "results/reference_image__PolynomialCorrected.npy": "8875da63a072c8f2de4f5cb707d779a064b663bf69aa0f304fe6fa74d4ff57a6" + }, + "physical_selected_inputs": { + "/home/ts/.cache/openhcs/cellprofiler_examples/ExampleIlluminationCorrection/images/ADSAStaphInfection2_A01_w2247376DD-6ADD-442D-AE47-F54A05F3EA94.tif": "5a57b7557bb0da5e241b48851b82d936c7ec36ede7aaca5e77b28ac4bfebf502" + }, + "image_differences": [], + "table_differences": [], + "full_physical_inventory": "PASS" + } + ], + "scope": "Four ordinary uninstrumented public Illumination runs ABBA, CPU5 1w_1t INLINE, default OUTCOMES and memory observer. Server READY preparation/startup and shutdown excluded. A is exact prior source bytes for three files; dependency Git HEADs identify containing checkout, file hashes identify actual baseline contents. Only source lookup, existing registered type projection and registry readiness differ. No scientific processing or numerical changes. No new native CP execution.", + "limits": [ + "Two observations per variant; no execution speedup is claimed.", + "Authored workload exports two images and no tables.", + "Native comparison is retained matched CP4.2.8.1 evidence, not a fresh native run.", + "Ordinary pipeline total excludes mandatory server startup and shutdown." + ], + "artifact_hashes": { + "freeze.json": "2c5d9272f1693e1da821ad45c6db3190cd046f12f446142f9c263611f8a81da8", + "observations.json": "aa72dc885608831f3bbc21efc62f2739d86ec74d64f5ae56d0ee27cd129792fd", + "science.json": "918c36612ec20738ad2d2760da85c9e9be07e81d4cd4bf0f60ec91dfcf906488", + "controller.py": "6fcf1cb1008ac32ee3ceaff8fd61f6db1fdba87544e1ffee1e4b3d484ce30b90", + "validate_science.py": "86fd34f0ca552309a453c5c169a97b949304aa37fb642a66972f4d12f9940684" + }, + "authoritative_artifacts": "/home/ts/.local/state/openhcs-maintenance/20261003/schema-source-readiness-ordinary-abba-v1", + "remaining_work": "No execution speedup claimed. Runtime plumbing, other workloads, fresh native/scaling sweeps and figures remain outstanding." +} diff --git a/benchmark/results/perf_wide_intensity_distribution_20260929/replay_saved_batch.py b/benchmark/results/perf_wide_intensity_distribution_20260929/replay_saved_batch.py index d131f3e5b3..831096cc9c 100644 --- a/benchmark/results/perf_wide_intensity_distribution_20260929/replay_saved_batch.py +++ b/benchmark/results/perf_wide_intensity_distribution_20260929/replay_saved_batch.py @@ -39,7 +39,7 @@ ) accumulator.add( table.rows, - export.cellprofiler_projected_measurement_feature_name, + export.CELLPROFILER_MEASUREMENT_DIALECT.projected_feature_name, default_subject=export._measurement_subject_name(table), default_scope=table.subject.scope, source_image_name=table.source_image_name, diff --git a/docs/plans/mcp_agent_experience_implementation_dry_run_20260629.md b/docs/plans/mcp_agent_experience_implementation_dry_run_20260629.md index f532b097cd..12b777b786 100644 --- a/docs/plans/mcp_agent_experience_implementation_dry_run_20260629.md +++ b/docs/plans/mcp_agent_experience_implementation_dry_run_20260629.md @@ -33,12 +33,11 @@ show("VirtualWorkspaceSourceProjection methods", tuple(name for name in ("pipeli from openhcs.core.compiled_step_plan import CompiledStepPlan from openhcs.core.source_bindings import CompiledSourceUniversePlan from openhcs.core.source_load_plan import SourceLoadPlan -from openhcs.core.source_binding_selection import SourceUniverseRequest, SourceUniverseStrategy +from openhcs.core.source_binding_selection import SourceUniverseRequest show("CompiledStepPlan source/artifact fields", tuple(f.name for f in fields(CompiledStepPlan) if f.name.startswith("source_") or f.name.startswith("artifact_"))) show("CompiledSourceUniversePlan fields", tuple(f.name for f in fields(CompiledSourceUniversePlan))) show("SourceLoadPlan fields", tuple(f.name for f in fields(SourceLoadPlan))) show("SourceUniverseRequest types", tuple(t.__name__ for t in SourceUniverseRequest.registered_request_types())) -show("SourceUniverseStrategy types", tuple(t.__name__ for t in SourceUniverseStrategy.registered_strategy_types())) from openhcs.core.artifacts import ArtifactSidecarRole, ArtifactSpec, ArtifactInputPlan, ArtifactOutputPlan show("ArtifactSidecarRole values", tuple(role.value for role in ArtifactSidecarRole)) @@ -105,10 +104,11 @@ Artifact/source coverage: richer source-load semantics until the compiler owns them. - `SourceUniverseRequest.registered_request_types()` returns `StepInputSourceUniverseRequest` and `PipelineStartSourceUniverseRequest`. -- `SourceUniverseStrategy.registered_strategy_types()` returns six concrete +- The historical independent source-universe strategy registry returned six concrete strategies covering current pattern, virtual workspace, physical axis, axis-scoped pipeline start, virtual workspace pipeline start, and physical - pipeline start. + pipeline start. These cases now belong directly to the registered request + owners through `source_universe()`. Runtime sidecars: diff --git a/docs/plans/mcp_artifact_source_coverage_plan_20260629.md b/docs/plans/mcp_artifact_source_coverage_plan_20260629.md index b70092767d..da6e9b7882 100644 --- a/docs/plans/mcp_artifact_source_coverage_plan_20260629.md +++ b/docs/plans/mcp_artifact_source_coverage_plan_20260629.md @@ -32,7 +32,6 @@ file counters in MCP to paper over ambiguity. - `_source_workspace_summary` - `openhcs/core/source_binding_selection.py` - `SourceUniverseRequest` - - `SourceUniverseStrategy` - step-input and pipeline-start universe strategies - `openhcs/core/source_workspace_projection.py` - `VirtualWorkspaceSourceProjection` @@ -89,8 +88,8 @@ The 2026-06-29 dry run showed `SourceLoadPlan` currently exposes only them to that plan. If implementation needs to enumerate source-universe strategy behavior, iterate -the nominal `SourceUniverseRequest`/`SourceUniverseStrategy` registration and -matching machinery. Do not mirror strategy names or physical/virtual/pipeline +the nominal `SourceUniverseRequest` registration and each request's +`source_universe()` operation. Do not mirror strategy names or physical/virtual/pipeline start categories in MCP. If implementation needs a generic compiled-context tree, iterate dataclass @@ -102,7 +101,8 @@ type. Do not use a string allowlist of important `CompiledStepPlan` fields. See `docs/plans/mcp_agent_experience_implementation_dry_run_20260629.md`. The dry run confirmed the compiled source/artifact fields on `CompiledStepPlan`, the three current `CompiledSourceUniversePlan` flags, the two -`SourceUniverseRequest` types, and six concrete `SourceUniverseStrategy` types. +`SourceUniverseRequest` types. Those request owners now resolve their universes +directly; the separate strategy family has been removed. It also confirmed `SourceLoadPlan` is currently only `zarr_config`. ## Implementation Steps @@ -146,7 +146,7 @@ Audit questions: - Does a generic compiled-context projection traverse dataclasses/types instead of maintaining a field allowlist? - Are source-universe facts projected from `CompiledSourceUniversePlan` and - `SourceUniverseRequest`/`SourceUniverseStrategy`, not recomputed in MCP? + `SourceUniverseRequest.source_universe()`, not recomputed in MCP? - Can an empty count be traced to the authority that was empty? Hard failures: diff --git a/docs/plans/runtime_plumbing_frontier_20261003.rst b/docs/plans/runtime_plumbing_frontier_20261003.rst new file mode 100644 index 0000000000..f859ea4ed1 --- /dev/null +++ b/docs/plans/runtime_plumbing_frontier_20261003.rst @@ -0,0 +1,534 @@ +Runtime plumbing frontier: current measurements and rejected routes +================================================================= + +This checkpoint supports PR #394 and issue #496. It records measurements and +remaining investigation, not a new production optimization. Main #498 was +normally merged and pushed at ``093c2f42d1235b5e218800f57937b6a52b4f5255``. +That transition changed documentation only; production sources remain identical +to the earlier native-qualified integrated source. + +Timing boundaries +----------------- + +Every run uses the original public benchmark driver, one worker and one CPU +thread, default OUTCOMES completion and the ordinary memory observer. Mandatory +registry/library/kernel preparation completes before server READY. Server +startup, preparation and shutdown are outside pipeline clocks. Execution excludes +compilation; total includes compilation and completion. Single-worker execution +is inline. The retained native invocation clock excludes import/JVM/pipeline +loading and includes prepare, modules, post-run and closure. + +Diagnostic nested exclusive clocks partition their original execution root. +They include observer overhead and required work. A callable boundary includes +its filtering, conversion and metadata behavior; it is not a pure-kernel clock. +Inclusive descendants cannot be added to their ancestor. Correct output bytes +do not establish performance improvement, input immutability or callback purity. + +Fresh ordinary Speckles +----------------------- + +Two independent uninstrumented invocations on the current source produced +execution times of 1.199828148s and 1.159908533s. Their means are: + +* Execution: 1.179868340s. +* Compilation: 1.067295671s. +* Total: 2.514483608s. + +Both complete five-file inventories, including all three scientific CSVs, +are byte identical to the qualified baseline. Physical images, pipeline, +configuration, server environment, dependencies and native evidence are joined +to the original receipts. Compared descriptively with the retained native +invocation mean of 1.915068373s, execution is 1.6231x faster and total is 0.7616x +as fast. The execution gap to 2x is 0.222334154s. Native was not rerun for this +checkpoint; two observations do not establish statistical significance or a +causal source improvement. + +The earlier and current pipelines both invoke IdentifyPrimaryObjects twice. +Their relevant source bodies and settings are identical. The prior slower +timing therefore has no established code-change explanation. The current +ordinary progress spans put about 0.820924s in those two steps, approximately +70 percent of execution. + +Actual declumping inputs and boolean output oracles were separately captured +under unchanged storage limits. The original two stage bodies took 0.070122s +and 0.001791s, totaling 0.071913s. Capture overhead was excluded from these +stage clocks. Even eliminating that stage cannot bridge the measured gap, so +the seed optimization route is stopped before a candidate or replay is built. +The original diagnostic wrapper import failure is retained separately; the +successful harness passed controls for all five actual installed hooks. + +Current 3D plumbing +------------------- + +An unchanged 24-boundary diagnostic on the current source completed with both +profilers disabled. Its execution root is 8.958889063s, partitioned into +4.163085915s at 211 callable boundaries and 4.795803148s outside them. The latter +is approximately 53.5 percent of execution. Selected disjoint exclusive terms: + +* Stack loading: 0.965303496s across 32 calls. +* Output saving: 0.608366542s across 28 calls. +* Worker-lane residual: 0.619469857s. +* Image-request construction: 0.390939402s across 30 calls. +* Module-output recording: 0.413856133s across 26 calls. +* Metadata publication: 0.493661132s across five calls. +* Artifact metadata reconciliation: 0.288939269s. +* Validation and unstacking: 0.189130950s across 28 calls. + +There are zero feature-query calls. The complete six-CSV/120-TIFF scientific +bytes match the qualified ordinary baseline, all 128 inventory paths match, +and three physical input volumes, the pipeline and retained native logical +volume/plane witnesses are verified. Only the managed metadata JSON differs, +with both hashes explicitly reported. This is a diagnostic breakdown, not an +accepted ordinary runtime gain. + +The prior ordinary 3D execution of 8.536s versus native 14.396s leaves roughly +1.34s to reach 2x execution. Publication and reconciliation together have only +a 0.7826s diagnostic ceiling before mandatory work. A publication-only change +is therefore insufficient. The investigation must span shared producer/source +derivation across loading, image requests, recording, saving and publication. +The existing nominal authorities are the intended owners; no extra mirror, +global cache, per-function shortcut or delayed per-step visibility is admitted. + +Measurement frontier and architectural constraints +-------------------------------------------------- + +The separate 42-boundary Beginner diagnostic measures a disjoint table +assembly/query/pivot envelope of 1.462782s. Native CSV rendering is another +0.163899s. All nine scientific output files and complete physical inventory +match the native-qualified baseline. Its occurrence graph reaches the original +4,096-event limit and remains RED independently of scientific correctness. +The complete Speckles graph demonstrates repeated access to one table and +object-label vector, but that entire measurement lane is only about 0.038s. +Neither query-only nor the 16-call intensity projection route can close the +dominant gaps, and the measurement fold is not a 3D optimization: that workload +does not perform these queries. + +Existing serialization views have distinct semantics. Raw projection source +metadata and enriched SOURCE_METADATA cannot share one output dictionary. +The transaction overlays raw path records before decoding surviving entries; +decoding overwritten malformed entries earlier would change first errors. +Serializer callbacks, independently mutable outputs, current per-step +publication visibility and concurrent-axis final pruning remain obligations. +A frozen projection declaration does not establish deep immutability of its +image metadata. Ownership proposals remain provisional until those laws and +representative replay show a sufficient end-to-end payoff. + +Retained evidence +----------------- + +The following local receipts contain exact source/controller/environment/input +pins, original commands, file inventories and hashes: + +* ``/var/tmp/openhcs-current-speckles-ordinary-pair-v1-20261003/observations.json``: + SHA-256 ``d08f35061285e8a4d543377c1de7993623654844eddcaea806d269672a0bf4a1``. +* ``/var/tmp/openhcs-speckles-seed-capture-v4-scientific-byte-gate-20261003.json``: + SHA-256 ``4da188db100b9526f18a6a02ce98872dad6e7ee5dca60c1b85e7052e1287e301``. +* ``/var/tmp/openhcs-current-3d-runtime-ledger-v1-scientific-byte-gate-20261003.json``: + SHA-256 ``36a4f2cdcc14baaa38f027a6dc759facd1229cc1f5960ddb063cbe689efda0cf``. +* ``/var/tmp/openhcs-measurement-occurrence-ledger-v1-scientific-byte-gate-v2-20261003.json``: + SHA-256 ``4352fa24e8984e0f4c67587ae674ff28085ed134531dea28fe7d5b8517671f99``. + +PR #394 remains draft. Whole-branch original R0 and the #479 per-file R1 +failures remain explicit and unwaived; installed consumer acceptance, +full-catalog/scaling measurements and fresh figures remain unfinished. +The performance goal remains active. + +Deeper current 3D attribution and producer ownership +--------------------------------------------------- + +Two further diagnostics use clean source ``396379b06769a3f5afe92413b7d9d6a21dd3f66f``. +Its production, test and benchmark driver bytes are unchanged from the preceding +``093c2f42`` source. Both preserve mandatory READY warmup, inline 1w_1t execution, +OUTCOMES export, the normal memory observer and both disabled profilers. Neither +is a new ordinary performance comparison. + +The 36-hook run separates metadata normalization and provenance operations from +their actual nested callers. It observes 29,701 normalization calls outside raw +callable boundaries, totaling 0.317682s exclusive. Ordinary normalization creates +a fresh scalar identity and reuses the cached plane collection; it does not copy +the complete 60-plane lineage. Whole-plane merges and derived naming do rebuild +plane/contributor snapshots. Those operations retain live-mutation and fresh +snapshot obligations. Their observed costs do not admit a standalone fix large +enough to close the 1.338s qualified execution gap. + +Several large isolated stalls prompted a separate 25-hook run with passive GC +callbacks. It does not disable GC, freeze objects, change thresholds, force a +collection or replace existing callbacks. Startup has no active pipeline root. +Its execution root is 8.462928s: 3.803686s within the 211 declared callable +boundaries and 4.659242s outside them. The public diagnostic clocks are execution +8.490154s, compilation 1.824986s and total 11.210223s. GC consumes 0.285505s, +including one 0.196025s generation-two collection during saving. Collection +durations overlap the owner clocks; adding them to plumbing would double count. +GC alone cannot explain or close the remaining gap, so a GC-policy optimization +is rejected. Different diagnostic clocks on identical production bytes are not +evidence of a production gain or regression. + +Both diagnostics match all six CSVs and 120 TIFFs byte for byte against the same +native-qualified baseline, with complete 128-file inventories and physical +input joins. No fresh native repetition is claimed. The 36-hook scientific +output is retained in a lossless, individually hash-verified archive at +``/var/tmp/openhcs-current-3d-owner-ledger-v2-20261003/scientific-output.tar.gz``; +its custody receipt records every original path, mode, size and hash. Later +readers must use or restore that archive rather than assume those extracted +files remain present. The 25-hook output uses the same verified custody protocol +at ``/var/tmp/openhcs-current-3d-gc-ledger-v1-20261003/scientific-output.tar.gz``. +Previous baselines and frozen failures are unchanged. + +Source and consumer audits reject two tempting shortcuts. Artifact-only groups +already return ``NoMainFlowOutput`` and skip unstacking and saving. Canonical CP +publication already reuses the stored runtime artifact payload. Downstream CP +inputs deliberately distinguish stored secondary artifacts from relation-owned +current main flow. The latter has an independent mutable whole buffer and final +filename/source-component context. Repeated cache hits share that buffer. A +direct stored-artifact substitution would change these relationships and, in a +saved determining case, 62 metadata facts. The final named output bundle can +also retain earlier sibling outputs, so the last canonical return roster cannot +stand in for the complete main-flow cohort. + +The remaining structural route belongs to existing ``PatternGroupOutputData``, +``AlignedImageStack``, manifest and runtime-input owners: derive physical plane +views and final context from the exact correlated producer occurrence, preserving +the independent main-flow buffer, rather than repeatedly project and recompose +the whole cohort. The seven marked load/request/record/unstack/save/publication/ +reconciliation spans total 3.432617s in the GC diagnostic. This is an upper +envelope containing mandatory work, not a claimed removable cost. Before a +candidate, representative replay must retain the stored occurrence, actual +merged bundle, projected leaves, final records and cache, filename/path prestates, +and next consumer edge in one graph. No fake processing context, new cache, +canonical-roster shortcut or zero-copy assumption is admitted. + +Additional retained receipts: + +* ``/var/tmp/openhcs-current-3d-owner-ledger-v2-scientific-byte-gate-20261003.json``: + SHA-256 ``df4f6548f4459c6a55ea5dc182ac52a5472eaacace572ae60740a9409377ca89``. +* ``/var/tmp/openhcs-current-3d-gc-ledger-v1-scientific-byte-gate-20261003.json``: + SHA-256 ``d0b8d6af1b8a1777b03624cf6435d67b04746e9477a5cefbc7a962feaa2d667d``. +* ``/var/tmp/openhcs-current3d-canonical-mainflow-CP-owner-review-v1-20261003.json``: + SHA-256 ``9c264eaa2a735388f5694a305dcbf8ff61258ed959adb4819ffacfcb39235bbf``. +* ``/var/tmp/openhcs-current3d-canonical-mainflow-macro-owner-audit-v4-20261003.json``: + SHA-256 ``c589df6f3c28d6d3a3dc668adc696089bc4aeb68aa2d762a0128592e8d67b891``. + +This checkpoint changes documentation only. No optimization, merge, original +R0/R1 waiver, installed acceptance or full-catalog/scaling completion is claimed. + +Current producer/consumer evidence and compilation frontier +---------------------------------------------------------- + +Fresh diagnostics at ``bb9c49c2ad70f1cee49fa0cde47592681edb2be3`` preserve +main ``87d9a99a9``, shared dependency/native/input pins, normal READY warmup, +inline 1w_1t execution, OUTCOMES completion and the normal memory observer. +Their observation clocks are not ordinary performance improvements. + +The bounded V7 capture retains four actual step-13 ImageMath producer and +step-14 Resize load states, totaling 856,419,294 bytes under the unchanged +384 MiB per-item and 1 GiB total limits. Its full six-CSV/120-TIFF parity, +complete scientific inventory, all 180 ordered physical source references, +and three native input-volume witnesses pass. Original step-13 replay matches +all 60 records, named/VFS/cache outputs and the complete 123-array identity, +sharing, dtype, stride and writeability graph. + +Original step-14 replay is RED before cache lookup: the actual producer +manifest lives in module ``_STEP_OUTPUT_MANIFESTS``, a WeakKeyDictionary outside +ProcessingContext transport. Reconstructing it from the separate producer +oracle would fabricate a receiver state and is rejected. Independently, +RuntimeSourceBindingContextCache deliberately drops four derived caches through +its reducer. The actual after-load graph proves the result is the retained +whole image for its exact 60-path cache key, but cold restored clocks cannot +represent warm pipeline work. A future replay must carry actual manifest/cache +owners in the same graph and rekey identity indexes only from real owner +references, or obtain live production confirmation. Original failed artifacts +remain preserved; schema completeness is not complete transaction state. + +A six-group ephemeral layout experiment validates the proposed existing-class +projection ancestor layout, constructor signatures, default factories, frozen +assignment, cooperative projection order, errors and fresh public provenance. +This proves layout feasibility only. Lazy read algorithms, custom subclass +behavior, combined transaction acceptance and sufficient elapsed savings +remain unproved. No new wrapper or cache authority is implemented. + +Illumination remains the weakest known total comparison. Its current V3 +diagnostic records compilation 1.125192s, execution job 0.377852s and total +1.844212s, with both authored NPY files, full inventory and actual physical +TIFF/pipeline/native witnesses matching the retained qualified reference. +The compilation partition places 0.302983s exclusive in dataclass analysis +and 0.285258s in nested documentation extraction: 0.588241s together. Four +client pipeline renders plus three config renders take 0.235231s. The joint +0.823472s envelope contains required work; it is not a saving estimate. +Ten effective-config getters include the schema/state subtree and cannot be +added to it. Completion alone is too small to close the remaining gap. + +The separate V4 diagnostic also passes full science and distinguishes actual +cache topology: compilation has 40 successful first-use misses and 338 hits +across 44 class identities; execution has 94 hits. There are no uncached empty +results. This rejects repeated failing analysis or fresh proxy churn as the +mechanism. Exact runtime class names were not retained because the diagnostic +read a type-owned attribute from the class dictionary; that metadata omission +is explicit. A separate declaration inspection finds 22 registered public/proxy +pairs and 95 differing fields, including Optional annotations and None defaults. +Canonical-class ParameterInfo substitution would change real reset and +reconstruction consumers, so it is rejected. The remaining candidate must +separate reusable declaration work from correctly timed value/default-factory +evaluation using the existing schema and preparation owners. + +Local source-qualified receipts: + +* ``/home/ts/.local/state/openhcs-maintenance/20261003/current-cohort-capture-v7-science-verification-v2.json`` + (SHA-256 ``99f2f830861eb1ecd1492c50ff6bbb2a66172674211e0a925f9f6a85359a1be0``). +* ``/home/ts/.local/state/openhcs-maintenance/20261003/current-cohort-v7-original-replay-v3.json``. +* ``/home/ts/.local/state/openhcs-maintenance/20261003/current-cohort-v7-load-owned-role-review.json`` + (SHA-256 ``bd08002bbb535911ba189b1b97bf8cbceb03c938b89c5ec8d0c061e4743735a7``). +* ``/home/ts/.local/state/openhcs-maintenance/20261003/projection_ancestor_feasibility_bb9c_v3.json`` + (SHA-256 ``b5ff353e33c70d4066de5315c0bef2046e1e8680056125404a7c393eb2e531ae``). +* ``/home/ts/.local/state/openhcs-maintenance/20261003/illumination-compiler-ledger-v3-science.json`` + (SHA-256 ``e042e25aa0fd9e087459c77613150f0db6447e91d0fc943acf2ea638312cc850``). +* ``/home/ts/.local/state/openhcs-maintenance/20261003/illumination-schema-cache-topology-v4-20261003.json`` + (SHA-256 ``134244ea39004ccfc86d20fa14d4fdc49e78aa72f4a92349092c6f420c1b89e3``). + +The preceding V3/V4 diagnostics are attribution only. They do not establish a +production saving, new native repetition, original R0/R1 waiver or +full-catalog/scaling completion. + +Registered configuration source readiness +----------------------------------------- + +The decisive source-only prototype found repeated Python 3.10--3.12 class +source lookup walking the complete config module. The existing +``SignatureAnalyzer`` now derives bounded module AST and qualified-class source +views from current immutable source contents. Python 3.13 and newer retain the +native locator. Live annotations, factories, mutable field/inherited docs, +loader invalidation and the original completed value-analysis cache remain at +their existing observation points. Earlier class-identity snapshots failed +real mutation controls and were rejected. + +``LazyDataclassFactory.registered_type_pairs()`` projects the existing registry +without a second roster or constructing values. ``RegistryService`` prepares +both public and proxy declarations after callable hooks and before READY, +including declarations registered after the catalog was cached. Default +factories are not evaluated during source preparation. + +At OpenHCS ``7258826d7198f2bb7010763276dba02320d62142``, four ordinary public +Illumination runs in ABBA order measured: + +.. list-table:: Ordinary 1w_1t mean seconds; two observations per variant + :header-rows: 1 + + * - Phase + - Prior source + - Prepared source + * - Compilation + - 0.962152 + - 0.587605 + * - Execution job + - 0.382655 + - 0.400589 + * - Total pipeline + - 1.693765 + - 1.363694 + +Compilation saves 0.374547s (38.9%); total saves 0.330070s (19.5%). No execution +gain is claimed. All four runs use CPU5, INLINE one-worker execution, normal +OUTCOMES and the default memory observer, without hooks or profilers. Mandatory +server startup/preparation and shutdown are outside total pipeline timing. +Exactly three owned source files vary; immutable before/after hashes identify +actual baseline contents separately from containing dependency Git HEADs. +All source, dependencies, native binaries, environment and physical inputs were +checked before/after each run; the clean candidate was restored afterward. + +All four complete authored output inventories retain both NPY artifacts exactly +and match the qualified physical TIFF/pipeline/native evidence. The workload +authors no tables. Native CellProfiler was not rerun in this experiment; broad +scaling or new native speedup claims are not made. Science receipt SHA-256: +``918c36612ec20738ad2d2760da85c9e9be07e81d4cd4bf0f60ec91dfcf906488``. + +The 136 upstream, 25 existing lazy-factory and 119 OpenHCS readiness/catalog/ +startup tests pass. python-introspect PR #6 and ObjectState PR #9 are merged and +formally close their issues #5 and #8. Their merge commits change no measured +source bytes. OpenHCS wiring is pushed in draft #394; a small main-only readiness +change can be isolated without merging the unresolved broad branch. +The reviewable measurement receipt and immutable recipe links/hashes are under +``benchmark/results/perf_schema_source_readiness_20261003``. Redundant tracked +local recipe copies were removed; the originals, source variants and immutable +outputs/freeze remain under the corresponding maintenance ABBA directory. +Those recipes depend on local paths and are not turnkey portable commands. +Runtime plumbing, full-catalog/scaling measurements, fresh native repetitions +and figures remain outstanding. Original whole-branch R0/R1 failures remain +explicit and unwaived. + +Canonical provenance identity integration +------------------------------------------ + +Main readiness #514 is merged into this branch. The overlapping readiness +regression was removed from the callable ABI suite; the dedicated main test +remains authoritative. Callable canonical-signature preparation still precedes +registered declaration preparation and kernel readiness. + +The existing ``SourceMetadataFields.provenance_identity_items`` now derives its +representation from ``identity_items``. Equal nested field mappings have equal +provenance fingerprints independent of insertion order. Raw wire order, real +value differences, ordered planes and lifetime-selected views remain intact. +Existing birth fingerprints are preserved by pickle/cloudpickle; they are not +recomputed from subsequently mutated public fields. Historical nested-mapping +fingerprints can therefore differ from newly canonical fingerprints. A fresh +same-source capture is required before candidate fingerprint replay. + +The integrated metadata/transport/readiness controls pass 86 tests in 2.40s. +The separate exact PR #494 source qualification passes its unchanged 31 writer +controls plus seven identity controls. Those writer controls cannot collect on +this branch because its independent ``PointROIOutput`` producer is absent; no +installed, native or live viewer acceptance is inferred. The integrated receipt +is ``~/.local/state/openhcs-maintenance/20261003/pr494-identity-owner-scratch/ +integrated-owned-qualification-v1.json``. + +V8's original producer and downstream loader replay now pass complete value, +metadata, manifest and array-alias gates, and the full six-CSV/120-TIFF science +gate passes. Serialization still drops nested metadata views and source-context +derived caches. These scoped clocks are not complete production-warm performance +evidence. The saved downstream cache hit constructs no new provenance objects; +it does not establish the payoff of a broader loading/recording/publication fix. +The next capture must retain actual nested caches in the same graph, under the +existing admission bounds, without rewarming or inventing state. + +Current graph-owned replay qualification (#510) +------------------------------------------------ + +The fresh V10 capture at ``4c636a281de4da7341f4f9f6bb8f718c75644a1d`` completes +that bounded qualification. Its four independent producer-13/loader-14 graphs +total 1,027,681,056 bytes, below the unchanged 1 GiB combined limit; each remains +below 384 MiB and 150,000 nodes. Original processing succeeds, with no capture +errors. The complete six-CSV/120-TIFF inventory and bytes, 180 ordered source +references and three physical input-volume hashes pass the original science +gate. Native agreement uses the retained qualified two-repeat witness; native +CellProfiler was not rerun by this diagnostic. + +Before serialization, the adapters retain actual manifest membership, source +cache dictionaries, process-ID key owners and physically stored nested fields +in each same graph. Restoration validates anchors and declarations before +reconnecting exact references; process-ID keys are rekeyed from retained owners. +Stored field absence, ordered metadata views, birth fingerprints and array +aliases remain intact. Fresh interpreters preserve the original hash seed zero. + +The smaller save oracle must also retain its actual memory backend. Its existing +parser must point to the receiver's exact FileManager; restoration reconnects +that backend through ``register_backend`` before restoring nested fields. This +closes V9's nine detached-owner failures without reconstructing missing state, +adding a receiver, unioning graphs, excluding owners or increasing bounds. + +Original producer replay restores all 1,112 after-oracle owners and matches all +60 records, output data, named values, VFS planes and whole-stack cache, including +123 complete array roles and their object/shared-memory relationships. Original +loader replay restores all 1,116 after-oracle owners and matches the complete +loaded result, runtime store, observations and stack cache, including 104 array +roles. Immediately after the original calls, before equality or property queries, +all 1,050 producer and 1,115 loader retained owners have unchanged stored fields +and cached entries; newly reachable owners are reported separately. + +The determining receipt is +``benchmark/results/perf_current_cohort_v10_20261003/qualification.json``; +its SHA-256 is +``17bb47f609d95ca6044f92810dbbf1c5f31e066ef330955aab264a5d8d7e6273``. +It identifies every immutable helper, snapshot, sidecar, log and consumer gate +under ``~/.local/state/openhcs-maintenance/20261003/current-cohort-capture-v10``. +The authoritative outer preparation/launch directory is the canonical OpenHCS +checkout; the public child still uses the owned temporary directory and CPU5. +The failed outer-environment preflight started no pipeline and remains retained. + +This completes the replay friction in #510. It qualifies only these actual +graph-owned warm occurrences, not process-global LRU state or a whole-pipeline +heap. Diagnostic durations are not ordinary performance gains. V7/V8/V9 failures +remain immutable, and the broad branch's architecture gates, fresh native runs, +full-catalog scaling and figures remain outstanding. + +Fresh current native comparison after main and dependency sync +------------------------------------------------------------- + +Clean source ``60b2ac9b4`` includes main ``f7de9efad`` and actual merged +ObjectState/python-introspect source heads at versions 1.1.9/0.1.15. The +shared environment qualification passes 35 primary controls and the supplementary +40/13 historical-selector controls; all eight imported source roots are recorded. +Protected canonical-first imports still select older canonical vendored sources. +This qualification applies to the owned benchmark checkout, not canonical startup. + +Two fresh ordinary sweeps and two fresh native measured repetitions per case pass +all eight full scientific comparisons. Startup/READY warmup/shutdown remain +excluded; native invocation includes preparation/modules/post-run/closure. Both +ordinary observations are retained with default OUTCOMES/RSS and inline 1w_1t: + +* 3D: compile mean 1.212512s; execute 9.127215s; total 11.153507s; + native 14.422177s. Execution speedup 1.58013x; total 1.29306x. +* Speckles: compile mean 0.663492s; execute 1.231350s; total 2.246087s; + native 1.954230s. Execution speedup 1.58706x; total 0.87006x. + +The remaining 2x execution gaps are now 1.916127s and 0.254235s; earlier +1.338s/0.222s targets refer only to their historical source-qualified samples. +These two observations are descriptive; source/environment synchronization and +run-to-run spread do not establish a causal improvement or regression. No new +callable/plumbing attribution is inferred from these uninstrumented clocks. + +All selected source occurrences and physical hashes match: 180 refs/one 3D +volumetric image set and two refs/one Speckles image set. Full 3D six-CSV/120-TIFF +and Speckles three-CSV controls, exact 3D labels, existing float tolerances, +relationship correlations and complete physical inventories pass. Root verified +all 11 linked receipt artifacts and all 290 unique compared output paths. + +Current receipts, raw rows, fresh native reports and two-case figure previews are +in ``benchmark/results/perf_current_native_paired_20261003``. Shared environment +qualification is in ``benchmark/results/perf_dependency_source_readiness_20261003``. +The unchanged original R0/R1 failures, full30/scaling work and other workloads' +unresolved native image differences remain open. No whole-goal completion is +claimed. + +Current delivery and dominant transport investigation +--------------------------------------------------- + +The aggregate-to-layer producer fix is merged into main as PR #523, closing +#515 through its formal closing link. The final PR head ``1419c5bd`` has the +same production source, tests and build configuration as the tested +``cab5363c`` checkpoint: 447 selected controls pass, with no deselections. +The subsequent main merge changes documentation only. A first temporary +checkout run failed collection because it lacked native extensions; the +passing run reused the existing binaries after checking both C++ sources +were byte-identical. This is local integration evidence, not installed GUI +acceptance or a performance gain. The temporary checkout has been retired. +The performance branch is synced with main ``6afc9a325`` at ``c49754e4c``; +its production and test bytes are unchanged from ``21934dad3``. + +The native-annotation experiment is stopped. Four alternating pairs of the +original five-write/publication/reconciliation sequence save 23--97ms, with +58.4ms median paired savings. All 16 controls pass, including the complete +609,001-byte ordered wire sequence, 120 produced entries and 180 source +entries. These savings do not materially close the current 1.916s 3D execution +gap. Definition-time alias binding still differs from deferred annotations; +this test-only experiment is not a universal annotation migration proof. +No production annotations, schema cache or benchmark driver were changed. +The determining decision is retained at +``~/.local/state/openhcs-maintenance/20261003/native-annotations-three-owner-replay-v1/decision.json`` +(SHA-256 ``c1159f2fda79a88e751228ad8215e1e64e79ecc5371313b79263f12b17af0396``). + +Unconditional manifest filename-cache routing is also rejected. An actual +uncached SourceSchema parser accepts ``z_index=[]`` and emits ``z[]``; the +existing explicit cache instead raises ``TypeError`` before construction. +The current filename-value mappings and parser have no persistent nominal +eligibility law. No graph replay or source patch was made. The determining +receipt is +``~/.local/state/openhcs-maintenance/20261003/manifest-filename-cache-eligibility-stop-v1.json`` +(SHA-256 ``188b02df644b1c7e6a3db0f8b222a87783e1d2b26e99137c2b4bb0285727baba``). +This does not reject a store-owned path index governed by the existing +records-revision boundary; that distinct structural route is being audited. + +The principal destination under investigation is the existing whole-stack +transport and compiled step-output dependency. Saving currently projects +per-path payloads and records, then recomposes their metadata for the stack +cache. Loading derives path, workspace and source-binding information before +checking that cache. The existing cache, manifest and compiled binding owners +must account for this handoff without another ledger. Actual VFS access, +selectors, source-identity birth epochs, independently mutable outputs and +publication remain production consumers to preserve. + +The retained coarse 3D ledger assigns about 1.646s to load, save and unstack +combined. That is an investigation ceiling including mandatory work, not +removable time. Retained profile call counts identify 10,680 normalizations +in axis-removal and source-projection operations; profiled time is not scaled +into an ordinary saving. A saved warm loader occurrence takes only 9.8ms and +cannot establish whole-pipeline payoff. The next evidence must determine +actual step-level cache hits, cohort fanout and metadata births, followed by +a consumer-complete replay and ordinary end-to-end verification. diff --git a/docs/refactor/receipts/aggregate-publication-435-494-20261004/README.rst b/docs/refactor/receipts/aggregate-publication-435-494-20261004/README.rst new file mode 100644 index 0000000000..963acfad75 --- /dev/null +++ b/docs/refactor/receipts/aggregate-publication-435-494-20261004/README.rst @@ -0,0 +1,277 @@ +Four-plane aggregate publication receiving control (#435 / NEW494) +================================================================== + +This extends the original ``test_saved_roles_publish_once_per_persisted_occurrence`` +writer/materializer control. It uses four real 5 x 7 uint16 TIFF source planes, +Z0..3, CHANNEL1 grouping, variable Z_INDEX and original source spacing +2/.65/.65 micrometers. The existing output contextualizer, RuntimeValue admission, +FunctionOutputIdentity, image materializer, metadata writer and durable workspace +reader own the complete path. No intrinsic Volume domain is forced: the payload +retains its original runtime-plane provenance and two-dimensional spatial domain. +The existing ARTIFACT_NAME whole-file materialization law saves the 4 x 5 x 7 +aggregate at ``A01_s001_w1_z000_t001_fixture_image_494.tif``. + +Both included JSON files are byte-exact receipts written BEFORE the occurrence +join. ``pre_join_main_flow`` and ``pre_join_artifacts`` use the existing typed +SourceProjectionMetadataSerializer and include complete persisted metadata; +``produced_records`` uses the existing dataclass JSON serializer. Original host +paths remain unchanged. They identify separately retained physical inputs and +outputs; no pixel dataset or large evidence archive is copied into this packet. + +Determining RED and corrected owner law +-------------------------------------- + +On receiving base ``89666e33ea40de4e50a413a456b55926b9043ecf`` (including root +``6f6414eb1``), the corrected aggregate fixture saves the TIFF, then the strict +join raises ``Conflicting metadata for persisted image occurrence``. Both typed +addresses are Z0. The complete persisted image metadata differ in exactly one +field: the artifact's scalar source-component metadata gains ``z_index: "0"``; +the main-flow aggregate has no scalar Z. Both retain all four original Z planes. +This is an observed failure of the receiving fixture. The exact compared pair +from the historical failed #494 execution was never retained, so its differing +field and actual failure cause remain unproved. + +The generic source-context owner now prevents a scalar fallback from filling a +coordinate that varies across the payload's actual runtime source planes. Its +existing variation operation returns immediately for zero/one runtime plane; +non-projectable contributors retain their existing scalar fallback semantics. +The publication owner distinguishes proven aggregate source coordinates from +storage filename coordinates. Intrinsic whole images and varying runtime-plane +aggregates use their represented semantic domain; incomplete incidental metadata +on scalar/contributor-only outputs retains the existing filename-address law. +The join compares the actual two semantic addresses, complete persisted metadata +and independent materialization-record scope. It still checks alias, kind, +producer scope and exact destination before accepting a shared occurrence. + +An initially broader incomplete-address-to-None attempt failed the two existing +collapsed Mosaic/contributor publication controls (pixel-size aggregation changed +from .5 to 1). This counterevidence is retained in +``/var/tmp/openhcs-publication435-joined-20261004.log``. That route was rejected; +the corrected law leaves those controls unchanged and passing. Earlier fixture +construction errors, the rejected pre-normalization witness, and the intervening +missing-import failure remain in their original private logs. None is substituted +for the corrected determining RED. + +Receiving evidence and limits +----------------------------- + +The final gate passes 84 controls in 2.19 seconds: the existing function-output +controls and eleven original/extended receiving cases. For the aggregate positive +case, both complete typed metadata/source maps and CHANNEL1/SITE1/TIME1 scopes +agree; both semantic addresses are None. The storage identity keeps Z0 while +semantic component values have no scalar Z. Ordered source Z0..3, four exact +physical source paths, uint16 dtype and original calibration survive metadata +serialization and workspace reopen. Complete saved pixels equal all 140 source +values. The RED and GREEN physical aggregate TIFF SHA256 is identical: +``083537b57bcf28f80bf8abff0f28452a4f0d66c4ed65e6f400cf4a437a1a4d8a``. + +Original scalar path/producer/name/kind negatives remain. Aggregate metadata, +stale producer, kind and independent execution-scope conflicts reject. Aggregate +outputs at distinct physical paths retain two separate occurrences with exact +pixels; the existing whole-artifact identity explicitly includes the source ref, +so those distinct occurrences must not be silently deduplicated or rejected as a +single scalar-plane address. + +The standard TIFF metadata receiver retains its actual channel-axis/header facts; +this control does not relabel a four-plane runtime stack as intrinsic ZYX Volume. +At that historical stage, this established the writer/materializer boundary +without public execution or fresh MCP receiving. The completed ordinary receiving +section below now covers those consumers. Neither stage establishes old failed-job +replay, native scientific qualification or performance improvement. + +Reproduction and retained receipts +--------------------------------- + +The final command was:: + + taskset -c 2 env PYTHONPATH=/var/tmp/openhcs-volume-source-filename-20261004 /home/ts/code/projects/openhcs/.venv/bin/python -m pytest tests/unit/test_derived_role_publication_435.py tests/unit/test_function_outputs.py -q --basetemp=/var/tmp/openhcs-publication435-complete-20261004 + +Its complete output is retained at +``/var/tmp/openhcs-publication435-complete-20261004.log``. The determining RED log +is ``/var/tmp/openhcs-publication435-aggregate-red5-20261004.log``. Receipt SHA256: + +* ``red-prejoin-operands.json``: + ``84e9ff8f021ab31f891461fa4a3d4c7fe026a2b8cd5d426f7e9fe4ef540ac50e``. +* ``green-prejoin-operands.json``: + ``b9d3d83aa92c1ccffaef4df7c899ec97c1e41f41a2306dda5da415a168b21de6``. + +Follow-up contributor-only Mosaic seam adjudication +-------------------------------------------------- + +The existing collapsed Mosaic controls do not include a paired saved artifact. +The initial negative parameter in the same receiving fixture used their actual +semantic case: scalar source components omit SITE, two pixel contributors declare SITE1 +and SITE2, and the retained physical filename anchors SITE1. Its image is saved +and materialized through the original ImageFile owner, without overriding output +metadata or constructing a replacement projection. + +At that initial stage, this did NOT reproduce the hypothesized new address mismatch. The real +materializer's source-context fallback fills SITE1 into artifact metadata, so both +pre-join addresses are SITE1. The main-flow metadata retains no scalar SITE; +complete persisted metadata therefore disagree and the strict guard rejects. +The same fixture was run once against the current integrated source and once +with both affected production owners restored byte-exact from the pre-fix +``89666e33ea40de4e50a413a456b55926b9043ecf``. Both runs pass the expected rejection +control and have the same determining addresses and differing metadata field. +This establishes no new regression on that actual materializer path; it does not +promote the historical contributor scalar-fill behavior as a universal source +law or establish an independently authored Mosaic production journey. + +The unchanged logs and complete pre-join witnesses remain respectively under +``/var/tmp/openhcs-publication435-mosaic-base-20261004`` and +``/var/tmp/openhcs-publication435-mosaic-current-20261004`` (matching ``.log`` +files alongside them). No production adjustment or normalized-source API expansion +was made at that initial adjudication stage. The subsequent repair below changes +this parameter to require successful publication. + +Completed ordinary installed receiving +------------------------------------- + +Both bounded public cases now PASS. The final controller imports production +source ``a0bb0f4089a85475e112cea32d60132c1cd94752`` with the actual installed +editable dependencies, including ZMQRuntime +``04d813fe6c93f74166c05847afb1eae158d3c817``. CustomFunctionManager registers the +original producer bytes; PipelineDocumentAuthority renders, saves and reopens +the typed documents. Public MCP compile/execute reaches COMPLETE. Complete public +inventory and pixel samples pass, followed by identical readback in a second +independent SDK process. + +The aggregate execution was already COMPLETE on +``ee23a11d4f05e088fc5e267e98862281d993eb29`` and is reused byte-exact without +processing again. All nine inventory records remain visible: four source image +planes, four scalar checkpoints and one named aggregate. The named aggregate +retains all 140 uint16 values in a 4 x 5 x 7 array, 2/.65/.65 micrometer spacing, +ordered runtime Z0..3 and their four original physical contributors. Its semantic +address is None; CHANNEL1 scope fixes SITE1/TIME1 and carries no scalar Z. Exactly +one durable row describes this named physical occurrence. Scalar records remain +in the complete inventory and are not mislabeled as aggregates. + +The fresh Mosaic execution on ``a0bb0f408`` consumes two real 4 x 5 TIFFs and +returns a genuine two-dimensional 8 x 5 image through SourceProjectedImageOutput. +All three main/checkpoint/named physical outputs retain all 40 uint16 values, +.5/.5 micrometer spacing, two ordered original SITE1/SITE2 contributors and zero +runtime planes. Scalar SITE and plane axis are absent. Each has semantic address +None and its own single durable row. The producer explicitly drops the source +spatial grid: rank remains two, while source origin and source shape are None. +Output array geometry is independently 8 x 5. + +Two remaining generic defects were exposed and fixed through existing owners: + +* Workspace REL/FULL keys can refer to the identical SourceProjection. + SourcePatternResolutionContext now counts that object as one declaration + position while retaining both identity paths and separately resolved metadata + records. Distinct projection instances and mapping-only declarations remain + independent; strict ambiguity and source-position checks stay active. +* FunctionCoreExecutor.save_artifact_outputs already normalizes the selected + canonical producer value. Removing outer recontextualization prevents consumed + runtime planes from being restored onto a contributor-only Mosaic. Raw and + unselected-canonical outputs still contextualize after save callbacks; + adapter-owned and NoMain branches retain their existing behavior. + +The authoritative final receipt is +``/home/ts/.local/state/openhcs-maintenance/20261004/public-435-aggregate-mosaic-v8/journey.json``. +``public-receiving-summary.json`` pins that receipt, controller/helper, source and +environment freeze, all 3 Mosaic / all 9 aggregate physical records, metadata, +prior failure receipts and two direct production-owner replays. The freeze pins +50 prepared files, including original custom functions, six input TIFFs, valid +saved documents, v4-v7 receipts and earlier complete outputs. The earlier v3 +receipt is retained separately. Startup-owned registry caches may populate; +scientific inputs, source and installed dependencies are unchanged. Only the fresh +Mosaic output folder is relocated; the recorded AST check preserves the original +pipeline steps and source-binding declaration. + +The exact final commands were:: + + /home/ts/code/projects/openhcs/.venv/bin/python -B /var/tmp/run_public_435_aggregate_mosaic_qualified_v8_20261004.py --qualify-head a0bb0f4089a85475e112cea32d60132c1cd94752 + /home/ts/code/projects/openhcs/.venv/bin/python -B /var/tmp/run_public_435_aggregate_mosaic_qualified_v8_20261004.py --run + +The run used owned port 6563, CPU3, a 600-second journey deadline and a 128 MiB +data guard. Final source/dependency/interpreter/native/input/controller and prior +output guards pass. Controller exit is zero; runtime PID 1285281 (create time +1791103474.58) acknowledges close and exits. Both SDK children exit zero and the +official execution lease is released. Missing plate grid dimensions legitimately +produce PARTIAL inspection with no other warning; no grid is manufactured. + +Earlier v3-v7 failures remain unchanged. The v3 fixture omitted filename metadata +extraction, so did not declare its intended Z domain; v4 corrects that declaration +through MetadataExtractionRule without changing input or producer bytes. +Subsequent alias ambiguity and double normalization were real production defects. +Enum/property/checker mistakes and rejected source-grid expectations are retained +separately. No saved output metadata is repaired by hand. + +This completes the ordinary synthetic NEW494 aggregate and contributor-only +Mosaic receiving obligation. It does not replay the unavailable historical +biological #494 job or prove that failure cause. It makes no native CP or +performance claim: V15 timings and twelve native comparisons remain separately +qualified on source ``4f2e44701`` and are not rerun or attributed to this +correctness follow-up. + + +Contributor-only source authority repair +--------------------------------------- + +The follow-up uses two real physical 4 x 5 uint16 TIFF sources, SITE1 and SITE2, +loaded through FileManager and retained as contributor-only provenance of the +2 x 4 x 5 Mosaic. Scalar semantic metadata omits SITE; its storage filename remains +``A01_s001_w2_z001_t001_MosaicRole.tif``. These parseable physical sources are a +new concrete fixture, distinct from the original unparseable ``site-1.tif`` and +``site-2.tif`` placeholders. The earlier placeholder rejection remains historical +evidence, not a claimed replay of the new physical control. + +Restoring the three affected production files byte-exact from ``67aee7cf7`` +(root ``2193a86fd`` plus the earlier fixture/docs adjudication) makes the physical +control fail the real persisted-image metadata guard. Both pre-join addresses are +SITE1; the materializer injects SITE1 and an extension into semantic source +identity, while the main-flow payload omits SITE. Complete typed operands and +actual persisted records are retained in ``mosaic-source-owner-red.json``. + +The fix removes the storage-to-source identity merge helper. Materialization +reads the existing payload provenance and actual execution scope; storage +basename/filename identity remain independently owned. A source-path-only scalar +is admitted from its ORIGINAL source path before scope attachment, excluding +intrinsic whole images and every runtime-plane/contributor declaration. Shared +numeric component canonicalization now belongs to SourceMetadataFields; output +filename coercion derives from that owner without constructing source-to-output- +to-source identity views. Explicit writer declarations may still select viewer +routing metadata from the filename identity. Those values feed only the declared +writer/viewer selector, never typed Output metadata or persisted provenance. + +Main-flow publication derives its address from semantic source metadata. An +incomplete aggregate is an existing SourceArtifactProjection with address None +and actual producer scope. The join still compares exact address, complete image +metadata and actual record scope. Atomic geometry derives calibration through +existing execution_anchor_projections, preserving aggregate-only .5 micrometer +spacing without inventing a scalar plane address. + +The corrected physical control has equal complete pre-join metadata, semantic +address None, and identical actual scope on both operands. Durable JSON readback +retains absent scalar SITE, both original contributor paths/sites, zero runtime +source planes, .5/.5 micrometer spacing, and all 40 reopened uint16 pixel values. +``mosaic-source-owner-green.json`` retains the complete operands. Original +scalar/aggregate negative kind, path, source metadata and producer-scope controls +remain active. Real scalar path/alias admissions, ROI storage names and RGB +filename-selector controls remain active as separate contracts. + +Final validation of this historical repair is recorded below. Its unit control +does not itself claim public execution, foreign failed-job replay, native +scientific qualification or performance gain. The completed ordinary receiving +section above supplies separate public execution and fresh-reopen evidence. + +The final coupled command was:: + + taskset -c 3 env PYTHONPATH=/var/tmp/openhcs-volume-source-filename-20261004 /home/ts/code/projects/openhcs/.venv/bin/python -m pytest -q tests/unit/test_function_artifact_materialization.py tests/unit/test_function_outputs.py tests/unit/test_derived_role_publication_435.py tests/unit/test_source_metadata_owner.py tests/unit/test_source_metadata_live_mutation.py --basetemp=/var/tmp/openhcs-publication435-source-owner-final-20261004 + +Result: 202 PASS in 3.31 seconds. Full log: +``/var/tmp/openhcs-publication435-source-owner-final-20261004.log``. +The real physical baseline RED log is +``/var/tmp/openhcs-publication435-physical-mosaic-red-20261004.log``. +The initial broad attempt's 11 supported scalar/storage/selector failures remain +in ``/var/tmp/openhcs-publication435-source-owner-gate-20261004.log``; they were +corrected through the owners described above, not waived. The later two +canonicalization failures remain in the corresponding ``gate2`` log. + +Receipt SHA256: + +* ``mosaic-source-owner-red.json``: ``5d5274beffe5dd5346977a5d88e447d1e81051d91c25b123c65c0d1933123e8b``. + +* ``mosaic-source-owner-green.json``: ``33bb923dc9351be385843f9d4282398c09996c8571ce3d4a7563227d990a0e15``. diff --git a/docs/refactor/receipts/aggregate-publication-435-494-20261004/green-prejoin-operands.json b/docs/refactor/receipts/aggregate-publication-435-494-20261004/green-prejoin-operands.json new file mode 100644 index 0000000000..7f48dca600 --- /dev/null +++ b/docs/refactor/receipts/aggregate-publication-435-494-20261004/green-prejoin-operands.json @@ -0,0 +1,474 @@ +{ + "source_scope": "step-scope-3", + "produced": [ + { + "path": "/var/tmp/openhcs-publication435-complete-20261004/test_saved_roles_publish_once_5/images/A01_s001_w1_z000_t001_fixture_image_494.tif", + "identity": { + "origin": "pipeline", + "output_kind": "main", + "output_key": "fixture_image_494", + "projection_key": "main", + "step_name": "Derived role images", + "pipeline_position": 3, + "step_scope_id": "step-scope-3", + "invocation_key": null, + "artifact_kind": "image" + }, + "address": { + "site": "1", + "channel": "1", + "z_index": "0", + "timepoint": "1", + "well": "A01" + } + } + ], + "materialized": [ + { + "path": "/var/tmp/openhcs-publication435-complete-20261004/test_saved_roles_publish_once_5/images/A01_s001_w1_z000_t001_fixture_image_494.tif", + "role": "fixture_image_494", + "producer_scope": "step-scope-3", + "stored_key": "ArtifactKey(name='fixture_image_494', artifact_type=, scope=RuntimeExecutionAxisScope(axis_id='A01', component=, value='1', fixed_component_values=((, '1'), (, '1'))), semantic_id=None)" + } + ], + "artifact_projections": [ + { + "path": "images/A01_s001_w1_z000_t001_fixture_image_494.tif", + "role": "source_artifact", + "address": null, + "alias": "fixture_image_494", + "kind": "image" + } + ], + "pre_join_main_flow": [ + { + "virtual_path": "images/A01_s001_w1_z000_t001_fixture_image_494.tif", + "address": null, + "ref": { + "backend": "disk", + "backend_address": "images/A01_s001_w1_z000_t001_fixture_image_494.tif", + "source_axis_indices": [] + }, + "projection_role": "source_artifact", + "source_alias": "fixture_image_494", + "source_metadata": { + "extension": ".tif", + "site": "1", + "channel": "1", + "timepoint": "1", + "well": "A01", + "OpenHCSSourceVoxelSpacingZYX": "2,0.65000000000000002,0.65000000000000002", + "OpenHCSSourceVoxelSpacingUnit": "micrometers" + }, + "execution_scope": { + "axis_id": "A01", + "component": "channel", + "value": "1", + "fixed_component_values": [ + [ + "site", + "1" + ], + [ + "timepoint", + "1" + ] + ] + }, + "artifact_kind": "image", + "image_metadata": { + "source_voxel_spacing": { + "values_zyx": [ + 2.0, + 0.65, + 0.65 + ], + "unit": "micrometers" + }, + "source_spatial_domain": { + "origin_yx": null, + "source_shape_yx": null, + "fill_value": 0, + "value_name": "Dense array", + "spatial_dimensions": 2 + }, + "source_provenance": { + "source_path": null, + "source_component_metadata": { + "well": "A01", + "site": "1", + "channel": "1", + "timepoint": "1", + "extension": ".tif" + }, + "source_image_provenance_planes": [ + { + "path": "/var/tmp/openhcs-publication435-complete-20261004/test_saved_roles_publish_once_5/physical_source/A01_s001_w1_z000_t001.tif", + "component_metadata": { + "well": "A01", + "site": "1", + "channel": "1", + "z_index": "0", + "timepoint": "1", + "extension": ".tif" + }, + "identity_kind": "runtime_plane", + "source_image_name": "fixture_image_494", + "contributors": [] + }, + { + "path": "/var/tmp/openhcs-publication435-complete-20261004/test_saved_roles_publish_once_5/physical_source/A01_s001_w1_z001_t001.tif", + "component_metadata": { + "well": "A01", + "site": "1", + "channel": "1", + "z_index": "1", + "timepoint": "1", + "extension": ".tif" + }, + "identity_kind": "runtime_plane", + "source_image_name": "fixture_image_494", + "contributors": [] + }, + { + "path": "/var/tmp/openhcs-publication435-complete-20261004/test_saved_roles_publish_once_5/physical_source/A01_s001_w1_z002_t001.tif", + "component_metadata": { + "well": "A01", + "site": "1", + "channel": "1", + "z_index": "2", + "timepoint": "1", + "extension": ".tif" + }, + "identity_kind": "runtime_plane", + "source_image_name": "fixture_image_494", + "contributors": [] + }, + { + "path": "/var/tmp/openhcs-publication435-complete-20261004/test_saved_roles_publish_once_5/physical_source/A01_s001_w1_z003_t001.tif", + "component_metadata": { + "well": "A01", + "site": "1", + "channel": "1", + "z_index": "3", + "timepoint": "1", + "extension": ".tif" + }, + "identity_kind": "runtime_plane", + "source_image_name": "fixture_image_494", + "contributors": [] + } + ], + "source_image_names": [ + "fixture_image_494" + ] + }, + "intensity_scale": 65535.0, + "source_dtype": "uint16", + "unit_interval_intensity": null, + "source_plane_intensity_scales": [ + 65535.0, + 65535.0, + 65535.0, + 65535.0 + ], + "source_plane_dtypes": [ + "uint16", + "uint16", + "uint16", + "uint16" + ], + "physical_border_edges_yx": null, + "mask_defines_border": null, + "source_channel_axis": 0, + "plane_axis": "runtime_slice" + } + } + ], + "pre_join_artifacts": [ + { + "virtual_path": "images/A01_s001_w1_z000_t001_fixture_image_494.tif", + "address": null, + "ref": { + "backend": "disk", + "backend_address": "images/A01_s001_w1_z000_t001_fixture_image_494.tif", + "source_axis_indices": [] + }, + "projection_role": "source_artifact", + "source_alias": "fixture_image_494", + "source_metadata": { + "well": "A01", + "site": "1", + "channel": "1", + "timepoint": "1", + "extension": ".tif", + "OpenHCSSourceVoxelSpacingZYX": "2,0.65000000000000002,0.65000000000000002", + "OpenHCSSourceVoxelSpacingUnit": "micrometers" + }, + "execution_scope": { + "axis_id": "A01", + "component": "channel", + "value": "1", + "fixed_component_values": [ + [ + "site", + "1" + ], + [ + "timepoint", + "1" + ] + ] + }, + "artifact_kind": "image", + "image_metadata": { + "source_voxel_spacing": { + "values_zyx": [ + 2.0, + 0.65, + 0.65 + ], + "unit": "micrometers" + }, + "source_spatial_domain": { + "origin_yx": null, + "source_shape_yx": null, + "fill_value": 0, + "value_name": "Dense array", + "spatial_dimensions": 2 + }, + "source_provenance": { + "source_path": null, + "source_component_metadata": { + "well": "A01", + "site": "1", + "channel": "1", + "timepoint": "1", + "extension": ".tif" + }, + "source_image_provenance_planes": [ + { + "path": "/var/tmp/openhcs-publication435-complete-20261004/test_saved_roles_publish_once_5/physical_source/A01_s001_w1_z000_t001.tif", + "component_metadata": { + "well": "A01", + "site": "1", + "channel": "1", + "z_index": "0", + "timepoint": "1", + "extension": ".tif" + }, + "identity_kind": "runtime_plane", + "source_image_name": "fixture_image_494", + "contributors": [] + }, + { + "path": "/var/tmp/openhcs-publication435-complete-20261004/test_saved_roles_publish_once_5/physical_source/A01_s001_w1_z001_t001.tif", + "component_metadata": { + "well": "A01", + "site": "1", + "channel": "1", + "z_index": "1", + "timepoint": "1", + "extension": ".tif" + }, + "identity_kind": "runtime_plane", + "source_image_name": "fixture_image_494", + "contributors": [] + }, + { + "path": "/var/tmp/openhcs-publication435-complete-20261004/test_saved_roles_publish_once_5/physical_source/A01_s001_w1_z002_t001.tif", + "component_metadata": { + "well": "A01", + "site": "1", + "channel": "1", + "z_index": "2", + "timepoint": "1", + "extension": ".tif" + }, + "identity_kind": "runtime_plane", + "source_image_name": "fixture_image_494", + "contributors": [] + }, + { + "path": "/var/tmp/openhcs-publication435-complete-20261004/test_saved_roles_publish_once_5/physical_source/A01_s001_w1_z003_t001.tif", + "component_metadata": { + "well": "A01", + "site": "1", + "channel": "1", + "z_index": "3", + "timepoint": "1", + "extension": ".tif" + }, + "identity_kind": "runtime_plane", + "source_image_name": "fixture_image_494", + "contributors": [] + } + ], + "source_image_names": [ + "fixture_image_494" + ] + }, + "intensity_scale": 65535.0, + "source_dtype": "uint16", + "unit_interval_intensity": null, + "source_plane_intensity_scales": [ + 65535.0, + 65535.0, + 65535.0, + 65535.0 + ], + "source_plane_dtypes": [ + "uint16", + "uint16", + "uint16", + "uint16" + ], + "physical_border_edges_yx": null, + "mask_defines_border": null, + "source_channel_axis": 0, + "plane_axis": "runtime_slice" + } + } + ], + "produced_records": [ + { + "component_values": { + "site": 1, + "channel": 1, + "timepoint": 1, + "well": "A01" + }, + "extension": ".tif", + "source": "multi-plane payload provenance over identity components ('z_index',)", + "filename_component_values": { + "site": 1, + "channel": 1, + "z_index": 0, + "timepoint": 1, + "well": "A01" + }, + "filename_qualifier": null, + "producer_identity": { + "origin": "pipeline", + "output_kind": "main", + "output_key": "fixture_image_494", + "projection_key": "main", + "step_name": "Derived role images", + "pipeline_position": 3, + "step_scope_id": "step-scope-3", + "invocation_key": null, + "artifact_kind": "image" + }, + "output_path": "/var/tmp/openhcs-publication435-complete-20261004/test_saved_roles_publish_once_5/images/A01_s001_w1_z000_t001_fixture_image_494.tif", + "relative_output_path": "A01_s001_w1_z000_t001_fixture_image_494.tif", + "image_metadata": { + "source_voxel_spacing": { + "values_zyx": [ + 2.0, + 0.65, + 0.65 + ], + "unit": "micrometers" + }, + "source_spatial_domain": { + "origin_yx": null, + "source_shape_yx": null, + "fill_value": 0, + "value_name": "Dense array", + "spatial_dimensions": 2 + }, + "source_provenance": { + "source_path": null, + "source_component_metadata": { + "well": "A01", + "site": "1", + "channel": "1", + "timepoint": "1", + "extension": ".tif" + }, + "source_image_provenance_planes": [ + { + "path": "/var/tmp/openhcs-publication435-complete-20261004/test_saved_roles_publish_once_5/physical_source/A01_s001_w1_z000_t001.tif", + "component_metadata": { + "well": "A01", + "site": "1", + "channel": "1", + "z_index": "0", + "timepoint": "1", + "extension": ".tif" + }, + "identity_kind": "runtime_plane", + "source_image_name": "fixture_image_494", + "contributors": [] + }, + { + "path": "/var/tmp/openhcs-publication435-complete-20261004/test_saved_roles_publish_once_5/physical_source/A01_s001_w1_z001_t001.tif", + "component_metadata": { + "well": "A01", + "site": "1", + "channel": "1", + "z_index": "1", + "timepoint": "1", + "extension": ".tif" + }, + "identity_kind": "runtime_plane", + "source_image_name": "fixture_image_494", + "contributors": [] + }, + { + "path": "/var/tmp/openhcs-publication435-complete-20261004/test_saved_roles_publish_once_5/physical_source/A01_s001_w1_z002_t001.tif", + "component_metadata": { + "well": "A01", + "site": "1", + "channel": "1", + "z_index": "2", + "timepoint": "1", + "extension": ".tif" + }, + "identity_kind": "runtime_plane", + "source_image_name": "fixture_image_494", + "contributors": [] + }, + { + "path": "/var/tmp/openhcs-publication435-complete-20261004/test_saved_roles_publish_once_5/physical_source/A01_s001_w1_z003_t001.tif", + "component_metadata": { + "well": "A01", + "site": "1", + "channel": "1", + "z_index": "3", + "timepoint": "1", + "extension": ".tif" + }, + "identity_kind": "runtime_plane", + "source_image_name": "fixture_image_494", + "contributors": [] + } + ], + "source_image_names": [ + "fixture_image_494" + ] + }, + "intensity_scale": null, + "source_dtype": null, + "unit_interval_intensity": null, + "source_plane_intensity_scales": [ + null, + null, + null, + null + ], + "source_plane_dtypes": [ + null, + null, + null, + null + ], + "physical_border_edges_yx": null, + "mask_defines_border": null, + "source_channel_axis": null, + "plane_axis": "runtime_slice" + }, + "main_flow_plane_axis": "runtime_slice" + } + ] +} \ No newline at end of file diff --git a/docs/refactor/receipts/aggregate-publication-435-494-20261004/mosaic-source-owner-green.json b/docs/refactor/receipts/aggregate-publication-435-494-20261004/mosaic-source-owner-green.json new file mode 100644 index 0000000000..4859aba099 --- /dev/null +++ b/docs/refactor/receipts/aggregate-publication-435-494-20261004/mosaic-source-owner-green.json @@ -0,0 +1,345 @@ +{ + "source_scope": "step-scope-3", + "produced": [ + { + "path": "/var/tmp/openhcs-publication435-source-owner-final-20261004/test_saved_roles_publish_once_11/images/A01_s001_w2_z001_t001_MosaicRole.tif", + "identity": { + "origin": "pipeline", + "output_kind": "main", + "output_key": "MosaicRole", + "projection_key": "main", + "step_name": "Derived role images", + "pipeline_position": 3, + "step_scope_id": "step-scope-3", + "invocation_key": null, + "artifact_kind": "image" + }, + "address": { + "site": "1", + "channel": "2", + "z_index": "1", + "timepoint": "1", + "well": "A01" + } + } + ], + "materialized": [ + { + "path": "/var/tmp/openhcs-publication435-source-owner-final-20261004/test_saved_roles_publish_once_11/images/A01_s001_w2_z001_t001_MosaicRole.tif", + "role": "MosaicRole", + "semantic_source": { + "path": null, + "component_metadata": { + "extension": ".tif", + "well": "A01", + "channel": "2", + "z_index": "1", + "timepoint": "1" + } + }, + "producer_scope": "step-scope-3", + "stored_key": "ArtifactKey(name='MosaicRole', artifact_type=, scope=RuntimeExecutionAxisScope(axis_id='A01', component=None, value=None, fixed_component_values=((, '2'), (, '1'), (, '1'))), semantic_id=None)" + } + ], + "artifact_projections": [ + { + "path": "images/A01_s001_w2_z001_t001_MosaicRole.tif", + "role": "source_artifact", + "address": null, + "alias": "MosaicRole", + "kind": "image" + } + ], + "pre_join_main_flow": [ + { + "virtual_path": "images/A01_s001_w2_z001_t001_MosaicRole.tif", + "address": null, + "ref": { + "backend": "disk", + "backend_address": "images/A01_s001_w2_z001_t001_MosaicRole.tif", + "source_axis_indices": [] + }, + "projection_role": "source_artifact", + "source_alias": "MosaicRole", + "source_metadata": { + "extension": ".tif", + "channel": "2", + "z_index": "1", + "timepoint": "1", + "well": "A01", + "OpenHCSSourceVoxelSpacingZYX": "0.5,0.5", + "OpenHCSSourceVoxelSpacingUnit": "micrometers" + }, + "execution_scope": { + "axis_id": "A01", + "component": null, + "value": null, + "fixed_component_values": [ + [ + "channel", + "2" + ], + [ + "z_index", + "1" + ], + [ + "timepoint", + "1" + ] + ] + }, + "artifact_kind": "image", + "image_metadata": { + "source_voxel_spacing": { + "values_zyx": [ + 0.5, + 0.5 + ], + "unit": "micrometers" + }, + "source_spatial_domain": { + "origin_yx": null, + "source_shape_yx": null, + "fill_value": 0, + "value_name": "Dense array", + "spatial_dimensions": 2 + }, + "source_provenance": { + "source_path": null, + "source_component_metadata": { + "well": "A01", + "channel": "2", + "z_index": "1", + "timepoint": "1", + "extension": ".tif" + }, + "source_image_provenance_planes": [ + { + "path": "/var/tmp/openhcs-publication435-source-owner-final-20261004/test_saved_roles_publish_once_11/physical_source/A01_s001_w2_z001_t001.tif", + "component_metadata": { + "site": "1" + }, + "identity_kind": "pixel_contributor", + "source_image_name": null, + "contributors": [] + }, + { + "path": "/var/tmp/openhcs-publication435-source-owner-final-20261004/test_saved_roles_publish_once_11/physical_source/A01_s002_w2_z001_t001.tif", + "component_metadata": { + "site": "2" + }, + "identity_kind": "pixel_contributor", + "source_image_name": null, + "contributors": [] + } + ], + "source_image_names": [ + "MosaicRole" + ] + }, + "intensity_scale": 65535.0, + "source_dtype": "uint16", + "unit_interval_intensity": null, + "source_plane_intensity_scales": [], + "source_plane_dtypes": [], + "physical_border_edges_yx": null, + "mask_defines_border": null, + "source_channel_axis": null, + "plane_axis": null + } + } + ], + "pre_join_artifacts": [ + { + "virtual_path": "images/A01_s001_w2_z001_t001_MosaicRole.tif", + "address": null, + "ref": { + "backend": "disk", + "backend_address": "images/A01_s001_w2_z001_t001_MosaicRole.tif", + "source_axis_indices": [] + }, + "projection_role": "source_artifact", + "source_alias": "MosaicRole", + "source_metadata": { + "well": "A01", + "channel": "2", + "z_index": "1", + "timepoint": "1", + "extension": ".tif", + "OpenHCSSourceVoxelSpacingZYX": "0.5,0.5", + "OpenHCSSourceVoxelSpacingUnit": "micrometers" + }, + "execution_scope": { + "axis_id": "A01", + "component": null, + "value": null, + "fixed_component_values": [ + [ + "channel", + "2" + ], + [ + "z_index", + "1" + ], + [ + "timepoint", + "1" + ] + ] + }, + "artifact_kind": "image", + "image_metadata": { + "source_voxel_spacing": { + "values_zyx": [ + 0.5, + 0.5 + ], + "unit": "micrometers" + }, + "source_spatial_domain": { + "origin_yx": null, + "source_shape_yx": null, + "fill_value": 0, + "value_name": "Dense array", + "spatial_dimensions": 2 + }, + "source_provenance": { + "source_path": null, + "source_component_metadata": { + "well": "A01", + "channel": "2", + "z_index": "1", + "timepoint": "1", + "extension": ".tif" + }, + "source_image_provenance_planes": [ + { + "path": "/var/tmp/openhcs-publication435-source-owner-final-20261004/test_saved_roles_publish_once_11/physical_source/A01_s001_w2_z001_t001.tif", + "component_metadata": { + "site": "1" + }, + "identity_kind": "pixel_contributor", + "source_image_name": null, + "contributors": [] + }, + { + "path": "/var/tmp/openhcs-publication435-source-owner-final-20261004/test_saved_roles_publish_once_11/physical_source/A01_s002_w2_z001_t001.tif", + "component_metadata": { + "site": "2" + }, + "identity_kind": "pixel_contributor", + "source_image_name": null, + "contributors": [] + } + ], + "source_image_names": [ + "MosaicRole" + ] + }, + "intensity_scale": 65535.0, + "source_dtype": "uint16", + "unit_interval_intensity": null, + "source_plane_intensity_scales": [], + "source_plane_dtypes": [], + "physical_border_edges_yx": null, + "mask_defines_border": null, + "source_channel_axis": null, + "plane_axis": null + } + } + ], + "produced_records": [ + { + "component_values": { + "well": "A01", + "channel": "2", + "z_index": "1", + "timepoint": "1" + }, + "extension": ".tif", + "source": "collapsed Mosaic contributors", + "filename_component_values": { + "well": "A01", + "site": "1", + "channel": "2", + "z_index": "1", + "timepoint": "1" + }, + "filename_qualifier": null, + "producer_identity": { + "origin": "pipeline", + "output_kind": "main", + "output_key": "MosaicRole", + "projection_key": "main", + "step_name": "Derived role images", + "pipeline_position": 3, + "step_scope_id": "step-scope-3", + "invocation_key": null, + "artifact_kind": "image" + }, + "output_path": "/var/tmp/openhcs-publication435-source-owner-final-20261004/test_saved_roles_publish_once_11/images/A01_s001_w2_z001_t001_MosaicRole.tif", + "relative_output_path": "A01_s001_w2_z001_t001_MosaicRole.tif", + "image_metadata": { + "source_voxel_spacing": { + "values_zyx": [ + 0.5, + 0.5 + ], + "unit": "micrometers" + }, + "source_spatial_domain": { + "origin_yx": null, + "source_shape_yx": null, + "fill_value": 0, + "value_name": "Dense array", + "spatial_dimensions": 2 + }, + "source_provenance": { + "source_path": null, + "source_component_metadata": { + "well": "A01", + "channel": "2", + "z_index": "1", + "timepoint": "1", + "extension": ".tif" + }, + "source_image_provenance_planes": [ + { + "path": "/var/tmp/openhcs-publication435-source-owner-final-20261004/test_saved_roles_publish_once_11/physical_source/A01_s001_w2_z001_t001.tif", + "component_metadata": { + "site": "1" + }, + "identity_kind": "pixel_contributor", + "source_image_name": null, + "contributors": [] + }, + { + "path": "/var/tmp/openhcs-publication435-source-owner-final-20261004/test_saved_roles_publish_once_11/physical_source/A01_s002_w2_z001_t001.tif", + "component_metadata": { + "site": "2" + }, + "identity_kind": "pixel_contributor", + "source_image_name": null, + "contributors": [] + } + ], + "source_image_names": [ + "MosaicRole" + ] + }, + "intensity_scale": null, + "source_dtype": null, + "unit_interval_intensity": null, + "source_plane_intensity_scales": [], + "source_plane_dtypes": [], + "physical_border_edges_yx": null, + "mask_defines_border": null, + "source_channel_axis": null, + "plane_axis": null + }, + "main_flow_plane_axis": "runtime_slice" + } + ] +} \ No newline at end of file diff --git a/docs/refactor/receipts/aggregate-publication-435-494-20261004/mosaic-source-owner-red.json b/docs/refactor/receipts/aggregate-publication-435-494-20261004/mosaic-source-owner-red.json new file mode 100644 index 0000000000..080f6ec205 --- /dev/null +++ b/docs/refactor/receipts/aggregate-publication-435-494-20261004/mosaic-source-owner-red.json @@ -0,0 +1,346 @@ +{ + "source_scope": "step-scope-3", + "produced": [ + { + "path": "/var/tmp/openhcs-publication435-physical-mosaic-red-20261004/test_saved_roles_publish_once_0/images/A01_s001_w2_z001_t001_MosaicRole.tif", + "identity": { + "origin": "pipeline", + "output_kind": "main", + "output_key": "MosaicRole", + "projection_key": "main", + "step_name": "Derived role images", + "pipeline_position": 3, + "step_scope_id": "step-scope-3", + "invocation_key": null, + "artifact_kind": "image" + }, + "address": { + "site": "1", + "channel": "2", + "z_index": "1", + "timepoint": "1", + "well": "A01" + } + } + ], + "materialized": [ + { + "path": "/var/tmp/openhcs-publication435-physical-mosaic-red-20261004/test_saved_roles_publish_once_0/images/A01_s001_w2_z001_t001_MosaicRole.tif", + "role": "MosaicRole", + "semantic_source": { + "path": null, + "component_metadata": { + "extension": ".tif", + "site": "1", + "channel": "2", + "z_index": "1", + "timepoint": "1", + "well": "A01" + } + }, + "producer_scope": "step-scope-3", + "stored_key": "ArtifactKey(name='MosaicRole', artifact_type=, scope=RuntimeExecutionAxisScope(axis_id='A01', component=None, value=None, fixed_component_values=((, '2'), (, '1'), (, '1'))), semantic_id=None)" + } + ], + "artifact_projections": [ + { + "path": "images/A01_s001_w2_z001_t001_MosaicRole.tif", + "role": "source_artifact", + "address": { + "site": "1", + "channel": "2", + "z_index": "1", + "timepoint": "1", + "well": "A01" + }, + "alias": "MosaicRole", + "kind": "image" + } + ], + "pre_join_main_flow": [ + { + "virtual_path": "images/A01_s001_w2_z001_t001_MosaicRole.tif", + "address": { + "site": "1", + "channel": "2", + "z_index": "1", + "timepoint": "1", + "well": "A01" + }, + "ref": { + "backend": "disk", + "backend_address": "images/A01_s001_w2_z001_t001_MosaicRole.tif", + "source_axis_indices": [] + }, + "projection_role": "primary_plane", + "source_alias": "MosaicRole", + "source_metadata": { + "extension": ".tif", + "channel": "2", + "z_index": "1", + "timepoint": "1", + "well": "A01", + "OpenHCSSourceVoxelSpacingZYX": "0.5,0.5", + "OpenHCSSourceVoxelSpacingUnit": "micrometers" + }, + "image_metadata": { + "source_voxel_spacing": { + "values_zyx": [ + 0.5, + 0.5 + ], + "unit": "micrometers" + }, + "source_spatial_domain": { + "origin_yx": null, + "source_shape_yx": null, + "fill_value": 0, + "value_name": "Dense array", + "spatial_dimensions": 2 + }, + "source_provenance": { + "source_path": null, + "source_component_metadata": { + "well": "A01", + "channel": "2", + "z_index": "1", + "timepoint": "1", + "extension": ".tif" + }, + "source_image_provenance_planes": [ + { + "path": "/var/tmp/openhcs-publication435-physical-mosaic-red-20261004/test_saved_roles_publish_once_0/physical_source/A01_s001_w2_z001_t001.tif", + "component_metadata": { + "site": "1" + }, + "identity_kind": "pixel_contributor", + "source_image_name": null, + "contributors": [] + }, + { + "path": "/var/tmp/openhcs-publication435-physical-mosaic-red-20261004/test_saved_roles_publish_once_0/physical_source/A01_s002_w2_z001_t001.tif", + "component_metadata": { + "site": "2" + }, + "identity_kind": "pixel_contributor", + "source_image_name": null, + "contributors": [] + } + ], + "source_image_names": [ + "MosaicRole" + ] + }, + "intensity_scale": 65535.0, + "source_dtype": "uint16", + "unit_interval_intensity": null, + "source_plane_intensity_scales": [], + "source_plane_dtypes": [], + "physical_border_edges_yx": null, + "mask_defines_border": null, + "source_channel_axis": null, + "plane_axis": null + } + } + ], + "pre_join_artifacts": [ + { + "virtual_path": "images/A01_s001_w2_z001_t001_MosaicRole.tif", + "address": { + "site": "1", + "channel": "2", + "z_index": "1", + "timepoint": "1", + "well": "A01" + }, + "ref": { + "backend": "disk", + "backend_address": "images/A01_s001_w2_z001_t001_MosaicRole.tif", + "source_axis_indices": [] + }, + "projection_role": "source_artifact", + "source_alias": "MosaicRole", + "source_metadata": { + "well": "A01", + "channel": "2", + "z_index": "1", + "timepoint": "1", + "extension": ".tif", + "site": "1", + "OpenHCSSourceVoxelSpacingZYX": "0.5,0.5", + "OpenHCSSourceVoxelSpacingUnit": "micrometers" + }, + "execution_scope": { + "axis_id": "A01", + "component": null, + "value": null, + "fixed_component_values": [ + [ + "channel", + "2" + ], + [ + "z_index", + "1" + ], + [ + "timepoint", + "1" + ] + ] + }, + "artifact_kind": "image", + "image_metadata": { + "source_voxel_spacing": { + "values_zyx": [ + 0.5, + 0.5 + ], + "unit": "micrometers" + }, + "source_spatial_domain": { + "origin_yx": null, + "source_shape_yx": null, + "fill_value": 0, + "value_name": "Dense array", + "spatial_dimensions": 2 + }, + "source_provenance": { + "source_path": null, + "source_component_metadata": { + "well": "A01", + "channel": "2", + "z_index": "1", + "timepoint": "1", + "extension": ".tif", + "site": "1" + }, + "source_image_provenance_planes": [ + { + "path": "/var/tmp/openhcs-publication435-physical-mosaic-red-20261004/test_saved_roles_publish_once_0/physical_source/A01_s001_w2_z001_t001.tif", + "component_metadata": { + "site": "1" + }, + "identity_kind": "pixel_contributor", + "source_image_name": null, + "contributors": [] + }, + { + "path": "/var/tmp/openhcs-publication435-physical-mosaic-red-20261004/test_saved_roles_publish_once_0/physical_source/A01_s002_w2_z001_t001.tif", + "component_metadata": { + "site": "2" + }, + "identity_kind": "pixel_contributor", + "source_image_name": null, + "contributors": [] + } + ], + "source_image_names": [ + "MosaicRole" + ] + }, + "intensity_scale": 65535.0, + "source_dtype": "uint16", + "unit_interval_intensity": null, + "source_plane_intensity_scales": [], + "source_plane_dtypes": [], + "physical_border_edges_yx": null, + "mask_defines_border": null, + "source_channel_axis": null, + "plane_axis": null + } + } + ], + "produced_records": [ + { + "component_values": { + "well": "A01", + "channel": "2", + "z_index": "1", + "timepoint": "1" + }, + "extension": ".tif", + "source": "collapsed Mosaic contributors", + "filename_component_values": { + "well": "A01", + "site": "1", + "channel": "2", + "z_index": "1", + "timepoint": "1" + }, + "filename_qualifier": null, + "producer_identity": { + "origin": "pipeline", + "output_kind": "main", + "output_key": "MosaicRole", + "projection_key": "main", + "step_name": "Derived role images", + "pipeline_position": 3, + "step_scope_id": "step-scope-3", + "invocation_key": null, + "artifact_kind": "image" + }, + "output_path": "/var/tmp/openhcs-publication435-physical-mosaic-red-20261004/test_saved_roles_publish_once_0/images/A01_s001_w2_z001_t001_MosaicRole.tif", + "relative_output_path": "A01_s001_w2_z001_t001_MosaicRole.tif", + "image_metadata": { + "source_voxel_spacing": { + "values_zyx": [ + 0.5, + 0.5 + ], + "unit": "micrometers" + }, + "source_spatial_domain": { + "origin_yx": null, + "source_shape_yx": null, + "fill_value": 0, + "value_name": "Dense array", + "spatial_dimensions": 2 + }, + "source_provenance": { + "source_path": null, + "source_component_metadata": { + "well": "A01", + "channel": "2", + "z_index": "1", + "timepoint": "1", + "extension": ".tif" + }, + "source_image_provenance_planes": [ + { + "path": "/var/tmp/openhcs-publication435-physical-mosaic-red-20261004/test_saved_roles_publish_once_0/physical_source/A01_s001_w2_z001_t001.tif", + "component_metadata": { + "site": "1" + }, + "identity_kind": "pixel_contributor", + "source_image_name": null, + "contributors": [] + }, + { + "path": "/var/tmp/openhcs-publication435-physical-mosaic-red-20261004/test_saved_roles_publish_once_0/physical_source/A01_s002_w2_z001_t001.tif", + "component_metadata": { + "site": "2" + }, + "identity_kind": "pixel_contributor", + "source_image_name": null, + "contributors": [] + } + ], + "source_image_names": [ + "MosaicRole" + ] + }, + "intensity_scale": null, + "source_dtype": null, + "unit_interval_intensity": null, + "source_plane_intensity_scales": [], + "source_plane_dtypes": [], + "physical_border_edges_yx": null, + "mask_defines_border": null, + "source_channel_axis": null, + "plane_axis": null + }, + "main_flow_plane_axis": "runtime_slice" + } + ] +} \ No newline at end of file diff --git a/docs/refactor/receipts/aggregate-publication-435-494-20261004/public-receiving-summary.json b/docs/refactor/receipts/aggregate-publication-435-494-20261004/public-receiving-summary.json new file mode 100644 index 0000000000..cd941006f1 --- /dev/null +++ b/docs/refactor/receipts/aggregate-publication-435-494-20261004/public-receiving-summary.json @@ -0,0 +1,388 @@ +{ + "status": "PASS", + "issue": 435, + "scope": "New bounded synthetic ordinary public #435 aggregate and 2D contributor Mosaic receiving; not biological #494 replay or performance evidence.", + "receiving_source": { + "path": "/var/tmp/openhcs-resolved-pipeline-owner-20261004", + "head": "a0bb0f4089a85475e112cea32d60132c1cd94752" + }, + "aggregate_execution_source": "ee23a11d4f05e088fc5e267e98862281d993eb29", + "production_fixes": { + "source_position_lookup_aliases": "ee23a11d4f05e088fc5e267e98862281d993eb29", + "qualify_canonical_main_output_once": "a0bb0f4089a85475e112cea32d60132c1cd94752" + }, + "dependencies": { + "external/ObjectState": "9fb5b7eeea96f3b7bb0579de30718bbcc0018823", + "external/python-introspect": "430fbbeeb6c7e0a9274d3bf9b0998a10cae5a505", + "external/arraybridge": "1e53d03d9f468322a1c085c8be29485fb139caf2", + "external/metaclass-registry": "393a7e03003cdc56df9013f932ed4f26e632d77a", + "external/zmqruntime": "04d813fe6c93f74166c05847afb1eae158d3c817", + "external/pycodify": "108a8edbf25de258168756bac22c7572f018fa90", + "external/PolyStore": "89deeef3662eabb11bc520fad9acd976698636bd", + "external/pyqt-reactive": "b64ed2eca96fcdad29ba90beb545caa669a4d3d8" + }, + "python": { + "path": "/home/ts/.local/share/uv/python/cpython-3.12.14-linux-x86_64-gnu/bin/python3.12", + "sha256": "edffa803e5c4d73a1357f7f2c6c9fd38e9693712b2c06793e6a5e5cc1090d03a" + }, + "native": { + "openhcs/core/_tabular_native.abi3.so": { + "path": "/home/ts/code/projects/openhcs/openhcs/core/_tabular_native.abi3.so", + "sha256": "2ce348417de70ad3f614962c82aed9c4977c32b3ba00e13531ecafb8c10d8d1d" + }, + "openhcs/processing/backends/cellprofiler/_granularity_native.abi3.so": { + "path": "/home/ts/code/projects/openhcs/openhcs/processing/backends/cellprofiler/_granularity_native.abi3.so", + "sha256": "6e45987a50d5c0588a8fb0b09a2232a63e72c122d6a3d583ae4d62830e3b4096" + } + }, + "custody": { + "final_journey": { + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/public-435-aggregate-mosaic-v8/journey.json", + "sha256": "caa36da0b2b91326e3c8f5476d7855d2a6a3bb0a02e85b0e5cbfbebf602338d9" + }, + "source_environment_and_50_prepared_file_hashes": { + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/public-435-aggregate-mosaic-v8/source-freeze.json", + "sha256": "264f99b2c3df7ba48553450212c2d182e2785336926ac71cc8c49e575c40ffc1" + }, + "original_preparation": { + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/public-435-aggregate-mosaic-v2/source-freeze.json", + "sha256": "0f815329ffdea143cd7525b788e2ea63f937d876f5876aef10626500bbed171a", + "head": "6145ac3e5315c0591035d19e502248c601f1247d", + "controller_sha256": "07bd7f72cd9397d8de9a969f8f614e80cbded9a0b3a84cce5bedc3d8bd37819b" + }, + "controller": { + "path": "/var/tmp/run_public_435_aggregate_mosaic_qualified_v8_20261004.py", + "sha256": "2d84f3eb7fb4cf30d5594f1f18321b7085f6bb5baf1dc088bad854f97f1adac5" + }, + "original_public_helper": { + "path": "/var/tmp/run_public_installed_consumers_419_435_450_v7_20261004.py", + "sha256": "733ba0c91ad79a01702708fc899ff5c1a3ff24a3bcb2c5a5ab31609010551bbe" + }, + "output_routing_only": { + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/public-435-aggregate-mosaic-v8/output-routing-only.json", + "sha256": "8635630b257cd5cd7a7dc3aa22d14c71962565bcb62e21c57812bbd21a7a8111" + }, + "controller_terminal_log": { + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/public-435-aggregate-mosaic-v8/controller.log", + "sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + }, + "prelaunch_refusals": { + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/public-435-aggregate-mosaic-v8/qualification-preflight-failures.json", + "sha256": "98fd76e0f6f3143a37a3ceeba6a3e44c6a820e22803fad393197319371e5b5b1" + }, + "preserved_prior_receipts": [ + { + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/public-435-aggregate-mosaic-v3/journey.json", + "sha256": "6fa69210c2f4654aefdaa0445575ffac8919ef1a9b14da6b123558252b914b55", + "included_in_final_prepared_guard": false + }, + { + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/public-435-aggregate-mosaic-v3/source-freeze.json", + "sha256": "44eb967d3b78edc1a9850da8e64788dd45c3d8f0efa8ac4695a6cdbab3bec25c", + "included_in_final_prepared_guard": false + }, + { + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/public-435-aggregate-mosaic-v4/journey.json", + "sha256": "5bee37afcc4577771fe64626b52705ae91ad4567339d93bd34f69bb0a3ea48a6", + "included_in_final_prepared_guard": true + }, + { + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/public-435-aggregate-mosaic-v4/source-freeze.json", + "sha256": "e18d944ea3cc0bad71307ed5b93d7f7b78a487e2071e896000a6f34fd97f3ba1", + "included_in_final_prepared_guard": true + }, + { + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/public-435-aggregate-mosaic-v5/journey.json", + "sha256": "12dde33a239b77448d15ab04ea32a73c70c66ec5046e163067c3b75169e89811", + "included_in_final_prepared_guard": true + }, + { + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/public-435-aggregate-mosaic-v5/source-freeze.json", + "sha256": "43f9769c0b240bea0b683caf89051b16ce02ab807fb8b017ed18ab26905f4ae4", + "included_in_final_prepared_guard": true + }, + { + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/public-435-aggregate-mosaic-v6/journey.json", + "sha256": "170393fb791c3146f6d61c5aac444acea09b0f051b8d15e44516cf2eafd00fb5", + "included_in_final_prepared_guard": true + }, + { + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/public-435-aggregate-mosaic-v6/source-freeze.json", + "sha256": "e261acf9f5af601d4ee5d5cb3985236184262a9ffae191c7918b312ffd893731", + "included_in_final_prepared_guard": true + }, + { + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/public-435-aggregate-mosaic-v7/journey.json", + "sha256": "a52879178c2fa876bda00b3cd8f21957b944f420508ac4725726758e0091580e", + "included_in_final_prepared_guard": true + }, + { + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/public-435-aggregate-mosaic-v7/source-freeze.json", + "sha256": "c18e194279834147839f1b3d50484f18c0ec644ca5371ec735afabb077859e9e", + "included_in_final_prepared_guard": true + } + ], + "production_owner_replays": [ + { + "path": "/var/tmp/openhcs-435-valid-v4-source-position-replay-20261004.json", + "sha256": "57f9282918e1638071af4c7f3592e362ef2f8c435eaea78282fa6edd665c32df" + }, + { + "path": "/var/tmp/openhcs-435-mosaic-main-owner-replay-20261004.json", + "sha256": "831d56a703a55a75b99caad4172d5e195ea25a62c4b8857ef8ea5e89a3884e92" + } + ] + }, + "immutable_guards": { + "status": "PASS: final controller validate(freeze) completed before accepted=True", + "prepared_file_count": 50, + "scope": "source, installed dependencies/environment, Python/native, controller/helper, original physical/custom/document bytes, pinned failures and completed old outputs", + "startup_owned_registry_caches_unfrozen": true + }, + "cases": { + "mosaic": { + "compile_status": "complete", + "execute_status": "complete", + "execution_reused_without_processing": false, + "function": "public_435_vertical_mosaic_20261004", + "role": "MosaicRole", + "output_plate_root": "/home/ts/.local/state/openhcs-maintenance/20261004/public-435-aggregate-mosaic-v8/outputs/mosaic/mosaic_openhcs", + "shape": [ + 8, + 5 + ], + "dtype": "uint16", + "spacing_micrometers": [ + 0.5, + 0.5 + ], + "complete_inventory_count": 3, + "qualified_role_count": 3, + "distinct_qualified_occurrences": 3, + "wire_rows_for_qualified_occurrences": 3, + "metadata_sha256": "3d16ab99de1a2ac214a48c8e1e0a5c0c4cf80c7df16b22f866b2e4a77a1973dc", + "first_public_receiving": "PASS", + "independent_fresh_sdk_reopen": "PASS: exact first-read equality", + "source_domain": { + "runtime_planes": 0, + "contributors": 2, + "ordered_sites": [ + "1", + "2" + ], + "scalar_site_absent": true, + "plane_axis": null, + "semantic_address": null, + "spatial_rank": 2, + "source_origin_yx": null, + "source_shape_yx": null + }, + "qualified_scope": { + "axis_id": "A01", + "component": null, + "value": null, + "fixed_component_values": [ + [ + "channel", + "2" + ], + [ + "z_index", + "1" + ], + [ + "timepoint", + "1" + ] + ] + }, + "inventory": [ + { + "virtual_path": "checkpoints/A01_s001_w2_z001_t001.tif", + "physical_file": { + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/public-435-aggregate-mosaic-v8/outputs/mosaic/mosaic_openhcs/checkpoints/A01_s001_w2_z001_t001.tif", + "sha256": "0a73a87400d5d48c59603aaadd37d2b85543260a51117d359098c617a19257c7" + }, + "disposition": "Full pixels, typed projection/domain/calibration and public sample PASS" + }, + { + "virtual_path": "checkpoints_results/A01_s001_w2_z001_t001_MosaicRole.tif", + "physical_file": { + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/public-435-aggregate-mosaic-v8/outputs/mosaic/mosaic_openhcs/checkpoints_results/A01_s001_w2_z001_t001_MosaicRole.tif", + "sha256": "0a73a87400d5d48c59603aaadd37d2b85543260a51117d359098c617a19257c7" + }, + "disposition": "Full pixels, typed projection/domain/calibration and public sample PASS" + }, + { + "virtual_path": "images/A01_s001_w2_z001_t001.tif", + "physical_file": { + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/public-435-aggregate-mosaic-v8/outputs/mosaic/mosaic_openhcs/images/A01_s001_w2_z001_t001.tif", + "sha256": "0a73a87400d5d48c59603aaadd37d2b85543260a51117d359098c617a19257c7" + }, + "disposition": "Full pixels, typed projection/domain/calibration and public sample PASS" + } + ] + }, + "aggregate": { + "compile_status": "complete", + "execute_status": "complete", + "execution_reused_without_processing": true, + "function": "public_435_aggregate_copy_20261004", + "role": "fixture_image_494", + "output_plate_root": "/home/ts/.local/state/openhcs-maintenance/20261004/public-435-aggregate-mosaic-v4/outputs/aggregate/aggregate_openhcs", + "shape": [ + 4, + 5, + 7 + ], + "dtype": "uint16", + "spacing_micrometers": [ + 2.0, + 0.65, + 0.65 + ], + "complete_inventory_count": 9, + "qualified_role_count": 1, + "distinct_qualified_occurrences": 1, + "wire_rows_for_qualified_occurrences": 1, + "metadata_sha256": "5051df18221dfec5776cab56e1a92789114e343d8104b8065fb903e29a4978ed", + "first_public_receiving": "PASS", + "independent_fresh_sdk_reopen": "PASS: exact first-read equality", + "source_domain": { + "runtime_planes": 4, + "nested_original_contributors": 4, + "ordered_z": [ + "0", + "1", + "2", + "3" + ], + "scalar_z_absent": true, + "semantic_address": null, + "spatial_rank": 2, + "source_shape_yx": [ + 5, + 7 + ] + }, + "qualified_scope": { + "axis_id": "A01", + "component": "channel", + "value": "1", + "fixed_component_values": [ + [ + "site", + "1" + ], + [ + "timepoint", + "1" + ] + ] + }, + "inventory": [ + { + "virtual_path": "checkpoints/A01_s001_w1_z000_t001.tif", + "physical_file": { + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/public-435-aggregate-mosaic-v4/outputs/aggregate/aggregate_openhcs/checkpoints/A01_s001_w1_z000_t001.tif", + "sha256": "185acf4f100bc70b25c2afeb1fa87ef93d1e30431054750190fde43d1c4a88ed" + }, + "disposition": "Scalar occurrence retained in complete public inventory; fresh reopen PASS" + }, + { + "virtual_path": "checkpoints/A01_s001_w1_z001_t001.tif", + "physical_file": { + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/public-435-aggregate-mosaic-v4/outputs/aggregate/aggregate_openhcs/checkpoints/A01_s001_w1_z001_t001.tif", + "sha256": "6ff09db984f2459da1d6f4d364c487419765f434cf916463f65f9a4e4ef76561" + }, + "disposition": "Scalar occurrence retained in complete public inventory; fresh reopen PASS" + }, + { + "virtual_path": "checkpoints/A01_s001_w1_z002_t001.tif", + "physical_file": { + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/public-435-aggregate-mosaic-v4/outputs/aggregate/aggregate_openhcs/checkpoints/A01_s001_w1_z002_t001.tif", + "sha256": "8d0b320758591c448b98e059717455d0c64cc1af3f2c18a25b6ba88e6c96cc2a" + }, + "disposition": "Scalar occurrence retained in complete public inventory; fresh reopen PASS" + }, + { + "virtual_path": "checkpoints/A01_s001_w1_z003_t001.tif", + "physical_file": { + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/public-435-aggregate-mosaic-v4/outputs/aggregate/aggregate_openhcs/checkpoints/A01_s001_w1_z003_t001.tif", + "sha256": "d29162230ba5972912bd665b43857d548afa2fa35ef2b3039f30268bf0757f4b" + }, + "disposition": "Scalar occurrence retained in complete public inventory; fresh reopen PASS" + }, + { + "virtual_path": "checkpoints_results/A01_s001_w1_z000_t001_fixture_image_494.tif", + "physical_file": { + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/public-435-aggregate-mosaic-v4/outputs/aggregate/aggregate_openhcs/checkpoints_results/A01_s001_w1_z000_t001_fixture_image_494.tif", + "sha256": "083537b57bcf28f80bf8abff0f28452a4f0d66c4ed65e6f400cf4a437a1a4d8a" + }, + "disposition": "Full pixels, typed projection/domain/calibration and public sample PASS" + }, + { + "virtual_path": "images/A01_s001_w1_z000_t001.tif", + "physical_file": { + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/public-435-aggregate-mosaic-v4/outputs/aggregate/aggregate_openhcs/images/A01_s001_w1_z000_t001.tif", + "sha256": "185acf4f100bc70b25c2afeb1fa87ef93d1e30431054750190fde43d1c4a88ed" + }, + "disposition": "Scalar occurrence retained in complete public inventory; fresh reopen PASS" + }, + { + "virtual_path": "images/A01_s001_w1_z001_t001.tif", + "physical_file": { + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/public-435-aggregate-mosaic-v4/outputs/aggregate/aggregate_openhcs/images/A01_s001_w1_z001_t001.tif", + "sha256": "6ff09db984f2459da1d6f4d364c487419765f434cf916463f65f9a4e4ef76561" + }, + "disposition": "Scalar occurrence retained in complete public inventory; fresh reopen PASS" + }, + { + "virtual_path": "images/A01_s001_w1_z002_t001.tif", + "physical_file": { + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/public-435-aggregate-mosaic-v4/outputs/aggregate/aggregate_openhcs/images/A01_s001_w1_z002_t001.tif", + "sha256": "8d0b320758591c448b98e059717455d0c64cc1af3f2c18a25b6ba88e6c96cc2a" + }, + "disposition": "Scalar occurrence retained in complete public inventory; fresh reopen PASS" + }, + { + "virtual_path": "images/A01_s001_w1_z003_t001.tif", + "physical_file": { + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/public-435-aggregate-mosaic-v4/outputs/aggregate/aggregate_openhcs/images/A01_s001_w1_z003_t001.tif", + "sha256": "d29162230ba5972912bd665b43857d548afa2fa35ef2b3039f30268bf0757f4b" + }, + "disposition": "Scalar occurrence retained in complete public inventory; fresh reopen PASS" + } + ] + } + }, + "terminal": { + "controller_returncode": 0, + "owned_runtime_terminal": true, + "runtime_process_identity": { + "pid": 1285281, + "create_time": 1791103474.58 + }, + "mcp_children": [ + { + "pid": 1285066, + "returncode": 0 + }, + { + "pid": 1286340, + "returncode": 0 + } + ], + "official_lease": "RELEASED" + }, + "commands": [ + "/home/ts/code/projects/openhcs/.venv/bin/python -B /var/tmp/run_public_435_aggregate_mosaic_qualified_v8_20261004.py --qualify-head a0bb0f4089a85475e112cea32d60132c1cd94752", + "/home/ts/code/projects/openhcs/.venv/bin/python -B /var/tmp/run_public_435_aggregate_mosaic_qualified_v8_20261004.py --run" + ], + "limits": [ + "Tiny synthetic cases, not historical biological #494 replay or failure-cause proof.", + "Aggregate execution on ee23 was retained without reprocessing; both plates freshly read on a0bb.", + "No native CP or performance claim; V15 source4f2 remains separate.", + "Inspection PARTIAL only for missing plate grid dimensions; no grid manufactured." + ] +} diff --git a/docs/refactor/receipts/aggregate-publication-435-494-20261004/red-prejoin-operands.json b/docs/refactor/receipts/aggregate-publication-435-494-20261004/red-prejoin-operands.json new file mode 100644 index 0000000000..81e8cc4467 --- /dev/null +++ b/docs/refactor/receipts/aggregate-publication-435-494-20261004/red-prejoin-operands.json @@ -0,0 +1,478 @@ +{ + "source_scope": "step-scope-3", + "produced": [ + { + "path": "/var/tmp/openhcs-publication435-aggregate-red5-20261004/test_saved_roles_publish_once_0/images/A01_s001_w1_z000_t001_fixture_image_494.tif", + "identity": { + "origin": "pipeline", + "output_kind": "main", + "output_key": "fixture_image_494", + "projection_key": "main", + "step_name": "Derived role images", + "pipeline_position": 3, + "step_scope_id": "step-scope-3", + "invocation_key": null, + "artifact_kind": "image" + }, + "address": { + "site": "1", + "channel": "1", + "z_index": "0", + "timepoint": "1", + "well": "A01" + } + } + ], + "materialized": [ + { + "path": "/var/tmp/openhcs-publication435-aggregate-red5-20261004/test_saved_roles_publish_once_0/images/A01_s001_w1_z000_t001_fixture_image_494.tif", + "role": "fixture_image_494", + "producer_scope": "step-scope-3", + "stored_key": "ArtifactKey(name='fixture_image_494', artifact_type=, scope=RuntimeExecutionAxisScope(axis_id='A01', component=, value='1', fixed_component_values=((, '1'), (, '1'))), semantic_id=None)" + } + ], + "artifact_projections": [ + { + "path": "images/A01_s001_w1_z000_t001_fixture_image_494.tif", + "role": "source_artifact", + "address": { + "site": "1", + "channel": "1", + "z_index": "0", + "timepoint": "1", + "well": "A01" + }, + "alias": "fixture_image_494", + "kind": "image" + } + ], + "pre_join_main_flow": [ + { + "virtual_path": "images/A01_s001_w1_z000_t001_fixture_image_494.tif", + "address": { + "site": "1", + "channel": "1", + "z_index": "0", + "timepoint": "1", + "well": "A01" + }, + "ref": { + "backend": "disk", + "backend_address": "images/A01_s001_w1_z000_t001_fixture_image_494.tif", + "source_axis_indices": [] + }, + "projection_role": "primary_plane", + "source_alias": "fixture_image_494", + "source_metadata": { + "extension": ".tif", + "site": "1", + "channel": "1", + "timepoint": "1", + "well": "A01", + "OpenHCSSourceVoxelSpacingZYX": "2,0.65000000000000002,0.65000000000000002", + "OpenHCSSourceVoxelSpacingUnit": "micrometers" + }, + "image_metadata": { + "source_voxel_spacing": { + "values_zyx": [ + 2.0, + 0.65, + 0.65 + ], + "unit": "micrometers" + }, + "source_spatial_domain": { + "origin_yx": null, + "source_shape_yx": null, + "fill_value": 0, + "value_name": "Dense array", + "spatial_dimensions": 2 + }, + "source_provenance": { + "source_path": null, + "source_component_metadata": { + "well": "A01", + "site": "1", + "channel": "1", + "timepoint": "1", + "extension": ".tif" + }, + "source_image_provenance_planes": [ + { + "path": "/var/tmp/openhcs-publication435-aggregate-red5-20261004/test_saved_roles_publish_once_0/physical_source/A01_s001_w1_z000_t001.tif", + "component_metadata": { + "well": "A01", + "site": "1", + "channel": "1", + "z_index": "0", + "timepoint": "1", + "extension": ".tif" + }, + "identity_kind": "runtime_plane", + "source_image_name": "fixture_image_494", + "contributors": [] + }, + { + "path": "/var/tmp/openhcs-publication435-aggregate-red5-20261004/test_saved_roles_publish_once_0/physical_source/A01_s001_w1_z001_t001.tif", + "component_metadata": { + "well": "A01", + "site": "1", + "channel": "1", + "z_index": "1", + "timepoint": "1", + "extension": ".tif" + }, + "identity_kind": "runtime_plane", + "source_image_name": "fixture_image_494", + "contributors": [] + }, + { + "path": "/var/tmp/openhcs-publication435-aggregate-red5-20261004/test_saved_roles_publish_once_0/physical_source/A01_s001_w1_z002_t001.tif", + "component_metadata": { + "well": "A01", + "site": "1", + "channel": "1", + "z_index": "2", + "timepoint": "1", + "extension": ".tif" + }, + "identity_kind": "runtime_plane", + "source_image_name": "fixture_image_494", + "contributors": [] + }, + { + "path": "/var/tmp/openhcs-publication435-aggregate-red5-20261004/test_saved_roles_publish_once_0/physical_source/A01_s001_w1_z003_t001.tif", + "component_metadata": { + "well": "A01", + "site": "1", + "channel": "1", + "z_index": "3", + "timepoint": "1", + "extension": ".tif" + }, + "identity_kind": "runtime_plane", + "source_image_name": "fixture_image_494", + "contributors": [] + } + ], + "source_image_names": [ + "fixture_image_494" + ] + }, + "intensity_scale": 65535.0, + "source_dtype": "uint16", + "unit_interval_intensity": null, + "source_plane_intensity_scales": [ + 65535.0, + 65535.0, + 65535.0, + 65535.0 + ], + "source_plane_dtypes": [ + "uint16", + "uint16", + "uint16", + "uint16" + ], + "physical_border_edges_yx": null, + "mask_defines_border": null, + "source_channel_axis": 0, + "plane_axis": "runtime_slice" + } + } + ], + "pre_join_artifacts": [ + { + "virtual_path": "images/A01_s001_w1_z000_t001_fixture_image_494.tif", + "address": { + "site": "1", + "channel": "1", + "z_index": "0", + "timepoint": "1", + "well": "A01" + }, + "ref": { + "backend": "disk", + "backend_address": "images/A01_s001_w1_z000_t001_fixture_image_494.tif", + "source_axis_indices": [] + }, + "projection_role": "source_artifact", + "source_alias": "fixture_image_494", + "source_metadata": { + "well": "A01", + "site": "1", + "channel": "1", + "timepoint": "1", + "extension": ".tif", + "z_index": "0", + "OpenHCSSourceVoxelSpacingZYX": "2,0.65000000000000002,0.65000000000000002", + "OpenHCSSourceVoxelSpacingUnit": "micrometers" + }, + "execution_scope": { + "axis_id": "A01", + "component": "channel", + "value": "1", + "fixed_component_values": [ + [ + "site", + "1" + ], + [ + "timepoint", + "1" + ] + ] + }, + "artifact_kind": "image", + "image_metadata": { + "source_voxel_spacing": { + "values_zyx": [ + 2.0, + 0.65, + 0.65 + ], + "unit": "micrometers" + }, + "source_spatial_domain": { + "origin_yx": null, + "source_shape_yx": null, + "fill_value": 0, + "value_name": "Dense array", + "spatial_dimensions": 2 + }, + "source_provenance": { + "source_path": null, + "source_component_metadata": { + "well": "A01", + "site": "1", + "channel": "1", + "timepoint": "1", + "extension": ".tif", + "z_index": "0" + }, + "source_image_provenance_planes": [ + { + "path": "/var/tmp/openhcs-publication435-aggregate-red5-20261004/test_saved_roles_publish_once_0/physical_source/A01_s001_w1_z000_t001.tif", + "component_metadata": { + "well": "A01", + "site": "1", + "channel": "1", + "z_index": "0", + "timepoint": "1", + "extension": ".tif" + }, + "identity_kind": "runtime_plane", + "source_image_name": "fixture_image_494", + "contributors": [] + }, + { + "path": "/var/tmp/openhcs-publication435-aggregate-red5-20261004/test_saved_roles_publish_once_0/physical_source/A01_s001_w1_z001_t001.tif", + "component_metadata": { + "well": "A01", + "site": "1", + "channel": "1", + "z_index": "1", + "timepoint": "1", + "extension": ".tif" + }, + "identity_kind": "runtime_plane", + "source_image_name": "fixture_image_494", + "contributors": [] + }, + { + "path": "/var/tmp/openhcs-publication435-aggregate-red5-20261004/test_saved_roles_publish_once_0/physical_source/A01_s001_w1_z002_t001.tif", + "component_metadata": { + "well": "A01", + "site": "1", + "channel": "1", + "z_index": "2", + "timepoint": "1", + "extension": ".tif" + }, + "identity_kind": "runtime_plane", + "source_image_name": "fixture_image_494", + "contributors": [] + }, + { + "path": "/var/tmp/openhcs-publication435-aggregate-red5-20261004/test_saved_roles_publish_once_0/physical_source/A01_s001_w1_z003_t001.tif", + "component_metadata": { + "well": "A01", + "site": "1", + "channel": "1", + "z_index": "3", + "timepoint": "1", + "extension": ".tif" + }, + "identity_kind": "runtime_plane", + "source_image_name": "fixture_image_494", + "contributors": [] + } + ], + "source_image_names": [ + "fixture_image_494" + ] + }, + "intensity_scale": 65535.0, + "source_dtype": "uint16", + "unit_interval_intensity": null, + "source_plane_intensity_scales": [ + 65535.0, + 65535.0, + 65535.0, + 65535.0 + ], + "source_plane_dtypes": [ + "uint16", + "uint16", + "uint16", + "uint16" + ], + "physical_border_edges_yx": null, + "mask_defines_border": null, + "source_channel_axis": 0, + "plane_axis": "runtime_slice" + } + } + ], + "produced_records": [ + { + "component_values": { + "site": 1, + "channel": 1, + "timepoint": 1, + "well": "A01" + }, + "extension": ".tif", + "source": "multi-plane payload provenance over identity components ('z_index',)", + "filename_component_values": { + "site": 1, + "channel": 1, + "z_index": 0, + "timepoint": 1, + "well": "A01" + }, + "filename_qualifier": null, + "producer_identity": { + "origin": "pipeline", + "output_kind": "main", + "output_key": "fixture_image_494", + "projection_key": "main", + "step_name": "Derived role images", + "pipeline_position": 3, + "step_scope_id": "step-scope-3", + "invocation_key": null, + "artifact_kind": "image" + }, + "output_path": "/var/tmp/openhcs-publication435-aggregate-red5-20261004/test_saved_roles_publish_once_0/images/A01_s001_w1_z000_t001_fixture_image_494.tif", + "relative_output_path": "A01_s001_w1_z000_t001_fixture_image_494.tif", + "image_metadata": { + "source_voxel_spacing": { + "values_zyx": [ + 2.0, + 0.65, + 0.65 + ], + "unit": "micrometers" + }, + "source_spatial_domain": { + "origin_yx": null, + "source_shape_yx": null, + "fill_value": 0, + "value_name": "Dense array", + "spatial_dimensions": 2 + }, + "source_provenance": { + "source_path": null, + "source_component_metadata": { + "well": "A01", + "site": "1", + "channel": "1", + "timepoint": "1", + "extension": ".tif" + }, + "source_image_provenance_planes": [ + { + "path": "/var/tmp/openhcs-publication435-aggregate-red5-20261004/test_saved_roles_publish_once_0/physical_source/A01_s001_w1_z000_t001.tif", + "component_metadata": { + "well": "A01", + "site": "1", + "channel": "1", + "z_index": "0", + "timepoint": "1", + "extension": ".tif" + }, + "identity_kind": "runtime_plane", + "source_image_name": "fixture_image_494", + "contributors": [] + }, + { + "path": "/var/tmp/openhcs-publication435-aggregate-red5-20261004/test_saved_roles_publish_once_0/physical_source/A01_s001_w1_z001_t001.tif", + "component_metadata": { + "well": "A01", + "site": "1", + "channel": "1", + "z_index": "1", + "timepoint": "1", + "extension": ".tif" + }, + "identity_kind": "runtime_plane", + "source_image_name": "fixture_image_494", + "contributors": [] + }, + { + "path": "/var/tmp/openhcs-publication435-aggregate-red5-20261004/test_saved_roles_publish_once_0/physical_source/A01_s001_w1_z002_t001.tif", + "component_metadata": { + "well": "A01", + "site": "1", + "channel": "1", + "z_index": "2", + "timepoint": "1", + "extension": ".tif" + }, + "identity_kind": "runtime_plane", + "source_image_name": "fixture_image_494", + "contributors": [] + }, + { + "path": "/var/tmp/openhcs-publication435-aggregate-red5-20261004/test_saved_roles_publish_once_0/physical_source/A01_s001_w1_z003_t001.tif", + "component_metadata": { + "well": "A01", + "site": "1", + "channel": "1", + "z_index": "3", + "timepoint": "1", + "extension": ".tif" + }, + "identity_kind": "runtime_plane", + "source_image_name": "fixture_image_494", + "contributors": [] + } + ], + "source_image_names": [ + "fixture_image_494" + ] + }, + "intensity_scale": null, + "source_dtype": null, + "unit_interval_intensity": null, + "source_plane_intensity_scales": [ + null, + null, + null, + null + ], + "source_plane_dtypes": [ + null, + null, + null, + null + ], + "physical_border_edges_yx": null, + "mask_defines_border": null, + "source_channel_axis": null, + "plane_axis": "runtime_slice" + }, + "main_flow_plane_axis": "runtime_slice" + } + ] +} \ No newline at end of file diff --git a/docs/refactor/receipts/installed-consumers-419-435-450-20261004/README.rst b/docs/refactor/receipts/installed-consumers-419-435-450-20261004/README.rst new file mode 100644 index 0000000000..a6ca168749 --- /dev/null +++ b/docs/refactor/receipts/installed-consumers-419-435-450-20261004/README.rst @@ -0,0 +1,96 @@ +Installed saved-pipeline consumer acceptance +========================================== + +``receipt.json`` is the unmodified successful fresh-reader receipt, SHA256 +``67ded2d57e6a7dd10a742ed6e7410851e9d88a0ab329682586cb60e73c09feb5``. +The saved-label execution and readback use OpenHCS source +``769ecb806e59db36ef3f83b20a40c701cf578dc9`` (integrated as +``cc4461bc8a58c90c2ae13a5dd3870a67e1d8fc0a``), the canonical virtualenv and +current editable dependencies, including ZMQRuntime ``be67b58``. Source freezes +retain actual dependency commits, tracked-file hashes, installed distributions, +Python/native identities, input hashes and environment overrides. No module +shims, canonical installation changes or foreign server adoption were used. + +Actual production consumers +--------------------------- + +* #435: the original five processing-step ASTs are unchanged. Only output roots + and the unused DAPI binding were adapted for one physical C2 synthetic source. + The public saved/reopened pipeline compiled and executed at ``ba522b7da`` + (tracked source equal to receiving root ``e6ef8f1d1``). Both 1024 x 1024 float32 + raw/capped roles pass complete-pixel comparisons with the existing + CellProfiler comparison owner and tolerances, public inventory/sample and + a fresh MCP SDK process reopen. Physical C2 and XY1.3556 micrometers survive; + exactly one projection per role and distinct virtual paths remain. Inspection + correctly reports PARTIAL solely because no plate grid was declared. +* #419: the actual registered IPO produced saved 32 x 32 object labels with + object areas 25 and 12 at ``ba522b7da``. A new canonical saved/reopened public + four-step pipeline then used those exact persisted labels for registered + MeasureObjectSizeShape and Morph DISTANCE. It compiled/executed COMPLETE; + the two 2-D area rows are 25 and 12, with no Volume column, and the complete + distance pixels match the independent EDT oracle. The original biological + input and original #419 authored pipeline files are unavailable locally. + This is installed registered-contract acceptance, not original biological + replay or proof of the author's scientific inference. +* #450: the same public pipeline exercises prepared Resize followed by an + ImageMath consumer. Both complete 64 x 64 float32 outputs equal the expected + nearest-neighbor resize and retain C2, source identity and source calibration. + This supplements, rather than replaces, the separate qualified original 3-D + scientific comparison and prepared-contract controls. + +Source and publication laws +--------------------------- + +The real saved-label source-admission failure occurred after valid typed role +selection: primary image and object aliases of the same physical file received +unequal fallback identities from different virtual positions. The existing +``SourceBindingMatchedImageSet`` now uses ``source_path_for(candidate)`` only +for the fallback identity. Metadata-key precedence and independent typed anchor +positions remain. Eighteen focused identity/selection controls pass; same-basename +files at distinct physical paths remain different sources. + +Resize calls ``ImagePayloadMetadata.with_spatial_resize``: it updates the local +source-domain shape/origin and border/mask facts, retaining original source pitch +1.3556 micrometers. It does not rescale source calibration to 0.6778. The terminal +consumer legitimately has a PRIMARY_PLANE publication in ``images/`` and an +independent SOURCE_ARTIFACT checkpoint publication in ``checkpoints_step3/``. +The reader admits the primary role through durable projection metadata and +independently checks both occurrences' complete pixels and public samples; +unique virtual-path and projection cardinality checks remain. + +Evidence preservation and reproduction +-------------------------------------- + +The accepted readback used only health, inspect, query and sample tools: no +runtime startup, compile, processing replay or mutating job retry. All runtime +and MCP children are terminal. ``output_files_before`` and ``output_files_after`` +contain identical SHA256 inventories for all 29 retained outputs. Original +journeys and failed checkers also retain identical hashes. The archived v7 +journey remains RED for its wrong resized-source-pitch expectation; the first +readback remains RED for demanding a single occurrence across distinct roles. +The separate successful receipt corrects those inspection assumptions without +changing outputs, science gates or original failures. + +``original-evidence.tar.gz`` contains byte-exact v2/v3/v7 source freezes, +controllers and journeys, plus the failed readback controller/receipt. +The three small saved pipeline files and final ``readback.py`` are included +separately. Pixel datasets and native binaries are retained at the receipt's +local paths and are not copied into this packet. Controllers are historical, +self-validating source/host-bound commands; their absolute paths were not rewritten +for publication. Their exact original commands were:: + + taskset -c 3 /home/ts/code/projects/openhcs/.venv/bin/python -B /var/tmp/run_public_installed_consumers_419_435_450_v2_20261004.py --run + taskset -c 3 /home/ts/code/projects/openhcs/.venv/bin/python -B /var/tmp/run_public_installed_consumers_419_435_450_v3_20261004.py --run + taskset -c 3 /home/ts/code/projects/openhcs/.venv/bin/python -B /var/tmp/run_public_installed_consumers_419_435_450_v7_20261004.py --run + /home/ts/code/projects/openhcs/.venv/bin/python -B /var/tmp/read_public_installed_consumers_419_435_450_v7_v2_20261004.py + +Controller SHA256 values, respectively: + +* v2: ``36d95e77443e4918d19b269e72fcf1d578cf5f0eed3d0c502fc7d67f2c544167`` +* v3: ``a341a0f74a61d6f21e588ed1b158f5110dc146581e91f60c6254060bd1a66b27`` +* v7: ``733ba0c91ad79a01702708fc899ff5c1a3ff24a3bcb2c5a5ab31609010551bbe`` +* accepted reader: see ``helper_sha256`` in ``receipt.json``. + +This packet makes no performance, full-catalog, scaling, #433 OOM-cause or +repeated-ready-server stability claim. It does not close unrelated graph/viewer +or analysis-unit receiving obligations. diff --git a/docs/refactor/receipts/installed-consumers-419-435-450-20261004/original-evidence.tar.gz b/docs/refactor/receipts/installed-consumers-419-435-450-20261004/original-evidence.tar.gz new file mode 100644 index 0000000000..b004e89a21 Binary files /dev/null and b/docs/refactor/receipts/installed-consumers-419-435-450-20261004/original-evidence.tar.gz differ diff --git a/docs/refactor/receipts/installed-consumers-419-435-450-20261004/original-five-step-435-saved-pipeline.py b/docs/refactor/receipts/installed-consumers-419-435-450-20261004/original-five-step-435-saved-pipeline.py new file mode 100644 index 0000000000..51dafe95f3 --- /dev/null +++ b/docs/refactor/receipts/installed-consumers-419-435-450-20261004/original-five-step-435-saved-pipeline.py @@ -0,0 +1,240 @@ +# OpenHCS pipeline + +from openhcs.constants.constants import ( + AllComponents, + GroupBy, + Microscope, + VariableComponents, +) +from openhcs.constants.input_source import InputSource +from openhcs.core.config import ( + LazyNapariStreamingConfig, + LazyPathPlanningConfig, + LazyProcessingConfig, + LazyStepMaterializationConfig, + LazyTiffConfig, + LazyWellFilterConfig, + PipelineConfig, +) +from openhcs.core.source_bindings import ( + ComponentSelector, + LazySourceBindingsConfig, + LazyStepSourceBindingsConfig, + NamedSourceBinding, + SourceFilterClause, + SourceFilterMatchType, + SourceFilterSubject, + SourceSelector, +) +from openhcs.core.source_metadata import SourceVoxelSpacing +from openhcs.core.steps.function_step import FunctionStep +from openhcs.processing.backends.cellprofiler.color import ( + GrayToColorModule, + ImageChannelType, +) +from openhcs.processing.backends.cellprofiler.image_math import ImageMathOperation +from openhcs.processing.func_registry import get_function +from pathlib import Path +from polystore.config import TiffCompression + +path_root = Path('/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs') + +pipeline_config = PipelineConfig( + materialization_results_path=path_root / 'input_openhcs' / 'results', + materialize_runtime_artifacts=True, + num_workers=1, + microscope=Microscope.SOURCE_BINDINGS, + use_threading=False, + well_filter_config=LazyWellFilterConfig( + well_filter='A01' + ), + tiff_config=LazyTiffConfig( + compression=TiffCompression.DEFLATE, + compression_level=9 + ), + source_bindings_config=LazySourceBindingsConfig( + bindings=( + NamedSourceBinding( + alias='FITC', + selector=SourceSelector( + filters=( + SourceFilterClause( + subject=SourceFilterSubject.FILE, + match_type=SourceFilterMatchType.EQUALS, + value='A01_s001_w2_z001_t001.tif' + ), + ) + ), + component_identity=( + ComponentSelector( + component=AllComponents.WELL, + value='A01' + ), + ComponentSelector( + component=AllComponents.SITE, + value='1' + ), + ComponentSelector( + component=AllComponents.CHANNEL, + value='2' + ), + ComponentSelector( + component=AllComponents.Z_INDEX, + value='1' + ), + ComponentSelector( + component=AllComponents.TIMEPOINT, + value='1' + ) + ) + ), + ), + source_voxel_spacing=SourceVoxelSpacing( + values_zyx=( + 1.3556, + 1.3556 + ) + ) + ), + path_planning_config=LazyPathPlanningConfig( + well_filter='A01', + global_output_folder=path_root + ), + step_materialization_config=LazyStepMaterializationConfig( + well_filter='A01', + enabled=False + ), + napari_streaming_config=LazyNapariStreamingConfig( + enabled=False + ) +) + +pipeline_steps = [ + FunctionStep( + func=(get_function('openhcs:cellprofiler_image_math'), { + 'operation': ImageMathOperation.NONE, + 'factors': ( + 1.0, + ), + 'truncate_low': False, + 'truncate_high': False, + 'select_the_first_image': 'FITC', + 'name_the_output_image': 'raw_calcein_body_reference' + }), + name='RawCalceinNamedIdentityContractProbe', + processing_config=LazyProcessingConfig( + variable_components=[ + VariableComponents.CHANNEL + ], + group_by=GroupBy.NONE, + input_source=InputSource.PIPELINE_START + ), + source_bindings=LazyStepSourceBindingsConfig( + enabled=True, + bindings=( + NamedSourceBinding( + alias='FITC' + ), + ) + ), + napari_streaming_config=LazyNapariStreamingConfig( + enabled=False + ) + ), + FunctionStep( + func=(get_function('skimage:exposure.rescale_intensity'), { + 'in_range': ( + 0.0005951018539711605, + 0.09155413138017852 + ), + 'out_range': ( + 0.0, + 1.0 + ) + }), + name='CapOnlyOutgrowthLaneAtOriginal6000Counts', + processing_config=LazyProcessingConfig( + variable_components=[ + VariableComponents.CHANNEL + ], + group_by=GroupBy.NONE, + input_source=InputSource.PREVIOUS_STEP + ), + napari_streaming_config=LazyNapariStreamingConfig( + enabled=False + ) + ), + FunctionStep( + func=(get_function('openhcs:cellprofiler_image_math'), { + 'operation': ImageMathOperation.NONE, + 'factors': ( + 1.0, + ), + 'truncate_low': False, + 'truncate_high': False, + 'name_the_output_image': 'capped_calcein_outgrowth' + }), + name='NameCappedScalarCalcein', + processing_config=LazyProcessingConfig( + variable_components=[ + VariableComponents.CHANNEL + ], + group_by=GroupBy.NONE, + input_source=InputSource.PREVIOUS_STEP + ), + napari_streaming_config=LazyNapariStreamingConfig( + enabled=False + ) + ), + FunctionStep( + func=(get_function('openhcs:cellprofiler_gray_to_color'), { + 'color_scheme': GrayToColorModule.Scheme.STACK, + 'rescale_intensity': False, + 'image_name': ( + 'raw_calcein_body_reference', + 'capped_calcein_outgrowth' + ), + 'name_the_output_image': 'raw_and_cap_channel_last' + }), + name='ComposeDeclaredScalarRawAndCappedArtifacts', + processing_config=LazyProcessingConfig( + variable_components=[ + VariableComponents.CHANNEL + ], + group_by=GroupBy.NONE, + input_source=InputSource.PREVIOUS_STEP + ), + napari_streaming_config=LazyNapariStreamingConfig( + enabled=False + ) + ), + FunctionStep( + func=(get_function('openhcs:cellprofiler_color_to_gray'), { + 'image_type': ImageChannelType.CHANNELS, + 'channel_indices': ( + 0, + 1 + ), + 'contributions': ( + 1.0, + 1.0 + ), + 'select_the_input_image': 'raw_and_cap_channel_last', + 'image_name': ( + 'raw_body_processing_role', + 'capped_outgrowth_processing_role' + ) + }), + name='ProjectColorChannelsToAlignedProcessingRoles', + processing_config=LazyProcessingConfig( + variable_components=[ + VariableComponents.CHANNEL + ], + group_by=GroupBy.NONE, + input_source=InputSource.PREVIOUS_STEP + ), + napari_streaming_config=LazyNapariStreamingConfig( + enabled=False + ) + ) +] \ No newline at end of file diff --git a/docs/refactor/receipts/installed-consumers-419-435-450-20261004/produce-saved-ipo-saved-pipeline.py b/docs/refactor/receipts/installed-consumers-419-435-450-20261004/produce-saved-ipo-saved-pipeline.py new file mode 100644 index 0000000000..981d2281f4 --- /dev/null +++ b/docs/refactor/receipts/installed-consumers-419-435-450-20261004/produce-saved-ipo-saved-pipeline.py @@ -0,0 +1,173 @@ +# OpenHCS pipeline + +from openhcs.constants.constants import ( + AllComponents, + GroupBy, + Microscope, + VariableComponents, +) +from openhcs.constants.input_source import InputSource +from openhcs.core.config import ( + LazyAnalysisConsolidationConfig, + LazyCompilationDebugConfig, + LazyDtypeConfig, + LazyFijiDisplayConfig, + LazyFijiStreamingConfig, + LazyNapariDisplayConfig, + LazyNapariStreamingConfig, + LazyPathPlanningConfig, + LazyPlateMetadataConfig, + LazyProcessingConfig, + LazySequentialProcessingConfig, + LazyStepMaterializationConfig, + LazyStepWellFilterConfig, + LazyStreamingDefaults, + LazyTiffConfig, + LazyVFSConfig, + LazyWellFilterConfig, + LazyZarrConfig, + MultiprocessingStartMethod, + PipelineConfig, +) +from openhcs.core.source_bindings import ( + ComponentSelector, + LazySourceBindingsConfig, + LazyStepSourceBindingsConfig, + NamedSourceBinding, + SourceFilterClause, + SourceFilterMatchType, + SourceFilterSubject, + SourceSelector, +) +from openhcs.core.source_metadata import SourceVoxelSpacing +from openhcs.core.source_spatial_domain import SourceSpatialDomain +from openhcs.core.steps.function_step import FunctionStep +from openhcs.processing.backends.cellprofiler.primary_objects import ( + UnclumpMethod, + WatershedMethod, +) +from openhcs.processing.backends.cellprofiler.thresholding import CellProfilerThresholdMethod +from openhcs.processing.func_registry import get_function +from pathlib import Path +from polystore.config import TiffCompression + +pipeline_config = PipelineConfig( + materialization_results_path=Path('results'), + materialize_runtime_artifacts=True, + num_workers=1, + microscope=Microscope.SOURCE_BINDINGS, + use_threading=False, + multiprocessing_start_method=MultiprocessingStartMethod.SPAWN, + auto_add_output_plate_to_plate_manager=False, + napari_display_config=LazyNapariDisplayConfig(), + fiji_display_config=LazyFijiDisplayConfig(), + well_filter_config=LazyWellFilterConfig( + well_filter='A01' + ), + zarr_config=LazyZarrConfig(), + tiff_config=LazyTiffConfig( + compression=TiffCompression.DEFLATE, + compression_level=9 + ), + vfs_config=LazyVFSConfig(), + dtype_config=LazyDtypeConfig(), + processing_config=LazyProcessingConfig(), + source_bindings_config=LazySourceBindingsConfig( + metadata_rules=(), + metadata_fields=(), + source_filters=(), + bindings=( + NamedSourceBinding( + alias='FITC', + selector=SourceSelector( + filters=( + SourceFilterClause( + subject=SourceFilterSubject.FILE, + match_type=SourceFilterMatchType.EQUALS, + value='A01_s001_w2_z001_t001.tif' + ), + ) + ), + component_identity=( + ComponentSelector( + component=AllComponents.WELL, + value='A01' + ), + ComponentSelector( + component=AllComponents.SITE, + value='1' + ), + ComponentSelector( + component=AllComponents.CHANNEL, + value='2' + ), + ComponentSelector( + component=AllComponents.Z_INDEX, + value='1' + ), + ComponentSelector( + component=AllComponents.TIMEPOINT, + value='1' + ) + ) + ), + ), + image_plane_sources=(), + imported_metadata_tables=(), + source_stack_components=(), + source_spatial_domain=SourceSpatialDomain(), + grouping_metadata_fields=(), + source_voxel_spacing=SourceVoxelSpacing( + values_zyx=( + 1.3556, + 1.3556 + ) + ) + ), + step_source_bindings_config=LazyStepSourceBindingsConfig(), + sequential_processing_config=LazySequentialProcessingConfig(), + analysis_consolidation_config=LazyAnalysisConsolidationConfig(), + plate_metadata_config=LazyPlateMetadataConfig(), + path_planning_config=LazyPathPlanningConfig( + well_filter='A01', + global_output_folder=Path('/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v3/outputs/ipo') + ), + step_well_filter_config=LazyStepWellFilterConfig(), + step_materialization_config=LazyStepMaterializationConfig( + well_filter='A01', + enabled=True + ), + streaming_defaults=LazyStreamingDefaults(), + napari_streaming_config=LazyNapariStreamingConfig( + enabled=False + ), + fiji_streaming_config=LazyFijiStreamingConfig(), + compilation_debug_config=LazyCompilationDebugConfig() +) + +pipeline_steps = [ + FunctionStep( + func=(get_function('openhcs:cellprofiler_identify_primary_objects'), { + 'exclude_size': False, + 'exclude_border_objects': False, + 'unclump_method': UnclumpMethod.NONE, + 'watershed_method': WatershedMethod.NONE, + 'threshold_method': CellProfilerThresholdMethod.MANUAL, + 'threshold_smoothing_scale': 0.0, + 'manual_threshold': 0.5, + 'select_the_input_image': 'FITC', + 'name_the_primary_objects_to_be_identified': 'SavedIPO' + }), + name='ProduceSavedIPO', + processing_config=LazyProcessingConfig( + variable_components=[ + VariableComponents.CHANNEL + ], + group_by=GroupBy.NONE, + input_source=InputSource.PIPELINE_START + ), + source_bindings=LazyStepSourceBindingsConfig( + enabled=True + ) + ) +] \ No newline at end of file diff --git a/docs/refactor/receipts/installed-consumers-419-435-450-20261004/readback.py b/docs/refactor/receipts/installed-consumers-419-435-450-20261004/readback.py new file mode 100644 index 0000000000..4bb85ca44b --- /dev/null +++ b/docs/refactor/receipts/installed-consumers-419-435-450-20261004/readback.py @@ -0,0 +1,108 @@ +"""Read-only fresh public SDK acceptance; original failed receipt is immutable.""" +from __future__ import annotations +import ast, asyncio, hashlib, importlib.util, json, os, subprocess, sys, time, traceback +from pathlib import Path +from csv import DictReader +CONTROLLER = Path('/var/tmp/run_public_installed_consumers_419_435_450_v7_20261004.py') +EVIDENCE = Path('/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7-readback-v2') +def sha(path): return hashlib.sha256(Path(path).read_bytes()).hexdigest() +spec=importlib.util.spec_from_file_location('frozen_v7_controller',CONTROLLER) +original=importlib.util.module_from_spec(spec); spec.loader.exec_module(original) +freeze=json.loads((original.OUTPUT/'source-freeze.json').read_text()) +original.validate(freeze) +journey=json.loads((original.OUTPUT/'journey.json').read_text()) +assert not journey['accepted'] and journey['failure']['type']=='AssertionError' +assert journey['owned_runtime_terminal'] and journey['mcp_children_terminal'] +for key in ('compile','execution'): + state=journey['installed_cases']['saved-label-geometry-distance-resize'][key] + assert state['status']=='complete' and not state['errors'], state +if '--worker' not in sys.argv: + EVIDENCE.mkdir(exist_ok=False) + with (EVIDENCE/'controller.log').open('x') as output: + result=subprocess.run(['/usr/bin/taskset','-c','3',str(original.PYTHON),'-B',__file__,'--worker'],cwd='/var/tmp',env=original.environment(),stdout=output,stderr=subprocess.STDOUT,timeout=300) + print(json.dumps({'returncode':result.returncode,'receipt':str(EVIDENCE/'receipt.json')})) + sys.exit(result.returncode) +sys.path.insert(0,str(original.SOURCE)) +import openhcs +assert Path(openhcs.__file__).resolve()==original.SOURCE/'openhcs/__init__.py' +import numpy as np, tifffile +from scipy.ndimage import distance_transform_edt +from openhcs.mcp.dev_client_core import McpDevServerSpec, McpDevStdioSession, McpDevToolResult +from openhcs.serialization.json import to_jsonable +from openhcs.core.artifacts import ImageArtifactType +from openhcs.core.virtual_workspace_metadata import METADATA_CONFIG +from benchmark.cellprofiler_reference_exports import CellProfilerReferenceExportArtifact, CellProfilerReferenceArtifactComparison +roots=(original.PRIOR/'outputs',original.IPO_PRIOR/'outputs',original.OUTPUT/'outputs') +def inventory(): return {str(p):sha(p) for root in roots for p in sorted(root.rglob('*')) if p.is_file()} +immutable_paths=(CONTROLLER, original.OUTPUT/'journey.json',original.OUTPUT/'source-freeze.json',original.PRIOR/'journey.json',original.IPO_PRIOR/'journey.json',Path('/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7-readback/receipt.json')) +immutable={str(p):sha(p) for p in immutable_paths} +receipt=dict(journey) +receipt.update(accepted=False,scope='Read-only fresh MCP SDK acceptance of immutable original435, public IPO and saved Shape/DISTANCE/prepared Resize consumer outputs. No runtime startup or processing replay. Original v7 failed checker receipt retained.',failure=None,calls=[],readers=[],original_failure=journey['failure'],original_journey=str(original.OUTPUT/'journey.json'),immutable_before=immutable,output_files_before=inventory(),helper_sha256=sha(__file__),calibration_correction={'reason':'ResizeGeometry.resize_payload uses ImagePayloadMetadata.with_spatial_resize, which changes only local SourceSpatialDomain and border/mask facts. Original source calibration remains unchanged; no calibration rescale is part of the existing contract.','source_files':{rel:sha(original.SOURCE/rel) for rel in ('openhcs/core/runtime_image_values.py','openhcs/core/source_spatial_domain.py','openhcs/processing/backends/cellprofiler/image_geometry.py','tests/unit/test_cellprofiler_resize_hotpath.py')}}) +def save(): (EVIDENCE/'receipt.json').write_text(json.dumps(receipt,indent=2)+'\n') +allowed={'openhcs_health_check','openhcs_inspect_plate_path','openhcs_query_plate_files','openhcs_sample_plate_image'} +async def call(session,name,arguments): + assert name in allowed + raw=await session.call_tool(name,arguments,timeout_seconds=30) + decoded=McpDevToolResult.from_payload(name,raw) + assert not decoded.has_errors(),to_jsonable(decoded.diagnostic_errors()) + result=to_jsonable(decoded.first_decoded_payload()); assert isinstance(result,dict) + receipt['calls'].append({'tool':name,'arguments':arguments,'response':raw}); save() + return result +# Reuse the exact original complete-pixel/public-inventory readers. The only +# correction is the rejected checker assumption about source calibration. +tree=ast.parse(CONTROLLER.read_text()) +worker=next(node for node in tree.body if isinstance(node,ast.AsyncFunctionDef) and node.name=='worker') +namespace=globals()|{'OUTPUT':original.OUTPUT,'PRIOR':original.PRIOR,'ALIASES':original.ALIASES} +for name in ('inspect_outputs','inspect_saved_case'): + node=next(node for node in worker.body if isinstance(node,ast.AsyncFunctionDef) and node.name==name) + source=ast.unparse(node) + if name=='inspect_saved_case': + old="wanted = 1.3556 if alias == 'SavedDistance' else 0.6778" + assert source.count(old)==1 + source=source.replace(old,'wanted = 1.3556') + old_cardinality = "assert len(records) == 1, (alias, records, inventory)\n record = records[0]" + assert source.count(old_cardinality)==1 + source=source.replace(old_cardinality, """document = json.loads(METADATA_CONFIG.metadata_path(root).read_text()) + projection_rows = [row for directory in document['subdirectories'].values() for row in directory.get('source_projection', []) if '_' + alias in Path(row['virtual_path']).stem] + assert len(records) == len(projection_rows), (alias, records, projection_rows) + primary_paths = {row['virtual_path'] for row in projection_rows if row['projection_role'] == 'primary_plane'} + primary_records = [record for record in records if record['virtual_path'] in primary_paths] + assert len(primary_records) == 1, (alias, records, projection_rows) + for occurrence in records: + physical = tifffile.imread(Path(occurrence['source_path'])) + np.testing.assert_allclose(physical, pixels, rtol=1e-6, atol=1e-6) + assert physical.shape == pixels.shape and physical.dtype == np.float32 + occurrence_sample = await call(session, 'openhcs_sample_plate_image', {'plate_path': str(root), 'image_path': occurrence['virtual_path'], 'microscope_type': 'auto', 'y': 0, 'x': 0, 'height': 2, 'width': 2, 'max_array_elements': 4, 'include_array_values': True}) + assert tuple(occurrence_sample['shape']) == pixels.shape and occurrence_sample['sample_included'] + np.testing.assert_array_equal(np.asarray(occurrence_sample['sample_values'], dtype=np.float32).reshape(2,2), physical[:2,:2]) + record = primary_records[0]""") + exec(compile(source,str(CONTROLLER)+'::'+name,'exec'),namespace) +async def readback(): + children=[] + try: + with (EVIDENCE/'fresh-reader-stderr.log').open('x') as stderr: + async with McpDevStdioSession(McpDevServerSpec(str(original.PYTHON)),stderr) as session: + process=session.require_process(); children.append(process) + receipt['readers'].append({'pid':process.pid,'source':str(original.SOURCE)}) + await session.initialize(timeout_seconds=180) + await session.list_tools(timeout_seconds=180) + health=await call(session,'openhcs_health_check',{}) + assert Path(health['server_source_path']).resolve()==original.SOURCE/'openhcs/mcp/server.py' + assert not health['errors'] and not health['restart_required'] + observed=await namespace['inspect_outputs'](session,'fresh_process_reopen') + prior=journey['first_public_readback'] + assert observed==(prior['inventory'],prior['samples']) + await namespace['inspect_saved_case'](session,'fresh_process_reopen') + original.validate(freeze) + assert {str(p):sha(p) for p in immutable_paths}==immutable + after=inventory(); assert after==receipt['output_files_before'] + receipt['output_files_after']=after + receipt['accepted']=True + except BaseException as error: + receipt['failure']={'type':type(error).__name__,'message':str(error),'traceback':traceback.format_exc()} + raise + finally: + receipt['reader_processes_terminal']=all(child.returncode is not None for child in children) + receipt['reader_returncodes']=[child.returncode for child in children] + save() +asyncio.run(readback()) diff --git a/docs/refactor/receipts/installed-consumers-419-435-450-20261004/receipt.json b/docs/refactor/receipts/installed-consumers-419-435-450-20261004/receipt.json new file mode 100644 index 0000000000..94e673d5df --- /dev/null +++ b/docs/refactor/receipts/installed-consumers-419-435-450-20261004/receipt.json @@ -0,0 +1,6036 @@ +{ + "accepted": true, + "scope": "Read-only fresh MCP SDK acceptance of immutable original435, public IPO and saved Shape/DISTANCE/prepared Resize consumer outputs. No runtime startup or processing replay. Original v7 failed checker receipt retained.", + "head": "769ecb806e59db36ef3f83b20a40c701cf578dc9", + "calls": [ + { + "tool": "openhcs_health_check", + "arguments": {}, + "response": { + "content": [ + { + "type": "text", + "text": "{\n \"schema_version\": \"openhcs.agent.v1\",\n \"errors\": [],\n \"warnings\": [],\n \"status\": \"ok\",\n \"started_at_unix\": 1791085056.084627,\n \"service\": \"openhcs.mcp\",\n \"openhcs_version\": \"0.8.7\",\n \"packaged_resources_ready\": true,\n \"packaged_resource_count\": 86,\n \"missing_packaged_resource_paths\": [],\n \"server_process_id\": 3790248,\n \"server_source_path\": \"/var/tmp/openhcs-resolved-pipeline-owner-20261004/openhcs/mcp/server.py\",\n \"server_import_mtime_ns\": 1791076987318725938,\n \"server_current_mtime_ns\": 1791076987318725938,\n \"server_source_changed_since_import\": false,\n \"stale_source_paths\": [],\n \"recovery_reason\": \"current\",\n \"installation_pointer_path\": null,\n \"installation_pointer_changed_since_import\": false,\n \"installation_pointer_available\": null,\n \"restart_required\": false,\n \"restart_command\": [],\n \"restart_command_is_stable\": false,\n \"reconnect_required\": false,\n \"reconnect_owner\": null,\n \"retry_after_reconnect\": false,\n \"automatic_recovery_on_reconnect\": false,\n \"restart_hint\": null\n}" + } + ], + "structuredContent": { + "schema_version": "openhcs.agent.v1", + "errors": [], + "warnings": [], + "status": "ok", + "started_at_unix": 1791085056.084627, + "service": "openhcs.mcp", + "openhcs_version": "0.8.7", + "packaged_resources_ready": true, + "packaged_resource_count": 86, + "missing_packaged_resource_paths": [], + "server_process_id": 3790248, + "server_source_path": "/var/tmp/openhcs-resolved-pipeline-owner-20261004/openhcs/mcp/server.py", + "server_import_mtime_ns": 1791076987318725938, + "server_current_mtime_ns": 1791076987318725938, + "server_source_changed_since_import": false, + "stale_source_paths": [], + "recovery_reason": "current", + "installation_pointer_path": null, + "installation_pointer_changed_since_import": false, + "installation_pointer_available": null, + "restart_required": false, + "restart_command": [], + "restart_command_is_stable": false, + "reconnect_required": false, + "reconnect_owner": null, + "retry_after_reconnect": false, + "automatic_recovery_on_reconnect": false, + "restart_hint": null + }, + "isError": false + } + }, + { + "tool": "openhcs_inspect_plate_path", + "arguments": { + "plate_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs/input_openhcs", + "microscope_type": "auto" + }, + "response": { + "content": [ + { + "type": "text", + "text": "{\n \"schema_version\": \"openhcs.agent.v1\",\n \"errors\": [],\n \"warnings\": [\n {\n \"code\": \"plate_grid_dimensions_unavailable\",\n \"message\": \"'grid_dimensions' must be a list of two integers in openhcs_metadata.json\",\n \"hint\": null\n }\n ],\n \"plate_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs/input_openhcs\",\n \"requested_microscope_type\": \"auto\",\n \"status\": \"partial\",\n \"confidence\": \"high\",\n \"available_microscope_types\": [\n \"bioformats\",\n \"imagexpress\",\n \"omero\",\n \"openhcsdata\",\n \"opera_phenix\",\n \"source_bindings\"\n ],\n \"detected_microscope_type\": \"openhcsdata\",\n \"handler_class\": \"OpenHCSMicroscopeHandler\",\n \"parser_class\": \"SourceSchemaFilenameParser\",\n \"metadata_handler_class\": \"OpenHCSMetadataHandler\",\n \"root_dir\": \"\",\n \"compatible_backends\": [\n \"zarr\",\n \"disk\"\n ],\n \"available_backends\": [\n \"disk\"\n ],\n \"metadata_file_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs/input_openhcs/openhcs_metadata.json\",\n \"grid_dimensions\": null,\n \"pixel_size\": 1.3556,\n \"image_files\": {\n \"count\": 2,\n \"sampled_files\": [\n \"images/A01_s001_w2_z001_t001_capped_outgrowth_processing_role.tif\",\n \"images/A01_s001_w2_z001_t001_raw_body_processing_role.tif\"\n ],\n \"sampled_records\": [\n {\n \"virtual_path\": \"images/A01_s001_w2_z001_t001_capped_outgrowth_processing_role.tif\",\n \"full_virtual_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs/input_openhcs/images/A01_s001_w2_z001_t001_capped_outgrowth_processing_role.tif\",\n \"source_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs/input_openhcs/images/A01_s001_w2_z001_t001_capped_outgrowth_processing_role.tif\",\n \"metadata\": {\n \"filename\": \"images/A01_s001_w2_z001_t001_capped_outgrowth_processing_role.tif\",\n \"virtual_path\": \"images/A01_s001_w2_z001_t001_capped_outgrowth_processing_role.tif\",\n \"full_virtual_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs/input_openhcs/images/A01_s001_w2_z001_t001_capped_outgrowth_processing_role.tif\",\n \"source_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs/input_openhcs/images/A01_s001_w2_z001_t001_capped_outgrowth_processing_role.tif\",\n \"type\": \"Image\",\n \"OpenHCSSourceVoxelSpacingZYX\": \"1.3555999999999999,1.3555999999999999\",\n \"OpenHCSSourceVoxelSpacingUnit\": \"micrometers\",\n \"OpenHCSSourceFilterPaths\": {\n \"0\": \"A01_s001_w2_z001_t001.tif\",\n \"1\": \"/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/input/A01_s001_w2_z001_t001.tif\"\n },\n \"source_alias\": \"FITC\",\n \"extension\": \".tif\",\n \"site\": 1,\n \"channel\": 2,\n \"z_index\": 1,\n \"timepoint\": 1,\n \"well\": \"A01\",\n \"source_artifact_type\": \"image\",\n \"size\": \"351.2 KB\",\n \"modified\": \"2026-10-03T23:00:27\"\n }\n },\n {\n \"virtual_path\": \"images/A01_s001_w2_z001_t001_raw_body_processing_role.tif\",\n \"full_virtual_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs/input_openhcs/images/A01_s001_w2_z001_t001_raw_body_processing_role.tif\",\n \"source_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs/input_openhcs/images/A01_s001_w2_z001_t001_raw_body_processing_role.tif\",\n \"metadata\": {\n \"filename\": \"images/A01_s001_w2_z001_t001_raw_body_processing_role.tif\",\n \"virtual_path\": \"images/A01_s001_w2_z001_t001_raw_body_processing_role.tif\",\n \"full_virtual_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs/input_openhcs/images/A01_s001_w2_z001_t001_raw_body_processing_role.tif\",\n \"source_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs/input_openhcs/images/A01_s001_w2_z001_t001_raw_body_processing_role.tif\",\n \"type\": \"Image\",\n \"OpenHCSSourceVoxelSpacingZYX\": \"1.3555999999999999,1.3555999999999999\",\n \"OpenHCSSourceVoxelSpacingUnit\": \"micrometers\",\n \"OpenHCSSourceFilterPaths\": {\n \"0\": \"A01_s001_w2_z001_t001.tif\",\n \"1\": \"/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/input/A01_s001_w2_z001_t001.tif\"\n },\n \"source_alias\": \"FITC\",\n \"extension\": \".tif\",\n \"site\": 1,\n \"channel\": 2,\n \"z_index\": 1,\n \"timepoint\": 1,\n \"well\": \"A01\",\n \"source_artifact_type\": \"image\",\n \"size\": \"2.7 MB\",\n \"modified\": \"2026-10-03T23:00:27\"\n }\n }\n ],\n \"truncated_file_count\": 0\n },\n \"result_files\": {\n \"count\": 0,\n \"scanned_file_count\": 0,\n \"sampled_files\": [],\n \"sampled_records\": [],\n \"truncated_file_count\": 0\n },\n \"parse_summary\": {\n \"attempted_file_count\": 2,\n \"skipped_file_count\": 0,\n \"parsed_file_count\": 2,\n \"failed_file_count\": 0,\n \"failure_samples\": [],\n \"truncated_failure_count\": 0\n },\n \"components\": [\n {\n \"component\": \"site\",\n \"source\": \"metadata_and_parsed_filenames\",\n \"count\": 1,\n \"values\": [\n {\n \"key\": \"1\",\n \"label\": null,\n \"declared_in_metadata\": true,\n \"observed_in_filenames\": true\n }\n ],\n \"truncated_value_count\": 0\n },\n {\n \"component\": \"channel\",\n \"source\": \"metadata_and_parsed_filenames\",\n \"count\": 1,\n \"values\": [\n {\n \"key\": \"2\",\n \"label\": \"FITC\",\n \"declared_in_metadata\": true,\n \"observed_in_filenames\": true\n }\n ],\n \"truncated_value_count\": 0\n },\n {\n \"component\": \"z_index\",\n \"source\": \"metadata_and_parsed_filenames\",\n \"count\": 1,\n \"values\": [\n {\n \"key\": \"1\",\n \"label\": null,\n \"declared_in_metadata\": true,\n \"observed_in_filenames\": true\n }\n ],\n \"truncated_value_count\": 0\n },\n {\n \"component\": \"timepoint\",\n \"source\": \"metadata_and_parsed_filenames\",\n \"count\": 1,\n \"values\": [\n {\n \"key\": \"1\",\n \"label\": null,\n \"declared_in_metadata\": true,\n \"observed_in_filenames\": true\n }\n ],\n \"truncated_value_count\": 0\n },\n {\n \"component\": \"well\",\n \"source\": \"metadata_and_parsed_filenames\",\n \"count\": 1,\n \"values\": [\n {\n \"key\": \"A01\",\n \"label\": null,\n \"declared_in_metadata\": true,\n \"observed_in_filenames\": true\n }\n ],\n \"truncated_value_count\": 0\n }\n ],\n \"source_diagnostics\": [],\n \"format_specific_handler_candidates\": [],\n \"workspace_preparation\": {\n \"read_only_inspection\": true,\n \"required_before_execution\": false,\n \"operation\": \"none\",\n \"reason\": \"OpenHCS metadata is already present; read-only inspection did not need workspace preparation.\"\n },\n \"workflow_advice\": {\n \"workflow_scope\": \"diagnostic\",\n \"ingestion_route\": \"detected_handler\",\n \"ingestion_owner\": \"openhcsdata\",\n \"source_binding_role\": \"not_projected_by_handler\",\n \"ui_code_document_id\": \"plate_manager.orchestrator_config\",\n \"ui_operation\": \"init\",\n \"knowledge_query\": \"source model CZI Bio-Formats source bindings\",\n \"probable_native_ingestion_owners\": [],\n \"message\": \"Keep the detected openhcsdata handler as the ingestion owner. For a visible workflow, add the plate directory through the PlateManager code document and initialize with auto-detection. Use for a workspace already prepared by OpenHCS and carrying its metadata document. The recorded workspace metadata, not raw vendor filename resemblance, owns parser and backend selection. This handler does not project declared source bindings.\"\n }\n}" + } + ], + "structuredContent": { + "schema_version": "openhcs.agent.v1", + "errors": [], + "warnings": [ + { + "code": "plate_grid_dimensions_unavailable", + "message": "'grid_dimensions' must be a list of two integers in openhcs_metadata.json", + "hint": null + } + ], + "plate_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs/input_openhcs", + "requested_microscope_type": "auto", + "status": "partial", + "confidence": "high", + "available_microscope_types": [ + "bioformats", + "imagexpress", + "omero", + "openhcsdata", + "opera_phenix", + "source_bindings" + ], + "detected_microscope_type": "openhcsdata", + "handler_class": "OpenHCSMicroscopeHandler", + "parser_class": "SourceSchemaFilenameParser", + "metadata_handler_class": "OpenHCSMetadataHandler", + "root_dir": "", + "compatible_backends": [ + "zarr", + "disk" + ], + "available_backends": [ + "disk" + ], + "metadata_file_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs/input_openhcs/openhcs_metadata.json", + "grid_dimensions": null, + "pixel_size": 1.3556, + "image_files": { + "count": 2, + "sampled_files": [ + "images/A01_s001_w2_z001_t001_capped_outgrowth_processing_role.tif", + "images/A01_s001_w2_z001_t001_raw_body_processing_role.tif" + ], + "sampled_records": [ + { + "virtual_path": "images/A01_s001_w2_z001_t001_capped_outgrowth_processing_role.tif", + "full_virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs/input_openhcs/images/A01_s001_w2_z001_t001_capped_outgrowth_processing_role.tif", + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs/input_openhcs/images/A01_s001_w2_z001_t001_capped_outgrowth_processing_role.tif", + "metadata": { + "filename": "images/A01_s001_w2_z001_t001_capped_outgrowth_processing_role.tif", + "virtual_path": "images/A01_s001_w2_z001_t001_capped_outgrowth_processing_role.tif", + "full_virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs/input_openhcs/images/A01_s001_w2_z001_t001_capped_outgrowth_processing_role.tif", + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs/input_openhcs/images/A01_s001_w2_z001_t001_capped_outgrowth_processing_role.tif", + "type": "Image", + "OpenHCSSourceVoxelSpacingZYX": "1.3555999999999999,1.3555999999999999", + "OpenHCSSourceVoxelSpacingUnit": "micrometers", + "OpenHCSSourceFilterPaths": { + "0": "A01_s001_w2_z001_t001.tif", + "1": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/input/A01_s001_w2_z001_t001.tif" + }, + "source_alias": "FITC", + "extension": ".tif", + "site": 1, + "channel": 2, + "z_index": 1, + "timepoint": 1, + "well": "A01", + "source_artifact_type": "image", + "size": "351.2 KB", + "modified": "2026-10-03T23:00:27" + } + }, + { + "virtual_path": "images/A01_s001_w2_z001_t001_raw_body_processing_role.tif", + "full_virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs/input_openhcs/images/A01_s001_w2_z001_t001_raw_body_processing_role.tif", + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs/input_openhcs/images/A01_s001_w2_z001_t001_raw_body_processing_role.tif", + "metadata": { + "filename": "images/A01_s001_w2_z001_t001_raw_body_processing_role.tif", + "virtual_path": "images/A01_s001_w2_z001_t001_raw_body_processing_role.tif", + "full_virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs/input_openhcs/images/A01_s001_w2_z001_t001_raw_body_processing_role.tif", + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs/input_openhcs/images/A01_s001_w2_z001_t001_raw_body_processing_role.tif", + "type": "Image", + "OpenHCSSourceVoxelSpacingZYX": "1.3555999999999999,1.3555999999999999", + "OpenHCSSourceVoxelSpacingUnit": "micrometers", + "OpenHCSSourceFilterPaths": { + "0": "A01_s001_w2_z001_t001.tif", + "1": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/input/A01_s001_w2_z001_t001.tif" + }, + "source_alias": "FITC", + "extension": ".tif", + "site": 1, + "channel": 2, + "z_index": 1, + "timepoint": 1, + "well": "A01", + "source_artifact_type": "image", + "size": "2.7 MB", + "modified": "2026-10-03T23:00:27" + } + } + ], + "truncated_file_count": 0 + }, + "result_files": { + "count": 0, + "scanned_file_count": 0, + "sampled_files": [], + "sampled_records": [], + "truncated_file_count": 0 + }, + "parse_summary": { + "attempted_file_count": 2, + "skipped_file_count": 0, + "parsed_file_count": 2, + "failed_file_count": 0, + "failure_samples": [], + "truncated_failure_count": 0 + }, + "components": [ + { + "component": "site", + "source": "metadata_and_parsed_filenames", + "count": 1, + "values": [ + { + "key": "1", + "label": null, + "declared_in_metadata": true, + "observed_in_filenames": true + } + ], + "truncated_value_count": 0 + }, + { + "component": "channel", + "source": "metadata_and_parsed_filenames", + "count": 1, + "values": [ + { + "key": "2", + "label": "FITC", + "declared_in_metadata": true, + "observed_in_filenames": true + } + ], + "truncated_value_count": 0 + }, + { + "component": "z_index", + "source": "metadata_and_parsed_filenames", + "count": 1, + "values": [ + { + "key": "1", + "label": null, + "declared_in_metadata": true, + "observed_in_filenames": true + } + ], + "truncated_value_count": 0 + }, + { + "component": "timepoint", + "source": "metadata_and_parsed_filenames", + "count": 1, + "values": [ + { + "key": "1", + "label": null, + "declared_in_metadata": true, + "observed_in_filenames": true + } + ], + "truncated_value_count": 0 + }, + { + "component": "well", + "source": "metadata_and_parsed_filenames", + "count": 1, + "values": [ + { + "key": "A01", + "label": null, + "declared_in_metadata": true, + "observed_in_filenames": true + } + ], + "truncated_value_count": 0 + } + ], + "source_diagnostics": [], + "format_specific_handler_candidates": [], + "workspace_preparation": { + "read_only_inspection": true, + "required_before_execution": false, + "operation": "none", + "reason": "OpenHCS metadata is already present; read-only inspection did not need workspace preparation." + }, + "workflow_advice": { + "workflow_scope": "diagnostic", + "ingestion_route": "detected_handler", + "ingestion_owner": "openhcsdata", + "source_binding_role": "not_projected_by_handler", + "ui_code_document_id": "plate_manager.orchestrator_config", + "ui_operation": "init", + "knowledge_query": "source model CZI Bio-Formats source bindings", + "probable_native_ingestion_owners": [], + "message": "Keep the detected openhcsdata handler as the ingestion owner. For a visible workflow, add the plate directory through the PlateManager code document and initialize with auto-detection. Use for a workspace already prepared by OpenHCS and carrying its metadata document. The recorded workspace metadata, not raw vendor filename resemblance, owns parser and backend selection. This handler does not project declared source bindings." + } + }, + "isError": false + } + }, + { + "tool": "openhcs_query_plate_files", + "arguments": { + "plate_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs/input_openhcs", + "microscope_type": "auto", + "kind": "image", + "limit": 100, + "include_previews": false + }, + "response": { + "content": [ + { + "type": "text", + "text": "{\n \"schema_version\": \"openhcs.agent.v1\",\n \"errors\": [],\n \"warnings\": [],\n \"plate_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs/input_openhcs\",\n \"result_directory\": null,\n \"requested_microscope_type\": \"auto\",\n \"detected_microscope_type\": \"openhcsdata\",\n \"handler_class\": \"OpenHCSMicroscopeHandler\",\n \"parser_class\": \"SourceSchemaFilenameParser\",\n \"total_count\": 2,\n \"returned_count\": 2,\n \"offset\": 0,\n \"limit\": 100,\n \"truncated_count\": 0,\n \"records\": [\n {\n \"kind\": \"image\",\n \"key\": \"images/A01_s001_w2_z001_t001_capped_outgrowth_processing_role.tif\",\n \"metadata\": {\n \"filename\": \"images/A01_s001_w2_z001_t001_capped_outgrowth_processing_role.tif\",\n \"virtual_path\": \"images/A01_s001_w2_z001_t001_capped_outgrowth_processing_role.tif\",\n \"full_virtual_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs/input_openhcs/images/A01_s001_w2_z001_t001_capped_outgrowth_processing_role.tif\",\n \"source_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs/input_openhcs/images/A01_s001_w2_z001_t001_capped_outgrowth_processing_role.tif\",\n \"type\": \"Image\",\n \"OpenHCSSourceVoxelSpacingZYX\": \"1.3555999999999999,1.3555999999999999\",\n \"OpenHCSSourceVoxelSpacingUnit\": \"micrometers\",\n \"OpenHCSSourceFilterPaths\": {\n \"0\": \"A01_s001_w2_z001_t001.tif\",\n \"1\": \"/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/input/A01_s001_w2_z001_t001.tif\"\n },\n \"source_alias\": \"FITC\",\n \"extension\": \".tif\",\n \"site\": 1,\n \"channel\": 2,\n \"z_index\": 1,\n \"timepoint\": 1,\n \"well\": \"A01\",\n \"source_artifact_type\": \"image\",\n \"size\": \"351.2 KB\",\n \"modified\": \"2026-10-03T23:00:27\"\n },\n \"virtual_path\": \"images/A01_s001_w2_z001_t001_capped_outgrowth_processing_role.tif\",\n \"full_virtual_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs/input_openhcs/images/A01_s001_w2_z001_t001_capped_outgrowth_processing_role.tif\",\n \"source_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs/input_openhcs/images/A01_s001_w2_z001_t001_capped_outgrowth_processing_role.tif\",\n \"relative_path\": null,\n \"full_path\": null,\n \"file_format\": null,\n \"preview\": null\n },\n {\n \"kind\": \"image\",\n \"key\": \"images/A01_s001_w2_z001_t001_raw_body_processing_role.tif\",\n \"metadata\": {\n \"filename\": \"images/A01_s001_w2_z001_t001_raw_body_processing_role.tif\",\n \"virtual_path\": \"images/A01_s001_w2_z001_t001_raw_body_processing_role.tif\",\n \"full_virtual_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs/input_openhcs/images/A01_s001_w2_z001_t001_raw_body_processing_role.tif\",\n \"source_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs/input_openhcs/images/A01_s001_w2_z001_t001_raw_body_processing_role.tif\",\n \"type\": \"Image\",\n \"OpenHCSSourceVoxelSpacingZYX\": \"1.3555999999999999,1.3555999999999999\",\n \"OpenHCSSourceVoxelSpacingUnit\": \"micrometers\",\n \"OpenHCSSourceFilterPaths\": {\n \"0\": \"A01_s001_w2_z001_t001.tif\",\n \"1\": \"/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/input/A01_s001_w2_z001_t001.tif\"\n },\n \"source_alias\": \"FITC\",\n \"extension\": \".tif\",\n \"site\": 1,\n \"channel\": 2,\n \"z_index\": 1,\n \"timepoint\": 1,\n \"well\": \"A01\",\n \"source_artifact_type\": \"image\",\n \"size\": \"2.7 MB\",\n \"modified\": \"2026-10-03T23:00:27\"\n },\n \"virtual_path\": \"images/A01_s001_w2_z001_t001_raw_body_processing_role.tif\",\n \"full_virtual_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs/input_openhcs/images/A01_s001_w2_z001_t001_raw_body_processing_role.tif\",\n \"source_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs/input_openhcs/images/A01_s001_w2_z001_t001_raw_body_processing_role.tif\",\n \"relative_path\": null,\n \"full_path\": null,\n \"file_format\": null,\n \"preview\": null\n }\n ]\n}" + } + ], + "structuredContent": { + "schema_version": "openhcs.agent.v1", + "errors": [], + "warnings": [], + "plate_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs/input_openhcs", + "result_directory": null, + "requested_microscope_type": "auto", + "detected_microscope_type": "openhcsdata", + "handler_class": "OpenHCSMicroscopeHandler", + "parser_class": "SourceSchemaFilenameParser", + "total_count": 2, + "returned_count": 2, + "offset": 0, + "limit": 100, + "truncated_count": 0, + "records": [ + { + "kind": "image", + "key": "images/A01_s001_w2_z001_t001_capped_outgrowth_processing_role.tif", + "metadata": { + "filename": "images/A01_s001_w2_z001_t001_capped_outgrowth_processing_role.tif", + "virtual_path": "images/A01_s001_w2_z001_t001_capped_outgrowth_processing_role.tif", + "full_virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs/input_openhcs/images/A01_s001_w2_z001_t001_capped_outgrowth_processing_role.tif", + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs/input_openhcs/images/A01_s001_w2_z001_t001_capped_outgrowth_processing_role.tif", + "type": "Image", + "OpenHCSSourceVoxelSpacingZYX": "1.3555999999999999,1.3555999999999999", + "OpenHCSSourceVoxelSpacingUnit": "micrometers", + "OpenHCSSourceFilterPaths": { + "0": "A01_s001_w2_z001_t001.tif", + "1": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/input/A01_s001_w2_z001_t001.tif" + }, + "source_alias": "FITC", + "extension": ".tif", + "site": 1, + "channel": 2, + "z_index": 1, + "timepoint": 1, + "well": "A01", + "source_artifact_type": "image", + "size": "351.2 KB", + "modified": "2026-10-03T23:00:27" + }, + "virtual_path": "images/A01_s001_w2_z001_t001_capped_outgrowth_processing_role.tif", + "full_virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs/input_openhcs/images/A01_s001_w2_z001_t001_capped_outgrowth_processing_role.tif", + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs/input_openhcs/images/A01_s001_w2_z001_t001_capped_outgrowth_processing_role.tif", + "relative_path": null, + "full_path": null, + "file_format": null, + "preview": null + }, + { + "kind": "image", + "key": "images/A01_s001_w2_z001_t001_raw_body_processing_role.tif", + "metadata": { + "filename": "images/A01_s001_w2_z001_t001_raw_body_processing_role.tif", + "virtual_path": "images/A01_s001_w2_z001_t001_raw_body_processing_role.tif", + "full_virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs/input_openhcs/images/A01_s001_w2_z001_t001_raw_body_processing_role.tif", + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs/input_openhcs/images/A01_s001_w2_z001_t001_raw_body_processing_role.tif", + "type": "Image", + "OpenHCSSourceVoxelSpacingZYX": "1.3555999999999999,1.3555999999999999", + "OpenHCSSourceVoxelSpacingUnit": "micrometers", + "OpenHCSSourceFilterPaths": { + "0": "A01_s001_w2_z001_t001.tif", + "1": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/input/A01_s001_w2_z001_t001.tif" + }, + "source_alias": "FITC", + "extension": ".tif", + "site": 1, + "channel": 2, + "z_index": 1, + "timepoint": 1, + "well": "A01", + "source_artifact_type": "image", + "size": "2.7 MB", + "modified": "2026-10-03T23:00:27" + }, + "virtual_path": "images/A01_s001_w2_z001_t001_raw_body_processing_role.tif", + "full_virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs/input_openhcs/images/A01_s001_w2_z001_t001_raw_body_processing_role.tif", + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs/input_openhcs/images/A01_s001_w2_z001_t001_raw_body_processing_role.tif", + "relative_path": null, + "full_path": null, + "file_format": null, + "preview": null + } + ] + }, + "isError": false + } + }, + { + "tool": "openhcs_sample_plate_image", + "arguments": { + "plate_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs/input_openhcs", + "image_path": "images/A01_s001_w2_z001_t001_raw_body_processing_role.tif", + "microscope_type": "auto", + "y": 0, + "x": 0, + "height": 1, + "width": 9, + "resolution_index": 0, + "max_array_elements": 9, + "include_array_values": true + }, + "response": { + "content": [ + { + "type": "text", + "text": "{\n \"schema_version\": \"openhcs.agent.v1\",\n \"errors\": [],\n \"warnings\": [],\n \"plate_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs/input_openhcs\",\n \"requested_image_path\": \"images/A01_s001_w2_z001_t001_raw_body_processing_role.tif\",\n \"virtual_path\": \"images/A01_s001_w2_z001_t001_raw_body_processing_role.tif\",\n \"full_virtual_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs/input_openhcs/images/A01_s001_w2_z001_t001_raw_body_processing_role.tif\",\n \"source_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs/input_openhcs/images/A01_s001_w2_z001_t001_raw_body_processing_role.tif\",\n \"source_metadata\": {\n \"filename\": \"images/A01_s001_w2_z001_t001_raw_body_processing_role.tif\",\n \"virtual_path\": \"images/A01_s001_w2_z001_t001_raw_body_processing_role.tif\",\n \"full_virtual_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs/input_openhcs/images/A01_s001_w2_z001_t001_raw_body_processing_role.tif\",\n \"source_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs/input_openhcs/images/A01_s001_w2_z001_t001_raw_body_processing_role.tif\",\n \"type\": \"Image\",\n \"OpenHCSSourceVoxelSpacingZYX\": \"1.3555999999999999,1.3555999999999999\",\n \"OpenHCSSourceVoxelSpacingUnit\": \"micrometers\",\n \"OpenHCSSourceFilterPaths\": {\n \"0\": \"A01_s001_w2_z001_t001.tif\",\n \"1\": \"/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/input/A01_s001_w2_z001_t001.tif\"\n },\n \"source_alias\": \"FITC\",\n \"extension\": \".tif\",\n \"site\": 1,\n \"channel\": 2,\n \"z_index\": 1,\n \"timepoint\": 1,\n \"well\": \"A01\",\n \"source_artifact_type\": \"image\",\n \"size\": \"2.7 MB\",\n \"modified\": \"2026-10-03T23:00:27\"\n },\n \"shape\": [\n 1024,\n 1024\n ],\n \"resolution_shape\": [\n 1024,\n 1024\n ],\n \"dtype\": \"float32\",\n \"minimum\": 0.0,\n \"maximum\": 1.0,\n \"mean\": 0.50044846534729,\n \"requested_resolution_index\": 0,\n \"selected_resolution_index\": 0,\n \"resolution_count\": 1,\n \"downsample_yx\": [\n 1.0,\n 1.0\n ],\n \"statistics_scope\": \"source_resolution\",\n \"sample_origin_yx\": [\n 0,\n 0\n ],\n \"sample_shape\": [\n 1,\n 9\n ],\n \"sample_included\": true,\n \"sample_values\": [\n [\n 0.0,\n 0.0005798428319394588,\n 0.0005951018538326025,\n 0.0006103608757257462,\n 0.00396734569221735,\n 0.09153886884450912,\n 0.09155413508415222,\n 0.09156939387321472,\n 1.0\n ]\n ],\n \"sample_omitted_reason\": null\n}" + } + ], + "structuredContent": { + "schema_version": "openhcs.agent.v1", + "errors": [], + "warnings": [], + "plate_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs/input_openhcs", + "requested_image_path": "images/A01_s001_w2_z001_t001_raw_body_processing_role.tif", + "virtual_path": "images/A01_s001_w2_z001_t001_raw_body_processing_role.tif", + "full_virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs/input_openhcs/images/A01_s001_w2_z001_t001_raw_body_processing_role.tif", + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs/input_openhcs/images/A01_s001_w2_z001_t001_raw_body_processing_role.tif", + "source_metadata": { + "filename": "images/A01_s001_w2_z001_t001_raw_body_processing_role.tif", + "virtual_path": "images/A01_s001_w2_z001_t001_raw_body_processing_role.tif", + "full_virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs/input_openhcs/images/A01_s001_w2_z001_t001_raw_body_processing_role.tif", + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs/input_openhcs/images/A01_s001_w2_z001_t001_raw_body_processing_role.tif", + "type": "Image", + "OpenHCSSourceVoxelSpacingZYX": "1.3555999999999999,1.3555999999999999", + "OpenHCSSourceVoxelSpacingUnit": "micrometers", + "OpenHCSSourceFilterPaths": { + "0": "A01_s001_w2_z001_t001.tif", + "1": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/input/A01_s001_w2_z001_t001.tif" + }, + "source_alias": "FITC", + "extension": ".tif", + "site": 1, + "channel": 2, + "z_index": 1, + "timepoint": 1, + "well": "A01", + "source_artifact_type": "image", + "size": "2.7 MB", + "modified": "2026-10-03T23:00:27" + }, + "shape": [ + 1024, + 1024 + ], + "resolution_shape": [ + 1024, + 1024 + ], + "dtype": "float32", + "minimum": 0.0, + "maximum": 1.0, + "mean": 0.50044846534729, + "requested_resolution_index": 0, + "selected_resolution_index": 0, + "resolution_count": 1, + "downsample_yx": [ + 1.0, + 1.0 + ], + "statistics_scope": "source_resolution", + "sample_origin_yx": [ + 0, + 0 + ], + "sample_shape": [ + 1, + 9 + ], + "sample_included": true, + "sample_values": [ + [ + 0.0, + 0.0005798428319394588, + 0.0005951018538326025, + 0.0006103608757257462, + 0.00396734569221735, + 0.09153886884450912, + 0.09155413508415222, + 0.09156939387321472, + 1.0 + ] + ], + "sample_omitted_reason": null + }, + "isError": false + } + }, + { + "tool": "openhcs_sample_plate_image", + "arguments": { + "plate_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs/input_openhcs", + "image_path": "images/A01_s001_w2_z001_t001_capped_outgrowth_processing_role.tif", + "microscope_type": "auto", + "y": 0, + "x": 0, + "height": 1, + "width": 9, + "resolution_index": 0, + "max_array_elements": 9, + "include_array_values": true + }, + "response": { + "content": [ + { + "type": "text", + "text": "{\n \"schema_version\": \"openhcs.agent.v1\",\n \"errors\": [],\n \"warnings\": [],\n \"plate_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs/input_openhcs\",\n \"requested_image_path\": \"images/A01_s001_w2_z001_t001_capped_outgrowth_processing_role.tif\",\n \"virtual_path\": \"images/A01_s001_w2_z001_t001_capped_outgrowth_processing_role.tif\",\n \"full_virtual_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs/input_openhcs/images/A01_s001_w2_z001_t001_capped_outgrowth_processing_role.tif\",\n \"source_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs/input_openhcs/images/A01_s001_w2_z001_t001_capped_outgrowth_processing_role.tif\",\n \"source_metadata\": {\n \"filename\": \"images/A01_s001_w2_z001_t001_capped_outgrowth_processing_role.tif\",\n \"virtual_path\": \"images/A01_s001_w2_z001_t001_capped_outgrowth_processing_role.tif\",\n \"full_virtual_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs/input_openhcs/images/A01_s001_w2_z001_t001_capped_outgrowth_processing_role.tif\",\n \"source_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs/input_openhcs/images/A01_s001_w2_z001_t001_capped_outgrowth_processing_role.tif\",\n \"type\": \"Image\",\n \"OpenHCSSourceVoxelSpacingZYX\": \"1.3555999999999999,1.3555999999999999\",\n \"OpenHCSSourceVoxelSpacingUnit\": \"micrometers\",\n \"OpenHCSSourceFilterPaths\": {\n \"0\": \"A01_s001_w2_z001_t001.tif\",\n \"1\": \"/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/input/A01_s001_w2_z001_t001.tif\"\n },\n \"source_alias\": \"FITC\",\n \"extension\": \".tif\",\n \"site\": 1,\n \"channel\": 2,\n \"z_index\": 1,\n \"timepoint\": 1,\n \"well\": \"A01\",\n \"source_artifact_type\": \"image\",\n \"size\": \"351.2 KB\",\n \"modified\": \"2026-10-03T23:00:27\"\n },\n \"shape\": [\n 1024,\n 1024\n ],\n \"resolution_shape\": [\n 1024,\n 1024\n ],\n \"dtype\": \"float32\",\n \"minimum\": 0.0,\n \"maximum\": 1.0000001192092896,\n \"mean\": 0.9539787769317627,\n \"requested_resolution_index\": 0,\n \"selected_resolution_index\": 0,\n \"resolution_count\": 1,\n \"downsample_yx\": [\n 1.0,\n 1.0\n ],\n \"statistics_scope\": \"source_resolution\",\n \"sample_origin_yx\": [\n 0,\n 0\n ],\n \"sample_shape\": [\n 1,\n 9\n ],\n \"sample_included\": true,\n \"sample_values\": [\n [\n 0.0,\n 0.0,\n 0.0,\n 0.00016775709809735417,\n 0.037074316293001175,\n 0.999832272529602,\n 1.0000001192092896,\n 1.0000001192092896,\n 1.0000001192092896\n ]\n ],\n \"sample_omitted_reason\": null\n}" + } + ], + "structuredContent": { + "schema_version": "openhcs.agent.v1", + "errors": [], + "warnings": [], + "plate_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs/input_openhcs", + "requested_image_path": "images/A01_s001_w2_z001_t001_capped_outgrowth_processing_role.tif", + "virtual_path": "images/A01_s001_w2_z001_t001_capped_outgrowth_processing_role.tif", + "full_virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs/input_openhcs/images/A01_s001_w2_z001_t001_capped_outgrowth_processing_role.tif", + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs/input_openhcs/images/A01_s001_w2_z001_t001_capped_outgrowth_processing_role.tif", + "source_metadata": { + "filename": "images/A01_s001_w2_z001_t001_capped_outgrowth_processing_role.tif", + "virtual_path": "images/A01_s001_w2_z001_t001_capped_outgrowth_processing_role.tif", + "full_virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs/input_openhcs/images/A01_s001_w2_z001_t001_capped_outgrowth_processing_role.tif", + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs/input_openhcs/images/A01_s001_w2_z001_t001_capped_outgrowth_processing_role.tif", + "type": "Image", + "OpenHCSSourceVoxelSpacingZYX": "1.3555999999999999,1.3555999999999999", + "OpenHCSSourceVoxelSpacingUnit": "micrometers", + "OpenHCSSourceFilterPaths": { + "0": "A01_s001_w2_z001_t001.tif", + "1": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/input/A01_s001_w2_z001_t001.tif" + }, + "source_alias": "FITC", + "extension": ".tif", + "site": 1, + "channel": 2, + "z_index": 1, + "timepoint": 1, + "well": "A01", + "source_artifact_type": "image", + "size": "351.2 KB", + "modified": "2026-10-03T23:00:27" + }, + "shape": [ + 1024, + 1024 + ], + "resolution_shape": [ + 1024, + 1024 + ], + "dtype": "float32", + "minimum": 0.0, + "maximum": 1.0000001192092896, + "mean": 0.9539787769317627, + "requested_resolution_index": 0, + "selected_resolution_index": 0, + "resolution_count": 1, + "downsample_yx": [ + 1.0, + 1.0 + ], + "statistics_scope": "source_resolution", + "sample_origin_yx": [ + 0, + 0 + ], + "sample_shape": [ + 1, + 9 + ], + "sample_included": true, + "sample_values": [ + [ + 0.0, + 0.0, + 0.0, + 0.00016775709809735417, + 0.037074316293001175, + 0.999832272529602, + 1.0000001192092896, + 1.0000001192092896, + 1.0000001192092896 + ] + ], + "sample_omitted_reason": null + }, + "isError": false + } + }, + { + "tool": "openhcs_inspect_plate_path", + "arguments": { + "plate_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs", + "microscope_type": "auto" + }, + "response": { + "content": [ + { + "type": "text", + "text": "{\n \"schema_version\": \"openhcs.agent.v1\",\n \"errors\": [],\n \"warnings\": [\n {\n \"code\": \"plate_grid_dimensions_unavailable\",\n \"message\": \"'grid_dimensions' must be a list of two integers in openhcs_metadata.json\",\n \"hint\": null\n }\n ],\n \"plate_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs\",\n \"requested_microscope_type\": \"auto\",\n \"status\": \"partial\",\n \"confidence\": \"high\",\n \"available_microscope_types\": [\n \"bioformats\",\n \"imagexpress\",\n \"omero\",\n \"openhcsdata\",\n \"opera_phenix\",\n \"source_bindings\"\n ],\n \"detected_microscope_type\": \"openhcsdata\",\n \"handler_class\": \"OpenHCSMicroscopeHandler\",\n \"parser_class\": \"SourceSchemaFilenameParser\",\n \"metadata_handler_class\": \"OpenHCSMetadataHandler\",\n \"root_dir\": \"\",\n \"compatible_backends\": [\n \"zarr\",\n \"disk\"\n ],\n \"available_backends\": [\n \"disk\"\n ],\n \"metadata_file_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/openhcs_metadata.json\",\n \"grid_dimensions\": null,\n \"pixel_size\": 1.3556,\n \"image_files\": {\n \"count\": 5,\n \"sampled_files\": [\n \"checkpoints_step0/A01_s001_w2_z001_t001.tif\",\n \"checkpoints_step1/A01_s001_w2_z001_t001_SavedDistance.tif\",\n \"checkpoints_step2/A01_s001_w2_z001_t001_ResizedDistance.tif\",\n \"checkpoints_step3/A01_s001_w2_z001_t001_ResizedConsumer.tif\",\n \"images/A01_s001_w2_z001_t001_ResizedConsumer.tif\"\n ],\n \"sampled_records\": [\n {\n \"virtual_path\": \"checkpoints_step0/A01_s001_w2_z001_t001.tif\",\n \"full_virtual_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step0/A01_s001_w2_z001_t001.tif\",\n \"source_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step0/A01_s001_w2_z001_t001.tif\",\n \"metadata\": {\n \"filename\": \"checkpoints_step0/A01_s001_w2_z001_t001.tif\",\n \"virtual_path\": \"checkpoints_step0/A01_s001_w2_z001_t001.tif\",\n \"full_virtual_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step0/A01_s001_w2_z001_t001.tif\",\n \"source_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step0/A01_s001_w2_z001_t001.tif\",\n \"type\": \"Image\",\n \"extension\": \".tif\",\n \"site\": 1,\n \"channel\": 2,\n \"z_index\": 1,\n \"timepoint\": 1,\n \"well\": \"A01\",\n \"size\": \"312 B\",\n \"modified\": \"2026-10-03T23:29:49\"\n }\n },\n {\n \"virtual_path\": \"checkpoints_step1/A01_s001_w2_z001_t001_SavedDistance.tif\",\n \"full_virtual_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step1/A01_s001_w2_z001_t001_SavedDistance.tif\",\n \"source_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step1/A01_s001_w2_z001_t001_SavedDistance.tif\",\n \"metadata\": {\n \"filename\": \"checkpoints_step1/A01_s001_w2_z001_t001_SavedDistance.tif\",\n \"virtual_path\": \"checkpoints_step1/A01_s001_w2_z001_t001_SavedDistance.tif\",\n \"full_virtual_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step1/A01_s001_w2_z001_t001_SavedDistance.tif\",\n \"source_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step1/A01_s001_w2_z001_t001_SavedDistance.tif\",\n \"type\": \"Image\",\n \"OpenHCSSourceVoxelSpacingZYX\": \"1.3555999999999999,1.3555999999999999\",\n \"OpenHCSSourceVoxelSpacingUnit\": \"micrometers\",\n \"OpenHCSSourceFilterPaths\": {\n \"0\": \"A01_SavedIPO_step0.labels.tif\",\n \"1\": \"/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v3/outputs/ipo/seed_openhcs/checkpoints_results/A01_SavedIPO_step0.labels.tif\"\n },\n \"source_alias\": \"SavedImage\",\n \"extension\": \".tif\",\n \"site\": 1,\n \"channel\": 2,\n \"z_index\": 1,\n \"timepoint\": 1,\n \"well\": \"A01\",\n \"size\": \"335 B\",\n \"modified\": \"2026-10-03T23:29:49\"\n }\n },\n {\n \"virtual_path\": \"checkpoints_step2/A01_s001_w2_z001_t001_ResizedDistance.tif\",\n \"full_virtual_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step2/A01_s001_w2_z001_t001_ResizedDistance.tif\",\n \"source_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step2/A01_s001_w2_z001_t001_ResizedDistance.tif\",\n \"metadata\": {\n \"filename\": \"checkpoints_step2/A01_s001_w2_z001_t001_ResizedDistance.tif\",\n \"virtual_path\": \"checkpoints_step2/A01_s001_w2_z001_t001_ResizedDistance.tif\",\n \"full_virtual_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step2/A01_s001_w2_z001_t001_ResizedDistance.tif\",\n \"source_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step2/A01_s001_w2_z001_t001_ResizedDistance.tif\",\n \"type\": \"Image\",\n \"OpenHCSSourceVoxelSpacingZYX\": \"1.3555999999999999,1.3555999999999999\",\n \"OpenHCSSourceVoxelSpacingUnit\": \"micrometers\",\n \"OpenHCSSourceFilterPaths\": {\n \"0\": \"A01_SavedIPO_step0.labels.tif\",\n \"1\": \"/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v3/outputs/ipo/seed_openhcs/checkpoints_results/A01_SavedIPO_step0.labels.tif\"\n },\n \"source_alias\": \"SavedImage\",\n \"extension\": \".tif\",\n \"site\": 1,\n \"channel\": 2,\n \"z_index\": 1,\n \"timepoint\": 1,\n \"well\": \"A01\",\n \"size\": \"356 B\",\n \"modified\": \"2026-10-03T23:29:49\"\n }\n },\n {\n \"virtual_path\": \"checkpoints_step3/A01_s001_w2_z001_t001_ResizedConsumer.tif\",\n \"full_virtual_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step3/A01_s001_w2_z001_t001_ResizedConsumer.tif\",\n \"source_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step3/A01_s001_w2_z001_t001_ResizedConsumer.tif\",\n \"metadata\": {\n \"filename\": \"checkpoints_step3/A01_s001_w2_z001_t001_ResizedConsumer.tif\",\n \"virtual_path\": \"checkpoints_step3/A01_s001_w2_z001_t001_ResizedConsumer.tif\",\n \"full_virtual_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step3/A01_s001_w2_z001_t001_ResizedConsumer.tif\",\n \"source_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step3/A01_s001_w2_z001_t001_ResizedConsumer.tif\",\n \"type\": \"Image\",\n \"OpenHCSSourceVoxelSpacingZYX\": \"1.3555999999999999,1.3555999999999999\",\n \"OpenHCSSourceVoxelSpacingUnit\": \"micrometers\",\n \"OpenHCSSourceFilterPaths\": {\n \"0\": \"A01_SavedIPO_step0.labels.tif\",\n \"1\": \"/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v3/outputs/ipo/seed_openhcs/checkpoints_results/A01_SavedIPO_step0.labels.tif\"\n },\n \"source_alias\": \"SavedImage\",\n \"extension\": \".tif\",\n \"site\": 1,\n \"channel\": 2,\n \"z_index\": 1,\n \"timepoint\": 1,\n \"well\": \"A01\",\n \"source_artifact_type\": \"image\",\n \"size\": \"356 B\",\n \"modified\": \"2026-10-03T23:29:49\"\n }\n },\n {\n \"virtual_path\": \"images/A01_s001_w2_z001_t001_ResizedConsumer.tif\",\n \"full_virtual_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/images/A01_s001_w2_z001_t001_ResizedConsumer.tif\",\n \"source_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/images/A01_s001_w2_z001_t001_ResizedConsumer.tif\",\n \"metadata\": {\n \"filename\": \"images/A01_s001_w2_z001_t001_ResizedConsumer.tif\",\n \"virtual_path\": \"images/A01_s001_w2_z001_t001_ResizedConsumer.tif\",\n \"full_virtual_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/images/A01_s001_w2_z001_t001_ResizedConsumer.tif\",\n \"source_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/images/A01_s001_w2_z001_t001_ResizedConsumer.tif\",\n \"type\": \"Image\",\n \"OpenHCSSourceVoxelSpacingZYX\": \"1.3555999999999999,1.3555999999999999\",\n \"OpenHCSSourceVoxelSpacingUnit\": \"micrometers\",\n \"OpenHCSSourceFilterPaths\": {\n \"0\": \"A01_SavedIPO_step0.labels.tif\",\n \"1\": \"/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v3/outputs/ipo/seed_openhcs/checkpoints_results/A01_SavedIPO_step0.labels.tif\"\n },\n \"source_alias\": \"SavedImage\",\n \"extension\": \".tif\",\n \"site\": 1,\n \"channel\": 2,\n \"z_index\": 1,\n \"timepoint\": 1,\n \"well\": \"A01\",\n \"size\": \"356 B\",\n \"modified\": \"2026-10-03T23:29:49\"\n }\n }\n ],\n \"truncated_file_count\": 0\n },\n \"result_files\": {\n \"count\": 2,\n \"scanned_file_count\": 3,\n \"sampled_files\": [\n \"checkpoints_step0_results/A01_SavedIPOShape_1_measurements_step0_details.csv\",\n \"checkpoints_step3/A01_s001_w2_z001_t001_ResizedConsumer.tif\"\n ],\n \"sampled_records\": [\n {\n \"relative_path\": \"checkpoints_step0_results/A01_SavedIPOShape_1_measurements_step0_details.csv\",\n \"full_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step0_results/A01_SavedIPOShape_1_measurements_step0_details.csv\",\n \"file_format\": \"CSV\",\n \"metadata\": {\n \"filename\": \"checkpoints_step0_results/A01_SavedIPOShape_1_measurements_step0_details.csv\",\n \"type\": \"CSV\",\n \"size\": \"1.0 KB\",\n \"modified\": \"2026-10-03T23:29:49\",\n \"result_subdirectory\": \"checkpoints_step0\",\n \"full_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step0_results/A01_SavedIPOShape_1_measurements_step0_details.csv\"\n },\n \"preview\": {\n \"text_lines\": [\n \"slice_index,object_label,AreaShape_Area,AreaShape_Perimeter,AreaShape_MajorAxisLength,AreaShape_MinorAxisLength,AreaShape_Eccentricity,AreaShape_Orientation,AreaShape_Center_X,AreaShape_Center_Y,AreaShape_BoundingBoxArea,AreaShape_BoundingBoxMinimum_X,AreaShape_BoundingBoxMaximum_X,AreaShape_BoundingBoxMinimum_Y,AreaShape_BoundingBoxMaximum_Y,AreaShape_FormFactor,AreaShape_Extent,AreaShape_Solidity,AreaShape_Compactness,AreaShape_EulerNumber,AreaShape_MaximumRadius,AreaShape_MeanRadius,AreaShape_MedianRadius,AreaShape_ConvexArea,AreaShape_MinFeretDiameter,AreaShape_MaxFeretDiameter,AreaShape_EquivalentDiameter\",\n \"0,1,25.0,16.0,5.656854249492381,5.656854249492381,0.0,45.0,4.0,4.0,25.0,2,7,2,7,1.227184630308513,1.0,1.0,0.8148733086305041,1,3.0,1.4,1.0,25.0,4.0,5.656854249492381,5.641895835477563\",\n \"0,2,12.0,10.0,4.47213595499958,3.2659863237109037,0.6831300510639733,90.0,21.5,13.0,12.0,20,24,12,15,1.5079644737231006,1.0,1.0,0.6631455962162306,1,2.0,1.1666666666666667,1.0,12.0,2.0,3.605551275463989,3.9088200952233594\"\n ],\n \"csv_columns\": [\n \"slice_index\",\n \"object_label\",\n \"AreaShape_Area\",\n \"AreaShape_Perimeter\",\n \"AreaShape_MajorAxisLength\",\n \"AreaShape_MinorAxisLength\",\n \"AreaShape_Eccentricity\",\n \"AreaShape_Orientation\",\n \"AreaShape_Center_X\",\n \"AreaShape_Center_Y\",\n \"AreaShape_BoundingBoxArea\",\n \"AreaShape_BoundingBoxMinimum_X\",\n \"AreaShape_BoundingBoxMaximum_X\",\n \"AreaShape_BoundingBoxMinimum_Y\",\n \"AreaShape_BoundingBoxMaximum_Y\",\n \"AreaShape_FormFactor\",\n \"AreaShape_Extent\",\n \"AreaShape_Solidity\",\n \"AreaShape_Compactness\",\n \"AreaShape_EulerNumber\",\n \"AreaShape_MaximumRadius\",\n \"AreaShape_MeanRadius\",\n \"AreaShape_MedianRadius\",\n \"AreaShape_ConvexArea\",\n \"AreaShape_MinFeretDiameter\",\n \"AreaShape_MaxFeretDiameter\",\n \"AreaShape_EquivalentDiameter\"\n ],\n \"csv_rows\": [\n {\n \"slice_index\": \"0\",\n \"object_label\": \"1\",\n \"AreaShape_Area\": \"25.0\",\n \"AreaShape_Perimeter\": \"16.0\",\n \"AreaShape_MajorAxisLength\": \"5.656854249492381\",\n \"AreaShape_MinorAxisLength\": \"5.656854249492381\",\n \"AreaShape_Eccentricity\": \"0.0\",\n \"AreaShape_Orientation\": \"45.0\",\n \"AreaShape_Center_X\": \"4.0\",\n \"AreaShape_Center_Y\": \"4.0\",\n \"AreaShape_BoundingBoxArea\": \"25.0\",\n \"AreaShape_BoundingBoxMinimum_X\": \"2\",\n \"AreaShape_BoundingBoxMaximum_X\": \"7\",\n \"AreaShape_BoundingBoxMinimum_Y\": \"2\",\n \"AreaShape_BoundingBoxMaximum_Y\": \"7\",\n \"AreaShape_FormFactor\": \"1.227184630308513\",\n \"AreaShape_Extent\": \"1.0\",\n \"AreaShape_Solidity\": \"1.0\",\n \"AreaShape_Compactness\": \"0.8148733086305041\",\n \"AreaShape_EulerNumber\": \"1\",\n \"AreaShape_MaximumRadius\": \"3.0\",\n \"AreaShape_MeanRadius\": \"1.4\",\n \"AreaShape_MedianRadius\": \"1.0\",\n \"AreaShape_ConvexArea\": \"25.0\",\n \"AreaShape_MinFeretDiameter\": \"4.0\",\n \"AreaShape_MaxFeretDiameter\": \"5.656854249492381\",\n \"AreaShape_EquivalentDiameter\": \"5.641895835477563\"\n },\n {\n \"slice_index\": \"0\",\n \"object_label\": \"2\",\n \"AreaShape_Area\": \"12.0\",\n \"AreaShape_Perimeter\": \"10.0\",\n \"AreaShape_MajorAxisLength\": \"4.47213595499958\",\n \"AreaShape_MinorAxisLength\": \"3.2659863237109037\",\n \"AreaShape_Eccentricity\": \"0.6831300510639733\",\n \"AreaShape_Orientation\": \"90.0\",\n \"AreaShape_Center_X\": \"21.5\",\n \"AreaShape_Center_Y\": \"13.0\",\n \"AreaShape_BoundingBoxArea\": \"12.0\",\n \"AreaShape_BoundingBoxMinimum_X\": \"20\",\n \"AreaShape_BoundingBoxMaximum_X\": \"24\",\n \"AreaShape_BoundingBoxMinimum_Y\": \"12\",\n \"AreaShape_BoundingBoxMaximum_Y\": \"15\",\n \"AreaShape_FormFactor\": \"1.5079644737231006\",\n \"AreaShape_Extent\": \"1.0\",\n \"AreaShape_Solidity\": \"1.0\",\n \"AreaShape_Compactness\": \"0.6631455962162306\",\n \"AreaShape_EulerNumber\": \"1\",\n \"AreaShape_MaximumRadius\": \"2.0\",\n \"AreaShape_MeanRadius\": \"1.1666666666666667\",\n \"AreaShape_MedianRadius\": \"1.0\",\n \"AreaShape_ConvexArea\": \"12.0\",\n \"AreaShape_MinFeretDiameter\": \"2.0\",\n \"AreaShape_MaxFeretDiameter\": \"3.605551275463989\",\n \"AreaShape_EquivalentDiameter\": \"3.9088200952233594\"\n }\n ],\n \"roi_count\": null,\n \"roi_member_count\": null,\n \"roi_duplicate_member_count\": null,\n \"roi_area_min\": null,\n \"roi_area_max\": null,\n \"roi_area_mean\": null,\n \"roi_examples\": [],\n \"truncated\": false,\n \"omitted_reason\": null\n }\n },\n {\n \"relative_path\": \"checkpoints_step3/A01_s001_w2_z001_t001_ResizedConsumer.tif\",\n \"full_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step3/A01_s001_w2_z001_t001_ResizedConsumer.tif\",\n \"file_format\": \"TIFF\",\n \"metadata\": {\n \"filename\": \"checkpoints_step3/A01_s001_w2_z001_t001_ResizedConsumer.tif\",\n \"type\": \"TIFF\",\n \"size\": \"356 B\",\n \"modified\": \"2026-10-03T23:29:49\",\n \"result_subdirectory\": \"checkpoints_step3\",\n \"full_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step3/A01_s001_w2_z001_t001_ResizedConsumer.tif\",\n \"OpenHCSSourceVoxelSpacingZYX\": \"1.3555999999999999,1.3555999999999999\",\n \"OpenHCSSourceVoxelSpacingUnit\": \"micrometers\",\n \"OpenHCSSourceFilterPaths\": {\n \"0\": \"A01_SavedIPO_step0.labels.tif\",\n \"1\": \"/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v3/outputs/ipo/seed_openhcs/checkpoints_results/A01_SavedIPO_step0.labels.tif\"\n },\n \"site\": \"1\",\n \"channel\": \"2\",\n \"z_index\": \"1\",\n \"timepoint\": \"1\",\n \"well\": \"A01\",\n \"source_alias\": \"SavedImage\",\n \"extension\": \".tif\"\n },\n \"preview\": null\n }\n ],\n \"truncated_file_count\": 0\n },\n \"parse_summary\": {\n \"attempted_file_count\": 5,\n \"skipped_file_count\": 0,\n \"parsed_file_count\": 5,\n \"failed_file_count\": 0,\n \"failure_samples\": [],\n \"truncated_failure_count\": 0\n },\n \"components\": [\n {\n \"component\": \"site\",\n \"source\": \"metadata_and_parsed_filenames\",\n \"count\": 1,\n \"values\": [\n {\n \"key\": \"1\",\n \"label\": null,\n \"declared_in_metadata\": true,\n \"observed_in_filenames\": true\n }\n ],\n \"truncated_value_count\": 0\n },\n {\n \"component\": \"channel\",\n \"source\": \"metadata_and_parsed_filenames\",\n \"count\": 1,\n \"values\": [\n {\n \"key\": \"2\",\n \"label\": \"SavedImage\",\n \"declared_in_metadata\": true,\n \"observed_in_filenames\": true\n }\n ],\n \"truncated_value_count\": 0\n },\n {\n \"component\": \"z_index\",\n \"source\": \"metadata_and_parsed_filenames\",\n \"count\": 1,\n \"values\": [\n {\n \"key\": \"1\",\n \"label\": null,\n \"declared_in_metadata\": true,\n \"observed_in_filenames\": true\n }\n ],\n \"truncated_value_count\": 0\n },\n {\n \"component\": \"timepoint\",\n \"source\": \"metadata_and_parsed_filenames\",\n \"count\": 1,\n \"values\": [\n {\n \"key\": \"1\",\n \"label\": null,\n \"declared_in_metadata\": true,\n \"observed_in_filenames\": true\n }\n ],\n \"truncated_value_count\": 0\n },\n {\n \"component\": \"well\",\n \"source\": \"metadata_and_parsed_filenames\",\n \"count\": 1,\n \"values\": [\n {\n \"key\": \"A01\",\n \"label\": null,\n \"declared_in_metadata\": true,\n \"observed_in_filenames\": true\n }\n ],\n \"truncated_value_count\": 0\n }\n ],\n \"source_diagnostics\": [],\n \"format_specific_handler_candidates\": [],\n \"workspace_preparation\": {\n \"read_only_inspection\": true,\n \"required_before_execution\": false,\n \"operation\": \"none\",\n \"reason\": \"OpenHCS metadata is already present; read-only inspection did not need workspace preparation.\"\n },\n \"workflow_advice\": {\n \"workflow_scope\": \"diagnostic\",\n \"ingestion_route\": \"detected_handler\",\n \"ingestion_owner\": \"openhcsdata\",\n \"source_binding_role\": \"not_projected_by_handler\",\n \"ui_code_document_id\": \"plate_manager.orchestrator_config\",\n \"ui_operation\": \"init\",\n \"knowledge_query\": \"source model CZI Bio-Formats source bindings\",\n \"probable_native_ingestion_owners\": [],\n \"message\": \"Keep the detected openhcsdata handler as the ingestion owner. For a visible workflow, add the plate directory through the PlateManager code document and initialize with auto-detection. Use for a workspace already prepared by OpenHCS and carrying its metadata document. The recorded workspace metadata, not raw vendor filename resemblance, owns parser and backend selection. This handler does not project declared source bindings.\"\n }\n}" + } + ], + "structuredContent": { + "schema_version": "openhcs.agent.v1", + "errors": [], + "warnings": [ + { + "code": "plate_grid_dimensions_unavailable", + "message": "'grid_dimensions' must be a list of two integers in openhcs_metadata.json", + "hint": null + } + ], + "plate_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs", + "requested_microscope_type": "auto", + "status": "partial", + "confidence": "high", + "available_microscope_types": [ + "bioformats", + "imagexpress", + "omero", + "openhcsdata", + "opera_phenix", + "source_bindings" + ], + "detected_microscope_type": "openhcsdata", + "handler_class": "OpenHCSMicroscopeHandler", + "parser_class": "SourceSchemaFilenameParser", + "metadata_handler_class": "OpenHCSMetadataHandler", + "root_dir": "", + "compatible_backends": [ + "zarr", + "disk" + ], + "available_backends": [ + "disk" + ], + "metadata_file_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/openhcs_metadata.json", + "grid_dimensions": null, + "pixel_size": 1.3556, + "image_files": { + "count": 5, + "sampled_files": [ + "checkpoints_step0/A01_s001_w2_z001_t001.tif", + "checkpoints_step1/A01_s001_w2_z001_t001_SavedDistance.tif", + "checkpoints_step2/A01_s001_w2_z001_t001_ResizedDistance.tif", + "checkpoints_step3/A01_s001_w2_z001_t001_ResizedConsumer.tif", + "images/A01_s001_w2_z001_t001_ResizedConsumer.tif" + ], + "sampled_records": [ + { + "virtual_path": "checkpoints_step0/A01_s001_w2_z001_t001.tif", + "full_virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step0/A01_s001_w2_z001_t001.tif", + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step0/A01_s001_w2_z001_t001.tif", + "metadata": { + "filename": "checkpoints_step0/A01_s001_w2_z001_t001.tif", + "virtual_path": "checkpoints_step0/A01_s001_w2_z001_t001.tif", + "full_virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step0/A01_s001_w2_z001_t001.tif", + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step0/A01_s001_w2_z001_t001.tif", + "type": "Image", + "extension": ".tif", + "site": 1, + "channel": 2, + "z_index": 1, + "timepoint": 1, + "well": "A01", + "size": "312 B", + "modified": "2026-10-03T23:29:49" + } + }, + { + "virtual_path": "checkpoints_step1/A01_s001_w2_z001_t001_SavedDistance.tif", + "full_virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step1/A01_s001_w2_z001_t001_SavedDistance.tif", + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step1/A01_s001_w2_z001_t001_SavedDistance.tif", + "metadata": { + "filename": "checkpoints_step1/A01_s001_w2_z001_t001_SavedDistance.tif", + "virtual_path": "checkpoints_step1/A01_s001_w2_z001_t001_SavedDistance.tif", + "full_virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step1/A01_s001_w2_z001_t001_SavedDistance.tif", + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step1/A01_s001_w2_z001_t001_SavedDistance.tif", + "type": "Image", + "OpenHCSSourceVoxelSpacingZYX": "1.3555999999999999,1.3555999999999999", + "OpenHCSSourceVoxelSpacingUnit": "micrometers", + "OpenHCSSourceFilterPaths": { + "0": "A01_SavedIPO_step0.labels.tif", + "1": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v3/outputs/ipo/seed_openhcs/checkpoints_results/A01_SavedIPO_step0.labels.tif" + }, + "source_alias": "SavedImage", + "extension": ".tif", + "site": 1, + "channel": 2, + "z_index": 1, + "timepoint": 1, + "well": "A01", + "size": "335 B", + "modified": "2026-10-03T23:29:49" + } + }, + { + "virtual_path": "checkpoints_step2/A01_s001_w2_z001_t001_ResizedDistance.tif", + "full_virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step2/A01_s001_w2_z001_t001_ResizedDistance.tif", + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step2/A01_s001_w2_z001_t001_ResizedDistance.tif", + "metadata": { + "filename": "checkpoints_step2/A01_s001_w2_z001_t001_ResizedDistance.tif", + "virtual_path": "checkpoints_step2/A01_s001_w2_z001_t001_ResizedDistance.tif", + "full_virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step2/A01_s001_w2_z001_t001_ResizedDistance.tif", + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step2/A01_s001_w2_z001_t001_ResizedDistance.tif", + "type": "Image", + "OpenHCSSourceVoxelSpacingZYX": "1.3555999999999999,1.3555999999999999", + "OpenHCSSourceVoxelSpacingUnit": "micrometers", + "OpenHCSSourceFilterPaths": { + "0": "A01_SavedIPO_step0.labels.tif", + "1": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v3/outputs/ipo/seed_openhcs/checkpoints_results/A01_SavedIPO_step0.labels.tif" + }, + "source_alias": "SavedImage", + "extension": ".tif", + "site": 1, + "channel": 2, + "z_index": 1, + "timepoint": 1, + "well": "A01", + "size": "356 B", + "modified": "2026-10-03T23:29:49" + } + }, + { + "virtual_path": "checkpoints_step3/A01_s001_w2_z001_t001_ResizedConsumer.tif", + "full_virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step3/A01_s001_w2_z001_t001_ResizedConsumer.tif", + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step3/A01_s001_w2_z001_t001_ResizedConsumer.tif", + "metadata": { + "filename": "checkpoints_step3/A01_s001_w2_z001_t001_ResizedConsumer.tif", + "virtual_path": "checkpoints_step3/A01_s001_w2_z001_t001_ResizedConsumer.tif", + "full_virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step3/A01_s001_w2_z001_t001_ResizedConsumer.tif", + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step3/A01_s001_w2_z001_t001_ResizedConsumer.tif", + "type": "Image", + "OpenHCSSourceVoxelSpacingZYX": "1.3555999999999999,1.3555999999999999", + "OpenHCSSourceVoxelSpacingUnit": "micrometers", + "OpenHCSSourceFilterPaths": { + "0": "A01_SavedIPO_step0.labels.tif", + "1": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v3/outputs/ipo/seed_openhcs/checkpoints_results/A01_SavedIPO_step0.labels.tif" + }, + "source_alias": "SavedImage", + "extension": ".tif", + "site": 1, + "channel": 2, + "z_index": 1, + "timepoint": 1, + "well": "A01", + "source_artifact_type": "image", + "size": "356 B", + "modified": "2026-10-03T23:29:49" + } + }, + { + "virtual_path": "images/A01_s001_w2_z001_t001_ResizedConsumer.tif", + "full_virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/images/A01_s001_w2_z001_t001_ResizedConsumer.tif", + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/images/A01_s001_w2_z001_t001_ResizedConsumer.tif", + "metadata": { + "filename": "images/A01_s001_w2_z001_t001_ResizedConsumer.tif", + "virtual_path": "images/A01_s001_w2_z001_t001_ResizedConsumer.tif", + "full_virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/images/A01_s001_w2_z001_t001_ResizedConsumer.tif", + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/images/A01_s001_w2_z001_t001_ResizedConsumer.tif", + "type": "Image", + "OpenHCSSourceVoxelSpacingZYX": "1.3555999999999999,1.3555999999999999", + "OpenHCSSourceVoxelSpacingUnit": "micrometers", + "OpenHCSSourceFilterPaths": { + "0": "A01_SavedIPO_step0.labels.tif", + "1": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v3/outputs/ipo/seed_openhcs/checkpoints_results/A01_SavedIPO_step0.labels.tif" + }, + "source_alias": "SavedImage", + "extension": ".tif", + "site": 1, + "channel": 2, + "z_index": 1, + "timepoint": 1, + "well": "A01", + "size": "356 B", + "modified": "2026-10-03T23:29:49" + } + } + ], + "truncated_file_count": 0 + }, + "result_files": { + "count": 2, + "scanned_file_count": 3, + "sampled_files": [ + "checkpoints_step0_results/A01_SavedIPOShape_1_measurements_step0_details.csv", + "checkpoints_step3/A01_s001_w2_z001_t001_ResizedConsumer.tif" + ], + "sampled_records": [ + { + "relative_path": "checkpoints_step0_results/A01_SavedIPOShape_1_measurements_step0_details.csv", + "full_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step0_results/A01_SavedIPOShape_1_measurements_step0_details.csv", + "file_format": "CSV", + "metadata": { + "filename": "checkpoints_step0_results/A01_SavedIPOShape_1_measurements_step0_details.csv", + "type": "CSV", + "size": "1.0 KB", + "modified": "2026-10-03T23:29:49", + "result_subdirectory": "checkpoints_step0", + "full_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step0_results/A01_SavedIPOShape_1_measurements_step0_details.csv" + }, + "preview": { + "text_lines": [ + "slice_index,object_label,AreaShape_Area,AreaShape_Perimeter,AreaShape_MajorAxisLength,AreaShape_MinorAxisLength,AreaShape_Eccentricity,AreaShape_Orientation,AreaShape_Center_X,AreaShape_Center_Y,AreaShape_BoundingBoxArea,AreaShape_BoundingBoxMinimum_X,AreaShape_BoundingBoxMaximum_X,AreaShape_BoundingBoxMinimum_Y,AreaShape_BoundingBoxMaximum_Y,AreaShape_FormFactor,AreaShape_Extent,AreaShape_Solidity,AreaShape_Compactness,AreaShape_EulerNumber,AreaShape_MaximumRadius,AreaShape_MeanRadius,AreaShape_MedianRadius,AreaShape_ConvexArea,AreaShape_MinFeretDiameter,AreaShape_MaxFeretDiameter,AreaShape_EquivalentDiameter", + "0,1,25.0,16.0,5.656854249492381,5.656854249492381,0.0,45.0,4.0,4.0,25.0,2,7,2,7,1.227184630308513,1.0,1.0,0.8148733086305041,1,3.0,1.4,1.0,25.0,4.0,5.656854249492381,5.641895835477563", + "0,2,12.0,10.0,4.47213595499958,3.2659863237109037,0.6831300510639733,90.0,21.5,13.0,12.0,20,24,12,15,1.5079644737231006,1.0,1.0,0.6631455962162306,1,2.0,1.1666666666666667,1.0,12.0,2.0,3.605551275463989,3.9088200952233594" + ], + "csv_columns": [ + "slice_index", + "object_label", + "AreaShape_Area", + "AreaShape_Perimeter", + "AreaShape_MajorAxisLength", + "AreaShape_MinorAxisLength", + "AreaShape_Eccentricity", + "AreaShape_Orientation", + "AreaShape_Center_X", + "AreaShape_Center_Y", + "AreaShape_BoundingBoxArea", + "AreaShape_BoundingBoxMinimum_X", + "AreaShape_BoundingBoxMaximum_X", + "AreaShape_BoundingBoxMinimum_Y", + "AreaShape_BoundingBoxMaximum_Y", + "AreaShape_FormFactor", + "AreaShape_Extent", + "AreaShape_Solidity", + "AreaShape_Compactness", + "AreaShape_EulerNumber", + "AreaShape_MaximumRadius", + "AreaShape_MeanRadius", + "AreaShape_MedianRadius", + "AreaShape_ConvexArea", + "AreaShape_MinFeretDiameter", + "AreaShape_MaxFeretDiameter", + "AreaShape_EquivalentDiameter" + ], + "csv_rows": [ + { + "slice_index": "0", + "object_label": "1", + "AreaShape_Area": "25.0", + "AreaShape_Perimeter": "16.0", + "AreaShape_MajorAxisLength": "5.656854249492381", + "AreaShape_MinorAxisLength": "5.656854249492381", + "AreaShape_Eccentricity": "0.0", + "AreaShape_Orientation": "45.0", + "AreaShape_Center_X": "4.0", + "AreaShape_Center_Y": "4.0", + "AreaShape_BoundingBoxArea": "25.0", + "AreaShape_BoundingBoxMinimum_X": "2", + "AreaShape_BoundingBoxMaximum_X": "7", + "AreaShape_BoundingBoxMinimum_Y": "2", + "AreaShape_BoundingBoxMaximum_Y": "7", + "AreaShape_FormFactor": "1.227184630308513", + "AreaShape_Extent": "1.0", + "AreaShape_Solidity": "1.0", + "AreaShape_Compactness": "0.8148733086305041", + "AreaShape_EulerNumber": "1", + "AreaShape_MaximumRadius": "3.0", + "AreaShape_MeanRadius": "1.4", + "AreaShape_MedianRadius": "1.0", + "AreaShape_ConvexArea": "25.0", + "AreaShape_MinFeretDiameter": "4.0", + "AreaShape_MaxFeretDiameter": "5.656854249492381", + "AreaShape_EquivalentDiameter": "5.641895835477563" + }, + { + "slice_index": "0", + "object_label": "2", + "AreaShape_Area": "12.0", + "AreaShape_Perimeter": "10.0", + "AreaShape_MajorAxisLength": "4.47213595499958", + "AreaShape_MinorAxisLength": "3.2659863237109037", + "AreaShape_Eccentricity": "0.6831300510639733", + "AreaShape_Orientation": "90.0", + "AreaShape_Center_X": "21.5", + "AreaShape_Center_Y": "13.0", + "AreaShape_BoundingBoxArea": "12.0", + "AreaShape_BoundingBoxMinimum_X": "20", + "AreaShape_BoundingBoxMaximum_X": "24", + "AreaShape_BoundingBoxMinimum_Y": "12", + "AreaShape_BoundingBoxMaximum_Y": "15", + "AreaShape_FormFactor": "1.5079644737231006", + "AreaShape_Extent": "1.0", + "AreaShape_Solidity": "1.0", + "AreaShape_Compactness": "0.6631455962162306", + "AreaShape_EulerNumber": "1", + "AreaShape_MaximumRadius": "2.0", + "AreaShape_MeanRadius": "1.1666666666666667", + "AreaShape_MedianRadius": "1.0", + "AreaShape_ConvexArea": "12.0", + "AreaShape_MinFeretDiameter": "2.0", + "AreaShape_MaxFeretDiameter": "3.605551275463989", + "AreaShape_EquivalentDiameter": "3.9088200952233594" + } + ], + "roi_count": null, + "roi_member_count": null, + "roi_duplicate_member_count": null, + "roi_area_min": null, + "roi_area_max": null, + "roi_area_mean": null, + "roi_examples": [], + "truncated": false, + "omitted_reason": null + } + }, + { + "relative_path": "checkpoints_step3/A01_s001_w2_z001_t001_ResizedConsumer.tif", + "full_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step3/A01_s001_w2_z001_t001_ResizedConsumer.tif", + "file_format": "TIFF", + "metadata": { + "filename": "checkpoints_step3/A01_s001_w2_z001_t001_ResizedConsumer.tif", + "type": "TIFF", + "size": "356 B", + "modified": "2026-10-03T23:29:49", + "result_subdirectory": "checkpoints_step3", + "full_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step3/A01_s001_w2_z001_t001_ResizedConsumer.tif", + "OpenHCSSourceVoxelSpacingZYX": "1.3555999999999999,1.3555999999999999", + "OpenHCSSourceVoxelSpacingUnit": "micrometers", + "OpenHCSSourceFilterPaths": { + "0": "A01_SavedIPO_step0.labels.tif", + "1": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v3/outputs/ipo/seed_openhcs/checkpoints_results/A01_SavedIPO_step0.labels.tif" + }, + "site": "1", + "channel": "2", + "z_index": "1", + "timepoint": "1", + "well": "A01", + "source_alias": "SavedImage", + "extension": ".tif" + }, + "preview": null + } + ], + "truncated_file_count": 0 + }, + "parse_summary": { + "attempted_file_count": 5, + "skipped_file_count": 0, + "parsed_file_count": 5, + "failed_file_count": 0, + "failure_samples": [], + "truncated_failure_count": 0 + }, + "components": [ + { + "component": "site", + "source": "metadata_and_parsed_filenames", + "count": 1, + "values": [ + { + "key": "1", + "label": null, + "declared_in_metadata": true, + "observed_in_filenames": true + } + ], + "truncated_value_count": 0 + }, + { + "component": "channel", + "source": "metadata_and_parsed_filenames", + "count": 1, + "values": [ + { + "key": "2", + "label": "SavedImage", + "declared_in_metadata": true, + "observed_in_filenames": true + } + ], + "truncated_value_count": 0 + }, + { + "component": "z_index", + "source": "metadata_and_parsed_filenames", + "count": 1, + "values": [ + { + "key": "1", + "label": null, + "declared_in_metadata": true, + "observed_in_filenames": true + } + ], + "truncated_value_count": 0 + }, + { + "component": "timepoint", + "source": "metadata_and_parsed_filenames", + "count": 1, + "values": [ + { + "key": "1", + "label": null, + "declared_in_metadata": true, + "observed_in_filenames": true + } + ], + "truncated_value_count": 0 + }, + { + "component": "well", + "source": "metadata_and_parsed_filenames", + "count": 1, + "values": [ + { + "key": "A01", + "label": null, + "declared_in_metadata": true, + "observed_in_filenames": true + } + ], + "truncated_value_count": 0 + } + ], + "source_diagnostics": [], + "format_specific_handler_candidates": [], + "workspace_preparation": { + "read_only_inspection": true, + "required_before_execution": false, + "operation": "none", + "reason": "OpenHCS metadata is already present; read-only inspection did not need workspace preparation." + }, + "workflow_advice": { + "workflow_scope": "diagnostic", + "ingestion_route": "detected_handler", + "ingestion_owner": "openhcsdata", + "source_binding_role": "not_projected_by_handler", + "ui_code_document_id": "plate_manager.orchestrator_config", + "ui_operation": "init", + "knowledge_query": "source model CZI Bio-Formats source bindings", + "probable_native_ingestion_owners": [], + "message": "Keep the detected openhcsdata handler as the ingestion owner. For a visible workflow, add the plate directory through the PlateManager code document and initialize with auto-detection. Use for a workspace already prepared by OpenHCS and carrying its metadata document. The recorded workspace metadata, not raw vendor filename resemblance, owns parser and backend selection. This handler does not project declared source bindings." + } + }, + "isError": false + } + }, + { + "tool": "openhcs_query_plate_files", + "arguments": { + "plate_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs", + "microscope_type": "auto", + "kind": "image", + "limit": 100, + "include_previews": false + }, + "response": { + "content": [ + { + "type": "text", + "text": "{\n \"schema_version\": \"openhcs.agent.v1\",\n \"errors\": [],\n \"warnings\": [],\n \"plate_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs\",\n \"result_directory\": null,\n \"requested_microscope_type\": \"auto\",\n \"detected_microscope_type\": \"openhcsdata\",\n \"handler_class\": \"OpenHCSMicroscopeHandler\",\n \"parser_class\": \"SourceSchemaFilenameParser\",\n \"total_count\": 5,\n \"returned_count\": 5,\n \"offset\": 0,\n \"limit\": 100,\n \"truncated_count\": 0,\n \"records\": [\n {\n \"kind\": \"image\",\n \"key\": \"checkpoints_step0/A01_s001_w2_z001_t001.tif\",\n \"metadata\": {\n \"filename\": \"checkpoints_step0/A01_s001_w2_z001_t001.tif\",\n \"virtual_path\": \"checkpoints_step0/A01_s001_w2_z001_t001.tif\",\n \"full_virtual_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step0/A01_s001_w2_z001_t001.tif\",\n \"source_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step0/A01_s001_w2_z001_t001.tif\",\n \"type\": \"Image\",\n \"extension\": \".tif\",\n \"site\": 1,\n \"channel\": 2,\n \"z_index\": 1,\n \"timepoint\": 1,\n \"well\": \"A01\",\n \"size\": \"312 B\",\n \"modified\": \"2026-10-03T23:29:49\"\n },\n \"virtual_path\": \"checkpoints_step0/A01_s001_w2_z001_t001.tif\",\n \"full_virtual_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step0/A01_s001_w2_z001_t001.tif\",\n \"source_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step0/A01_s001_w2_z001_t001.tif\",\n \"relative_path\": null,\n \"full_path\": null,\n \"file_format\": null,\n \"preview\": null\n },\n {\n \"kind\": \"image\",\n \"key\": \"checkpoints_step1/A01_s001_w2_z001_t001_SavedDistance.tif\",\n \"metadata\": {\n \"filename\": \"checkpoints_step1/A01_s001_w2_z001_t001_SavedDistance.tif\",\n \"virtual_path\": \"checkpoints_step1/A01_s001_w2_z001_t001_SavedDistance.tif\",\n \"full_virtual_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step1/A01_s001_w2_z001_t001_SavedDistance.tif\",\n \"source_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step1/A01_s001_w2_z001_t001_SavedDistance.tif\",\n \"type\": \"Image\",\n \"OpenHCSSourceVoxelSpacingZYX\": \"1.3555999999999999,1.3555999999999999\",\n \"OpenHCSSourceVoxelSpacingUnit\": \"micrometers\",\n \"OpenHCSSourceFilterPaths\": {\n \"0\": \"A01_SavedIPO_step0.labels.tif\",\n \"1\": \"/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v3/outputs/ipo/seed_openhcs/checkpoints_results/A01_SavedIPO_step0.labels.tif\"\n },\n \"source_alias\": \"SavedImage\",\n \"extension\": \".tif\",\n \"site\": 1,\n \"channel\": 2,\n \"z_index\": 1,\n \"timepoint\": 1,\n \"well\": \"A01\",\n \"size\": \"335 B\",\n \"modified\": \"2026-10-03T23:29:49\"\n },\n \"virtual_path\": \"checkpoints_step1/A01_s001_w2_z001_t001_SavedDistance.tif\",\n \"full_virtual_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step1/A01_s001_w2_z001_t001_SavedDistance.tif\",\n \"source_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step1/A01_s001_w2_z001_t001_SavedDistance.tif\",\n \"relative_path\": null,\n \"full_path\": null,\n \"file_format\": null,\n \"preview\": null\n },\n {\n \"kind\": \"image\",\n \"key\": \"checkpoints_step2/A01_s001_w2_z001_t001_ResizedDistance.tif\",\n \"metadata\": {\n \"filename\": \"checkpoints_step2/A01_s001_w2_z001_t001_ResizedDistance.tif\",\n \"virtual_path\": \"checkpoints_step2/A01_s001_w2_z001_t001_ResizedDistance.tif\",\n \"full_virtual_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step2/A01_s001_w2_z001_t001_ResizedDistance.tif\",\n \"source_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step2/A01_s001_w2_z001_t001_ResizedDistance.tif\",\n \"type\": \"Image\",\n \"OpenHCSSourceVoxelSpacingZYX\": \"1.3555999999999999,1.3555999999999999\",\n \"OpenHCSSourceVoxelSpacingUnit\": \"micrometers\",\n \"OpenHCSSourceFilterPaths\": {\n \"0\": \"A01_SavedIPO_step0.labels.tif\",\n \"1\": \"/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v3/outputs/ipo/seed_openhcs/checkpoints_results/A01_SavedIPO_step0.labels.tif\"\n },\n \"source_alias\": \"SavedImage\",\n \"extension\": \".tif\",\n \"site\": 1,\n \"channel\": 2,\n \"z_index\": 1,\n \"timepoint\": 1,\n \"well\": \"A01\",\n \"size\": \"356 B\",\n \"modified\": \"2026-10-03T23:29:49\"\n },\n \"virtual_path\": \"checkpoints_step2/A01_s001_w2_z001_t001_ResizedDistance.tif\",\n \"full_virtual_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step2/A01_s001_w2_z001_t001_ResizedDistance.tif\",\n \"source_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step2/A01_s001_w2_z001_t001_ResizedDistance.tif\",\n \"relative_path\": null,\n \"full_path\": null,\n \"file_format\": null,\n \"preview\": null\n },\n {\n \"kind\": \"image\",\n \"key\": \"checkpoints_step3/A01_s001_w2_z001_t001_ResizedConsumer.tif\",\n \"metadata\": {\n \"filename\": \"checkpoints_step3/A01_s001_w2_z001_t001_ResizedConsumer.tif\",\n \"virtual_path\": \"checkpoints_step3/A01_s001_w2_z001_t001_ResizedConsumer.tif\",\n \"full_virtual_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step3/A01_s001_w2_z001_t001_ResizedConsumer.tif\",\n \"source_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step3/A01_s001_w2_z001_t001_ResizedConsumer.tif\",\n \"type\": \"Image\",\n \"OpenHCSSourceVoxelSpacingZYX\": \"1.3555999999999999,1.3555999999999999\",\n \"OpenHCSSourceVoxelSpacingUnit\": \"micrometers\",\n \"OpenHCSSourceFilterPaths\": {\n \"0\": \"A01_SavedIPO_step0.labels.tif\",\n \"1\": \"/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v3/outputs/ipo/seed_openhcs/checkpoints_results/A01_SavedIPO_step0.labels.tif\"\n },\n \"source_alias\": \"SavedImage\",\n \"extension\": \".tif\",\n \"site\": 1,\n \"channel\": 2,\n \"z_index\": 1,\n \"timepoint\": 1,\n \"well\": \"A01\",\n \"source_artifact_type\": \"image\",\n \"size\": \"356 B\",\n \"modified\": \"2026-10-03T23:29:49\"\n },\n \"virtual_path\": \"checkpoints_step3/A01_s001_w2_z001_t001_ResizedConsumer.tif\",\n \"full_virtual_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step3/A01_s001_w2_z001_t001_ResizedConsumer.tif\",\n \"source_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step3/A01_s001_w2_z001_t001_ResizedConsumer.tif\",\n \"relative_path\": null,\n \"full_path\": null,\n \"file_format\": null,\n \"preview\": null\n },\n {\n \"kind\": \"image\",\n \"key\": \"images/A01_s001_w2_z001_t001_ResizedConsumer.tif\",\n \"metadata\": {\n \"filename\": \"images/A01_s001_w2_z001_t001_ResizedConsumer.tif\",\n \"virtual_path\": \"images/A01_s001_w2_z001_t001_ResizedConsumer.tif\",\n \"full_virtual_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/images/A01_s001_w2_z001_t001_ResizedConsumer.tif\",\n \"source_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/images/A01_s001_w2_z001_t001_ResizedConsumer.tif\",\n \"type\": \"Image\",\n \"OpenHCSSourceVoxelSpacingZYX\": \"1.3555999999999999,1.3555999999999999\",\n \"OpenHCSSourceVoxelSpacingUnit\": \"micrometers\",\n \"OpenHCSSourceFilterPaths\": {\n \"0\": \"A01_SavedIPO_step0.labels.tif\",\n \"1\": \"/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v3/outputs/ipo/seed_openhcs/checkpoints_results/A01_SavedIPO_step0.labels.tif\"\n },\n \"source_alias\": \"SavedImage\",\n \"extension\": \".tif\",\n \"site\": 1,\n \"channel\": 2,\n \"z_index\": 1,\n \"timepoint\": 1,\n \"well\": \"A01\",\n \"size\": \"356 B\",\n \"modified\": \"2026-10-03T23:29:49\"\n },\n \"virtual_path\": \"images/A01_s001_w2_z001_t001_ResizedConsumer.tif\",\n \"full_virtual_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/images/A01_s001_w2_z001_t001_ResizedConsumer.tif\",\n \"source_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/images/A01_s001_w2_z001_t001_ResizedConsumer.tif\",\n \"relative_path\": null,\n \"full_path\": null,\n \"file_format\": null,\n \"preview\": null\n }\n ]\n}" + } + ], + "structuredContent": { + "schema_version": "openhcs.agent.v1", + "errors": [], + "warnings": [], + "plate_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs", + "result_directory": null, + "requested_microscope_type": "auto", + "detected_microscope_type": "openhcsdata", + "handler_class": "OpenHCSMicroscopeHandler", + "parser_class": "SourceSchemaFilenameParser", + "total_count": 5, + "returned_count": 5, + "offset": 0, + "limit": 100, + "truncated_count": 0, + "records": [ + { + "kind": "image", + "key": "checkpoints_step0/A01_s001_w2_z001_t001.tif", + "metadata": { + "filename": "checkpoints_step0/A01_s001_w2_z001_t001.tif", + "virtual_path": "checkpoints_step0/A01_s001_w2_z001_t001.tif", + "full_virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step0/A01_s001_w2_z001_t001.tif", + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step0/A01_s001_w2_z001_t001.tif", + "type": "Image", + "extension": ".tif", + "site": 1, + "channel": 2, + "z_index": 1, + "timepoint": 1, + "well": "A01", + "size": "312 B", + "modified": "2026-10-03T23:29:49" + }, + "virtual_path": "checkpoints_step0/A01_s001_w2_z001_t001.tif", + "full_virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step0/A01_s001_w2_z001_t001.tif", + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step0/A01_s001_w2_z001_t001.tif", + "relative_path": null, + "full_path": null, + "file_format": null, + "preview": null + }, + { + "kind": "image", + "key": "checkpoints_step1/A01_s001_w2_z001_t001_SavedDistance.tif", + "metadata": { + "filename": "checkpoints_step1/A01_s001_w2_z001_t001_SavedDistance.tif", + "virtual_path": "checkpoints_step1/A01_s001_w2_z001_t001_SavedDistance.tif", + "full_virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step1/A01_s001_w2_z001_t001_SavedDistance.tif", + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step1/A01_s001_w2_z001_t001_SavedDistance.tif", + "type": "Image", + "OpenHCSSourceVoxelSpacingZYX": "1.3555999999999999,1.3555999999999999", + "OpenHCSSourceVoxelSpacingUnit": "micrometers", + "OpenHCSSourceFilterPaths": { + "0": "A01_SavedIPO_step0.labels.tif", + "1": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v3/outputs/ipo/seed_openhcs/checkpoints_results/A01_SavedIPO_step0.labels.tif" + }, + "source_alias": "SavedImage", + "extension": ".tif", + "site": 1, + "channel": 2, + "z_index": 1, + "timepoint": 1, + "well": "A01", + "size": "335 B", + "modified": "2026-10-03T23:29:49" + }, + "virtual_path": "checkpoints_step1/A01_s001_w2_z001_t001_SavedDistance.tif", + "full_virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step1/A01_s001_w2_z001_t001_SavedDistance.tif", + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step1/A01_s001_w2_z001_t001_SavedDistance.tif", + "relative_path": null, + "full_path": null, + "file_format": null, + "preview": null + }, + { + "kind": "image", + "key": "checkpoints_step2/A01_s001_w2_z001_t001_ResizedDistance.tif", + "metadata": { + "filename": "checkpoints_step2/A01_s001_w2_z001_t001_ResizedDistance.tif", + "virtual_path": "checkpoints_step2/A01_s001_w2_z001_t001_ResizedDistance.tif", + "full_virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step2/A01_s001_w2_z001_t001_ResizedDistance.tif", + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step2/A01_s001_w2_z001_t001_ResizedDistance.tif", + "type": "Image", + "OpenHCSSourceVoxelSpacingZYX": "1.3555999999999999,1.3555999999999999", + "OpenHCSSourceVoxelSpacingUnit": "micrometers", + "OpenHCSSourceFilterPaths": { + "0": "A01_SavedIPO_step0.labels.tif", + "1": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v3/outputs/ipo/seed_openhcs/checkpoints_results/A01_SavedIPO_step0.labels.tif" + }, + "source_alias": "SavedImage", + "extension": ".tif", + "site": 1, + "channel": 2, + "z_index": 1, + "timepoint": 1, + "well": "A01", + "size": "356 B", + "modified": "2026-10-03T23:29:49" + }, + "virtual_path": "checkpoints_step2/A01_s001_w2_z001_t001_ResizedDistance.tif", + "full_virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step2/A01_s001_w2_z001_t001_ResizedDistance.tif", + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step2/A01_s001_w2_z001_t001_ResizedDistance.tif", + "relative_path": null, + "full_path": null, + "file_format": null, + "preview": null + }, + { + "kind": "image", + "key": "checkpoints_step3/A01_s001_w2_z001_t001_ResizedConsumer.tif", + "metadata": { + "filename": "checkpoints_step3/A01_s001_w2_z001_t001_ResizedConsumer.tif", + "virtual_path": "checkpoints_step3/A01_s001_w2_z001_t001_ResizedConsumer.tif", + "full_virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step3/A01_s001_w2_z001_t001_ResizedConsumer.tif", + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step3/A01_s001_w2_z001_t001_ResizedConsumer.tif", + "type": "Image", + "OpenHCSSourceVoxelSpacingZYX": "1.3555999999999999,1.3555999999999999", + "OpenHCSSourceVoxelSpacingUnit": "micrometers", + "OpenHCSSourceFilterPaths": { + "0": "A01_SavedIPO_step0.labels.tif", + "1": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v3/outputs/ipo/seed_openhcs/checkpoints_results/A01_SavedIPO_step0.labels.tif" + }, + "source_alias": "SavedImage", + "extension": ".tif", + "site": 1, + "channel": 2, + "z_index": 1, + "timepoint": 1, + "well": "A01", + "source_artifact_type": "image", + "size": "356 B", + "modified": "2026-10-03T23:29:49" + }, + "virtual_path": "checkpoints_step3/A01_s001_w2_z001_t001_ResizedConsumer.tif", + "full_virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step3/A01_s001_w2_z001_t001_ResizedConsumer.tif", + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step3/A01_s001_w2_z001_t001_ResizedConsumer.tif", + "relative_path": null, + "full_path": null, + "file_format": null, + "preview": null + }, + { + "kind": "image", + "key": "images/A01_s001_w2_z001_t001_ResizedConsumer.tif", + "metadata": { + "filename": "images/A01_s001_w2_z001_t001_ResizedConsumer.tif", + "virtual_path": "images/A01_s001_w2_z001_t001_ResizedConsumer.tif", + "full_virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/images/A01_s001_w2_z001_t001_ResizedConsumer.tif", + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/images/A01_s001_w2_z001_t001_ResizedConsumer.tif", + "type": "Image", + "OpenHCSSourceVoxelSpacingZYX": "1.3555999999999999,1.3555999999999999", + "OpenHCSSourceVoxelSpacingUnit": "micrometers", + "OpenHCSSourceFilterPaths": { + "0": "A01_SavedIPO_step0.labels.tif", + "1": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v3/outputs/ipo/seed_openhcs/checkpoints_results/A01_SavedIPO_step0.labels.tif" + }, + "source_alias": "SavedImage", + "extension": ".tif", + "site": 1, + "channel": 2, + "z_index": 1, + "timepoint": 1, + "well": "A01", + "size": "356 B", + "modified": "2026-10-03T23:29:49" + }, + "virtual_path": "images/A01_s001_w2_z001_t001_ResizedConsumer.tif", + "full_virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/images/A01_s001_w2_z001_t001_ResizedConsumer.tif", + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/images/A01_s001_w2_z001_t001_ResizedConsumer.tif", + "relative_path": null, + "full_path": null, + "file_format": null, + "preview": null + } + ] + }, + "isError": false + } + }, + { + "tool": "openhcs_sample_plate_image", + "arguments": { + "plate_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs", + "image_path": "checkpoints_step1/A01_s001_w2_z001_t001_SavedDistance.tif", + "microscope_type": "auto", + "y": 0, + "x": 0, + "height": 2, + "width": 2, + "max_array_elements": 4, + "include_array_values": true + }, + "response": { + "content": [ + { + "type": "text", + "text": "{\n \"schema_version\": \"openhcs.agent.v1\",\n \"errors\": [],\n \"warnings\": [],\n \"plate_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs\",\n \"requested_image_path\": \"checkpoints_step1/A01_s001_w2_z001_t001_SavedDistance.tif\",\n \"virtual_path\": \"checkpoints_step1/A01_s001_w2_z001_t001_SavedDistance.tif\",\n \"full_virtual_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step1/A01_s001_w2_z001_t001_SavedDistance.tif\",\n \"source_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step1/A01_s001_w2_z001_t001_SavedDistance.tif\",\n \"source_metadata\": {\n \"filename\": \"checkpoints_step1/A01_s001_w2_z001_t001_SavedDistance.tif\",\n \"virtual_path\": \"checkpoints_step1/A01_s001_w2_z001_t001_SavedDistance.tif\",\n \"full_virtual_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step1/A01_s001_w2_z001_t001_SavedDistance.tif\",\n \"source_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step1/A01_s001_w2_z001_t001_SavedDistance.tif\",\n \"type\": \"Image\",\n \"OpenHCSSourceVoxelSpacingZYX\": \"1.3555999999999999,1.3555999999999999\",\n \"OpenHCSSourceVoxelSpacingUnit\": \"micrometers\",\n \"OpenHCSSourceFilterPaths\": {\n \"0\": \"A01_SavedIPO_step0.labels.tif\",\n \"1\": \"/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v3/outputs/ipo/seed_openhcs/checkpoints_results/A01_SavedIPO_step0.labels.tif\"\n },\n \"source_alias\": \"SavedImage\",\n \"extension\": \".tif\",\n \"site\": 1,\n \"channel\": 2,\n \"z_index\": 1,\n \"timepoint\": 1,\n \"well\": \"A01\",\n \"size\": \"335 B\",\n \"modified\": \"2026-10-03T23:29:49\"\n },\n \"shape\": [\n 32,\n 32\n ],\n \"resolution_shape\": [\n 32,\n 32\n ],\n \"dtype\": \"float32\",\n \"minimum\": 0.0,\n \"maximum\": 3.0,\n \"mean\": 0.0478515625,\n \"requested_resolution_index\": null,\n \"selected_resolution_index\": 0,\n \"resolution_count\": 1,\n \"downsample_yx\": [\n 1.0,\n 1.0\n ],\n \"statistics_scope\": \"source_resolution\",\n \"sample_origin_yx\": [\n 0,\n 0\n ],\n \"sample_shape\": [\n 2,\n 2\n ],\n \"sample_included\": true,\n \"sample_values\": [\n [\n 0.0,\n 0.0\n ],\n [\n 0.0,\n 0.0\n ]\n ],\n \"sample_omitted_reason\": null\n}" + } + ], + "structuredContent": { + "schema_version": "openhcs.agent.v1", + "errors": [], + "warnings": [], + "plate_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs", + "requested_image_path": "checkpoints_step1/A01_s001_w2_z001_t001_SavedDistance.tif", + "virtual_path": "checkpoints_step1/A01_s001_w2_z001_t001_SavedDistance.tif", + "full_virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step1/A01_s001_w2_z001_t001_SavedDistance.tif", + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step1/A01_s001_w2_z001_t001_SavedDistance.tif", + "source_metadata": { + "filename": "checkpoints_step1/A01_s001_w2_z001_t001_SavedDistance.tif", + "virtual_path": "checkpoints_step1/A01_s001_w2_z001_t001_SavedDistance.tif", + "full_virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step1/A01_s001_w2_z001_t001_SavedDistance.tif", + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step1/A01_s001_w2_z001_t001_SavedDistance.tif", + "type": "Image", + "OpenHCSSourceVoxelSpacingZYX": "1.3555999999999999,1.3555999999999999", + "OpenHCSSourceVoxelSpacingUnit": "micrometers", + "OpenHCSSourceFilterPaths": { + "0": "A01_SavedIPO_step0.labels.tif", + "1": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v3/outputs/ipo/seed_openhcs/checkpoints_results/A01_SavedIPO_step0.labels.tif" + }, + "source_alias": "SavedImage", + "extension": ".tif", + "site": 1, + "channel": 2, + "z_index": 1, + "timepoint": 1, + "well": "A01", + "size": "335 B", + "modified": "2026-10-03T23:29:49" + }, + "shape": [ + 32, + 32 + ], + "resolution_shape": [ + 32, + 32 + ], + "dtype": "float32", + "minimum": 0.0, + "maximum": 3.0, + "mean": 0.0478515625, + "requested_resolution_index": null, + "selected_resolution_index": 0, + "resolution_count": 1, + "downsample_yx": [ + 1.0, + 1.0 + ], + "statistics_scope": "source_resolution", + "sample_origin_yx": [ + 0, + 0 + ], + "sample_shape": [ + 2, + 2 + ], + "sample_included": true, + "sample_values": [ + [ + 0.0, + 0.0 + ], + [ + 0.0, + 0.0 + ] + ], + "sample_omitted_reason": null + }, + "isError": false + } + }, + { + "tool": "openhcs_sample_plate_image", + "arguments": { + "plate_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs", + "image_path": "checkpoints_step1/A01_s001_w2_z001_t001_SavedDistance.tif", + "microscope_type": "auto", + "y": 0, + "x": 0, + "height": 2, + "width": 2, + "max_array_elements": 4, + "include_array_values": true + }, + "response": { + "content": [ + { + "type": "text", + "text": "{\n \"schema_version\": \"openhcs.agent.v1\",\n \"errors\": [],\n \"warnings\": [],\n \"plate_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs\",\n \"requested_image_path\": \"checkpoints_step1/A01_s001_w2_z001_t001_SavedDistance.tif\",\n \"virtual_path\": \"checkpoints_step1/A01_s001_w2_z001_t001_SavedDistance.tif\",\n \"full_virtual_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step1/A01_s001_w2_z001_t001_SavedDistance.tif\",\n \"source_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step1/A01_s001_w2_z001_t001_SavedDistance.tif\",\n \"source_metadata\": {\n \"filename\": \"checkpoints_step1/A01_s001_w2_z001_t001_SavedDistance.tif\",\n \"virtual_path\": \"checkpoints_step1/A01_s001_w2_z001_t001_SavedDistance.tif\",\n \"full_virtual_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step1/A01_s001_w2_z001_t001_SavedDistance.tif\",\n \"source_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step1/A01_s001_w2_z001_t001_SavedDistance.tif\",\n \"type\": \"Image\",\n \"OpenHCSSourceVoxelSpacingZYX\": \"1.3555999999999999,1.3555999999999999\",\n \"OpenHCSSourceVoxelSpacingUnit\": \"micrometers\",\n \"OpenHCSSourceFilterPaths\": {\n \"0\": \"A01_SavedIPO_step0.labels.tif\",\n \"1\": \"/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v3/outputs/ipo/seed_openhcs/checkpoints_results/A01_SavedIPO_step0.labels.tif\"\n },\n \"source_alias\": \"SavedImage\",\n \"extension\": \".tif\",\n \"site\": 1,\n \"channel\": 2,\n \"z_index\": 1,\n \"timepoint\": 1,\n \"well\": \"A01\",\n \"size\": \"335 B\",\n \"modified\": \"2026-10-03T23:29:49\"\n },\n \"shape\": [\n 32,\n 32\n ],\n \"resolution_shape\": [\n 32,\n 32\n ],\n \"dtype\": \"float32\",\n \"minimum\": 0.0,\n \"maximum\": 3.0,\n \"mean\": 0.0478515625,\n \"requested_resolution_index\": null,\n \"selected_resolution_index\": 0,\n \"resolution_count\": 1,\n \"downsample_yx\": [\n 1.0,\n 1.0\n ],\n \"statistics_scope\": \"source_resolution\",\n \"sample_origin_yx\": [\n 0,\n 0\n ],\n \"sample_shape\": [\n 2,\n 2\n ],\n \"sample_included\": true,\n \"sample_values\": [\n [\n 0.0,\n 0.0\n ],\n [\n 0.0,\n 0.0\n ]\n ],\n \"sample_omitted_reason\": null\n}" + } + ], + "structuredContent": { + "schema_version": "openhcs.agent.v1", + "errors": [], + "warnings": [], + "plate_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs", + "requested_image_path": "checkpoints_step1/A01_s001_w2_z001_t001_SavedDistance.tif", + "virtual_path": "checkpoints_step1/A01_s001_w2_z001_t001_SavedDistance.tif", + "full_virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step1/A01_s001_w2_z001_t001_SavedDistance.tif", + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step1/A01_s001_w2_z001_t001_SavedDistance.tif", + "source_metadata": { + "filename": "checkpoints_step1/A01_s001_w2_z001_t001_SavedDistance.tif", + "virtual_path": "checkpoints_step1/A01_s001_w2_z001_t001_SavedDistance.tif", + "full_virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step1/A01_s001_w2_z001_t001_SavedDistance.tif", + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step1/A01_s001_w2_z001_t001_SavedDistance.tif", + "type": "Image", + "OpenHCSSourceVoxelSpacingZYX": "1.3555999999999999,1.3555999999999999", + "OpenHCSSourceVoxelSpacingUnit": "micrometers", + "OpenHCSSourceFilterPaths": { + "0": "A01_SavedIPO_step0.labels.tif", + "1": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v3/outputs/ipo/seed_openhcs/checkpoints_results/A01_SavedIPO_step0.labels.tif" + }, + "source_alias": "SavedImage", + "extension": ".tif", + "site": 1, + "channel": 2, + "z_index": 1, + "timepoint": 1, + "well": "A01", + "size": "335 B", + "modified": "2026-10-03T23:29:49" + }, + "shape": [ + 32, + 32 + ], + "resolution_shape": [ + 32, + 32 + ], + "dtype": "float32", + "minimum": 0.0, + "maximum": 3.0, + "mean": 0.0478515625, + "requested_resolution_index": null, + "selected_resolution_index": 0, + "resolution_count": 1, + "downsample_yx": [ + 1.0, + 1.0 + ], + "statistics_scope": "source_resolution", + "sample_origin_yx": [ + 0, + 0 + ], + "sample_shape": [ + 2, + 2 + ], + "sample_included": true, + "sample_values": [ + [ + 0.0, + 0.0 + ], + [ + 0.0, + 0.0 + ] + ], + "sample_omitted_reason": null + }, + "isError": false + } + }, + { + "tool": "openhcs_sample_plate_image", + "arguments": { + "plate_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs", + "image_path": "checkpoints_step2/A01_s001_w2_z001_t001_ResizedDistance.tif", + "microscope_type": "auto", + "y": 0, + "x": 0, + "height": 2, + "width": 2, + "max_array_elements": 4, + "include_array_values": true + }, + "response": { + "content": [ + { + "type": "text", + "text": "{\n \"schema_version\": \"openhcs.agent.v1\",\n \"errors\": [],\n \"warnings\": [],\n \"plate_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs\",\n \"requested_image_path\": \"checkpoints_step2/A01_s001_w2_z001_t001_ResizedDistance.tif\",\n \"virtual_path\": \"checkpoints_step2/A01_s001_w2_z001_t001_ResizedDistance.tif\",\n \"full_virtual_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step2/A01_s001_w2_z001_t001_ResizedDistance.tif\",\n \"source_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step2/A01_s001_w2_z001_t001_ResizedDistance.tif\",\n \"source_metadata\": {\n \"filename\": \"checkpoints_step2/A01_s001_w2_z001_t001_ResizedDistance.tif\",\n \"virtual_path\": \"checkpoints_step2/A01_s001_w2_z001_t001_ResizedDistance.tif\",\n \"full_virtual_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step2/A01_s001_w2_z001_t001_ResizedDistance.tif\",\n \"source_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step2/A01_s001_w2_z001_t001_ResizedDistance.tif\",\n \"type\": \"Image\",\n \"OpenHCSSourceVoxelSpacingZYX\": \"1.3555999999999999,1.3555999999999999\",\n \"OpenHCSSourceVoxelSpacingUnit\": \"micrometers\",\n \"OpenHCSSourceFilterPaths\": {\n \"0\": \"A01_SavedIPO_step0.labels.tif\",\n \"1\": \"/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v3/outputs/ipo/seed_openhcs/checkpoints_results/A01_SavedIPO_step0.labels.tif\"\n },\n \"source_alias\": \"SavedImage\",\n \"extension\": \".tif\",\n \"site\": 1,\n \"channel\": 2,\n \"z_index\": 1,\n \"timepoint\": 1,\n \"well\": \"A01\",\n \"size\": \"356 B\",\n \"modified\": \"2026-10-03T23:29:49\"\n },\n \"shape\": [\n 64,\n 64\n ],\n \"resolution_shape\": [\n 64,\n 64\n ],\n \"dtype\": \"float32\",\n \"minimum\": 0.0,\n \"maximum\": 3.0,\n \"mean\": 0.0478515625,\n \"requested_resolution_index\": null,\n \"selected_resolution_index\": 0,\n \"resolution_count\": 1,\n \"downsample_yx\": [\n 1.0,\n 1.0\n ],\n \"statistics_scope\": \"source_resolution\",\n \"sample_origin_yx\": [\n 0,\n 0\n ],\n \"sample_shape\": [\n 2,\n 2\n ],\n \"sample_included\": true,\n \"sample_values\": [\n [\n 0.0,\n 0.0\n ],\n [\n 0.0,\n 0.0\n ]\n ],\n \"sample_omitted_reason\": null\n}" + } + ], + "structuredContent": { + "schema_version": "openhcs.agent.v1", + "errors": [], + "warnings": [], + "plate_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs", + "requested_image_path": "checkpoints_step2/A01_s001_w2_z001_t001_ResizedDistance.tif", + "virtual_path": "checkpoints_step2/A01_s001_w2_z001_t001_ResizedDistance.tif", + "full_virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step2/A01_s001_w2_z001_t001_ResizedDistance.tif", + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step2/A01_s001_w2_z001_t001_ResizedDistance.tif", + "source_metadata": { + "filename": "checkpoints_step2/A01_s001_w2_z001_t001_ResizedDistance.tif", + "virtual_path": "checkpoints_step2/A01_s001_w2_z001_t001_ResizedDistance.tif", + "full_virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step2/A01_s001_w2_z001_t001_ResizedDistance.tif", + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step2/A01_s001_w2_z001_t001_ResizedDistance.tif", + "type": "Image", + "OpenHCSSourceVoxelSpacingZYX": "1.3555999999999999,1.3555999999999999", + "OpenHCSSourceVoxelSpacingUnit": "micrometers", + "OpenHCSSourceFilterPaths": { + "0": "A01_SavedIPO_step0.labels.tif", + "1": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v3/outputs/ipo/seed_openhcs/checkpoints_results/A01_SavedIPO_step0.labels.tif" + }, + "source_alias": "SavedImage", + "extension": ".tif", + "site": 1, + "channel": 2, + "z_index": 1, + "timepoint": 1, + "well": "A01", + "size": "356 B", + "modified": "2026-10-03T23:29:49" + }, + "shape": [ + 64, + 64 + ], + "resolution_shape": [ + 64, + 64 + ], + "dtype": "float32", + "minimum": 0.0, + "maximum": 3.0, + "mean": 0.0478515625, + "requested_resolution_index": null, + "selected_resolution_index": 0, + "resolution_count": 1, + "downsample_yx": [ + 1.0, + 1.0 + ], + "statistics_scope": "source_resolution", + "sample_origin_yx": [ + 0, + 0 + ], + "sample_shape": [ + 2, + 2 + ], + "sample_included": true, + "sample_values": [ + [ + 0.0, + 0.0 + ], + [ + 0.0, + 0.0 + ] + ], + "sample_omitted_reason": null + }, + "isError": false + } + }, + { + "tool": "openhcs_sample_plate_image", + "arguments": { + "plate_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs", + "image_path": "checkpoints_step2/A01_s001_w2_z001_t001_ResizedDistance.tif", + "microscope_type": "auto", + "y": 0, + "x": 0, + "height": 2, + "width": 2, + "max_array_elements": 4, + "include_array_values": true + }, + "response": { + "content": [ + { + "type": "text", + "text": "{\n \"schema_version\": \"openhcs.agent.v1\",\n \"errors\": [],\n \"warnings\": [],\n \"plate_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs\",\n \"requested_image_path\": \"checkpoints_step2/A01_s001_w2_z001_t001_ResizedDistance.tif\",\n \"virtual_path\": \"checkpoints_step2/A01_s001_w2_z001_t001_ResizedDistance.tif\",\n \"full_virtual_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step2/A01_s001_w2_z001_t001_ResizedDistance.tif\",\n \"source_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step2/A01_s001_w2_z001_t001_ResizedDistance.tif\",\n \"source_metadata\": {\n \"filename\": \"checkpoints_step2/A01_s001_w2_z001_t001_ResizedDistance.tif\",\n \"virtual_path\": \"checkpoints_step2/A01_s001_w2_z001_t001_ResizedDistance.tif\",\n \"full_virtual_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step2/A01_s001_w2_z001_t001_ResizedDistance.tif\",\n \"source_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step2/A01_s001_w2_z001_t001_ResizedDistance.tif\",\n \"type\": \"Image\",\n \"OpenHCSSourceVoxelSpacingZYX\": \"1.3555999999999999,1.3555999999999999\",\n \"OpenHCSSourceVoxelSpacingUnit\": \"micrometers\",\n \"OpenHCSSourceFilterPaths\": {\n \"0\": \"A01_SavedIPO_step0.labels.tif\",\n \"1\": \"/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v3/outputs/ipo/seed_openhcs/checkpoints_results/A01_SavedIPO_step0.labels.tif\"\n },\n \"source_alias\": \"SavedImage\",\n \"extension\": \".tif\",\n \"site\": 1,\n \"channel\": 2,\n \"z_index\": 1,\n \"timepoint\": 1,\n \"well\": \"A01\",\n \"size\": \"356 B\",\n \"modified\": \"2026-10-03T23:29:49\"\n },\n \"shape\": [\n 64,\n 64\n ],\n \"resolution_shape\": [\n 64,\n 64\n ],\n \"dtype\": \"float32\",\n \"minimum\": 0.0,\n \"maximum\": 3.0,\n \"mean\": 0.0478515625,\n \"requested_resolution_index\": null,\n \"selected_resolution_index\": 0,\n \"resolution_count\": 1,\n \"downsample_yx\": [\n 1.0,\n 1.0\n ],\n \"statistics_scope\": \"source_resolution\",\n \"sample_origin_yx\": [\n 0,\n 0\n ],\n \"sample_shape\": [\n 2,\n 2\n ],\n \"sample_included\": true,\n \"sample_values\": [\n [\n 0.0,\n 0.0\n ],\n [\n 0.0,\n 0.0\n ]\n ],\n \"sample_omitted_reason\": null\n}" + } + ], + "structuredContent": { + "schema_version": "openhcs.agent.v1", + "errors": [], + "warnings": [], + "plate_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs", + "requested_image_path": "checkpoints_step2/A01_s001_w2_z001_t001_ResizedDistance.tif", + "virtual_path": "checkpoints_step2/A01_s001_w2_z001_t001_ResizedDistance.tif", + "full_virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step2/A01_s001_w2_z001_t001_ResizedDistance.tif", + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step2/A01_s001_w2_z001_t001_ResizedDistance.tif", + "source_metadata": { + "filename": "checkpoints_step2/A01_s001_w2_z001_t001_ResizedDistance.tif", + "virtual_path": "checkpoints_step2/A01_s001_w2_z001_t001_ResizedDistance.tif", + "full_virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step2/A01_s001_w2_z001_t001_ResizedDistance.tif", + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step2/A01_s001_w2_z001_t001_ResizedDistance.tif", + "type": "Image", + "OpenHCSSourceVoxelSpacingZYX": "1.3555999999999999,1.3555999999999999", + "OpenHCSSourceVoxelSpacingUnit": "micrometers", + "OpenHCSSourceFilterPaths": { + "0": "A01_SavedIPO_step0.labels.tif", + "1": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v3/outputs/ipo/seed_openhcs/checkpoints_results/A01_SavedIPO_step0.labels.tif" + }, + "source_alias": "SavedImage", + "extension": ".tif", + "site": 1, + "channel": 2, + "z_index": 1, + "timepoint": 1, + "well": "A01", + "size": "356 B", + "modified": "2026-10-03T23:29:49" + }, + "shape": [ + 64, + 64 + ], + "resolution_shape": [ + 64, + 64 + ], + "dtype": "float32", + "minimum": 0.0, + "maximum": 3.0, + "mean": 0.0478515625, + "requested_resolution_index": null, + "selected_resolution_index": 0, + "resolution_count": 1, + "downsample_yx": [ + 1.0, + 1.0 + ], + "statistics_scope": "source_resolution", + "sample_origin_yx": [ + 0, + 0 + ], + "sample_shape": [ + 2, + 2 + ], + "sample_included": true, + "sample_values": [ + [ + 0.0, + 0.0 + ], + [ + 0.0, + 0.0 + ] + ], + "sample_omitted_reason": null + }, + "isError": false + } + }, + { + "tool": "openhcs_sample_plate_image", + "arguments": { + "plate_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs", + "image_path": "checkpoints_step3/A01_s001_w2_z001_t001_ResizedConsumer.tif", + "microscope_type": "auto", + "y": 0, + "x": 0, + "height": 2, + "width": 2, + "max_array_elements": 4, + "include_array_values": true + }, + "response": { + "content": [ + { + "type": "text", + "text": "{\n \"schema_version\": \"openhcs.agent.v1\",\n \"errors\": [],\n \"warnings\": [],\n \"plate_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs\",\n \"requested_image_path\": \"checkpoints_step3/A01_s001_w2_z001_t001_ResizedConsumer.tif\",\n \"virtual_path\": \"checkpoints_step3/A01_s001_w2_z001_t001_ResizedConsumer.tif\",\n \"full_virtual_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step3/A01_s001_w2_z001_t001_ResizedConsumer.tif\",\n \"source_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step3/A01_s001_w2_z001_t001_ResizedConsumer.tif\",\n \"source_metadata\": {\n \"filename\": \"checkpoints_step3/A01_s001_w2_z001_t001_ResizedConsumer.tif\",\n \"virtual_path\": \"checkpoints_step3/A01_s001_w2_z001_t001_ResizedConsumer.tif\",\n \"full_virtual_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step3/A01_s001_w2_z001_t001_ResizedConsumer.tif\",\n \"source_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step3/A01_s001_w2_z001_t001_ResizedConsumer.tif\",\n \"type\": \"Image\",\n \"OpenHCSSourceVoxelSpacingZYX\": \"1.3555999999999999,1.3555999999999999\",\n \"OpenHCSSourceVoxelSpacingUnit\": \"micrometers\",\n \"OpenHCSSourceFilterPaths\": {\n \"0\": \"A01_SavedIPO_step0.labels.tif\",\n \"1\": \"/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v3/outputs/ipo/seed_openhcs/checkpoints_results/A01_SavedIPO_step0.labels.tif\"\n },\n \"source_alias\": \"SavedImage\",\n \"extension\": \".tif\",\n \"site\": 1,\n \"channel\": 2,\n \"z_index\": 1,\n \"timepoint\": 1,\n \"well\": \"A01\",\n \"source_artifact_type\": \"image\",\n \"size\": \"356 B\",\n \"modified\": \"2026-10-03T23:29:49\"\n },\n \"shape\": [\n 64,\n 64\n ],\n \"resolution_shape\": [\n 64,\n 64\n ],\n \"dtype\": \"float32\",\n \"minimum\": 0.0,\n \"maximum\": 3.0,\n \"mean\": 0.0478515625,\n \"requested_resolution_index\": null,\n \"selected_resolution_index\": 0,\n \"resolution_count\": 1,\n \"downsample_yx\": [\n 1.0,\n 1.0\n ],\n \"statistics_scope\": \"source_resolution\",\n \"sample_origin_yx\": [\n 0,\n 0\n ],\n \"sample_shape\": [\n 2,\n 2\n ],\n \"sample_included\": true,\n \"sample_values\": [\n [\n 0.0,\n 0.0\n ],\n [\n 0.0,\n 0.0\n ]\n ],\n \"sample_omitted_reason\": null\n}" + } + ], + "structuredContent": { + "schema_version": "openhcs.agent.v1", + "errors": [], + "warnings": [], + "plate_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs", + "requested_image_path": "checkpoints_step3/A01_s001_w2_z001_t001_ResizedConsumer.tif", + "virtual_path": "checkpoints_step3/A01_s001_w2_z001_t001_ResizedConsumer.tif", + "full_virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step3/A01_s001_w2_z001_t001_ResizedConsumer.tif", + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step3/A01_s001_w2_z001_t001_ResizedConsumer.tif", + "source_metadata": { + "filename": "checkpoints_step3/A01_s001_w2_z001_t001_ResizedConsumer.tif", + "virtual_path": "checkpoints_step3/A01_s001_w2_z001_t001_ResizedConsumer.tif", + "full_virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step3/A01_s001_w2_z001_t001_ResizedConsumer.tif", + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step3/A01_s001_w2_z001_t001_ResizedConsumer.tif", + "type": "Image", + "OpenHCSSourceVoxelSpacingZYX": "1.3555999999999999,1.3555999999999999", + "OpenHCSSourceVoxelSpacingUnit": "micrometers", + "OpenHCSSourceFilterPaths": { + "0": "A01_SavedIPO_step0.labels.tif", + "1": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v3/outputs/ipo/seed_openhcs/checkpoints_results/A01_SavedIPO_step0.labels.tif" + }, + "source_alias": "SavedImage", + "extension": ".tif", + "site": 1, + "channel": 2, + "z_index": 1, + "timepoint": 1, + "well": "A01", + "source_artifact_type": "image", + "size": "356 B", + "modified": "2026-10-03T23:29:49" + }, + "shape": [ + 64, + 64 + ], + "resolution_shape": [ + 64, + 64 + ], + "dtype": "float32", + "minimum": 0.0, + "maximum": 3.0, + "mean": 0.0478515625, + "requested_resolution_index": null, + "selected_resolution_index": 0, + "resolution_count": 1, + "downsample_yx": [ + 1.0, + 1.0 + ], + "statistics_scope": "source_resolution", + "sample_origin_yx": [ + 0, + 0 + ], + "sample_shape": [ + 2, + 2 + ], + "sample_included": true, + "sample_values": [ + [ + 0.0, + 0.0 + ], + [ + 0.0, + 0.0 + ] + ], + "sample_omitted_reason": null + }, + "isError": false + } + }, + { + "tool": "openhcs_sample_plate_image", + "arguments": { + "plate_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs", + "image_path": "images/A01_s001_w2_z001_t001_ResizedConsumer.tif", + "microscope_type": "auto", + "y": 0, + "x": 0, + "height": 2, + "width": 2, + "max_array_elements": 4, + "include_array_values": true + }, + "response": { + "content": [ + { + "type": "text", + "text": "{\n \"schema_version\": \"openhcs.agent.v1\",\n \"errors\": [],\n \"warnings\": [],\n \"plate_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs\",\n \"requested_image_path\": \"images/A01_s001_w2_z001_t001_ResizedConsumer.tif\",\n \"virtual_path\": \"images/A01_s001_w2_z001_t001_ResizedConsumer.tif\",\n \"full_virtual_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/images/A01_s001_w2_z001_t001_ResizedConsumer.tif\",\n \"source_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/images/A01_s001_w2_z001_t001_ResizedConsumer.tif\",\n \"source_metadata\": {\n \"filename\": \"images/A01_s001_w2_z001_t001_ResizedConsumer.tif\",\n \"virtual_path\": \"images/A01_s001_w2_z001_t001_ResizedConsumer.tif\",\n \"full_virtual_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/images/A01_s001_w2_z001_t001_ResizedConsumer.tif\",\n \"source_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/images/A01_s001_w2_z001_t001_ResizedConsumer.tif\",\n \"type\": \"Image\",\n \"OpenHCSSourceVoxelSpacingZYX\": \"1.3555999999999999,1.3555999999999999\",\n \"OpenHCSSourceVoxelSpacingUnit\": \"micrometers\",\n \"OpenHCSSourceFilterPaths\": {\n \"0\": \"A01_SavedIPO_step0.labels.tif\",\n \"1\": \"/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v3/outputs/ipo/seed_openhcs/checkpoints_results/A01_SavedIPO_step0.labels.tif\"\n },\n \"source_alias\": \"SavedImage\",\n \"extension\": \".tif\",\n \"site\": 1,\n \"channel\": 2,\n \"z_index\": 1,\n \"timepoint\": 1,\n \"well\": \"A01\",\n \"size\": \"356 B\",\n \"modified\": \"2026-10-03T23:29:49\"\n },\n \"shape\": [\n 64,\n 64\n ],\n \"resolution_shape\": [\n 64,\n 64\n ],\n \"dtype\": \"float32\",\n \"minimum\": 0.0,\n \"maximum\": 3.0,\n \"mean\": 0.0478515625,\n \"requested_resolution_index\": null,\n \"selected_resolution_index\": 0,\n \"resolution_count\": 1,\n \"downsample_yx\": [\n 1.0,\n 1.0\n ],\n \"statistics_scope\": \"source_resolution\",\n \"sample_origin_yx\": [\n 0,\n 0\n ],\n \"sample_shape\": [\n 2,\n 2\n ],\n \"sample_included\": true,\n \"sample_values\": [\n [\n 0.0,\n 0.0\n ],\n [\n 0.0,\n 0.0\n ]\n ],\n \"sample_omitted_reason\": null\n}" + } + ], + "structuredContent": { + "schema_version": "openhcs.agent.v1", + "errors": [], + "warnings": [], + "plate_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs", + "requested_image_path": "images/A01_s001_w2_z001_t001_ResizedConsumer.tif", + "virtual_path": "images/A01_s001_w2_z001_t001_ResizedConsumer.tif", + "full_virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/images/A01_s001_w2_z001_t001_ResizedConsumer.tif", + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/images/A01_s001_w2_z001_t001_ResizedConsumer.tif", + "source_metadata": { + "filename": "images/A01_s001_w2_z001_t001_ResizedConsumer.tif", + "virtual_path": "images/A01_s001_w2_z001_t001_ResizedConsumer.tif", + "full_virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/images/A01_s001_w2_z001_t001_ResizedConsumer.tif", + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/images/A01_s001_w2_z001_t001_ResizedConsumer.tif", + "type": "Image", + "OpenHCSSourceVoxelSpacingZYX": "1.3555999999999999,1.3555999999999999", + "OpenHCSSourceVoxelSpacingUnit": "micrometers", + "OpenHCSSourceFilterPaths": { + "0": "A01_SavedIPO_step0.labels.tif", + "1": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v3/outputs/ipo/seed_openhcs/checkpoints_results/A01_SavedIPO_step0.labels.tif" + }, + "source_alias": "SavedImage", + "extension": ".tif", + "site": 1, + "channel": 2, + "z_index": 1, + "timepoint": 1, + "well": "A01", + "size": "356 B", + "modified": "2026-10-03T23:29:49" + }, + "shape": [ + 64, + 64 + ], + "resolution_shape": [ + 64, + 64 + ], + "dtype": "float32", + "minimum": 0.0, + "maximum": 3.0, + "mean": 0.0478515625, + "requested_resolution_index": null, + "selected_resolution_index": 0, + "resolution_count": 1, + "downsample_yx": [ + 1.0, + 1.0 + ], + "statistics_scope": "source_resolution", + "sample_origin_yx": [ + 0, + 0 + ], + "sample_shape": [ + 2, + 2 + ], + "sample_included": true, + "sample_values": [ + [ + 0.0, + 0.0 + ], + [ + 0.0, + 0.0 + ] + ], + "sample_omitted_reason": null + }, + "isError": false + } + }, + { + "tool": "openhcs_sample_plate_image", + "arguments": { + "plate_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs", + "image_path": "images/A01_s001_w2_z001_t001_ResizedConsumer.tif", + "microscope_type": "auto", + "y": 0, + "x": 0, + "height": 2, + "width": 2, + "max_array_elements": 4, + "include_array_values": true + }, + "response": { + "content": [ + { + "type": "text", + "text": "{\n \"schema_version\": \"openhcs.agent.v1\",\n \"errors\": [],\n \"warnings\": [],\n \"plate_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs\",\n \"requested_image_path\": \"images/A01_s001_w2_z001_t001_ResizedConsumer.tif\",\n \"virtual_path\": \"images/A01_s001_w2_z001_t001_ResizedConsumer.tif\",\n \"full_virtual_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/images/A01_s001_w2_z001_t001_ResizedConsumer.tif\",\n \"source_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/images/A01_s001_w2_z001_t001_ResizedConsumer.tif\",\n \"source_metadata\": {\n \"filename\": \"images/A01_s001_w2_z001_t001_ResizedConsumer.tif\",\n \"virtual_path\": \"images/A01_s001_w2_z001_t001_ResizedConsumer.tif\",\n \"full_virtual_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/images/A01_s001_w2_z001_t001_ResizedConsumer.tif\",\n \"source_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/images/A01_s001_w2_z001_t001_ResizedConsumer.tif\",\n \"type\": \"Image\",\n \"OpenHCSSourceVoxelSpacingZYX\": \"1.3555999999999999,1.3555999999999999\",\n \"OpenHCSSourceVoxelSpacingUnit\": \"micrometers\",\n \"OpenHCSSourceFilterPaths\": {\n \"0\": \"A01_SavedIPO_step0.labels.tif\",\n \"1\": \"/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v3/outputs/ipo/seed_openhcs/checkpoints_results/A01_SavedIPO_step0.labels.tif\"\n },\n \"source_alias\": \"SavedImage\",\n \"extension\": \".tif\",\n \"site\": 1,\n \"channel\": 2,\n \"z_index\": 1,\n \"timepoint\": 1,\n \"well\": \"A01\",\n \"size\": \"356 B\",\n \"modified\": \"2026-10-03T23:29:49\"\n },\n \"shape\": [\n 64,\n 64\n ],\n \"resolution_shape\": [\n 64,\n 64\n ],\n \"dtype\": \"float32\",\n \"minimum\": 0.0,\n \"maximum\": 3.0,\n \"mean\": 0.0478515625,\n \"requested_resolution_index\": null,\n \"selected_resolution_index\": 0,\n \"resolution_count\": 1,\n \"downsample_yx\": [\n 1.0,\n 1.0\n ],\n \"statistics_scope\": \"source_resolution\",\n \"sample_origin_yx\": [\n 0,\n 0\n ],\n \"sample_shape\": [\n 2,\n 2\n ],\n \"sample_included\": true,\n \"sample_values\": [\n [\n 0.0,\n 0.0\n ],\n [\n 0.0,\n 0.0\n ]\n ],\n \"sample_omitted_reason\": null\n}" + } + ], + "structuredContent": { + "schema_version": "openhcs.agent.v1", + "errors": [], + "warnings": [], + "plate_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs", + "requested_image_path": "images/A01_s001_w2_z001_t001_ResizedConsumer.tif", + "virtual_path": "images/A01_s001_w2_z001_t001_ResizedConsumer.tif", + "full_virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/images/A01_s001_w2_z001_t001_ResizedConsumer.tif", + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/images/A01_s001_w2_z001_t001_ResizedConsumer.tif", + "source_metadata": { + "filename": "images/A01_s001_w2_z001_t001_ResizedConsumer.tif", + "virtual_path": "images/A01_s001_w2_z001_t001_ResizedConsumer.tif", + "full_virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/images/A01_s001_w2_z001_t001_ResizedConsumer.tif", + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/images/A01_s001_w2_z001_t001_ResizedConsumer.tif", + "type": "Image", + "OpenHCSSourceVoxelSpacingZYX": "1.3555999999999999,1.3555999999999999", + "OpenHCSSourceVoxelSpacingUnit": "micrometers", + "OpenHCSSourceFilterPaths": { + "0": "A01_SavedIPO_step0.labels.tif", + "1": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v3/outputs/ipo/seed_openhcs/checkpoints_results/A01_SavedIPO_step0.labels.tif" + }, + "source_alias": "SavedImage", + "extension": ".tif", + "site": 1, + "channel": 2, + "z_index": 1, + "timepoint": 1, + "well": "A01", + "size": "356 B", + "modified": "2026-10-03T23:29:49" + }, + "shape": [ + 64, + 64 + ], + "resolution_shape": [ + 64, + 64 + ], + "dtype": "float32", + "minimum": 0.0, + "maximum": 3.0, + "mean": 0.0478515625, + "requested_resolution_index": null, + "selected_resolution_index": 0, + "resolution_count": 1, + "downsample_yx": [ + 1.0, + 1.0 + ], + "statistics_scope": "source_resolution", + "sample_origin_yx": [ + 0, + 0 + ], + "sample_shape": [ + 2, + 2 + ], + "sample_included": true, + "sample_values": [ + [ + 0.0, + 0.0 + ], + [ + 0.0, + 0.0 + ] + ], + "sample_omitted_reason": null + }, + "isError": false + } + } + ], + "owned_runtime_terminal": true, + "mcp_processes": [ + { + "pid": 3739957, + "source": "/var/tmp/openhcs-resolved-pipeline-owner-20261004" + } + ], + "failure": null, + "owned_runtime_handle": { + "connection": { + "host": "127.0.0.1", + "port": 6559, + "transport_mode": "tcp", + "persistent": true + }, + "process_identity": { + "pid": 3740222, + "create_time": 1791084576.07 + }, + "launch_plan": { + "runtime_dir": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/owned/data/openhcs", + "log_file": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/owned/data/openhcs/logs/openhcs_zmq_server_port_6559_1791084576159471156.log", + "startup_status_file": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/owned/data/openhcs/logs/openhcs_zmq_server_port_6559_1791084576159471156.startup.jsonl", + "storage_dir": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/owned/data/openhcs/custom_functions", + "registry_cache_dir": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/owned/cache/metaclass-registry", + "transport_write_paths": [ + "/home/ts/.openhcs/tcp/7559.startup.lock", + "/home/ts/.openhcs/tcp/6559.startup.lock" + ] + } + }, + "startup_catalog_complete_before_compile": true, + "execution_status": { + "schema_version": "openhcs.agent.v1", + "errors": [], + "warnings": [ + { + "code": "headless_execution_did_not_update_plate_manager", + "message": "This direct execution session completed without adding the output plate to the running UI PlateManager.", + "hint": "For user-visible work in an open UI, load plate_paths and pipeline_data through the plate_manager.orchestrator_config code document, then run init/compile/run with openhcs_ui_selected_plate_workflow." + } + ], + "session_id": "session-1", + "job_id": "job-2", + "kind": "execute", + "uri": "openhcs://execution/jobs/job-2", + "server_execution_id": "4a0ea6ec-301b-436f-b6f3-980de2344060", + "status": "complete", + "response": { + "status": "ok", + "execution": { + "execution_id": "4a0ea6ec-301b-436f-b6f3-980de2344060", + "plate_id": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/input", + "client_address": null, + "status": "complete", + "start_time": 1791082826.8191087, + "end_time": 1791082827.4816234, + "error": null, + "compile_only": false, + "results_summary": { + "well_count": 1, + "wells": [ + "A01" + ], + "output_plate_root": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs/input_openhcs", + "auto_add_output_plate_to_plate_manager": false, + "runtime_observation_export_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outcomes.pkl.gz", + "runtime_observation_export_scope": "outcomes" + } + } + }, + "progress": { + "sequence": 24, + "event": { + "execution_id": "4a0ea6ec-301b-436f-b6f3-980de2344060", + "plate_id": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/input", + "axis_id": "", + "step_name": "pipeline", + "phase": "success", + "status": "success", + "percent": 100.0, + "completed": 5, + "total": 5, + "timestamp": 1791082827.477402, + "pid": 3580229, + "total_wells": [ + "A01" + ], + "worker_assignments": { + "worker_0": [ + "A01" + ] + } + } + } + }, + "prior_original_435_journey": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/journey.json", + "original_435_processing_not_replayed": true, + "complete_pixel_comparisons": { + "first_public_readback-raw_body_processing_role": { + "artifact": { + "artifact_name": "raw_body_processing_role", + "artifact_type": "ImageArtifactType", + "semantic_kind": "numeric_image_pixels", + "output_filename": "reference_image__raw_body_processing_role.npy", + "comparison": "float pixels: atol=1e-6, rtol=1e-6, zero mismatches" + }, + "reference_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/expected/raw_body_processing_role.npy", + "candidate_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs/input_openhcs/images/A01_s001_w2_z001_t001_raw_body_processing_role.tif", + "reference_shape": [ + 1024, + 1024 + ], + "candidate_shape": [ + 1024, + 1024 + ], + "reference_dtype": "float32", + "candidate_dtype": "float32", + "reference_pixel_digest": "2343ab163aaf95471d5052efb2345302db10dd9488170a11bcece25974173fed", + "candidate_pixel_digest": "2343ab163aaf95471d5052efb2345302db10dd9488170a11bcece25974173fed", + "compared_pixel_count": 1048576, + "different_pixel_count": null, + "out_of_tolerance_pixel_count": 0, + "max_abs_difference": 0.0, + "equivalent": true + }, + "first_public_readback-capped_outgrowth_processing_role": { + "artifact": { + "artifact_name": "capped_outgrowth_processing_role", + "artifact_type": "ImageArtifactType", + "semantic_kind": "numeric_image_pixels", + "output_filename": "reference_image__capped_outgrowth_processing_role.npy", + "comparison": "float pixels: atol=1e-6, rtol=1e-6, zero mismatches" + }, + "reference_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/expected/capped_outgrowth_processing_role.npy", + "candidate_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs/input_openhcs/images/A01_s001_w2_z001_t001_capped_outgrowth_processing_role.tif", + "reference_shape": [ + 1024, + 1024 + ], + "candidate_shape": [ + 1024, + 1024 + ], + "reference_dtype": "float32", + "candidate_dtype": "float32", + "reference_pixel_digest": "59558fefdf8dfbb1f4c887f25912f10d6943f92569923228ee7012f191cd4253", + "candidate_pixel_digest": "3eeb9c453653d782e432e177f8ccfa392cceebc0ba33d97a025461ce2abf7dfb", + "compared_pixel_count": 1048576, + "different_pixel_count": null, + "out_of_tolerance_pixel_count": 0, + "max_abs_difference": 1.1920928955078125e-07, + "equivalent": true + }, + "fresh_process_reopen-raw_body_processing_role": { + "artifact": { + "artifact_name": "raw_body_processing_role", + "artifact_type": "ImageArtifactType", + "semantic_kind": "numeric_image_pixels", + "output_filename": "reference_image__raw_body_processing_role.npy", + "comparison": "float pixels: atol=1e-6, rtol=1e-6, zero mismatches" + }, + "reference_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/expected/raw_body_processing_role.npy", + "candidate_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs/input_openhcs/images/A01_s001_w2_z001_t001_raw_body_processing_role.tif", + "reference_shape": [ + 1024, + 1024 + ], + "candidate_shape": [ + 1024, + 1024 + ], + "reference_dtype": "float32", + "candidate_dtype": "float32", + "reference_pixel_digest": "2343ab163aaf95471d5052efb2345302db10dd9488170a11bcece25974173fed", + "candidate_pixel_digest": "2343ab163aaf95471d5052efb2345302db10dd9488170a11bcece25974173fed", + "compared_pixel_count": 1048576, + "different_pixel_count": null, + "out_of_tolerance_pixel_count": 0, + "max_abs_difference": 0.0, + "equivalent": true + }, + "fresh_process_reopen-capped_outgrowth_processing_role": { + "artifact": { + "artifact_name": "capped_outgrowth_processing_role", + "artifact_type": "ImageArtifactType", + "semantic_kind": "numeric_image_pixels", + "output_filename": "reference_image__capped_outgrowth_processing_role.npy", + "comparison": "float pixels: atol=1e-6, rtol=1e-6, zero mismatches" + }, + "reference_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/expected/capped_outgrowth_processing_role.npy", + "candidate_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs/input_openhcs/images/A01_s001_w2_z001_t001_capped_outgrowth_processing_role.tif", + "reference_shape": [ + 1024, + 1024 + ], + "candidate_shape": [ + 1024, + 1024 + ], + "reference_dtype": "float32", + "candidate_dtype": "float32", + "reference_pixel_digest": "59558fefdf8dfbb1f4c887f25912f10d6943f92569923228ee7012f191cd4253", + "candidate_pixel_digest": "3eeb9c453653d782e432e177f8ccfa392cceebc0ba33d97a025461ce2abf7dfb", + "compared_pixel_count": 1048576, + "different_pixel_count": null, + "out_of_tolerance_pixel_count": 0, + "max_abs_difference": 1.1920928955078125e-07, + "equivalent": true + } + }, + "first_public_readback": { + "plate": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs/input_openhcs", + "inspection": { + "schema_version": "openhcs.agent.v1", + "errors": [], + "warnings": [ + { + "code": "plate_grid_dimensions_unavailable", + "message": "'grid_dimensions' must be a list of two integers in openhcs_metadata.json", + "hint": null + } + ], + "plate_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs/input_openhcs", + "requested_microscope_type": "auto", + "status": "partial", + "confidence": "high", + "available_microscope_types": [ + "bioformats", + "imagexpress", + "omero", + "openhcsdata", + "opera_phenix", + "source_bindings" + ], + "detected_microscope_type": "openhcsdata", + "handler_class": "OpenHCSMicroscopeHandler", + "parser_class": "SourceSchemaFilenameParser", + "metadata_handler_class": "OpenHCSMetadataHandler", + "root_dir": "", + "compatible_backends": [ + "zarr", + "disk" + ], + "available_backends": [ + "disk" + ], + "metadata_file_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs/input_openhcs/openhcs_metadata.json", + "grid_dimensions": null, + "pixel_size": 1.3556, + "image_files": { + "count": 2, + "sampled_files": [ + "images/A01_s001_w2_z001_t001_capped_outgrowth_processing_role.tif", + "images/A01_s001_w2_z001_t001_raw_body_processing_role.tif" + ], + "sampled_records": [ + { + "virtual_path": "images/A01_s001_w2_z001_t001_capped_outgrowth_processing_role.tif", + "full_virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs/input_openhcs/images/A01_s001_w2_z001_t001_capped_outgrowth_processing_role.tif", + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs/input_openhcs/images/A01_s001_w2_z001_t001_capped_outgrowth_processing_role.tif", + "metadata": { + "filename": "images/A01_s001_w2_z001_t001_capped_outgrowth_processing_role.tif", + "virtual_path": "images/A01_s001_w2_z001_t001_capped_outgrowth_processing_role.tif", + "full_virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs/input_openhcs/images/A01_s001_w2_z001_t001_capped_outgrowth_processing_role.tif", + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs/input_openhcs/images/A01_s001_w2_z001_t001_capped_outgrowth_processing_role.tif", + "type": "Image", + "OpenHCSSourceVoxelSpacingZYX": "1.3555999999999999,1.3555999999999999", + "OpenHCSSourceVoxelSpacingUnit": "micrometers", + "OpenHCSSourceFilterPaths": { + "0": "A01_s001_w2_z001_t001.tif", + "1": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/input/A01_s001_w2_z001_t001.tif" + }, + "source_alias": "FITC", + "extension": ".tif", + "site": 1, + "channel": 2, + "z_index": 1, + "timepoint": 1, + "well": "A01", + "source_artifact_type": "image", + "size": "351.2 KB", + "modified": "2026-10-03T23:00:27" + } + }, + { + "virtual_path": "images/A01_s001_w2_z001_t001_raw_body_processing_role.tif", + "full_virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs/input_openhcs/images/A01_s001_w2_z001_t001_raw_body_processing_role.tif", + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs/input_openhcs/images/A01_s001_w2_z001_t001_raw_body_processing_role.tif", + "metadata": { + "filename": "images/A01_s001_w2_z001_t001_raw_body_processing_role.tif", + "virtual_path": "images/A01_s001_w2_z001_t001_raw_body_processing_role.tif", + "full_virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs/input_openhcs/images/A01_s001_w2_z001_t001_raw_body_processing_role.tif", + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs/input_openhcs/images/A01_s001_w2_z001_t001_raw_body_processing_role.tif", + "type": "Image", + "OpenHCSSourceVoxelSpacingZYX": "1.3555999999999999,1.3555999999999999", + "OpenHCSSourceVoxelSpacingUnit": "micrometers", + "OpenHCSSourceFilterPaths": { + "0": "A01_s001_w2_z001_t001.tif", + "1": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/input/A01_s001_w2_z001_t001.tif" + }, + "source_alias": "FITC", + "extension": ".tif", + "site": 1, + "channel": 2, + "z_index": 1, + "timepoint": 1, + "well": "A01", + "source_artifact_type": "image", + "size": "2.7 MB", + "modified": "2026-10-03T23:00:27" + } + } + ], + "truncated_file_count": 0 + }, + "result_files": { + "count": 0, + "scanned_file_count": 0, + "sampled_files": [], + "sampled_records": [], + "truncated_file_count": 0 + }, + "parse_summary": { + "attempted_file_count": 2, + "skipped_file_count": 0, + "parsed_file_count": 2, + "failed_file_count": 0, + "failure_samples": [], + "truncated_failure_count": 0 + }, + "components": [ + { + "component": "site", + "source": "metadata_and_parsed_filenames", + "count": 1, + "values": [ + { + "key": "1", + "label": null, + "declared_in_metadata": true, + "observed_in_filenames": true + } + ], + "truncated_value_count": 0 + }, + { + "component": "channel", + "source": "metadata_and_parsed_filenames", + "count": 1, + "values": [ + { + "key": "2", + "label": "FITC", + "declared_in_metadata": true, + "observed_in_filenames": true + } + ], + "truncated_value_count": 0 + }, + { + "component": "z_index", + "source": "metadata_and_parsed_filenames", + "count": 1, + "values": [ + { + "key": "1", + "label": null, + "declared_in_metadata": true, + "observed_in_filenames": true + } + ], + "truncated_value_count": 0 + }, + { + "component": "timepoint", + "source": "metadata_and_parsed_filenames", + "count": 1, + "values": [ + { + "key": "1", + "label": null, + "declared_in_metadata": true, + "observed_in_filenames": true + } + ], + "truncated_value_count": 0 + }, + { + "component": "well", + "source": "metadata_and_parsed_filenames", + "count": 1, + "values": [ + { + "key": "A01", + "label": null, + "declared_in_metadata": true, + "observed_in_filenames": true + } + ], + "truncated_value_count": 0 + } + ], + "source_diagnostics": [], + "format_specific_handler_candidates": [], + "workspace_preparation": { + "read_only_inspection": true, + "required_before_execution": false, + "operation": "none", + "reason": "OpenHCS metadata is already present; read-only inspection did not need workspace preparation." + }, + "workflow_advice": { + "workflow_scope": "diagnostic", + "ingestion_route": "detected_handler", + "ingestion_owner": "openhcsdata", + "source_binding_role": "not_projected_by_handler", + "ui_code_document_id": "plate_manager.orchestrator_config", + "ui_operation": "init", + "knowledge_query": "source model CZI Bio-Formats source bindings", + "probable_native_ingestion_owners": [], + "message": "Keep the detected openhcsdata handler as the ingestion owner. For a visible workflow, add the plate directory through the PlateManager code document and initialize with auto-detection. Use for a workspace already prepared by OpenHCS and carrying its metadata document. The recorded workspace metadata, not raw vendor filename resemblance, owns parser and backend selection. This handler does not project declared source bindings." + } + }, + "inventory": { + "schema_version": "openhcs.agent.v1", + "errors": [], + "warnings": [], + "plate_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs/input_openhcs", + "result_directory": null, + "requested_microscope_type": "auto", + "detected_microscope_type": "openhcsdata", + "handler_class": "OpenHCSMicroscopeHandler", + "parser_class": "SourceSchemaFilenameParser", + "total_count": 2, + "returned_count": 2, + "offset": 0, + "limit": 100, + "truncated_count": 0, + "records": [ + { + "kind": "image", + "key": "images/A01_s001_w2_z001_t001_capped_outgrowth_processing_role.tif", + "metadata": { + "filename": "images/A01_s001_w2_z001_t001_capped_outgrowth_processing_role.tif", + "virtual_path": "images/A01_s001_w2_z001_t001_capped_outgrowth_processing_role.tif", + "full_virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs/input_openhcs/images/A01_s001_w2_z001_t001_capped_outgrowth_processing_role.tif", + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs/input_openhcs/images/A01_s001_w2_z001_t001_capped_outgrowth_processing_role.tif", + "type": "Image", + "OpenHCSSourceVoxelSpacingZYX": "1.3555999999999999,1.3555999999999999", + "OpenHCSSourceVoxelSpacingUnit": "micrometers", + "OpenHCSSourceFilterPaths": { + "0": "A01_s001_w2_z001_t001.tif", + "1": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/input/A01_s001_w2_z001_t001.tif" + }, + "source_alias": "FITC", + "extension": ".tif", + "site": 1, + "channel": 2, + "z_index": 1, + "timepoint": 1, + "well": "A01", + "source_artifact_type": "image", + "size": "351.2 KB", + "modified": "2026-10-03T23:00:27" + }, + "virtual_path": "images/A01_s001_w2_z001_t001_capped_outgrowth_processing_role.tif", + "full_virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs/input_openhcs/images/A01_s001_w2_z001_t001_capped_outgrowth_processing_role.tif", + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs/input_openhcs/images/A01_s001_w2_z001_t001_capped_outgrowth_processing_role.tif", + "relative_path": null, + "full_path": null, + "file_format": null, + "preview": null + }, + { + "kind": "image", + "key": "images/A01_s001_w2_z001_t001_raw_body_processing_role.tif", + "metadata": { + "filename": "images/A01_s001_w2_z001_t001_raw_body_processing_role.tif", + "virtual_path": "images/A01_s001_w2_z001_t001_raw_body_processing_role.tif", + "full_virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs/input_openhcs/images/A01_s001_w2_z001_t001_raw_body_processing_role.tif", + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs/input_openhcs/images/A01_s001_w2_z001_t001_raw_body_processing_role.tif", + "type": "Image", + "OpenHCSSourceVoxelSpacingZYX": "1.3555999999999999,1.3555999999999999", + "OpenHCSSourceVoxelSpacingUnit": "micrometers", + "OpenHCSSourceFilterPaths": { + "0": "A01_s001_w2_z001_t001.tif", + "1": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/input/A01_s001_w2_z001_t001.tif" + }, + "source_alias": "FITC", + "extension": ".tif", + "site": 1, + "channel": 2, + "z_index": 1, + "timepoint": 1, + "well": "A01", + "source_artifact_type": "image", + "size": "2.7 MB", + "modified": "2026-10-03T23:00:27" + }, + "virtual_path": "images/A01_s001_w2_z001_t001_raw_body_processing_role.tif", + "full_virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs/input_openhcs/images/A01_s001_w2_z001_t001_raw_body_processing_role.tif", + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs/input_openhcs/images/A01_s001_w2_z001_t001_raw_body_processing_role.tif", + "relative_path": null, + "full_path": null, + "file_format": null, + "preview": null + } + ] + }, + "samples": { + "raw_body_processing_role": { + "schema_version": "openhcs.agent.v1", + "errors": [], + "warnings": [], + "plate_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs/input_openhcs", + "requested_image_path": "images/A01_s001_w2_z001_t001_raw_body_processing_role.tif", + "virtual_path": "images/A01_s001_w2_z001_t001_raw_body_processing_role.tif", + "full_virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs/input_openhcs/images/A01_s001_w2_z001_t001_raw_body_processing_role.tif", + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs/input_openhcs/images/A01_s001_w2_z001_t001_raw_body_processing_role.tif", + "source_metadata": { + "filename": "images/A01_s001_w2_z001_t001_raw_body_processing_role.tif", + "virtual_path": "images/A01_s001_w2_z001_t001_raw_body_processing_role.tif", + "full_virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs/input_openhcs/images/A01_s001_w2_z001_t001_raw_body_processing_role.tif", + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs/input_openhcs/images/A01_s001_w2_z001_t001_raw_body_processing_role.tif", + "type": "Image", + "OpenHCSSourceVoxelSpacingZYX": "1.3555999999999999,1.3555999999999999", + "OpenHCSSourceVoxelSpacingUnit": "micrometers", + "OpenHCSSourceFilterPaths": { + "0": "A01_s001_w2_z001_t001.tif", + "1": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/input/A01_s001_w2_z001_t001.tif" + }, + "source_alias": "FITC", + "extension": ".tif", + "site": 1, + "channel": 2, + "z_index": 1, + "timepoint": 1, + "well": "A01", + "source_artifact_type": "image", + "size": "2.7 MB", + "modified": "2026-10-03T23:00:27" + }, + "shape": [ + 1024, + 1024 + ], + "resolution_shape": [ + 1024, + 1024 + ], + "dtype": "float32", + "minimum": 0.0, + "maximum": 1.0, + "mean": 0.50044846534729, + "requested_resolution_index": 0, + "selected_resolution_index": 0, + "resolution_count": 1, + "downsample_yx": [ + 1.0, + 1.0 + ], + "statistics_scope": "source_resolution", + "sample_origin_yx": [ + 0, + 0 + ], + "sample_shape": [ + 1, + 9 + ], + "sample_included": true, + "sample_values": [ + [ + 0.0, + 0.0005798428319394588, + 0.0005951018538326025, + 0.0006103608757257462, + 0.00396734569221735, + 0.09153886884450912, + 0.09155413508415222, + 0.09156939387321472, + 1.0 + ] + ], + "sample_omitted_reason": null + }, + "capped_outgrowth_processing_role": { + "schema_version": "openhcs.agent.v1", + "errors": [], + "warnings": [], + "plate_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs/input_openhcs", + "requested_image_path": "images/A01_s001_w2_z001_t001_capped_outgrowth_processing_role.tif", + "virtual_path": "images/A01_s001_w2_z001_t001_capped_outgrowth_processing_role.tif", + "full_virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs/input_openhcs/images/A01_s001_w2_z001_t001_capped_outgrowth_processing_role.tif", + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs/input_openhcs/images/A01_s001_w2_z001_t001_capped_outgrowth_processing_role.tif", + "source_metadata": { + "filename": "images/A01_s001_w2_z001_t001_capped_outgrowth_processing_role.tif", + "virtual_path": "images/A01_s001_w2_z001_t001_capped_outgrowth_processing_role.tif", + "full_virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs/input_openhcs/images/A01_s001_w2_z001_t001_capped_outgrowth_processing_role.tif", + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs/input_openhcs/images/A01_s001_w2_z001_t001_capped_outgrowth_processing_role.tif", + "type": "Image", + "OpenHCSSourceVoxelSpacingZYX": "1.3555999999999999,1.3555999999999999", + "OpenHCSSourceVoxelSpacingUnit": "micrometers", + "OpenHCSSourceFilterPaths": { + "0": "A01_s001_w2_z001_t001.tif", + "1": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/input/A01_s001_w2_z001_t001.tif" + }, + "source_alias": "FITC", + "extension": ".tif", + "site": 1, + "channel": 2, + "z_index": 1, + "timepoint": 1, + "well": "A01", + "source_artifact_type": "image", + "size": "351.2 KB", + "modified": "2026-10-03T23:00:27" + }, + "shape": [ + 1024, + 1024 + ], + "resolution_shape": [ + 1024, + 1024 + ], + "dtype": "float32", + "minimum": 0.0, + "maximum": 1.0000001192092896, + "mean": 0.9539787769317627, + "requested_resolution_index": 0, + "selected_resolution_index": 0, + "resolution_count": 1, + "downsample_yx": [ + 1.0, + 1.0 + ], + "statistics_scope": "source_resolution", + "sample_origin_yx": [ + 0, + 0 + ], + "sample_shape": [ + 1, + 9 + ], + "sample_included": true, + "sample_values": [ + [ + 0.0, + 0.0, + 0.0, + 0.00016775709809735417, + 0.037074316293001175, + 0.999832272529602, + 1.0000001192092896, + 1.0000001192092896, + 1.0000001192092896 + ] + ], + "sample_omitted_reason": null + } + }, + "complete_role_pixels": true, + "metadata_sha256": "b9c6a375aada724c4d4859fad51def6e421cea8e952a482e23659e4cda3d210a", + "role_projection_rows": { + "raw_body_processing_role": [ + { + "virtual_path": "images/A01_s001_w2_z001_t001_raw_body_processing_role.tif", + "address": { + "site": "1", + "channel": "2", + "z_index": "1", + "timepoint": "1", + "well": "A01" + }, + "ref": { + "backend": "disk", + "backend_address": "images/A01_s001_w2_z001_t001_raw_body_processing_role.tif", + "source_axis_indices": [] + }, + "projection_role": "source_artifact", + "source_alias": "raw_body_processing_role", + "source_metadata": { + "OpenHCSSourceVoxelSpacingZYX": "1.3555999999999999,1.3555999999999999", + "OpenHCSSourceVoxelSpacingUnit": "micrometers", + "OpenHCSSourceFilterPaths": { + "0": "A01_s001_w2_z001_t001.tif", + "1": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/input/A01_s001_w2_z001_t001.tif" + }, + "site": "1", + "channel": "2", + "z_index": "1", + "timepoint": "1", + "well": "A01", + "source_alias": "FITC", + "extension": ".tif" + }, + "execution_scope": { + "axis_id": "A01", + "component": null, + "value": null, + "fixed_component_values": [ + [ + "site", + "1" + ], + [ + "z_index", + "1" + ], + [ + "timepoint", + "1" + ] + ] + }, + "artifact_kind": "image", + "image_metadata": { + "source_voxel_spacing": { + "values_zyx": [ + 1.3556, + 1.3556 + ], + "unit": "micrometers" + }, + "source_spatial_domain": { + "origin_yx": [ + 0, + 0 + ], + "source_shape_yx": [ + 1024, + 1024 + ], + "fill_value": 0, + "value_name": "Dense array", + "spatial_dimensions": 2 + }, + "source_provenance": { + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/input/A01_s001_w2_z001_t001.tif", + "source_component_metadata": { + "OpenHCSSourceVoxelSpacingZYX": "1.3555999999999999,1.3555999999999999", + "OpenHCSSourceVoxelSpacingUnit": "micrometers", + "OpenHCSSourceFilterPaths": { + "0": "A01_s001_w2_z001_t001.tif", + "1": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/input/A01_s001_w2_z001_t001.tif" + }, + "site": "1", + "channel": "2", + "z_index": "1", + "timepoint": "1", + "well": "A01", + "source_alias": "FITC", + "extension": ".tif" + }, + "source_image_provenance_planes": [ + { + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/input/A01_s001_w2_z001_t001.tif", + "component_metadata": { + "OpenHCSSourceVoxelSpacingZYX": "1.3555999999999999,1.3555999999999999", + "OpenHCSSourceVoxelSpacingUnit": "micrometers", + "OpenHCSSourceFilterPaths": { + "0": "A01_s001_w2_z001_t001.tif", + "1": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/input/A01_s001_w2_z001_t001.tif" + }, + "site": "1", + "channel": "2", + "z_index": "1", + "timepoint": "1", + "well": "A01", + "source_alias": "FITC" + }, + "identity_kind": "pixel_contributor", + "source_image_name": "FITC", + "contributors": [] + }, + { + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/input/A01_s001_w2_z001_t001.tif", + "component_metadata": { + "OpenHCSSourceVoxelSpacingZYX": "1.3555999999999999,1.3555999999999999", + "OpenHCSSourceVoxelSpacingUnit": "micrometers", + "OpenHCSSourceFilterPaths": { + "0": "A01_s001_w2_z001_t001.tif", + "1": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/input/A01_s001_w2_z001_t001.tif" + }, + "site": "1", + "channel": "2", + "z_index": "1", + "timepoint": "1", + "well": "A01", + "source_alias": "FITC" + }, + "identity_kind": "pixel_contributor", + "source_image_name": "raw_calcein_body_reference", + "contributors": [] + }, + { + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/input/A01_s001_w2_z001_t001.tif", + "component_metadata": { + "OpenHCSSourceVoxelSpacingZYX": "1.3555999999999999,1.3555999999999999", + "OpenHCSSourceVoxelSpacingUnit": "micrometers", + "OpenHCSSourceFilterPaths": { + "0": "A01_s001_w2_z001_t001.tif", + "1": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/input/A01_s001_w2_z001_t001.tif" + }, + "site": "1", + "channel": "2", + "z_index": "1", + "timepoint": "1", + "well": "A01", + "source_alias": "FITC" + }, + "identity_kind": "pixel_contributor", + "source_image_name": "raw_and_cap_channel_last", + "contributors": [] + } + ], + "source_image_names": [ + "raw_body_processing_role" + ] + }, + "intensity_scale": null, + "source_dtype": "float32", + "unit_interval_intensity": { + "scale": null, + "source_plane_scales": [] + }, + "source_plane_intensity_scales": [], + "source_plane_dtypes": [], + "physical_border_edges_yx": null, + "mask_defines_border": null, + "source_channel_axis": null, + "plane_axis": null + } + } + ], + "capped_outgrowth_processing_role": [ + { + "virtual_path": "images/A01_s001_w2_z001_t001_capped_outgrowth_processing_role.tif", + "address": { + "site": "1", + "channel": "2", + "z_index": "1", + "timepoint": "1", + "well": "A01" + }, + "ref": { + "backend": "disk", + "backend_address": "images/A01_s001_w2_z001_t001_capped_outgrowth_processing_role.tif", + "source_axis_indices": [] + }, + "projection_role": "source_artifact", + "source_alias": "capped_outgrowth_processing_role", + "source_metadata": { + "OpenHCSSourceVoxelSpacingZYX": "1.3555999999999999,1.3555999999999999", + "OpenHCSSourceVoxelSpacingUnit": "micrometers", + "OpenHCSSourceFilterPaths": { + "0": "A01_s001_w2_z001_t001.tif", + "1": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/input/A01_s001_w2_z001_t001.tif" + }, + "site": "1", + "channel": "2", + "z_index": "1", + "timepoint": "1", + "well": "A01", + "source_alias": "FITC", + "extension": ".tif" + }, + "execution_scope": { + "axis_id": "A01", + "component": null, + "value": null, + "fixed_component_values": [ + [ + "site", + "1" + ], + [ + "z_index", + "1" + ], + [ + "timepoint", + "1" + ] + ] + }, + "artifact_kind": "image", + "image_metadata": { + "source_voxel_spacing": { + "values_zyx": [ + 1.3556, + 1.3556 + ], + "unit": "micrometers" + }, + "source_spatial_domain": { + "origin_yx": [ + 0, + 0 + ], + "source_shape_yx": [ + 1024, + 1024 + ], + "fill_value": 0, + "value_name": "Dense array", + "spatial_dimensions": 2 + }, + "source_provenance": { + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/input/A01_s001_w2_z001_t001.tif", + "source_component_metadata": { + "OpenHCSSourceVoxelSpacingZYX": "1.3555999999999999,1.3555999999999999", + "OpenHCSSourceVoxelSpacingUnit": "micrometers", + "OpenHCSSourceFilterPaths": { + "0": "A01_s001_w2_z001_t001.tif", + "1": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/input/A01_s001_w2_z001_t001.tif" + }, + "site": "1", + "channel": "2", + "z_index": "1", + "timepoint": "1", + "well": "A01", + "source_alias": "FITC", + "extension": ".tif" + }, + "source_image_provenance_planes": [ + { + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/input/A01_s001_w2_z001_t001.tif", + "component_metadata": { + "OpenHCSSourceVoxelSpacingZYX": "1.3555999999999999,1.3555999999999999", + "OpenHCSSourceVoxelSpacingUnit": "micrometers", + "OpenHCSSourceFilterPaths": { + "0": "A01_s001_w2_z001_t001.tif", + "1": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/input/A01_s001_w2_z001_t001.tif" + }, + "site": "1", + "channel": "2", + "z_index": "1", + "timepoint": "1", + "well": "A01", + "source_alias": "FITC" + }, + "identity_kind": "pixel_contributor", + "source_image_name": "FITC", + "contributors": [] + }, + { + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/input/A01_s001_w2_z001_t001.tif", + "component_metadata": { + "OpenHCSSourceVoxelSpacingZYX": "1.3555999999999999,1.3555999999999999", + "OpenHCSSourceVoxelSpacingUnit": "micrometers", + "OpenHCSSourceFilterPaths": { + "0": "A01_s001_w2_z001_t001.tif", + "1": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/input/A01_s001_w2_z001_t001.tif" + }, + "site": "1", + "channel": "2", + "z_index": "1", + "timepoint": "1", + "well": "A01", + "source_alias": "FITC" + }, + "identity_kind": "pixel_contributor", + "source_image_name": "raw_calcein_body_reference", + "contributors": [] + }, + { + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/input/A01_s001_w2_z001_t001.tif", + "component_metadata": { + "OpenHCSSourceVoxelSpacingZYX": "1.3555999999999999,1.3555999999999999", + "OpenHCSSourceVoxelSpacingUnit": "micrometers", + "OpenHCSSourceFilterPaths": { + "0": "A01_s001_w2_z001_t001.tif", + "1": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/input/A01_s001_w2_z001_t001.tif" + }, + "site": "1", + "channel": "2", + "z_index": "1", + "timepoint": "1", + "well": "A01", + "source_alias": "FITC" + }, + "identity_kind": "pixel_contributor", + "source_image_name": "raw_and_cap_channel_last", + "contributors": [] + } + ], + "source_image_names": [ + "capped_outgrowth_processing_role" + ] + }, + "intensity_scale": null, + "source_dtype": "float32", + "unit_interval_intensity": { + "scale": null, + "source_plane_scales": [] + }, + "source_plane_intensity_scales": [], + "source_plane_dtypes": [], + "physical_border_edges_yx": null, + "mask_defines_border": null, + "source_channel_axis": null, + "plane_axis": null + } + } + ] + } + }, + "installed_cases": { + "produce-saved-ipo": { + "compile": { + "schema_version": "openhcs.agent.v1", + "errors": [], + "warnings": [ + { + "code": "headless_execution_did_not_update_plate_manager", + "message": "This direct execution session completed without adding the output plate to the running UI PlateManager.", + "hint": "For user-visible work in an open UI, load plate_paths and pipeline_data through the plate_manager.orchestrator_config code document, then run init/compile/run with openhcs_ui_selected_plate_workflow." + } + ], + "session_id": "session-1", + "job_id": "job-1", + "kind": "compile", + "uri": "openhcs://execution/jobs/job-1", + "server_execution_id": "72d79f4d-3d87-49de-963a-a48fdc75dddc", + "status": "complete", + "response": { + "status": "ok", + "execution": { + "execution_id": "72d79f4d-3d87-49de-963a-a48fdc75dddc", + "plate_id": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v3/seed", + "client_address": null, + "status": "complete", + "start_time": 1791083078.2859125, + "end_time": 1791083078.651259, + "error": null, + "compile_only": true, + "results_summary": { + "well_count": 1, + "wells": [ + "A01" + ], + "output_plate_root": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v3/outputs/ipo/seed_openhcs", + "auto_add_output_plate_to_plate_manager": false + } + } + }, + "progress": { + "sequence": 6, + "event": { + "execution_id": "72d79f4d-3d87-49de-963a-a48fdc75dddc", + "plate_id": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v3/seed", + "axis_id": "A01", + "step_name": "compilation", + "phase": "compile", + "status": "success", + "percent": 100.0, + "completed": 1, + "total": 1, + "timestamp": 1791083078.651062, + "pid": 3602886 + } + } + }, + "execution": { + "schema_version": "openhcs.agent.v1", + "errors": [], + "warnings": [ + { + "code": "headless_execution_did_not_update_plate_manager", + "message": "This direct execution session completed without adding the output plate to the running UI PlateManager.", + "hint": "For user-visible work in an open UI, load plate_paths and pipeline_data through the plate_manager.orchestrator_config code document, then run init/compile/run with openhcs_ui_selected_plate_workflow." + } + ], + "session_id": "session-1", + "job_id": "job-2", + "kind": "execute", + "uri": "openhcs://execution/jobs/job-2", + "server_execution_id": "47824acc-0e5f-4701-9f7c-857334212798", + "status": "complete", + "response": { + "status": "ok", + "execution": { + "execution_id": "47824acc-0e5f-4701-9f7c-857334212798", + "plate_id": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v3/seed", + "client_address": null, + "status": "complete", + "start_time": 1791083079.0774002, + "end_time": 1791083079.5062525, + "error": null, + "compile_only": false, + "results_summary": { + "well_count": 1, + "wells": [ + "A01" + ], + "output_plate_root": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v3/outputs/ipo/seed_openhcs", + "auto_add_output_plate_to_plate_manager": false, + "runtime_observation_export_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v3/produce-saved-ipo-outcomes.pkl.gz", + "runtime_observation_export_scope": "outcomes" + } + } + }, + "progress": { + "sequence": 12, + "event": { + "execution_id": "47824acc-0e5f-4701-9f7c-857334212798", + "plate_id": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v3/seed", + "axis_id": "", + "step_name": "pipeline", + "phase": "success", + "status": "success", + "percent": 100.0, + "completed": 1, + "total": 1, + "timestamp": 1791083079.5015962, + "pid": 3602886, + "total_wells": [ + "A01" + ], + "worker_assignments": { + "worker_0": [ + "A01" + ] + } + } + } + } + }, + "saved-label-geometry-distance-resize": { + "compile": { + "schema_version": "openhcs.agent.v1", + "errors": [], + "warnings": [ + { + "code": "headless_execution_did_not_update_plate_manager", + "message": "This direct execution session completed without adding the output plate to the running UI PlateManager.", + "hint": "For user-visible work in an open UI, load plate_paths and pipeline_data through the plate_manager.orchestrator_config code document, then run init/compile/run with openhcs_ui_selected_plate_workflow." + } + ], + "session_id": "session-1", + "job_id": "job-1", + "kind": "compile", + "uri": "openhcs://execution/jobs/job-1", + "server_execution_id": "fba99f1f-c007-47a2-80df-5c5c5c18a3b3", + "status": "complete", + "response": { + "status": "ok", + "execution": { + "execution_id": "fba99f1f-c007-47a2-80df-5c5c5c18a3b3", + "plate_id": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v3/outputs/ipo/seed_openhcs/checkpoints_results", + "client_address": null, + "status": "complete", + "start_time": 1791084588.3187003, + "end_time": 1791084588.749012, + "error": null, + "compile_only": true, + "results_summary": { + "well_count": 1, + "wells": [ + "A01" + ], + "output_plate_root": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs", + "auto_add_output_plate_to_plate_manager": false + } + } + }, + "progress": { + "sequence": 6, + "event": { + "execution_id": "fba99f1f-c007-47a2-80df-5c5c5c18a3b3", + "plate_id": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v3/outputs/ipo/seed_openhcs/checkpoints_results", + "axis_id": "A01", + "step_name": "compilation", + "phase": "compile", + "status": "success", + "percent": 100.0, + "completed": 1, + "total": 1, + "timestamp": 1791084588.7483895, + "pid": 3740222 + } + } + }, + "execution": { + "schema_version": "openhcs.agent.v1", + "errors": [], + "warnings": [ + { + "code": "headless_execution_did_not_update_plate_manager", + "message": "This direct execution session completed without adding the output plate to the running UI PlateManager.", + "hint": "For user-visible work in an open UI, load plate_paths and pipeline_data through the plate_manager.orchestrator_config code document, then run init/compile/run with openhcs_ui_selected_plate_workflow." + } + ], + "session_id": "session-1", + "job_id": "job-2", + "kind": "execute", + "uri": "openhcs://execution/jobs/job-2", + "server_execution_id": "8a7ee729-b7f1-409f-b95e-fcac46bac44b", + "status": "complete", + "response": { + "status": "ok", + "execution": { + "execution_id": "8a7ee729-b7f1-409f-b95e-fcac46bac44b", + "plate_id": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v3/outputs/ipo/seed_openhcs/checkpoints_results", + "client_address": null, + "status": "complete", + "start_time": 1791084589.113593, + "end_time": 1791084589.6584854, + "error": null, + "compile_only": false, + "results_summary": { + "well_count": 1, + "wells": [ + "A01" + ], + "output_plate_root": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs", + "auto_add_output_plate_to_plate_manager": false, + "runtime_observation_export_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/saved-label-geometry-distance-resize-outcomes.pkl.gz", + "runtime_observation_export_scope": "outcomes" + } + } + }, + "progress": { + "sequence": 21, + "event": { + "execution_id": "8a7ee729-b7f1-409f-b95e-fcac46bac44b", + "plate_id": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v3/outputs/ipo/seed_openhcs/checkpoints_results", + "axis_id": "", + "step_name": "pipeline", + "phase": "success", + "status": "success", + "percent": 100.0, + "completed": 4, + "total": 4, + "timestamp": 1791084589.653943, + "pid": 3740222, + "total_wells": [ + "A01" + ], + "worker_assignments": { + "worker_0": [ + "A01" + ] + } + } + } + }, + "plate": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs" + } + }, + "prior_ipo_journey": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v3/journey.json", + "ipo_processing_not_replayed": true, + "saved_label_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v3/outputs/ipo/seed_openhcs/checkpoints_results/A01_SavedIPO_step0.labels.tif", + "saved_label_sha256": "6d4aa46dcee3c97b08cbc437a1f18877133e757d7ba908f514e3755368d17974", + "saved_labels_array": [ + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 1, + 1, + 1, + 1, + 1, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 1, + 1, + 1, + 1, + 1, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 1, + 1, + 1, + 1, + 1, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 1, + 1, + 1, + 1, + 1, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 1, + 1, + 1, + 1, + 1, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 2, + 2, + 2, + 2, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 2, + 2, + 2, + 2, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 2, + 2, + 2, + 2, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ] + ], + "saved_documents": { + "saved-label-geometry-distance-resize": { + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/saved-label-geometry-distance-resize-saved-pipeline.py", + "sha256": "a4f864e21a763dcf4701b13c3968d9f5d0304e7396268c01f6013e8a757f1857", + "step_count": 4, + "authority": "PipelineDocumentAuthority.render/from_source" + } + }, + "failure_cleanup": { + "schema_version": "openhcs.agent.v1", + "errors": [], + "warnings": [], + "handle": { + "connection": { + "host": "127.0.0.1", + "port": 6559, + "transport_mode": "tcp", + "persistent": true + }, + "process_identity": { + "pid": 3740222, + "create_time": 1791084576.07 + }, + "launch_plan": { + "runtime_dir": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/owned/data/openhcs", + "log_file": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/owned/data/openhcs/logs/openhcs_zmq_server_port_6559_1791084576159471156.log", + "startup_status_file": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/owned/data/openhcs/logs/openhcs_zmq_server_port_6559_1791084576159471156.startup.jsonl", + "storage_dir": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/owned/data/openhcs/custom_functions", + "registry_cache_dir": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/owned/cache/metaclass-registry", + "transport_write_paths": [ + "/home/ts/.openhcs/tcp/7559.startup.lock", + "/home/ts/.openhcs/tcp/6559.startup.lock" + ] + } + }, + "outcome": { + "succeeded": true, + "endpoint_terminated": true, + "process_identity": { + "pid": 3740222, + "create_time": 1791084576.07 + }, + "process_exited": true, + "request_attempted": true, + "acknowledged": true + } + }, + "cleanup_mcp_returncode": 0, + "all_observed_mcp_children": [ + { + "pid": 3739957, + "returncode": 0 + }, + { + "pid": 3741507, + "returncode": 0 + } + ], + "mcp_children_terminal": true, + "elapsed_seconds": 126.1061459616758, + "readers": [ + { + "pid": 3790248, + "source": "/var/tmp/openhcs-resolved-pipeline-owner-20261004" + } + ], + "original_failure": { + "type": "AssertionError", + "message": "('ResizedDistance', {'filename': 'checkpoints_step2/A01_s001_w2_z001_t001_ResizedDistance.tif', 'virtual_path': 'checkpoints_step2/A01_s001_w2_z001_t001_ResizedDistance.tif', 'full_virtual_path': '/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step2/A01_s001_w2_z001_t001_ResizedDistance.tif', 'source_path': '/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step2/A01_s001_w2_z001_t001_ResizedDistance.tif', 'type': 'Image', 'OpenHCSSourceVoxelSpacingZYX': '1.3555999999999999,1.3555999999999999', 'OpenHCSSourceVoxelSpacingUnit': 'micrometers', 'OpenHCSSourceFilterPaths': {'0': 'A01_SavedIPO_step0.labels.tif', '1': '/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v3/outputs/ipo/seed_openhcs/checkpoints_results/A01_SavedIPO_step0.labels.tif'}, 'source_alias': 'SavedImage', 'extension': '.tif', 'site': 1, 'channel': 2, 'z_index': 1, 'timepoint': 1, 'well': 'A01', 'size': '356 B', 'modified': '2026-10-03T23:29:49'})", + "traceback": "Traceback (most recent call last):\n File \"/var/tmp/run_public_installed_consumers_419_435_450_v7_20261004.py\", line 487, in worker\n first_saved=await inspect_saved_case(session,'first_public_readback')\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/var/tmp/run_public_installed_consumers_419_435_450_v7_20261004.py\", line 418, in inspect_saved_case\n assert len(spacing)==2 and all(abs(v-wanted)<1e-12 for v in spacing),(alias,metadata)\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\nAssertionError: ('ResizedDistance', {'filename': 'checkpoints_step2/A01_s001_w2_z001_t001_ResizedDistance.tif', 'virtual_path': 'checkpoints_step2/A01_s001_w2_z001_t001_ResizedDistance.tif', 'full_virtual_path': '/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step2/A01_s001_w2_z001_t001_ResizedDistance.tif', 'source_path': '/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step2/A01_s001_w2_z001_t001_ResizedDistance.tif', 'type': 'Image', 'OpenHCSSourceVoxelSpacingZYX': '1.3555999999999999,1.3555999999999999', 'OpenHCSSourceVoxelSpacingUnit': 'micrometers', 'OpenHCSSourceFilterPaths': {'0': 'A01_SavedIPO_step0.labels.tif', '1': '/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v3/outputs/ipo/seed_openhcs/checkpoints_results/A01_SavedIPO_step0.labels.tif'}, 'source_alias': 'SavedImage', 'extension': '.tif', 'site': 1, 'channel': 2, 'z_index': 1, 'timepoint': 1, 'well': 'A01', 'size': '356 B', 'modified': '2026-10-03T23:29:49'})\n" + }, + "original_journey": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/journey.json", + "immutable_before": { + "/var/tmp/run_public_installed_consumers_419_435_450_v7_20261004.py": "733ba0c91ad79a01702708fc899ff5c1a3ff24a3bcb2c5a5ab31609010551bbe", + "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/journey.json": "20fdc27cc70d1e9f4439ba9b138c3f7ac5ccc8d0a6b715764fe1d88c9b2690a1", + "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/source-freeze.json": "3441bbca862f3119802e60b106bcdc14d7fee9fd50cafed997c8a19eced46311", + "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/journey.json": "1c6d7d48679e409778aaa6a278245a95e9536e42e098546e65443a4b7ba41d09", + "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v3/journey.json": "6a3b0773ff35e24908fe7bdaf84bd024de6cc3d339c8e0bd8861b869acd6a1c8", + "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7-readback/receipt.json": "eb3c7b11c280ea92168e8960bc3c88dbb7eced93b65b2b6adce9530ba5676aaf" + }, + "output_files_before": { + "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs/input_openhcs/images/A01_s001_w2_z001_t001_capped_outgrowth_processing_role.tif": "c849c419fb6963fd458874a387d3f917c06c15de5e1532e60c6ec8e84ffff68c", + "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs/input_openhcs/images/A01_s001_w2_z001_t001_raw_body_processing_role.tif": "2c6af3065b97c59d36a34b1f6ee4f7eaabf6d2ca44ccb07827b5e59335d5dc7f", + "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs/input_openhcs/openhcs_metadata.json": "b9c6a375aada724c4d4859fad51def6e421cea8e952a482e23659e4cda3d210a", + "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs/input_openhcs/openhcs_metadata.json.lock": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v3/outputs/ipo/seed_openhcs/checkpoints/A01_s001_w2_z001_t001.tif": "3c4e6fe6cf04439c73cfec7adf6fb87d5cd709886a51a47abd9b02f68f7eb15c", + "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v3/outputs/ipo/seed_openhcs/checkpoints_results/A01_ProduceSavedIPO_1_measurements_step0_details.csv": "c5f87bc8a56ba31b8416bddb5690a7b89c0e719dfda2720194bebb39e1b56293", + "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v3/outputs/ipo/seed_openhcs/checkpoints_results/A01_SavedIPO__qa_checkpoint__declump_response_step0.tif": "9b5c5e34a7478e204832f194487a38d213d408d4cde8e75192a37d482489433c", + "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v3/outputs/ipo/seed_openhcs/checkpoints_results/A01_SavedIPO__qa_checkpoint__initial_components_step0.tif": "6d4aa46dcee3c97b08cbc437a1f18877133e757d7ba908f514e3755368d17974", + "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v3/outputs/ipo/seed_openhcs/checkpoints_results/A01_SavedIPO__qa_checkpoint__seed_markers_step0.tif": "4f9b6b07a6bac02ea7c547a45a5889c289f4012a6129aff2d9143faa5353bd6e", + "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v3/outputs/ipo/seed_openhcs/checkpoints_results/A01_SavedIPO__qa_checkpoint__seed_maxima_step0.tif": "a58c2391271947b06775d3fcb2b943b25703fdb2f6bc254e47285b93b00898b0", + "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v3/outputs/ipo/seed_openhcs/checkpoints_results/A01_SavedIPO__qa_checkpoint__small_removed_objects_step0.tif": "6d4aa46dcee3c97b08cbc437a1f18877133e757d7ba908f514e3755368d17974", + "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v3/outputs/ipo/seed_openhcs/checkpoints_results/A01_SavedIPO__qa_checkpoint__threshold_support_step0.tif": "60a7157936cf6019a6177584a107d0382c180b55d85519501b02d6c68c0e6cc3", + "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v3/outputs/ipo/seed_openhcs/checkpoints_results/A01_SavedIPO__qa_checkpoint__unedited_objects_step0.tif": "6d4aa46dcee3c97b08cbc437a1f18877133e757d7ba908f514e3755368d17974", + "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v3/outputs/ipo/seed_openhcs/checkpoints_results/A01_SavedIPO_step0.labels.tif": "6d4aa46dcee3c97b08cbc437a1f18877133e757d7ba908f514e3755368d17974", + "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v3/outputs/ipo/seed_openhcs/checkpoints_results/A01_SavedIPO_step0_rois.roi.zip": "9282dbf2a2d18552b7874ec1aa1b84a8b0072df87aedbdc3f919826c4ce4fe85", + "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v3/outputs/ipo/seed_openhcs/checkpoints_results/A01_SavedIPO_step0_segmentation_summary.txt": "04ce2d48d8621343b5ef319fe53b2a66faea9084069a2911c965feef82253b5d", + "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v3/outputs/ipo/seed_openhcs/checkpoints_results/openhcs_metadata.json": "c5077cd1669ec5b0d6ad86afa33f46c8de08e7b9773ad0156b94bd8a9004256d", + "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v3/outputs/ipo/seed_openhcs/checkpoints_results/openhcs_metadata.json.lock": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v3/outputs/ipo/seed_openhcs/images/A01_s001_w2_z001_t001.tif": "3c4e6fe6cf04439c73cfec7adf6fb87d5cd709886a51a47abd9b02f68f7eb15c", + "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v3/outputs/ipo/seed_openhcs/openhcs_metadata.json": "ba74ca1a758c7a89441a1f6058ef604e84b603ad798b246abf4eb89fd78d7865", + "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v3/outputs/ipo/seed_openhcs/openhcs_metadata.json.lock": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step0/A01_s001_w2_z001_t001.tif": "6d4aa46dcee3c97b08cbc437a1f18877133e757d7ba908f514e3755368d17974", + "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step0_results/A01_SavedIPOShape_1_measurements_step0_details.csv": "990b9c33e8bcebce675b7ba93baa54a759297a70f834e149af6dae5407070eea", + "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step1/A01_s001_w2_z001_t001_SavedDistance.tif": "001aa97060b3bafeb87d08287ea226c6aeed8e18e60dc647e935f61e16123f69", + "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step2/A01_s001_w2_z001_t001_ResizedDistance.tif": "9f8795cfe6a54e1d260e32db3f54de70b5966fbb628181c882b016b97c22e29a", + "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step3/A01_s001_w2_z001_t001_ResizedConsumer.tif": "9f8795cfe6a54e1d260e32db3f54de70b5966fbb628181c882b016b97c22e29a", + "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/images/A01_s001_w2_z001_t001_ResizedConsumer.tif": "9f8795cfe6a54e1d260e32db3f54de70b5966fbb628181c882b016b97c22e29a", + "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/openhcs_metadata.json": "7c321a6c343856f313f821bec819165dbb4dc1ac4d2901c05c68b1d606904866", + "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/openhcs_metadata.json.lock": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + }, + "helper_sha256": "a7e567c782432ea67b0cb1b50493539173af8f61e0bc62f950dbd88bd0cb6539", + "calibration_correction": { + "reason": "ResizeGeometry.resize_payload uses ImagePayloadMetadata.with_spatial_resize, which changes only local SourceSpatialDomain and border/mask facts. Original source calibration remains unchanged; no calibration rescale is part of the existing contract.", + "source_files": { + "openhcs/core/runtime_image_values.py": "9a4b566edb1a0199d58d033f156f079f6dc7d4fe832f09a120dc694d2fbe680e", + "openhcs/core/source_spatial_domain.py": "b3a803dff3213db3d54a2b74d6d0624658cc19df84e30d96d82e23806e9cf7f2", + "openhcs/processing/backends/cellprofiler/image_geometry.py": "be8b4aa4700b17f3c987b2c88501589048cde0a62278a69e4b11d9111d736c77", + "tests/unit/test_cellprofiler_resize_hotpath.py": "680502c768c3628e14b4ca43909b4d5005c578079705e9aded393c389dd3fa18" + } + }, + "fresh_process_reopen": { + "plate": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs/input_openhcs", + "inspection": { + "schema_version": "openhcs.agent.v1", + "errors": [], + "warnings": [ + { + "code": "plate_grid_dimensions_unavailable", + "message": "'grid_dimensions' must be a list of two integers in openhcs_metadata.json", + "hint": null + } + ], + "plate_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs/input_openhcs", + "requested_microscope_type": "auto", + "status": "partial", + "confidence": "high", + "available_microscope_types": [ + "bioformats", + "imagexpress", + "omero", + "openhcsdata", + "opera_phenix", + "source_bindings" + ], + "detected_microscope_type": "openhcsdata", + "handler_class": "OpenHCSMicroscopeHandler", + "parser_class": "SourceSchemaFilenameParser", + "metadata_handler_class": "OpenHCSMetadataHandler", + "root_dir": "", + "compatible_backends": [ + "zarr", + "disk" + ], + "available_backends": [ + "disk" + ], + "metadata_file_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs/input_openhcs/openhcs_metadata.json", + "grid_dimensions": null, + "pixel_size": 1.3556, + "image_files": { + "count": 2, + "sampled_files": [ + "images/A01_s001_w2_z001_t001_capped_outgrowth_processing_role.tif", + "images/A01_s001_w2_z001_t001_raw_body_processing_role.tif" + ], + "sampled_records": [ + { + "virtual_path": "images/A01_s001_w2_z001_t001_capped_outgrowth_processing_role.tif", + "full_virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs/input_openhcs/images/A01_s001_w2_z001_t001_capped_outgrowth_processing_role.tif", + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs/input_openhcs/images/A01_s001_w2_z001_t001_capped_outgrowth_processing_role.tif", + "metadata": { + "filename": "images/A01_s001_w2_z001_t001_capped_outgrowth_processing_role.tif", + "virtual_path": "images/A01_s001_w2_z001_t001_capped_outgrowth_processing_role.tif", + "full_virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs/input_openhcs/images/A01_s001_w2_z001_t001_capped_outgrowth_processing_role.tif", + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs/input_openhcs/images/A01_s001_w2_z001_t001_capped_outgrowth_processing_role.tif", + "type": "Image", + "OpenHCSSourceVoxelSpacingZYX": "1.3555999999999999,1.3555999999999999", + "OpenHCSSourceVoxelSpacingUnit": "micrometers", + "OpenHCSSourceFilterPaths": { + "0": "A01_s001_w2_z001_t001.tif", + "1": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/input/A01_s001_w2_z001_t001.tif" + }, + "source_alias": "FITC", + "extension": ".tif", + "site": 1, + "channel": 2, + "z_index": 1, + "timepoint": 1, + "well": "A01", + "source_artifact_type": "image", + "size": "351.2 KB", + "modified": "2026-10-03T23:00:27" + } + }, + { + "virtual_path": "images/A01_s001_w2_z001_t001_raw_body_processing_role.tif", + "full_virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs/input_openhcs/images/A01_s001_w2_z001_t001_raw_body_processing_role.tif", + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs/input_openhcs/images/A01_s001_w2_z001_t001_raw_body_processing_role.tif", + "metadata": { + "filename": "images/A01_s001_w2_z001_t001_raw_body_processing_role.tif", + "virtual_path": "images/A01_s001_w2_z001_t001_raw_body_processing_role.tif", + "full_virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs/input_openhcs/images/A01_s001_w2_z001_t001_raw_body_processing_role.tif", + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs/input_openhcs/images/A01_s001_w2_z001_t001_raw_body_processing_role.tif", + "type": "Image", + "OpenHCSSourceVoxelSpacingZYX": "1.3555999999999999,1.3555999999999999", + "OpenHCSSourceVoxelSpacingUnit": "micrometers", + "OpenHCSSourceFilterPaths": { + "0": "A01_s001_w2_z001_t001.tif", + "1": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/input/A01_s001_w2_z001_t001.tif" + }, + "source_alias": "FITC", + "extension": ".tif", + "site": 1, + "channel": 2, + "z_index": 1, + "timepoint": 1, + "well": "A01", + "source_artifact_type": "image", + "size": "2.7 MB", + "modified": "2026-10-03T23:00:27" + } + } + ], + "truncated_file_count": 0 + }, + "result_files": { + "count": 0, + "scanned_file_count": 0, + "sampled_files": [], + "sampled_records": [], + "truncated_file_count": 0 + }, + "parse_summary": { + "attempted_file_count": 2, + "skipped_file_count": 0, + "parsed_file_count": 2, + "failed_file_count": 0, + "failure_samples": [], + "truncated_failure_count": 0 + }, + "components": [ + { + "component": "site", + "source": "metadata_and_parsed_filenames", + "count": 1, + "values": [ + { + "key": "1", + "label": null, + "declared_in_metadata": true, + "observed_in_filenames": true + } + ], + "truncated_value_count": 0 + }, + { + "component": "channel", + "source": "metadata_and_parsed_filenames", + "count": 1, + "values": [ + { + "key": "2", + "label": "FITC", + "declared_in_metadata": true, + "observed_in_filenames": true + } + ], + "truncated_value_count": 0 + }, + { + "component": "z_index", + "source": "metadata_and_parsed_filenames", + "count": 1, + "values": [ + { + "key": "1", + "label": null, + "declared_in_metadata": true, + "observed_in_filenames": true + } + ], + "truncated_value_count": 0 + }, + { + "component": "timepoint", + "source": "metadata_and_parsed_filenames", + "count": 1, + "values": [ + { + "key": "1", + "label": null, + "declared_in_metadata": true, + "observed_in_filenames": true + } + ], + "truncated_value_count": 0 + }, + { + "component": "well", + "source": "metadata_and_parsed_filenames", + "count": 1, + "values": [ + { + "key": "A01", + "label": null, + "declared_in_metadata": true, + "observed_in_filenames": true + } + ], + "truncated_value_count": 0 + } + ], + "source_diagnostics": [], + "format_specific_handler_candidates": [], + "workspace_preparation": { + "read_only_inspection": true, + "required_before_execution": false, + "operation": "none", + "reason": "OpenHCS metadata is already present; read-only inspection did not need workspace preparation." + }, + "workflow_advice": { + "workflow_scope": "diagnostic", + "ingestion_route": "detected_handler", + "ingestion_owner": "openhcsdata", + "source_binding_role": "not_projected_by_handler", + "ui_code_document_id": "plate_manager.orchestrator_config", + "ui_operation": "init", + "knowledge_query": "source model CZI Bio-Formats source bindings", + "probable_native_ingestion_owners": [], + "message": "Keep the detected openhcsdata handler as the ingestion owner. For a visible workflow, add the plate directory through the PlateManager code document and initialize with auto-detection. Use for a workspace already prepared by OpenHCS and carrying its metadata document. The recorded workspace metadata, not raw vendor filename resemblance, owns parser and backend selection. This handler does not project declared source bindings." + } + }, + "inventory": { + "schema_version": "openhcs.agent.v1", + "errors": [], + "warnings": [], + "plate_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs/input_openhcs", + "result_directory": null, + "requested_microscope_type": "auto", + "detected_microscope_type": "openhcsdata", + "handler_class": "OpenHCSMicroscopeHandler", + "parser_class": "SourceSchemaFilenameParser", + "total_count": 2, + "returned_count": 2, + "offset": 0, + "limit": 100, + "truncated_count": 0, + "records": [ + { + "kind": "image", + "key": "images/A01_s001_w2_z001_t001_capped_outgrowth_processing_role.tif", + "metadata": { + "filename": "images/A01_s001_w2_z001_t001_capped_outgrowth_processing_role.tif", + "virtual_path": "images/A01_s001_w2_z001_t001_capped_outgrowth_processing_role.tif", + "full_virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs/input_openhcs/images/A01_s001_w2_z001_t001_capped_outgrowth_processing_role.tif", + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs/input_openhcs/images/A01_s001_w2_z001_t001_capped_outgrowth_processing_role.tif", + "type": "Image", + "OpenHCSSourceVoxelSpacingZYX": "1.3555999999999999,1.3555999999999999", + "OpenHCSSourceVoxelSpacingUnit": "micrometers", + "OpenHCSSourceFilterPaths": { + "0": "A01_s001_w2_z001_t001.tif", + "1": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/input/A01_s001_w2_z001_t001.tif" + }, + "source_alias": "FITC", + "extension": ".tif", + "site": 1, + "channel": 2, + "z_index": 1, + "timepoint": 1, + "well": "A01", + "source_artifact_type": "image", + "size": "351.2 KB", + "modified": "2026-10-03T23:00:27" + }, + "virtual_path": "images/A01_s001_w2_z001_t001_capped_outgrowth_processing_role.tif", + "full_virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs/input_openhcs/images/A01_s001_w2_z001_t001_capped_outgrowth_processing_role.tif", + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs/input_openhcs/images/A01_s001_w2_z001_t001_capped_outgrowth_processing_role.tif", + "relative_path": null, + "full_path": null, + "file_format": null, + "preview": null + }, + { + "kind": "image", + "key": "images/A01_s001_w2_z001_t001_raw_body_processing_role.tif", + "metadata": { + "filename": "images/A01_s001_w2_z001_t001_raw_body_processing_role.tif", + "virtual_path": "images/A01_s001_w2_z001_t001_raw_body_processing_role.tif", + "full_virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs/input_openhcs/images/A01_s001_w2_z001_t001_raw_body_processing_role.tif", + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs/input_openhcs/images/A01_s001_w2_z001_t001_raw_body_processing_role.tif", + "type": "Image", + "OpenHCSSourceVoxelSpacingZYX": "1.3555999999999999,1.3555999999999999", + "OpenHCSSourceVoxelSpacingUnit": "micrometers", + "OpenHCSSourceFilterPaths": { + "0": "A01_s001_w2_z001_t001.tif", + "1": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/input/A01_s001_w2_z001_t001.tif" + }, + "source_alias": "FITC", + "extension": ".tif", + "site": 1, + "channel": 2, + "z_index": 1, + "timepoint": 1, + "well": "A01", + "source_artifact_type": "image", + "size": "2.7 MB", + "modified": "2026-10-03T23:00:27" + }, + "virtual_path": "images/A01_s001_w2_z001_t001_raw_body_processing_role.tif", + "full_virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs/input_openhcs/images/A01_s001_w2_z001_t001_raw_body_processing_role.tif", + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs/input_openhcs/images/A01_s001_w2_z001_t001_raw_body_processing_role.tif", + "relative_path": null, + "full_path": null, + "file_format": null, + "preview": null + } + ] + }, + "samples": { + "raw_body_processing_role": { + "schema_version": "openhcs.agent.v1", + "errors": [], + "warnings": [], + "plate_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs/input_openhcs", + "requested_image_path": "images/A01_s001_w2_z001_t001_raw_body_processing_role.tif", + "virtual_path": "images/A01_s001_w2_z001_t001_raw_body_processing_role.tif", + "full_virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs/input_openhcs/images/A01_s001_w2_z001_t001_raw_body_processing_role.tif", + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs/input_openhcs/images/A01_s001_w2_z001_t001_raw_body_processing_role.tif", + "source_metadata": { + "filename": "images/A01_s001_w2_z001_t001_raw_body_processing_role.tif", + "virtual_path": "images/A01_s001_w2_z001_t001_raw_body_processing_role.tif", + "full_virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs/input_openhcs/images/A01_s001_w2_z001_t001_raw_body_processing_role.tif", + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs/input_openhcs/images/A01_s001_w2_z001_t001_raw_body_processing_role.tif", + "type": "Image", + "OpenHCSSourceVoxelSpacingZYX": "1.3555999999999999,1.3555999999999999", + "OpenHCSSourceVoxelSpacingUnit": "micrometers", + "OpenHCSSourceFilterPaths": { + "0": "A01_s001_w2_z001_t001.tif", + "1": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/input/A01_s001_w2_z001_t001.tif" + }, + "source_alias": "FITC", + "extension": ".tif", + "site": 1, + "channel": 2, + "z_index": 1, + "timepoint": 1, + "well": "A01", + "source_artifact_type": "image", + "size": "2.7 MB", + "modified": "2026-10-03T23:00:27" + }, + "shape": [ + 1024, + 1024 + ], + "resolution_shape": [ + 1024, + 1024 + ], + "dtype": "float32", + "minimum": 0.0, + "maximum": 1.0, + "mean": 0.50044846534729, + "requested_resolution_index": 0, + "selected_resolution_index": 0, + "resolution_count": 1, + "downsample_yx": [ + 1.0, + 1.0 + ], + "statistics_scope": "source_resolution", + "sample_origin_yx": [ + 0, + 0 + ], + "sample_shape": [ + 1, + 9 + ], + "sample_included": true, + "sample_values": [ + [ + 0.0, + 0.0005798428319394588, + 0.0005951018538326025, + 0.0006103608757257462, + 0.00396734569221735, + 0.09153886884450912, + 0.09155413508415222, + 0.09156939387321472, + 1.0 + ] + ], + "sample_omitted_reason": null + }, + "capped_outgrowth_processing_role": { + "schema_version": "openhcs.agent.v1", + "errors": [], + "warnings": [], + "plate_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs/input_openhcs", + "requested_image_path": "images/A01_s001_w2_z001_t001_capped_outgrowth_processing_role.tif", + "virtual_path": "images/A01_s001_w2_z001_t001_capped_outgrowth_processing_role.tif", + "full_virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs/input_openhcs/images/A01_s001_w2_z001_t001_capped_outgrowth_processing_role.tif", + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs/input_openhcs/images/A01_s001_w2_z001_t001_capped_outgrowth_processing_role.tif", + "source_metadata": { + "filename": "images/A01_s001_w2_z001_t001_capped_outgrowth_processing_role.tif", + "virtual_path": "images/A01_s001_w2_z001_t001_capped_outgrowth_processing_role.tif", + "full_virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs/input_openhcs/images/A01_s001_w2_z001_t001_capped_outgrowth_processing_role.tif", + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs/input_openhcs/images/A01_s001_w2_z001_t001_capped_outgrowth_processing_role.tif", + "type": "Image", + "OpenHCSSourceVoxelSpacingZYX": "1.3555999999999999,1.3555999999999999", + "OpenHCSSourceVoxelSpacingUnit": "micrometers", + "OpenHCSSourceFilterPaths": { + "0": "A01_s001_w2_z001_t001.tif", + "1": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/input/A01_s001_w2_z001_t001.tif" + }, + "source_alias": "FITC", + "extension": ".tif", + "site": 1, + "channel": 2, + "z_index": 1, + "timepoint": 1, + "well": "A01", + "source_artifact_type": "image", + "size": "351.2 KB", + "modified": "2026-10-03T23:00:27" + }, + "shape": [ + 1024, + 1024 + ], + "resolution_shape": [ + 1024, + 1024 + ], + "dtype": "float32", + "minimum": 0.0, + "maximum": 1.0000001192092896, + "mean": 0.9539787769317627, + "requested_resolution_index": 0, + "selected_resolution_index": 0, + "resolution_count": 1, + "downsample_yx": [ + 1.0, + 1.0 + ], + "statistics_scope": "source_resolution", + "sample_origin_yx": [ + 0, + 0 + ], + "sample_shape": [ + 1, + 9 + ], + "sample_included": true, + "sample_values": [ + [ + 0.0, + 0.0, + 0.0, + 0.00016775709809735417, + 0.037074316293001175, + 0.999832272529602, + 1.0000001192092896, + 1.0000001192092896, + 1.0000001192092896 + ] + ], + "sample_omitted_reason": null + } + }, + "complete_role_pixels": true, + "metadata_sha256": "b9c6a375aada724c4d4859fad51def6e421cea8e952a482e23659e4cda3d210a", + "role_projection_rows": { + "raw_body_processing_role": [ + { + "virtual_path": "images/A01_s001_w2_z001_t001_raw_body_processing_role.tif", + "address": { + "site": "1", + "channel": "2", + "z_index": "1", + "timepoint": "1", + "well": "A01" + }, + "ref": { + "backend": "disk", + "backend_address": "images/A01_s001_w2_z001_t001_raw_body_processing_role.tif", + "source_axis_indices": [] + }, + "projection_role": "source_artifact", + "source_alias": "raw_body_processing_role", + "source_metadata": { + "OpenHCSSourceVoxelSpacingZYX": "1.3555999999999999,1.3555999999999999", + "OpenHCSSourceVoxelSpacingUnit": "micrometers", + "OpenHCSSourceFilterPaths": { + "0": "A01_s001_w2_z001_t001.tif", + "1": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/input/A01_s001_w2_z001_t001.tif" + }, + "site": "1", + "channel": "2", + "z_index": "1", + "timepoint": "1", + "well": "A01", + "source_alias": "FITC", + "extension": ".tif" + }, + "execution_scope": { + "axis_id": "A01", + "component": null, + "value": null, + "fixed_component_values": [ + [ + "site", + "1" + ], + [ + "z_index", + "1" + ], + [ + "timepoint", + "1" + ] + ] + }, + "artifact_kind": "image", + "image_metadata": { + "source_voxel_spacing": { + "values_zyx": [ + 1.3556, + 1.3556 + ], + "unit": "micrometers" + }, + "source_spatial_domain": { + "origin_yx": [ + 0, + 0 + ], + "source_shape_yx": [ + 1024, + 1024 + ], + "fill_value": 0, + "value_name": "Dense array", + "spatial_dimensions": 2 + }, + "source_provenance": { + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/input/A01_s001_w2_z001_t001.tif", + "source_component_metadata": { + "OpenHCSSourceVoxelSpacingZYX": "1.3555999999999999,1.3555999999999999", + "OpenHCSSourceVoxelSpacingUnit": "micrometers", + "OpenHCSSourceFilterPaths": { + "0": "A01_s001_w2_z001_t001.tif", + "1": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/input/A01_s001_w2_z001_t001.tif" + }, + "site": "1", + "channel": "2", + "z_index": "1", + "timepoint": "1", + "well": "A01", + "source_alias": "FITC", + "extension": ".tif" + }, + "source_image_provenance_planes": [ + { + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/input/A01_s001_w2_z001_t001.tif", + "component_metadata": { + "OpenHCSSourceVoxelSpacingZYX": "1.3555999999999999,1.3555999999999999", + "OpenHCSSourceVoxelSpacingUnit": "micrometers", + "OpenHCSSourceFilterPaths": { + "0": "A01_s001_w2_z001_t001.tif", + "1": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/input/A01_s001_w2_z001_t001.tif" + }, + "site": "1", + "channel": "2", + "z_index": "1", + "timepoint": "1", + "well": "A01", + "source_alias": "FITC" + }, + "identity_kind": "pixel_contributor", + "source_image_name": "FITC", + "contributors": [] + }, + { + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/input/A01_s001_w2_z001_t001.tif", + "component_metadata": { + "OpenHCSSourceVoxelSpacingZYX": "1.3555999999999999,1.3555999999999999", + "OpenHCSSourceVoxelSpacingUnit": "micrometers", + "OpenHCSSourceFilterPaths": { + "0": "A01_s001_w2_z001_t001.tif", + "1": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/input/A01_s001_w2_z001_t001.tif" + }, + "site": "1", + "channel": "2", + "z_index": "1", + "timepoint": "1", + "well": "A01", + "source_alias": "FITC" + }, + "identity_kind": "pixel_contributor", + "source_image_name": "raw_calcein_body_reference", + "contributors": [] + }, + { + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/input/A01_s001_w2_z001_t001.tif", + "component_metadata": { + "OpenHCSSourceVoxelSpacingZYX": "1.3555999999999999,1.3555999999999999", + "OpenHCSSourceVoxelSpacingUnit": "micrometers", + "OpenHCSSourceFilterPaths": { + "0": "A01_s001_w2_z001_t001.tif", + "1": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/input/A01_s001_w2_z001_t001.tif" + }, + "site": "1", + "channel": "2", + "z_index": "1", + "timepoint": "1", + "well": "A01", + "source_alias": "FITC" + }, + "identity_kind": "pixel_contributor", + "source_image_name": "raw_and_cap_channel_last", + "contributors": [] + } + ], + "source_image_names": [ + "raw_body_processing_role" + ] + }, + "intensity_scale": null, + "source_dtype": "float32", + "unit_interval_intensity": { + "scale": null, + "source_plane_scales": [] + }, + "source_plane_intensity_scales": [], + "source_plane_dtypes": [], + "physical_border_edges_yx": null, + "mask_defines_border": null, + "source_channel_axis": null, + "plane_axis": null + } + } + ], + "capped_outgrowth_processing_role": [ + { + "virtual_path": "images/A01_s001_w2_z001_t001_capped_outgrowth_processing_role.tif", + "address": { + "site": "1", + "channel": "2", + "z_index": "1", + "timepoint": "1", + "well": "A01" + }, + "ref": { + "backend": "disk", + "backend_address": "images/A01_s001_w2_z001_t001_capped_outgrowth_processing_role.tif", + "source_axis_indices": [] + }, + "projection_role": "source_artifact", + "source_alias": "capped_outgrowth_processing_role", + "source_metadata": { + "OpenHCSSourceVoxelSpacingZYX": "1.3555999999999999,1.3555999999999999", + "OpenHCSSourceVoxelSpacingUnit": "micrometers", + "OpenHCSSourceFilterPaths": { + "0": "A01_s001_w2_z001_t001.tif", + "1": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/input/A01_s001_w2_z001_t001.tif" + }, + "site": "1", + "channel": "2", + "z_index": "1", + "timepoint": "1", + "well": "A01", + "source_alias": "FITC", + "extension": ".tif" + }, + "execution_scope": { + "axis_id": "A01", + "component": null, + "value": null, + "fixed_component_values": [ + [ + "site", + "1" + ], + [ + "z_index", + "1" + ], + [ + "timepoint", + "1" + ] + ] + }, + "artifact_kind": "image", + "image_metadata": { + "source_voxel_spacing": { + "values_zyx": [ + 1.3556, + 1.3556 + ], + "unit": "micrometers" + }, + "source_spatial_domain": { + "origin_yx": [ + 0, + 0 + ], + "source_shape_yx": [ + 1024, + 1024 + ], + "fill_value": 0, + "value_name": "Dense array", + "spatial_dimensions": 2 + }, + "source_provenance": { + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/input/A01_s001_w2_z001_t001.tif", + "source_component_metadata": { + "OpenHCSSourceVoxelSpacingZYX": "1.3555999999999999,1.3555999999999999", + "OpenHCSSourceVoxelSpacingUnit": "micrometers", + "OpenHCSSourceFilterPaths": { + "0": "A01_s001_w2_z001_t001.tif", + "1": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/input/A01_s001_w2_z001_t001.tif" + }, + "site": "1", + "channel": "2", + "z_index": "1", + "timepoint": "1", + "well": "A01", + "source_alias": "FITC", + "extension": ".tif" + }, + "source_image_provenance_planes": [ + { + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/input/A01_s001_w2_z001_t001.tif", + "component_metadata": { + "OpenHCSSourceVoxelSpacingZYX": "1.3555999999999999,1.3555999999999999", + "OpenHCSSourceVoxelSpacingUnit": "micrometers", + "OpenHCSSourceFilterPaths": { + "0": "A01_s001_w2_z001_t001.tif", + "1": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/input/A01_s001_w2_z001_t001.tif" + }, + "site": "1", + "channel": "2", + "z_index": "1", + "timepoint": "1", + "well": "A01", + "source_alias": "FITC" + }, + "identity_kind": "pixel_contributor", + "source_image_name": "FITC", + "contributors": [] + }, + { + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/input/A01_s001_w2_z001_t001.tif", + "component_metadata": { + "OpenHCSSourceVoxelSpacingZYX": "1.3555999999999999,1.3555999999999999", + "OpenHCSSourceVoxelSpacingUnit": "micrometers", + "OpenHCSSourceFilterPaths": { + "0": "A01_s001_w2_z001_t001.tif", + "1": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/input/A01_s001_w2_z001_t001.tif" + }, + "site": "1", + "channel": "2", + "z_index": "1", + "timepoint": "1", + "well": "A01", + "source_alias": "FITC" + }, + "identity_kind": "pixel_contributor", + "source_image_name": "raw_calcein_body_reference", + "contributors": [] + }, + { + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/input/A01_s001_w2_z001_t001.tif", + "component_metadata": { + "OpenHCSSourceVoxelSpacingZYX": "1.3555999999999999,1.3555999999999999", + "OpenHCSSourceVoxelSpacingUnit": "micrometers", + "OpenHCSSourceFilterPaths": { + "0": "A01_s001_w2_z001_t001.tif", + "1": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/input/A01_s001_w2_z001_t001.tif" + }, + "site": "1", + "channel": "2", + "z_index": "1", + "timepoint": "1", + "well": "A01", + "source_alias": "FITC" + }, + "identity_kind": "pixel_contributor", + "source_image_name": "raw_and_cap_channel_last", + "contributors": [] + } + ], + "source_image_names": [ + "capped_outgrowth_processing_role" + ] + }, + "intensity_scale": null, + "source_dtype": "float32", + "unit_interval_intensity": { + "scale": null, + "source_plane_scales": [] + }, + "source_plane_intensity_scales": [], + "source_plane_dtypes": [], + "physical_border_edges_yx": null, + "mask_defines_border": null, + "source_channel_axis": null, + "plane_axis": null + } + } + ] + } + }, + "fresh_process_reopen-419-450": { + "inspection": { + "schema_version": "openhcs.agent.v1", + "errors": [], + "warnings": [ + { + "code": "plate_grid_dimensions_unavailable", + "message": "'grid_dimensions' must be a list of two integers in openhcs_metadata.json", + "hint": null + } + ], + "plate_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs", + "requested_microscope_type": "auto", + "status": "partial", + "confidence": "high", + "available_microscope_types": [ + "bioformats", + "imagexpress", + "omero", + "openhcsdata", + "opera_phenix", + "source_bindings" + ], + "detected_microscope_type": "openhcsdata", + "handler_class": "OpenHCSMicroscopeHandler", + "parser_class": "SourceSchemaFilenameParser", + "metadata_handler_class": "OpenHCSMetadataHandler", + "root_dir": "", + "compatible_backends": [ + "zarr", + "disk" + ], + "available_backends": [ + "disk" + ], + "metadata_file_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/openhcs_metadata.json", + "grid_dimensions": null, + "pixel_size": 1.3556, + "image_files": { + "count": 5, + "sampled_files": [ + "checkpoints_step0/A01_s001_w2_z001_t001.tif", + "checkpoints_step1/A01_s001_w2_z001_t001_SavedDistance.tif", + "checkpoints_step2/A01_s001_w2_z001_t001_ResizedDistance.tif", + "checkpoints_step3/A01_s001_w2_z001_t001_ResizedConsumer.tif", + "images/A01_s001_w2_z001_t001_ResizedConsumer.tif" + ], + "sampled_records": [ + { + "virtual_path": "checkpoints_step0/A01_s001_w2_z001_t001.tif", + "full_virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step0/A01_s001_w2_z001_t001.tif", + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step0/A01_s001_w2_z001_t001.tif", + "metadata": { + "filename": "checkpoints_step0/A01_s001_w2_z001_t001.tif", + "virtual_path": "checkpoints_step0/A01_s001_w2_z001_t001.tif", + "full_virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step0/A01_s001_w2_z001_t001.tif", + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step0/A01_s001_w2_z001_t001.tif", + "type": "Image", + "extension": ".tif", + "site": 1, + "channel": 2, + "z_index": 1, + "timepoint": 1, + "well": "A01", + "size": "312 B", + "modified": "2026-10-03T23:29:49" + } + }, + { + "virtual_path": "checkpoints_step1/A01_s001_w2_z001_t001_SavedDistance.tif", + "full_virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step1/A01_s001_w2_z001_t001_SavedDistance.tif", + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step1/A01_s001_w2_z001_t001_SavedDistance.tif", + "metadata": { + "filename": "checkpoints_step1/A01_s001_w2_z001_t001_SavedDistance.tif", + "virtual_path": "checkpoints_step1/A01_s001_w2_z001_t001_SavedDistance.tif", + "full_virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step1/A01_s001_w2_z001_t001_SavedDistance.tif", + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step1/A01_s001_w2_z001_t001_SavedDistance.tif", + "type": "Image", + "OpenHCSSourceVoxelSpacingZYX": "1.3555999999999999,1.3555999999999999", + "OpenHCSSourceVoxelSpacingUnit": "micrometers", + "OpenHCSSourceFilterPaths": { + "0": "A01_SavedIPO_step0.labels.tif", + "1": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v3/outputs/ipo/seed_openhcs/checkpoints_results/A01_SavedIPO_step0.labels.tif" + }, + "source_alias": "SavedImage", + "extension": ".tif", + "site": 1, + "channel": 2, + "z_index": 1, + "timepoint": 1, + "well": "A01", + "size": "335 B", + "modified": "2026-10-03T23:29:49" + } + }, + { + "virtual_path": "checkpoints_step2/A01_s001_w2_z001_t001_ResizedDistance.tif", + "full_virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step2/A01_s001_w2_z001_t001_ResizedDistance.tif", + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step2/A01_s001_w2_z001_t001_ResizedDistance.tif", + "metadata": { + "filename": "checkpoints_step2/A01_s001_w2_z001_t001_ResizedDistance.tif", + "virtual_path": "checkpoints_step2/A01_s001_w2_z001_t001_ResizedDistance.tif", + "full_virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step2/A01_s001_w2_z001_t001_ResizedDistance.tif", + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step2/A01_s001_w2_z001_t001_ResizedDistance.tif", + "type": "Image", + "OpenHCSSourceVoxelSpacingZYX": "1.3555999999999999,1.3555999999999999", + "OpenHCSSourceVoxelSpacingUnit": "micrometers", + "OpenHCSSourceFilterPaths": { + "0": "A01_SavedIPO_step0.labels.tif", + "1": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v3/outputs/ipo/seed_openhcs/checkpoints_results/A01_SavedIPO_step0.labels.tif" + }, + "source_alias": "SavedImage", + "extension": ".tif", + "site": 1, + "channel": 2, + "z_index": 1, + "timepoint": 1, + "well": "A01", + "size": "356 B", + "modified": "2026-10-03T23:29:49" + } + }, + { + "virtual_path": "checkpoints_step3/A01_s001_w2_z001_t001_ResizedConsumer.tif", + "full_virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step3/A01_s001_w2_z001_t001_ResizedConsumer.tif", + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step3/A01_s001_w2_z001_t001_ResizedConsumer.tif", + "metadata": { + "filename": "checkpoints_step3/A01_s001_w2_z001_t001_ResizedConsumer.tif", + "virtual_path": "checkpoints_step3/A01_s001_w2_z001_t001_ResizedConsumer.tif", + "full_virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step3/A01_s001_w2_z001_t001_ResizedConsumer.tif", + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step3/A01_s001_w2_z001_t001_ResizedConsumer.tif", + "type": "Image", + "OpenHCSSourceVoxelSpacingZYX": "1.3555999999999999,1.3555999999999999", + "OpenHCSSourceVoxelSpacingUnit": "micrometers", + "OpenHCSSourceFilterPaths": { + "0": "A01_SavedIPO_step0.labels.tif", + "1": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v3/outputs/ipo/seed_openhcs/checkpoints_results/A01_SavedIPO_step0.labels.tif" + }, + "source_alias": "SavedImage", + "extension": ".tif", + "site": 1, + "channel": 2, + "z_index": 1, + "timepoint": 1, + "well": "A01", + "source_artifact_type": "image", + "size": "356 B", + "modified": "2026-10-03T23:29:49" + } + }, + { + "virtual_path": "images/A01_s001_w2_z001_t001_ResizedConsumer.tif", + "full_virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/images/A01_s001_w2_z001_t001_ResizedConsumer.tif", + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/images/A01_s001_w2_z001_t001_ResizedConsumer.tif", + "metadata": { + "filename": "images/A01_s001_w2_z001_t001_ResizedConsumer.tif", + "virtual_path": "images/A01_s001_w2_z001_t001_ResizedConsumer.tif", + "full_virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/images/A01_s001_w2_z001_t001_ResizedConsumer.tif", + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/images/A01_s001_w2_z001_t001_ResizedConsumer.tif", + "type": "Image", + "OpenHCSSourceVoxelSpacingZYX": "1.3555999999999999,1.3555999999999999", + "OpenHCSSourceVoxelSpacingUnit": "micrometers", + "OpenHCSSourceFilterPaths": { + "0": "A01_SavedIPO_step0.labels.tif", + "1": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v3/outputs/ipo/seed_openhcs/checkpoints_results/A01_SavedIPO_step0.labels.tif" + }, + "source_alias": "SavedImage", + "extension": ".tif", + "site": 1, + "channel": 2, + "z_index": 1, + "timepoint": 1, + "well": "A01", + "size": "356 B", + "modified": "2026-10-03T23:29:49" + } + } + ], + "truncated_file_count": 0 + }, + "result_files": { + "count": 2, + "scanned_file_count": 3, + "sampled_files": [ + "checkpoints_step0_results/A01_SavedIPOShape_1_measurements_step0_details.csv", + "checkpoints_step3/A01_s001_w2_z001_t001_ResizedConsumer.tif" + ], + "sampled_records": [ + { + "relative_path": "checkpoints_step0_results/A01_SavedIPOShape_1_measurements_step0_details.csv", + "full_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step0_results/A01_SavedIPOShape_1_measurements_step0_details.csv", + "file_format": "CSV", + "metadata": { + "filename": "checkpoints_step0_results/A01_SavedIPOShape_1_measurements_step0_details.csv", + "type": "CSV", + "size": "1.0 KB", + "modified": "2026-10-03T23:29:49", + "result_subdirectory": "checkpoints_step0", + "full_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step0_results/A01_SavedIPOShape_1_measurements_step0_details.csv" + }, + "preview": { + "text_lines": [ + "slice_index,object_label,AreaShape_Area,AreaShape_Perimeter,AreaShape_MajorAxisLength,AreaShape_MinorAxisLength,AreaShape_Eccentricity,AreaShape_Orientation,AreaShape_Center_X,AreaShape_Center_Y,AreaShape_BoundingBoxArea,AreaShape_BoundingBoxMinimum_X,AreaShape_BoundingBoxMaximum_X,AreaShape_BoundingBoxMinimum_Y,AreaShape_BoundingBoxMaximum_Y,AreaShape_FormFactor,AreaShape_Extent,AreaShape_Solidity,AreaShape_Compactness,AreaShape_EulerNumber,AreaShape_MaximumRadius,AreaShape_MeanRadius,AreaShape_MedianRadius,AreaShape_ConvexArea,AreaShape_MinFeretDiameter,AreaShape_MaxFeretDiameter,AreaShape_EquivalentDiameter", + "0,1,25.0,16.0,5.656854249492381,5.656854249492381,0.0,45.0,4.0,4.0,25.0,2,7,2,7,1.227184630308513,1.0,1.0,0.8148733086305041,1,3.0,1.4,1.0,25.0,4.0,5.656854249492381,5.641895835477563", + "0,2,12.0,10.0,4.47213595499958,3.2659863237109037,0.6831300510639733,90.0,21.5,13.0,12.0,20,24,12,15,1.5079644737231006,1.0,1.0,0.6631455962162306,1,2.0,1.1666666666666667,1.0,12.0,2.0,3.605551275463989,3.9088200952233594" + ], + "csv_columns": [ + "slice_index", + "object_label", + "AreaShape_Area", + "AreaShape_Perimeter", + "AreaShape_MajorAxisLength", + "AreaShape_MinorAxisLength", + "AreaShape_Eccentricity", + "AreaShape_Orientation", + "AreaShape_Center_X", + "AreaShape_Center_Y", + "AreaShape_BoundingBoxArea", + "AreaShape_BoundingBoxMinimum_X", + "AreaShape_BoundingBoxMaximum_X", + "AreaShape_BoundingBoxMinimum_Y", + "AreaShape_BoundingBoxMaximum_Y", + "AreaShape_FormFactor", + "AreaShape_Extent", + "AreaShape_Solidity", + "AreaShape_Compactness", + "AreaShape_EulerNumber", + "AreaShape_MaximumRadius", + "AreaShape_MeanRadius", + "AreaShape_MedianRadius", + "AreaShape_ConvexArea", + "AreaShape_MinFeretDiameter", + "AreaShape_MaxFeretDiameter", + "AreaShape_EquivalentDiameter" + ], + "csv_rows": [ + { + "slice_index": "0", + "object_label": "1", + "AreaShape_Area": "25.0", + "AreaShape_Perimeter": "16.0", + "AreaShape_MajorAxisLength": "5.656854249492381", + "AreaShape_MinorAxisLength": "5.656854249492381", + "AreaShape_Eccentricity": "0.0", + "AreaShape_Orientation": "45.0", + "AreaShape_Center_X": "4.0", + "AreaShape_Center_Y": "4.0", + "AreaShape_BoundingBoxArea": "25.0", + "AreaShape_BoundingBoxMinimum_X": "2", + "AreaShape_BoundingBoxMaximum_X": "7", + "AreaShape_BoundingBoxMinimum_Y": "2", + "AreaShape_BoundingBoxMaximum_Y": "7", + "AreaShape_FormFactor": "1.227184630308513", + "AreaShape_Extent": "1.0", + "AreaShape_Solidity": "1.0", + "AreaShape_Compactness": "0.8148733086305041", + "AreaShape_EulerNumber": "1", + "AreaShape_MaximumRadius": "3.0", + "AreaShape_MeanRadius": "1.4", + "AreaShape_MedianRadius": "1.0", + "AreaShape_ConvexArea": "25.0", + "AreaShape_MinFeretDiameter": "4.0", + "AreaShape_MaxFeretDiameter": "5.656854249492381", + "AreaShape_EquivalentDiameter": "5.641895835477563" + }, + { + "slice_index": "0", + "object_label": "2", + "AreaShape_Area": "12.0", + "AreaShape_Perimeter": "10.0", + "AreaShape_MajorAxisLength": "4.47213595499958", + "AreaShape_MinorAxisLength": "3.2659863237109037", + "AreaShape_Eccentricity": "0.6831300510639733", + "AreaShape_Orientation": "90.0", + "AreaShape_Center_X": "21.5", + "AreaShape_Center_Y": "13.0", + "AreaShape_BoundingBoxArea": "12.0", + "AreaShape_BoundingBoxMinimum_X": "20", + "AreaShape_BoundingBoxMaximum_X": "24", + "AreaShape_BoundingBoxMinimum_Y": "12", + "AreaShape_BoundingBoxMaximum_Y": "15", + "AreaShape_FormFactor": "1.5079644737231006", + "AreaShape_Extent": "1.0", + "AreaShape_Solidity": "1.0", + "AreaShape_Compactness": "0.6631455962162306", + "AreaShape_EulerNumber": "1", + "AreaShape_MaximumRadius": "2.0", + "AreaShape_MeanRadius": "1.1666666666666667", + "AreaShape_MedianRadius": "1.0", + "AreaShape_ConvexArea": "12.0", + "AreaShape_MinFeretDiameter": "2.0", + "AreaShape_MaxFeretDiameter": "3.605551275463989", + "AreaShape_EquivalentDiameter": "3.9088200952233594" + } + ], + "roi_count": null, + "roi_member_count": null, + "roi_duplicate_member_count": null, + "roi_area_min": null, + "roi_area_max": null, + "roi_area_mean": null, + "roi_examples": [], + "truncated": false, + "omitted_reason": null + } + }, + { + "relative_path": "checkpoints_step3/A01_s001_w2_z001_t001_ResizedConsumer.tif", + "full_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step3/A01_s001_w2_z001_t001_ResizedConsumer.tif", + "file_format": "TIFF", + "metadata": { + "filename": "checkpoints_step3/A01_s001_w2_z001_t001_ResizedConsumer.tif", + "type": "TIFF", + "size": "356 B", + "modified": "2026-10-03T23:29:49", + "result_subdirectory": "checkpoints_step3", + "full_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step3/A01_s001_w2_z001_t001_ResizedConsumer.tif", + "OpenHCSSourceVoxelSpacingZYX": "1.3555999999999999,1.3555999999999999", + "OpenHCSSourceVoxelSpacingUnit": "micrometers", + "OpenHCSSourceFilterPaths": { + "0": "A01_SavedIPO_step0.labels.tif", + "1": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v3/outputs/ipo/seed_openhcs/checkpoints_results/A01_SavedIPO_step0.labels.tif" + }, + "site": "1", + "channel": "2", + "z_index": "1", + "timepoint": "1", + "well": "A01", + "source_alias": "SavedImage", + "extension": ".tif" + }, + "preview": null + } + ], + "truncated_file_count": 0 + }, + "parse_summary": { + "attempted_file_count": 5, + "skipped_file_count": 0, + "parsed_file_count": 5, + "failed_file_count": 0, + "failure_samples": [], + "truncated_failure_count": 0 + }, + "components": [ + { + "component": "site", + "source": "metadata_and_parsed_filenames", + "count": 1, + "values": [ + { + "key": "1", + "label": null, + "declared_in_metadata": true, + "observed_in_filenames": true + } + ], + "truncated_value_count": 0 + }, + { + "component": "channel", + "source": "metadata_and_parsed_filenames", + "count": 1, + "values": [ + { + "key": "2", + "label": "SavedImage", + "declared_in_metadata": true, + "observed_in_filenames": true + } + ], + "truncated_value_count": 0 + }, + { + "component": "z_index", + "source": "metadata_and_parsed_filenames", + "count": 1, + "values": [ + { + "key": "1", + "label": null, + "declared_in_metadata": true, + "observed_in_filenames": true + } + ], + "truncated_value_count": 0 + }, + { + "component": "timepoint", + "source": "metadata_and_parsed_filenames", + "count": 1, + "values": [ + { + "key": "1", + "label": null, + "declared_in_metadata": true, + "observed_in_filenames": true + } + ], + "truncated_value_count": 0 + }, + { + "component": "well", + "source": "metadata_and_parsed_filenames", + "count": 1, + "values": [ + { + "key": "A01", + "label": null, + "declared_in_metadata": true, + "observed_in_filenames": true + } + ], + "truncated_value_count": 0 + } + ], + "source_diagnostics": [], + "format_specific_handler_candidates": [], + "workspace_preparation": { + "read_only_inspection": true, + "required_before_execution": false, + "operation": "none", + "reason": "OpenHCS metadata is already present; read-only inspection did not need workspace preparation." + }, + "workflow_advice": { + "workflow_scope": "diagnostic", + "ingestion_route": "detected_handler", + "ingestion_owner": "openhcsdata", + "source_binding_role": "not_projected_by_handler", + "ui_code_document_id": "plate_manager.orchestrator_config", + "ui_operation": "init", + "knowledge_query": "source model CZI Bio-Formats source bindings", + "probable_native_ingestion_owners": [], + "message": "Keep the detected openhcsdata handler as the ingestion owner. For a visible workflow, add the plate directory through the PlateManager code document and initialize with auto-detection. Use for a workspace already prepared by OpenHCS and carrying its metadata document. The recorded workspace metadata, not raw vendor filename resemblance, owns parser and backend selection. This handler does not project declared source bindings." + } + }, + "inventory": { + "schema_version": "openhcs.agent.v1", + "errors": [], + "warnings": [], + "plate_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs", + "result_directory": null, + "requested_microscope_type": "auto", + "detected_microscope_type": "openhcsdata", + "handler_class": "OpenHCSMicroscopeHandler", + "parser_class": "SourceSchemaFilenameParser", + "total_count": 5, + "returned_count": 5, + "offset": 0, + "limit": 100, + "truncated_count": 0, + "records": [ + { + "kind": "image", + "key": "checkpoints_step0/A01_s001_w2_z001_t001.tif", + "metadata": { + "filename": "checkpoints_step0/A01_s001_w2_z001_t001.tif", + "virtual_path": "checkpoints_step0/A01_s001_w2_z001_t001.tif", + "full_virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step0/A01_s001_w2_z001_t001.tif", + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step0/A01_s001_w2_z001_t001.tif", + "type": "Image", + "extension": ".tif", + "site": 1, + "channel": 2, + "z_index": 1, + "timepoint": 1, + "well": "A01", + "size": "312 B", + "modified": "2026-10-03T23:29:49" + }, + "virtual_path": "checkpoints_step0/A01_s001_w2_z001_t001.tif", + "full_virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step0/A01_s001_w2_z001_t001.tif", + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step0/A01_s001_w2_z001_t001.tif", + "relative_path": null, + "full_path": null, + "file_format": null, + "preview": null + }, + { + "kind": "image", + "key": "checkpoints_step1/A01_s001_w2_z001_t001_SavedDistance.tif", + "metadata": { + "filename": "checkpoints_step1/A01_s001_w2_z001_t001_SavedDistance.tif", + "virtual_path": "checkpoints_step1/A01_s001_w2_z001_t001_SavedDistance.tif", + "full_virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step1/A01_s001_w2_z001_t001_SavedDistance.tif", + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step1/A01_s001_w2_z001_t001_SavedDistance.tif", + "type": "Image", + "OpenHCSSourceVoxelSpacingZYX": "1.3555999999999999,1.3555999999999999", + "OpenHCSSourceVoxelSpacingUnit": "micrometers", + "OpenHCSSourceFilterPaths": { + "0": "A01_SavedIPO_step0.labels.tif", + "1": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v3/outputs/ipo/seed_openhcs/checkpoints_results/A01_SavedIPO_step0.labels.tif" + }, + "source_alias": "SavedImage", + "extension": ".tif", + "site": 1, + "channel": 2, + "z_index": 1, + "timepoint": 1, + "well": "A01", + "size": "335 B", + "modified": "2026-10-03T23:29:49" + }, + "virtual_path": "checkpoints_step1/A01_s001_w2_z001_t001_SavedDistance.tif", + "full_virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step1/A01_s001_w2_z001_t001_SavedDistance.tif", + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step1/A01_s001_w2_z001_t001_SavedDistance.tif", + "relative_path": null, + "full_path": null, + "file_format": null, + "preview": null + }, + { + "kind": "image", + "key": "checkpoints_step2/A01_s001_w2_z001_t001_ResizedDistance.tif", + "metadata": { + "filename": "checkpoints_step2/A01_s001_w2_z001_t001_ResizedDistance.tif", + "virtual_path": "checkpoints_step2/A01_s001_w2_z001_t001_ResizedDistance.tif", + "full_virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step2/A01_s001_w2_z001_t001_ResizedDistance.tif", + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step2/A01_s001_w2_z001_t001_ResizedDistance.tif", + "type": "Image", + "OpenHCSSourceVoxelSpacingZYX": "1.3555999999999999,1.3555999999999999", + "OpenHCSSourceVoxelSpacingUnit": "micrometers", + "OpenHCSSourceFilterPaths": { + "0": "A01_SavedIPO_step0.labels.tif", + "1": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v3/outputs/ipo/seed_openhcs/checkpoints_results/A01_SavedIPO_step0.labels.tif" + }, + "source_alias": "SavedImage", + "extension": ".tif", + "site": 1, + "channel": 2, + "z_index": 1, + "timepoint": 1, + "well": "A01", + "size": "356 B", + "modified": "2026-10-03T23:29:49" + }, + "virtual_path": "checkpoints_step2/A01_s001_w2_z001_t001_ResizedDistance.tif", + "full_virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step2/A01_s001_w2_z001_t001_ResizedDistance.tif", + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step2/A01_s001_w2_z001_t001_ResizedDistance.tif", + "relative_path": null, + "full_path": null, + "file_format": null, + "preview": null + }, + { + "kind": "image", + "key": "checkpoints_step3/A01_s001_w2_z001_t001_ResizedConsumer.tif", + "metadata": { + "filename": "checkpoints_step3/A01_s001_w2_z001_t001_ResizedConsumer.tif", + "virtual_path": "checkpoints_step3/A01_s001_w2_z001_t001_ResizedConsumer.tif", + "full_virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step3/A01_s001_w2_z001_t001_ResizedConsumer.tif", + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step3/A01_s001_w2_z001_t001_ResizedConsumer.tif", + "type": "Image", + "OpenHCSSourceVoxelSpacingZYX": "1.3555999999999999,1.3555999999999999", + "OpenHCSSourceVoxelSpacingUnit": "micrometers", + "OpenHCSSourceFilterPaths": { + "0": "A01_SavedIPO_step0.labels.tif", + "1": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v3/outputs/ipo/seed_openhcs/checkpoints_results/A01_SavedIPO_step0.labels.tif" + }, + "source_alias": "SavedImage", + "extension": ".tif", + "site": 1, + "channel": 2, + "z_index": 1, + "timepoint": 1, + "well": "A01", + "source_artifact_type": "image", + "size": "356 B", + "modified": "2026-10-03T23:29:49" + }, + "virtual_path": "checkpoints_step3/A01_s001_w2_z001_t001_ResizedConsumer.tif", + "full_virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step3/A01_s001_w2_z001_t001_ResizedConsumer.tif", + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step3/A01_s001_w2_z001_t001_ResizedConsumer.tif", + "relative_path": null, + "full_path": null, + "file_format": null, + "preview": null + }, + { + "kind": "image", + "key": "images/A01_s001_w2_z001_t001_ResizedConsumer.tif", + "metadata": { + "filename": "images/A01_s001_w2_z001_t001_ResizedConsumer.tif", + "virtual_path": "images/A01_s001_w2_z001_t001_ResizedConsumer.tif", + "full_virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/images/A01_s001_w2_z001_t001_ResizedConsumer.tif", + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/images/A01_s001_w2_z001_t001_ResizedConsumer.tif", + "type": "Image", + "OpenHCSSourceVoxelSpacingZYX": "1.3555999999999999,1.3555999999999999", + "OpenHCSSourceVoxelSpacingUnit": "micrometers", + "OpenHCSSourceFilterPaths": { + "0": "A01_SavedIPO_step0.labels.tif", + "1": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v3/outputs/ipo/seed_openhcs/checkpoints_results/A01_SavedIPO_step0.labels.tif" + }, + "source_alias": "SavedImage", + "extension": ".tif", + "site": 1, + "channel": 2, + "z_index": 1, + "timepoint": 1, + "well": "A01", + "size": "356 B", + "modified": "2026-10-03T23:29:49" + }, + "virtual_path": "images/A01_s001_w2_z001_t001_ResizedConsumer.tif", + "full_virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/images/A01_s001_w2_z001_t001_ResizedConsumer.tif", + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/images/A01_s001_w2_z001_t001_ResizedConsumer.tif", + "relative_path": null, + "full_path": null, + "file_format": null, + "preview": null + } + ] + }, + "samples": { + "SavedDistance": { + "schema_version": "openhcs.agent.v1", + "errors": [], + "warnings": [], + "plate_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs", + "requested_image_path": "checkpoints_step1/A01_s001_w2_z001_t001_SavedDistance.tif", + "virtual_path": "checkpoints_step1/A01_s001_w2_z001_t001_SavedDistance.tif", + "full_virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step1/A01_s001_w2_z001_t001_SavedDistance.tif", + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step1/A01_s001_w2_z001_t001_SavedDistance.tif", + "source_metadata": { + "filename": "checkpoints_step1/A01_s001_w2_z001_t001_SavedDistance.tif", + "virtual_path": "checkpoints_step1/A01_s001_w2_z001_t001_SavedDistance.tif", + "full_virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step1/A01_s001_w2_z001_t001_SavedDistance.tif", + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step1/A01_s001_w2_z001_t001_SavedDistance.tif", + "type": "Image", + "OpenHCSSourceVoxelSpacingZYX": "1.3555999999999999,1.3555999999999999", + "OpenHCSSourceVoxelSpacingUnit": "micrometers", + "OpenHCSSourceFilterPaths": { + "0": "A01_SavedIPO_step0.labels.tif", + "1": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v3/outputs/ipo/seed_openhcs/checkpoints_results/A01_SavedIPO_step0.labels.tif" + }, + "source_alias": "SavedImage", + "extension": ".tif", + "site": 1, + "channel": 2, + "z_index": 1, + "timepoint": 1, + "well": "A01", + "size": "335 B", + "modified": "2026-10-03T23:29:49" + }, + "shape": [ + 32, + 32 + ], + "resolution_shape": [ + 32, + 32 + ], + "dtype": "float32", + "minimum": 0.0, + "maximum": 3.0, + "mean": 0.0478515625, + "requested_resolution_index": null, + "selected_resolution_index": 0, + "resolution_count": 1, + "downsample_yx": [ + 1.0, + 1.0 + ], + "statistics_scope": "source_resolution", + "sample_origin_yx": [ + 0, + 0 + ], + "sample_shape": [ + 2, + 2 + ], + "sample_included": true, + "sample_values": [ + [ + 0.0, + 0.0 + ], + [ + 0.0, + 0.0 + ] + ], + "sample_omitted_reason": null + }, + "ResizedDistance": { + "schema_version": "openhcs.agent.v1", + "errors": [], + "warnings": [], + "plate_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs", + "requested_image_path": "checkpoints_step2/A01_s001_w2_z001_t001_ResizedDistance.tif", + "virtual_path": "checkpoints_step2/A01_s001_w2_z001_t001_ResizedDistance.tif", + "full_virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step2/A01_s001_w2_z001_t001_ResizedDistance.tif", + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step2/A01_s001_w2_z001_t001_ResizedDistance.tif", + "source_metadata": { + "filename": "checkpoints_step2/A01_s001_w2_z001_t001_ResizedDistance.tif", + "virtual_path": "checkpoints_step2/A01_s001_w2_z001_t001_ResizedDistance.tif", + "full_virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step2/A01_s001_w2_z001_t001_ResizedDistance.tif", + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step2/A01_s001_w2_z001_t001_ResizedDistance.tif", + "type": "Image", + "OpenHCSSourceVoxelSpacingZYX": "1.3555999999999999,1.3555999999999999", + "OpenHCSSourceVoxelSpacingUnit": "micrometers", + "OpenHCSSourceFilterPaths": { + "0": "A01_SavedIPO_step0.labels.tif", + "1": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v3/outputs/ipo/seed_openhcs/checkpoints_results/A01_SavedIPO_step0.labels.tif" + }, + "source_alias": "SavedImage", + "extension": ".tif", + "site": 1, + "channel": 2, + "z_index": 1, + "timepoint": 1, + "well": "A01", + "size": "356 B", + "modified": "2026-10-03T23:29:49" + }, + "shape": [ + 64, + 64 + ], + "resolution_shape": [ + 64, + 64 + ], + "dtype": "float32", + "minimum": 0.0, + "maximum": 3.0, + "mean": 0.0478515625, + "requested_resolution_index": null, + "selected_resolution_index": 0, + "resolution_count": 1, + "downsample_yx": [ + 1.0, + 1.0 + ], + "statistics_scope": "source_resolution", + "sample_origin_yx": [ + 0, + 0 + ], + "sample_shape": [ + 2, + 2 + ], + "sample_included": true, + "sample_values": [ + [ + 0.0, + 0.0 + ], + [ + 0.0, + 0.0 + ] + ], + "sample_omitted_reason": null + }, + "ResizedConsumer": { + "schema_version": "openhcs.agent.v1", + "errors": [], + "warnings": [], + "plate_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs", + "requested_image_path": "images/A01_s001_w2_z001_t001_ResizedConsumer.tif", + "virtual_path": "images/A01_s001_w2_z001_t001_ResizedConsumer.tif", + "full_virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/images/A01_s001_w2_z001_t001_ResizedConsumer.tif", + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/images/A01_s001_w2_z001_t001_ResizedConsumer.tif", + "source_metadata": { + "filename": "images/A01_s001_w2_z001_t001_ResizedConsumer.tif", + "virtual_path": "images/A01_s001_w2_z001_t001_ResizedConsumer.tif", + "full_virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/images/A01_s001_w2_z001_t001_ResizedConsumer.tif", + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/images/A01_s001_w2_z001_t001_ResizedConsumer.tif", + "type": "Image", + "OpenHCSSourceVoxelSpacingZYX": "1.3555999999999999,1.3555999999999999", + "OpenHCSSourceVoxelSpacingUnit": "micrometers", + "OpenHCSSourceFilterPaths": { + "0": "A01_SavedIPO_step0.labels.tif", + "1": "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v3/outputs/ipo/seed_openhcs/checkpoints_results/A01_SavedIPO_step0.labels.tif" + }, + "source_alias": "SavedImage", + "extension": ".tif", + "site": 1, + "channel": 2, + "z_index": 1, + "timepoint": 1, + "well": "A01", + "size": "356 B", + "modified": "2026-10-03T23:29:49" + }, + "shape": [ + 64, + 64 + ], + "resolution_shape": [ + 64, + 64 + ], + "dtype": "float32", + "minimum": 0.0, + "maximum": 3.0, + "mean": 0.0478515625, + "requested_resolution_index": null, + "selected_resolution_index": 0, + "resolution_count": 1, + "downsample_yx": [ + 1.0, + 1.0 + ], + "statistics_scope": "source_resolution", + "sample_origin_yx": [ + 0, + 0 + ], + "sample_shape": [ + 2, + 2 + ], + "sample_included": true, + "sample_values": [ + [ + 0.0, + 0.0 + ], + [ + 0.0, + 0.0 + ] + ], + "sample_omitted_reason": null + } + }, + "areas": [ + 25.0, + 12.0 + ], + "csv_files": [ + "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step0_results/A01_SavedIPOShape_1_measurements_step0_details.csv" + ] + }, + "output_files_after": { + "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs/input_openhcs/images/A01_s001_w2_z001_t001_capped_outgrowth_processing_role.tif": "c849c419fb6963fd458874a387d3f917c06c15de5e1532e60c6ec8e84ffff68c", + "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs/input_openhcs/images/A01_s001_w2_z001_t001_raw_body_processing_role.tif": "2c6af3065b97c59d36a34b1f6ee4f7eaabf6d2ca44ccb07827b5e59335d5dc7f", + "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs/input_openhcs/openhcs_metadata.json": "b9c6a375aada724c4d4859fad51def6e421cea8e952a482e23659e4cda3d210a", + "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v2/outputs/input_openhcs/openhcs_metadata.json.lock": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v3/outputs/ipo/seed_openhcs/checkpoints/A01_s001_w2_z001_t001.tif": "3c4e6fe6cf04439c73cfec7adf6fb87d5cd709886a51a47abd9b02f68f7eb15c", + "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v3/outputs/ipo/seed_openhcs/checkpoints_results/A01_ProduceSavedIPO_1_measurements_step0_details.csv": "c5f87bc8a56ba31b8416bddb5690a7b89c0e719dfda2720194bebb39e1b56293", + "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v3/outputs/ipo/seed_openhcs/checkpoints_results/A01_SavedIPO__qa_checkpoint__declump_response_step0.tif": "9b5c5e34a7478e204832f194487a38d213d408d4cde8e75192a37d482489433c", + "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v3/outputs/ipo/seed_openhcs/checkpoints_results/A01_SavedIPO__qa_checkpoint__initial_components_step0.tif": "6d4aa46dcee3c97b08cbc437a1f18877133e757d7ba908f514e3755368d17974", + "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v3/outputs/ipo/seed_openhcs/checkpoints_results/A01_SavedIPO__qa_checkpoint__seed_markers_step0.tif": "4f9b6b07a6bac02ea7c547a45a5889c289f4012a6129aff2d9143faa5353bd6e", + "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v3/outputs/ipo/seed_openhcs/checkpoints_results/A01_SavedIPO__qa_checkpoint__seed_maxima_step0.tif": "a58c2391271947b06775d3fcb2b943b25703fdb2f6bc254e47285b93b00898b0", + "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v3/outputs/ipo/seed_openhcs/checkpoints_results/A01_SavedIPO__qa_checkpoint__small_removed_objects_step0.tif": "6d4aa46dcee3c97b08cbc437a1f18877133e757d7ba908f514e3755368d17974", + "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v3/outputs/ipo/seed_openhcs/checkpoints_results/A01_SavedIPO__qa_checkpoint__threshold_support_step0.tif": "60a7157936cf6019a6177584a107d0382c180b55d85519501b02d6c68c0e6cc3", + "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v3/outputs/ipo/seed_openhcs/checkpoints_results/A01_SavedIPO__qa_checkpoint__unedited_objects_step0.tif": "6d4aa46dcee3c97b08cbc437a1f18877133e757d7ba908f514e3755368d17974", + "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v3/outputs/ipo/seed_openhcs/checkpoints_results/A01_SavedIPO_step0.labels.tif": "6d4aa46dcee3c97b08cbc437a1f18877133e757d7ba908f514e3755368d17974", + "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v3/outputs/ipo/seed_openhcs/checkpoints_results/A01_SavedIPO_step0_rois.roi.zip": "9282dbf2a2d18552b7874ec1aa1b84a8b0072df87aedbdc3f919826c4ce4fe85", + "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v3/outputs/ipo/seed_openhcs/checkpoints_results/A01_SavedIPO_step0_segmentation_summary.txt": "04ce2d48d8621343b5ef319fe53b2a66faea9084069a2911c965feef82253b5d", + "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v3/outputs/ipo/seed_openhcs/checkpoints_results/openhcs_metadata.json": "c5077cd1669ec5b0d6ad86afa33f46c8de08e7b9773ad0156b94bd8a9004256d", + "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v3/outputs/ipo/seed_openhcs/checkpoints_results/openhcs_metadata.json.lock": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v3/outputs/ipo/seed_openhcs/images/A01_s001_w2_z001_t001.tif": "3c4e6fe6cf04439c73cfec7adf6fb87d5cd709886a51a47abd9b02f68f7eb15c", + "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v3/outputs/ipo/seed_openhcs/openhcs_metadata.json": "ba74ca1a758c7a89441a1f6058ef604e84b603ad798b246abf4eb89fd78d7865", + "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v3/outputs/ipo/seed_openhcs/openhcs_metadata.json.lock": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step0/A01_s001_w2_z001_t001.tif": "6d4aa46dcee3c97b08cbc437a1f18877133e757d7ba908f514e3755368d17974", + "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step0_results/A01_SavedIPOShape_1_measurements_step0_details.csv": "990b9c33e8bcebce675b7ba93baa54a759297a70f834e149af6dae5407070eea", + "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step1/A01_s001_w2_z001_t001_SavedDistance.tif": "001aa97060b3bafeb87d08287ea226c6aeed8e18e60dc647e935f61e16123f69", + "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step2/A01_s001_w2_z001_t001_ResizedDistance.tif": "9f8795cfe6a54e1d260e32db3f54de70b5966fbb628181c882b016b97c22e29a", + "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/checkpoints_step3/A01_s001_w2_z001_t001_ResizedConsumer.tif": "9f8795cfe6a54e1d260e32db3f54de70b5966fbb628181c882b016b97c22e29a", + "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/images/A01_s001_w2_z001_t001_ResizedConsumer.tif": "9f8795cfe6a54e1d260e32db3f54de70b5966fbb628181c882b016b97c22e29a", + "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/openhcs_metadata.json": "7c321a6c343856f313f821bec819165dbb4dc1ac4d2901c05c68b1d606904866", + "/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved/checkpoints_results_openhcs/openhcs_metadata.json.lock": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + }, + "reader_processes_terminal": true, + "reader_returncodes": [ + 0 + ] +} diff --git a/docs/refactor/receipts/installed-consumers-419-435-450-20261004/saved-label-geometry-distance-resize-saved-pipeline.py b/docs/refactor/receipts/installed-consumers-419-435-450-20261004/saved-label-geometry-distance-resize-saved-pipeline.py new file mode 100644 index 0000000000..31f65338c6 --- /dev/null +++ b/docs/refactor/receipts/installed-consumers-419-435-450-20261004/saved-label-geometry-distance-resize-saved-pipeline.py @@ -0,0 +1,329 @@ +# OpenHCS pipeline + +from openhcs.constants.constants import ( + AllComponents, + GroupBy, + Microscope, + VariableComponents, +) +from openhcs.constants.input_source import InputSource +from openhcs.core.artifacts import ObjectLabelsArtifactType +from openhcs.core.config import ( + LazyAnalysisConsolidationConfig, + LazyCompilationDebugConfig, + LazyDtypeConfig, + LazyFijiDisplayConfig, + LazyFijiStreamingConfig, + LazyNapariDisplayConfig, + LazyNapariStreamingConfig, + LazyPathPlanningConfig, + LazyPlateMetadataConfig, + LazyProcessingConfig, + LazySequentialProcessingConfig, + LazyStepMaterializationConfig, + LazyStepWellFilterConfig, + LazyStreamingDefaults, + LazyTiffConfig, + LazyVFSConfig, + LazyWellFilterConfig, + LazyZarrConfig, + MultiprocessingStartMethod, + PipelineConfig, +) +from openhcs.core.source_bindings import ( + ComponentSelector, + LazySourceBindingsConfig, + LazyStepSourceBindingsConfig, + NamedSourceBinding, + SourceBindingMatchDimension, + SourceBindingMatchField, + SourceBindingMatchMethod, + SourceBindingMatchPlan, + SourceFilterClause, + SourceFilterMatchType, + SourceFilterSubject, + SourceProjectionRole, + SourceSelector, +) +from openhcs.core.source_metadata import SourceVoxelSpacing +from openhcs.core.source_spatial_domain import SourceSpatialDomain +from openhcs.core.steps.function_step import FunctionStep +from openhcs.processing.backends.cellprofiler.image_math import ImageMathOperation +from openhcs.processing.backends.cellprofiler.morphology import MorphOperation +from openhcs.processing.func_registry import get_function +from pathlib import Path +from polystore.config import TiffCompression + +pipeline_config = PipelineConfig( + materialization_results_path=Path('results'), + materialize_runtime_artifacts=True, + num_workers=1, + microscope=Microscope.SOURCE_BINDINGS, + use_threading=False, + multiprocessing_start_method=MultiprocessingStartMethod.SPAWN, + auto_add_output_plate_to_plate_manager=False, + napari_display_config=LazyNapariDisplayConfig(), + fiji_display_config=LazyFijiDisplayConfig(), + well_filter_config=LazyWellFilterConfig( + well_filter='A01' + ), + zarr_config=LazyZarrConfig(), + tiff_config=LazyTiffConfig( + compression=TiffCompression.DEFLATE, + compression_level=9 + ), + vfs_config=LazyVFSConfig(), + dtype_config=LazyDtypeConfig(), + processing_config=LazyProcessingConfig(), + source_bindings_config=LazySourceBindingsConfig( + metadata_rules=(), + match_plan=SourceBindingMatchPlan( + method=SourceBindingMatchMethod.METADATA, + dimensions=( + SourceBindingMatchDimension( + fields=( + SourceBindingMatchField( + alias='SavedImage', + metadata_field='well' + ), + SourceBindingMatchField( + alias='SavedIPO', + metadata_field='well' + ) + ) + ), + SourceBindingMatchDimension( + fields=( + SourceBindingMatchField( + alias='SavedImage', + metadata_field='site' + ), + SourceBindingMatchField( + alias='SavedIPO', + metadata_field='site' + ) + ) + ), + SourceBindingMatchDimension( + fields=( + SourceBindingMatchField( + alias='SavedImage', + metadata_field='channel' + ), + SourceBindingMatchField( + alias='SavedIPO', + metadata_field='channel' + ) + ) + ), + SourceBindingMatchDimension( + fields=( + SourceBindingMatchField( + alias='SavedImage', + metadata_field='z_index' + ), + SourceBindingMatchField( + alias='SavedIPO', + metadata_field='z_index' + ) + ) + ), + SourceBindingMatchDimension( + fields=( + SourceBindingMatchField( + alias='SavedImage', + metadata_field='timepoint' + ), + SourceBindingMatchField( + alias='SavedIPO', + metadata_field='timepoint' + ) + ) + ) + ) + ), + metadata_fields=(), + source_filters=(), + bindings=( + NamedSourceBinding( + alias='SavedImage', + selector=SourceSelector( + filters=( + SourceFilterClause( + subject=SourceFilterSubject.FILE, + match_type=SourceFilterMatchType.EQUALS, + value='A01_SavedIPO_step0.labels.tif' + ), + ) + ), + component_identity=( + ComponentSelector( + component=AllComponents.WELL, + value='A01' + ), + ComponentSelector( + component=AllComponents.SITE, + value='1' + ), + ComponentSelector( + component=AllComponents.CHANNEL, + value='2' + ), + ComponentSelector( + component=AllComponents.Z_INDEX, + value='1' + ), + ComponentSelector( + component=AllComponents.TIMEPOINT, + value='1' + ) + ) + ), + NamedSourceBinding( + alias='SavedIPO', + selector=SourceSelector( + filters=( + SourceFilterClause( + subject=SourceFilterSubject.FILE, + match_type=SourceFilterMatchType.EQUALS, + value='A01_SavedIPO_step0.labels.tif' + ), + ) + ), + component_identity=( + ComponentSelector( + component=AllComponents.WELL, + value='A01' + ), + ComponentSelector( + component=AllComponents.SITE, + value='1' + ), + ComponentSelector( + component=AllComponents.CHANNEL, + value='2' + ), + ComponentSelector( + component=AllComponents.Z_INDEX, + value='1' + ), + ComponentSelector( + component=AllComponents.TIMEPOINT, + value='1' + ) + ), + artifact_kind=ObjectLabelsArtifactType, + projection_role=SourceProjectionRole.SOURCE_ARTIFACT + ) + ), + image_plane_sources=(), + imported_metadata_tables=(), + source_stack_components=(), + source_spatial_domain=SourceSpatialDomain(), + grouping_metadata_fields=(), + source_voxel_spacing=SourceVoxelSpacing( + values_zyx=( + 1.3556, + 1.3556 + ) + ) + ), + step_source_bindings_config=LazyStepSourceBindingsConfig(), + sequential_processing_config=LazySequentialProcessingConfig(), + analysis_consolidation_config=LazyAnalysisConsolidationConfig(), + plate_metadata_config=LazyPlateMetadataConfig(), + path_planning_config=LazyPathPlanningConfig( + well_filter='A01', + global_output_folder=Path('/home/ts/.local/state/openhcs-maintenance/20261004/installed-consumer-419-435-450-v7/outputs/saved') + ), + step_well_filter_config=LazyStepWellFilterConfig(), + step_materialization_config=LazyStepMaterializationConfig( + well_filter='A01', + enabled=True + ), + streaming_defaults=LazyStreamingDefaults(), + napari_streaming_config=LazyNapariStreamingConfig( + enabled=False + ), + fiji_streaming_config=LazyFijiStreamingConfig(), + compilation_debug_config=LazyCompilationDebugConfig() +) + +pipeline_steps = [ + FunctionStep( + func=(get_function('openhcs:cellprofiler_measure_object_size_shape'), { + 'calculate_advanced': False, + 'calculate_zernikes': False, + 'select_object_sets_to_measure': ( + 'SavedIPO', + ) + }), + name='SavedIPOShape', + processing_config=LazyProcessingConfig( + variable_components=[ + VariableComponents.CHANNEL + ], + group_by=GroupBy.NONE, + input_source=InputSource.PIPELINE_START + ), + source_bindings=LazyStepSourceBindingsConfig( + enabled=True + ) + ), + FunctionStep( + func=(get_function('openhcs:cellprofiler_morph'), { + 'operation': MorphOperation.DISTANCE, + 'rescale_values': False, + 'select_the_input_image': 'SavedImage', + 'name_the_output_image': 'SavedDistance' + }), + name='SavedIPODistance', + processing_config=LazyProcessingConfig( + variable_components=[ + VariableComponents.CHANNEL + ], + group_by=GroupBy.NONE, + input_source=InputSource.PIPELINE_START + ), + source_bindings=LazyStepSourceBindingsConfig( + enabled=True + ) + ), + FunctionStep( + func=(get_function('openhcs:cellprofiler_resize'), { + 'resizing_factor_x': 2.0, + 'resizing_factor_y': 2.0, + 'name_the_output_image': 'ResizedDistance' + }), + name='PreparedSavedDistanceResize', + processing_config=LazyProcessingConfig( + variable_components=[ + VariableComponents.CHANNEL + ], + group_by=GroupBy.NONE, + input_source=InputSource.PREVIOUS_STEP + ), + source_bindings=LazyStepSourceBindingsConfig( + enabled=False + ) + ), + FunctionStep( + func=(get_function('openhcs:cellprofiler_image_math'), { + 'operation': ImageMathOperation.NONE, + 'truncate_low': False, + 'truncate_high': False, + 'name_the_output_image': 'ResizedConsumer' + }), + name='ConsumePreparedResize', + processing_config=LazyProcessingConfig( + variable_components=[ + VariableComponents.CHANNEL + ], + group_by=GroupBy.NONE, + input_source=InputSource.PREVIOUS_STEP + ), + source_bindings=LazyStepSourceBindingsConfig( + enabled=False + ) + ) +] \ No newline at end of file diff --git a/docs/refactor/receipts/issue433-controlled-values-20261004/README.rst b/docs/refactor/receipts/issue433-controlled-values-20261004/README.rst new file mode 100644 index 0000000000..ef556df716 --- /dev/null +++ b/docs/refactor/receipts/issue433-controlled-values-20261004/README.rst @@ -0,0 +1,125 @@ +Controlled retained-VALUES repeat for issue #433 +================================================ + +All 16 public measured jobs and 32 strict native-output comparisons passed on +one READY server incarnation, without restarts, forced garbage collection, +process-cache clears, changed collection thresholds or observation exclusions. +This is a finite memory/scientific acceptance gate, not a latency experiment. + +Source and entry point +---------------------- + +The measured source is ``a6c0e1e030ae6b9859c7447541a7f1f89531e1cd``. The +source was frozen on HOME; installed editable dependencies, native binaries, +original input files, controller and native goldens were hashed before and after. +Newer ``origin/main`` (``eea1f25ca86f5ff9bad2d836b8cdeab55be6a8be``) was +recorded before the freeze; this sequence deliberately tests the specified source, +not subsequent compiler/dependency changes. + +The controller calls existing ``execute_measured_openhcs_pipeline_on_client`` +with original ``prepare_cellprofiler_input_workspace`` declarations and source +universes: 180 references for 3D, two for Speckles and ten for Beginner. All jobs +use one well/one inline thread, CPU5 and existing native thread limits. Mandatory +function-library/kernel READY warmup precedes jobs. The export scope is VALUES, +as in the original OOM; real record counts are 41/26/44 respectively. + +The finite sequence is ``[3D, Speckles, Beginner, 3D]`` repeated four times. +The endpoint PID is ``3971124``, create time ``1791086892.75``, +and port 7777 for every measured receipt and typed handshake. All 16 consumed +ordinary compile artifacts are unavailable through actual public compiled-artifact +inspection. Existing terminal statuses and output receipts remain complete. + +The native goldens are both fresh measured output sets from qualified V12. +Existing strict scientific/relationship/image/file-inventory owners compare each +job to both sets: 32 comparisons, all PASS. No native execution or native timing +was repeated. 3D pixels require exact agreement; existing native numerical +comparison tolerances apply elsewhere. No outputs/features were excluded. + +Bounded RSS evidence +-------------------- + +Existing ``MemoryMetric`` samples at a requested 50 ms interval and uses existing +``ChildProcessTerminator`` if aggregate owned controller/server/descendant RSS +exceeds 6144 MiB. A guard trip would stop the entire sequence, never restart or +continue on a new server. The controller only journals the existing samples. +This polling guard is not a kernel-enforced hard allocation ceiling. + +There are 6795 retained samples. The greatest observed sample gap is +0.770619 s. Aggregate peak is +4002.011719 MiB; sampled server peak is +2335.167969 MiB. READY server RSS is +962.812500 MiB; final post-job server RSS is +2131.953125 MiB. The first cycles allocate additional memory; the last seven +post-job values range from 2117.882812 to 2210.179688 MiB, +with the final cycle ending below the preceding cycle. This demonstrates a +plateau in this finite window, not infinite-run or full-catalog memory safety. +RSS does not distinguish live retention from allocator high-water capacity. + +All raw post-job samples are retained (MiB):: + + Job Case Server RSS Aggregate peak Values Science + 1 3D 1466.882812 2757.812500 41 PASS2 + 2 Speckles 1561.714844 2862.300781 26 PASS2 + 3 Beginner 1690.382812 3189.507812 44 PASS2 + 4 3D 1676.960938 3493.238281 41 PASS2 + 5 3D 1621.417969 3493.238281 41 PASS2 + 6 Speckles 1627.882812 3502.300781 26 PASS2 + 7 Beginner 1688.277344 3502.300781 44 PASS2 + 8 3D 2017.488281 3568.140625 41 PASS2 + 9 3D 2320.007812 4001.980469 41 PASS2 + 10 Speckles 2210.019531 4002.011719 26 PASS2 + 11 Beginner 2210.164062 4002.011719 44 PASS2 + 12 3D 2210.179688 4002.011719 41 PASS2 + 13 3D 2118.082031 4002.011719 41 PASS2 + 14 Speckles 2117.882812 4002.011719 26 PASS2 + 15 Beginner 2130.835938 4002.011719 44 PASS2 + 16 3D 2131.953125 4002.011719 41 PASS2 + +Retaining-owner evidence and limits +---------------------------------- + +The archived standalone actual production-query reproduction behind #582 proves +that process-wide label/vector/axis/schema caches retain two real label buffers +(1,048,576 bytes) after ``RuntimeValueStore.clear`` and return stale 0.5 after +store replacement with 7.5. The repaired replay immediately returns 7.5 and +releases the label buffers and feature column without a process-cache clear. +Five query/schema cache families, their three keys and the detached dataclass +row cache were removed; existing store-owned revision reuse and call-local +batching remain. Saved production CSV replay checks 936 correlated values. + +That proof identifies actual incorrect owners; it does not establish that these +were the sole cause of the historical 13 GiB OOM. The original dominant allocation +and retaining references were not captured. This controlled run is separate +empirical evidence of bounded repeated READY-server execution after the repairs. + +Existing wire STATUS excludes ``ExecutionRecord.metadata``. Live byte counts for +record extras and runtime stores are therefore not claimed. Orchestrator-extra +release, worker-store clear and parent diagnostic retention are documented source +laws; public consumed-artifact absence is the actual observed lifetime check. +The sequence preserves retained VALUES, publication and independent image buffers; +it does not change checkpoint/debug retention policies. + +Prelaunch RED is retained: the first preparation and launch used different shell +contexts, and the prelaunch source-state guard failed. The subsequent read-only +full comparison differed only in the inherited environment hash; all observed +source/dependency/input/native bytes were unchanged. No server or scientific +job started on that attempt. The successful namespace creates and validates its +complete freeze in the same taskset launch process, without dropping guard fields. + +The controlled-repeat acceptance clause in #433 is satisfied. Recommend closing +that bounded functional gate after review while keeping full 30-case scientific, +performance and scaling acceptance open in PR #394. No historical sole-cause, +full-catalog memory guarantee or individual timing gain is asserted. + +Retained artifacts +------------------ + +``qualification.json`` contains exact summary, raw post-job rows and hashes. +``original-evidence.tar.gz`` contains all 6795 RSS samples, all 16 job +receipts/comparisons, original freezes/endpoint records/controller/server logs, +prelaunch RED and original/fixed production-query proofs. Pixel outputs remain in +HOME's owned qualification namespace (482,867,459 bytes), without dataset copies. + +Archive SHA-256: ``7ec66003049ae82dcaabe286a525dc7fd725bcc1fbb28679f07a0fa1d9b85d66``. +Source freeze SHA-256: ``ae74357713b962276244810ddf13959565ad38295e954684bc95abb5805a48fd``. +RSS journal SHA-256: ``6488d594fe770328c1545d27688e4de68b732407de79a51e13a65c093d8a7538``. diff --git a/docs/refactor/receipts/issue433-controlled-values-20261004/original-evidence.tar.gz b/docs/refactor/receipts/issue433-controlled-values-20261004/original-evidence.tar.gz new file mode 100644 index 0000000000..3f7f74507f Binary files /dev/null and b/docs/refactor/receipts/issue433-controlled-values-20261004/original-evidence.tar.gz differ diff --git a/docs/refactor/receipts/issue433-controlled-values-20261004/qualification.json b/docs/refactor/receipts/issue433-controlled-values-20261004/qualification.json new file mode 100644 index 0000000000..bf96852d00 --- /dev/null +++ b/docs/refactor/receipts/issue433-controlled-values-20261004/qualification.json @@ -0,0 +1,1425 @@ +{ + "status": "PASS", + "source_head": "a6c0e1e030ae6b9859c7447541a7f1f89531e1cd", + "completed_jobs": 16, + "strict_comparisons": 32, + "one_endpoint": { + "pid": 3971124, + "create_time": 1791086892.75, + "port": 7777 + }, + "peak_aggregate_mb": 4002.01171875, + "cap_mb": 6144, + "postjob_server_rss_mb": [ + 1466.8828125, + 1561.71484375, + 1690.3828125, + 1676.9609375, + 1621.41796875, + 1627.8828125, + 1688.27734375, + 2017.48828125, + 2320.0078125, + 2210.01953125, + 2210.1640625, + 2210.1796875, + 2118.08203125, + 2117.8828125, + 2130.8359375, + 2131.953125 + ], + "scope": "Finite one-server VALUES repeat, not latency or full30 qualification. No forced GC/global clear/threshold changes/restarts. Native outputs reused solely for science.", + "live_extra_inspection": "Unavailable in existing wire protocol; STATUS deliberately excludes ExecutionRecord.metadata. Consumed compilation availability tested via existing compiled-artifact inspection.", + "memory_samples_sha256": "6488d594fe770328c1545d27688e4de68b732407de79a51e13a65c093d8a7538", + "source_freeze_sha256": "ae74357713b962276244810ddf13959565ad38295e954684bc95abb5805a48fd", + "ready_server_rss_mb": 962.8125, + "server_peak_sampled_mb": 2335.16796875, + "rss_sample_count": 6795, + "max_observed_sampling_gap_seconds": 0.7706191539764404, + "cycle_end_postjob_rss_mb": [ + 1676.9609375, + 2017.48828125, + 2210.1796875, + 2131.953125 + ], + "last_seven_postjob_range_mb": [ + 2117.8828125, + 2210.1796875 + ], + "retained_output_bytes": 482867459, + "archive": { + "filename": "original-evidence.tar.gz", + "sha256": "7ec66003049ae82dcaabe286a525dc7fd725bcc1fbb28679f07a0fa1d9b85d66", + "bytes": 1327577 + }, + "archived_files": [ + { + "path": "controlled/source-freeze.json", + "sha256": "ae74357713b962276244810ddf13959565ad38295e954684bc95abb5805a48fd", + "bytes": 1234263 + }, + { + "path": "controlled/decision.json", + "sha256": "68c7b6317a2d58c70ffc043354d517e57ce1fc87cd1eb77a0023c342c6fb76d1", + "bytes": 1191 + }, + { + "path": "controlled/ready-endpoint.json", + "sha256": "cf57018579164c0622ee7eba58d6b66e5deebb0054df5577929da08a5962d552", + "bytes": 303 + }, + { + "path": "controlled/ready-endpoint-final.json", + "sha256": "54d7547d7b97391b98ed3a185503de4b96f70f5d4dabe2f4f7496baa5d17d987", + "bytes": 134 + }, + { + "path": "controlled/rss-samples.jsonl", + "sha256": "6488d594fe770328c1545d27688e4de68b732407de79a51e13a65c093d8a7538", + "bytes": 690157 + }, + { + "path": "controlled/job-00.json", + "sha256": "edb01f901e1b627f97810a99ac9362f25d32db79931c0fec168ee12c5832fab1", + "bytes": 27544 + }, + { + "path": "controlled/job-01.json", + "sha256": "5679bd212689b1c6338214d727c666fa441a9ead500eac20c3451ca020fc3fb6", + "bytes": 27334 + }, + { + "path": "controlled/job-02.json", + "sha256": "63fe23612abe548dc6235d5e786436cd2669b052eccbc85425164f8712b7730a", + "bytes": 27859 + }, + { + "path": "controlled/job-03.json", + "sha256": "53df8bb7c69461998644fcd1d536661a7ed9d91d694d4268f07e1d59180c24e9", + "bytes": 27548 + }, + { + "path": "controlled/job-04.json", + "sha256": "9bf77958a79bb8cfdd323238cae5b971b5837739c8e2ff20876f6a69e58e2c03", + "bytes": 27551 + }, + { + "path": "controlled/job-05.json", + "sha256": "f72dc1045a8e227b61133f1756dcf3c964833e35c132f31e7d95e1bca9da86e2", + "bytes": 27333 + }, + { + "path": "controlled/job-06.json", + "sha256": "e687c876175e225d651c22f1d65f7f9c2eb6ee9ed4ad80031455de7f031c19e8", + "bytes": 27861 + }, + { + "path": "controlled/job-07.json", + "sha256": "1a628b635c2d22304a3a9e6d29d6339dd6c7085e40e76ea65faf4fe9af8fb7d5", + "bytes": 27548 + }, + { + "path": "controlled/job-08.json", + "sha256": "c6a9d99efe01a5cbdd39402d3dd25e05dc65851281d1b9c3e1f9b4703915abc5", + "bytes": 27549 + }, + { + "path": "controlled/job-09.json", + "sha256": "b2f5e6d58a09f518f451e711eb213804737232a3d1f112bb77c8ab9e76736661", + "bytes": 27331 + }, + { + "path": "controlled/job-10.json", + "sha256": "da48e122abfaa1db7f579aa538ef4f5c505082162a442554eaec5303e803d79b", + "bytes": 27870 + }, + { + "path": "controlled/job-11.json", + "sha256": "51c077f9c9d9df3fe51fbf69ae48cf2b4a6a27df2fd0d84cf05457cccb492a1c", + "bytes": 27559 + }, + { + "path": "controlled/job-12.json", + "sha256": "c45b8d5af60ece3e833ebe80503fcb81ebf415ffac6370222ad404155d077e07", + "bytes": 27558 + }, + { + "path": "controlled/job-13.json", + "sha256": "3bc7fdd0ff9b8f1ed135cfebda29a470e35eee564b3113b6fb35e5adadbc70d5", + "bytes": 27341 + }, + { + "path": "controlled/job-14.json", + "sha256": "bc871c3d9fb6ac19be83fb71baec8d125afbddbf2202d819ba3c2b443eedb5c2", + "bytes": 27873 + }, + { + "path": "controlled/job-15.json", + "sha256": "0dcfea14cb2b29e770e359222372c6ff900af50dc4bb89af4b1d94901a433640", + "bytes": 27559 + }, + { + "path": "controller/controller.py", + "sha256": "f535758caf792fa4e13d986240816e55ffc25c5b4a37c0d38264babad02bd1f1", + "bytes": 17242 + }, + { + "path": "controller/controller-prelaunch-rejected.py", + "sha256": "ca8f5d96d08ae709bb05e35e275992ca708527ccfa0cf3542668f5610c4b124d", + "bytes": 17165 + }, + { + "path": "controller/prepare.log", + "sha256": "1e012a6fa3dfb100a3ac9d6dc10ea79c3b2f49bf9c09e1b19968f6b2a7268c98", + "bytes": 696 + }, + { + "path": "controller/run.log", + "sha256": "4dc275f26ee1d338f40bb1e8979337c94ab579a76b67689738dfe793274ca2d9", + "bytes": 848 + }, + { + "path": "controller/run-v2.log", + "sha256": "cc6f12928ca7f8678b057b210fd16a439a1bc3dbb99cf3641beae1230b636e68", + "bytes": 3427 + }, + { + "path": "prelaunch-red/source-freeze.json", + "sha256": "9f0911a79a8db4b9f48135c2063dcbdfce07595730fd2b252e5640602c3d4a1c", + "bytes": 1234143 + }, + { + "path": "prelaunch-red/prelaunch-state-current.json", + "sha256": "e0ea5ec628b18b4ce4d1f5962b06815fcc57cb314eaf7fcce6a7cbaf8b65e3a3", + "bytes": 1204989 + }, + { + "path": "query-retention/openhcs-measurement-cache-retention-proof-20261004.py", + "sha256": "3105e966ba91ca6b854d0cf549161fe51cb59d4bdd5623f8f9a75bb6a82bbeec", + "bytes": 5627 + }, + { + "path": "query-retention/openhcs-measurement-cache-retention-proof-20261004.json", + "sha256": "111cab1ee6ed16986277217c15e613663e32385b10cc266c85a3d665fe6efe2e", + "bytes": 1128 + }, + { + "path": "query-retention/openhcs-measurement-cache-retention-fixed-replay-20261004.py", + "sha256": "b927714272ce12276738d97772b32b909bec632677a081a929b2bdfa32843e3d", + "bytes": 4271 + }, + { + "path": "query-retention/openhcs-measurement-cache-retention-fixed-replay-20261004.json", + "sha256": "82325ed210b0996b3d8178fd471d2dcbabec38fdcd79bf13160c6dc4bab94c4c", + "bytes": 584 + }, + { + "path": "query-retention/openhcs-measurement-cache-saved-production-replay-20261004.py", + "sha256": "57079170797fbc85d3dc236d0a58e07ebcfdc92840890413c6e090a38c089cd4", + "bytes": 3438 + }, + { + "path": "query-retention/openhcs-measurement-cache-saved-production-replay-20261004.json", + "sha256": "c0e301136e1d2b2820e51bb673f373fbab70f5d8deebd81ddf8df1da0dc814a8", + "bytes": 5447 + }, + { + "path": "controller/server.log", + "sha256": "fc3e1fa7905c3f3f67e6226882457e2f77b690acd3ba0ef69f4178c621ac104f", + "bytes": 17802 + } + ], + "raw_postjob_rows": [ + { + "index": 0, + "case": "cp_tutorial_3d_monolayer", + "before": { + "pid": 3971124, + "create_time": 1791086892.75, + "port": 7777, + "server_rss_bytes": 1009582080, + "epoch": 1791086948.2820473 + }, + "after": { + "pid": 3971124, + "create_time": 1791086892.75, + "port": 7777, + "server_rss_bytes": 1538138112, + "epoch": 1791086956.786006 + }, + "after_controller_release": { + "pid": 3971124, + "create_time": 1791086892.75, + "port": 7777, + "server_rss_bytes": 1538138112, + "epoch": 1791086959.2570045 + }, + "retained_record_counts": { + "W001": 41 + }, + "peak_aggregate_mb_so_far": 2757.8125, + "observation_export_bytes": 26229448, + "science": [ + { + "native_repeat": 0, + "measurement_differences": 0, + "image_differences": 0, + "tables": [ + 7, + 6 + ], + "physical_images": [ + 2, + 2 + ], + "logical_images": [ + 2, + 2 + ], + "known_relationship_keys": [ + 3, + 3 + ] + }, + { + "native_repeat": 1, + "measurement_differences": 0, + "image_differences": 0, + "tables": [ + 7, + 6 + ], + "physical_images": [ + 2, + 2 + ], + "logical_images": [ + 2, + 2 + ], + "known_relationship_keys": [ + 3, + 3 + ] + } + ] + }, + { + "index": 1, + "case": "ExampleSpeckles", + "before": { + "pid": 3971124, + "create_time": 1791086892.75, + "port": 7777, + "server_rss_bytes": 1538138112, + "epoch": 1791086959.270328 + }, + "after": { + "pid": 3971124, + "create_time": 1791086892.75, + "port": 7777, + "server_rss_bytes": 1637576704, + "epoch": 1791086961.1800673 + }, + "after_controller_release": { + "pid": 3971124, + "create_time": 1791086892.75, + "port": 7777, + "server_rss_bytes": 1637576704, + "epoch": 1791086962.3832035 + }, + "retained_record_counts": { + "W001": 26 + }, + "peak_aggregate_mb_so_far": 2862.30078125, + "observation_export_bytes": 12407840, + "science": [ + { + "native_repeat": 0, + "measurement_differences": 0, + "image_differences": 0, + "tables": [ + 3, + 3 + ], + "physical_images": [ + 0, + 0 + ], + "logical_images": [ + 0, + 0 + ], + "known_relationship_keys": [ + 1, + 1 + ] + }, + { + "native_repeat": 1, + "measurement_differences": 0, + "image_differences": 0, + "tables": [ + 3, + 3 + ], + "physical_images": [ + 0, + 0 + ], + "logical_images": [ + 0, + 0 + ], + "known_relationship_keys": [ + 1, + 1 + ] + } + ] + }, + { + "index": 2, + "case": "cp_tutorial_beginner_segmentation_final", + "before": { + "pid": 3971124, + "create_time": 1791086892.75, + "port": 7777, + "server_rss_bytes": 1637576704, + "epoch": 1791086962.3967478 + }, + "after": { + "pid": 3971124, + "create_time": 1791086892.75, + "port": 7777, + "server_rss_bytes": 1772494848, + "epoch": 1791086967.6351411 + }, + "after_controller_release": { + "pid": 3971124, + "create_time": 1791086892.75, + "port": 7777, + "server_rss_bytes": 1772494848, + "epoch": 1791087032.9085379 + }, + "retained_record_counts": { + "W001": 44 + }, + "peak_aggregate_mb_so_far": 3189.5078125, + "observation_export_bytes": 15477083, + "science": [ + { + "native_repeat": 0, + "measurement_differences": 0, + "image_differences": 0, + "tables": [ + 7, + 7 + ], + "physical_images": [ + 2, + 2 + ], + "logical_images": [ + 2, + 2 + ], + "known_relationship_keys": [ + 5, + 5 + ] + }, + { + "native_repeat": 1, + "measurement_differences": 0, + "image_differences": 0, + "tables": [ + 7, + 7 + ], + "physical_images": [ + 2, + 2 + ], + "logical_images": [ + 2, + 2 + ], + "known_relationship_keys": [ + 5, + 5 + ] + } + ] + }, + { + "index": 3, + "case": "cp_tutorial_3d_monolayer", + "before": { + "pid": 3971124, + "create_time": 1791086892.75, + "port": 7777, + "server_rss_bytes": 1772494848, + "epoch": 1791087032.9218714 + }, + "after": { + "pid": 3971124, + "create_time": 1791086892.75, + "port": 7777, + "server_rss_bytes": 1758420992, + "epoch": 1791087041.079347 + }, + "after_controller_release": { + "pid": 3971124, + "create_time": 1791086892.75, + "port": 7777, + "server_rss_bytes": 1758420992, + "epoch": 1791087042.0794837 + }, + "retained_record_counts": { + "W001": 41 + }, + "peak_aggregate_mb_so_far": 3493.23828125, + "observation_export_bytes": 26229440, + "science": [ + { + "native_repeat": 0, + "measurement_differences": 0, + "image_differences": 0, + "tables": [ + 7, + 6 + ], + "physical_images": [ + 2, + 2 + ], + "logical_images": [ + 2, + 2 + ], + "known_relationship_keys": [ + 3, + 3 + ] + }, + { + "native_repeat": 1, + "measurement_differences": 0, + "image_differences": 0, + "tables": [ + 7, + 6 + ], + "physical_images": [ + 2, + 2 + ], + "logical_images": [ + 2, + 2 + ], + "known_relationship_keys": [ + 3, + 3 + ] + } + ] + }, + { + "index": 4, + "case": "cp_tutorial_3d_monolayer", + "before": { + "pid": 3971124, + "create_time": 1791086892.75, + "port": 7777, + "server_rss_bytes": 1758420992, + "epoch": 1791087042.0934122 + }, + "after": { + "pid": 3971124, + "create_time": 1791086892.75, + "port": 7777, + "server_rss_bytes": 1700179968, + "epoch": 1791087048.7551827 + }, + "after_controller_release": { + "pid": 3971124, + "create_time": 1791086892.75, + "port": 7777, + "server_rss_bytes": 1700179968, + "epoch": 1791087049.610956 + }, + "retained_record_counts": { + "W001": 41 + }, + "peak_aggregate_mb_so_far": 3493.23828125, + "observation_export_bytes": 26229451, + "science": [ + { + "native_repeat": 0, + "measurement_differences": 0, + "image_differences": 0, + "tables": [ + 7, + 6 + ], + "physical_images": [ + 2, + 2 + ], + "logical_images": [ + 2, + 2 + ], + "known_relationship_keys": [ + 3, + 3 + ] + }, + { + "native_repeat": 1, + "measurement_differences": 0, + "image_differences": 0, + "tables": [ + 7, + 6 + ], + "physical_images": [ + 2, + 2 + ], + "logical_images": [ + 2, + 2 + ], + "known_relationship_keys": [ + 3, + 3 + ] + } + ] + }, + { + "index": 5, + "case": "ExampleSpeckles", + "before": { + "pid": 3971124, + "create_time": 1791086892.75, + "port": 7777, + "server_rss_bytes": 1700179968, + "epoch": 1791087049.6250563 + }, + "after": { + "pid": 3971124, + "create_time": 1791086892.75, + "port": 7777, + "server_rss_bytes": 1706958848, + "epoch": 1791087051.375434 + }, + "after_controller_release": { + "pid": 3971124, + "create_time": 1791086892.75, + "port": 7777, + "server_rss_bytes": 1706958848, + "epoch": 1791087052.5788448 + }, + "retained_record_counts": { + "W001": 26 + }, + "peak_aggregate_mb_so_far": 3502.30078125, + "observation_export_bytes": 12407843, + "science": [ + { + "native_repeat": 0, + "measurement_differences": 0, + "image_differences": 0, + "tables": [ + 3, + 3 + ], + "physical_images": [ + 0, + 0 + ], + "logical_images": [ + 0, + 0 + ], + "known_relationship_keys": [ + 1, + 1 + ] + }, + { + "native_repeat": 1, + "measurement_differences": 0, + "image_differences": 0, + "tables": [ + 3, + 3 + ], + "physical_images": [ + 0, + 0 + ], + "logical_images": [ + 0, + 0 + ], + "known_relationship_keys": [ + 1, + 1 + ] + } + ] + }, + { + "index": 6, + "case": "cp_tutorial_beginner_segmentation_final", + "before": { + "pid": 3971124, + "create_time": 1791086892.75, + "port": 7777, + "server_rss_bytes": 1706958848, + "epoch": 1791087052.5927496 + }, + "after": { + "pid": 3971124, + "create_time": 1791086892.75, + "port": 7777, + "server_rss_bytes": 1770287104, + "epoch": 1791087057.7784603 + }, + "after_controller_release": { + "pid": 3971124, + "create_time": 1791086892.75, + "port": 7777, + "server_rss_bytes": 1770287104, + "epoch": 1791087119.7366214 + }, + "retained_record_counts": { + "W001": 44 + }, + "peak_aggregate_mb_so_far": 3502.30078125, + "observation_export_bytes": 15477084, + "science": [ + { + "native_repeat": 0, + "measurement_differences": 0, + "image_differences": 0, + "tables": [ + 7, + 7 + ], + "physical_images": [ + 2, + 2 + ], + "logical_images": [ + 2, + 2 + ], + "known_relationship_keys": [ + 5, + 5 + ] + }, + { + "native_repeat": 1, + "measurement_differences": 0, + "image_differences": 0, + "tables": [ + 7, + 7 + ], + "physical_images": [ + 2, + 2 + ], + "logical_images": [ + 2, + 2 + ], + "known_relationship_keys": [ + 5, + 5 + ] + } + ] + }, + { + "index": 7, + "case": "cp_tutorial_3d_monolayer", + "before": { + "pid": 3971124, + "create_time": 1791086892.75, + "port": 7777, + "server_rss_bytes": 1770287104, + "epoch": 1791087119.7507863 + }, + "after": { + "pid": 3971124, + "create_time": 1791086892.75, + "port": 7777, + "server_rss_bytes": 2115489792, + "epoch": 1791087127.320304 + }, + "after_controller_release": { + "pid": 3971124, + "create_time": 1791086892.75, + "port": 7777, + "server_rss_bytes": 2115489792, + "epoch": 1791087128.2282498 + }, + "retained_record_counts": { + "W001": 41 + }, + "peak_aggregate_mb_so_far": 3568.140625, + "observation_export_bytes": 26229451, + "science": [ + { + "native_repeat": 0, + "measurement_differences": 0, + "image_differences": 0, + "tables": [ + 7, + 6 + ], + "physical_images": [ + 2, + 2 + ], + "logical_images": [ + 2, + 2 + ], + "known_relationship_keys": [ + 3, + 3 + ] + }, + { + "native_repeat": 1, + "measurement_differences": 0, + "image_differences": 0, + "tables": [ + 7, + 6 + ], + "physical_images": [ + 2, + 2 + ], + "logical_images": [ + 2, + 2 + ], + "known_relationship_keys": [ + 3, + 3 + ] + } + ] + }, + { + "index": 8, + "case": "cp_tutorial_3d_monolayer", + "before": { + "pid": 3971124, + "create_time": 1791086892.75, + "port": 7777, + "server_rss_bytes": 2115489792, + "epoch": 1791087128.2425702 + }, + "after": { + "pid": 3971124, + "create_time": 1791086892.75, + "port": 7777, + "server_rss_bytes": 2432704512, + "epoch": 1791087137.2907908 + }, + "after_controller_release": { + "pid": 3971124, + "create_time": 1791086892.75, + "port": 7777, + "server_rss_bytes": 2432704512, + "epoch": 1791087138.1241124 + }, + "retained_record_counts": { + "W001": 41 + }, + "peak_aggregate_mb_so_far": 4001.98046875, + "observation_export_bytes": 26229448, + "science": [ + { + "native_repeat": 0, + "measurement_differences": 0, + "image_differences": 0, + "tables": [ + 7, + 6 + ], + "physical_images": [ + 2, + 2 + ], + "logical_images": [ + 2, + 2 + ], + "known_relationship_keys": [ + 3, + 3 + ] + }, + { + "native_repeat": 1, + "measurement_differences": 0, + "image_differences": 0, + "tables": [ + 7, + 6 + ], + "physical_images": [ + 2, + 2 + ], + "logical_images": [ + 2, + 2 + ], + "known_relationship_keys": [ + 3, + 3 + ] + } + ] + }, + { + "index": 9, + "case": "ExampleSpeckles", + "before": { + "pid": 3971124, + "create_time": 1791086892.75, + "port": 7777, + "server_rss_bytes": 2432704512, + "epoch": 1791087138.1385155 + }, + "after": { + "pid": 3971124, + "create_time": 1791086892.75, + "port": 7777, + "server_rss_bytes": 2317373440, + "epoch": 1791087140.207031 + }, + "after_controller_release": { + "pid": 3971124, + "create_time": 1791086892.75, + "port": 7777, + "server_rss_bytes": 2317373440, + "epoch": 1791087141.3476853 + }, + "retained_record_counts": { + "W001": 26 + }, + "peak_aggregate_mb_so_far": 4002.01171875, + "observation_export_bytes": 12407840, + "science": [ + { + "native_repeat": 0, + "measurement_differences": 0, + "image_differences": 0, + "tables": [ + 3, + 3 + ], + "physical_images": [ + 0, + 0 + ], + "logical_images": [ + 0, + 0 + ], + "known_relationship_keys": [ + 1, + 1 + ] + }, + { + "native_repeat": 1, + "measurement_differences": 0, + "image_differences": 0, + "tables": [ + 3, + 3 + ], + "physical_images": [ + 0, + 0 + ], + "logical_images": [ + 0, + 0 + ], + "known_relationship_keys": [ + 1, + 1 + ] + } + ] + }, + { + "index": 10, + "case": "cp_tutorial_beginner_segmentation_final", + "before": { + "pid": 3971124, + "create_time": 1791086892.75, + "port": 7777, + "server_rss_bytes": 2317373440, + "epoch": 1791087141.3624246 + }, + "after": { + "pid": 3971124, + "create_time": 1791086892.75, + "port": 7777, + "server_rss_bytes": 2317524992, + "epoch": 1791087146.3808043 + }, + "after_controller_release": { + "pid": 3971124, + "create_time": 1791086892.75, + "port": 7777, + "server_rss_bytes": 2317524992, + "epoch": 1791087208.0946314 + }, + "retained_record_counts": { + "W001": 44 + }, + "peak_aggregate_mb_so_far": 4002.01171875, + "observation_export_bytes": 15477082, + "science": [ + { + "native_repeat": 0, + "measurement_differences": 0, + "image_differences": 0, + "tables": [ + 7, + 7 + ], + "physical_images": [ + 2, + 2 + ], + "logical_images": [ + 2, + 2 + ], + "known_relationship_keys": [ + 5, + 5 + ] + }, + { + "native_repeat": 1, + "measurement_differences": 0, + "image_differences": 0, + "tables": [ + 7, + 7 + ], + "physical_images": [ + 2, + 2 + ], + "logical_images": [ + 2, + 2 + ], + "known_relationship_keys": [ + 5, + 5 + ] + } + ] + }, + { + "index": 11, + "case": "cp_tutorial_3d_monolayer", + "before": { + "pid": 3971124, + "create_time": 1791086892.75, + "port": 7777, + "server_rss_bytes": 2317524992, + "epoch": 1791087208.109406 + }, + "after": { + "pid": 3971124, + "create_time": 1791086892.75, + "port": 7777, + "server_rss_bytes": 2317541376, + "epoch": 1791087214.6807764 + }, + "after_controller_release": { + "pid": 3971124, + "create_time": 1791086892.75, + "port": 7777, + "server_rss_bytes": 2317541376, + "epoch": 1791087215.5368412 + }, + "retained_record_counts": { + "W001": 41 + }, + "peak_aggregate_mb_so_far": 4002.01171875, + "observation_export_bytes": 26229453, + "science": [ + { + "native_repeat": 0, + "measurement_differences": 0, + "image_differences": 0, + "tables": [ + 7, + 6 + ], + "physical_images": [ + 2, + 2 + ], + "logical_images": [ + 2, + 2 + ], + "known_relationship_keys": [ + 3, + 3 + ] + }, + { + "native_repeat": 1, + "measurement_differences": 0, + "image_differences": 0, + "tables": [ + 7, + 6 + ], + "physical_images": [ + 2, + 2 + ], + "logical_images": [ + 2, + 2 + ], + "known_relationship_keys": [ + 3, + 3 + ] + } + ] + }, + { + "index": 12, + "case": "cp_tutorial_3d_monolayer", + "before": { + "pid": 3971124, + "create_time": 1791086892.75, + "port": 7777, + "server_rss_bytes": 2317541376, + "epoch": 1791087215.5515075 + }, + "after": { + "pid": 3971124, + "create_time": 1791086892.75, + "port": 7777, + "server_rss_bytes": 2220969984, + "epoch": 1791087222.278022 + }, + "after_controller_release": { + "pid": 3971124, + "create_time": 1791086892.75, + "port": 7777, + "server_rss_bytes": 2220666880, + "epoch": 1791087223.472522 + }, + "retained_record_counts": { + "W001": 41 + }, + "peak_aggregate_mb_so_far": 4002.01171875, + "observation_export_bytes": 26229454, + "science": [ + { + "native_repeat": 0, + "measurement_differences": 0, + "image_differences": 0, + "tables": [ + 7, + 6 + ], + "physical_images": [ + 2, + 2 + ], + "logical_images": [ + 2, + 2 + ], + "known_relationship_keys": [ + 3, + 3 + ] + }, + { + "native_repeat": 1, + "measurement_differences": 0, + "image_differences": 0, + "tables": [ + 7, + 6 + ], + "physical_images": [ + 2, + 2 + ], + "logical_images": [ + 2, + 2 + ], + "known_relationship_keys": [ + 3, + 3 + ] + } + ] + }, + { + "index": 13, + "case": "ExampleSpeckles", + "before": { + "pid": 3971124, + "create_time": 1791086892.75, + "port": 7777, + "server_rss_bytes": 2220666880, + "epoch": 1791087223.4863892 + }, + "after": { + "pid": 3971124, + "create_time": 1791086892.75, + "port": 7777, + "server_rss_bytes": 2220761088, + "epoch": 1791087225.049398 + }, + "after_controller_release": { + "pid": 3971124, + "create_time": 1791086892.75, + "port": 7777, + "server_rss_bytes": 2220761088, + "epoch": 1791087225.8335369 + }, + "retained_record_counts": { + "W001": 26 + }, + "peak_aggregate_mb_so_far": 4002.01171875, + "observation_export_bytes": 12407781, + "science": [ + { + "native_repeat": 0, + "measurement_differences": 0, + "image_differences": 0, + "tables": [ + 3, + 3 + ], + "physical_images": [ + 0, + 0 + ], + "logical_images": [ + 0, + 0 + ], + "known_relationship_keys": [ + 1, + 1 + ] + }, + { + "native_repeat": 1, + "measurement_differences": 0, + "image_differences": 0, + "tables": [ + 3, + 3 + ], + "physical_images": [ + 0, + 0 + ], + "logical_images": [ + 0, + 0 + ], + "known_relationship_keys": [ + 1, + 1 + ] + } + ] + }, + { + "index": 14, + "case": "cp_tutorial_beginner_segmentation_final", + "before": { + "pid": 3971124, + "create_time": 1791086892.75, + "port": 7777, + "server_rss_bytes": 2220761088, + "epoch": 1791087225.847525 + }, + "after": { + "pid": 3971124, + "create_time": 1791086892.75, + "port": 7777, + "server_rss_bytes": 2234343424, + "epoch": 1791087230.8540587 + }, + "after_controller_release": { + "pid": 3971124, + "create_time": 1791086892.75, + "port": 7777, + "server_rss_bytes": 2234343424, + "epoch": 1791087293.734815 + }, + "retained_record_counts": { + "W001": 44 + }, + "peak_aggregate_mb_so_far": 4002.01171875, + "observation_export_bytes": 15477084, + "science": [ + { + "native_repeat": 0, + "measurement_differences": 0, + "image_differences": 0, + "tables": [ + 7, + 7 + ], + "physical_images": [ + 2, + 2 + ], + "logical_images": [ + 2, + 2 + ], + "known_relationship_keys": [ + 5, + 5 + ] + }, + { + "native_repeat": 1, + "measurement_differences": 0, + "image_differences": 0, + "tables": [ + 7, + 7 + ], + "physical_images": [ + 2, + 2 + ], + "logical_images": [ + 2, + 2 + ], + "known_relationship_keys": [ + 5, + 5 + ] + } + ] + }, + { + "index": 15, + "case": "cp_tutorial_3d_monolayer", + "before": { + "pid": 3971124, + "create_time": 1791086892.75, + "port": 7777, + "server_rss_bytes": 2234343424, + "epoch": 1791087293.7494626 + }, + "after": { + "pid": 3971124, + "create_time": 1791086892.75, + "port": 7777, + "server_rss_bytes": 2235514880, + "epoch": 1791087300.9916 + }, + "after_controller_release": { + "pid": 3971124, + "create_time": 1791086892.75, + "port": 7777, + "server_rss_bytes": 2235514880, + "epoch": 1791087301.9009016 + }, + "retained_record_counts": { + "W001": 41 + }, + "peak_aggregate_mb_so_far": 4002.01171875, + "observation_export_bytes": 26229457, + "science": [ + { + "native_repeat": 0, + "measurement_differences": 0, + "image_differences": 0, + "tables": [ + 7, + 6 + ], + "physical_images": [ + 2, + 2 + ], + "logical_images": [ + 2, + 2 + ], + "known_relationship_keys": [ + 3, + 3 + ] + }, + { + "native_repeat": 1, + "measurement_differences": 0, + "image_differences": 0, + "tables": [ + 7, + 6 + ], + "physical_images": [ + 2, + 2 + ], + "logical_images": [ + 2, + 2 + ], + "known_relationship_keys": [ + 3, + 3 + ] + } + ] + } + ], + "source_law_not_live_inspection": [ + "ZMQCompilationRequest.reuse_artifact pops ordinary compilation artifact; actual public inspection unavailable for all16 consumed IDs.", + "InMemoryExecutionLifecycleEngine retains terminal records; existing wire STATUS omits ExecutionRecord.metadata so no live extra/record-store byte accounting is claimed.", + "ExecutionServer.run_execution finally pops orchestrator extra; worker finally releases image cache and clears RuntimeValueStore. These are source laws, not direct live reference observations.", + "CompiledPlateExecutionExtras records parent diagnostics/plate observation; those retained extras are preserved, not globally cleared." + ], + "closure_recommendation": "Controlled acceptance clause of #433 satisfied: actual #582 retaining-owner mutation/release repair plus finite same-READY VALUES plateau and full strict science. Sole historical allocation cause and infinite/full30 memory safety remain unproved; full catalog/scaling acceptance remains PR394 work." +} diff --git a/docs/refactor/receipts/measurement-column-batches-20261004/README.rst b/docs/refactor/receipts/measurement-column-batches-20261004/README.rst new file mode 100644 index 0000000000..756bb941eb --- /dev/null +++ b/docs/refactor/receipts/measurement-column-batches-20261004/README.rst @@ -0,0 +1,41 @@ +Physical measurement batches across preview, query, and export +============================================================ + +The existing ConcatenatedColumnarRows owner carries the actual correlated row +batches. Preview, feature admission, and CSV accumulation previously expanded +those batches into writable rectangular union columns, including absent feature +domains. The new declared read operations use physical batches; an explicitly +read whole column remains the authoritative writable snapshot. + +ColumnarRows owns bounded prefixes and physical segments. The existing Schema, +MeasurementScalarLiteral, RuntimeMeasurementDialect, and row accumulator own +admission, classification, naming, and accumulation. RelateObjects, spreadsheet +export, CPA export, and intensity-distribution naming use those owners directly. +MeasurementTableObjectFeatureSemantics and ObjectMeasurementTableIndex are +removed, together with their detached qualifier/projector callbacks. Arbitrary +public qualification/projector callbacks retain their original complete-column +admission and callback order. + +Preview is now a bounded live read, not an implicit whole-table snapshot barrier. +Later leaf mutations are visible unless a caller explicitly admitted the whole +column. Schema membership no longer invokes lazy column getters. Meaningful +controls cover this distinction, cached-padding writes, opaque qualifier label +mutation, and authored scalar conversions before label resolution. + +One final saved Beginner VALUES replay (not a pipeline latency benchmark) used +original physical row owners and source/label correlations. It preserved all +448 feature/axis indexes and 188,212 label values, recomputed 30,105 upstream +parent-mean cells exactly, and rendered seven CSV files byte-for-byte. The 270 +producer-local distance means are retained unchanged in that rendered bundle; +they were not recomputed by the upstream query replay. + +Final replay: preview 0.01013 -> 0.00816 s, query 0.41223 -> 0.39500 s, +export 0.67671 -> 0.45113 s; combined 0.24478 s reduction. The earlier 0.52496 s +result was invalidated by the necessary authored scalar/label epoch repair. +The strongest demonstrated improvement is export. No end-to-end patch gain, +new native timing, or original #496 full-graph/cap acceptance is claimed. + +The original retained source is the qualified #433 job 02 VALUES observation: +/home/ts/.local/state/openhcs-maintenance/20261004/issue433-controlled-values-a6-qualified-v2/jobs/02-cp_tutorial_beginner_segmentation_final/evidence/runtime_values.pkl.gz. +The replay helper uses the existing observation, schema, image-set numbering, +accumulator, and CSV owners; source readiness is outside its clocks. diff --git a/docs/refactor/receipts/measurement-column-batches-20261004/qualification.json b/docs/refactor/receipts/measurement-column-batches-20261004/qualification.json new file mode 100644 index 0000000000..d144fa153c --- /dev/null +++ b/docs/refactor/receipts/measurement-column-batches-20261004/qualification.json @@ -0,0 +1,32 @@ +{ + "scope": "one production implementation replay on original retained Beginner VALUES leaf owners; registry/sourcealias readiness excluded, no pipeline/native run or accepted latency", + "base_head": "9ae6f7d31fb9c44b9bb2e3ba8ad31c2d372446e6", + "preview_old_s": 0.010128967463970184, + "preview_new_s": 0.008156565949320793, + "query_old_s": 0.4122339151799679, + "query_new_s": 0.39500196371227503, + "export_old_s": 0.6767069287598133, + "export_new_s": 0.45112940296530724, + "coupled_replay_delta_s": 0.24478187877684832, + "indexes": 448, + "values": 188212, + "exact_indexes": true, + "exact_recomputed_upstream_mean_cells": 30105, + "untouched_retained_distance_mean_cells_in_exact_rendered_bundle": 270, + "exact_saved_files": 7, + "exact_csv_bytes": true, + "limits": [ + "Single replay, no causal full-pipeline speedup claim", + "Preview now bounded live read rather than accidental whole-column freeze", + "Explicit whole-column snapshots/writes remain authority", + "Public arbitrary qualifiers/projectors keep original callback admission", + "Original496 full graph/cap/preexport acceptance not claimed" + ], + "source_diff_sha256": "504d9b166f7f4a3dbe2937334dcc8ad07c7f3113bfd6cdbe0706feb12b354a24", + "semantic_controls": { + "original_joined_controls_passed": 116, + "consumer_projection_controls_passed": 7, + "final_opaque_and_authored_scalar_epoch_controls_passed": 4, + "failing_control_before_repair": "str-subclass __float__ was lost during inferred Unicode snapshot conversion" + } +} diff --git a/docs/refactor/receipts/measurement-column-batches-20261004/replay_saved_values.py b/docs/refactor/receipts/measurement-column-batches-20261004/replay_saved_values.py new file mode 100644 index 0000000000..32ed26a513 --- /dev/null +++ b/docs/refactor/receipts/measurement-column-batches-20261004/replay_saved_values.py @@ -0,0 +1,80 @@ +from pathlib import Path +import copy,dataclasses,inspect,json,subprocess,sys,textwrap,time,csv +import numpy as np +sys.path.insert(0,'/var/tmp/openhcs-cp-compiled-contract-reuse-20261004') +BASE=Path('/home/ts/.local/state/openhcs-maintenance/20261004/measurement-query-owner-pricing') +prelude=(BASE/'price_actual_values.py').read_text().split('original=ColumnarMeasurementTableSchema.feature_value_indexes')[0] +prelude=prelude.replace('ColumnarMeasurementTableSchema,MeasurementTableObjectFeatureSemantics,','ColumnarMeasurementTableSchema,').replace('MeasurementTableObjectFeatureSemantics.from_table(table)','ColumnarMeasurementTableSchema.from_table(table)').replace('semantics.object_names','semantics.object_names(table)').replace('semantics.feature_names','semantics.feature_names(table)') +exec(compile(prelude,str(BASE/'price_actual_values.py'), 'exec')) +from openhcs.core.measurement_row_materialization import ConcatenatedColumnarRows,WideMeasurementRowAccumulator +from openhcs.core.runtime_stores import RuntimeArtifactBatch +from openhcs.core.artifacts import MeasurementsArtifactType,RelationshipsArtifactType +from openhcs.core.progress.live_measurements import _columnar_row_preview +from openhcs.processing.backends.cellprofiler.spreadsheet_export import render_spreadsheet_bundle + +def old_method(path,start,end,current): + source=subprocess.check_output(['git','show','9ae6f7d31fb9c44b9bb2e3ba8ad31c2d372446e6:'+path],text=True) + source=source[source.index(start):source.index(end,source.index(start))] + ns=dict(current.__globals__) + exec(compile('from __future__ import annotations\n'+textwrap.dedent(source),'','exec'),ns) + return ns[current.__name__] +old_query=old_method('openhcs/core/measurement_feature_queries.py',' def feature_value_indexes(',' def matching_feature_column(',ColumnarMeasurementTableSchema.feature_value_indexes) +old_preview=old_method('openhcs/core/progress/live_measurements.py','def _columnar_row_preview(','def _mapping_columns_to_row_preview(',_columnar_row_preview) +old_add=old_method('openhcs/core/measurement_row_materialization.py',' def add(\n',' def _add_object_scoped_long_form(',WideMeasurementRowAccumulator.add) +def birth(rows): + return ConcatenatedColumnarRows(tuple(birth(r) for r in rows.row_batches)) if isinstance(rows,ConcatenatedColumnarRows) else rows + +def query(production): + output={a:{f:MeasurementFeatureValueIndex(dict(i.values_by_label),list(i.positional_values)) for f,i in fs.items()} for a,fs in cores.items()} + preview_s=query_s=0 + for table,queries,masks,aligned in admissions: + current=copy.copy(table);current.rows=birth(table.rows) + start=time.perf_counter();preview=(_columnar_row_preview if production else old_preview)(current.rows,50,64);preview_s+=time.perf_counter()-start + start=time.perf_counter();schema=ColumnarMeasurementTableSchema.from_table(current) + options=dict(index_type=MeasurementFeatureValueIndex,row_masks=masks) + if production:method=ColumnarMeasurementTableSchema.non_absent_feature_value_indexes + else: + method=old_query;options['measurement_value_qualifier']=lambda value:not MeasurementScalarLiteral(value).is_absent + for feature,axes in method(schema,current,queries,{f:{'Nucleoli':q.query_object_name} for f,q in queries.items()},**options): + for axis,objects in axes.items(): + index=objects.get('Nucleoli') + if index is not None:output.setdefault(aligned[axis],{}).setdefault(feature,MeasurementFeatureValueIndex()).values_by_label.update(index.values_by_label) + query_s+=time.perf_counter()-start + return output,preview_s,query_s +from openhcs.core.runtime_measurements import MeasurementScalarLiteral +baseline,old_preview_s,old_query_s=query(False) +production,new_preview_s,new_query_s=query(True) +for a,fs in baseline.items(): + assert fs.keys()==production[a].keys() + for f,index in fs.items(): + other=production[a][f];assert index.values_by_label.keys()==other.values_by_label.keys() + np.testing.assert_array_equal(list(index.values_by_label.values()),list(other.values_by_label.values())) +parent=ArtifactSpec.input('Nuclei',ObjectLabelsArtifactType);child=ArtifactSpec.input('Nucleoli',ObjectLabelsArtifactType) +class SavedRows(RelateObjectsRelationshipMeasurementRows): + def upstream_child_feature_indexes(self,spec): + assert spec==child;return production +means=SavedRows(None).parent_mean_upstream_measurement_rows(parent_spec=parent,child_spec=child,payload=relationship) +mean_maps={(r['slice_index'],r['object_label']):r for r in means.iter_row_mappings()} +with (JOB/'source_workspace_controlled_values/results/MyExpt_Nuclei.csv').open() as stream:expected=list(csv.DictReader(stream)) +compared=0;producer_local=0 +for row in expected: + key=int(row['image_number'])-1,int(row['object_label']) + for field,value in row.items(): + if not field.startswith('Mean_Nucleoli_'):continue + if field.startswith('Mean_Nucleoli_Distance_'): + producer_local+=1;continue + if value=='':assert field not in mean_maps.get(key,{}) + else: + actual=mean_maps[key][field];assert actual==float(value) or np.isnan(actual) and np.isnan(float(value)) + compared+=1 +specs=tuple(ArtifactSpec.input(n,t) for n,t in dict.fromkeys((r.key.name,r.key.artifact_type) for r in records if r.key.artifact_type in (MeasurementsArtifactType,RelationshipsArtifactType))) +actual=RuntimeArtifactBatch(specs,obs.records_by_axis,obs.source_image_set_identity_policy) +golden=next(r.data for r in records if r.key.name=='ExportToSpreadsheet_13_files') +new_add=WideMeasurementRowAccumulator.add_declared_rows +WideMeasurementRowAccumulator.add_declared_rows=lambda self,rows,dialect,**kw:old_add(self,rows,dialect.projected_feature_name,**kw) +start=time.perf_counter();old_bundle=render_spreadsheet_bundle(actual);old_export_s=time.perf_counter()-start +assert old_bundle==golden +WideMeasurementRowAccumulator.add_declared_rows=new_add +start=time.perf_counter();new_bundle=render_spreadsheet_bundle(actual);new_export_s=time.perf_counter()-start +assert new_bundle==golden +print(json.dumps({'scope':'one production implementation replay on original retained Beginner VALUES leaf owners; registry/sourcealias readiness excluded, no pipeline/native run or accepted latency','base_head':subprocess.check_output(['git','rev-parse','HEAD'],text=True).strip(),'preview_old_s':old_preview_s,'preview_new_s':new_preview_s,'query_old_s':old_query_s,'query_new_s':new_query_s,'export_old_s':old_export_s,'export_new_s':new_export_s,'coupled_replay_delta_s':old_preview_s+old_query_s+old_export_s-new_preview_s-new_query_s-new_export_s,'indexes':sum(len(fs) for fs in production.values()),'values':sum(len(i.values_by_label) for fs in production.values() for i in fs.values()),'exact_indexes':True,'exact_recomputed_upstream_mean_cells':compared,'untouched_retained_distance_mean_cells_in_exact_rendered_bundle':producer_local,'exact_saved_files':len(new_bundle),'exact_csv_bytes':True,'limits':['Single replay, no causal full-pipeline speedup claim','Preview now bounded live read rather than accidental whole-column freeze','Explicit whole-column snapshots/writes remain authority','Public arbitrary qualifiers/projectors keep original callback admission','Original496 full graph/cap/preexport acceptance not claimed']},indent=2)) diff --git a/docs/refactor/receipts/measurement-query-callback-496-20261004.rst b/docs/refactor/receipts/measurement-query-callback-496-20261004.rst new file mode 100644 index 0000000000..92febae021 --- /dev/null +++ b/docs/refactor/receipts/measurement-query-callback-496-20261004.rst @@ -0,0 +1,42 @@ +Measurement query callback boundary (#496) +========================================== + +The shared feature projection read the object ID field and label column before +running arbitrary value qualifiers. The previous scalar implementation read +them after qualification. A qualifier which changes the table subject or +replaces the label column therefore returned stale object identities. + +The existing ``ColumnarMeasurementTableSchema.feature_value_indexes`` now reads +object identity after qualification. Arbitrary qualifiers run independently for +each query, including repeated queries of the same physical column. Their +admitted values and resolved labels are not reused across callback boundaries. +Default scalar qualification still shares physical-column admission. No new +owner, registry or process cache is introduced. + +The regression fails on the previous source for both scalar and batched paths. +It changes ``subject.id_field`` and replaces the label column during the +callback, requires masked-out nonstructural values to be visited, excludes +structural missing cells, and checks both callback order and result identities. +The affected runtime-query and measurement-lookup suites pass: 53 controls. +This is correctness evidence, not a performance claim. + +The earlier saved-CSV indexing-only improvement of approximately 21 percent +is withdrawn as warm runtime performance evidence. Its timing included registry +discovery, and CSVs do not preserve the original runtime argument graph required +by #496. The exact saved-output comparison remains valid within its stated scope. + +The separate, warm-prepared replay of actual retained #433 VALUES measures +qualification/index construction at 0.338779 seconds versus a numeric prototype +at 0.321176 seconds, and parent means at 0.158795 versus 0.095242 seconds. +Its 81-millisecond combined saving is insufficient for the dominant target and +the prototype is not promoted. It preserves 448 indexes, 188,212 values and +30,105 upstream means exactly. Another 270 exported mean cells are produced +locally by RelateObjects distance computation and are not upstream query inputs. +Original evidence is retained at:: + + /home/ts/.local/state/openhcs-maintenance/20261004/measurement-query-owner-pricing/actual-values-pricing.json + +The original #496 preexport graph/query-roster, bounded admission and coupled +query/export obligations remain open. The qualified v12 end-to-end campaign +remains independent evidence; neither this callback fix nor this rejected +prototype has an attributed end-to-end gain. diff --git a/docs/refactor/receipts/public-native-receiving-134-20261004/README.rst b/docs/refactor/receipts/public-native-receiving-134-20261004/README.rst new file mode 100644 index 0000000000..dff5fc2f48 --- /dev/null +++ b/docs/refactor/receipts/public-native-receiving-134-20261004/README.rst @@ -0,0 +1,92 @@ +Public native receiving: #134 +============================ + +The positive synthetic receiving journey passed on 2026-10-04. This packet +records the actual public MCP responses and render-complete native captures; +it is not a biological pipeline or native CellProfiler benchmark. + +``receipt.json`` is the final 24-call public journey, SHA256 +``85de19eb38eb507d0e181ca082d5611b99a4c64d1bfc08c56779fb82fa698191``. +The initial calibrated label mount and confirmed close are retained separately +as ``journey-live8.json`` inside ``retained-evidence.tar.gz``. Its exact native +state is ``label-source-receipt.json``; the final journey verifies and consumes +those original bytes instead of rerunning initial processing. + +Actual coverage +--------------- + +* Two authored 32x32 raw TIFFs and one two-plane 32x32 grayscale label TIFF. + Label source-plane order is channel (2, 1); the native viewer's shared channel + domain is (1, 2). Both label planes and both raw arrays were compared completely + through their actual projected native records: 4,096 pixels in total. +* Native metadata and receipt admission retain micrometer XY spacing + (1.3556, 1.3556). Fresh public ``kind=result`` reopening uses the exact physical + source receipt, followed by independent raw streaming into the same viewer. +* An authored ``SpatialGraph`` is contextualized and materialized through the + production output-context and graph ROI writers. Public result inventory and + streaming accept its absolute result directory **inside** its output plate. + Its two native paths retain source channel 2, exact YX coordinates, neuron + field 7, directed endpoint identifiers, and branch-distance field 8.5. +* Raw, result (labels plus graph), and combined captures use the same camera, + semantic channel 2, 2-D Y/X display and 643x478 canvas. All three captures meet + the existing 5-second operation / 2.5-second render-observation bounds. The + result and combined images were visually inspected for visible aligned data. + +Capture hashes, paths and renderer completion evidence are in the receipt; +all three PNGs are included under ``captures-live12`` in the archive. Their +SHA256 values are: + +* raw: ``f9050beeffc54c925aaca4cf4188ecf1c51b42c4fa49f2b08c5f880d47ce59d2`` +* result: ``440488c036ff602991ecd5a4124a47241b8093dcf7a5a2c157233076978a410b`` +* combined: ``a0b0492b919e4ecbc1c9eca2bff5f9fc0580a8d38365499ffddb9ea127ecec84`` + +Ownership and source +-------------------- + +The source is ``044b2269e``, functionally equivalent to root ``a6c0e1e03``: +an experimentally relaxed scalar admission was committed as ``1548c33d1`` +and reverted after fixture counterevidence invalidated its premise. **No new +production fix is claimed by this packet.** Existing main #550 / #576 source +and calibration behavior is exercised with the original strict guards. + +The actual command was:: + + /home/ts/code/projects/openhcs/.venv/bin/python -B \ + /var/tmp/run_public_receiving_134_20261004.py + +The frozen ``controller.py`` is the executed audit source, SHA256 +``ddcbf82ddec594e2205489c9b6e68c263cd147afa95b92cf1916d4bd8cb41158``. +It refuses overwriting its evidence namespace; it is not a portable fresh-fixture +recipe. The exact tiny persisted fixtures and public call arguments are retained. + +The controller owns CPU 3, TCP 6609/7609, private X display :119 and a user cgroup +with MemoryMax=1800M, MemorySwapMax=0 and TasksMax=256. It used a privately +extracted Arch Xvfb 21.1.22-2 binary, without system installation or the foreign +:0 desktop. No execution server, pipeline processing or native CP run was started. +Installed dependency versions, including python-introspect 0.1.16, remained +unchanged during the accepted phase. The viewer close was acknowledged and +process exit verified; the MCP child and private X server both returned 0. + +Failure preservation and limits +------------------------------- + +The archive retains earlier failed JSON receipts, launcher logs, controllers and +native error logs byte-for-byte. Errors included wrong fixture handler keys, +incorrect scalar-axis declarations, result-kind/SDK argument mistakes, and +checkers confusing projected planes with whole TIFFs or route-local indices with +global indices. Mutable synthetic fixture metadata was corrected in place; this +packet does **not** claim immutable snapshots of every earlier malformed fixture. +The initially proposed guard change was reverted rather than promoted. + +The graph is an authored transport fixture, not a biological segmentation or +proof of a production object's membership. Native graph summaries retain source +identity and calibration but report no per-ROI source origin/shape. Therefore a +reported zero out-of-source-bounds count is **not** evidence of native bounds +validation. The exact coordinates and actual 32x32 source pixels are independently +observed. Existing main #550/#576 negative metadata controls remain distinct: +this journey did not run fresh missing/conflicting-archive negative streams. +It does not qualify arbitrary external result roots, #522 well remounts, the +original #404 biological pipeline, or full-catalog/scaling performance. + +The archive SHA256 is +``0353ab95c5e3a46a509e79d7f94fb4813ebebded62ca84b8ec1794fa3d72cb1b``. diff --git a/docs/refactor/receipts/public-native-receiving-134-20261004/controller.py b/docs/refactor/receipts/public-native-receiving-134-20261004/controller.py new file mode 100644 index 0000000000..cc569cce12 --- /dev/null +++ b/docs/refactor/receipts/public-native-receiving-134-20261004/controller.py @@ -0,0 +1,220 @@ +"""One bounded synthetic receiving journey through actual metadata/writer and public MCP.""" +from __future__ import annotations +from dataclasses import replace +import asyncio, hashlib, json, os, secrets, socket, subprocess, sys, time, traceback +from pathlib import Path +SOURCE=Path('/var/tmp/openhcs-resolved-pipeline-owner-20261004') +OUT=Path('/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native') +PYTHON=Path('/home/ts/code/projects/openhcs/.venv/bin/python') +PORT=6609; DISPLAY=':119' +def sha(p): return hashlib.sha256(Path(p).read_bytes()).hexdigest() +def environment(): + e=dict(os.environ) + for k in tuple(e): + if k.startswith('OPENHCS_PROFILE_') or k.startswith('OPENHCS_DIAGNOSTIC_'): del e[k] + e.update(PYTHONPATH=str(SOURCE),PYTHONDONTWRITEBYTECODE='1',OPENHCS_CPU_ONLY='true',OPENHCS_HEADLESS='false',OPENHCS_SUBPROCESS_NO_GPU='1',POLYSTORE_SUBPROCESS_NO_GPU='1',CUDA_VISIBLE_DEVICES='',QT_QPA_PLATFORM='xcb',DISPLAY=DISPLAY,XAUTHORITY=str(OUT/'owned.xauthority'),LIBGL_ALWAYS_SOFTWARE='1',QT_OPENGL='software',OPENHCS_AGENT_READ_ROOTS=os.pathsep.join((str(OUT),str(SOURCE))),OPENHCS_AGENT_WRITE_ROOTS=str(OUT),POLYSTORE_IMAGEJ_ALLOW_DOWNLOAD='false',OPENHCS_UI_CONFIG_CACHE_FILE=str(OUT/'owned/ui-config.config')) + e.pop('WAYLAND_DISPLAY',None) + for key,sub in [('XDG_DATA_HOME','data'),('XDG_CONFIG_HOME','config'),('XDG_CACHE_HOME','cache'),('XDG_STATE_HOME','state'),('XDG_RUNTIME_DIR','runtime'),('MPLCONFIGDIR','matplotlib'),('NUMBA_CACHE_DIR','numba')]: e[key]=str(OUT/'owned'/sub) + for key in ('OMP_NUM_THREADS','OPENBLAS_NUM_THREADS','MKL_NUM_THREADS','NUMEXPR_NUM_THREADS','NUMBA_NUM_THREADS','BLIS_NUM_THREADS','VECLIB_MAXIMUM_THREADS'):e[key]='1' + return e +if '--worker' not in sys.argv: + for sub in ('data','config','cache','state','runtime','matplotlib','numba'): (OUT/'owned'/sub).mkdir(parents=True,exist_ok=True) + (OUT/'owned/runtime').chmod(0o700) + assert not (OUT/'journey-live12.json').exists(), 'Never overwrite a receiving attempt' + with (OUT/'controller-live12.log').open('x') as log: + r=subprocess.run(['/usr/bin/systemd-run','--user','--scope','--quiet','-p','MemoryMax=1800M','-p','MemorySwapMax=0','-p','TasksMax=256','/usr/bin/env',*[f'{k}={v}' for k,v in environment().items()],'/usr/bin/taskset','-c','3',str(PYTHON),'-B',__file__,'--worker'],env=dict(os.environ),cwd='/var/tmp',stdout=log,stderr=subprocess.STDOUT,timeout=360) + print(json.dumps({'returncode':r.returncode,'receipt':str(OUT/'journey-live12.json')})); sys.exit(r.returncode) +sys.path.insert(0,str(SOURCE)) +import openhcs +assert Path(openhcs.__file__).resolve()==SOURCE/'openhcs/__init__.py' +import numpy as np, tifffile +import importlib.metadata as package_metadata +receipt_dependencies={name:package_metadata.version(name) for name in ('python-introspect','polystore','zmqruntime','napari','numpy','PyQt6')} +from polystore.disk import DiskStorageBackend +from polystore.filemanager import FileManager +from polystore.virtual_workspace import SourcePixelRef +from polystore.roi import load_rois_from_zip +from openhcs.constants import AllComponents +from openhcs.core.plate_file_inventory import PlateFileKind +from openhcs.core.artifacts import ArtifactOutputPlan,ArtifactSpec,ObjectLabelsArtifactType,SpatialGraphArtifactType,ObjectArtifactMemberSubjectRelation +from openhcs.core.source_projection import OpenHCSPlaneAddress,SourcePlaneProjection,SourceProjectionMetadataSerializer +from openhcs.core.virtual_workspace_metadata import AtomicMetadataWriter,VirtualWorkspaceSourceProjectionEntries,METADATA_CONFIG +from openhcs.microscopes.imagexpress import ImageXpressFilenameParser,ImageXpressHandler +from openhcs.core.runtime_image_values import ImagePayloadMetadata +from openhcs.core.runtime_plane_projection import RuntimePlaneAxis +from openhcs.core.source_image_provenance import SourceImageProvenancePlanes +from openhcs.core.source_spatial_domain import SourceSpatialDomain +from openhcs.core.source_metadata import SourceVoxelSpacing +from openhcs.core.runtime_spatial_graph import SpatialGraph,SpatialGraphNode,SpatialGraphEdge +from openhcs.core.steps.function_runtime import FunctionOutputContextStrategy +from openhcs.processing.materialization import MaterializationSpec,SpatialGraphROIOptions,materialize +from openhcs.core.roi_source_metadata import ROIArchiveSourceMetadata +from openhcs.agent.dto.execution import ExecutionConnectionSpec +from openhcs.agent.dto.plate import PlateFileStreamRequest +from openhcs.agent.dto.common import AgentResourceRef +from openhcs.agent.dto.viewer import ViewerWindowStateRequest,ViewerWindowSnapshotRequest,ViewerWindowCloseRequest,ViewerWindowLayerIsolationRequest,ViewerWindowImageSampleRequest,ViewerWindowRoiSummaryRequest,ViewerWindowPayloadRequest,ViewerWindowViewportRequest +from openhcs.mcp.dev_client_core import McpDevServerSpec,McpDevStdioSession,McpDevToolResult +from openhcs.serialization.json import to_jsonable +from zmqruntime.config import TransportMode +from zmqruntime.transport import TransportEndpoint +from openhcs.runtime.zmq_config import OPENHCS_ZMQ_CONFIG +conn=ExecutionConnectionSpec(host='127.0.0.1',port=PORT,transport_mode=TransportMode.TCP,persistent=True) +receipt={'accepted':False,'scope':'Synthetic native receiving only; no biological processing or native CP rerun','source_head':subprocess.check_output(['git','-C',str(SOURCE),'rev-parse','HEAD'],text=True).strip(),'source':str(SOURCE),'controller_sha256':sha(__file__),'calls':[],'failure':None,'children':[],'installed_dependencies':receipt_dependencies} +def save(): (OUT/'journey-live12.json').write_text(json.dumps(receipt,indent=2)+'\n') +def prepare_fixture(): + raw=OUT/'raw_plate'; labels=OUT/'labels_plate' + if raw.exists(): + for root in (raw,labels): + doc=json.loads(METADATA_CONFIG.metadata_path(root).read_text()) + (OUT/(root.name+'-metadata-invalid-axis.json')).write_text(json.dumps(doc,indent=2)+'\n') + doc=json.loads(METADATA_CONFIG.metadata_path(raw).read_text()) + owner=VirtualWorkspaceSourceProjectionEntries.from_subdirectory(doc['subdirectories']['images']) + scalar=VirtualWorkspaceSourceProjectionEntries({path:replace(projection,image_metadata=replace(projection.image_metadata,plane_axis=None)) for path,projection in owner.entries.items()}) + AtomicMetadataWriter().merge_source_projection_metadata(METADATA_CONFIG.metadata_path(raw),'images',scalar) + paths=tuple(raw/'images'/f'A01_s001_w{ch}_z001_t001.tif' for ch in (2,1)) + components=tuple(dict(scalar.entries[str(path)].source_metadata) for path in paths) + spacing=SourceVoxelSpacing((1.3556,1.3556)) + metadata=ImagePayloadMetadata(plane_axis=RuntimePlaneAxis.RUNTIME_SLICE,source_image_provenance_planes=SourceImageProvenancePlanes.from_components(paths=tuple(map(str,paths)),component_metadata=components),source_image_names=('raw_2','raw_1'),source_spatial_domain=SourceSpatialDomain((0,0),(32,32)),source_voxel_spacing=spacing) + target=labels/'stacked_labels'/'A01_s001_w2_z001_t001_Labels.tif';target.parent.mkdir(exist_ok=True) + pixels=np.stack([tifffile.imread(labels/'images'/path.name) for path in paths]) + if target.exists():np.testing.assert_array_equal(tifffile.imread(target),pixels) + else:tifffile.imwrite(target,pixels,photometric='minisblack',metadata={'axes':'ZYX'}) + projection=SourcePlaneProjection(address=OpenHCSPlaneAddress.from_values('A01',1,2,1,1),ref=SourcePixelRef('disk',str(target)),source_metadata=components[0],image_metadata=metadata) + AtomicMetadataWriter().merge_subdirectory_metadata(METADATA_CONFIG.metadata_path(labels),{'images':{'main':False}}) + AtomicMetadataWriter().publish_source_projection_metadata(METADATA_CONFIG.metadata_path(labels),'stacked_labels',VirtualWorkspaceSourceProjectionEntries.from_projection_paths(((projection,str(target)),)),serializer=SourceProjectionMetadataSerializer(ImageXpressFilenameParser()),saved_image_paths=(str(target),),microscope_handler_name=ImageXpressHandler._microscope_type,source_filename_parser_name='ImageXpressFilenameParser',component_labels={},backend='disk',is_main=True,results_dir=str(labels/'graph_results')) + graph=labels/'graph_results'/'A01_s001_w2_z001_t001_graph.graph.roi.zip' + restored=load_rois_from_zip(graph); graph_metadata=ROIArchiveSourceMetadata.decode(restored) + assert graph_metadata.source_voxel_spacing==spacing + expected={str(path):tifffile.imread(path).tolist() for path in (*paths,target)} + receipt['fixture']={'raw':str(raw),'labels':str(labels),'label_paths':[str(target)],'graph':str(graph),'metadata':to_jsonable(graph_metadata),'label_metadata':to_jsonable(metadata),'roi_features':[to_jsonable(r.metadata) for r in restored],'files':{str(p):sha(p) for root in (raw,labels) for p in root.rglob('*') if p.is_file()},'expected_pixels':expected,'retained_failed_receipts':[str(OUT/f'journey-{name}.json') for name in ('live','live2','live3','live4','live5')]};save() + assert pixels.shape==(2,32,32) and metadata.source_image_provenance_planes.count==2 + return raw,labels,graph + + for root in (raw,labels):(root/'images').mkdir(parents=True) + spacing=SourceVoxelSpacing((1.3556,1.3556)); domain=SourceSpatialDomain((0,0),(32,32)); rows=[] + for ch in (2,1): + path=raw/'images'/f'A01_s001_w{ch}_z001_t001.tif'; pixels=(np.arange(1024,dtype=np.uint16).reshape(32,32)+ch*100) + tifffile.imwrite(path,pixels,photometric='minisblack',metadata={'axes':'YX'}); rows.append((ch,path,pixels)) + entries={raw:[],labels:[]}; expected={} + for ch,path,pixels in rows: + components={'well':'A01','site':'1','channel':str(ch),'z_index':'1','timepoint':'1'}; spacing.merge_into(components,path=str(path)) + metadata=ImagePayloadMetadata(plane_axis=RuntimePlaneAxis.RUNTIME_SLICE,source_image_provenance_planes=SourceImageProvenancePlanes.from_components(paths=(str(path),),component_metadata=(components,)),source_image_names=(f'raw_{ch}',),source_spatial_domain=domain,source_voxel_spacing=spacing) + for root in (raw,labels): + target=root/'images'/path.name + if root==labels: + label=np.zeros((32,32),dtype=np.uint16);label[3:12,4:14]=7;label[17:25,20:28]=11 + label*=ch; tifffile.imwrite(target,label,photometric='minisblack',metadata={'axes':'YX'}) + expected[str(target)]=tifffile.imread(target).tolist() + entries[root].append((SourcePlaneProjection(address=OpenHCSPlaneAddress.from_values('A01',1,ch,1,1),ref=SourcePixelRef('disk',str(target)),source_metadata=components,image_metadata=metadata),str(target))) + for root in (raw,labels): + AtomicMetadataWriter().publish_source_projection_metadata(METADATA_CONFIG.metadata_path(root),'images',VirtualWorkspaceSourceProjectionEntries.from_projection_paths(entries[root]),serializer=SourceProjectionMetadataSerializer(ImageXpressFilenameParser()),saved_image_paths=tuple(p for _,p in entries[root]),microscope_handler_name='ImageXpress',source_filename_parser_name='ImageXpressFilenameParser',component_labels={},backend='disk',is_main=True,results_dir=str(labels/'graph_results') if root==labels else None) + nodes=tuple(SpatialGraphNode(i+1,xy) for i,xy in enumerate(((2.25,3.5),(5.25,9.5),(7.25,12.5)))) + edges=tuple(SpatialGraphEdge.from_features(edge_id=i+1,source=nodes[i],target=nodes[i+1],coordinates=np.asarray((nodes[i].coordinates,nodes[i+1].coordinates)),features={'neuron_label':7,'branch_distance_um':8.5}) for i in range(2)) + graph=SpatialGraph(name='declared_graph',nodes=nodes,edges=edges,coordinate_spacing=spacing.values_zyx,source_plane_index=0) + plan=ArtifactOutputPlan(name=graph.name,path=str(labels/'graph.pkl'),artifact_type=SpatialGraphArtifactType,relations=(ObjectArtifactMemberSubjectRelation(source=ArtifactSpec.output('neurons',ObjectLabelsArtifactType).ref(),member_id_field='neuron_label'),),producer_step_index=4,producer_step_scope_id='synthetic-receiving-134') + source_metadata=ImagePayloadMetadata(plane_axis=RuntimePlaneAxis.RUNTIME_SLICE,source_image_provenance_planes=SourceImageProvenancePlanes.from_components(paths=tuple(str(path) for _,path,_ in rows),component_metadata=tuple(dict(p.source_metadata) for p,_ in entries[raw])),source_image_names=('raw_2','raw_1'),source_spatial_domain=domain,source_voxel_spacing=spacing) + graph=FunctionOutputContextStrategy.for_output_plan(plan).contextualize(source_metadata.payload_with(np.stack([pixels for _,_,pixels in rows])),graph,plan,None) + graph_path=labels/'graph_results'/'A01_s001_w2_z001_t001_graph.roi.zip';graph_path.parent.mkdir() + materialize(MaterializationSpec(SpatialGraphROIOptions()),data=graph,path=str(graph_path),filemanager=FileManager({'disk':DiskStorageBackend()}),backends=['disk'],backend_kwargs={},output_plan=plan) + restored=load_rois_from_zip(graph_path); decoded=ROIArchiveSourceMetadata.decode(restored) + assert decoded.source_provenance==source_metadata.source_provenance.for_source_plane(0) + receipt['fixture']={'raw':str(raw),'labels':str(labels),'graph':str(graph_path),'spacing':to_jsonable(spacing),'metadata':to_jsonable(decoded),'roi_features':[to_jsonable(r.metadata) for r in restored],'files':{str(p):sha(p) for root in (raw,labels) for p in root.rglob('*') if p.is_file()},'expected_pixels':expected};save() + return raw,labels,graph_path +async def call(session,name,args,*,allow_error=False): + raw=await session.call_tool(name,args,timeout_seconds=45); decoded=McpDevToolResult.from_payload(name,raw) + payload=to_jsonable(decoded.first_decoded_payload()); receipt['calls'].append({'tool':name,'arguments':args,'response':raw,'payload':payload});save() + if not allow_error:assert not decoded.has_errors(),to_jsonable(decoded.diagnostic_errors()) + return payload +async def journey(): + children=[]; xserver=None; active=False + try: + for displaypath in (Path('/tmp/.X119-lock'),Path('/tmp/.X11-unix/X119')):assert not displaypath.exists(), f'Foreign display reservation {displaypath}' + endpoint=TransportEndpoint('127.0.0.1',PORT,TransportMode.TCP) + ports=sorted(endpoint.port_pair(OPENHCS_ZMQ_CONFIG).ports) + for port in ports: + lock=TransportMode.TCP.declaration.startup_lock_path(port,OPENHCS_ZMQ_CONFIG);assert not lock.exists(),str(lock) + with socket.socket() as sock:assert sock.connect_ex(('127.0.0.1',port))!=0,port + receipt['owned_ports']=ports + raw,labels,graph=prepare_fixture() + auth=OUT/'owned.xauthority';auth.touch(mode=0o600) + subprocess.run(['xauth','-f',str(auth),'add',DISPLAY,'.',secrets.token_hex(16)],check=True,stdout=subprocess.DEVNULL) + with (OUT/'xserver-live12.log').open('x') as xlog: + xserver=subprocess.Popen([str(OUT/'private-xserver/usr/bin/Xvfb'),DISPLAY,'-screen','0','1280x960x24','-nolisten','tcp','-auth',str(auth)],stdout=xlog,stderr=subprocess.STDOUT) + receipt['xserver_pid']=xserver.pid;save() + for _ in range(50): + if Path('/tmp/.X11-unix/X119').exists():break + assert xserver.poll() is None;await asyncio.sleep(.1) + assert Path('/tmp/.X11-unix/X119').exists() + with (OUT/'mcp-live12.log').open('x') as log: + async with McpDevStdioSession(McpDevServerSpec(str(PYTHON)),log) as session: + children.append(session.require_process());await session.initialize(timeout_seconds=90);await session.list_tools(timeout_seconds=90) + health=await call(session,'openhcs_health_check',{});assert Path(health['server_source_path']).resolve()==SOURCE/'openhcs/mcp/server.py' + for plate in (raw,labels): + inventory=await call(session,'openhcs_query_plate_files',{'plate_path':str(plate),'kind':'image','limit':10});assert inventory['total_count']==(2 if plate==raw else 3) and not inventory['warnings'],inventory + label_paths=receipt['fixture']['label_paths'] + prior=json.loads((OUT/'journey-live8.json').read_text()) + assert prior['source_head']==receipt['source_head'] and prior['installed_dependencies']==receipt['installed_dependencies'] + state=next(row['payload'] for row in prior['calls'] if row['tool']=='openhcs_get_viewer_window_state') + receipt_path=OUT/'label-source-receipt.json';assert json.loads(receipt_path.read_text())==state + from openhcs.agent.dto.viewer import ViewerWindowStateResult + typed=ViewerWindowStateResult.from_mapping(state) + for path in label_paths: + record,_=typed.image_payload_binding_for(path);assert record.summary.voxel_spacing==SourceVoxelSpacing((1.3556,1.3556)) + receipt['initial_native_qualification']={'receipt':str(OUT/'journey-live8.json'),'sha256':sha(OUT/'journey-live8.json'),'native_state':str(receipt_path),'state_sha256':sha(receipt_path)};save() + ref=AgentResourceRef(uri=receipt_path.as_uri(),title='Actual calibrated native label state',path=str(receipt_path),size_bytes=receipt_path.stat().st_size,sha256=sha(receipt_path)) + active=True + await call(session,'openhcs_stream_plate_files_to_viewer',PlateFileStreamRequest(plate_path=str(labels),result_directory=str(labels/'stacked_labels'),file_paths=tuple(label_paths),kind=PlateFileKind.RESULT,limit=2,connection=conn,fresh_viewer=True,source_receipt=ref).as_tool_arguments()) + await call(session,'openhcs_stream_plate_files_to_viewer',PlateFileStreamRequest(plate_path=str(raw),limit=2,connection=conn).as_tool_arguments()) + inventory=await call(session,'openhcs_query_plate_files',{'plate_path':str(labels),'result_directory':str(graph.parent),'kind':'result','limit':10}) + await call(session,'openhcs_stream_plate_files_to_viewer',PlateFileStreamRequest(plate_path=str(labels),context_plate_path=str(raw),result_directory=str(graph.parent),file_paths=(str(graph),),kind=PlateFileKind.RESULT,limit=1,connection=conn).as_tool_arguments()) + state=await call(session,'openhcs_get_viewer_window_state',ViewerWindowStateRequest(connection=conn).as_tool_arguments());(OUT/'combined-state.json').write_text(json.dumps(state,indent=2)+'\n') + typed=ViewerWindowStateResult.from_mapping(state) + route_for={summary.path:layer.route_key for layer in typed.layers for summary in layer.payload_summaries} + raw_routes={route_for[path] for path in receipt['fixture']['expected_pixels'] if '/raw_plate/' in path} + label_routes={route_for[path] for path in label_paths}; graph_route=route_for[str(graph)] + assert raw_routes.isdisjoint(label_routes),(raw_routes,label_routes) + seen=set() + payloads=await call(session,'openhcs_get_viewer_window_payloads',ViewerWindowPayloadRequest.from_fields(connection=conn,include_array_values=True,max_array_elements=4096,include_shape_payloads=True,max_shape_payloads=20).as_tool_arguments()) + for layer in payloads['layers']: + for record in layer['payloads']: + if record['data_type']!='image':continue + path=record['path'];assert path in receipt['fixture']['expected_pixels'],record + expected=np.asarray(receipt['fixture']['expected_pixels'][path]) + plane=record['aggregate_axis_indices'][0] if expected.ndim==3 else None + selected=expected[plane] if plane is not None else expected + np.testing.assert_array_equal(np.asarray(record['array_values']).reshape(selected.shape),selected);seen.add((path,plane)) + wanted={(path,plane) for path,values in receipt['fixture']['expected_pixels'].items() for plane in (range(len(values)) if np.asarray(values).ndim==3 else (None,))} + assert seen==wanted,seen + roi=await call(session,'openhcs_summarize_viewer_window_rois',ViewerWindowRoiSummaryRequest(connection=conn,route_key=graph_route,max_examples=10).as_tool_arguments()) + assert roi['observed'] and roi['total_roi_count']==len(receipt['fixture']['roi_features']) and roi['roi_count_exact'],roi + for payload in roi['payloads']: + assert payload['components']['channel'] in ('2',2),payload + assert payload['out_of_source_bounds_count']==0,payload + await call(session,'openhcs_get_viewer_window_payloads',ViewerWindowPayloadRequest.from_fields(connection=conn,route_key=graph_route,include_shape_payloads=True,max_shape_payloads=20).as_tool_arguments()) + captures={}; matched=[]; viewport=typed.native_viewport + for name,routes in [('raw',raw_routes),('result',label_routes|{graph_route}),('combined',raw_routes|label_routes|{graph_route})]: + await call(session,'openhcs_isolate_viewer_window_layers',ViewerWindowLayerIsolationRequest.from_fields(connection=conn,visible_route_keys=sorted(routes),selected_route_key=next(iter(sorted(label_routes if label_routes.issubset(routes) else raw_routes))),axis_indices={'channel':1}).as_tool_arguments()) + await call(session,'openhcs_set_viewer_viewport',ViewerWindowViewportRequest.from_fields(connection=conn,presentation=viewport).as_tool_arguments()) + observed=await call(session,'openhcs_get_viewer_window_state',ViewerWindowStateRequest(connection=conn).as_tool_arguments());matched.append(observed['native_viewport']) + assert {l['route_key'] for l in observed['layers'] if l['visible']}==routes,observed + captures[name]=await call(session,'openhcs_viewer_snapshot_window',ViewerWindowSnapshotRequest.from_fields(connection=conn,output_dir_path=str(OUT/'captures-live12'/name)).as_tool_arguments()) + assert captures[name]['captured'],captures[name] + assert matched[0]==matched[1]==matched[2],matched + receipt['captures']=captures;receipt['complete_native_pixel_paths']=sorted(seen);receipt['accepted']=True + await call(session,'openhcs_close_viewer_window',ViewerWindowCloseRequest(connection=conn,confirmed=True).as_tool_arguments());active=False + except BaseException as error: + receipt['failure']={'type':type(error).__name__,'message':str(error),'traceback':traceback.format_exc()};save();raise + finally: + if active: + with (OUT/'cleanup-mcp-live12.log').open('x') as log: + async with McpDevStdioSession(McpDevServerSpec(str(PYTHON)),log) as session: + children.append(session.require_process());await session.initialize(timeout_seconds=90) + receipt['cleanup']=await call(session,'openhcs_close_viewer_window',ViewerWindowCloseRequest(connection=conn,confirmed=True).as_tool_arguments(),allow_error=True) + if xserver is not None: + xserver.terminate() + try:xserver.wait(timeout=5) + except subprocess.TimeoutExpired:xserver.kill();xserver.wait(timeout=5) + receipt['xserver_returncode']=xserver.returncode + receipt['dependencies_unchanged']=receipt_dependencies=={name:package_metadata.version(name) for name in receipt_dependencies} + receipt['mcp_children']=[{'pid':p.pid,'returncode':p.returncode} for p in children];save() +asyncio.run(journey()) diff --git a/docs/refactor/receipts/public-native-receiving-134-20261004/label-source-receipt.json b/docs/refactor/receipts/public-native-receiving-134-20261004/label-source-receipt.json new file mode 100644 index 0000000000..0c5ebf2d54 --- /dev/null +++ b/docs/refactor/receipts/public-native-receiving-134-20261004/label-source-receipt.json @@ -0,0 +1,674 @@ +{ + "connection": { + "host": "127.0.0.1", + "port": 6609, + "transport_mode": "tcp", + "persistent": true + }, + "schema_version": "openhcs.agent.v1", + "errors": [], + "warnings": [], + "observed": true, + "viewer": { + "viewer_type": "napari", + "title": "OpenHCS Napari Visualization" + }, + "layer_count": 1, + "layers": [ + { + "route_key": "origin_manual_kind_manual_projection_selected_images_8c7357d46ccc38823ca9e68096baf86f25c3004b61b63ba1eef9adea41d34fb8_scalar_stack", + "title": "selected_images image stack", + "mounted": true, + "item_count": 1, + "producer_identities": [ + { + "origin": "manual", + "output_kind": "manual", + "output_key": "selected_images", + "projection_key": "selected_images_8c7357d46ccc38823ca9e68096baf86f25c3004b61b63ba1eef9adea41d34fb8", + "step_name": null, + "pipeline_position": null, + "step_scope_id": null, + "invocation_key": null, + "artifact_kind": null + } + ], + "axis_labels": [ + "site", + "channel", + "z_index", + "timepoint", + "well", + "y", + "x" + ], + "stack_axes": [ + "channel" + ], + "pending_update": false, + "data_types": [ + "image" + ], + "component_values": [ + { + "site": 1, + "z_index": 1, + "timepoint": 1, + "well": "A01" + } + ], + "component_value_count": 1, + "component_values_truncated": false, + "payload_summaries": [ + { + "shape": [ + 2, + 32, + 32 + ], + "dtype": "uint16", + "size": 2048, + "nonzero_count": 308, + "min": 0, + "max": 22, + "nonzero_min_coordinate": [ + 0, + 3, + 4 + ], + "nonzero_max_coordinate": [ + 1, + 24, + 27 + ], + "nonzero_example_coordinates": [ + [ + 0, + 3, + 4 + ], + [ + 0, + 5, + 4 + ], + [ + 0, + 7, + 4 + ], + [ + 0, + 9, + 5 + ], + [ + 0, + 11, + 5 + ], + [ + 0, + 18, + 24 + ], + [ + 0, + 21, + 20 + ], + [ + 0, + 23, + 25 + ], + [ + 1, + 3, + 13 + ], + [ + 1, + 6, + 4 + ], + [ + 1, + 8, + 4 + ], + [ + 1, + 10, + 5 + ], + [ + 1, + 17, + 21 + ], + [ + 1, + 19, + 26 + ], + [ + 1, + 22, + 22 + ], + [ + 1, + 24, + 27 + ] + ], + "source_voxel_spacing": { + "values_zyx": [ + 1.3556, + 1.3556 + ], + "unit": "micrometers" + }, + "spatial_origin_yx": [ + 0, + 0 + ], + "source_spatial_shape_yx": [ + 32, + 32 + ], + "aggregate_component_values": { + "channel": [ + 2, + 1 + ] + }, + "data_type": "image", + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/stacked_labels/A01_s001_w2_z001_t001_Labels.tif", + "components": { + "site": 1, + "z_index": 1, + "timepoint": 1, + "well": "A01" + }, + "payload_type": "ndarray" + } + ], + "payload_summary_count": 1, + "payload_summaries_truncated": false, + "axis_offsets": [ + 0 + ], + "scalar_labels": [ + "Site 1", + "Z 1", + "T 1", + "Well A01" + ], + "labels": { + "channel": [ + "Ch 1", + "Ch 2" + ] + }, + "axis_component_values": { + "channel": [ + 1, + 2 + ] + }, + "routed_component_values": { + "channel": [ + 1, + 2 + ] + }, + "routed_component_coordinates": [ + [ + 1 + ], + [ + 2 + ] + ], + "data_shape": [ + 1, + 2, + 1, + 1, + 1, + 32, + 32 + ], + "native_transform": { + "scale": [ + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.3556, + 1.3556 + ], + "translate": [ + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0 + ] + }, + "native_intensity": { + "contrast_limits": [ + 0.0, + 22.0 + ], + "gamma": 1.0 + }, + "visible": true, + "selected": true, + "feature_row_count": 0, + "selected_data_indices": [] + } + ], + "active_dimension_label_route": "origin_manual_kind_manual_projection_selected_images_8c7357d46ccc38823ca9e68096baf86f25c3004b61b63ba1eef9adea41d34fb8_scalar_stack", + "viewer_ndim": 7, + "current_step": [ + 0, + 0, + 0, + 0, + 0, + 15, + 15 + ], + "axis_labels": [ + "site", + "channel", + "z_index", + "timepoint", + "well", + "y", + "x" + ], + "component_group_count": 1, + "component_item_count": 1, + "native_viewport": { + "center": [ + 0.0, + 21.011799999999997, + 21.011799999999997 + ], + "zoom": 6.635668707583358 + }, + "native_dimensions": { + "order": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6 + ], + "ndisplay": 2, + "displayed_axes": [ + "y", + "x" + ], + "point": [ + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 20.334, + 20.334 + ], + "camera_angles": [ + 0.0, + 0.0, + 0.0 + ], + "canvas_size": [ + 643, + 478 + ] + }, + "response": { + "type": "state_ack", + "status": "success", + "viewer": { + "type": "napari", + "title": "OpenHCS Napari Visualization" + }, + "layer_count": 1, + "layers": [ + { + "route_key": "origin_manual_kind_manual_projection_selected_images_8c7357d46ccc38823ca9e68096baf86f25c3004b61b63ba1eef9adea41d34fb8_scalar_stack", + "producer_identities": [ + { + "origin": "manual", + "output_kind": "manual", + "output_key": "selected_images", + "projection_key": "selected_images_8c7357d46ccc38823ca9e68096baf86f25c3004b61b63ba1eef9adea41d34fb8", + "step_name": null, + "pipeline_position": null, + "step_scope_id": null, + "invocation_key": null, + "artifact_kind": null + } + ], + "title": "selected_images image stack", + "mounted": true, + "item_count": 1, + "data_types": [ + "image" + ], + "component_values": [ + { + "site": 1, + "z_index": 1, + "timepoint": 1, + "well": "A01" + } + ], + "component_value_count": 1, + "component_values_truncated": false, + "payload_summaries": [ + { + "shape": [ + 2, + 32, + 32 + ], + "dtype": "uint16", + "size": 2048, + "nonzero_count": 308, + "min": 0, + "max": 22, + "nonzero_min_coordinate": [ + 0, + 3, + 4 + ], + "nonzero_max_coordinate": [ + 1, + 24, + 27 + ], + "nonzero_example_coordinates": [ + [ + 0, + 3, + 4 + ], + [ + 0, + 5, + 4 + ], + [ + 0, + 7, + 4 + ], + [ + 0, + 9, + 5 + ], + [ + 0, + 11, + 5 + ], + [ + 0, + 18, + 24 + ], + [ + 0, + 21, + 20 + ], + [ + 0, + 23, + 25 + ], + [ + 1, + 3, + 13 + ], + [ + 1, + 6, + 4 + ], + [ + 1, + 8, + 4 + ], + [ + 1, + 10, + 5 + ], + [ + 1, + 17, + 21 + ], + [ + 1, + 19, + 26 + ], + [ + 1, + 22, + 22 + ], + [ + 1, + 24, + 27 + ] + ], + "source_voxel_spacing": { + "values_zyx": [ + 1.3556, + 1.3556 + ], + "unit": "micrometers" + }, + "spatial_origin_yx": [ + 0, + 0 + ], + "source_spatial_shape_yx": [ + 32, + 32 + ], + "aggregate_component_values": { + "channel": [ + 2, + 1 + ] + }, + "data_type": "image", + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/stacked_labels/A01_s001_w2_z001_t001_Labels.tif", + "components": { + "site": 1, + "z_index": 1, + "timepoint": 1, + "well": "A01" + }, + "payload_type": "ndarray" + } + ], + "payload_summary_count": 1, + "payload_summaries_truncated": false, + "axis_labels": [ + "site", + "channel", + "z_index", + "timepoint", + "well", + "y", + "x" + ], + "stack_axes": [ + "channel" + ], + "axis_offsets": [ + 0 + ], + "scalar_labels": [ + "Site 1", + "Z 1", + "T 1", + "Well A01" + ], + "labels": { + "channel": [ + "Ch 1", + "Ch 2" + ] + }, + "axis_component_values": { + "channel": [ + 1, + 2 + ] + }, + "routed_component_values": { + "channel": [ + 1, + 2 + ] + }, + "routed_component_coordinates": [ + [ + 1 + ], + [ + 2 + ] + ], + "data_shape": [ + 1, + 2, + 1, + 1, + 1, + 32, + 32 + ], + "native_transform": { + "scale": [ + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.3556, + 1.3556 + ], + "translate": [ + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0 + ] + }, + "native_intensity": { + "contrast_limits": [ + 0.0, + 22.0 + ], + "gamma": 1.0 + }, + "visible": true, + "selected": true, + "feature_row_count": 0, + "selected_data_indices": [], + "pending_update": false + } + ], + "native_viewport": { + "center": [ + 0.0, + 21.011799999999997, + 21.011799999999997 + ], + "zoom": 6.635668707583358 + }, + "native_dimensions": { + "order": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6 + ], + "ndisplay": 2, + "displayed_axes": [ + "y", + "x" + ], + "point": [ + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 20.334, + 20.334 + ], + "camera_angles": [ + 0.0, + 0.0, + 0.0 + ], + "canvas_size": [ + 643, + 478 + ] + }, + "active_dimension_label_route": "origin_manual_kind_manual_projection_selected_images_8c7357d46ccc38823ca9e68096baf86f25c3004b61b63ba1eef9adea41d34fb8_scalar_stack", + "viewer_ndim": 7, + "current_step": [ + 0, + 0, + 0, + 0, + 0, + 15, + 15 + ], + "axis_labels": [ + "site", + "channel", + "z_index", + "timepoint", + "well", + "y", + "x" + ], + "component_group_count": 1, + "component_item_count": 1 + } +} diff --git a/docs/refactor/receipts/public-native-receiving-134-20261004/receipt.json b/docs/refactor/receipts/public-native-receiving-134-20261004/receipt.json new file mode 100644 index 0000000000..6bfe194d58 --- /dev/null +++ b/docs/refactor/receipts/public-native-receiving-134-20261004/receipt.json @@ -0,0 +1,32693 @@ +{ + "accepted": true, + "scope": "Synthetic native receiving only; no biological processing or native CP rerun", + "source_head": "044b2269e4a98f8f75ac3760db797257a40fda94", + "source": "/var/tmp/openhcs-resolved-pipeline-owner-20261004", + "controller_sha256": "ddcbf82ddec594e2205489c9b6e68c263cd147afa95b92cf1916d4bd8cb41158", + "calls": [ + { + "tool": "openhcs_health_check", + "arguments": {}, + "response": { + "content": [ + { + "type": "text", + "text": "{\n \"schema_version\": \"openhcs.agent.v1\",\n \"errors\": [],\n \"warnings\": [],\n \"status\": \"ok\",\n \"started_at_unix\": 1791088238.291639,\n \"service\": \"openhcs.mcp\",\n \"openhcs_version\": \"0.8.7\",\n \"packaged_resources_ready\": true,\n \"packaged_resource_count\": 86,\n \"missing_packaged_resource_paths\": [],\n \"server_process_id\": 4094137,\n \"server_source_path\": \"/var/tmp/openhcs-resolved-pipeline-owner-20261004/openhcs/mcp/server.py\",\n \"server_import_mtime_ns\": 1791076987318725938,\n \"server_current_mtime_ns\": 1791076987318725938,\n \"server_source_changed_since_import\": false,\n \"stale_source_paths\": [],\n \"recovery_reason\": \"current\",\n \"installation_pointer_path\": null,\n \"installation_pointer_changed_since_import\": false,\n \"installation_pointer_available\": null,\n \"restart_required\": false,\n \"restart_command\": [],\n \"restart_command_is_stable\": false,\n \"reconnect_required\": false,\n \"reconnect_owner\": null,\n \"retry_after_reconnect\": false,\n \"automatic_recovery_on_reconnect\": false,\n \"restart_hint\": null\n}" + } + ], + "structuredContent": { + "schema_version": "openhcs.agent.v1", + "errors": [], + "warnings": [], + "status": "ok", + "started_at_unix": 1791088238.291639, + "service": "openhcs.mcp", + "openhcs_version": "0.8.7", + "packaged_resources_ready": true, + "packaged_resource_count": 86, + "missing_packaged_resource_paths": [], + "server_process_id": 4094137, + "server_source_path": "/var/tmp/openhcs-resolved-pipeline-owner-20261004/openhcs/mcp/server.py", + "server_import_mtime_ns": 1791076987318725938, + "server_current_mtime_ns": 1791076987318725938, + "server_source_changed_since_import": false, + "stale_source_paths": [], + "recovery_reason": "current", + "installation_pointer_path": null, + "installation_pointer_changed_since_import": false, + "installation_pointer_available": null, + "restart_required": false, + "restart_command": [], + "restart_command_is_stable": false, + "reconnect_required": false, + "reconnect_owner": null, + "retry_after_reconnect": false, + "automatic_recovery_on_reconnect": false, + "restart_hint": null + }, + "isError": false + }, + "payload": { + "schema_version": "openhcs.agent.v1", + "errors": [], + "warnings": [], + "status": "ok", + "started_at_unix": 1791088238.291639, + "service": "openhcs.mcp", + "openhcs_version": "0.8.7", + "packaged_resources_ready": true, + "packaged_resource_count": 86, + "missing_packaged_resource_paths": [], + "server_process_id": 4094137, + "server_source_path": "/var/tmp/openhcs-resolved-pipeline-owner-20261004/openhcs/mcp/server.py", + "server_import_mtime_ns": 1791076987318725938, + "server_current_mtime_ns": 1791076987318725938, + "server_source_changed_since_import": false, + "stale_source_paths": [], + "recovery_reason": "current", + "installation_pointer_path": null, + "installation_pointer_changed_since_import": false, + "installation_pointer_available": null, + "restart_required": false, + "restart_command": [], + "restart_command_is_stable": false, + "reconnect_required": false, + "reconnect_owner": null, + "retry_after_reconnect": false, + "automatic_recovery_on_reconnect": false, + "restart_hint": null + } + }, + { + "tool": "openhcs_query_plate_files", + "arguments": { + "plate_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate", + "kind": "image", + "limit": 10 + }, + "response": { + "content": [ + { + "type": "text", + "text": "{\n \"schema_version\": \"openhcs.agent.v1\",\n \"errors\": [],\n \"warnings\": [],\n \"plate_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate\",\n \"result_directory\": null,\n \"requested_microscope_type\": \"auto\",\n \"detected_microscope_type\": \"openhcsdata\",\n \"handler_class\": \"OpenHCSMicroscopeHandler\",\n \"parser_class\": \"ImageXpressFilenameParser\",\n \"total_count\": 2,\n \"returned_count\": 2,\n \"offset\": 0,\n \"limit\": 10,\n \"truncated_count\": 0,\n \"records\": [\n {\n \"kind\": \"image\",\n \"key\": \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w1_z001_t001.tif\",\n \"metadata\": {\n \"filename\": \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w1_z001_t001.tif\",\n \"virtual_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w1_z001_t001.tif\",\n \"full_virtual_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w1_z001_t001.tif\",\n \"source_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w1_z001_t001.tif\",\n \"type\": \"Image\",\n \"OpenHCSSourceVoxelSpacingZYX\": \"1.3555999999999999,1.3555999999999999\",\n \"OpenHCSSourceVoxelSpacingUnit\": \"micrometers\",\n \"site\": 1,\n \"channel\": 1,\n \"z_index\": 1,\n \"timepoint\": 1,\n \"well\": \"A01\",\n \"extension\": \".tif\",\n \"size\": \"2.3 KB\",\n \"modified\": \"2026-10-04T00:10:26\"\n },\n \"virtual_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w1_z001_t001.tif\",\n \"full_virtual_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w1_z001_t001.tif\",\n \"source_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w1_z001_t001.tif\",\n \"relative_path\": null,\n \"full_path\": null,\n \"file_format\": null,\n \"preview\": null\n },\n {\n \"kind\": \"image\",\n \"key\": \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w2_z001_t001.tif\",\n \"metadata\": {\n \"filename\": \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w2_z001_t001.tif\",\n \"virtual_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w2_z001_t001.tif\",\n \"full_virtual_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w2_z001_t001.tif\",\n \"source_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w2_z001_t001.tif\",\n \"type\": \"Image\",\n \"OpenHCSSourceVoxelSpacingZYX\": \"1.3555999999999999,1.3555999999999999\",\n \"OpenHCSSourceVoxelSpacingUnit\": \"micrometers\",\n \"site\": 1,\n \"channel\": 2,\n \"z_index\": 1,\n \"timepoint\": 1,\n \"well\": \"A01\",\n \"extension\": \".tif\",\n \"size\": \"2.3 KB\",\n \"modified\": \"2026-10-04T00:10:26\"\n },\n \"virtual_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w2_z001_t001.tif\",\n \"full_virtual_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w2_z001_t001.tif\",\n \"source_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w2_z001_t001.tif\",\n \"relative_path\": null,\n \"full_path\": null,\n \"file_format\": null,\n \"preview\": null\n }\n ]\n}" + } + ], + "structuredContent": { + "schema_version": "openhcs.agent.v1", + "errors": [], + "warnings": [], + "plate_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate", + "result_directory": null, + "requested_microscope_type": "auto", + "detected_microscope_type": "openhcsdata", + "handler_class": "OpenHCSMicroscopeHandler", + "parser_class": "ImageXpressFilenameParser", + "total_count": 2, + "returned_count": 2, + "offset": 0, + "limit": 10, + "truncated_count": 0, + "records": [ + { + "kind": "image", + "key": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w1_z001_t001.tif", + "metadata": { + "filename": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w1_z001_t001.tif", + "virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w1_z001_t001.tif", + "full_virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w1_z001_t001.tif", + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w1_z001_t001.tif", + "type": "Image", + "OpenHCSSourceVoxelSpacingZYX": "1.3555999999999999,1.3555999999999999", + "OpenHCSSourceVoxelSpacingUnit": "micrometers", + "site": 1, + "channel": 1, + "z_index": 1, + "timepoint": 1, + "well": "A01", + "extension": ".tif", + "size": "2.3 KB", + "modified": "2026-10-04T00:10:26" + }, + "virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w1_z001_t001.tif", + "full_virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w1_z001_t001.tif", + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w1_z001_t001.tif", + "relative_path": null, + "full_path": null, + "file_format": null, + "preview": null + }, + { + "kind": "image", + "key": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w2_z001_t001.tif", + "metadata": { + "filename": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w2_z001_t001.tif", + "virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w2_z001_t001.tif", + "full_virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w2_z001_t001.tif", + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w2_z001_t001.tif", + "type": "Image", + "OpenHCSSourceVoxelSpacingZYX": "1.3555999999999999,1.3555999999999999", + "OpenHCSSourceVoxelSpacingUnit": "micrometers", + "site": 1, + "channel": 2, + "z_index": 1, + "timepoint": 1, + "well": "A01", + "extension": ".tif", + "size": "2.3 KB", + "modified": "2026-10-04T00:10:26" + }, + "virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w2_z001_t001.tif", + "full_virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w2_z001_t001.tif", + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w2_z001_t001.tif", + "relative_path": null, + "full_path": null, + "file_format": null, + "preview": null + } + ] + }, + "isError": false + }, + "payload": { + "schema_version": "openhcs.agent.v1", + "errors": [], + "warnings": [], + "plate_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate", + "result_directory": null, + "requested_microscope_type": "auto", + "detected_microscope_type": "openhcsdata", + "handler_class": "OpenHCSMicroscopeHandler", + "parser_class": "ImageXpressFilenameParser", + "total_count": 2, + "returned_count": 2, + "offset": 0, + "limit": 10, + "truncated_count": 0, + "records": [ + { + "kind": "image", + "key": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w1_z001_t001.tif", + "metadata": { + "filename": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w1_z001_t001.tif", + "virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w1_z001_t001.tif", + "full_virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w1_z001_t001.tif", + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w1_z001_t001.tif", + "type": "Image", + "OpenHCSSourceVoxelSpacingZYX": "1.3555999999999999,1.3555999999999999", + "OpenHCSSourceVoxelSpacingUnit": "micrometers", + "site": 1, + "channel": 1, + "z_index": 1, + "timepoint": 1, + "well": "A01", + "extension": ".tif", + "size": "2.3 KB", + "modified": "2026-10-04T00:10:26" + }, + "virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w1_z001_t001.tif", + "full_virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w1_z001_t001.tif", + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w1_z001_t001.tif", + "relative_path": null, + "full_path": null, + "file_format": null, + "preview": null + }, + { + "kind": "image", + "key": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w2_z001_t001.tif", + "metadata": { + "filename": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w2_z001_t001.tif", + "virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w2_z001_t001.tif", + "full_virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w2_z001_t001.tif", + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w2_z001_t001.tif", + "type": "Image", + "OpenHCSSourceVoxelSpacingZYX": "1.3555999999999999,1.3555999999999999", + "OpenHCSSourceVoxelSpacingUnit": "micrometers", + "site": 1, + "channel": 2, + "z_index": 1, + "timepoint": 1, + "well": "A01", + "extension": ".tif", + "size": "2.3 KB", + "modified": "2026-10-04T00:10:26" + }, + "virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w2_z001_t001.tif", + "full_virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w2_z001_t001.tif", + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w2_z001_t001.tif", + "relative_path": null, + "full_path": null, + "file_format": null, + "preview": null + } + ] + } + }, + { + "tool": "openhcs_query_plate_files", + "arguments": { + "plate_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate", + "kind": "image", + "limit": 10 + }, + "response": { + "content": [ + { + "type": "text", + "text": "{\n \"schema_version\": \"openhcs.agent.v1\",\n \"errors\": [],\n \"warnings\": [],\n \"plate_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate\",\n \"result_directory\": null,\n \"requested_microscope_type\": \"auto\",\n \"detected_microscope_type\": \"openhcsdata\",\n \"handler_class\": \"OpenHCSMicroscopeHandler\",\n \"parser_class\": \"ImageXpressFilenameParser\",\n \"total_count\": 3,\n \"returned_count\": 3,\n \"offset\": 0,\n \"limit\": 10,\n \"truncated_count\": 0,\n \"records\": [\n {\n \"kind\": \"image\",\n \"key\": \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/images/A01_s001_w1_z001_t001.tif\",\n \"metadata\": {\n \"filename\": \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/images/A01_s001_w1_z001_t001.tif\",\n \"virtual_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/images/A01_s001_w1_z001_t001.tif\",\n \"full_virtual_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/images/A01_s001_w1_z001_t001.tif\",\n \"source_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/images/A01_s001_w1_z001_t001.tif\",\n \"type\": \"Image\",\n \"OpenHCSSourceVoxelSpacingZYX\": \"1.3555999999999999,1.3555999999999999\",\n \"OpenHCSSourceVoxelSpacingUnit\": \"micrometers\",\n \"site\": 1,\n \"channel\": 1,\n \"z_index\": 1,\n \"timepoint\": 1,\n \"well\": \"A01\",\n \"extension\": \".tif\",\n \"size\": \"2.3 KB\",\n \"modified\": \"2026-10-04T00:10:26\"\n },\n \"virtual_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/images/A01_s001_w1_z001_t001.tif\",\n \"full_virtual_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/images/A01_s001_w1_z001_t001.tif\",\n \"source_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/images/A01_s001_w1_z001_t001.tif\",\n \"relative_path\": null,\n \"full_path\": null,\n \"file_format\": null,\n \"preview\": null\n },\n {\n \"kind\": \"image\",\n \"key\": \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/images/A01_s001_w2_z001_t001.tif\",\n \"metadata\": {\n \"filename\": \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/images/A01_s001_w2_z001_t001.tif\",\n \"virtual_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/images/A01_s001_w2_z001_t001.tif\",\n \"full_virtual_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/images/A01_s001_w2_z001_t001.tif\",\n \"source_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/images/A01_s001_w2_z001_t001.tif\",\n \"type\": \"Image\",\n \"OpenHCSSourceVoxelSpacingZYX\": \"1.3555999999999999,1.3555999999999999\",\n \"OpenHCSSourceVoxelSpacingUnit\": \"micrometers\",\n \"site\": 1,\n \"channel\": 2,\n \"z_index\": 1,\n \"timepoint\": 1,\n \"well\": \"A01\",\n \"extension\": \".tif\",\n \"size\": \"2.3 KB\",\n \"modified\": \"2026-10-04T00:10:26\"\n },\n \"virtual_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/images/A01_s001_w2_z001_t001.tif\",\n \"full_virtual_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/images/A01_s001_w2_z001_t001.tif\",\n \"source_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/images/A01_s001_w2_z001_t001.tif\",\n \"relative_path\": null,\n \"full_path\": null,\n \"file_format\": null,\n \"preview\": null\n },\n {\n \"kind\": \"image\",\n \"key\": \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/stacked_labels/A01_s001_w2_z001_t001_Labels.tif\",\n \"metadata\": {\n \"filename\": \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/stacked_labels/A01_s001_w2_z001_t001_Labels.tif\",\n \"virtual_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/stacked_labels/A01_s001_w2_z001_t001_Labels.tif\",\n \"full_virtual_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/stacked_labels/A01_s001_w2_z001_t001_Labels.tif\",\n \"source_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/stacked_labels/A01_s001_w2_z001_t001_Labels.tif\",\n \"type\": \"Image\",\n \"OpenHCSSourceVoxelSpacingZYX\": \"1.3555999999999999,1.3555999999999999\",\n \"OpenHCSSourceVoxelSpacingUnit\": \"micrometers\",\n \"site\": 1,\n \"channel\": 2,\n \"z_index\": 1,\n \"timepoint\": 1,\n \"well\": \"A01\",\n \"extension\": \".tif\",\n \"size\": \"4.4 KB\",\n \"modified\": \"2026-10-04T00:24:30\"\n },\n \"virtual_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/stacked_labels/A01_s001_w2_z001_t001_Labels.tif\",\n \"full_virtual_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/stacked_labels/A01_s001_w2_z001_t001_Labels.tif\",\n \"source_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/stacked_labels/A01_s001_w2_z001_t001_Labels.tif\",\n \"relative_path\": null,\n \"full_path\": null,\n \"file_format\": null,\n \"preview\": null\n }\n ]\n}" + } + ], + "structuredContent": { + "schema_version": "openhcs.agent.v1", + "errors": [], + "warnings": [], + "plate_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate", + "result_directory": null, + "requested_microscope_type": "auto", + "detected_microscope_type": "openhcsdata", + "handler_class": "OpenHCSMicroscopeHandler", + "parser_class": "ImageXpressFilenameParser", + "total_count": 3, + "returned_count": 3, + "offset": 0, + "limit": 10, + "truncated_count": 0, + "records": [ + { + "kind": "image", + "key": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/images/A01_s001_w1_z001_t001.tif", + "metadata": { + "filename": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/images/A01_s001_w1_z001_t001.tif", + "virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/images/A01_s001_w1_z001_t001.tif", + "full_virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/images/A01_s001_w1_z001_t001.tif", + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/images/A01_s001_w1_z001_t001.tif", + "type": "Image", + "OpenHCSSourceVoxelSpacingZYX": "1.3555999999999999,1.3555999999999999", + "OpenHCSSourceVoxelSpacingUnit": "micrometers", + "site": 1, + "channel": 1, + "z_index": 1, + "timepoint": 1, + "well": "A01", + "extension": ".tif", + "size": "2.3 KB", + "modified": "2026-10-04T00:10:26" + }, + "virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/images/A01_s001_w1_z001_t001.tif", + "full_virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/images/A01_s001_w1_z001_t001.tif", + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/images/A01_s001_w1_z001_t001.tif", + "relative_path": null, + "full_path": null, + "file_format": null, + "preview": null + }, + { + "kind": "image", + "key": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/images/A01_s001_w2_z001_t001.tif", + "metadata": { + "filename": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/images/A01_s001_w2_z001_t001.tif", + "virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/images/A01_s001_w2_z001_t001.tif", + "full_virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/images/A01_s001_w2_z001_t001.tif", + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/images/A01_s001_w2_z001_t001.tif", + "type": "Image", + "OpenHCSSourceVoxelSpacingZYX": "1.3555999999999999,1.3555999999999999", + "OpenHCSSourceVoxelSpacingUnit": "micrometers", + "site": 1, + "channel": 2, + "z_index": 1, + "timepoint": 1, + "well": "A01", + "extension": ".tif", + "size": "2.3 KB", + "modified": "2026-10-04T00:10:26" + }, + "virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/images/A01_s001_w2_z001_t001.tif", + "full_virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/images/A01_s001_w2_z001_t001.tif", + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/images/A01_s001_w2_z001_t001.tif", + "relative_path": null, + "full_path": null, + "file_format": null, + "preview": null + }, + { + "kind": "image", + "key": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/stacked_labels/A01_s001_w2_z001_t001_Labels.tif", + "metadata": { + "filename": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/stacked_labels/A01_s001_w2_z001_t001_Labels.tif", + "virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/stacked_labels/A01_s001_w2_z001_t001_Labels.tif", + "full_virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/stacked_labels/A01_s001_w2_z001_t001_Labels.tif", + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/stacked_labels/A01_s001_w2_z001_t001_Labels.tif", + "type": "Image", + "OpenHCSSourceVoxelSpacingZYX": "1.3555999999999999,1.3555999999999999", + "OpenHCSSourceVoxelSpacingUnit": "micrometers", + "site": 1, + "channel": 2, + "z_index": 1, + "timepoint": 1, + "well": "A01", + "extension": ".tif", + "size": "4.4 KB", + "modified": "2026-10-04T00:24:30" + }, + "virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/stacked_labels/A01_s001_w2_z001_t001_Labels.tif", + "full_virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/stacked_labels/A01_s001_w2_z001_t001_Labels.tif", + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/stacked_labels/A01_s001_w2_z001_t001_Labels.tif", + "relative_path": null, + "full_path": null, + "file_format": null, + "preview": null + } + ] + }, + "isError": false + }, + "payload": { + "schema_version": "openhcs.agent.v1", + "errors": [], + "warnings": [], + "plate_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate", + "result_directory": null, + "requested_microscope_type": "auto", + "detected_microscope_type": "openhcsdata", + "handler_class": "OpenHCSMicroscopeHandler", + "parser_class": "ImageXpressFilenameParser", + "total_count": 3, + "returned_count": 3, + "offset": 0, + "limit": 10, + "truncated_count": 0, + "records": [ + { + "kind": "image", + "key": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/images/A01_s001_w1_z001_t001.tif", + "metadata": { + "filename": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/images/A01_s001_w1_z001_t001.tif", + "virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/images/A01_s001_w1_z001_t001.tif", + "full_virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/images/A01_s001_w1_z001_t001.tif", + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/images/A01_s001_w1_z001_t001.tif", + "type": "Image", + "OpenHCSSourceVoxelSpacingZYX": "1.3555999999999999,1.3555999999999999", + "OpenHCSSourceVoxelSpacingUnit": "micrometers", + "site": 1, + "channel": 1, + "z_index": 1, + "timepoint": 1, + "well": "A01", + "extension": ".tif", + "size": "2.3 KB", + "modified": "2026-10-04T00:10:26" + }, + "virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/images/A01_s001_w1_z001_t001.tif", + "full_virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/images/A01_s001_w1_z001_t001.tif", + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/images/A01_s001_w1_z001_t001.tif", + "relative_path": null, + "full_path": null, + "file_format": null, + "preview": null + }, + { + "kind": "image", + "key": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/images/A01_s001_w2_z001_t001.tif", + "metadata": { + "filename": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/images/A01_s001_w2_z001_t001.tif", + "virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/images/A01_s001_w2_z001_t001.tif", + "full_virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/images/A01_s001_w2_z001_t001.tif", + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/images/A01_s001_w2_z001_t001.tif", + "type": "Image", + "OpenHCSSourceVoxelSpacingZYX": "1.3555999999999999,1.3555999999999999", + "OpenHCSSourceVoxelSpacingUnit": "micrometers", + "site": 1, + "channel": 2, + "z_index": 1, + "timepoint": 1, + "well": "A01", + "extension": ".tif", + "size": "2.3 KB", + "modified": "2026-10-04T00:10:26" + }, + "virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/images/A01_s001_w2_z001_t001.tif", + "full_virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/images/A01_s001_w2_z001_t001.tif", + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/images/A01_s001_w2_z001_t001.tif", + "relative_path": null, + "full_path": null, + "file_format": null, + "preview": null + }, + { + "kind": "image", + "key": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/stacked_labels/A01_s001_w2_z001_t001_Labels.tif", + "metadata": { + "filename": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/stacked_labels/A01_s001_w2_z001_t001_Labels.tif", + "virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/stacked_labels/A01_s001_w2_z001_t001_Labels.tif", + "full_virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/stacked_labels/A01_s001_w2_z001_t001_Labels.tif", + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/stacked_labels/A01_s001_w2_z001_t001_Labels.tif", + "type": "Image", + "OpenHCSSourceVoxelSpacingZYX": "1.3555999999999999,1.3555999999999999", + "OpenHCSSourceVoxelSpacingUnit": "micrometers", + "site": 1, + "channel": 2, + "z_index": 1, + "timepoint": 1, + "well": "A01", + "extension": ".tif", + "size": "4.4 KB", + "modified": "2026-10-04T00:24:30" + }, + "virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/stacked_labels/A01_s001_w2_z001_t001_Labels.tif", + "full_virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/stacked_labels/A01_s001_w2_z001_t001_Labels.tif", + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/stacked_labels/A01_s001_w2_z001_t001_Labels.tif", + "relative_path": null, + "full_path": null, + "file_format": null, + "preview": null + } + ] + } + }, + { + "tool": "openhcs_stream_plate_files_to_viewer", + "arguments": { + "plate_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate", + "result_directory": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/stacked_labels", + "file_paths": [ + "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/stacked_labels/A01_s001_w2_z001_t001_Labels.tif" + ], + "microscope_type": "auto", + "pattern_format": null, + "kind": "result", + "path_contains": null, + "well": null, + "limit": 2, + "viewer_config_key": "napari_streaming_config", + "display_config": null, + "host": "127.0.0.1", + "port": 6609, + "transport_mode": "tcp", + "persistent": true, + "fresh_viewer": true, + "source_receipt": { + "uri": "file:///home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/label-source-receipt.json", + "title": "Actual calibrated native label state", + "mime_type": "application/json", + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/label-source-receipt.json", + "size_bytes": 13360, + "sha256": "98ec069b91300ccfb716c9b34bf48dfecb4ee81013471262be95ff05063a1679" + } + }, + "response": { + "content": [ + { + "type": "text", + "text": "{\n \"schema_version\": \"openhcs.agent.v1\",\n \"errors\": [],\n \"warnings\": [],\n \"plate_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate\",\n \"requested_microscope_type\": \"auto\",\n \"detected_microscope_type\": \"openhcsdata\",\n \"handler_class\": \"OpenHCSMicroscopeHandler\",\n \"parser_class\": \"ImageXpressFilenameParser\",\n \"viewer_config_key\": \"napari_streaming_config\",\n \"viewer_type\": \"napari\",\n \"connection\": {\n \"host\": \"127.0.0.1\",\n \"port\": 6609,\n \"transport_mode\": \"tcp\",\n \"persistent\": true\n },\n \"requested_paths\": [\n \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/stacked_labels/A01_s001_w2_z001_t001_Labels.tif\"\n ],\n \"resolved_records\": [\n {\n \"kind\": \"result\",\n \"key\": \"A01_s001_w2_z001_t001_Labels.tif\",\n \"metadata\": {\n \"filename\": \"A01_s001_w2_z001_t001_Labels.tif\",\n \"type\": \"TIFF\",\n \"size\": \"4.4 KB\",\n \"modified\": \"2026-10-04T00:24:30\",\n \"result_subdirectory\": \"stacked_labels\",\n \"full_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/stacked_labels/A01_s001_w2_z001_t001_Labels.tif\"\n },\n \"virtual_path\": null,\n \"full_virtual_path\": null,\n \"source_path\": null,\n \"relative_path\": \"A01_s001_w2_z001_t001_Labels.tif\",\n \"full_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/stacked_labels/A01_s001_w2_z001_t001_Labels.tif\",\n \"file_format\": \"TIFF\",\n \"preview\": null\n }\n ],\n \"streamed_image_paths\": [\n \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/stacked_labels/A01_s001_w2_z001_t001_Labels.tif\"\n ],\n \"streamed_roi_paths\": [],\n \"skipped_records\": [],\n \"status_messages\": [\n \"Loading chunk 1/1 (1 images)...\",\n \"Streamed 1 images to Napari\"\n ]\n}" + } + ], + "structuredContent": { + "schema_version": "openhcs.agent.v1", + "errors": [], + "warnings": [], + "plate_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate", + "requested_microscope_type": "auto", + "detected_microscope_type": "openhcsdata", + "handler_class": "OpenHCSMicroscopeHandler", + "parser_class": "ImageXpressFilenameParser", + "viewer_config_key": "napari_streaming_config", + "viewer_type": "napari", + "connection": { + "host": "127.0.0.1", + "port": 6609, + "transport_mode": "tcp", + "persistent": true + }, + "requested_paths": [ + "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/stacked_labels/A01_s001_w2_z001_t001_Labels.tif" + ], + "resolved_records": [ + { + "kind": "result", + "key": "A01_s001_w2_z001_t001_Labels.tif", + "metadata": { + "filename": "A01_s001_w2_z001_t001_Labels.tif", + "type": "TIFF", + "size": "4.4 KB", + "modified": "2026-10-04T00:24:30", + "result_subdirectory": "stacked_labels", + "full_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/stacked_labels/A01_s001_w2_z001_t001_Labels.tif" + }, + "virtual_path": null, + "full_virtual_path": null, + "source_path": null, + "relative_path": "A01_s001_w2_z001_t001_Labels.tif", + "full_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/stacked_labels/A01_s001_w2_z001_t001_Labels.tif", + "file_format": "TIFF", + "preview": null + } + ], + "streamed_image_paths": [ + "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/stacked_labels/A01_s001_w2_z001_t001_Labels.tif" + ], + "streamed_roi_paths": [], + "skipped_records": [], + "status_messages": [ + "Loading chunk 1/1 (1 images)...", + "Streamed 1 images to Napari" + ] + }, + "isError": false + }, + "payload": { + "schema_version": "openhcs.agent.v1", + "errors": [], + "warnings": [], + "plate_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate", + "requested_microscope_type": "auto", + "detected_microscope_type": "openhcsdata", + "handler_class": "OpenHCSMicroscopeHandler", + "parser_class": "ImageXpressFilenameParser", + "viewer_config_key": "napari_streaming_config", + "viewer_type": "napari", + "connection": { + "host": "127.0.0.1", + "port": 6609, + "transport_mode": "tcp", + "persistent": true + }, + "requested_paths": [ + "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/stacked_labels/A01_s001_w2_z001_t001_Labels.tif" + ], + "resolved_records": [ + { + "kind": "result", + "key": "A01_s001_w2_z001_t001_Labels.tif", + "metadata": { + "filename": "A01_s001_w2_z001_t001_Labels.tif", + "type": "TIFF", + "size": "4.4 KB", + "modified": "2026-10-04T00:24:30", + "result_subdirectory": "stacked_labels", + "full_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/stacked_labels/A01_s001_w2_z001_t001_Labels.tif" + }, + "virtual_path": null, + "full_virtual_path": null, + "source_path": null, + "relative_path": "A01_s001_w2_z001_t001_Labels.tif", + "full_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/stacked_labels/A01_s001_w2_z001_t001_Labels.tif", + "file_format": "TIFF", + "preview": null + } + ], + "streamed_image_paths": [ + "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/stacked_labels/A01_s001_w2_z001_t001_Labels.tif" + ], + "streamed_roi_paths": [], + "skipped_records": [], + "status_messages": [ + "Loading chunk 1/1 (1 images)...", + "Streamed 1 images to Napari" + ] + } + }, + { + "tool": "openhcs_stream_plate_files_to_viewer", + "arguments": { + "plate_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate", + "result_directory": null, + "file_paths": null, + "microscope_type": "auto", + "pattern_format": null, + "kind": "image", + "path_contains": null, + "well": null, + "limit": 2, + "viewer_config_key": "napari_streaming_config", + "display_config": null, + "host": "127.0.0.1", + "port": 6609, + "transport_mode": "tcp", + "persistent": true, + "fresh_viewer": false, + "source_receipt": null + }, + "response": { + "content": [ + { + "type": "text", + "text": "{\n \"schema_version\": \"openhcs.agent.v1\",\n \"errors\": [],\n \"warnings\": [],\n \"plate_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate\",\n \"requested_microscope_type\": \"auto\",\n \"detected_microscope_type\": \"openhcsdata\",\n \"handler_class\": \"OpenHCSMicroscopeHandler\",\n \"parser_class\": \"ImageXpressFilenameParser\",\n \"viewer_config_key\": \"napari_streaming_config\",\n \"viewer_type\": \"napari\",\n \"connection\": {\n \"host\": \"127.0.0.1\",\n \"port\": 6609,\n \"transport_mode\": \"tcp\",\n \"persistent\": true\n },\n \"requested_paths\": [],\n \"resolved_records\": [\n {\n \"kind\": \"image\",\n \"key\": \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w1_z001_t001.tif\",\n \"metadata\": {\n \"filename\": \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w1_z001_t001.tif\",\n \"virtual_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w1_z001_t001.tif\",\n \"full_virtual_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w1_z001_t001.tif\",\n \"source_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w1_z001_t001.tif\",\n \"type\": \"Image\",\n \"OpenHCSSourceVoxelSpacingZYX\": \"1.3555999999999999,1.3555999999999999\",\n \"OpenHCSSourceVoxelSpacingUnit\": \"micrometers\",\n \"site\": 1,\n \"channel\": 1,\n \"z_index\": 1,\n \"timepoint\": 1,\n \"well\": \"A01\",\n \"extension\": \".tif\",\n \"size\": \"2.3 KB\",\n \"modified\": \"2026-10-04T00:10:26\"\n },\n \"virtual_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w1_z001_t001.tif\",\n \"full_virtual_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w1_z001_t001.tif\",\n \"source_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w1_z001_t001.tif\",\n \"relative_path\": null,\n \"full_path\": null,\n \"file_format\": null,\n \"preview\": null\n },\n {\n \"kind\": \"image\",\n \"key\": \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w2_z001_t001.tif\",\n \"metadata\": {\n \"filename\": \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w2_z001_t001.tif\",\n \"virtual_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w2_z001_t001.tif\",\n \"full_virtual_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w2_z001_t001.tif\",\n \"source_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w2_z001_t001.tif\",\n \"type\": \"Image\",\n \"OpenHCSSourceVoxelSpacingZYX\": \"1.3555999999999999,1.3555999999999999\",\n \"OpenHCSSourceVoxelSpacingUnit\": \"micrometers\",\n \"site\": 1,\n \"channel\": 2,\n \"z_index\": 1,\n \"timepoint\": 1,\n \"well\": \"A01\",\n \"extension\": \".tif\",\n \"size\": \"2.3 KB\",\n \"modified\": \"2026-10-04T00:10:26\"\n },\n \"virtual_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w2_z001_t001.tif\",\n \"full_virtual_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w2_z001_t001.tif\",\n \"source_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w2_z001_t001.tif\",\n \"relative_path\": null,\n \"full_path\": null,\n \"file_format\": null,\n \"preview\": null\n }\n ],\n \"streamed_image_paths\": [\n \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w1_z001_t001.tif\",\n \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w2_z001_t001.tif\"\n ],\n \"streamed_roi_paths\": [],\n \"skipped_records\": [],\n \"status_messages\": [\n \"Loading chunk 1/1 (2 images)...\",\n \"Streamed 2 images to Napari\"\n ]\n}" + } + ], + "structuredContent": { + "schema_version": "openhcs.agent.v1", + "errors": [], + "warnings": [], + "plate_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate", + "requested_microscope_type": "auto", + "detected_microscope_type": "openhcsdata", + "handler_class": "OpenHCSMicroscopeHandler", + "parser_class": "ImageXpressFilenameParser", + "viewer_config_key": "napari_streaming_config", + "viewer_type": "napari", + "connection": { + "host": "127.0.0.1", + "port": 6609, + "transport_mode": "tcp", + "persistent": true + }, + "requested_paths": [], + "resolved_records": [ + { + "kind": "image", + "key": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w1_z001_t001.tif", + "metadata": { + "filename": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w1_z001_t001.tif", + "virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w1_z001_t001.tif", + "full_virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w1_z001_t001.tif", + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w1_z001_t001.tif", + "type": "Image", + "OpenHCSSourceVoxelSpacingZYX": "1.3555999999999999,1.3555999999999999", + "OpenHCSSourceVoxelSpacingUnit": "micrometers", + "site": 1, + "channel": 1, + "z_index": 1, + "timepoint": 1, + "well": "A01", + "extension": ".tif", + "size": "2.3 KB", + "modified": "2026-10-04T00:10:26" + }, + "virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w1_z001_t001.tif", + "full_virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w1_z001_t001.tif", + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w1_z001_t001.tif", + "relative_path": null, + "full_path": null, + "file_format": null, + "preview": null + }, + { + "kind": "image", + "key": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w2_z001_t001.tif", + "metadata": { + "filename": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w2_z001_t001.tif", + "virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w2_z001_t001.tif", + "full_virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w2_z001_t001.tif", + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w2_z001_t001.tif", + "type": "Image", + "OpenHCSSourceVoxelSpacingZYX": "1.3555999999999999,1.3555999999999999", + "OpenHCSSourceVoxelSpacingUnit": "micrometers", + "site": 1, + "channel": 2, + "z_index": 1, + "timepoint": 1, + "well": "A01", + "extension": ".tif", + "size": "2.3 KB", + "modified": "2026-10-04T00:10:26" + }, + "virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w2_z001_t001.tif", + "full_virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w2_z001_t001.tif", + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w2_z001_t001.tif", + "relative_path": null, + "full_path": null, + "file_format": null, + "preview": null + } + ], + "streamed_image_paths": [ + "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w1_z001_t001.tif", + "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w2_z001_t001.tif" + ], + "streamed_roi_paths": [], + "skipped_records": [], + "status_messages": [ + "Loading chunk 1/1 (2 images)...", + "Streamed 2 images to Napari" + ] + }, + "isError": false + }, + "payload": { + "schema_version": "openhcs.agent.v1", + "errors": [], + "warnings": [], + "plate_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate", + "requested_microscope_type": "auto", + "detected_microscope_type": "openhcsdata", + "handler_class": "OpenHCSMicroscopeHandler", + "parser_class": "ImageXpressFilenameParser", + "viewer_config_key": "napari_streaming_config", + "viewer_type": "napari", + "connection": { + "host": "127.0.0.1", + "port": 6609, + "transport_mode": "tcp", + "persistent": true + }, + "requested_paths": [], + "resolved_records": [ + { + "kind": "image", + "key": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w1_z001_t001.tif", + "metadata": { + "filename": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w1_z001_t001.tif", + "virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w1_z001_t001.tif", + "full_virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w1_z001_t001.tif", + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w1_z001_t001.tif", + "type": "Image", + "OpenHCSSourceVoxelSpacingZYX": "1.3555999999999999,1.3555999999999999", + "OpenHCSSourceVoxelSpacingUnit": "micrometers", + "site": 1, + "channel": 1, + "z_index": 1, + "timepoint": 1, + "well": "A01", + "extension": ".tif", + "size": "2.3 KB", + "modified": "2026-10-04T00:10:26" + }, + "virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w1_z001_t001.tif", + "full_virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w1_z001_t001.tif", + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w1_z001_t001.tif", + "relative_path": null, + "full_path": null, + "file_format": null, + "preview": null + }, + { + "kind": "image", + "key": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w2_z001_t001.tif", + "metadata": { + "filename": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w2_z001_t001.tif", + "virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w2_z001_t001.tif", + "full_virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w2_z001_t001.tif", + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w2_z001_t001.tif", + "type": "Image", + "OpenHCSSourceVoxelSpacingZYX": "1.3555999999999999,1.3555999999999999", + "OpenHCSSourceVoxelSpacingUnit": "micrometers", + "site": 1, + "channel": 2, + "z_index": 1, + "timepoint": 1, + "well": "A01", + "extension": ".tif", + "size": "2.3 KB", + "modified": "2026-10-04T00:10:26" + }, + "virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w2_z001_t001.tif", + "full_virtual_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w2_z001_t001.tif", + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w2_z001_t001.tif", + "relative_path": null, + "full_path": null, + "file_format": null, + "preview": null + } + ], + "streamed_image_paths": [ + "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w1_z001_t001.tif", + "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w2_z001_t001.tif" + ], + "streamed_roi_paths": [], + "skipped_records": [], + "status_messages": [ + "Loading chunk 1/1 (2 images)...", + "Streamed 2 images to Napari" + ] + } + }, + { + "tool": "openhcs_query_plate_files", + "arguments": { + "plate_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate", + "result_directory": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/graph_results", + "kind": "result", + "limit": 10 + }, + "response": { + "content": [ + { + "type": "text", + "text": "{\n \"schema_version\": \"openhcs.agent.v1\",\n \"errors\": [],\n \"warnings\": [],\n \"plate_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate\",\n \"result_directory\": \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/graph_results\",\n \"requested_microscope_type\": \"auto\",\n \"detected_microscope_type\": null,\n \"handler_class\": null,\n \"parser_class\": null,\n \"total_count\": 1,\n \"returned_count\": 1,\n \"offset\": 0,\n \"limit\": 10,\n \"truncated_count\": 0,\n \"records\": [\n {\n \"kind\": \"result\",\n \"key\": \"A01_s001_w2_z001_t001_graph.graph.roi.zip\",\n \"metadata\": {\n \"filename\": \"A01_s001_w2_z001_t001_graph.graph.roi.zip\",\n \"type\": \"ROI\",\n \"size\": \"1.1 KB\",\n \"modified\": \"2026-10-04T00:10:26\",\n \"result_subdirectory\": \"graph_results\",\n \"full_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/graph_results/A01_s001_w2_z001_t001_graph.graph.roi.zip\"\n },\n \"virtual_path\": null,\n \"full_virtual_path\": null,\n \"source_path\": null,\n \"relative_path\": \"A01_s001_w2_z001_t001_graph.graph.roi.zip\",\n \"full_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/graph_results/A01_s001_w2_z001_t001_graph.graph.roi.zip\",\n \"file_format\": \"ROI\",\n \"preview\": {\n \"text_lines\": [],\n \"csv_columns\": [],\n \"csv_rows\": [],\n \"roi_count\": 2,\n \"roi_member_count\": 2,\n \"roi_duplicate_member_count\": 0,\n \"roi_area_min\": 0.0,\n \"roi_area_max\": 0.0,\n \"roi_area_mean\": 0.0,\n \"roi_examples\": [\n {\n \"shape_count\": 1,\n \"label\": 1,\n \"area\": 0.0,\n \"centroid\": [\n 3.75,\n 6.5\n ]\n },\n {\n \"shape_count\": 1,\n \"label\": 2,\n \"area\": 0.0,\n \"centroid\": [\n 6.25,\n 11.0\n ]\n }\n ],\n \"truncated\": false,\n \"omitted_reason\": null\n }\n }\n ]\n}" + } + ], + "structuredContent": { + "schema_version": "openhcs.agent.v1", + "errors": [], + "warnings": [], + "plate_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate", + "result_directory": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/graph_results", + "requested_microscope_type": "auto", + "detected_microscope_type": null, + "handler_class": null, + "parser_class": null, + "total_count": 1, + "returned_count": 1, + "offset": 0, + "limit": 10, + "truncated_count": 0, + "records": [ + { + "kind": "result", + "key": "A01_s001_w2_z001_t001_graph.graph.roi.zip", + "metadata": { + "filename": "A01_s001_w2_z001_t001_graph.graph.roi.zip", + "type": "ROI", + "size": "1.1 KB", + "modified": "2026-10-04T00:10:26", + "result_subdirectory": "graph_results", + "full_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/graph_results/A01_s001_w2_z001_t001_graph.graph.roi.zip" + }, + "virtual_path": null, + "full_virtual_path": null, + "source_path": null, + "relative_path": "A01_s001_w2_z001_t001_graph.graph.roi.zip", + "full_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/graph_results/A01_s001_w2_z001_t001_graph.graph.roi.zip", + "file_format": "ROI", + "preview": { + "text_lines": [], + "csv_columns": [], + "csv_rows": [], + "roi_count": 2, + "roi_member_count": 2, + "roi_duplicate_member_count": 0, + "roi_area_min": 0.0, + "roi_area_max": 0.0, + "roi_area_mean": 0.0, + "roi_examples": [ + { + "shape_count": 1, + "label": 1, + "area": 0.0, + "centroid": [ + 3.75, + 6.5 + ] + }, + { + "shape_count": 1, + "label": 2, + "area": 0.0, + "centroid": [ + 6.25, + 11.0 + ] + } + ], + "truncated": false, + "omitted_reason": null + } + } + ] + }, + "isError": false + }, + "payload": { + "schema_version": "openhcs.agent.v1", + "errors": [], + "warnings": [], + "plate_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate", + "result_directory": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/graph_results", + "requested_microscope_type": "auto", + "detected_microscope_type": null, + "handler_class": null, + "parser_class": null, + "total_count": 1, + "returned_count": 1, + "offset": 0, + "limit": 10, + "truncated_count": 0, + "records": [ + { + "kind": "result", + "key": "A01_s001_w2_z001_t001_graph.graph.roi.zip", + "metadata": { + "filename": "A01_s001_w2_z001_t001_graph.graph.roi.zip", + "type": "ROI", + "size": "1.1 KB", + "modified": "2026-10-04T00:10:26", + "result_subdirectory": "graph_results", + "full_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/graph_results/A01_s001_w2_z001_t001_graph.graph.roi.zip" + }, + "virtual_path": null, + "full_virtual_path": null, + "source_path": null, + "relative_path": "A01_s001_w2_z001_t001_graph.graph.roi.zip", + "full_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/graph_results/A01_s001_w2_z001_t001_graph.graph.roi.zip", + "file_format": "ROI", + "preview": { + "text_lines": [], + "csv_columns": [], + "csv_rows": [], + "roi_count": 2, + "roi_member_count": 2, + "roi_duplicate_member_count": 0, + "roi_area_min": 0.0, + "roi_area_max": 0.0, + "roi_area_mean": 0.0, + "roi_examples": [ + { + "shape_count": 1, + "label": 1, + "area": 0.0, + "centroid": [ + 3.75, + 6.5 + ] + }, + { + "shape_count": 1, + "label": 2, + "area": 0.0, + "centroid": [ + 6.25, + 11.0 + ] + } + ], + "truncated": false, + "omitted_reason": null + } + } + ] + } + }, + { + "tool": "openhcs_stream_plate_files_to_viewer", + "arguments": { + "plate_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate", + "result_directory": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/graph_results", + "file_paths": [ + "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/graph_results/A01_s001_w2_z001_t001_graph.graph.roi.zip" + ], + "microscope_type": "auto", + "pattern_format": null, + "kind": "result", + "path_contains": null, + "well": null, + "limit": 1, + "viewer_config_key": "napari_streaming_config", + "display_config": null, + "host": "127.0.0.1", + "port": 6609, + "transport_mode": "tcp", + "persistent": true, + "fresh_viewer": false, + "source_receipt": null + }, + "response": { + "content": [ + { + "type": "text", + "text": "{\n \"schema_version\": \"openhcs.agent.v1\",\n \"errors\": [],\n \"warnings\": [],\n \"plate_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate\",\n \"requested_microscope_type\": \"auto\",\n \"detected_microscope_type\": \"openhcsdata\",\n \"handler_class\": \"OpenHCSMicroscopeHandler\",\n \"parser_class\": \"ImageXpressFilenameParser\",\n \"viewer_config_key\": \"napari_streaming_config\",\n \"viewer_type\": \"napari\",\n \"connection\": {\n \"host\": \"127.0.0.1\",\n \"port\": 6609,\n \"transport_mode\": \"tcp\",\n \"persistent\": true\n },\n \"requested_paths\": [\n \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/graph_results/A01_s001_w2_z001_t001_graph.graph.roi.zip\"\n ],\n \"resolved_records\": [\n {\n \"kind\": \"result\",\n \"key\": \"A01_s001_w2_z001_t001_graph.graph.roi.zip\",\n \"metadata\": {\n \"filename\": \"A01_s001_w2_z001_t001_graph.graph.roi.zip\",\n \"type\": \"ROI\",\n \"size\": \"1.1 KB\",\n \"modified\": \"2026-10-04T00:10:26\",\n \"result_subdirectory\": \"graph_results\",\n \"full_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/graph_results/A01_s001_w2_z001_t001_graph.graph.roi.zip\"\n },\n \"virtual_path\": null,\n \"full_virtual_path\": null,\n \"source_path\": null,\n \"relative_path\": \"A01_s001_w2_z001_t001_graph.graph.roi.zip\",\n \"full_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/graph_results/A01_s001_w2_z001_t001_graph.graph.roi.zip\",\n \"file_format\": \"ROI\",\n \"preview\": null\n }\n ],\n \"streamed_image_paths\": [],\n \"streamed_roi_paths\": [\n \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/graph_results/A01_s001_w2_z001_t001_graph.graph.roi.zip\"\n ],\n \"skipped_records\": [],\n \"status_messages\": [\n \"Loading 1 ROI file(s) from disk...\",\n \"Loading ROIs: 1/1 file(s)...\",\n \"Streaming 1 ROI file(s) to Napari...\",\n \"Streamed 1 ROI file(s) to Napari on port 6609\"\n ]\n}" + } + ], + "structuredContent": { + "schema_version": "openhcs.agent.v1", + "errors": [], + "warnings": [], + "plate_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate", + "requested_microscope_type": "auto", + "detected_microscope_type": "openhcsdata", + "handler_class": "OpenHCSMicroscopeHandler", + "parser_class": "ImageXpressFilenameParser", + "viewer_config_key": "napari_streaming_config", + "viewer_type": "napari", + "connection": { + "host": "127.0.0.1", + "port": 6609, + "transport_mode": "tcp", + "persistent": true + }, + "requested_paths": [ + "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/graph_results/A01_s001_w2_z001_t001_graph.graph.roi.zip" + ], + "resolved_records": [ + { + "kind": "result", + "key": "A01_s001_w2_z001_t001_graph.graph.roi.zip", + "metadata": { + "filename": "A01_s001_w2_z001_t001_graph.graph.roi.zip", + "type": "ROI", + "size": "1.1 KB", + "modified": "2026-10-04T00:10:26", + "result_subdirectory": "graph_results", + "full_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/graph_results/A01_s001_w2_z001_t001_graph.graph.roi.zip" + }, + "virtual_path": null, + "full_virtual_path": null, + "source_path": null, + "relative_path": "A01_s001_w2_z001_t001_graph.graph.roi.zip", + "full_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/graph_results/A01_s001_w2_z001_t001_graph.graph.roi.zip", + "file_format": "ROI", + "preview": null + } + ], + "streamed_image_paths": [], + "streamed_roi_paths": [ + "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/graph_results/A01_s001_w2_z001_t001_graph.graph.roi.zip" + ], + "skipped_records": [], + "status_messages": [ + "Loading 1 ROI file(s) from disk...", + "Loading ROIs: 1/1 file(s)...", + "Streaming 1 ROI file(s) to Napari...", + "Streamed 1 ROI file(s) to Napari on port 6609" + ] + }, + "isError": false + }, + "payload": { + "schema_version": "openhcs.agent.v1", + "errors": [], + "warnings": [], + "plate_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate", + "requested_microscope_type": "auto", + "detected_microscope_type": "openhcsdata", + "handler_class": "OpenHCSMicroscopeHandler", + "parser_class": "ImageXpressFilenameParser", + "viewer_config_key": "napari_streaming_config", + "viewer_type": "napari", + "connection": { + "host": "127.0.0.1", + "port": 6609, + "transport_mode": "tcp", + "persistent": true + }, + "requested_paths": [ + "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/graph_results/A01_s001_w2_z001_t001_graph.graph.roi.zip" + ], + "resolved_records": [ + { + "kind": "result", + "key": "A01_s001_w2_z001_t001_graph.graph.roi.zip", + "metadata": { + "filename": "A01_s001_w2_z001_t001_graph.graph.roi.zip", + "type": "ROI", + "size": "1.1 KB", + "modified": "2026-10-04T00:10:26", + "result_subdirectory": "graph_results", + "full_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/graph_results/A01_s001_w2_z001_t001_graph.graph.roi.zip" + }, + "virtual_path": null, + "full_virtual_path": null, + "source_path": null, + "relative_path": "A01_s001_w2_z001_t001_graph.graph.roi.zip", + "full_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/graph_results/A01_s001_w2_z001_t001_graph.graph.roi.zip", + "file_format": "ROI", + "preview": null + } + ], + "streamed_image_paths": [], + "streamed_roi_paths": [ + "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/graph_results/A01_s001_w2_z001_t001_graph.graph.roi.zip" + ], + "skipped_records": [], + "status_messages": [ + "Loading 1 ROI file(s) from disk...", + "Loading ROIs: 1/1 file(s)...", + "Streaming 1 ROI file(s) to Napari...", + "Streamed 1 ROI file(s) to Napari on port 6609" + ] + } + }, + { + "tool": "openhcs_get_viewer_window_state", + "arguments": { + "host": "127.0.0.1", + "port": 6609, + "transport_mode": "tcp", + "route_key": null, + "include_component_values": true, + "max_component_values_per_layer": null, + "include_payload_summaries": true, + "max_payload_summaries_per_layer": null, + "include_response": true + }, + "response": { + "content": [ + { + "type": "text", + "text": "{\n \"connection\": {\n \"host\": \"127.0.0.1\",\n \"port\": 6609,\n \"transport_mode\": \"tcp\",\n \"persistent\": true\n },\n \"schema_version\": \"openhcs.agent.v1\",\n \"errors\": [],\n \"warnings\": [],\n \"observed\": true,\n \"viewer\": {\n \"viewer_type\": \"napari\",\n \"title\": \"OpenHCS Napari Visualization\"\n },\n \"layer_count\": 3,\n \"layers\": [\n {\n \"route_key\": \"origin_manual_kind_manual_projection_selected_images_8c7357d46ccc38823ca9e68096baf86f25c3004b61b63ba1eef9adea41d34fb8_scalar_stack\",\n \"title\": \"selected_images image stack\",\n \"mounted\": true,\n \"item_count\": 1,\n \"producer_identities\": [\n {\n \"origin\": \"manual\",\n \"output_kind\": \"manual\",\n \"output_key\": \"selected_images\",\n \"projection_key\": \"selected_images_8c7357d46ccc38823ca9e68096baf86f25c3004b61b63ba1eef9adea41d34fb8\",\n \"step_name\": null,\n \"pipeline_position\": null,\n \"step_scope_id\": null,\n \"invocation_key\": null,\n \"artifact_kind\": null\n }\n ],\n \"axis_labels\": [\n \"site\",\n \"channel\",\n \"z_index\",\n \"timepoint\",\n \"well\",\n \"y\",\n \"x\"\n ],\n \"stack_axes\": [\n \"channel\"\n ],\n \"pending_update\": false,\n \"data_types\": [\n \"image\"\n ],\n \"component_values\": [\n {\n \"site\": 1,\n \"z_index\": 1,\n \"timepoint\": 1,\n \"well\": \"A01\"\n }\n ],\n \"component_value_count\": 1,\n \"component_values_truncated\": false,\n \"payload_summaries\": [\n {\n \"shape\": [\n 2,\n 32,\n 32\n ],\n \"dtype\": \"uint16\",\n \"size\": 2048,\n \"nonzero_count\": 308,\n \"min\": 0,\n \"max\": 22,\n \"nonzero_min_coordinate\": [\n 0,\n 3,\n 4\n ],\n \"nonzero_max_coordinate\": [\n 1,\n 24,\n 27\n ],\n \"nonzero_example_coordinates\": [\n [\n 0,\n 3,\n 4\n ],\n [\n 0,\n 5,\n 4\n ],\n [\n 0,\n 7,\n 4\n ],\n [\n 0,\n 9,\n 5\n ],\n [\n 0,\n 11,\n 5\n ],\n [\n 0,\n 18,\n 24\n ],\n [\n 0,\n 21,\n 20\n ],\n [\n 0,\n 23,\n 25\n ],\n [\n 1,\n 3,\n 13\n ],\n [\n 1,\n 6,\n 4\n ],\n [\n 1,\n 8,\n 4\n ],\n [\n 1,\n 10,\n 5\n ],\n [\n 1,\n 17,\n 21\n ],\n [\n 1,\n 19,\n 26\n ],\n [\n 1,\n 22,\n 22\n ],\n [\n 1,\n 24,\n 27\n ]\n ],\n \"source_voxel_spacing\": {\n \"values_zyx\": [\n 1.3556,\n 1.3556\n ],\n \"unit\": \"micrometers\"\n },\n \"spatial_origin_yx\": [\n 0,\n 0\n ],\n \"source_spatial_shape_yx\": [\n 32,\n 32\n ],\n \"aggregate_component_values\": {\n \"channel\": [\n 2,\n 1\n ]\n },\n \"data_type\": \"image\",\n \"path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/stacked_labels/A01_s001_w2_z001_t001_Labels.tif\",\n \"components\": {\n \"site\": 1,\n \"z_index\": 1,\n \"timepoint\": 1,\n \"well\": \"A01\"\n },\n \"payload_type\": \"ndarray\"\n }\n ],\n \"payload_summary_count\": 1,\n \"payload_summaries_truncated\": false,\n \"axis_offsets\": [\n 0\n ],\n \"scalar_labels\": [\n \"Site 1\",\n \"Z 1\",\n \"T 1\",\n \"Well A01\"\n ],\n \"labels\": {\n \"channel\": [\n \"Ch 1\",\n \"Ch 2\"\n ]\n },\n \"axis_component_values\": {\n \"channel\": [\n 1,\n 2\n ]\n },\n \"routed_component_values\": {\n \"channel\": [\n 1,\n 2\n ]\n },\n \"routed_component_coordinates\": [\n [\n 1\n ],\n [\n 2\n ]\n ],\n \"data_shape\": [\n 1,\n 2,\n 1,\n 1,\n 1,\n 32,\n 32\n ],\n \"native_transform\": {\n \"scale\": [\n 1.0,\n 1.0,\n 1.0,\n 1.0,\n 1.0,\n 1.3556,\n 1.3556\n ],\n \"translate\": [\n 0.0,\n 0.0,\n 0.0,\n 0.0,\n 0.0,\n 0.0,\n 0.0\n ]\n },\n \"native_intensity\": {\n \"contrast_limits\": [\n 0.0,\n 22.0\n ],\n \"gamma\": 1.0\n },\n \"visible\": true,\n \"selected\": true,\n \"feature_row_count\": 0,\n \"selected_data_indices\": []\n },\n {\n \"route_key\": \"origin_manual_kind_manual_projection_selected_images_e83ddc2185a63aca4b85ec471143f61c8f4eabdb08df3557ca21f2bddcda60b9\",\n \"title\": \"selected_images\",\n \"mounted\": true,\n \"item_count\": 2,\n \"producer_identities\": [\n {\n \"origin\": \"manual\",\n \"output_kind\": \"manual\",\n \"output_key\": \"selected_images\",\n \"projection_key\": \"selected_images_e83ddc2185a63aca4b85ec471143f61c8f4eabdb08df3557ca21f2bddcda60b9\",\n \"step_name\": null,\n \"pipeline_position\": null,\n \"step_scope_id\": null,\n \"invocation_key\": null,\n \"artifact_kind\": null\n }\n ],\n \"axis_labels\": [\n \"site\",\n \"channel\",\n \"z_index\",\n \"timepoint\",\n \"well\",\n \"y\",\n \"x\"\n ],\n \"stack_axes\": [\n \"channel\"\n ],\n \"pending_update\": false,\n \"data_types\": [\n \"image\"\n ],\n \"component_values\": [\n {\n \"site\": 1,\n \"channel\": 1,\n \"z_index\": 1,\n \"timepoint\": 1,\n \"well\": \"A01\"\n },\n {\n \"site\": 1,\n \"channel\": 2,\n \"z_index\": 1,\n \"timepoint\": 1,\n \"well\": \"A01\"\n }\n ],\n \"component_value_count\": 2,\n \"component_values_truncated\": false,\n \"payload_summaries\": [\n {\n \"shape\": [\n 32,\n 32\n ],\n \"dtype\": \"uint16\",\n \"size\": 1024,\n \"nonzero_count\": 1024,\n \"min\": 100,\n \"max\": 1123,\n \"nonzero_min_coordinate\": [\n 0,\n 0\n ],\n \"nonzero_max_coordinate\": [\n 31,\n 31\n ],\n \"nonzero_example_coordinates\": [\n [\n 0,\n 0\n ],\n [\n 2,\n 4\n ],\n [\n 4,\n 8\n ],\n [\n 6,\n 12\n ],\n [\n 8,\n 16\n ],\n [\n 10,\n 21\n ],\n [\n 12,\n 25\n ],\n [\n 14,\n 29\n ],\n [\n 17,\n 1\n ],\n [\n 19,\n 5\n ],\n [\n 21,\n 10\n ],\n [\n 23,\n 14\n ],\n [\n 25,\n 18\n ],\n [\n 27,\n 22\n ],\n [\n 29,\n 26\n ],\n [\n 31,\n 31\n ]\n ],\n \"source_voxel_spacing\": {\n \"values_zyx\": [\n 1.3556,\n 1.3556\n ],\n \"unit\": \"micrometers\"\n },\n \"spatial_origin_yx\": [\n 0,\n 0\n ],\n \"source_spatial_shape_yx\": [\n 32,\n 32\n ],\n \"data_type\": \"image\",\n \"path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w1_z001_t001.tif\",\n \"components\": {\n \"site\": 1,\n \"channel\": 1,\n \"z_index\": 1,\n \"timepoint\": 1,\n \"well\": \"A01\"\n },\n \"payload_type\": \"ndarray\"\n },\n {\n \"shape\": [\n 32,\n 32\n ],\n \"dtype\": \"uint16\",\n \"size\": 1024,\n \"nonzero_count\": 1024,\n \"min\": 200,\n \"max\": 1223,\n \"nonzero_min_coordinate\": [\n 0,\n 0\n ],\n \"nonzero_max_coordinate\": [\n 31,\n 31\n ],\n \"nonzero_example_coordinates\": [\n [\n 0,\n 0\n ],\n [\n 2,\n 4\n ],\n [\n 4,\n 8\n ],\n [\n 6,\n 12\n ],\n [\n 8,\n 16\n ],\n [\n 10,\n 21\n ],\n [\n 12,\n 25\n ],\n [\n 14,\n 29\n ],\n [\n 17,\n 1\n ],\n [\n 19,\n 5\n ],\n [\n 21,\n 10\n ],\n [\n 23,\n 14\n ],\n [\n 25,\n 18\n ],\n [\n 27,\n 22\n ],\n [\n 29,\n 26\n ],\n [\n 31,\n 31\n ]\n ],\n \"source_voxel_spacing\": {\n \"values_zyx\": [\n 1.3556,\n 1.3556\n ],\n \"unit\": \"micrometers\"\n },\n \"spatial_origin_yx\": [\n 0,\n 0\n ],\n \"source_spatial_shape_yx\": [\n 32,\n 32\n ],\n \"data_type\": \"image\",\n \"path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w2_z001_t001.tif\",\n \"components\": {\n \"site\": 1,\n \"channel\": 2,\n \"z_index\": 1,\n \"timepoint\": 1,\n \"well\": \"A01\"\n },\n \"payload_type\": \"ndarray\"\n }\n ],\n \"payload_summary_count\": 2,\n \"payload_summaries_truncated\": false,\n \"axis_offsets\": [\n 0\n ],\n \"scalar_labels\": [\n \"Site 1\",\n \"Z 1\",\n \"T 1\",\n \"Well A01\"\n ],\n \"labels\": {\n \"channel\": [\n \"Ch 1\",\n \"Ch 2\"\n ]\n },\n \"axis_component_values\": {\n \"channel\": [\n 1,\n 2\n ]\n },\n \"routed_component_values\": {\n \"channel\": [\n 1,\n 2\n ]\n },\n \"routed_component_coordinates\": [\n [\n 1\n ],\n [\n 2\n ]\n ],\n \"data_shape\": [\n 1,\n 2,\n 1,\n 1,\n 1,\n 32,\n 32\n ],\n \"native_transform\": {\n \"scale\": [\n 1.0,\n 1.0,\n 1.0,\n 1.0,\n 1.0,\n 1.3556,\n 1.3556\n ],\n \"translate\": [\n 0.0,\n 0.0,\n 0.0,\n 0.0,\n 0.0,\n 0.0,\n 0.0\n ]\n },\n \"native_intensity\": {\n \"contrast_limits\": [\n 100.0,\n 1223.0\n ],\n \"gamma\": 1.0\n },\n \"visible\": true,\n \"selected\": false,\n \"feature_row_count\": 0,\n \"selected_data_indices\": []\n },\n {\n \"route_key\": \"origin_manual_kind_manual_projection_A01_s001_w2_z001_t001_graph.graph.roi.zip_shapes\",\n \"title\": \"A01_s001_w2_z001_t001_graph.graph.roi.zip ROIs\",\n \"mounted\": true,\n \"item_count\": 1,\n \"producer_identities\": [\n {\n \"origin\": \"manual\",\n \"output_kind\": \"manual\",\n \"output_key\": \"A01_s001_w2_z001_t001_graph.graph.roi.zip\",\n \"projection_key\": \"A01_s001_w2_z001_t001_graph.graph.roi.zip\",\n \"step_name\": null,\n \"pipeline_position\": null,\n \"step_scope_id\": null,\n \"invocation_key\": null,\n \"artifact_kind\": null\n }\n ],\n \"axis_labels\": [\n \"site\",\n \"channel\",\n \"z_index\",\n \"timepoint\",\n \"well\",\n \"y\",\n \"x\"\n ],\n \"stack_axes\": [\n \"channel\"\n ],\n \"pending_update\": false,\n \"data_types\": [\n \"shapes\"\n ],\n \"component_values\": [\n {\n \"site\": 1,\n \"channel\": 2,\n \"z_index\": 1,\n \"timepoint\": 1,\n \"well\": \"A01\"\n }\n ],\n \"component_value_count\": 1,\n \"component_values_truncated\": false,\n \"payload_summaries\": [\n {\n \"nonzero_count\": 2,\n \"item_count\": 2,\n \"shape_payload_count\": 2,\n \"missing_source_spatial_shape_count\": 2,\n \"shape_coordinate_count\": 4,\n \"shape_out_of_source_bounds_count\": 0,\n \"shape_coordinate_bounds_yx\": {\n \"min_yx\": [\n 2.25,\n 3.5\n ],\n \"max_yx\": [\n 7.25,\n 12.5\n ],\n \"coordinate_count\": 4\n },\n \"source_voxel_spacing\": {\n \"values_zyx\": [\n 1.3556,\n 1.3556\n ],\n \"unit\": \"micrometers\"\n },\n \"data_type\": \"shapes\",\n \"path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/graph_results/A01_s001_w2_z001_t001_graph.graph.roi.zip\",\n \"components\": {\n \"site\": 1,\n \"channel\": 2,\n \"z_index\": 1,\n \"timepoint\": 1,\n \"well\": \"A01\"\n },\n \"payload_type\": \"list\"\n }\n ],\n \"payload_summary_count\": 1,\n \"payload_summaries_truncated\": false,\n \"axis_offsets\": [\n 1\n ],\n \"scalar_labels\": [\n \"Site 1\",\n \"Z 1\",\n \"T 1\",\n \"Well A01\"\n ],\n \"labels\": {\n \"channel\": [\n \"Ch 2\"\n ]\n },\n \"axis_component_values\": {\n \"channel\": [\n 2\n ]\n },\n \"routed_component_values\": {\n \"channel\": [\n 2\n ]\n },\n \"routed_component_coordinates\": [\n [\n 2\n ]\n ],\n \"data_shape\": [\n 2\n ],\n \"native_transform\": {\n \"scale\": [\n 1.0,\n 1.0,\n 1.0,\n 1.0,\n 1.0,\n 1.3556,\n 1.3556\n ],\n \"translate\": [\n 0.0,\n 1.0,\n 0.0,\n 0.0,\n 0.0,\n 0.0,\n 0.0\n ]\n },\n \"native_intensity\": null,\n \"visible\": true,\n \"selected\": false,\n \"feature_row_count\": 2,\n \"selected_data_indices\": []\n }\n ],\n \"active_dimension_label_route\": \"origin_manual_kind_manual_projection_selected_images_8c7357d46ccc38823ca9e68096baf86f25c3004b61b63ba1eef9adea41d34fb8_scalar_stack\",\n \"viewer_ndim\": 7,\n \"current_step\": [\n 0,\n 0,\n 0,\n 0,\n 0,\n 15,\n 15\n ],\n \"axis_labels\": [\n \"site\",\n \"channel\",\n \"z_index\",\n \"timepoint\",\n \"well\",\n \"y\",\n \"x\"\n ],\n \"component_group_count\": 3,\n \"component_item_count\": 4,\n \"native_viewport\": {\n \"center\": [\n 0.0,\n 21.011799999999997,\n 21.011799999999997\n ],\n \"zoom\": 6.635668707583358\n },\n \"native_dimensions\": {\n \"order\": [\n 0,\n 1,\n 2,\n 3,\n 4,\n 5,\n 6\n ],\n \"ndisplay\": 2,\n \"displayed_axes\": [\n \"y\",\n \"x\"\n ],\n \"point\": [\n 0.0,\n 0.0,\n 0.0,\n 0.0,\n 0.0,\n 20.334,\n 20.334\n ],\n \"camera_angles\": [\n 0.0,\n 0.0,\n 0.0\n ],\n \"canvas_size\": [\n 643,\n 478\n ]\n },\n \"response\": {\n \"type\": \"state_ack\",\n \"status\": \"success\",\n \"viewer\": {\n \"type\": \"napari\",\n \"title\": \"OpenHCS Napari Visualization\"\n },\n \"layer_count\": 3,\n \"layers\": [\n {\n \"route_key\": \"origin_manual_kind_manual_projection_selected_images_8c7357d46ccc38823ca9e68096baf86f25c3004b61b63ba1eef9adea41d34fb8_scalar_stack\",\n \"producer_identities\": [\n {\n \"origin\": \"manual\",\n \"output_kind\": \"manual\",\n \"output_key\": \"selected_images\",\n \"projection_key\": \"selected_images_8c7357d46ccc38823ca9e68096baf86f25c3004b61b63ba1eef9adea41d34fb8\",\n \"step_name\": null,\n \"pipeline_position\": null,\n \"step_scope_id\": null,\n \"invocation_key\": null,\n \"artifact_kind\": null\n }\n ],\n \"title\": \"selected_images image stack\",\n \"mounted\": true,\n \"item_count\": 1,\n \"data_types\": [\n \"image\"\n ],\n \"component_values\": [\n {\n \"site\": 1,\n \"z_index\": 1,\n \"timepoint\": 1,\n \"well\": \"A01\"\n }\n ],\n \"component_value_count\": 1,\n \"component_values_truncated\": false,\n \"payload_summaries\": [\n {\n \"shape\": [\n 2,\n 32,\n 32\n ],\n \"dtype\": \"uint16\",\n \"size\": 2048,\n \"nonzero_count\": 308,\n \"min\": 0,\n \"max\": 22,\n \"nonzero_min_coordinate\": [\n 0,\n 3,\n 4\n ],\n \"nonzero_max_coordinate\": [\n 1,\n 24,\n 27\n ],\n \"nonzero_example_coordinates\": [\n [\n 0,\n 3,\n 4\n ],\n [\n 0,\n 5,\n 4\n ],\n [\n 0,\n 7,\n 4\n ],\n [\n 0,\n 9,\n 5\n ],\n [\n 0,\n 11,\n 5\n ],\n [\n 0,\n 18,\n 24\n ],\n [\n 0,\n 21,\n 20\n ],\n [\n 0,\n 23,\n 25\n ],\n [\n 1,\n 3,\n 13\n ],\n [\n 1,\n 6,\n 4\n ],\n [\n 1,\n 8,\n 4\n ],\n [\n 1,\n 10,\n 5\n ],\n [\n 1,\n 17,\n 21\n ],\n [\n 1,\n 19,\n 26\n ],\n [\n 1,\n 22,\n 22\n ],\n [\n 1,\n 24,\n 27\n ]\n ],\n \"source_voxel_spacing\": {\n \"values_zyx\": [\n 1.3556,\n 1.3556\n ],\n \"unit\": \"micrometers\"\n },\n \"spatial_origin_yx\": [\n 0,\n 0\n ],\n \"source_spatial_shape_yx\": [\n 32,\n 32\n ],\n \"aggregate_component_values\": {\n \"channel\": [\n 2,\n 1\n ]\n },\n \"data_type\": \"image\",\n \"path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/stacked_labels/A01_s001_w2_z001_t001_Labels.tif\",\n \"components\": {\n \"site\": 1,\n \"z_index\": 1,\n \"timepoint\": 1,\n \"well\": \"A01\"\n },\n \"payload_type\": \"ndarray\"\n }\n ],\n \"payload_summary_count\": 1,\n \"payload_summaries_truncated\": false,\n \"axis_labels\": [\n \"site\",\n \"channel\",\n \"z_index\",\n \"timepoint\",\n \"well\",\n \"y\",\n \"x\"\n ],\n \"stack_axes\": [\n \"channel\"\n ],\n \"axis_offsets\": [\n 0\n ],\n \"scalar_labels\": [\n \"Site 1\",\n \"Z 1\",\n \"T 1\",\n \"Well A01\"\n ],\n \"labels\": {\n \"channel\": [\n \"Ch 1\",\n \"Ch 2\"\n ]\n },\n \"axis_component_values\": {\n \"channel\": [\n 1,\n 2\n ]\n },\n \"routed_component_values\": {\n \"channel\": [\n 1,\n 2\n ]\n },\n \"routed_component_coordinates\": [\n [\n 1\n ],\n [\n 2\n ]\n ],\n \"data_shape\": [\n 1,\n 2,\n 1,\n 1,\n 1,\n 32,\n 32\n ],\n \"native_transform\": {\n \"scale\": [\n 1.0,\n 1.0,\n 1.0,\n 1.0,\n 1.0,\n 1.3556,\n 1.3556\n ],\n \"translate\": [\n 0.0,\n 0.0,\n 0.0,\n 0.0,\n 0.0,\n 0.0,\n 0.0\n ]\n },\n \"native_intensity\": {\n \"contrast_limits\": [\n 0.0,\n 22.0\n ],\n \"gamma\": 1.0\n },\n \"visible\": true,\n \"selected\": true,\n \"feature_row_count\": 0,\n \"selected_data_indices\": [],\n \"pending_update\": false\n },\n {\n \"route_key\": \"origin_manual_kind_manual_projection_selected_images_e83ddc2185a63aca4b85ec471143f61c8f4eabdb08df3557ca21f2bddcda60b9\",\n \"producer_identities\": [\n {\n \"origin\": \"manual\",\n \"output_kind\": \"manual\",\n \"output_key\": \"selected_images\",\n \"projection_key\": \"selected_images_e83ddc2185a63aca4b85ec471143f61c8f4eabdb08df3557ca21f2bddcda60b9\",\n \"step_name\": null,\n \"pipeline_position\": null,\n \"step_scope_id\": null,\n \"invocation_key\": null,\n \"artifact_kind\": null\n }\n ],\n \"title\": \"selected_images\",\n \"mounted\": true,\n \"item_count\": 2,\n \"data_types\": [\n \"image\"\n ],\n \"component_values\": [\n {\n \"site\": 1,\n \"channel\": 1,\n \"z_index\": 1,\n \"timepoint\": 1,\n \"well\": \"A01\"\n },\n {\n \"site\": 1,\n \"channel\": 2,\n \"z_index\": 1,\n \"timepoint\": 1,\n \"well\": \"A01\"\n }\n ],\n \"component_value_count\": 2,\n \"component_values_truncated\": false,\n \"payload_summaries\": [\n {\n \"shape\": [\n 32,\n 32\n ],\n \"dtype\": \"uint16\",\n \"size\": 1024,\n \"nonzero_count\": 1024,\n \"min\": 100,\n \"max\": 1123,\n \"nonzero_min_coordinate\": [\n 0,\n 0\n ],\n \"nonzero_max_coordinate\": [\n 31,\n 31\n ],\n \"nonzero_example_coordinates\": [\n [\n 0,\n 0\n ],\n [\n 2,\n 4\n ],\n [\n 4,\n 8\n ],\n [\n 6,\n 12\n ],\n [\n 8,\n 16\n ],\n [\n 10,\n 21\n ],\n [\n 12,\n 25\n ],\n [\n 14,\n 29\n ],\n [\n 17,\n 1\n ],\n [\n 19,\n 5\n ],\n [\n 21,\n 10\n ],\n [\n 23,\n 14\n ],\n [\n 25,\n 18\n ],\n [\n 27,\n 22\n ],\n [\n 29,\n 26\n ],\n [\n 31,\n 31\n ]\n ],\n \"source_voxel_spacing\": {\n \"values_zyx\": [\n 1.3556,\n 1.3556\n ],\n \"unit\": \"micrometers\"\n },\n \"spatial_origin_yx\": [\n 0,\n 0\n ],\n \"source_spatial_shape_yx\": [\n 32,\n 32\n ],\n \"data_type\": \"image\",\n \"path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w1_z001_t001.tif\",\n \"components\": {\n \"site\": 1,\n \"channel\": 1,\n \"z_index\": 1,\n \"timepoint\": 1,\n \"well\": \"A01\"\n },\n \"payload_type\": \"ndarray\"\n },\n {\n \"shape\": [\n 32,\n 32\n ],\n \"dtype\": \"uint16\",\n \"size\": 1024,\n \"nonzero_count\": 1024,\n \"min\": 200,\n \"max\": 1223,\n \"nonzero_min_coordinate\": [\n 0,\n 0\n ],\n \"nonzero_max_coordinate\": [\n 31,\n 31\n ],\n \"nonzero_example_coordinates\": [\n [\n 0,\n 0\n ],\n [\n 2,\n 4\n ],\n [\n 4,\n 8\n ],\n [\n 6,\n 12\n ],\n [\n 8,\n 16\n ],\n [\n 10,\n 21\n ],\n [\n 12,\n 25\n ],\n [\n 14,\n 29\n ],\n [\n 17,\n 1\n ],\n [\n 19,\n 5\n ],\n [\n 21,\n 10\n ],\n [\n 23,\n 14\n ],\n [\n 25,\n 18\n ],\n [\n 27,\n 22\n ],\n [\n 29,\n 26\n ],\n [\n 31,\n 31\n ]\n ],\n \"source_voxel_spacing\": {\n \"values_zyx\": [\n 1.3556,\n 1.3556\n ],\n \"unit\": \"micrometers\"\n },\n \"spatial_origin_yx\": [\n 0,\n 0\n ],\n \"source_spatial_shape_yx\": [\n 32,\n 32\n ],\n \"data_type\": \"image\",\n \"path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w2_z001_t001.tif\",\n \"components\": {\n \"site\": 1,\n \"channel\": 2,\n \"z_index\": 1,\n \"timepoint\": 1,\n \"well\": \"A01\"\n },\n \"payload_type\": \"ndarray\"\n }\n ],\n \"payload_summary_count\": 2,\n \"payload_summaries_truncated\": false,\n \"axis_labels\": [\n \"site\",\n \"channel\",\n \"z_index\",\n \"timepoint\",\n \"well\",\n \"y\",\n \"x\"\n ],\n \"stack_axes\": [\n \"channel\"\n ],\n \"axis_offsets\": [\n 0\n ],\n \"scalar_labels\": [\n \"Site 1\",\n \"Z 1\",\n \"T 1\",\n \"Well A01\"\n ],\n \"labels\": {\n \"channel\": [\n \"Ch 1\",\n \"Ch 2\"\n ]\n },\n \"axis_component_values\": {\n \"channel\": [\n 1,\n 2\n ]\n },\n \"routed_component_values\": {\n \"channel\": [\n 1,\n 2\n ]\n },\n \"routed_component_coordinates\": [\n [\n 1\n ],\n [\n 2\n ]\n ],\n \"data_shape\": [\n 1,\n 2,\n 1,\n 1,\n 1,\n 32,\n 32\n ],\n \"native_transform\": {\n \"scale\": [\n 1.0,\n 1.0,\n 1.0,\n 1.0,\n 1.0,\n 1.3556,\n 1.3556\n ],\n \"translate\": [\n 0.0,\n 0.0,\n 0.0,\n 0.0,\n 0.0,\n 0.0,\n 0.0\n ]\n },\n \"native_intensity\": {\n \"contrast_limits\": [\n 100.0,\n 1223.0\n ],\n \"gamma\": 1.0\n },\n \"visible\": true,\n \"selected\": false,\n \"feature_row_count\": 0,\n \"selected_data_indices\": [],\n \"pending_update\": false\n },\n {\n \"route_key\": \"origin_manual_kind_manual_projection_A01_s001_w2_z001_t001_graph.graph.roi.zip_shapes\",\n \"producer_identities\": [\n {\n \"origin\": \"manual\",\n \"output_kind\": \"manual\",\n \"output_key\": \"A01_s001_w2_z001_t001_graph.graph.roi.zip\",\n \"projection_key\": \"A01_s001_w2_z001_t001_graph.graph.roi.zip\",\n \"step_name\": null,\n \"pipeline_position\": null,\n \"step_scope_id\": null,\n \"invocation_key\": null,\n \"artifact_kind\": null\n }\n ],\n \"title\": \"A01_s001_w2_z001_t001_graph.graph.roi.zip ROIs\",\n \"mounted\": true,\n \"item_count\": 1,\n \"data_types\": [\n \"shapes\"\n ],\n \"component_values\": [\n {\n \"site\": 1,\n \"channel\": 2,\n \"z_index\": 1,\n \"timepoint\": 1,\n \"well\": \"A01\"\n }\n ],\n \"component_value_count\": 1,\n \"component_values_truncated\": false,\n \"payload_summaries\": [\n {\n \"nonzero_count\": 2,\n \"item_count\": 2,\n \"shape_payload_count\": 2,\n \"missing_source_spatial_shape_count\": 2,\n \"shape_coordinate_count\": 4,\n \"shape_out_of_source_bounds_count\": 0,\n \"shape_coordinate_bounds_yx\": {\n \"min_yx\": [\n 2.25,\n 3.5\n ],\n \"max_yx\": [\n 7.25,\n 12.5\n ],\n \"coordinate_count\": 4\n },\n \"source_voxel_spacing\": {\n \"values_zyx\": [\n 1.3556,\n 1.3556\n ],\n \"unit\": \"micrometers\"\n },\n \"data_type\": \"shapes\",\n \"path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/graph_results/A01_s001_w2_z001_t001_graph.graph.roi.zip\",\n \"components\": {\n \"site\": 1,\n \"channel\": 2,\n \"z_index\": 1,\n \"timepoint\": 1,\n \"well\": \"A01\"\n },\n \"payload_type\": \"list\"\n }\n ],\n \"payload_summary_count\": 1,\n \"payload_summaries_truncated\": false,\n \"axis_labels\": [\n \"site\",\n \"channel\",\n \"z_index\",\n \"timepoint\",\n \"well\",\n \"y\",\n \"x\"\n ],\n \"stack_axes\": [\n \"channel\"\n ],\n \"axis_offsets\": [\n 1\n ],\n \"scalar_labels\": [\n \"Site 1\",\n \"Z 1\",\n \"T 1\",\n \"Well A01\"\n ],\n \"labels\": {\n \"channel\": [\n \"Ch 2\"\n ]\n },\n \"axis_component_values\": {\n \"channel\": [\n 2\n ]\n },\n \"routed_component_values\": {\n \"channel\": [\n 2\n ]\n },\n \"routed_component_coordinates\": [\n [\n 2\n ]\n ],\n \"data_shape\": [\n 2\n ],\n \"native_transform\": {\n \"scale\": [\n 1.0,\n 1.0,\n 1.0,\n 1.0,\n 1.0,\n 1.3556,\n 1.3556\n ],\n \"translate\": [\n 0.0,\n 1.0,\n 0.0,\n 0.0,\n 0.0,\n 0.0,\n 0.0\n ]\n },\n \"native_intensity\": null,\n \"visible\": true,\n \"selected\": false,\n \"feature_row_count\": 2,\n \"selected_data_indices\": [],\n \"pending_update\": false\n }\n ],\n \"native_viewport\": {\n \"center\": [\n 0.0,\n 21.011799999999997,\n 21.011799999999997\n ],\n \"zoom\": 6.635668707583358\n },\n \"native_dimensions\": {\n \"order\": [\n 0,\n 1,\n 2,\n 3,\n 4,\n 5,\n 6\n ],\n \"ndisplay\": 2,\n \"displayed_axes\": [\n \"y\",\n \"x\"\n ],\n \"point\": [\n 0.0,\n 0.0,\n 0.0,\n 0.0,\n 0.0,\n 20.334,\n 20.334\n ],\n \"camera_angles\": [\n 0.0,\n 0.0,\n 0.0\n ],\n \"canvas_size\": [\n 643,\n 478\n ]\n },\n \"active_dimension_label_route\": \"origin_manual_kind_manual_projection_selected_images_8c7357d46ccc38823ca9e68096baf86f25c3004b61b63ba1eef9adea41d34fb8_scalar_stack\",\n \"viewer_ndim\": 7,\n \"current_step\": [\n 0,\n 0,\n 0,\n 0,\n 0,\n 15,\n 15\n ],\n \"axis_labels\": [\n \"site\",\n \"channel\",\n \"z_index\",\n \"timepoint\",\n \"well\",\n \"y\",\n \"x\"\n ],\n \"component_group_count\": 3,\n \"component_item_count\": 4\n }\n}" + } + ], + "structuredContent": { + "connection": { + "host": "127.0.0.1", + "port": 6609, + "transport_mode": "tcp", + "persistent": true + }, + "schema_version": "openhcs.agent.v1", + "errors": [], + "warnings": [], + "observed": true, + "viewer": { + "viewer_type": "napari", + "title": "OpenHCS Napari Visualization" + }, + "layer_count": 3, + "layers": [ + { + "route_key": "origin_manual_kind_manual_projection_selected_images_8c7357d46ccc38823ca9e68096baf86f25c3004b61b63ba1eef9adea41d34fb8_scalar_stack", + "title": "selected_images image stack", + "mounted": true, + "item_count": 1, + "producer_identities": [ + { + "origin": "manual", + "output_kind": "manual", + "output_key": "selected_images", + "projection_key": "selected_images_8c7357d46ccc38823ca9e68096baf86f25c3004b61b63ba1eef9adea41d34fb8", + "step_name": null, + "pipeline_position": null, + "step_scope_id": null, + "invocation_key": null, + "artifact_kind": null + } + ], + "axis_labels": [ + "site", + "channel", + "z_index", + "timepoint", + "well", + "y", + "x" + ], + "stack_axes": [ + "channel" + ], + "pending_update": false, + "data_types": [ + "image" + ], + "component_values": [ + { + "site": 1, + "z_index": 1, + "timepoint": 1, + "well": "A01" + } + ], + "component_value_count": 1, + "component_values_truncated": false, + "payload_summaries": [ + { + "shape": [ + 2, + 32, + 32 + ], + "dtype": "uint16", + "size": 2048, + "nonzero_count": 308, + "min": 0, + "max": 22, + "nonzero_min_coordinate": [ + 0, + 3, + 4 + ], + "nonzero_max_coordinate": [ + 1, + 24, + 27 + ], + "nonzero_example_coordinates": [ + [ + 0, + 3, + 4 + ], + [ + 0, + 5, + 4 + ], + [ + 0, + 7, + 4 + ], + [ + 0, + 9, + 5 + ], + [ + 0, + 11, + 5 + ], + [ + 0, + 18, + 24 + ], + [ + 0, + 21, + 20 + ], + [ + 0, + 23, + 25 + ], + [ + 1, + 3, + 13 + ], + [ + 1, + 6, + 4 + ], + [ + 1, + 8, + 4 + ], + [ + 1, + 10, + 5 + ], + [ + 1, + 17, + 21 + ], + [ + 1, + 19, + 26 + ], + [ + 1, + 22, + 22 + ], + [ + 1, + 24, + 27 + ] + ], + "source_voxel_spacing": { + "values_zyx": [ + 1.3556, + 1.3556 + ], + "unit": "micrometers" + }, + "spatial_origin_yx": [ + 0, + 0 + ], + "source_spatial_shape_yx": [ + 32, + 32 + ], + "aggregate_component_values": { + "channel": [ + 2, + 1 + ] + }, + "data_type": "image", + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/stacked_labels/A01_s001_w2_z001_t001_Labels.tif", + "components": { + "site": 1, + "z_index": 1, + "timepoint": 1, + "well": "A01" + }, + "payload_type": "ndarray" + } + ], + "payload_summary_count": 1, + "payload_summaries_truncated": false, + "axis_offsets": [ + 0 + ], + "scalar_labels": [ + "Site 1", + "Z 1", + "T 1", + "Well A01" + ], + "labels": { + "channel": [ + "Ch 1", + "Ch 2" + ] + }, + "axis_component_values": { + "channel": [ + 1, + 2 + ] + }, + "routed_component_values": { + "channel": [ + 1, + 2 + ] + }, + "routed_component_coordinates": [ + [ + 1 + ], + [ + 2 + ] + ], + "data_shape": [ + 1, + 2, + 1, + 1, + 1, + 32, + 32 + ], + "native_transform": { + "scale": [ + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.3556, + 1.3556 + ], + "translate": [ + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0 + ] + }, + "native_intensity": { + "contrast_limits": [ + 0.0, + 22.0 + ], + "gamma": 1.0 + }, + "visible": true, + "selected": true, + "feature_row_count": 0, + "selected_data_indices": [] + }, + { + "route_key": "origin_manual_kind_manual_projection_selected_images_e83ddc2185a63aca4b85ec471143f61c8f4eabdb08df3557ca21f2bddcda60b9", + "title": "selected_images", + "mounted": true, + "item_count": 2, + "producer_identities": [ + { + "origin": "manual", + "output_kind": "manual", + "output_key": "selected_images", + "projection_key": "selected_images_e83ddc2185a63aca4b85ec471143f61c8f4eabdb08df3557ca21f2bddcda60b9", + "step_name": null, + "pipeline_position": null, + "step_scope_id": null, + "invocation_key": null, + "artifact_kind": null + } + ], + "axis_labels": [ + "site", + "channel", + "z_index", + "timepoint", + "well", + "y", + "x" + ], + "stack_axes": [ + "channel" + ], + "pending_update": false, + "data_types": [ + "image" + ], + "component_values": [ + { + "site": 1, + "channel": 1, + "z_index": 1, + "timepoint": 1, + "well": "A01" + }, + { + "site": 1, + "channel": 2, + "z_index": 1, + "timepoint": 1, + "well": "A01" + } + ], + "component_value_count": 2, + "component_values_truncated": false, + "payload_summaries": [ + { + "shape": [ + 32, + 32 + ], + "dtype": "uint16", + "size": 1024, + "nonzero_count": 1024, + "min": 100, + "max": 1123, + "nonzero_min_coordinate": [ + 0, + 0 + ], + "nonzero_max_coordinate": [ + 31, + 31 + ], + "nonzero_example_coordinates": [ + [ + 0, + 0 + ], + [ + 2, + 4 + ], + [ + 4, + 8 + ], + [ + 6, + 12 + ], + [ + 8, + 16 + ], + [ + 10, + 21 + ], + [ + 12, + 25 + ], + [ + 14, + 29 + ], + [ + 17, + 1 + ], + [ + 19, + 5 + ], + [ + 21, + 10 + ], + [ + 23, + 14 + ], + [ + 25, + 18 + ], + [ + 27, + 22 + ], + [ + 29, + 26 + ], + [ + 31, + 31 + ] + ], + "source_voxel_spacing": { + "values_zyx": [ + 1.3556, + 1.3556 + ], + "unit": "micrometers" + }, + "spatial_origin_yx": [ + 0, + 0 + ], + "source_spatial_shape_yx": [ + 32, + 32 + ], + "data_type": "image", + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w1_z001_t001.tif", + "components": { + "site": 1, + "channel": 1, + "z_index": 1, + "timepoint": 1, + "well": "A01" + }, + "payload_type": "ndarray" + }, + { + "shape": [ + 32, + 32 + ], + "dtype": "uint16", + "size": 1024, + "nonzero_count": 1024, + "min": 200, + "max": 1223, + "nonzero_min_coordinate": [ + 0, + 0 + ], + "nonzero_max_coordinate": [ + 31, + 31 + ], + "nonzero_example_coordinates": [ + [ + 0, + 0 + ], + [ + 2, + 4 + ], + [ + 4, + 8 + ], + [ + 6, + 12 + ], + [ + 8, + 16 + ], + [ + 10, + 21 + ], + [ + 12, + 25 + ], + [ + 14, + 29 + ], + [ + 17, + 1 + ], + [ + 19, + 5 + ], + [ + 21, + 10 + ], + [ + 23, + 14 + ], + [ + 25, + 18 + ], + [ + 27, + 22 + ], + [ + 29, + 26 + ], + [ + 31, + 31 + ] + ], + "source_voxel_spacing": { + "values_zyx": [ + 1.3556, + 1.3556 + ], + "unit": "micrometers" + }, + "spatial_origin_yx": [ + 0, + 0 + ], + "source_spatial_shape_yx": [ + 32, + 32 + ], + "data_type": "image", + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w2_z001_t001.tif", + "components": { + "site": 1, + "channel": 2, + "z_index": 1, + "timepoint": 1, + "well": "A01" + }, + "payload_type": "ndarray" + } + ], + "payload_summary_count": 2, + "payload_summaries_truncated": false, + "axis_offsets": [ + 0 + ], + "scalar_labels": [ + "Site 1", + "Z 1", + "T 1", + "Well A01" + ], + "labels": { + "channel": [ + "Ch 1", + "Ch 2" + ] + }, + "axis_component_values": { + "channel": [ + 1, + 2 + ] + }, + "routed_component_values": { + "channel": [ + 1, + 2 + ] + }, + "routed_component_coordinates": [ + [ + 1 + ], + [ + 2 + ] + ], + "data_shape": [ + 1, + 2, + 1, + 1, + 1, + 32, + 32 + ], + "native_transform": { + "scale": [ + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.3556, + 1.3556 + ], + "translate": [ + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0 + ] + }, + "native_intensity": { + "contrast_limits": [ + 100.0, + 1223.0 + ], + "gamma": 1.0 + }, + "visible": true, + "selected": false, + "feature_row_count": 0, + "selected_data_indices": [] + }, + { + "route_key": "origin_manual_kind_manual_projection_A01_s001_w2_z001_t001_graph.graph.roi.zip_shapes", + "title": "A01_s001_w2_z001_t001_graph.graph.roi.zip ROIs", + "mounted": true, + "item_count": 1, + "producer_identities": [ + { + "origin": "manual", + "output_kind": "manual", + "output_key": "A01_s001_w2_z001_t001_graph.graph.roi.zip", + "projection_key": "A01_s001_w2_z001_t001_graph.graph.roi.zip", + "step_name": null, + "pipeline_position": null, + "step_scope_id": null, + "invocation_key": null, + "artifact_kind": null + } + ], + "axis_labels": [ + "site", + "channel", + "z_index", + "timepoint", + "well", + "y", + "x" + ], + "stack_axes": [ + "channel" + ], + "pending_update": false, + "data_types": [ + "shapes" + ], + "component_values": [ + { + "site": 1, + "channel": 2, + "z_index": 1, + "timepoint": 1, + "well": "A01" + } + ], + "component_value_count": 1, + "component_values_truncated": false, + "payload_summaries": [ + { + "nonzero_count": 2, + "item_count": 2, + "shape_payload_count": 2, + "missing_source_spatial_shape_count": 2, + "shape_coordinate_count": 4, + "shape_out_of_source_bounds_count": 0, + "shape_coordinate_bounds_yx": { + "min_yx": [ + 2.25, + 3.5 + ], + "max_yx": [ + 7.25, + 12.5 + ], + "coordinate_count": 4 + }, + "source_voxel_spacing": { + "values_zyx": [ + 1.3556, + 1.3556 + ], + "unit": "micrometers" + }, + "data_type": "shapes", + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/graph_results/A01_s001_w2_z001_t001_graph.graph.roi.zip", + "components": { + "site": 1, + "channel": 2, + "z_index": 1, + "timepoint": 1, + "well": "A01" + }, + "payload_type": "list" + } + ], + "payload_summary_count": 1, + "payload_summaries_truncated": false, + "axis_offsets": [ + 1 + ], + "scalar_labels": [ + "Site 1", + "Z 1", + "T 1", + "Well A01" + ], + "labels": { + "channel": [ + "Ch 2" + ] + }, + "axis_component_values": { + "channel": [ + 2 + ] + }, + "routed_component_values": { + "channel": [ + 2 + ] + }, + "routed_component_coordinates": [ + [ + 2 + ] + ], + "data_shape": [ + 2 + ], + "native_transform": { + "scale": [ + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.3556, + 1.3556 + ], + "translate": [ + 0.0, + 1.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0 + ] + }, + "native_intensity": null, + "visible": true, + "selected": false, + "feature_row_count": 2, + "selected_data_indices": [] + } + ], + "active_dimension_label_route": "origin_manual_kind_manual_projection_selected_images_8c7357d46ccc38823ca9e68096baf86f25c3004b61b63ba1eef9adea41d34fb8_scalar_stack", + "viewer_ndim": 7, + "current_step": [ + 0, + 0, + 0, + 0, + 0, + 15, + 15 + ], + "axis_labels": [ + "site", + "channel", + "z_index", + "timepoint", + "well", + "y", + "x" + ], + "component_group_count": 3, + "component_item_count": 4, + "native_viewport": { + "center": [ + 0.0, + 21.011799999999997, + 21.011799999999997 + ], + "zoom": 6.635668707583358 + }, + "native_dimensions": { + "order": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6 + ], + "ndisplay": 2, + "displayed_axes": [ + "y", + "x" + ], + "point": [ + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 20.334, + 20.334 + ], + "camera_angles": [ + 0.0, + 0.0, + 0.0 + ], + "canvas_size": [ + 643, + 478 + ] + }, + "response": { + "type": "state_ack", + "status": "success", + "viewer": { + "type": "napari", + "title": "OpenHCS Napari Visualization" + }, + "layer_count": 3, + "layers": [ + { + "route_key": "origin_manual_kind_manual_projection_selected_images_8c7357d46ccc38823ca9e68096baf86f25c3004b61b63ba1eef9adea41d34fb8_scalar_stack", + "producer_identities": [ + { + "origin": "manual", + "output_kind": "manual", + "output_key": "selected_images", + "projection_key": "selected_images_8c7357d46ccc38823ca9e68096baf86f25c3004b61b63ba1eef9adea41d34fb8", + "step_name": null, + "pipeline_position": null, + "step_scope_id": null, + "invocation_key": null, + "artifact_kind": null + } + ], + "title": "selected_images image stack", + "mounted": true, + "item_count": 1, + "data_types": [ + "image" + ], + "component_values": [ + { + "site": 1, + "z_index": 1, + "timepoint": 1, + "well": "A01" + } + ], + "component_value_count": 1, + "component_values_truncated": false, + "payload_summaries": [ + { + "shape": [ + 2, + 32, + 32 + ], + "dtype": "uint16", + "size": 2048, + "nonzero_count": 308, + "min": 0, + "max": 22, + "nonzero_min_coordinate": [ + 0, + 3, + 4 + ], + "nonzero_max_coordinate": [ + 1, + 24, + 27 + ], + "nonzero_example_coordinates": [ + [ + 0, + 3, + 4 + ], + [ + 0, + 5, + 4 + ], + [ + 0, + 7, + 4 + ], + [ + 0, + 9, + 5 + ], + [ + 0, + 11, + 5 + ], + [ + 0, + 18, + 24 + ], + [ + 0, + 21, + 20 + ], + [ + 0, + 23, + 25 + ], + [ + 1, + 3, + 13 + ], + [ + 1, + 6, + 4 + ], + [ + 1, + 8, + 4 + ], + [ + 1, + 10, + 5 + ], + [ + 1, + 17, + 21 + ], + [ + 1, + 19, + 26 + ], + [ + 1, + 22, + 22 + ], + [ + 1, + 24, + 27 + ] + ], + "source_voxel_spacing": { + "values_zyx": [ + 1.3556, + 1.3556 + ], + "unit": "micrometers" + }, + "spatial_origin_yx": [ + 0, + 0 + ], + "source_spatial_shape_yx": [ + 32, + 32 + ], + "aggregate_component_values": { + "channel": [ + 2, + 1 + ] + }, + "data_type": "image", + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/stacked_labels/A01_s001_w2_z001_t001_Labels.tif", + "components": { + "site": 1, + "z_index": 1, + "timepoint": 1, + "well": "A01" + }, + "payload_type": "ndarray" + } + ], + "payload_summary_count": 1, + "payload_summaries_truncated": false, + "axis_labels": [ + "site", + "channel", + "z_index", + "timepoint", + "well", + "y", + "x" + ], + "stack_axes": [ + "channel" + ], + "axis_offsets": [ + 0 + ], + "scalar_labels": [ + "Site 1", + "Z 1", + "T 1", + "Well A01" + ], + "labels": { + "channel": [ + "Ch 1", + "Ch 2" + ] + }, + "axis_component_values": { + "channel": [ + 1, + 2 + ] + }, + "routed_component_values": { + "channel": [ + 1, + 2 + ] + }, + "routed_component_coordinates": [ + [ + 1 + ], + [ + 2 + ] + ], + "data_shape": [ + 1, + 2, + 1, + 1, + 1, + 32, + 32 + ], + "native_transform": { + "scale": [ + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.3556, + 1.3556 + ], + "translate": [ + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0 + ] + }, + "native_intensity": { + "contrast_limits": [ + 0.0, + 22.0 + ], + "gamma": 1.0 + }, + "visible": true, + "selected": true, + "feature_row_count": 0, + "selected_data_indices": [], + "pending_update": false + }, + { + "route_key": "origin_manual_kind_manual_projection_selected_images_e83ddc2185a63aca4b85ec471143f61c8f4eabdb08df3557ca21f2bddcda60b9", + "producer_identities": [ + { + "origin": "manual", + "output_kind": "manual", + "output_key": "selected_images", + "projection_key": "selected_images_e83ddc2185a63aca4b85ec471143f61c8f4eabdb08df3557ca21f2bddcda60b9", + "step_name": null, + "pipeline_position": null, + "step_scope_id": null, + "invocation_key": null, + "artifact_kind": null + } + ], + "title": "selected_images", + "mounted": true, + "item_count": 2, + "data_types": [ + "image" + ], + "component_values": [ + { + "site": 1, + "channel": 1, + "z_index": 1, + "timepoint": 1, + "well": "A01" + }, + { + "site": 1, + "channel": 2, + "z_index": 1, + "timepoint": 1, + "well": "A01" + } + ], + "component_value_count": 2, + "component_values_truncated": false, + "payload_summaries": [ + { + "shape": [ + 32, + 32 + ], + "dtype": "uint16", + "size": 1024, + "nonzero_count": 1024, + "min": 100, + "max": 1123, + "nonzero_min_coordinate": [ + 0, + 0 + ], + "nonzero_max_coordinate": [ + 31, + 31 + ], + "nonzero_example_coordinates": [ + [ + 0, + 0 + ], + [ + 2, + 4 + ], + [ + 4, + 8 + ], + [ + 6, + 12 + ], + [ + 8, + 16 + ], + [ + 10, + 21 + ], + [ + 12, + 25 + ], + [ + 14, + 29 + ], + [ + 17, + 1 + ], + [ + 19, + 5 + ], + [ + 21, + 10 + ], + [ + 23, + 14 + ], + [ + 25, + 18 + ], + [ + 27, + 22 + ], + [ + 29, + 26 + ], + [ + 31, + 31 + ] + ], + "source_voxel_spacing": { + "values_zyx": [ + 1.3556, + 1.3556 + ], + "unit": "micrometers" + }, + "spatial_origin_yx": [ + 0, + 0 + ], + "source_spatial_shape_yx": [ + 32, + 32 + ], + "data_type": "image", + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w1_z001_t001.tif", + "components": { + "site": 1, + "channel": 1, + "z_index": 1, + "timepoint": 1, + "well": "A01" + }, + "payload_type": "ndarray" + }, + { + "shape": [ + 32, + 32 + ], + "dtype": "uint16", + "size": 1024, + "nonzero_count": 1024, + "min": 200, + "max": 1223, + "nonzero_min_coordinate": [ + 0, + 0 + ], + "nonzero_max_coordinate": [ + 31, + 31 + ], + "nonzero_example_coordinates": [ + [ + 0, + 0 + ], + [ + 2, + 4 + ], + [ + 4, + 8 + ], + [ + 6, + 12 + ], + [ + 8, + 16 + ], + [ + 10, + 21 + ], + [ + 12, + 25 + ], + [ + 14, + 29 + ], + [ + 17, + 1 + ], + [ + 19, + 5 + ], + [ + 21, + 10 + ], + [ + 23, + 14 + ], + [ + 25, + 18 + ], + [ + 27, + 22 + ], + [ + 29, + 26 + ], + [ + 31, + 31 + ] + ], + "source_voxel_spacing": { + "values_zyx": [ + 1.3556, + 1.3556 + ], + "unit": "micrometers" + }, + "spatial_origin_yx": [ + 0, + 0 + ], + "source_spatial_shape_yx": [ + 32, + 32 + ], + "data_type": "image", + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w2_z001_t001.tif", + "components": { + "site": 1, + "channel": 2, + "z_index": 1, + "timepoint": 1, + "well": "A01" + }, + "payload_type": "ndarray" + } + ], + "payload_summary_count": 2, + "payload_summaries_truncated": false, + "axis_labels": [ + "site", + "channel", + "z_index", + "timepoint", + "well", + "y", + "x" + ], + "stack_axes": [ + "channel" + ], + "axis_offsets": [ + 0 + ], + "scalar_labels": [ + "Site 1", + "Z 1", + "T 1", + "Well A01" + ], + "labels": { + "channel": [ + "Ch 1", + "Ch 2" + ] + }, + "axis_component_values": { + "channel": [ + 1, + 2 + ] + }, + "routed_component_values": { + "channel": [ + 1, + 2 + ] + }, + "routed_component_coordinates": [ + [ + 1 + ], + [ + 2 + ] + ], + "data_shape": [ + 1, + 2, + 1, + 1, + 1, + 32, + 32 + ], + "native_transform": { + "scale": [ + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.3556, + 1.3556 + ], + "translate": [ + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0 + ] + }, + "native_intensity": { + "contrast_limits": [ + 100.0, + 1223.0 + ], + "gamma": 1.0 + }, + "visible": true, + "selected": false, + "feature_row_count": 0, + "selected_data_indices": [], + "pending_update": false + }, + { + "route_key": "origin_manual_kind_manual_projection_A01_s001_w2_z001_t001_graph.graph.roi.zip_shapes", + "producer_identities": [ + { + "origin": "manual", + "output_kind": "manual", + "output_key": "A01_s001_w2_z001_t001_graph.graph.roi.zip", + "projection_key": "A01_s001_w2_z001_t001_graph.graph.roi.zip", + "step_name": null, + "pipeline_position": null, + "step_scope_id": null, + "invocation_key": null, + "artifact_kind": null + } + ], + "title": "A01_s001_w2_z001_t001_graph.graph.roi.zip ROIs", + "mounted": true, + "item_count": 1, + "data_types": [ + "shapes" + ], + "component_values": [ + { + "site": 1, + "channel": 2, + "z_index": 1, + "timepoint": 1, + "well": "A01" + } + ], + "component_value_count": 1, + "component_values_truncated": false, + "payload_summaries": [ + { + "nonzero_count": 2, + "item_count": 2, + "shape_payload_count": 2, + "missing_source_spatial_shape_count": 2, + "shape_coordinate_count": 4, + "shape_out_of_source_bounds_count": 0, + "shape_coordinate_bounds_yx": { + "min_yx": [ + 2.25, + 3.5 + ], + "max_yx": [ + 7.25, + 12.5 + ], + "coordinate_count": 4 + }, + "source_voxel_spacing": { + "values_zyx": [ + 1.3556, + 1.3556 + ], + "unit": "micrometers" + }, + "data_type": "shapes", + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/graph_results/A01_s001_w2_z001_t001_graph.graph.roi.zip", + "components": { + "site": 1, + "channel": 2, + "z_index": 1, + "timepoint": 1, + "well": "A01" + }, + "payload_type": "list" + } + ], + "payload_summary_count": 1, + "payload_summaries_truncated": false, + "axis_labels": [ + "site", + "channel", + "z_index", + "timepoint", + "well", + "y", + "x" + ], + "stack_axes": [ + "channel" + ], + "axis_offsets": [ + 1 + ], + "scalar_labels": [ + "Site 1", + "Z 1", + "T 1", + "Well A01" + ], + "labels": { + "channel": [ + "Ch 2" + ] + }, + "axis_component_values": { + "channel": [ + 2 + ] + }, + "routed_component_values": { + "channel": [ + 2 + ] + }, + "routed_component_coordinates": [ + [ + 2 + ] + ], + "data_shape": [ + 2 + ], + "native_transform": { + "scale": [ + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.3556, + 1.3556 + ], + "translate": [ + 0.0, + 1.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0 + ] + }, + "native_intensity": null, + "visible": true, + "selected": false, + "feature_row_count": 2, + "selected_data_indices": [], + "pending_update": false + } + ], + "native_viewport": { + "center": [ + 0.0, + 21.011799999999997, + 21.011799999999997 + ], + "zoom": 6.635668707583358 + }, + "native_dimensions": { + "order": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6 + ], + "ndisplay": 2, + "displayed_axes": [ + "y", + "x" + ], + "point": [ + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 20.334, + 20.334 + ], + "camera_angles": [ + 0.0, + 0.0, + 0.0 + ], + "canvas_size": [ + 643, + 478 + ] + }, + "active_dimension_label_route": "origin_manual_kind_manual_projection_selected_images_8c7357d46ccc38823ca9e68096baf86f25c3004b61b63ba1eef9adea41d34fb8_scalar_stack", + "viewer_ndim": 7, + "current_step": [ + 0, + 0, + 0, + 0, + 0, + 15, + 15 + ], + "axis_labels": [ + "site", + "channel", + "z_index", + "timepoint", + "well", + "y", + "x" + ], + "component_group_count": 3, + "component_item_count": 4 + } + }, + "isError": false + }, + "payload": { + "connection": { + "host": "127.0.0.1", + "port": 6609, + "transport_mode": "tcp", + "persistent": true + }, + "schema_version": "openhcs.agent.v1", + "errors": [], + "warnings": [], + "observed": true, + "viewer": { + "viewer_type": "napari", + "title": "OpenHCS Napari Visualization" + }, + "layer_count": 3, + "layers": [ + { + "route_key": "origin_manual_kind_manual_projection_selected_images_8c7357d46ccc38823ca9e68096baf86f25c3004b61b63ba1eef9adea41d34fb8_scalar_stack", + "title": "selected_images image stack", + "mounted": true, + "item_count": 1, + "producer_identities": [ + { + "origin": "manual", + "output_kind": "manual", + "output_key": "selected_images", + "projection_key": "selected_images_8c7357d46ccc38823ca9e68096baf86f25c3004b61b63ba1eef9adea41d34fb8", + "step_name": null, + "pipeline_position": null, + "step_scope_id": null, + "invocation_key": null, + "artifact_kind": null + } + ], + "axis_labels": [ + "site", + "channel", + "z_index", + "timepoint", + "well", + "y", + "x" + ], + "stack_axes": [ + "channel" + ], + "pending_update": false, + "data_types": [ + "image" + ], + "component_values": [ + { + "site": 1, + "z_index": 1, + "timepoint": 1, + "well": "A01" + } + ], + "component_value_count": 1, + "component_values_truncated": false, + "payload_summaries": [ + { + "shape": [ + 2, + 32, + 32 + ], + "dtype": "uint16", + "size": 2048, + "nonzero_count": 308, + "min": 0, + "max": 22, + "nonzero_min_coordinate": [ + 0, + 3, + 4 + ], + "nonzero_max_coordinate": [ + 1, + 24, + 27 + ], + "nonzero_example_coordinates": [ + [ + 0, + 3, + 4 + ], + [ + 0, + 5, + 4 + ], + [ + 0, + 7, + 4 + ], + [ + 0, + 9, + 5 + ], + [ + 0, + 11, + 5 + ], + [ + 0, + 18, + 24 + ], + [ + 0, + 21, + 20 + ], + [ + 0, + 23, + 25 + ], + [ + 1, + 3, + 13 + ], + [ + 1, + 6, + 4 + ], + [ + 1, + 8, + 4 + ], + [ + 1, + 10, + 5 + ], + [ + 1, + 17, + 21 + ], + [ + 1, + 19, + 26 + ], + [ + 1, + 22, + 22 + ], + [ + 1, + 24, + 27 + ] + ], + "source_voxel_spacing": { + "values_zyx": [ + 1.3556, + 1.3556 + ], + "unit": "micrometers" + }, + "spatial_origin_yx": [ + 0, + 0 + ], + "source_spatial_shape_yx": [ + 32, + 32 + ], + "aggregate_component_values": { + "channel": [ + 2, + 1 + ] + }, + "data_type": "image", + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/stacked_labels/A01_s001_w2_z001_t001_Labels.tif", + "components": { + "site": 1, + "z_index": 1, + "timepoint": 1, + "well": "A01" + }, + "payload_type": "ndarray" + } + ], + "payload_summary_count": 1, + "payload_summaries_truncated": false, + "axis_offsets": [ + 0 + ], + "scalar_labels": [ + "Site 1", + "Z 1", + "T 1", + "Well A01" + ], + "labels": { + "channel": [ + "Ch 1", + "Ch 2" + ] + }, + "axis_component_values": { + "channel": [ + 1, + 2 + ] + }, + "routed_component_values": { + "channel": [ + 1, + 2 + ] + }, + "routed_component_coordinates": [ + [ + 1 + ], + [ + 2 + ] + ], + "data_shape": [ + 1, + 2, + 1, + 1, + 1, + 32, + 32 + ], + "native_transform": { + "scale": [ + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.3556, + 1.3556 + ], + "translate": [ + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0 + ] + }, + "native_intensity": { + "contrast_limits": [ + 0.0, + 22.0 + ], + "gamma": 1.0 + }, + "visible": true, + "selected": true, + "feature_row_count": 0, + "selected_data_indices": [] + }, + { + "route_key": "origin_manual_kind_manual_projection_selected_images_e83ddc2185a63aca4b85ec471143f61c8f4eabdb08df3557ca21f2bddcda60b9", + "title": "selected_images", + "mounted": true, + "item_count": 2, + "producer_identities": [ + { + "origin": "manual", + "output_kind": "manual", + "output_key": "selected_images", + "projection_key": "selected_images_e83ddc2185a63aca4b85ec471143f61c8f4eabdb08df3557ca21f2bddcda60b9", + "step_name": null, + "pipeline_position": null, + "step_scope_id": null, + "invocation_key": null, + "artifact_kind": null + } + ], + "axis_labels": [ + "site", + "channel", + "z_index", + "timepoint", + "well", + "y", + "x" + ], + "stack_axes": [ + "channel" + ], + "pending_update": false, + "data_types": [ + "image" + ], + "component_values": [ + { + "site": 1, + "channel": 1, + "z_index": 1, + "timepoint": 1, + "well": "A01" + }, + { + "site": 1, + "channel": 2, + "z_index": 1, + "timepoint": 1, + "well": "A01" + } + ], + "component_value_count": 2, + "component_values_truncated": false, + "payload_summaries": [ + { + "shape": [ + 32, + 32 + ], + "dtype": "uint16", + "size": 1024, + "nonzero_count": 1024, + "min": 100, + "max": 1123, + "nonzero_min_coordinate": [ + 0, + 0 + ], + "nonzero_max_coordinate": [ + 31, + 31 + ], + "nonzero_example_coordinates": [ + [ + 0, + 0 + ], + [ + 2, + 4 + ], + [ + 4, + 8 + ], + [ + 6, + 12 + ], + [ + 8, + 16 + ], + [ + 10, + 21 + ], + [ + 12, + 25 + ], + [ + 14, + 29 + ], + [ + 17, + 1 + ], + [ + 19, + 5 + ], + [ + 21, + 10 + ], + [ + 23, + 14 + ], + [ + 25, + 18 + ], + [ + 27, + 22 + ], + [ + 29, + 26 + ], + [ + 31, + 31 + ] + ], + "source_voxel_spacing": { + "values_zyx": [ + 1.3556, + 1.3556 + ], + "unit": "micrometers" + }, + "spatial_origin_yx": [ + 0, + 0 + ], + "source_spatial_shape_yx": [ + 32, + 32 + ], + "data_type": "image", + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w1_z001_t001.tif", + "components": { + "site": 1, + "channel": 1, + "z_index": 1, + "timepoint": 1, + "well": "A01" + }, + "payload_type": "ndarray" + }, + { + "shape": [ + 32, + 32 + ], + "dtype": "uint16", + "size": 1024, + "nonzero_count": 1024, + "min": 200, + "max": 1223, + "nonzero_min_coordinate": [ + 0, + 0 + ], + "nonzero_max_coordinate": [ + 31, + 31 + ], + "nonzero_example_coordinates": [ + [ + 0, + 0 + ], + [ + 2, + 4 + ], + [ + 4, + 8 + ], + [ + 6, + 12 + ], + [ + 8, + 16 + ], + [ + 10, + 21 + ], + [ + 12, + 25 + ], + [ + 14, + 29 + ], + [ + 17, + 1 + ], + [ + 19, + 5 + ], + [ + 21, + 10 + ], + [ + 23, + 14 + ], + [ + 25, + 18 + ], + [ + 27, + 22 + ], + [ + 29, + 26 + ], + [ + 31, + 31 + ] + ], + "source_voxel_spacing": { + "values_zyx": [ + 1.3556, + 1.3556 + ], + "unit": "micrometers" + }, + "spatial_origin_yx": [ + 0, + 0 + ], + "source_spatial_shape_yx": [ + 32, + 32 + ], + "data_type": "image", + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w2_z001_t001.tif", + "components": { + "site": 1, + "channel": 2, + "z_index": 1, + "timepoint": 1, + "well": "A01" + }, + "payload_type": "ndarray" + } + ], + "payload_summary_count": 2, + "payload_summaries_truncated": false, + "axis_offsets": [ + 0 + ], + "scalar_labels": [ + "Site 1", + "Z 1", + "T 1", + "Well A01" + ], + "labels": { + "channel": [ + "Ch 1", + "Ch 2" + ] + }, + "axis_component_values": { + "channel": [ + 1, + 2 + ] + }, + "routed_component_values": { + "channel": [ + 1, + 2 + ] + }, + "routed_component_coordinates": [ + [ + 1 + ], + [ + 2 + ] + ], + "data_shape": [ + 1, + 2, + 1, + 1, + 1, + 32, + 32 + ], + "native_transform": { + "scale": [ + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.3556, + 1.3556 + ], + "translate": [ + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0 + ] + }, + "native_intensity": { + "contrast_limits": [ + 100.0, + 1223.0 + ], + "gamma": 1.0 + }, + "visible": true, + "selected": false, + "feature_row_count": 0, + "selected_data_indices": [] + }, + { + "route_key": "origin_manual_kind_manual_projection_A01_s001_w2_z001_t001_graph.graph.roi.zip_shapes", + "title": "A01_s001_w2_z001_t001_graph.graph.roi.zip ROIs", + "mounted": true, + "item_count": 1, + "producer_identities": [ + { + "origin": "manual", + "output_kind": "manual", + "output_key": "A01_s001_w2_z001_t001_graph.graph.roi.zip", + "projection_key": "A01_s001_w2_z001_t001_graph.graph.roi.zip", + "step_name": null, + "pipeline_position": null, + "step_scope_id": null, + "invocation_key": null, + "artifact_kind": null + } + ], + "axis_labels": [ + "site", + "channel", + "z_index", + "timepoint", + "well", + "y", + "x" + ], + "stack_axes": [ + "channel" + ], + "pending_update": false, + "data_types": [ + "shapes" + ], + "component_values": [ + { + "site": 1, + "channel": 2, + "z_index": 1, + "timepoint": 1, + "well": "A01" + } + ], + "component_value_count": 1, + "component_values_truncated": false, + "payload_summaries": [ + { + "nonzero_count": 2, + "item_count": 2, + "shape_payload_count": 2, + "missing_source_spatial_shape_count": 2, + "shape_coordinate_count": 4, + "shape_out_of_source_bounds_count": 0, + "shape_coordinate_bounds_yx": { + "min_yx": [ + 2.25, + 3.5 + ], + "max_yx": [ + 7.25, + 12.5 + ], + "coordinate_count": 4 + }, + "source_voxel_spacing": { + "values_zyx": [ + 1.3556, + 1.3556 + ], + "unit": "micrometers" + }, + "data_type": "shapes", + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/graph_results/A01_s001_w2_z001_t001_graph.graph.roi.zip", + "components": { + "site": 1, + "channel": 2, + "z_index": 1, + "timepoint": 1, + "well": "A01" + }, + "payload_type": "list" + } + ], + "payload_summary_count": 1, + "payload_summaries_truncated": false, + "axis_offsets": [ + 1 + ], + "scalar_labels": [ + "Site 1", + "Z 1", + "T 1", + "Well A01" + ], + "labels": { + "channel": [ + "Ch 2" + ] + }, + "axis_component_values": { + "channel": [ + 2 + ] + }, + "routed_component_values": { + "channel": [ + 2 + ] + }, + "routed_component_coordinates": [ + [ + 2 + ] + ], + "data_shape": [ + 2 + ], + "native_transform": { + "scale": [ + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.3556, + 1.3556 + ], + "translate": [ + 0.0, + 1.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0 + ] + }, + "native_intensity": null, + "visible": true, + "selected": false, + "feature_row_count": 2, + "selected_data_indices": [] + } + ], + "active_dimension_label_route": "origin_manual_kind_manual_projection_selected_images_8c7357d46ccc38823ca9e68096baf86f25c3004b61b63ba1eef9adea41d34fb8_scalar_stack", + "viewer_ndim": 7, + "current_step": [ + 0, + 0, + 0, + 0, + 0, + 15, + 15 + ], + "axis_labels": [ + "site", + "channel", + "z_index", + "timepoint", + "well", + "y", + "x" + ], + "component_group_count": 3, + "component_item_count": 4, + "native_viewport": { + "center": [ + 0.0, + 21.011799999999997, + 21.011799999999997 + ], + "zoom": 6.635668707583358 + }, + "native_dimensions": { + "order": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6 + ], + "ndisplay": 2, + "displayed_axes": [ + "y", + "x" + ], + "point": [ + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 20.334, + 20.334 + ], + "camera_angles": [ + 0.0, + 0.0, + 0.0 + ], + "canvas_size": [ + 643, + 478 + ] + }, + "response": { + "type": "state_ack", + "status": "success", + "viewer": { + "type": "napari", + "title": "OpenHCS Napari Visualization" + }, + "layer_count": 3, + "layers": [ + { + "route_key": "origin_manual_kind_manual_projection_selected_images_8c7357d46ccc38823ca9e68096baf86f25c3004b61b63ba1eef9adea41d34fb8_scalar_stack", + "producer_identities": [ + { + "origin": "manual", + "output_kind": "manual", + "output_key": "selected_images", + "projection_key": "selected_images_8c7357d46ccc38823ca9e68096baf86f25c3004b61b63ba1eef9adea41d34fb8", + "step_name": null, + "pipeline_position": null, + "step_scope_id": null, + "invocation_key": null, + "artifact_kind": null + } + ], + "title": "selected_images image stack", + "mounted": true, + "item_count": 1, + "data_types": [ + "image" + ], + "component_values": [ + { + "site": 1, + "z_index": 1, + "timepoint": 1, + "well": "A01" + } + ], + "component_value_count": 1, + "component_values_truncated": false, + "payload_summaries": [ + { + "shape": [ + 2, + 32, + 32 + ], + "dtype": "uint16", + "size": 2048, + "nonzero_count": 308, + "min": 0, + "max": 22, + "nonzero_min_coordinate": [ + 0, + 3, + 4 + ], + "nonzero_max_coordinate": [ + 1, + 24, + 27 + ], + "nonzero_example_coordinates": [ + [ + 0, + 3, + 4 + ], + [ + 0, + 5, + 4 + ], + [ + 0, + 7, + 4 + ], + [ + 0, + 9, + 5 + ], + [ + 0, + 11, + 5 + ], + [ + 0, + 18, + 24 + ], + [ + 0, + 21, + 20 + ], + [ + 0, + 23, + 25 + ], + [ + 1, + 3, + 13 + ], + [ + 1, + 6, + 4 + ], + [ + 1, + 8, + 4 + ], + [ + 1, + 10, + 5 + ], + [ + 1, + 17, + 21 + ], + [ + 1, + 19, + 26 + ], + [ + 1, + 22, + 22 + ], + [ + 1, + 24, + 27 + ] + ], + "source_voxel_spacing": { + "values_zyx": [ + 1.3556, + 1.3556 + ], + "unit": "micrometers" + }, + "spatial_origin_yx": [ + 0, + 0 + ], + "source_spatial_shape_yx": [ + 32, + 32 + ], + "aggregate_component_values": { + "channel": [ + 2, + 1 + ] + }, + "data_type": "image", + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/stacked_labels/A01_s001_w2_z001_t001_Labels.tif", + "components": { + "site": 1, + "z_index": 1, + "timepoint": 1, + "well": "A01" + }, + "payload_type": "ndarray" + } + ], + "payload_summary_count": 1, + "payload_summaries_truncated": false, + "axis_labels": [ + "site", + "channel", + "z_index", + "timepoint", + "well", + "y", + "x" + ], + "stack_axes": [ + "channel" + ], + "axis_offsets": [ + 0 + ], + "scalar_labels": [ + "Site 1", + "Z 1", + "T 1", + "Well A01" + ], + "labels": { + "channel": [ + "Ch 1", + "Ch 2" + ] + }, + "axis_component_values": { + "channel": [ + 1, + 2 + ] + }, + "routed_component_values": { + "channel": [ + 1, + 2 + ] + }, + "routed_component_coordinates": [ + [ + 1 + ], + [ + 2 + ] + ], + "data_shape": [ + 1, + 2, + 1, + 1, + 1, + 32, + 32 + ], + "native_transform": { + "scale": [ + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.3556, + 1.3556 + ], + "translate": [ + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0 + ] + }, + "native_intensity": { + "contrast_limits": [ + 0.0, + 22.0 + ], + "gamma": 1.0 + }, + "visible": true, + "selected": true, + "feature_row_count": 0, + "selected_data_indices": [], + "pending_update": false + }, + { + "route_key": "origin_manual_kind_manual_projection_selected_images_e83ddc2185a63aca4b85ec471143f61c8f4eabdb08df3557ca21f2bddcda60b9", + "producer_identities": [ + { + "origin": "manual", + "output_kind": "manual", + "output_key": "selected_images", + "projection_key": "selected_images_e83ddc2185a63aca4b85ec471143f61c8f4eabdb08df3557ca21f2bddcda60b9", + "step_name": null, + "pipeline_position": null, + "step_scope_id": null, + "invocation_key": null, + "artifact_kind": null + } + ], + "title": "selected_images", + "mounted": true, + "item_count": 2, + "data_types": [ + "image" + ], + "component_values": [ + { + "site": 1, + "channel": 1, + "z_index": 1, + "timepoint": 1, + "well": "A01" + }, + { + "site": 1, + "channel": 2, + "z_index": 1, + "timepoint": 1, + "well": "A01" + } + ], + "component_value_count": 2, + "component_values_truncated": false, + "payload_summaries": [ + { + "shape": [ + 32, + 32 + ], + "dtype": "uint16", + "size": 1024, + "nonzero_count": 1024, + "min": 100, + "max": 1123, + "nonzero_min_coordinate": [ + 0, + 0 + ], + "nonzero_max_coordinate": [ + 31, + 31 + ], + "nonzero_example_coordinates": [ + [ + 0, + 0 + ], + [ + 2, + 4 + ], + [ + 4, + 8 + ], + [ + 6, + 12 + ], + [ + 8, + 16 + ], + [ + 10, + 21 + ], + [ + 12, + 25 + ], + [ + 14, + 29 + ], + [ + 17, + 1 + ], + [ + 19, + 5 + ], + [ + 21, + 10 + ], + [ + 23, + 14 + ], + [ + 25, + 18 + ], + [ + 27, + 22 + ], + [ + 29, + 26 + ], + [ + 31, + 31 + ] + ], + "source_voxel_spacing": { + "values_zyx": [ + 1.3556, + 1.3556 + ], + "unit": "micrometers" + }, + "spatial_origin_yx": [ + 0, + 0 + ], + "source_spatial_shape_yx": [ + 32, + 32 + ], + "data_type": "image", + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w1_z001_t001.tif", + "components": { + "site": 1, + "channel": 1, + "z_index": 1, + "timepoint": 1, + "well": "A01" + }, + "payload_type": "ndarray" + }, + { + "shape": [ + 32, + 32 + ], + "dtype": "uint16", + "size": 1024, + "nonzero_count": 1024, + "min": 200, + "max": 1223, + "nonzero_min_coordinate": [ + 0, + 0 + ], + "nonzero_max_coordinate": [ + 31, + 31 + ], + "nonzero_example_coordinates": [ + [ + 0, + 0 + ], + [ + 2, + 4 + ], + [ + 4, + 8 + ], + [ + 6, + 12 + ], + [ + 8, + 16 + ], + [ + 10, + 21 + ], + [ + 12, + 25 + ], + [ + 14, + 29 + ], + [ + 17, + 1 + ], + [ + 19, + 5 + ], + [ + 21, + 10 + ], + [ + 23, + 14 + ], + [ + 25, + 18 + ], + [ + 27, + 22 + ], + [ + 29, + 26 + ], + [ + 31, + 31 + ] + ], + "source_voxel_spacing": { + "values_zyx": [ + 1.3556, + 1.3556 + ], + "unit": "micrometers" + }, + "spatial_origin_yx": [ + 0, + 0 + ], + "source_spatial_shape_yx": [ + 32, + 32 + ], + "data_type": "image", + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w2_z001_t001.tif", + "components": { + "site": 1, + "channel": 2, + "z_index": 1, + "timepoint": 1, + "well": "A01" + }, + "payload_type": "ndarray" + } + ], + "payload_summary_count": 2, + "payload_summaries_truncated": false, + "axis_labels": [ + "site", + "channel", + "z_index", + "timepoint", + "well", + "y", + "x" + ], + "stack_axes": [ + "channel" + ], + "axis_offsets": [ + 0 + ], + "scalar_labels": [ + "Site 1", + "Z 1", + "T 1", + "Well A01" + ], + "labels": { + "channel": [ + "Ch 1", + "Ch 2" + ] + }, + "axis_component_values": { + "channel": [ + 1, + 2 + ] + }, + "routed_component_values": { + "channel": [ + 1, + 2 + ] + }, + "routed_component_coordinates": [ + [ + 1 + ], + [ + 2 + ] + ], + "data_shape": [ + 1, + 2, + 1, + 1, + 1, + 32, + 32 + ], + "native_transform": { + "scale": [ + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.3556, + 1.3556 + ], + "translate": [ + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0 + ] + }, + "native_intensity": { + "contrast_limits": [ + 100.0, + 1223.0 + ], + "gamma": 1.0 + }, + "visible": true, + "selected": false, + "feature_row_count": 0, + "selected_data_indices": [], + "pending_update": false + }, + { + "route_key": "origin_manual_kind_manual_projection_A01_s001_w2_z001_t001_graph.graph.roi.zip_shapes", + "producer_identities": [ + { + "origin": "manual", + "output_kind": "manual", + "output_key": "A01_s001_w2_z001_t001_graph.graph.roi.zip", + "projection_key": "A01_s001_w2_z001_t001_graph.graph.roi.zip", + "step_name": null, + "pipeline_position": null, + "step_scope_id": null, + "invocation_key": null, + "artifact_kind": null + } + ], + "title": "A01_s001_w2_z001_t001_graph.graph.roi.zip ROIs", + "mounted": true, + "item_count": 1, + "data_types": [ + "shapes" + ], + "component_values": [ + { + "site": 1, + "channel": 2, + "z_index": 1, + "timepoint": 1, + "well": "A01" + } + ], + "component_value_count": 1, + "component_values_truncated": false, + "payload_summaries": [ + { + "nonzero_count": 2, + "item_count": 2, + "shape_payload_count": 2, + "missing_source_spatial_shape_count": 2, + "shape_coordinate_count": 4, + "shape_out_of_source_bounds_count": 0, + "shape_coordinate_bounds_yx": { + "min_yx": [ + 2.25, + 3.5 + ], + "max_yx": [ + 7.25, + 12.5 + ], + "coordinate_count": 4 + }, + "source_voxel_spacing": { + "values_zyx": [ + 1.3556, + 1.3556 + ], + "unit": "micrometers" + }, + "data_type": "shapes", + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/graph_results/A01_s001_w2_z001_t001_graph.graph.roi.zip", + "components": { + "site": 1, + "channel": 2, + "z_index": 1, + "timepoint": 1, + "well": "A01" + }, + "payload_type": "list" + } + ], + "payload_summary_count": 1, + "payload_summaries_truncated": false, + "axis_labels": [ + "site", + "channel", + "z_index", + "timepoint", + "well", + "y", + "x" + ], + "stack_axes": [ + "channel" + ], + "axis_offsets": [ + 1 + ], + "scalar_labels": [ + "Site 1", + "Z 1", + "T 1", + "Well A01" + ], + "labels": { + "channel": [ + "Ch 2" + ] + }, + "axis_component_values": { + "channel": [ + 2 + ] + }, + "routed_component_values": { + "channel": [ + 2 + ] + }, + "routed_component_coordinates": [ + [ + 2 + ] + ], + "data_shape": [ + 2 + ], + "native_transform": { + "scale": [ + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.3556, + 1.3556 + ], + "translate": [ + 0.0, + 1.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0 + ] + }, + "native_intensity": null, + "visible": true, + "selected": false, + "feature_row_count": 2, + "selected_data_indices": [], + "pending_update": false + } + ], + "native_viewport": { + "center": [ + 0.0, + 21.011799999999997, + 21.011799999999997 + ], + "zoom": 6.635668707583358 + }, + "native_dimensions": { + "order": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6 + ], + "ndisplay": 2, + "displayed_axes": [ + "y", + "x" + ], + "point": [ + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 20.334, + 20.334 + ], + "camera_angles": [ + 0.0, + 0.0, + 0.0 + ], + "canvas_size": [ + 643, + 478 + ] + }, + "active_dimension_label_route": "origin_manual_kind_manual_projection_selected_images_8c7357d46ccc38823ca9e68096baf86f25c3004b61b63ba1eef9adea41d34fb8_scalar_stack", + "viewer_ndim": 7, + "current_step": [ + 0, + 0, + 0, + 0, + 0, + 15, + 15 + ], + "axis_labels": [ + "site", + "channel", + "z_index", + "timepoint", + "well", + "y", + "x" + ], + "component_group_count": 3, + "component_item_count": 4 + } + } + }, + { + "tool": "openhcs_get_viewer_window_payloads", + "arguments": { + "host": "127.0.0.1", + "port": 6609, + "transport_mode": "tcp", + "route_key": null, + "axis_indices": null, + "include_array_values": true, + "max_array_elements": 4096, + "array_slices": null, + "include_shape_payloads": true, + "max_shape_payloads": 20, + "include_response": false + }, + "response": { + "content": [ + { + "type": "text", + "text": "{\n \"connection\": {\n \"host\": \"127.0.0.1\",\n \"port\": 6609,\n \"transport_mode\": \"tcp\",\n \"persistent\": true\n },\n \"schema_version\": \"openhcs.agent.v1\",\n \"errors\": [],\n \"warnings\": [],\n \"observed\": true,\n \"viewer\": {\n \"viewer_type\": \"napari\",\n \"title\": \"OpenHCS Napari Visualization\"\n },\n \"layer_count\": 3,\n \"layers\": [\n {\n \"route_key\": \"origin_manual_kind_manual_projection_selected_images_8c7357d46ccc38823ca9e68096baf86f25c3004b61b63ba1eef9adea41d34fb8_scalar_stack\",\n \"title\": \"selected_images image stack\",\n \"mounted\": true,\n \"item_count\": 1,\n \"producer_identities\": [\n {\n \"origin\": \"manual\",\n \"output_kind\": \"manual\",\n \"output_key\": \"selected_images\",\n \"projection_key\": \"selected_images_8c7357d46ccc38823ca9e68096baf86f25c3004b61b63ba1eef9adea41d34fb8\",\n \"step_name\": null,\n \"pipeline_position\": null,\n \"step_scope_id\": null,\n \"invocation_key\": null,\n \"artifact_kind\": null\n }\n ],\n \"axis_labels\": [\n \"site\",\n \"channel\",\n \"z_index\",\n \"timepoint\",\n \"well\",\n \"y\",\n \"x\"\n ],\n \"stack_axes\": [\n \"channel\"\n ],\n \"pending_update\": false,\n \"payloads\": [\n {\n \"data_type\": \"image\",\n \"path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/stacked_labels/A01_s001_w2_z001_t001_Labels.tif\",\n \"components\": {\n \"site\": 1,\n \"z_index\": 1,\n \"timepoint\": 1,\n \"well\": \"A01\",\n \"channel\": 2\n },\n \"axis_indices\": [\n 1\n ],\n \"aggregate_axis_indices\": [\n 0\n ],\n \"summary\": {\n \"shape\": [\n 32,\n 32\n ],\n \"dtype\": \"uint16\",\n \"size\": 1024,\n \"nonzero_count\": 154,\n \"min\": 0,\n \"max\": 22,\n \"nonzero_min_coordinate\": [\n 3,\n 4\n ],\n \"nonzero_max_coordinate\": [\n 24,\n 27\n ],\n \"nonzero_example_coordinates\": [\n [\n 3,\n 4\n ],\n [\n 4,\n 4\n ],\n [\n 5,\n 4\n ],\n [\n 6,\n 4\n ],\n [\n 7,\n 4\n ],\n [\n 8,\n 5\n ],\n [\n 9,\n 5\n ],\n [\n 10,\n 5\n ],\n [\n 11,\n 5\n ],\n [\n 17,\n 21\n ],\n [\n 18,\n 24\n ],\n [\n 19,\n 26\n ],\n [\n 21,\n 20\n ],\n [\n 22,\n 22\n ],\n [\n 23,\n 24\n ],\n [\n 24,\n 27\n ]\n ],\n \"source_voxel_spacing\": {\n \"values_zyx\": [\n 1.3556,\n 1.3556\n ],\n \"unit\": \"micrometers\"\n },\n \"spatial_origin_yx\": [\n 0,\n 0\n ],\n \"source_spatial_shape_yx\": [\n 32,\n 32\n ],\n \"data_type\": \"image\",\n \"path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/stacked_labels/A01_s001_w2_z001_t001_Labels.tif\",\n \"components\": {\n \"site\": 1,\n \"z_index\": 1,\n \"timepoint\": 1,\n \"well\": \"A01\",\n \"channel\": 2\n },\n \"payload_type\": \"ndarray\"\n },\n \"array_values\": [\n [\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0\n ],\n [\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0\n ],\n [\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0\n ],\n [\n 0,\n 0,\n 0,\n 0,\n 14,\n 14,\n 14,\n 14,\n 14,\n 14,\n 14,\n 14,\n 14,\n 14,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0\n ],\n [\n 0,\n 0,\n 0,\n 0,\n 14,\n 14,\n 14,\n 14,\n 14,\n 14,\n 14,\n 14,\n 14,\n 14,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0\n ],\n [\n 0,\n 0,\n 0,\n 0,\n 14,\n 14,\n 14,\n 14,\n 14,\n 14,\n 14,\n 14,\n 14,\n 14,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0\n ],\n [\n 0,\n 0,\n 0,\n 0,\n 14,\n 14,\n 14,\n 14,\n 14,\n 14,\n 14,\n 14,\n 14,\n 14,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0\n ],\n [\n 0,\n 0,\n 0,\n 0,\n 14,\n 14,\n 14,\n 14,\n 14,\n 14,\n 14,\n 14,\n 14,\n 14,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0\n ],\n [\n 0,\n 0,\n 0,\n 0,\n 14,\n 14,\n 14,\n 14,\n 14,\n 14,\n 14,\n 14,\n 14,\n 14,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0\n ],\n [\n 0,\n 0,\n 0,\n 0,\n 14,\n 14,\n 14,\n 14,\n 14,\n 14,\n 14,\n 14,\n 14,\n 14,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0\n ],\n [\n 0,\n 0,\n 0,\n 0,\n 14,\n 14,\n 14,\n 14,\n 14,\n 14,\n 14,\n 14,\n 14,\n 14,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0\n ],\n [\n 0,\n 0,\n 0,\n 0,\n 14,\n 14,\n 14,\n 14,\n 14,\n 14,\n 14,\n 14,\n 14,\n 14,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0\n ],\n [\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0\n ],\n [\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0\n ],\n [\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0\n ],\n [\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0\n ],\n [\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0\n ],\n [\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 22,\n 22,\n 22,\n 22,\n 22,\n 22,\n 22,\n 22,\n 0,\n 0,\n 0,\n 0\n ],\n [\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 22,\n 22,\n 22,\n 22,\n 22,\n 22,\n 22,\n 22,\n 0,\n 0,\n 0,\n 0\n ],\n [\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 22,\n 22,\n 22,\n 22,\n 22,\n 22,\n 22,\n 22,\n 0,\n 0,\n 0,\n 0\n ],\n [\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 22,\n 22,\n 22,\n 22,\n 22,\n 22,\n 22,\n 22,\n 0,\n 0,\n 0,\n 0\n ],\n [\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 22,\n 22,\n 22,\n 22,\n 22,\n 22,\n 22,\n 22,\n 0,\n 0,\n 0,\n 0\n ],\n [\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 22,\n 22,\n 22,\n 22,\n 22,\n 22,\n 22,\n 22,\n 0,\n 0,\n 0,\n 0\n ],\n [\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 22,\n 22,\n 22,\n 22,\n 22,\n 22,\n 22,\n 22,\n 0,\n 0,\n 0,\n 0\n ],\n [\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 22,\n 22,\n 22,\n 22,\n 22,\n 22,\n 22,\n 22,\n 0,\n 0,\n 0,\n 0\n ],\n [\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0\n ],\n [\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0\n ],\n [\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0\n ],\n [\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0\n ],\n [\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0\n ],\n [\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0\n ],\n [\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0\n ]\n ],\n \"array_value_summary\": {\n \"shape\": [\n 32,\n 32\n ],\n \"dtype\": \"uint16\",\n \"size\": 1024,\n \"nonzero_count\": 154,\n \"min\": 0,\n \"max\": 22,\n \"requested\": true,\n \"included\": true,\n \"slice_ranges\": [\n [\n 0,\n 32\n ],\n [\n 0,\n 32\n ]\n ]\n },\n \"route_key\": \"origin_manual_kind_manual_projection_selected_images_8c7357d46ccc38823ca9e68096baf86f25c3004b61b63ba1eef9adea41d34fb8_scalar_stack\",\n \"shape_payloads\": []\n },\n {\n \"data_type\": \"image\",\n \"path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/stacked_labels/A01_s001_w2_z001_t001_Labels.tif\",\n \"components\": {\n \"site\": 1,\n \"z_index\": 1,\n \"timepoint\": 1,\n \"well\": \"A01\",\n \"channel\": 1\n },\n \"axis_indices\": [\n 0\n ],\n \"aggregate_axis_indices\": [\n 1\n ],\n \"summary\": {\n \"shape\": [\n 32,\n 32\n ],\n \"dtype\": \"uint16\",\n \"size\": 1024,\n \"nonzero_count\": 154,\n \"min\": 0,\n \"max\": 11,\n \"nonzero_min_coordinate\": [\n 3,\n 4\n ],\n \"nonzero_max_coordinate\": [\n 24,\n 27\n ],\n \"nonzero_example_coordinates\": [\n [\n 3,\n 4\n ],\n [\n 4,\n 4\n ],\n [\n 5,\n 4\n ],\n [\n 6,\n 4\n ],\n [\n 7,\n 4\n ],\n [\n 8,\n 5\n ],\n [\n 9,\n 5\n ],\n [\n 10,\n 5\n ],\n [\n 11,\n 5\n ],\n [\n 17,\n 21\n ],\n [\n 18,\n 24\n ],\n [\n 19,\n 26\n ],\n [\n 21,\n 20\n ],\n [\n 22,\n 22\n ],\n [\n 23,\n 24\n ],\n [\n 24,\n 27\n ]\n ],\n \"source_voxel_spacing\": {\n \"values_zyx\": [\n 1.3556,\n 1.3556\n ],\n \"unit\": \"micrometers\"\n },\n \"spatial_origin_yx\": [\n 0,\n 0\n ],\n \"source_spatial_shape_yx\": [\n 32,\n 32\n ],\n \"data_type\": \"image\",\n \"path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/stacked_labels/A01_s001_w2_z001_t001_Labels.tif\",\n \"components\": {\n \"site\": 1,\n \"z_index\": 1,\n \"timepoint\": 1,\n \"well\": \"A01\",\n \"channel\": 1\n },\n \"payload_type\": \"ndarray\"\n },\n \"array_values\": [\n [\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0\n ],\n [\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0\n ],\n [\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0\n ],\n [\n 0,\n 0,\n 0,\n 0,\n 7,\n 7,\n 7,\n 7,\n 7,\n 7,\n 7,\n 7,\n 7,\n 7,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0\n ],\n [\n 0,\n 0,\n 0,\n 0,\n 7,\n 7,\n 7,\n 7,\n 7,\n 7,\n 7,\n 7,\n 7,\n 7,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0\n ],\n [\n 0,\n 0,\n 0,\n 0,\n 7,\n 7,\n 7,\n 7,\n 7,\n 7,\n 7,\n 7,\n 7,\n 7,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0\n ],\n [\n 0,\n 0,\n 0,\n 0,\n 7,\n 7,\n 7,\n 7,\n 7,\n 7,\n 7,\n 7,\n 7,\n 7,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0\n ],\n [\n 0,\n 0,\n 0,\n 0,\n 7,\n 7,\n 7,\n 7,\n 7,\n 7,\n 7,\n 7,\n 7,\n 7,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0\n ],\n [\n 0,\n 0,\n 0,\n 0,\n 7,\n 7,\n 7,\n 7,\n 7,\n 7,\n 7,\n 7,\n 7,\n 7,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0\n ],\n [\n 0,\n 0,\n 0,\n 0,\n 7,\n 7,\n 7,\n 7,\n 7,\n 7,\n 7,\n 7,\n 7,\n 7,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0\n ],\n [\n 0,\n 0,\n 0,\n 0,\n 7,\n 7,\n 7,\n 7,\n 7,\n 7,\n 7,\n 7,\n 7,\n 7,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0\n ],\n [\n 0,\n 0,\n 0,\n 0,\n 7,\n 7,\n 7,\n 7,\n 7,\n 7,\n 7,\n 7,\n 7,\n 7,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0\n ],\n [\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0\n ],\n [\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0\n ],\n [\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0\n ],\n [\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0\n ],\n [\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0\n ],\n [\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 11,\n 11,\n 11,\n 11,\n 11,\n 11,\n 11,\n 11,\n 0,\n 0,\n 0,\n 0\n ],\n [\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 11,\n 11,\n 11,\n 11,\n 11,\n 11,\n 11,\n 11,\n 0,\n 0,\n 0,\n 0\n ],\n [\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 11,\n 11,\n 11,\n 11,\n 11,\n 11,\n 11,\n 11,\n 0,\n 0,\n 0,\n 0\n ],\n [\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 11,\n 11,\n 11,\n 11,\n 11,\n 11,\n 11,\n 11,\n 0,\n 0,\n 0,\n 0\n ],\n [\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 11,\n 11,\n 11,\n 11,\n 11,\n 11,\n 11,\n 11,\n 0,\n 0,\n 0,\n 0\n ],\n [\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 11,\n 11,\n 11,\n 11,\n 11,\n 11,\n 11,\n 11,\n 0,\n 0,\n 0,\n 0\n ],\n [\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 11,\n 11,\n 11,\n 11,\n 11,\n 11,\n 11,\n 11,\n 0,\n 0,\n 0,\n 0\n ],\n [\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 11,\n 11,\n 11,\n 11,\n 11,\n 11,\n 11,\n 11,\n 0,\n 0,\n 0,\n 0\n ],\n [\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0\n ],\n [\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0\n ],\n [\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0\n ],\n [\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0\n ],\n [\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0\n ],\n [\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0\n ],\n [\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0\n ]\n ],\n \"array_value_summary\": {\n \"shape\": [\n 32,\n 32\n ],\n \"dtype\": \"uint16\",\n \"size\": 1024,\n \"nonzero_count\": 154,\n \"min\": 0,\n \"max\": 11,\n \"requested\": true,\n \"included\": true,\n \"slice_ranges\": [\n [\n 0,\n 32\n ],\n [\n 0,\n 32\n ]\n ]\n },\n \"route_key\": \"origin_manual_kind_manual_projection_selected_images_8c7357d46ccc38823ca9e68096baf86f25c3004b61b63ba1eef9adea41d34fb8_scalar_stack\",\n \"shape_payloads\": []\n }\n ]\n },\n {\n \"route_key\": \"origin_manual_kind_manual_projection_selected_images_e83ddc2185a63aca4b85ec471143f61c8f4eabdb08df3557ca21f2bddcda60b9\",\n \"title\": \"selected_images\",\n \"mounted\": true,\n \"item_count\": 2,\n \"producer_identities\": [\n {\n \"origin\": \"manual\",\n \"output_kind\": \"manual\",\n \"output_key\": \"selected_images\",\n \"projection_key\": \"selected_images_e83ddc2185a63aca4b85ec471143f61c8f4eabdb08df3557ca21f2bddcda60b9\",\n \"step_name\": null,\n \"pipeline_position\": null,\n \"step_scope_id\": null,\n \"invocation_key\": null,\n \"artifact_kind\": null\n }\n ],\n \"axis_labels\": [\n \"site\",\n \"channel\",\n \"z_index\",\n \"timepoint\",\n \"well\",\n \"y\",\n \"x\"\n ],\n \"stack_axes\": [\n \"channel\"\n ],\n \"pending_update\": false,\n \"payloads\": [\n {\n \"data_type\": \"image\",\n \"path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w1_z001_t001.tif\",\n \"components\": {\n \"site\": 1,\n \"channel\": 1,\n \"z_index\": 1,\n \"timepoint\": 1,\n \"well\": \"A01\"\n },\n \"axis_indices\": [\n 0\n ],\n \"aggregate_axis_indices\": [],\n \"summary\": {\n \"shape\": [\n 32,\n 32\n ],\n \"dtype\": \"uint16\",\n \"size\": 1024,\n \"nonzero_count\": 1024,\n \"min\": 100,\n \"max\": 1123,\n \"nonzero_min_coordinate\": [\n 0,\n 0\n ],\n \"nonzero_max_coordinate\": [\n 31,\n 31\n ],\n \"nonzero_example_coordinates\": [\n [\n 0,\n 0\n ],\n [\n 2,\n 4\n ],\n [\n 4,\n 8\n ],\n [\n 6,\n 12\n ],\n [\n 8,\n 16\n ],\n [\n 10,\n 21\n ],\n [\n 12,\n 25\n ],\n [\n 14,\n 29\n ],\n [\n 17,\n 1\n ],\n [\n 19,\n 5\n ],\n [\n 21,\n 10\n ],\n [\n 23,\n 14\n ],\n [\n 25,\n 18\n ],\n [\n 27,\n 22\n ],\n [\n 29,\n 26\n ],\n [\n 31,\n 31\n ]\n ],\n \"source_voxel_spacing\": {\n \"values_zyx\": [\n 1.3556,\n 1.3556\n ],\n \"unit\": \"micrometers\"\n },\n \"spatial_origin_yx\": [\n 0,\n 0\n ],\n \"source_spatial_shape_yx\": [\n 32,\n 32\n ],\n \"data_type\": \"image\",\n \"path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w1_z001_t001.tif\",\n \"components\": {\n \"site\": 1,\n \"channel\": 1,\n \"z_index\": 1,\n \"timepoint\": 1,\n \"well\": \"A01\"\n },\n \"payload_type\": \"ndarray\"\n },\n \"array_values\": [\n [\n 100,\n 101,\n 102,\n 103,\n 104,\n 105,\n 106,\n 107,\n 108,\n 109,\n 110,\n 111,\n 112,\n 113,\n 114,\n 115,\n 116,\n 117,\n 118,\n 119,\n 120,\n 121,\n 122,\n 123,\n 124,\n 125,\n 126,\n 127,\n 128,\n 129,\n 130,\n 131\n ],\n [\n 132,\n 133,\n 134,\n 135,\n 136,\n 137,\n 138,\n 139,\n 140,\n 141,\n 142,\n 143,\n 144,\n 145,\n 146,\n 147,\n 148,\n 149,\n 150,\n 151,\n 152,\n 153,\n 154,\n 155,\n 156,\n 157,\n 158,\n 159,\n 160,\n 161,\n 162,\n 163\n ],\n [\n 164,\n 165,\n 166,\n 167,\n 168,\n 169,\n 170,\n 171,\n 172,\n 173,\n 174,\n 175,\n 176,\n 177,\n 178,\n 179,\n 180,\n 181,\n 182,\n 183,\n 184,\n 185,\n 186,\n 187,\n 188,\n 189,\n 190,\n 191,\n 192,\n 193,\n 194,\n 195\n ],\n [\n 196,\n 197,\n 198,\n 199,\n 200,\n 201,\n 202,\n 203,\n 204,\n 205,\n 206,\n 207,\n 208,\n 209,\n 210,\n 211,\n 212,\n 213,\n 214,\n 215,\n 216,\n 217,\n 218,\n 219,\n 220,\n 221,\n 222,\n 223,\n 224,\n 225,\n 226,\n 227\n ],\n [\n 228,\n 229,\n 230,\n 231,\n 232,\n 233,\n 234,\n 235,\n 236,\n 237,\n 238,\n 239,\n 240,\n 241,\n 242,\n 243,\n 244,\n 245,\n 246,\n 247,\n 248,\n 249,\n 250,\n 251,\n 252,\n 253,\n 254,\n 255,\n 256,\n 257,\n 258,\n 259\n ],\n [\n 260,\n 261,\n 262,\n 263,\n 264,\n 265,\n 266,\n 267,\n 268,\n 269,\n 270,\n 271,\n 272,\n 273,\n 274,\n 275,\n 276,\n 277,\n 278,\n 279,\n 280,\n 281,\n 282,\n 283,\n 284,\n 285,\n 286,\n 287,\n 288,\n 289,\n 290,\n 291\n ],\n [\n 292,\n 293,\n 294,\n 295,\n 296,\n 297,\n 298,\n 299,\n 300,\n 301,\n 302,\n 303,\n 304,\n 305,\n 306,\n 307,\n 308,\n 309,\n 310,\n 311,\n 312,\n 313,\n 314,\n 315,\n 316,\n 317,\n 318,\n 319,\n 320,\n 321,\n 322,\n 323\n ],\n [\n 324,\n 325,\n 326,\n 327,\n 328,\n 329,\n 330,\n 331,\n 332,\n 333,\n 334,\n 335,\n 336,\n 337,\n 338,\n 339,\n 340,\n 341,\n 342,\n 343,\n 344,\n 345,\n 346,\n 347,\n 348,\n 349,\n 350,\n 351,\n 352,\n 353,\n 354,\n 355\n ],\n [\n 356,\n 357,\n 358,\n 359,\n 360,\n 361,\n 362,\n 363,\n 364,\n 365,\n 366,\n 367,\n 368,\n 369,\n 370,\n 371,\n 372,\n 373,\n 374,\n 375,\n 376,\n 377,\n 378,\n 379,\n 380,\n 381,\n 382,\n 383,\n 384,\n 385,\n 386,\n 387\n ],\n [\n 388,\n 389,\n 390,\n 391,\n 392,\n 393,\n 394,\n 395,\n 396,\n 397,\n 398,\n 399,\n 400,\n 401,\n 402,\n 403,\n 404,\n 405,\n 406,\n 407,\n 408,\n 409,\n 410,\n 411,\n 412,\n 413,\n 414,\n 415,\n 416,\n 417,\n 418,\n 419\n ],\n [\n 420,\n 421,\n 422,\n 423,\n 424,\n 425,\n 426,\n 427,\n 428,\n 429,\n 430,\n 431,\n 432,\n 433,\n 434,\n 435,\n 436,\n 437,\n 438,\n 439,\n 440,\n 441,\n 442,\n 443,\n 444,\n 445,\n 446,\n 447,\n 448,\n 449,\n 450,\n 451\n ],\n [\n 452,\n 453,\n 454,\n 455,\n 456,\n 457,\n 458,\n 459,\n 460,\n 461,\n 462,\n 463,\n 464,\n 465,\n 466,\n 467,\n 468,\n 469,\n 470,\n 471,\n 472,\n 473,\n 474,\n 475,\n 476,\n 477,\n 478,\n 479,\n 480,\n 481,\n 482,\n 483\n ],\n [\n 484,\n 485,\n 486,\n 487,\n 488,\n 489,\n 490,\n 491,\n 492,\n 493,\n 494,\n 495,\n 496,\n 497,\n 498,\n 499,\n 500,\n 501,\n 502,\n 503,\n 504,\n 505,\n 506,\n 507,\n 508,\n 509,\n 510,\n 511,\n 512,\n 513,\n 514,\n 515\n ],\n [\n 516,\n 517,\n 518,\n 519,\n 520,\n 521,\n 522,\n 523,\n 524,\n 525,\n 526,\n 527,\n 528,\n 529,\n 530,\n 531,\n 532,\n 533,\n 534,\n 535,\n 536,\n 537,\n 538,\n 539,\n 540,\n 541,\n 542,\n 543,\n 544,\n 545,\n 546,\n 547\n ],\n [\n 548,\n 549,\n 550,\n 551,\n 552,\n 553,\n 554,\n 555,\n 556,\n 557,\n 558,\n 559,\n 560,\n 561,\n 562,\n 563,\n 564,\n 565,\n 566,\n 567,\n 568,\n 569,\n 570,\n 571,\n 572,\n 573,\n 574,\n 575,\n 576,\n 577,\n 578,\n 579\n ],\n [\n 580,\n 581,\n 582,\n 583,\n 584,\n 585,\n 586,\n 587,\n 588,\n 589,\n 590,\n 591,\n 592,\n 593,\n 594,\n 595,\n 596,\n 597,\n 598,\n 599,\n 600,\n 601,\n 602,\n 603,\n 604,\n 605,\n 606,\n 607,\n 608,\n 609,\n 610,\n 611\n ],\n [\n 612,\n 613,\n 614,\n 615,\n 616,\n 617,\n 618,\n 619,\n 620,\n 621,\n 622,\n 623,\n 624,\n 625,\n 626,\n 627,\n 628,\n 629,\n 630,\n 631,\n 632,\n 633,\n 634,\n 635,\n 636,\n 637,\n 638,\n 639,\n 640,\n 641,\n 642,\n 643\n ],\n [\n 644,\n 645,\n 646,\n 647,\n 648,\n 649,\n 650,\n 651,\n 652,\n 653,\n 654,\n 655,\n 656,\n 657,\n 658,\n 659,\n 660,\n 661,\n 662,\n 663,\n 664,\n 665,\n 666,\n 667,\n 668,\n 669,\n 670,\n 671,\n 672,\n 673,\n 674,\n 675\n ],\n [\n 676,\n 677,\n 678,\n 679,\n 680,\n 681,\n 682,\n 683,\n 684,\n 685,\n 686,\n 687,\n 688,\n 689,\n 690,\n 691,\n 692,\n 693,\n 694,\n 695,\n 696,\n 697,\n 698,\n 699,\n 700,\n 701,\n 702,\n 703,\n 704,\n 705,\n 706,\n 707\n ],\n [\n 708,\n 709,\n 710,\n 711,\n 712,\n 713,\n 714,\n 715,\n 716,\n 717,\n 718,\n 719,\n 720,\n 721,\n 722,\n 723,\n 724,\n 725,\n 726,\n 727,\n 728,\n 729,\n 730,\n 731,\n 732,\n 733,\n 734,\n 735,\n 736,\n 737,\n 738,\n 739\n ],\n [\n 740,\n 741,\n 742,\n 743,\n 744,\n 745,\n 746,\n 747,\n 748,\n 749,\n 750,\n 751,\n 752,\n 753,\n 754,\n 755,\n 756,\n 757,\n 758,\n 759,\n 760,\n 761,\n 762,\n 763,\n 764,\n 765,\n 766,\n 767,\n 768,\n 769,\n 770,\n 771\n ],\n [\n 772,\n 773,\n 774,\n 775,\n 776,\n 777,\n 778,\n 779,\n 780,\n 781,\n 782,\n 783,\n 784,\n 785,\n 786,\n 787,\n 788,\n 789,\n 790,\n 791,\n 792,\n 793,\n 794,\n 795,\n 796,\n 797,\n 798,\n 799,\n 800,\n 801,\n 802,\n 803\n ],\n [\n 804,\n 805,\n 806,\n 807,\n 808,\n 809,\n 810,\n 811,\n 812,\n 813,\n 814,\n 815,\n 816,\n 817,\n 818,\n 819,\n 820,\n 821,\n 822,\n 823,\n 824,\n 825,\n 826,\n 827,\n 828,\n 829,\n 830,\n 831,\n 832,\n 833,\n 834,\n 835\n ],\n [\n 836,\n 837,\n 838,\n 839,\n 840,\n 841,\n 842,\n 843,\n 844,\n 845,\n 846,\n 847,\n 848,\n 849,\n 850,\n 851,\n 852,\n 853,\n 854,\n 855,\n 856,\n 857,\n 858,\n 859,\n 860,\n 861,\n 862,\n 863,\n 864,\n 865,\n 866,\n 867\n ],\n [\n 868,\n 869,\n 870,\n 871,\n 872,\n 873,\n 874,\n 875,\n 876,\n 877,\n 878,\n 879,\n 880,\n 881,\n 882,\n 883,\n 884,\n 885,\n 886,\n 887,\n 888,\n 889,\n 890,\n 891,\n 892,\n 893,\n 894,\n 895,\n 896,\n 897,\n 898,\n 899\n ],\n [\n 900,\n 901,\n 902,\n 903,\n 904,\n 905,\n 906,\n 907,\n 908,\n 909,\n 910,\n 911,\n 912,\n 913,\n 914,\n 915,\n 916,\n 917,\n 918,\n 919,\n 920,\n 921,\n 922,\n 923,\n 924,\n 925,\n 926,\n 927,\n 928,\n 929,\n 930,\n 931\n ],\n [\n 932,\n 933,\n 934,\n 935,\n 936,\n 937,\n 938,\n 939,\n 940,\n 941,\n 942,\n 943,\n 944,\n 945,\n 946,\n 947,\n 948,\n 949,\n 950,\n 951,\n 952,\n 953,\n 954,\n 955,\n 956,\n 957,\n 958,\n 959,\n 960,\n 961,\n 962,\n 963\n ],\n [\n 964,\n 965,\n 966,\n 967,\n 968,\n 969,\n 970,\n 971,\n 972,\n 973,\n 974,\n 975,\n 976,\n 977,\n 978,\n 979,\n 980,\n 981,\n 982,\n 983,\n 984,\n 985,\n 986,\n 987,\n 988,\n 989,\n 990,\n 991,\n 992,\n 993,\n 994,\n 995\n ],\n [\n 996,\n 997,\n 998,\n 999,\n 1000,\n 1001,\n 1002,\n 1003,\n 1004,\n 1005,\n 1006,\n 1007,\n 1008,\n 1009,\n 1010,\n 1011,\n 1012,\n 1013,\n 1014,\n 1015,\n 1016,\n 1017,\n 1018,\n 1019,\n 1020,\n 1021,\n 1022,\n 1023,\n 1024,\n 1025,\n 1026,\n 1027\n ],\n [\n 1028,\n 1029,\n 1030,\n 1031,\n 1032,\n 1033,\n 1034,\n 1035,\n 1036,\n 1037,\n 1038,\n 1039,\n 1040,\n 1041,\n 1042,\n 1043,\n 1044,\n 1045,\n 1046,\n 1047,\n 1048,\n 1049,\n 1050,\n 1051,\n 1052,\n 1053,\n 1054,\n 1055,\n 1056,\n 1057,\n 1058,\n 1059\n ],\n [\n 1060,\n 1061,\n 1062,\n 1063,\n 1064,\n 1065,\n 1066,\n 1067,\n 1068,\n 1069,\n 1070,\n 1071,\n 1072,\n 1073,\n 1074,\n 1075,\n 1076,\n 1077,\n 1078,\n 1079,\n 1080,\n 1081,\n 1082,\n 1083,\n 1084,\n 1085,\n 1086,\n 1087,\n 1088,\n 1089,\n 1090,\n 1091\n ],\n [\n 1092,\n 1093,\n 1094,\n 1095,\n 1096,\n 1097,\n 1098,\n 1099,\n 1100,\n 1101,\n 1102,\n 1103,\n 1104,\n 1105,\n 1106,\n 1107,\n 1108,\n 1109,\n 1110,\n 1111,\n 1112,\n 1113,\n 1114,\n 1115,\n 1116,\n 1117,\n 1118,\n 1119,\n 1120,\n 1121,\n 1122,\n 1123\n ]\n ],\n \"array_value_summary\": {\n \"shape\": [\n 32,\n 32\n ],\n \"dtype\": \"uint16\",\n \"size\": 1024,\n \"nonzero_count\": 1024,\n \"min\": 100,\n \"max\": 1123,\n \"requested\": true,\n \"included\": true,\n \"slice_ranges\": [\n [\n 0,\n 32\n ],\n [\n 0,\n 32\n ]\n ]\n },\n \"route_key\": \"origin_manual_kind_manual_projection_selected_images_e83ddc2185a63aca4b85ec471143f61c8f4eabdb08df3557ca21f2bddcda60b9\",\n \"shape_payloads\": []\n },\n {\n \"data_type\": \"image\",\n \"path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w2_z001_t001.tif\",\n \"components\": {\n \"site\": 1,\n \"channel\": 2,\n \"z_index\": 1,\n \"timepoint\": 1,\n \"well\": \"A01\"\n },\n \"axis_indices\": [\n 1\n ],\n \"aggregate_axis_indices\": [],\n \"summary\": {\n \"shape\": [\n 32,\n 32\n ],\n \"dtype\": \"uint16\",\n \"size\": 1024,\n \"nonzero_count\": 1024,\n \"min\": 200,\n \"max\": 1223,\n \"nonzero_min_coordinate\": [\n 0,\n 0\n ],\n \"nonzero_max_coordinate\": [\n 31,\n 31\n ],\n \"nonzero_example_coordinates\": [\n [\n 0,\n 0\n ],\n [\n 2,\n 4\n ],\n [\n 4,\n 8\n ],\n [\n 6,\n 12\n ],\n [\n 8,\n 16\n ],\n [\n 10,\n 21\n ],\n [\n 12,\n 25\n ],\n [\n 14,\n 29\n ],\n [\n 17,\n 1\n ],\n [\n 19,\n 5\n ],\n [\n 21,\n 10\n ],\n [\n 23,\n 14\n ],\n [\n 25,\n 18\n ],\n [\n 27,\n 22\n ],\n [\n 29,\n 26\n ],\n [\n 31,\n 31\n ]\n ],\n \"source_voxel_spacing\": {\n \"values_zyx\": [\n 1.3556,\n 1.3556\n ],\n \"unit\": \"micrometers\"\n },\n \"spatial_origin_yx\": [\n 0,\n 0\n ],\n \"source_spatial_shape_yx\": [\n 32,\n 32\n ],\n \"data_type\": \"image\",\n \"path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w2_z001_t001.tif\",\n \"components\": {\n \"site\": 1,\n \"channel\": 2,\n \"z_index\": 1,\n \"timepoint\": 1,\n \"well\": \"A01\"\n },\n \"payload_type\": \"ndarray\"\n },\n \"array_values\": [\n [\n 200,\n 201,\n 202,\n 203,\n 204,\n 205,\n 206,\n 207,\n 208,\n 209,\n 210,\n 211,\n 212,\n 213,\n 214,\n 215,\n 216,\n 217,\n 218,\n 219,\n 220,\n 221,\n 222,\n 223,\n 224,\n 225,\n 226,\n 227,\n 228,\n 229,\n 230,\n 231\n ],\n [\n 232,\n 233,\n 234,\n 235,\n 236,\n 237,\n 238,\n 239,\n 240,\n 241,\n 242,\n 243,\n 244,\n 245,\n 246,\n 247,\n 248,\n 249,\n 250,\n 251,\n 252,\n 253,\n 254,\n 255,\n 256,\n 257,\n 258,\n 259,\n 260,\n 261,\n 262,\n 263\n ],\n [\n 264,\n 265,\n 266,\n 267,\n 268,\n 269,\n 270,\n 271,\n 272,\n 273,\n 274,\n 275,\n 276,\n 277,\n 278,\n 279,\n 280,\n 281,\n 282,\n 283,\n 284,\n 285,\n 286,\n 287,\n 288,\n 289,\n 290,\n 291,\n 292,\n 293,\n 294,\n 295\n ],\n [\n 296,\n 297,\n 298,\n 299,\n 300,\n 301,\n 302,\n 303,\n 304,\n 305,\n 306,\n 307,\n 308,\n 309,\n 310,\n 311,\n 312,\n 313,\n 314,\n 315,\n 316,\n 317,\n 318,\n 319,\n 320,\n 321,\n 322,\n 323,\n 324,\n 325,\n 326,\n 327\n ],\n [\n 328,\n 329,\n 330,\n 331,\n 332,\n 333,\n 334,\n 335,\n 336,\n 337,\n 338,\n 339,\n 340,\n 341,\n 342,\n 343,\n 344,\n 345,\n 346,\n 347,\n 348,\n 349,\n 350,\n 351,\n 352,\n 353,\n 354,\n 355,\n 356,\n 357,\n 358,\n 359\n ],\n [\n 360,\n 361,\n 362,\n 363,\n 364,\n 365,\n 366,\n 367,\n 368,\n 369,\n 370,\n 371,\n 372,\n 373,\n 374,\n 375,\n 376,\n 377,\n 378,\n 379,\n 380,\n 381,\n 382,\n 383,\n 384,\n 385,\n 386,\n 387,\n 388,\n 389,\n 390,\n 391\n ],\n [\n 392,\n 393,\n 394,\n 395,\n 396,\n 397,\n 398,\n 399,\n 400,\n 401,\n 402,\n 403,\n 404,\n 405,\n 406,\n 407,\n 408,\n 409,\n 410,\n 411,\n 412,\n 413,\n 414,\n 415,\n 416,\n 417,\n 418,\n 419,\n 420,\n 421,\n 422,\n 423\n ],\n [\n 424,\n 425,\n 426,\n 427,\n 428,\n 429,\n 430,\n 431,\n 432,\n 433,\n 434,\n 435,\n 436,\n 437,\n 438,\n 439,\n 440,\n 441,\n 442,\n 443,\n 444,\n 445,\n 446,\n 447,\n 448,\n 449,\n 450,\n 451,\n 452,\n 453,\n 454,\n 455\n ],\n [\n 456,\n 457,\n 458,\n 459,\n 460,\n 461,\n 462,\n 463,\n 464,\n 465,\n 466,\n 467,\n 468,\n 469,\n 470,\n 471,\n 472,\n 473,\n 474,\n 475,\n 476,\n 477,\n 478,\n 479,\n 480,\n 481,\n 482,\n 483,\n 484,\n 485,\n 486,\n 487\n ],\n [\n 488,\n 489,\n 490,\n 491,\n 492,\n 493,\n 494,\n 495,\n 496,\n 497,\n 498,\n 499,\n 500,\n 501,\n 502,\n 503,\n 504,\n 505,\n 506,\n 507,\n 508,\n 509,\n 510,\n 511,\n 512,\n 513,\n 514,\n 515,\n 516,\n 517,\n 518,\n 519\n ],\n [\n 520,\n 521,\n 522,\n 523,\n 524,\n 525,\n 526,\n 527,\n 528,\n 529,\n 530,\n 531,\n 532,\n 533,\n 534,\n 535,\n 536,\n 537,\n 538,\n 539,\n 540,\n 541,\n 542,\n 543,\n 544,\n 545,\n 546,\n 547,\n 548,\n 549,\n 550,\n 551\n ],\n [\n 552,\n 553,\n 554,\n 555,\n 556,\n 557,\n 558,\n 559,\n 560,\n 561,\n 562,\n 563,\n 564,\n 565,\n 566,\n 567,\n 568,\n 569,\n 570,\n 571,\n 572,\n 573,\n 574,\n 575,\n 576,\n 577,\n 578,\n 579,\n 580,\n 581,\n 582,\n 583\n ],\n [\n 584,\n 585,\n 586,\n 587,\n 588,\n 589,\n 590,\n 591,\n 592,\n 593,\n 594,\n 595,\n 596,\n 597,\n 598,\n 599,\n 600,\n 601,\n 602,\n 603,\n 604,\n 605,\n 606,\n 607,\n 608,\n 609,\n 610,\n 611,\n 612,\n 613,\n 614,\n 615\n ],\n [\n 616,\n 617,\n 618,\n 619,\n 620,\n 621,\n 622,\n 623,\n 624,\n 625,\n 626,\n 627,\n 628,\n 629,\n 630,\n 631,\n 632,\n 633,\n 634,\n 635,\n 636,\n 637,\n 638,\n 639,\n 640,\n 641,\n 642,\n 643,\n 644,\n 645,\n 646,\n 647\n ],\n [\n 648,\n 649,\n 650,\n 651,\n 652,\n 653,\n 654,\n 655,\n 656,\n 657,\n 658,\n 659,\n 660,\n 661,\n 662,\n 663,\n 664,\n 665,\n 666,\n 667,\n 668,\n 669,\n 670,\n 671,\n 672,\n 673,\n 674,\n 675,\n 676,\n 677,\n 678,\n 679\n ],\n [\n 680,\n 681,\n 682,\n 683,\n 684,\n 685,\n 686,\n 687,\n 688,\n 689,\n 690,\n 691,\n 692,\n 693,\n 694,\n 695,\n 696,\n 697,\n 698,\n 699,\n 700,\n 701,\n 702,\n 703,\n 704,\n 705,\n 706,\n 707,\n 708,\n 709,\n 710,\n 711\n ],\n [\n 712,\n 713,\n 714,\n 715,\n 716,\n 717,\n 718,\n 719,\n 720,\n 721,\n 722,\n 723,\n 724,\n 725,\n 726,\n 727,\n 728,\n 729,\n 730,\n 731,\n 732,\n 733,\n 734,\n 735,\n 736,\n 737,\n 738,\n 739,\n 740,\n 741,\n 742,\n 743\n ],\n [\n 744,\n 745,\n 746,\n 747,\n 748,\n 749,\n 750,\n 751,\n 752,\n 753,\n 754,\n 755,\n 756,\n 757,\n 758,\n 759,\n 760,\n 761,\n 762,\n 763,\n 764,\n 765,\n 766,\n 767,\n 768,\n 769,\n 770,\n 771,\n 772,\n 773,\n 774,\n 775\n ],\n [\n 776,\n 777,\n 778,\n 779,\n 780,\n 781,\n 782,\n 783,\n 784,\n 785,\n 786,\n 787,\n 788,\n 789,\n 790,\n 791,\n 792,\n 793,\n 794,\n 795,\n 796,\n 797,\n 798,\n 799,\n 800,\n 801,\n 802,\n 803,\n 804,\n 805,\n 806,\n 807\n ],\n [\n 808,\n 809,\n 810,\n 811,\n 812,\n 813,\n 814,\n 815,\n 816,\n 817,\n 818,\n 819,\n 820,\n 821,\n 822,\n 823,\n 824,\n 825,\n 826,\n 827,\n 828,\n 829,\n 830,\n 831,\n 832,\n 833,\n 834,\n 835,\n 836,\n 837,\n 838,\n 839\n ],\n [\n 840,\n 841,\n 842,\n 843,\n 844,\n 845,\n 846,\n 847,\n 848,\n 849,\n 850,\n 851,\n 852,\n 853,\n 854,\n 855,\n 856,\n 857,\n 858,\n 859,\n 860,\n 861,\n 862,\n 863,\n 864,\n 865,\n 866,\n 867,\n 868,\n 869,\n 870,\n 871\n ],\n [\n 872,\n 873,\n 874,\n 875,\n 876,\n 877,\n 878,\n 879,\n 880,\n 881,\n 882,\n 883,\n 884,\n 885,\n 886,\n 887,\n 888,\n 889,\n 890,\n 891,\n 892,\n 893,\n 894,\n 895,\n 896,\n 897,\n 898,\n 899,\n 900,\n 901,\n 902,\n 903\n ],\n [\n 904,\n 905,\n 906,\n 907,\n 908,\n 909,\n 910,\n 911,\n 912,\n 913,\n 914,\n 915,\n 916,\n 917,\n 918,\n 919,\n 920,\n 921,\n 922,\n 923,\n 924,\n 925,\n 926,\n 927,\n 928,\n 929,\n 930,\n 931,\n 932,\n 933,\n 934,\n 935\n ],\n [\n 936,\n 937,\n 938,\n 939,\n 940,\n 941,\n 942,\n 943,\n 944,\n 945,\n 946,\n 947,\n 948,\n 949,\n 950,\n 951,\n 952,\n 953,\n 954,\n 955,\n 956,\n 957,\n 958,\n 959,\n 960,\n 961,\n 962,\n 963,\n 964,\n 965,\n 966,\n 967\n ],\n [\n 968,\n 969,\n 970,\n 971,\n 972,\n 973,\n 974,\n 975,\n 976,\n 977,\n 978,\n 979,\n 980,\n 981,\n 982,\n 983,\n 984,\n 985,\n 986,\n 987,\n 988,\n 989,\n 990,\n 991,\n 992,\n 993,\n 994,\n 995,\n 996,\n 997,\n 998,\n 999\n ],\n [\n 1000,\n 1001,\n 1002,\n 1003,\n 1004,\n 1005,\n 1006,\n 1007,\n 1008,\n 1009,\n 1010,\n 1011,\n 1012,\n 1013,\n 1014,\n 1015,\n 1016,\n 1017,\n 1018,\n 1019,\n 1020,\n 1021,\n 1022,\n 1023,\n 1024,\n 1025,\n 1026,\n 1027,\n 1028,\n 1029,\n 1030,\n 1031\n ],\n [\n 1032,\n 1033,\n 1034,\n 1035,\n 1036,\n 1037,\n 1038,\n 1039,\n 1040,\n 1041,\n 1042,\n 1043,\n 1044,\n 1045,\n 1046,\n 1047,\n 1048,\n 1049,\n 1050,\n 1051,\n 1052,\n 1053,\n 1054,\n 1055,\n 1056,\n 1057,\n 1058,\n 1059,\n 1060,\n 1061,\n 1062,\n 1063\n ],\n [\n 1064,\n 1065,\n 1066,\n 1067,\n 1068,\n 1069,\n 1070,\n 1071,\n 1072,\n 1073,\n 1074,\n 1075,\n 1076,\n 1077,\n 1078,\n 1079,\n 1080,\n 1081,\n 1082,\n 1083,\n 1084,\n 1085,\n 1086,\n 1087,\n 1088,\n 1089,\n 1090,\n 1091,\n 1092,\n 1093,\n 1094,\n 1095\n ],\n [\n 1096,\n 1097,\n 1098,\n 1099,\n 1100,\n 1101,\n 1102,\n 1103,\n 1104,\n 1105,\n 1106,\n 1107,\n 1108,\n 1109,\n 1110,\n 1111,\n 1112,\n 1113,\n 1114,\n 1115,\n 1116,\n 1117,\n 1118,\n 1119,\n 1120,\n 1121,\n 1122,\n 1123,\n 1124,\n 1125,\n 1126,\n 1127\n ],\n [\n 1128,\n 1129,\n 1130,\n 1131,\n 1132,\n 1133,\n 1134,\n 1135,\n 1136,\n 1137,\n 1138,\n 1139,\n 1140,\n 1141,\n 1142,\n 1143,\n 1144,\n 1145,\n 1146,\n 1147,\n 1148,\n 1149,\n 1150,\n 1151,\n 1152,\n 1153,\n 1154,\n 1155,\n 1156,\n 1157,\n 1158,\n 1159\n ],\n [\n 1160,\n 1161,\n 1162,\n 1163,\n 1164,\n 1165,\n 1166,\n 1167,\n 1168,\n 1169,\n 1170,\n 1171,\n 1172,\n 1173,\n 1174,\n 1175,\n 1176,\n 1177,\n 1178,\n 1179,\n 1180,\n 1181,\n 1182,\n 1183,\n 1184,\n 1185,\n 1186,\n 1187,\n 1188,\n 1189,\n 1190,\n 1191\n ],\n [\n 1192,\n 1193,\n 1194,\n 1195,\n 1196,\n 1197,\n 1198,\n 1199,\n 1200,\n 1201,\n 1202,\n 1203,\n 1204,\n 1205,\n 1206,\n 1207,\n 1208,\n 1209,\n 1210,\n 1211,\n 1212,\n 1213,\n 1214,\n 1215,\n 1216,\n 1217,\n 1218,\n 1219,\n 1220,\n 1221,\n 1222,\n 1223\n ]\n ],\n \"array_value_summary\": {\n \"shape\": [\n 32,\n 32\n ],\n \"dtype\": \"uint16\",\n \"size\": 1024,\n \"nonzero_count\": 1024,\n \"min\": 200,\n \"max\": 1223,\n \"requested\": true,\n \"included\": true,\n \"slice_ranges\": [\n [\n 0,\n 32\n ],\n [\n 0,\n 32\n ]\n ]\n },\n \"route_key\": \"origin_manual_kind_manual_projection_selected_images_e83ddc2185a63aca4b85ec471143f61c8f4eabdb08df3557ca21f2bddcda60b9\",\n \"shape_payloads\": []\n }\n ]\n },\n {\n \"route_key\": \"origin_manual_kind_manual_projection_A01_s001_w2_z001_t001_graph.graph.roi.zip_shapes\",\n \"title\": \"A01_s001_w2_z001_t001_graph.graph.roi.zip ROIs\",\n \"mounted\": true,\n \"item_count\": 1,\n \"producer_identities\": [\n {\n \"origin\": \"manual\",\n \"output_kind\": \"manual\",\n \"output_key\": \"A01_s001_w2_z001_t001_graph.graph.roi.zip\",\n \"projection_key\": \"A01_s001_w2_z001_t001_graph.graph.roi.zip\",\n \"step_name\": null,\n \"pipeline_position\": null,\n \"step_scope_id\": null,\n \"invocation_key\": null,\n \"artifact_kind\": null\n }\n ],\n \"axis_labels\": [\n \"site\",\n \"channel\",\n \"z_index\",\n \"timepoint\",\n \"well\",\n \"y\",\n \"x\"\n ],\n \"stack_axes\": [\n \"channel\"\n ],\n \"pending_update\": false,\n \"payloads\": [\n {\n \"data_type\": \"shapes\",\n \"path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/graph_results/A01_s001_w2_z001_t001_graph.graph.roi.zip\",\n \"components\": {\n \"site\": 1,\n \"channel\": 2,\n \"z_index\": 1,\n \"timepoint\": 1,\n \"well\": \"A01\"\n },\n \"axis_indices\": [\n 0\n ],\n \"aggregate_axis_indices\": [],\n \"summary\": {\n \"nonzero_count\": 2,\n \"item_count\": 2,\n \"shape_payload_count\": 2,\n \"missing_source_spatial_shape_count\": 2,\n \"shape_coordinate_count\": 4,\n \"shape_out_of_source_bounds_count\": 0,\n \"shape_coordinate_bounds_yx\": {\n \"min_yx\": [\n 2.25,\n 3.5\n ],\n \"max_yx\": [\n 7.25,\n 12.5\n ],\n \"coordinate_count\": 4\n },\n \"source_voxel_spacing\": {\n \"values_zyx\": [\n 1.3556,\n 1.3556\n ],\n \"unit\": \"micrometers\"\n },\n \"data_type\": \"shapes\",\n \"path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/graph_results/A01_s001_w2_z001_t001_graph.graph.roi.zip\",\n \"components\": {\n \"site\": 1,\n \"channel\": 2,\n \"z_index\": 1,\n \"timepoint\": 1,\n \"well\": \"A01\"\n },\n \"payload_type\": \"list\"\n },\n \"array_values\": [],\n \"array_value_summary\": {\n \"requested\": true,\n \"included\": false,\n \"omitted_reason\": \"payload_not_ndarray\"\n },\n \"route_key\": \"origin_manual_kind_manual_projection_A01_s001_w2_z001_t001_graph.graph.roi.zip_shapes\",\n \"shape_payloads\": [\n {\n \"type\": \"path\",\n \"coordinates\": [\n [\n 2.25,\n 3.5\n ],\n [\n 5.25,\n 9.5\n ]\n ],\n \"metadata\": {\n \"__openhcs_object_subject__\": \"[\\\"output\\\",\\\"object_labels\\\",\\\"neurons\\\",\\\"synthetic-receiving-134\\\",4]\",\n \"__openhcs_object_subject_id__\": 7,\n \"area\": 0.0,\n \"branch_distance_um\": 8.5,\n \"centroid\": [\n 3.75,\n 6.5\n ],\n \"edge_id\": 1,\n \"graph\": \"declared_graph\",\n \"label\": 1,\n \"neuron_label\": 7,\n \"openhcs_image_payload_metadata\": {\n \"intensity_scale\": null,\n \"mask_defines_border\": null,\n \"physical_border_edges_yx\": null,\n \"plane_axis\": null,\n \"source_channel_axis\": null,\n \"source_dtype\": null,\n \"source_plane_dtypes\": [],\n \"source_plane_intensity_scales\": [],\n \"source_provenance\": {\n \"source_component_metadata\": {\n \"OpenHCSSourceVoxelSpacingUnit\": \"micrometers\",\n \"OpenHCSSourceVoxelSpacingZYX\": \"1.3555999999999999,1.3555999999999999\",\n \"channel\": \"2\",\n \"site\": \"1\",\n \"timepoint\": \"1\",\n \"well\": \"A01\",\n \"z_index\": \"1\"\n },\n \"source_image_names\": [\n \"raw_2\"\n ],\n \"source_image_provenance_planes\": [],\n \"source_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w2_z001_t001.tif\"\n },\n \"source_spatial_domain\": {\n \"fill_value\": 0,\n \"origin_yx\": null,\n \"source_shape_yx\": null,\n \"spatial_dimensions\": 2,\n \"value_name\": \"Dense array\"\n },\n \"source_voxel_spacing\": {\n \"unit\": \"micrometers\",\n \"values_zyx\": [\n 1.3556,\n 1.3556\n ]\n },\n \"unit_interval_intensity\": null\n },\n \"perimeter\": 6.708203932499369,\n \"source_node_id\": 1,\n \"target_node_id\": 2\n }\n },\n {\n \"type\": \"path\",\n \"coordinates\": [\n [\n 5.25,\n 9.5\n ],\n [\n 7.25,\n 12.5\n ]\n ],\n \"metadata\": {\n \"__openhcs_object_subject__\": \"[\\\"output\\\",\\\"object_labels\\\",\\\"neurons\\\",\\\"synthetic-receiving-134\\\",4]\",\n \"__openhcs_object_subject_id__\": 7,\n \"area\": 0.0,\n \"branch_distance_um\": 8.5,\n \"centroid\": [\n 6.25,\n 11.0\n ],\n \"edge_id\": 2,\n \"graph\": \"declared_graph\",\n \"label\": 2,\n \"neuron_label\": 7,\n \"openhcs_image_payload_metadata\": {\n \"intensity_scale\": null,\n \"mask_defines_border\": null,\n \"physical_border_edges_yx\": null,\n \"plane_axis\": null,\n \"source_channel_axis\": null,\n \"source_dtype\": null,\n \"source_plane_dtypes\": [],\n \"source_plane_intensity_scales\": [],\n \"source_provenance\": {\n \"source_component_metadata\": {\n \"OpenHCSSourceVoxelSpacingUnit\": \"micrometers\",\n \"OpenHCSSourceVoxelSpacingZYX\": \"1.3555999999999999,1.3555999999999999\",\n \"channel\": \"2\",\n \"site\": \"1\",\n \"timepoint\": \"1\",\n \"well\": \"A01\",\n \"z_index\": \"1\"\n },\n \"source_image_names\": [\n \"raw_2\"\n ],\n \"source_image_provenance_planes\": [],\n \"source_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w2_z001_t001.tif\"\n },\n \"source_spatial_domain\": {\n \"fill_value\": 0,\n \"origin_yx\": null,\n \"source_shape_yx\": null,\n \"spatial_dimensions\": 2,\n \"value_name\": \"Dense array\"\n },\n \"source_voxel_spacing\": {\n \"unit\": \"micrometers\",\n \"values_zyx\": [\n 1.3556,\n 1.3556\n ]\n },\n \"unit_interval_intensity\": null\n },\n \"perimeter\": 3.605551275463989,\n \"source_node_id\": 2,\n \"target_node_id\": 3\n }\n }\n ]\n }\n ]\n }\n ],\n \"response\": {}\n}" + } + ], + "structuredContent": { + "connection": { + "host": "127.0.0.1", + "port": 6609, + "transport_mode": "tcp", + "persistent": true + }, + "schema_version": "openhcs.agent.v1", + "errors": [], + "warnings": [], + "observed": true, + "viewer": { + "viewer_type": "napari", + "title": "OpenHCS Napari Visualization" + }, + "layer_count": 3, + "layers": [ + { + "route_key": "origin_manual_kind_manual_projection_selected_images_8c7357d46ccc38823ca9e68096baf86f25c3004b61b63ba1eef9adea41d34fb8_scalar_stack", + "title": "selected_images image stack", + "mounted": true, + "item_count": 1, + "producer_identities": [ + { + "origin": "manual", + "output_kind": "manual", + "output_key": "selected_images", + "projection_key": "selected_images_8c7357d46ccc38823ca9e68096baf86f25c3004b61b63ba1eef9adea41d34fb8", + "step_name": null, + "pipeline_position": null, + "step_scope_id": null, + "invocation_key": null, + "artifact_kind": null + } + ], + "axis_labels": [ + "site", + "channel", + "z_index", + "timepoint", + "well", + "y", + "x" + ], + "stack_axes": [ + "channel" + ], + "pending_update": false, + "payloads": [ + { + "data_type": "image", + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/stacked_labels/A01_s001_w2_z001_t001_Labels.tif", + "components": { + "site": 1, + "z_index": 1, + "timepoint": 1, + "well": "A01", + "channel": 2 + }, + "axis_indices": [ + 1 + ], + "aggregate_axis_indices": [ + 0 + ], + "summary": { + "shape": [ + 32, + 32 + ], + "dtype": "uint16", + "size": 1024, + "nonzero_count": 154, + "min": 0, + "max": 22, + "nonzero_min_coordinate": [ + 3, + 4 + ], + "nonzero_max_coordinate": [ + 24, + 27 + ], + "nonzero_example_coordinates": [ + [ + 3, + 4 + ], + [ + 4, + 4 + ], + [ + 5, + 4 + ], + [ + 6, + 4 + ], + [ + 7, + 4 + ], + [ + 8, + 5 + ], + [ + 9, + 5 + ], + [ + 10, + 5 + ], + [ + 11, + 5 + ], + [ + 17, + 21 + ], + [ + 18, + 24 + ], + [ + 19, + 26 + ], + [ + 21, + 20 + ], + [ + 22, + 22 + ], + [ + 23, + 24 + ], + [ + 24, + 27 + ] + ], + "source_voxel_spacing": { + "values_zyx": [ + 1.3556, + 1.3556 + ], + "unit": "micrometers" + }, + "spatial_origin_yx": [ + 0, + 0 + ], + "source_spatial_shape_yx": [ + 32, + 32 + ], + "data_type": "image", + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/stacked_labels/A01_s001_w2_z001_t001_Labels.tif", + "components": { + "site": 1, + "z_index": 1, + "timepoint": 1, + "well": "A01", + "channel": 2 + }, + "payload_type": "ndarray" + }, + "array_values": [ + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 14, + 14, + 14, + 14, + 14, + 14, + 14, + 14, + 14, + 14, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 14, + 14, + 14, + 14, + 14, + 14, + 14, + 14, + 14, + 14, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 14, + 14, + 14, + 14, + 14, + 14, + 14, + 14, + 14, + 14, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 14, + 14, + 14, + 14, + 14, + 14, + 14, + 14, + 14, + 14, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 14, + 14, + 14, + 14, + 14, + 14, + 14, + 14, + 14, + 14, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 14, + 14, + 14, + 14, + 14, + 14, + 14, + 14, + 14, + 14, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 14, + 14, + 14, + 14, + 14, + 14, + 14, + 14, + 14, + 14, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 14, + 14, + 14, + 14, + 14, + 14, + 14, + 14, + 14, + 14, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 14, + 14, + 14, + 14, + 14, + 14, + 14, + 14, + 14, + 14, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 22, + 22, + 22, + 22, + 22, + 22, + 22, + 22, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 22, + 22, + 22, + 22, + 22, + 22, + 22, + 22, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 22, + 22, + 22, + 22, + 22, + 22, + 22, + 22, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 22, + 22, + 22, + 22, + 22, + 22, + 22, + 22, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 22, + 22, + 22, + 22, + 22, + 22, + 22, + 22, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 22, + 22, + 22, + 22, + 22, + 22, + 22, + 22, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 22, + 22, + 22, + 22, + 22, + 22, + 22, + 22, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 22, + 22, + 22, + 22, + 22, + 22, + 22, + 22, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ] + ], + "array_value_summary": { + "shape": [ + 32, + 32 + ], + "dtype": "uint16", + "size": 1024, + "nonzero_count": 154, + "min": 0, + "max": 22, + "requested": true, + "included": true, + "slice_ranges": [ + [ + 0, + 32 + ], + [ + 0, + 32 + ] + ] + }, + "route_key": "origin_manual_kind_manual_projection_selected_images_8c7357d46ccc38823ca9e68096baf86f25c3004b61b63ba1eef9adea41d34fb8_scalar_stack", + "shape_payloads": [] + }, + { + "data_type": "image", + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/stacked_labels/A01_s001_w2_z001_t001_Labels.tif", + "components": { + "site": 1, + "z_index": 1, + "timepoint": 1, + "well": "A01", + "channel": 1 + }, + "axis_indices": [ + 0 + ], + "aggregate_axis_indices": [ + 1 + ], + "summary": { + "shape": [ + 32, + 32 + ], + "dtype": "uint16", + "size": 1024, + "nonzero_count": 154, + "min": 0, + "max": 11, + "nonzero_min_coordinate": [ + 3, + 4 + ], + "nonzero_max_coordinate": [ + 24, + 27 + ], + "nonzero_example_coordinates": [ + [ + 3, + 4 + ], + [ + 4, + 4 + ], + [ + 5, + 4 + ], + [ + 6, + 4 + ], + [ + 7, + 4 + ], + [ + 8, + 5 + ], + [ + 9, + 5 + ], + [ + 10, + 5 + ], + [ + 11, + 5 + ], + [ + 17, + 21 + ], + [ + 18, + 24 + ], + [ + 19, + 26 + ], + [ + 21, + 20 + ], + [ + 22, + 22 + ], + [ + 23, + 24 + ], + [ + 24, + 27 + ] + ], + "source_voxel_spacing": { + "values_zyx": [ + 1.3556, + 1.3556 + ], + "unit": "micrometers" + }, + "spatial_origin_yx": [ + 0, + 0 + ], + "source_spatial_shape_yx": [ + 32, + 32 + ], + "data_type": "image", + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/stacked_labels/A01_s001_w2_z001_t001_Labels.tif", + "components": { + "site": 1, + "z_index": 1, + "timepoint": 1, + "well": "A01", + "channel": 1 + }, + "payload_type": "ndarray" + }, + "array_values": [ + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 11, + 11, + 11, + 11, + 11, + 11, + 11, + 11, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 11, + 11, + 11, + 11, + 11, + 11, + 11, + 11, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 11, + 11, + 11, + 11, + 11, + 11, + 11, + 11, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 11, + 11, + 11, + 11, + 11, + 11, + 11, + 11, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 11, + 11, + 11, + 11, + 11, + 11, + 11, + 11, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 11, + 11, + 11, + 11, + 11, + 11, + 11, + 11, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 11, + 11, + 11, + 11, + 11, + 11, + 11, + 11, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 11, + 11, + 11, + 11, + 11, + 11, + 11, + 11, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ] + ], + "array_value_summary": { + "shape": [ + 32, + 32 + ], + "dtype": "uint16", + "size": 1024, + "nonzero_count": 154, + "min": 0, + "max": 11, + "requested": true, + "included": true, + "slice_ranges": [ + [ + 0, + 32 + ], + [ + 0, + 32 + ] + ] + }, + "route_key": "origin_manual_kind_manual_projection_selected_images_8c7357d46ccc38823ca9e68096baf86f25c3004b61b63ba1eef9adea41d34fb8_scalar_stack", + "shape_payloads": [] + } + ] + }, + { + "route_key": "origin_manual_kind_manual_projection_selected_images_e83ddc2185a63aca4b85ec471143f61c8f4eabdb08df3557ca21f2bddcda60b9", + "title": "selected_images", + "mounted": true, + "item_count": 2, + "producer_identities": [ + { + "origin": "manual", + "output_kind": "manual", + "output_key": "selected_images", + "projection_key": "selected_images_e83ddc2185a63aca4b85ec471143f61c8f4eabdb08df3557ca21f2bddcda60b9", + "step_name": null, + "pipeline_position": null, + "step_scope_id": null, + "invocation_key": null, + "artifact_kind": null + } + ], + "axis_labels": [ + "site", + "channel", + "z_index", + "timepoint", + "well", + "y", + "x" + ], + "stack_axes": [ + "channel" + ], + "pending_update": false, + "payloads": [ + { + "data_type": "image", + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w1_z001_t001.tif", + "components": { + "site": 1, + "channel": 1, + "z_index": 1, + "timepoint": 1, + "well": "A01" + }, + "axis_indices": [ + 0 + ], + "aggregate_axis_indices": [], + "summary": { + "shape": [ + 32, + 32 + ], + "dtype": "uint16", + "size": 1024, + "nonzero_count": 1024, + "min": 100, + "max": 1123, + "nonzero_min_coordinate": [ + 0, + 0 + ], + "nonzero_max_coordinate": [ + 31, + 31 + ], + "nonzero_example_coordinates": [ + [ + 0, + 0 + ], + [ + 2, + 4 + ], + [ + 4, + 8 + ], + [ + 6, + 12 + ], + [ + 8, + 16 + ], + [ + 10, + 21 + ], + [ + 12, + 25 + ], + [ + 14, + 29 + ], + [ + 17, + 1 + ], + [ + 19, + 5 + ], + [ + 21, + 10 + ], + [ + 23, + 14 + ], + [ + 25, + 18 + ], + [ + 27, + 22 + ], + [ + 29, + 26 + ], + [ + 31, + 31 + ] + ], + "source_voxel_spacing": { + "values_zyx": [ + 1.3556, + 1.3556 + ], + "unit": "micrometers" + }, + "spatial_origin_yx": [ + 0, + 0 + ], + "source_spatial_shape_yx": [ + 32, + 32 + ], + "data_type": "image", + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w1_z001_t001.tif", + "components": { + "site": 1, + "channel": 1, + "z_index": 1, + "timepoint": 1, + "well": "A01" + }, + "payload_type": "ndarray" + }, + "array_values": [ + [ + 100, + 101, + 102, + 103, + 104, + 105, + 106, + 107, + 108, + 109, + 110, + 111, + 112, + 113, + 114, + 115, + 116, + 117, + 118, + 119, + 120, + 121, + 122, + 123, + 124, + 125, + 126, + 127, + 128, + 129, + 130, + 131 + ], + [ + 132, + 133, + 134, + 135, + 136, + 137, + 138, + 139, + 140, + 141, + 142, + 143, + 144, + 145, + 146, + 147, + 148, + 149, + 150, + 151, + 152, + 153, + 154, + 155, + 156, + 157, + 158, + 159, + 160, + 161, + 162, + 163 + ], + [ + 164, + 165, + 166, + 167, + 168, + 169, + 170, + 171, + 172, + 173, + 174, + 175, + 176, + 177, + 178, + 179, + 180, + 181, + 182, + 183, + 184, + 185, + 186, + 187, + 188, + 189, + 190, + 191, + 192, + 193, + 194, + 195 + ], + [ + 196, + 197, + 198, + 199, + 200, + 201, + 202, + 203, + 204, + 205, + 206, + 207, + 208, + 209, + 210, + 211, + 212, + 213, + 214, + 215, + 216, + 217, + 218, + 219, + 220, + 221, + 222, + 223, + 224, + 225, + 226, + 227 + ], + [ + 228, + 229, + 230, + 231, + 232, + 233, + 234, + 235, + 236, + 237, + 238, + 239, + 240, + 241, + 242, + 243, + 244, + 245, + 246, + 247, + 248, + 249, + 250, + 251, + 252, + 253, + 254, + 255, + 256, + 257, + 258, + 259 + ], + [ + 260, + 261, + 262, + 263, + 264, + 265, + 266, + 267, + 268, + 269, + 270, + 271, + 272, + 273, + 274, + 275, + 276, + 277, + 278, + 279, + 280, + 281, + 282, + 283, + 284, + 285, + 286, + 287, + 288, + 289, + 290, + 291 + ], + [ + 292, + 293, + 294, + 295, + 296, + 297, + 298, + 299, + 300, + 301, + 302, + 303, + 304, + 305, + 306, + 307, + 308, + 309, + 310, + 311, + 312, + 313, + 314, + 315, + 316, + 317, + 318, + 319, + 320, + 321, + 322, + 323 + ], + [ + 324, + 325, + 326, + 327, + 328, + 329, + 330, + 331, + 332, + 333, + 334, + 335, + 336, + 337, + 338, + 339, + 340, + 341, + 342, + 343, + 344, + 345, + 346, + 347, + 348, + 349, + 350, + 351, + 352, + 353, + 354, + 355 + ], + [ + 356, + 357, + 358, + 359, + 360, + 361, + 362, + 363, + 364, + 365, + 366, + 367, + 368, + 369, + 370, + 371, + 372, + 373, + 374, + 375, + 376, + 377, + 378, + 379, + 380, + 381, + 382, + 383, + 384, + 385, + 386, + 387 + ], + [ + 388, + 389, + 390, + 391, + 392, + 393, + 394, + 395, + 396, + 397, + 398, + 399, + 400, + 401, + 402, + 403, + 404, + 405, + 406, + 407, + 408, + 409, + 410, + 411, + 412, + 413, + 414, + 415, + 416, + 417, + 418, + 419 + ], + [ + 420, + 421, + 422, + 423, + 424, + 425, + 426, + 427, + 428, + 429, + 430, + 431, + 432, + 433, + 434, + 435, + 436, + 437, + 438, + 439, + 440, + 441, + 442, + 443, + 444, + 445, + 446, + 447, + 448, + 449, + 450, + 451 + ], + [ + 452, + 453, + 454, + 455, + 456, + 457, + 458, + 459, + 460, + 461, + 462, + 463, + 464, + 465, + 466, + 467, + 468, + 469, + 470, + 471, + 472, + 473, + 474, + 475, + 476, + 477, + 478, + 479, + 480, + 481, + 482, + 483 + ], + [ + 484, + 485, + 486, + 487, + 488, + 489, + 490, + 491, + 492, + 493, + 494, + 495, + 496, + 497, + 498, + 499, + 500, + 501, + 502, + 503, + 504, + 505, + 506, + 507, + 508, + 509, + 510, + 511, + 512, + 513, + 514, + 515 + ], + [ + 516, + 517, + 518, + 519, + 520, + 521, + 522, + 523, + 524, + 525, + 526, + 527, + 528, + 529, + 530, + 531, + 532, + 533, + 534, + 535, + 536, + 537, + 538, + 539, + 540, + 541, + 542, + 543, + 544, + 545, + 546, + 547 + ], + [ + 548, + 549, + 550, + 551, + 552, + 553, + 554, + 555, + 556, + 557, + 558, + 559, + 560, + 561, + 562, + 563, + 564, + 565, + 566, + 567, + 568, + 569, + 570, + 571, + 572, + 573, + 574, + 575, + 576, + 577, + 578, + 579 + ], + [ + 580, + 581, + 582, + 583, + 584, + 585, + 586, + 587, + 588, + 589, + 590, + 591, + 592, + 593, + 594, + 595, + 596, + 597, + 598, + 599, + 600, + 601, + 602, + 603, + 604, + 605, + 606, + 607, + 608, + 609, + 610, + 611 + ], + [ + 612, + 613, + 614, + 615, + 616, + 617, + 618, + 619, + 620, + 621, + 622, + 623, + 624, + 625, + 626, + 627, + 628, + 629, + 630, + 631, + 632, + 633, + 634, + 635, + 636, + 637, + 638, + 639, + 640, + 641, + 642, + 643 + ], + [ + 644, + 645, + 646, + 647, + 648, + 649, + 650, + 651, + 652, + 653, + 654, + 655, + 656, + 657, + 658, + 659, + 660, + 661, + 662, + 663, + 664, + 665, + 666, + 667, + 668, + 669, + 670, + 671, + 672, + 673, + 674, + 675 + ], + [ + 676, + 677, + 678, + 679, + 680, + 681, + 682, + 683, + 684, + 685, + 686, + 687, + 688, + 689, + 690, + 691, + 692, + 693, + 694, + 695, + 696, + 697, + 698, + 699, + 700, + 701, + 702, + 703, + 704, + 705, + 706, + 707 + ], + [ + 708, + 709, + 710, + 711, + 712, + 713, + 714, + 715, + 716, + 717, + 718, + 719, + 720, + 721, + 722, + 723, + 724, + 725, + 726, + 727, + 728, + 729, + 730, + 731, + 732, + 733, + 734, + 735, + 736, + 737, + 738, + 739 + ], + [ + 740, + 741, + 742, + 743, + 744, + 745, + 746, + 747, + 748, + 749, + 750, + 751, + 752, + 753, + 754, + 755, + 756, + 757, + 758, + 759, + 760, + 761, + 762, + 763, + 764, + 765, + 766, + 767, + 768, + 769, + 770, + 771 + ], + [ + 772, + 773, + 774, + 775, + 776, + 777, + 778, + 779, + 780, + 781, + 782, + 783, + 784, + 785, + 786, + 787, + 788, + 789, + 790, + 791, + 792, + 793, + 794, + 795, + 796, + 797, + 798, + 799, + 800, + 801, + 802, + 803 + ], + [ + 804, + 805, + 806, + 807, + 808, + 809, + 810, + 811, + 812, + 813, + 814, + 815, + 816, + 817, + 818, + 819, + 820, + 821, + 822, + 823, + 824, + 825, + 826, + 827, + 828, + 829, + 830, + 831, + 832, + 833, + 834, + 835 + ], + [ + 836, + 837, + 838, + 839, + 840, + 841, + 842, + 843, + 844, + 845, + 846, + 847, + 848, + 849, + 850, + 851, + 852, + 853, + 854, + 855, + 856, + 857, + 858, + 859, + 860, + 861, + 862, + 863, + 864, + 865, + 866, + 867 + ], + [ + 868, + 869, + 870, + 871, + 872, + 873, + 874, + 875, + 876, + 877, + 878, + 879, + 880, + 881, + 882, + 883, + 884, + 885, + 886, + 887, + 888, + 889, + 890, + 891, + 892, + 893, + 894, + 895, + 896, + 897, + 898, + 899 + ], + [ + 900, + 901, + 902, + 903, + 904, + 905, + 906, + 907, + 908, + 909, + 910, + 911, + 912, + 913, + 914, + 915, + 916, + 917, + 918, + 919, + 920, + 921, + 922, + 923, + 924, + 925, + 926, + 927, + 928, + 929, + 930, + 931 + ], + [ + 932, + 933, + 934, + 935, + 936, + 937, + 938, + 939, + 940, + 941, + 942, + 943, + 944, + 945, + 946, + 947, + 948, + 949, + 950, + 951, + 952, + 953, + 954, + 955, + 956, + 957, + 958, + 959, + 960, + 961, + 962, + 963 + ], + [ + 964, + 965, + 966, + 967, + 968, + 969, + 970, + 971, + 972, + 973, + 974, + 975, + 976, + 977, + 978, + 979, + 980, + 981, + 982, + 983, + 984, + 985, + 986, + 987, + 988, + 989, + 990, + 991, + 992, + 993, + 994, + 995 + ], + [ + 996, + 997, + 998, + 999, + 1000, + 1001, + 1002, + 1003, + 1004, + 1005, + 1006, + 1007, + 1008, + 1009, + 1010, + 1011, + 1012, + 1013, + 1014, + 1015, + 1016, + 1017, + 1018, + 1019, + 1020, + 1021, + 1022, + 1023, + 1024, + 1025, + 1026, + 1027 + ], + [ + 1028, + 1029, + 1030, + 1031, + 1032, + 1033, + 1034, + 1035, + 1036, + 1037, + 1038, + 1039, + 1040, + 1041, + 1042, + 1043, + 1044, + 1045, + 1046, + 1047, + 1048, + 1049, + 1050, + 1051, + 1052, + 1053, + 1054, + 1055, + 1056, + 1057, + 1058, + 1059 + ], + [ + 1060, + 1061, + 1062, + 1063, + 1064, + 1065, + 1066, + 1067, + 1068, + 1069, + 1070, + 1071, + 1072, + 1073, + 1074, + 1075, + 1076, + 1077, + 1078, + 1079, + 1080, + 1081, + 1082, + 1083, + 1084, + 1085, + 1086, + 1087, + 1088, + 1089, + 1090, + 1091 + ], + [ + 1092, + 1093, + 1094, + 1095, + 1096, + 1097, + 1098, + 1099, + 1100, + 1101, + 1102, + 1103, + 1104, + 1105, + 1106, + 1107, + 1108, + 1109, + 1110, + 1111, + 1112, + 1113, + 1114, + 1115, + 1116, + 1117, + 1118, + 1119, + 1120, + 1121, + 1122, + 1123 + ] + ], + "array_value_summary": { + "shape": [ + 32, + 32 + ], + "dtype": "uint16", + "size": 1024, + "nonzero_count": 1024, + "min": 100, + "max": 1123, + "requested": true, + "included": true, + "slice_ranges": [ + [ + 0, + 32 + ], + [ + 0, + 32 + ] + ] + }, + "route_key": "origin_manual_kind_manual_projection_selected_images_e83ddc2185a63aca4b85ec471143f61c8f4eabdb08df3557ca21f2bddcda60b9", + "shape_payloads": [] + }, + { + "data_type": "image", + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w2_z001_t001.tif", + "components": { + "site": 1, + "channel": 2, + "z_index": 1, + "timepoint": 1, + "well": "A01" + }, + "axis_indices": [ + 1 + ], + "aggregate_axis_indices": [], + "summary": { + "shape": [ + 32, + 32 + ], + "dtype": "uint16", + "size": 1024, + "nonzero_count": 1024, + "min": 200, + "max": 1223, + "nonzero_min_coordinate": [ + 0, + 0 + ], + "nonzero_max_coordinate": [ + 31, + 31 + ], + "nonzero_example_coordinates": [ + [ + 0, + 0 + ], + [ + 2, + 4 + ], + [ + 4, + 8 + ], + [ + 6, + 12 + ], + [ + 8, + 16 + ], + [ + 10, + 21 + ], + [ + 12, + 25 + ], + [ + 14, + 29 + ], + [ + 17, + 1 + ], + [ + 19, + 5 + ], + [ + 21, + 10 + ], + [ + 23, + 14 + ], + [ + 25, + 18 + ], + [ + 27, + 22 + ], + [ + 29, + 26 + ], + [ + 31, + 31 + ] + ], + "source_voxel_spacing": { + "values_zyx": [ + 1.3556, + 1.3556 + ], + "unit": "micrometers" + }, + "spatial_origin_yx": [ + 0, + 0 + ], + "source_spatial_shape_yx": [ + 32, + 32 + ], + "data_type": "image", + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w2_z001_t001.tif", + "components": { + "site": 1, + "channel": 2, + "z_index": 1, + "timepoint": 1, + "well": "A01" + }, + "payload_type": "ndarray" + }, + "array_values": [ + [ + 200, + 201, + 202, + 203, + 204, + 205, + 206, + 207, + 208, + 209, + 210, + 211, + 212, + 213, + 214, + 215, + 216, + 217, + 218, + 219, + 220, + 221, + 222, + 223, + 224, + 225, + 226, + 227, + 228, + 229, + 230, + 231 + ], + [ + 232, + 233, + 234, + 235, + 236, + 237, + 238, + 239, + 240, + 241, + 242, + 243, + 244, + 245, + 246, + 247, + 248, + 249, + 250, + 251, + 252, + 253, + 254, + 255, + 256, + 257, + 258, + 259, + 260, + 261, + 262, + 263 + ], + [ + 264, + 265, + 266, + 267, + 268, + 269, + 270, + 271, + 272, + 273, + 274, + 275, + 276, + 277, + 278, + 279, + 280, + 281, + 282, + 283, + 284, + 285, + 286, + 287, + 288, + 289, + 290, + 291, + 292, + 293, + 294, + 295 + ], + [ + 296, + 297, + 298, + 299, + 300, + 301, + 302, + 303, + 304, + 305, + 306, + 307, + 308, + 309, + 310, + 311, + 312, + 313, + 314, + 315, + 316, + 317, + 318, + 319, + 320, + 321, + 322, + 323, + 324, + 325, + 326, + 327 + ], + [ + 328, + 329, + 330, + 331, + 332, + 333, + 334, + 335, + 336, + 337, + 338, + 339, + 340, + 341, + 342, + 343, + 344, + 345, + 346, + 347, + 348, + 349, + 350, + 351, + 352, + 353, + 354, + 355, + 356, + 357, + 358, + 359 + ], + [ + 360, + 361, + 362, + 363, + 364, + 365, + 366, + 367, + 368, + 369, + 370, + 371, + 372, + 373, + 374, + 375, + 376, + 377, + 378, + 379, + 380, + 381, + 382, + 383, + 384, + 385, + 386, + 387, + 388, + 389, + 390, + 391 + ], + [ + 392, + 393, + 394, + 395, + 396, + 397, + 398, + 399, + 400, + 401, + 402, + 403, + 404, + 405, + 406, + 407, + 408, + 409, + 410, + 411, + 412, + 413, + 414, + 415, + 416, + 417, + 418, + 419, + 420, + 421, + 422, + 423 + ], + [ + 424, + 425, + 426, + 427, + 428, + 429, + 430, + 431, + 432, + 433, + 434, + 435, + 436, + 437, + 438, + 439, + 440, + 441, + 442, + 443, + 444, + 445, + 446, + 447, + 448, + 449, + 450, + 451, + 452, + 453, + 454, + 455 + ], + [ + 456, + 457, + 458, + 459, + 460, + 461, + 462, + 463, + 464, + 465, + 466, + 467, + 468, + 469, + 470, + 471, + 472, + 473, + 474, + 475, + 476, + 477, + 478, + 479, + 480, + 481, + 482, + 483, + 484, + 485, + 486, + 487 + ], + [ + 488, + 489, + 490, + 491, + 492, + 493, + 494, + 495, + 496, + 497, + 498, + 499, + 500, + 501, + 502, + 503, + 504, + 505, + 506, + 507, + 508, + 509, + 510, + 511, + 512, + 513, + 514, + 515, + 516, + 517, + 518, + 519 + ], + [ + 520, + 521, + 522, + 523, + 524, + 525, + 526, + 527, + 528, + 529, + 530, + 531, + 532, + 533, + 534, + 535, + 536, + 537, + 538, + 539, + 540, + 541, + 542, + 543, + 544, + 545, + 546, + 547, + 548, + 549, + 550, + 551 + ], + [ + 552, + 553, + 554, + 555, + 556, + 557, + 558, + 559, + 560, + 561, + 562, + 563, + 564, + 565, + 566, + 567, + 568, + 569, + 570, + 571, + 572, + 573, + 574, + 575, + 576, + 577, + 578, + 579, + 580, + 581, + 582, + 583 + ], + [ + 584, + 585, + 586, + 587, + 588, + 589, + 590, + 591, + 592, + 593, + 594, + 595, + 596, + 597, + 598, + 599, + 600, + 601, + 602, + 603, + 604, + 605, + 606, + 607, + 608, + 609, + 610, + 611, + 612, + 613, + 614, + 615 + ], + [ + 616, + 617, + 618, + 619, + 620, + 621, + 622, + 623, + 624, + 625, + 626, + 627, + 628, + 629, + 630, + 631, + 632, + 633, + 634, + 635, + 636, + 637, + 638, + 639, + 640, + 641, + 642, + 643, + 644, + 645, + 646, + 647 + ], + [ + 648, + 649, + 650, + 651, + 652, + 653, + 654, + 655, + 656, + 657, + 658, + 659, + 660, + 661, + 662, + 663, + 664, + 665, + 666, + 667, + 668, + 669, + 670, + 671, + 672, + 673, + 674, + 675, + 676, + 677, + 678, + 679 + ], + [ + 680, + 681, + 682, + 683, + 684, + 685, + 686, + 687, + 688, + 689, + 690, + 691, + 692, + 693, + 694, + 695, + 696, + 697, + 698, + 699, + 700, + 701, + 702, + 703, + 704, + 705, + 706, + 707, + 708, + 709, + 710, + 711 + ], + [ + 712, + 713, + 714, + 715, + 716, + 717, + 718, + 719, + 720, + 721, + 722, + 723, + 724, + 725, + 726, + 727, + 728, + 729, + 730, + 731, + 732, + 733, + 734, + 735, + 736, + 737, + 738, + 739, + 740, + 741, + 742, + 743 + ], + [ + 744, + 745, + 746, + 747, + 748, + 749, + 750, + 751, + 752, + 753, + 754, + 755, + 756, + 757, + 758, + 759, + 760, + 761, + 762, + 763, + 764, + 765, + 766, + 767, + 768, + 769, + 770, + 771, + 772, + 773, + 774, + 775 + ], + [ + 776, + 777, + 778, + 779, + 780, + 781, + 782, + 783, + 784, + 785, + 786, + 787, + 788, + 789, + 790, + 791, + 792, + 793, + 794, + 795, + 796, + 797, + 798, + 799, + 800, + 801, + 802, + 803, + 804, + 805, + 806, + 807 + ], + [ + 808, + 809, + 810, + 811, + 812, + 813, + 814, + 815, + 816, + 817, + 818, + 819, + 820, + 821, + 822, + 823, + 824, + 825, + 826, + 827, + 828, + 829, + 830, + 831, + 832, + 833, + 834, + 835, + 836, + 837, + 838, + 839 + ], + [ + 840, + 841, + 842, + 843, + 844, + 845, + 846, + 847, + 848, + 849, + 850, + 851, + 852, + 853, + 854, + 855, + 856, + 857, + 858, + 859, + 860, + 861, + 862, + 863, + 864, + 865, + 866, + 867, + 868, + 869, + 870, + 871 + ], + [ + 872, + 873, + 874, + 875, + 876, + 877, + 878, + 879, + 880, + 881, + 882, + 883, + 884, + 885, + 886, + 887, + 888, + 889, + 890, + 891, + 892, + 893, + 894, + 895, + 896, + 897, + 898, + 899, + 900, + 901, + 902, + 903 + ], + [ + 904, + 905, + 906, + 907, + 908, + 909, + 910, + 911, + 912, + 913, + 914, + 915, + 916, + 917, + 918, + 919, + 920, + 921, + 922, + 923, + 924, + 925, + 926, + 927, + 928, + 929, + 930, + 931, + 932, + 933, + 934, + 935 + ], + [ + 936, + 937, + 938, + 939, + 940, + 941, + 942, + 943, + 944, + 945, + 946, + 947, + 948, + 949, + 950, + 951, + 952, + 953, + 954, + 955, + 956, + 957, + 958, + 959, + 960, + 961, + 962, + 963, + 964, + 965, + 966, + 967 + ], + [ + 968, + 969, + 970, + 971, + 972, + 973, + 974, + 975, + 976, + 977, + 978, + 979, + 980, + 981, + 982, + 983, + 984, + 985, + 986, + 987, + 988, + 989, + 990, + 991, + 992, + 993, + 994, + 995, + 996, + 997, + 998, + 999 + ], + [ + 1000, + 1001, + 1002, + 1003, + 1004, + 1005, + 1006, + 1007, + 1008, + 1009, + 1010, + 1011, + 1012, + 1013, + 1014, + 1015, + 1016, + 1017, + 1018, + 1019, + 1020, + 1021, + 1022, + 1023, + 1024, + 1025, + 1026, + 1027, + 1028, + 1029, + 1030, + 1031 + ], + [ + 1032, + 1033, + 1034, + 1035, + 1036, + 1037, + 1038, + 1039, + 1040, + 1041, + 1042, + 1043, + 1044, + 1045, + 1046, + 1047, + 1048, + 1049, + 1050, + 1051, + 1052, + 1053, + 1054, + 1055, + 1056, + 1057, + 1058, + 1059, + 1060, + 1061, + 1062, + 1063 + ], + [ + 1064, + 1065, + 1066, + 1067, + 1068, + 1069, + 1070, + 1071, + 1072, + 1073, + 1074, + 1075, + 1076, + 1077, + 1078, + 1079, + 1080, + 1081, + 1082, + 1083, + 1084, + 1085, + 1086, + 1087, + 1088, + 1089, + 1090, + 1091, + 1092, + 1093, + 1094, + 1095 + ], + [ + 1096, + 1097, + 1098, + 1099, + 1100, + 1101, + 1102, + 1103, + 1104, + 1105, + 1106, + 1107, + 1108, + 1109, + 1110, + 1111, + 1112, + 1113, + 1114, + 1115, + 1116, + 1117, + 1118, + 1119, + 1120, + 1121, + 1122, + 1123, + 1124, + 1125, + 1126, + 1127 + ], + [ + 1128, + 1129, + 1130, + 1131, + 1132, + 1133, + 1134, + 1135, + 1136, + 1137, + 1138, + 1139, + 1140, + 1141, + 1142, + 1143, + 1144, + 1145, + 1146, + 1147, + 1148, + 1149, + 1150, + 1151, + 1152, + 1153, + 1154, + 1155, + 1156, + 1157, + 1158, + 1159 + ], + [ + 1160, + 1161, + 1162, + 1163, + 1164, + 1165, + 1166, + 1167, + 1168, + 1169, + 1170, + 1171, + 1172, + 1173, + 1174, + 1175, + 1176, + 1177, + 1178, + 1179, + 1180, + 1181, + 1182, + 1183, + 1184, + 1185, + 1186, + 1187, + 1188, + 1189, + 1190, + 1191 + ], + [ + 1192, + 1193, + 1194, + 1195, + 1196, + 1197, + 1198, + 1199, + 1200, + 1201, + 1202, + 1203, + 1204, + 1205, + 1206, + 1207, + 1208, + 1209, + 1210, + 1211, + 1212, + 1213, + 1214, + 1215, + 1216, + 1217, + 1218, + 1219, + 1220, + 1221, + 1222, + 1223 + ] + ], + "array_value_summary": { + "shape": [ + 32, + 32 + ], + "dtype": "uint16", + "size": 1024, + "nonzero_count": 1024, + "min": 200, + "max": 1223, + "requested": true, + "included": true, + "slice_ranges": [ + [ + 0, + 32 + ], + [ + 0, + 32 + ] + ] + }, + "route_key": "origin_manual_kind_manual_projection_selected_images_e83ddc2185a63aca4b85ec471143f61c8f4eabdb08df3557ca21f2bddcda60b9", + "shape_payloads": [] + } + ] + }, + { + "route_key": "origin_manual_kind_manual_projection_A01_s001_w2_z001_t001_graph.graph.roi.zip_shapes", + "title": "A01_s001_w2_z001_t001_graph.graph.roi.zip ROIs", + "mounted": true, + "item_count": 1, + "producer_identities": [ + { + "origin": "manual", + "output_kind": "manual", + "output_key": "A01_s001_w2_z001_t001_graph.graph.roi.zip", + "projection_key": "A01_s001_w2_z001_t001_graph.graph.roi.zip", + "step_name": null, + "pipeline_position": null, + "step_scope_id": null, + "invocation_key": null, + "artifact_kind": null + } + ], + "axis_labels": [ + "site", + "channel", + "z_index", + "timepoint", + "well", + "y", + "x" + ], + "stack_axes": [ + "channel" + ], + "pending_update": false, + "payloads": [ + { + "data_type": "shapes", + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/graph_results/A01_s001_w2_z001_t001_graph.graph.roi.zip", + "components": { + "site": 1, + "channel": 2, + "z_index": 1, + "timepoint": 1, + "well": "A01" + }, + "axis_indices": [ + 0 + ], + "aggregate_axis_indices": [], + "summary": { + "nonzero_count": 2, + "item_count": 2, + "shape_payload_count": 2, + "missing_source_spatial_shape_count": 2, + "shape_coordinate_count": 4, + "shape_out_of_source_bounds_count": 0, + "shape_coordinate_bounds_yx": { + "min_yx": [ + 2.25, + 3.5 + ], + "max_yx": [ + 7.25, + 12.5 + ], + "coordinate_count": 4 + }, + "source_voxel_spacing": { + "values_zyx": [ + 1.3556, + 1.3556 + ], + "unit": "micrometers" + }, + "data_type": "shapes", + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/graph_results/A01_s001_w2_z001_t001_graph.graph.roi.zip", + "components": { + "site": 1, + "channel": 2, + "z_index": 1, + "timepoint": 1, + "well": "A01" + }, + "payload_type": "list" + }, + "array_values": [], + "array_value_summary": { + "requested": true, + "included": false, + "omitted_reason": "payload_not_ndarray" + }, + "route_key": "origin_manual_kind_manual_projection_A01_s001_w2_z001_t001_graph.graph.roi.zip_shapes", + "shape_payloads": [ + { + "type": "path", + "coordinates": [ + [ + 2.25, + 3.5 + ], + [ + 5.25, + 9.5 + ] + ], + "metadata": { + "__openhcs_object_subject__": "[\"output\",\"object_labels\",\"neurons\",\"synthetic-receiving-134\",4]", + "__openhcs_object_subject_id__": 7, + "area": 0.0, + "branch_distance_um": 8.5, + "centroid": [ + 3.75, + 6.5 + ], + "edge_id": 1, + "graph": "declared_graph", + "label": 1, + "neuron_label": 7, + "openhcs_image_payload_metadata": { + "intensity_scale": null, + "mask_defines_border": null, + "physical_border_edges_yx": null, + "plane_axis": null, + "source_channel_axis": null, + "source_dtype": null, + "source_plane_dtypes": [], + "source_plane_intensity_scales": [], + "source_provenance": { + "source_component_metadata": { + "OpenHCSSourceVoxelSpacingUnit": "micrometers", + "OpenHCSSourceVoxelSpacingZYX": "1.3555999999999999,1.3555999999999999", + "channel": "2", + "site": "1", + "timepoint": "1", + "well": "A01", + "z_index": "1" + }, + "source_image_names": [ + "raw_2" + ], + "source_image_provenance_planes": [], + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w2_z001_t001.tif" + }, + "source_spatial_domain": { + "fill_value": 0, + "origin_yx": null, + "source_shape_yx": null, + "spatial_dimensions": 2, + "value_name": "Dense array" + }, + "source_voxel_spacing": { + "unit": "micrometers", + "values_zyx": [ + 1.3556, + 1.3556 + ] + }, + "unit_interval_intensity": null + }, + "perimeter": 6.708203932499369, + "source_node_id": 1, + "target_node_id": 2 + } + }, + { + "type": "path", + "coordinates": [ + [ + 5.25, + 9.5 + ], + [ + 7.25, + 12.5 + ] + ], + "metadata": { + "__openhcs_object_subject__": "[\"output\",\"object_labels\",\"neurons\",\"synthetic-receiving-134\",4]", + "__openhcs_object_subject_id__": 7, + "area": 0.0, + "branch_distance_um": 8.5, + "centroid": [ + 6.25, + 11.0 + ], + "edge_id": 2, + "graph": "declared_graph", + "label": 2, + "neuron_label": 7, + "openhcs_image_payload_metadata": { + "intensity_scale": null, + "mask_defines_border": null, + "physical_border_edges_yx": null, + "plane_axis": null, + "source_channel_axis": null, + "source_dtype": null, + "source_plane_dtypes": [], + "source_plane_intensity_scales": [], + "source_provenance": { + "source_component_metadata": { + "OpenHCSSourceVoxelSpacingUnit": "micrometers", + "OpenHCSSourceVoxelSpacingZYX": "1.3555999999999999,1.3555999999999999", + "channel": "2", + "site": "1", + "timepoint": "1", + "well": "A01", + "z_index": "1" + }, + "source_image_names": [ + "raw_2" + ], + "source_image_provenance_planes": [], + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w2_z001_t001.tif" + }, + "source_spatial_domain": { + "fill_value": 0, + "origin_yx": null, + "source_shape_yx": null, + "spatial_dimensions": 2, + "value_name": "Dense array" + }, + "source_voxel_spacing": { + "unit": "micrometers", + "values_zyx": [ + 1.3556, + 1.3556 + ] + }, + "unit_interval_intensity": null + }, + "perimeter": 3.605551275463989, + "source_node_id": 2, + "target_node_id": 3 + } + } + ] + } + ] + } + ], + "response": {} + }, + "isError": false + }, + "payload": { + "connection": { + "host": "127.0.0.1", + "port": 6609, + "transport_mode": "tcp", + "persistent": true + }, + "schema_version": "openhcs.agent.v1", + "errors": [], + "warnings": [], + "observed": true, + "viewer": { + "viewer_type": "napari", + "title": "OpenHCS Napari Visualization" + }, + "layer_count": 3, + "layers": [ + { + "route_key": "origin_manual_kind_manual_projection_selected_images_8c7357d46ccc38823ca9e68096baf86f25c3004b61b63ba1eef9adea41d34fb8_scalar_stack", + "title": "selected_images image stack", + "mounted": true, + "item_count": 1, + "producer_identities": [ + { + "origin": "manual", + "output_kind": "manual", + "output_key": "selected_images", + "projection_key": "selected_images_8c7357d46ccc38823ca9e68096baf86f25c3004b61b63ba1eef9adea41d34fb8", + "step_name": null, + "pipeline_position": null, + "step_scope_id": null, + "invocation_key": null, + "artifact_kind": null + } + ], + "axis_labels": [ + "site", + "channel", + "z_index", + "timepoint", + "well", + "y", + "x" + ], + "stack_axes": [ + "channel" + ], + "pending_update": false, + "payloads": [ + { + "data_type": "image", + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/stacked_labels/A01_s001_w2_z001_t001_Labels.tif", + "components": { + "site": 1, + "z_index": 1, + "timepoint": 1, + "well": "A01", + "channel": 2 + }, + "axis_indices": [ + 1 + ], + "aggregate_axis_indices": [ + 0 + ], + "summary": { + "shape": [ + 32, + 32 + ], + "dtype": "uint16", + "size": 1024, + "nonzero_count": 154, + "min": 0, + "max": 22, + "nonzero_min_coordinate": [ + 3, + 4 + ], + "nonzero_max_coordinate": [ + 24, + 27 + ], + "nonzero_example_coordinates": [ + [ + 3, + 4 + ], + [ + 4, + 4 + ], + [ + 5, + 4 + ], + [ + 6, + 4 + ], + [ + 7, + 4 + ], + [ + 8, + 5 + ], + [ + 9, + 5 + ], + [ + 10, + 5 + ], + [ + 11, + 5 + ], + [ + 17, + 21 + ], + [ + 18, + 24 + ], + [ + 19, + 26 + ], + [ + 21, + 20 + ], + [ + 22, + 22 + ], + [ + 23, + 24 + ], + [ + 24, + 27 + ] + ], + "source_voxel_spacing": { + "values_zyx": [ + 1.3556, + 1.3556 + ], + "unit": "micrometers" + }, + "spatial_origin_yx": [ + 0, + 0 + ], + "source_spatial_shape_yx": [ + 32, + 32 + ], + "data_type": "image", + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/stacked_labels/A01_s001_w2_z001_t001_Labels.tif", + "components": { + "site": 1, + "z_index": 1, + "timepoint": 1, + "well": "A01", + "channel": 2 + }, + "payload_type": "ndarray" + }, + "array_values": [ + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 14, + 14, + 14, + 14, + 14, + 14, + 14, + 14, + 14, + 14, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 14, + 14, + 14, + 14, + 14, + 14, + 14, + 14, + 14, + 14, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 14, + 14, + 14, + 14, + 14, + 14, + 14, + 14, + 14, + 14, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 14, + 14, + 14, + 14, + 14, + 14, + 14, + 14, + 14, + 14, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 14, + 14, + 14, + 14, + 14, + 14, + 14, + 14, + 14, + 14, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 14, + 14, + 14, + 14, + 14, + 14, + 14, + 14, + 14, + 14, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 14, + 14, + 14, + 14, + 14, + 14, + 14, + 14, + 14, + 14, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 14, + 14, + 14, + 14, + 14, + 14, + 14, + 14, + 14, + 14, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 14, + 14, + 14, + 14, + 14, + 14, + 14, + 14, + 14, + 14, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 22, + 22, + 22, + 22, + 22, + 22, + 22, + 22, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 22, + 22, + 22, + 22, + 22, + 22, + 22, + 22, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 22, + 22, + 22, + 22, + 22, + 22, + 22, + 22, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 22, + 22, + 22, + 22, + 22, + 22, + 22, + 22, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 22, + 22, + 22, + 22, + 22, + 22, + 22, + 22, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 22, + 22, + 22, + 22, + 22, + 22, + 22, + 22, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 22, + 22, + 22, + 22, + 22, + 22, + 22, + 22, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 22, + 22, + 22, + 22, + 22, + 22, + 22, + 22, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ] + ], + "array_value_summary": { + "shape": [ + 32, + 32 + ], + "dtype": "uint16", + "size": 1024, + "nonzero_count": 154, + "min": 0, + "max": 22, + "requested": true, + "included": true, + "slice_ranges": [ + [ + 0, + 32 + ], + [ + 0, + 32 + ] + ] + }, + "route_key": "origin_manual_kind_manual_projection_selected_images_8c7357d46ccc38823ca9e68096baf86f25c3004b61b63ba1eef9adea41d34fb8_scalar_stack", + "shape_payloads": [] + }, + { + "data_type": "image", + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/stacked_labels/A01_s001_w2_z001_t001_Labels.tif", + "components": { + "site": 1, + "z_index": 1, + "timepoint": 1, + "well": "A01", + "channel": 1 + }, + "axis_indices": [ + 0 + ], + "aggregate_axis_indices": [ + 1 + ], + "summary": { + "shape": [ + 32, + 32 + ], + "dtype": "uint16", + "size": 1024, + "nonzero_count": 154, + "min": 0, + "max": 11, + "nonzero_min_coordinate": [ + 3, + 4 + ], + "nonzero_max_coordinate": [ + 24, + 27 + ], + "nonzero_example_coordinates": [ + [ + 3, + 4 + ], + [ + 4, + 4 + ], + [ + 5, + 4 + ], + [ + 6, + 4 + ], + [ + 7, + 4 + ], + [ + 8, + 5 + ], + [ + 9, + 5 + ], + [ + 10, + 5 + ], + [ + 11, + 5 + ], + [ + 17, + 21 + ], + [ + 18, + 24 + ], + [ + 19, + 26 + ], + [ + 21, + 20 + ], + [ + 22, + 22 + ], + [ + 23, + 24 + ], + [ + 24, + 27 + ] + ], + "source_voxel_spacing": { + "values_zyx": [ + 1.3556, + 1.3556 + ], + "unit": "micrometers" + }, + "spatial_origin_yx": [ + 0, + 0 + ], + "source_spatial_shape_yx": [ + 32, + 32 + ], + "data_type": "image", + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/stacked_labels/A01_s001_w2_z001_t001_Labels.tif", + "components": { + "site": 1, + "z_index": 1, + "timepoint": 1, + "well": "A01", + "channel": 1 + }, + "payload_type": "ndarray" + }, + "array_values": [ + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 11, + 11, + 11, + 11, + 11, + 11, + 11, + 11, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 11, + 11, + 11, + 11, + 11, + 11, + 11, + 11, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 11, + 11, + 11, + 11, + 11, + 11, + 11, + 11, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 11, + 11, + 11, + 11, + 11, + 11, + 11, + 11, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 11, + 11, + 11, + 11, + 11, + 11, + 11, + 11, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 11, + 11, + 11, + 11, + 11, + 11, + 11, + 11, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 11, + 11, + 11, + 11, + 11, + 11, + 11, + 11, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 11, + 11, + 11, + 11, + 11, + 11, + 11, + 11, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ] + ], + "array_value_summary": { + "shape": [ + 32, + 32 + ], + "dtype": "uint16", + "size": 1024, + "nonzero_count": 154, + "min": 0, + "max": 11, + "requested": true, + "included": true, + "slice_ranges": [ + [ + 0, + 32 + ], + [ + 0, + 32 + ] + ] + }, + "route_key": "origin_manual_kind_manual_projection_selected_images_8c7357d46ccc38823ca9e68096baf86f25c3004b61b63ba1eef9adea41d34fb8_scalar_stack", + "shape_payloads": [] + } + ] + }, + { + "route_key": "origin_manual_kind_manual_projection_selected_images_e83ddc2185a63aca4b85ec471143f61c8f4eabdb08df3557ca21f2bddcda60b9", + "title": "selected_images", + "mounted": true, + "item_count": 2, + "producer_identities": [ + { + "origin": "manual", + "output_kind": "manual", + "output_key": "selected_images", + "projection_key": "selected_images_e83ddc2185a63aca4b85ec471143f61c8f4eabdb08df3557ca21f2bddcda60b9", + "step_name": null, + "pipeline_position": null, + "step_scope_id": null, + "invocation_key": null, + "artifact_kind": null + } + ], + "axis_labels": [ + "site", + "channel", + "z_index", + "timepoint", + "well", + "y", + "x" + ], + "stack_axes": [ + "channel" + ], + "pending_update": false, + "payloads": [ + { + "data_type": "image", + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w1_z001_t001.tif", + "components": { + "site": 1, + "channel": 1, + "z_index": 1, + "timepoint": 1, + "well": "A01" + }, + "axis_indices": [ + 0 + ], + "aggregate_axis_indices": [], + "summary": { + "shape": [ + 32, + 32 + ], + "dtype": "uint16", + "size": 1024, + "nonzero_count": 1024, + "min": 100, + "max": 1123, + "nonzero_min_coordinate": [ + 0, + 0 + ], + "nonzero_max_coordinate": [ + 31, + 31 + ], + "nonzero_example_coordinates": [ + [ + 0, + 0 + ], + [ + 2, + 4 + ], + [ + 4, + 8 + ], + [ + 6, + 12 + ], + [ + 8, + 16 + ], + [ + 10, + 21 + ], + [ + 12, + 25 + ], + [ + 14, + 29 + ], + [ + 17, + 1 + ], + [ + 19, + 5 + ], + [ + 21, + 10 + ], + [ + 23, + 14 + ], + [ + 25, + 18 + ], + [ + 27, + 22 + ], + [ + 29, + 26 + ], + [ + 31, + 31 + ] + ], + "source_voxel_spacing": { + "values_zyx": [ + 1.3556, + 1.3556 + ], + "unit": "micrometers" + }, + "spatial_origin_yx": [ + 0, + 0 + ], + "source_spatial_shape_yx": [ + 32, + 32 + ], + "data_type": "image", + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w1_z001_t001.tif", + "components": { + "site": 1, + "channel": 1, + "z_index": 1, + "timepoint": 1, + "well": "A01" + }, + "payload_type": "ndarray" + }, + "array_values": [ + [ + 100, + 101, + 102, + 103, + 104, + 105, + 106, + 107, + 108, + 109, + 110, + 111, + 112, + 113, + 114, + 115, + 116, + 117, + 118, + 119, + 120, + 121, + 122, + 123, + 124, + 125, + 126, + 127, + 128, + 129, + 130, + 131 + ], + [ + 132, + 133, + 134, + 135, + 136, + 137, + 138, + 139, + 140, + 141, + 142, + 143, + 144, + 145, + 146, + 147, + 148, + 149, + 150, + 151, + 152, + 153, + 154, + 155, + 156, + 157, + 158, + 159, + 160, + 161, + 162, + 163 + ], + [ + 164, + 165, + 166, + 167, + 168, + 169, + 170, + 171, + 172, + 173, + 174, + 175, + 176, + 177, + 178, + 179, + 180, + 181, + 182, + 183, + 184, + 185, + 186, + 187, + 188, + 189, + 190, + 191, + 192, + 193, + 194, + 195 + ], + [ + 196, + 197, + 198, + 199, + 200, + 201, + 202, + 203, + 204, + 205, + 206, + 207, + 208, + 209, + 210, + 211, + 212, + 213, + 214, + 215, + 216, + 217, + 218, + 219, + 220, + 221, + 222, + 223, + 224, + 225, + 226, + 227 + ], + [ + 228, + 229, + 230, + 231, + 232, + 233, + 234, + 235, + 236, + 237, + 238, + 239, + 240, + 241, + 242, + 243, + 244, + 245, + 246, + 247, + 248, + 249, + 250, + 251, + 252, + 253, + 254, + 255, + 256, + 257, + 258, + 259 + ], + [ + 260, + 261, + 262, + 263, + 264, + 265, + 266, + 267, + 268, + 269, + 270, + 271, + 272, + 273, + 274, + 275, + 276, + 277, + 278, + 279, + 280, + 281, + 282, + 283, + 284, + 285, + 286, + 287, + 288, + 289, + 290, + 291 + ], + [ + 292, + 293, + 294, + 295, + 296, + 297, + 298, + 299, + 300, + 301, + 302, + 303, + 304, + 305, + 306, + 307, + 308, + 309, + 310, + 311, + 312, + 313, + 314, + 315, + 316, + 317, + 318, + 319, + 320, + 321, + 322, + 323 + ], + [ + 324, + 325, + 326, + 327, + 328, + 329, + 330, + 331, + 332, + 333, + 334, + 335, + 336, + 337, + 338, + 339, + 340, + 341, + 342, + 343, + 344, + 345, + 346, + 347, + 348, + 349, + 350, + 351, + 352, + 353, + 354, + 355 + ], + [ + 356, + 357, + 358, + 359, + 360, + 361, + 362, + 363, + 364, + 365, + 366, + 367, + 368, + 369, + 370, + 371, + 372, + 373, + 374, + 375, + 376, + 377, + 378, + 379, + 380, + 381, + 382, + 383, + 384, + 385, + 386, + 387 + ], + [ + 388, + 389, + 390, + 391, + 392, + 393, + 394, + 395, + 396, + 397, + 398, + 399, + 400, + 401, + 402, + 403, + 404, + 405, + 406, + 407, + 408, + 409, + 410, + 411, + 412, + 413, + 414, + 415, + 416, + 417, + 418, + 419 + ], + [ + 420, + 421, + 422, + 423, + 424, + 425, + 426, + 427, + 428, + 429, + 430, + 431, + 432, + 433, + 434, + 435, + 436, + 437, + 438, + 439, + 440, + 441, + 442, + 443, + 444, + 445, + 446, + 447, + 448, + 449, + 450, + 451 + ], + [ + 452, + 453, + 454, + 455, + 456, + 457, + 458, + 459, + 460, + 461, + 462, + 463, + 464, + 465, + 466, + 467, + 468, + 469, + 470, + 471, + 472, + 473, + 474, + 475, + 476, + 477, + 478, + 479, + 480, + 481, + 482, + 483 + ], + [ + 484, + 485, + 486, + 487, + 488, + 489, + 490, + 491, + 492, + 493, + 494, + 495, + 496, + 497, + 498, + 499, + 500, + 501, + 502, + 503, + 504, + 505, + 506, + 507, + 508, + 509, + 510, + 511, + 512, + 513, + 514, + 515 + ], + [ + 516, + 517, + 518, + 519, + 520, + 521, + 522, + 523, + 524, + 525, + 526, + 527, + 528, + 529, + 530, + 531, + 532, + 533, + 534, + 535, + 536, + 537, + 538, + 539, + 540, + 541, + 542, + 543, + 544, + 545, + 546, + 547 + ], + [ + 548, + 549, + 550, + 551, + 552, + 553, + 554, + 555, + 556, + 557, + 558, + 559, + 560, + 561, + 562, + 563, + 564, + 565, + 566, + 567, + 568, + 569, + 570, + 571, + 572, + 573, + 574, + 575, + 576, + 577, + 578, + 579 + ], + [ + 580, + 581, + 582, + 583, + 584, + 585, + 586, + 587, + 588, + 589, + 590, + 591, + 592, + 593, + 594, + 595, + 596, + 597, + 598, + 599, + 600, + 601, + 602, + 603, + 604, + 605, + 606, + 607, + 608, + 609, + 610, + 611 + ], + [ + 612, + 613, + 614, + 615, + 616, + 617, + 618, + 619, + 620, + 621, + 622, + 623, + 624, + 625, + 626, + 627, + 628, + 629, + 630, + 631, + 632, + 633, + 634, + 635, + 636, + 637, + 638, + 639, + 640, + 641, + 642, + 643 + ], + [ + 644, + 645, + 646, + 647, + 648, + 649, + 650, + 651, + 652, + 653, + 654, + 655, + 656, + 657, + 658, + 659, + 660, + 661, + 662, + 663, + 664, + 665, + 666, + 667, + 668, + 669, + 670, + 671, + 672, + 673, + 674, + 675 + ], + [ + 676, + 677, + 678, + 679, + 680, + 681, + 682, + 683, + 684, + 685, + 686, + 687, + 688, + 689, + 690, + 691, + 692, + 693, + 694, + 695, + 696, + 697, + 698, + 699, + 700, + 701, + 702, + 703, + 704, + 705, + 706, + 707 + ], + [ + 708, + 709, + 710, + 711, + 712, + 713, + 714, + 715, + 716, + 717, + 718, + 719, + 720, + 721, + 722, + 723, + 724, + 725, + 726, + 727, + 728, + 729, + 730, + 731, + 732, + 733, + 734, + 735, + 736, + 737, + 738, + 739 + ], + [ + 740, + 741, + 742, + 743, + 744, + 745, + 746, + 747, + 748, + 749, + 750, + 751, + 752, + 753, + 754, + 755, + 756, + 757, + 758, + 759, + 760, + 761, + 762, + 763, + 764, + 765, + 766, + 767, + 768, + 769, + 770, + 771 + ], + [ + 772, + 773, + 774, + 775, + 776, + 777, + 778, + 779, + 780, + 781, + 782, + 783, + 784, + 785, + 786, + 787, + 788, + 789, + 790, + 791, + 792, + 793, + 794, + 795, + 796, + 797, + 798, + 799, + 800, + 801, + 802, + 803 + ], + [ + 804, + 805, + 806, + 807, + 808, + 809, + 810, + 811, + 812, + 813, + 814, + 815, + 816, + 817, + 818, + 819, + 820, + 821, + 822, + 823, + 824, + 825, + 826, + 827, + 828, + 829, + 830, + 831, + 832, + 833, + 834, + 835 + ], + [ + 836, + 837, + 838, + 839, + 840, + 841, + 842, + 843, + 844, + 845, + 846, + 847, + 848, + 849, + 850, + 851, + 852, + 853, + 854, + 855, + 856, + 857, + 858, + 859, + 860, + 861, + 862, + 863, + 864, + 865, + 866, + 867 + ], + [ + 868, + 869, + 870, + 871, + 872, + 873, + 874, + 875, + 876, + 877, + 878, + 879, + 880, + 881, + 882, + 883, + 884, + 885, + 886, + 887, + 888, + 889, + 890, + 891, + 892, + 893, + 894, + 895, + 896, + 897, + 898, + 899 + ], + [ + 900, + 901, + 902, + 903, + 904, + 905, + 906, + 907, + 908, + 909, + 910, + 911, + 912, + 913, + 914, + 915, + 916, + 917, + 918, + 919, + 920, + 921, + 922, + 923, + 924, + 925, + 926, + 927, + 928, + 929, + 930, + 931 + ], + [ + 932, + 933, + 934, + 935, + 936, + 937, + 938, + 939, + 940, + 941, + 942, + 943, + 944, + 945, + 946, + 947, + 948, + 949, + 950, + 951, + 952, + 953, + 954, + 955, + 956, + 957, + 958, + 959, + 960, + 961, + 962, + 963 + ], + [ + 964, + 965, + 966, + 967, + 968, + 969, + 970, + 971, + 972, + 973, + 974, + 975, + 976, + 977, + 978, + 979, + 980, + 981, + 982, + 983, + 984, + 985, + 986, + 987, + 988, + 989, + 990, + 991, + 992, + 993, + 994, + 995 + ], + [ + 996, + 997, + 998, + 999, + 1000, + 1001, + 1002, + 1003, + 1004, + 1005, + 1006, + 1007, + 1008, + 1009, + 1010, + 1011, + 1012, + 1013, + 1014, + 1015, + 1016, + 1017, + 1018, + 1019, + 1020, + 1021, + 1022, + 1023, + 1024, + 1025, + 1026, + 1027 + ], + [ + 1028, + 1029, + 1030, + 1031, + 1032, + 1033, + 1034, + 1035, + 1036, + 1037, + 1038, + 1039, + 1040, + 1041, + 1042, + 1043, + 1044, + 1045, + 1046, + 1047, + 1048, + 1049, + 1050, + 1051, + 1052, + 1053, + 1054, + 1055, + 1056, + 1057, + 1058, + 1059 + ], + [ + 1060, + 1061, + 1062, + 1063, + 1064, + 1065, + 1066, + 1067, + 1068, + 1069, + 1070, + 1071, + 1072, + 1073, + 1074, + 1075, + 1076, + 1077, + 1078, + 1079, + 1080, + 1081, + 1082, + 1083, + 1084, + 1085, + 1086, + 1087, + 1088, + 1089, + 1090, + 1091 + ], + [ + 1092, + 1093, + 1094, + 1095, + 1096, + 1097, + 1098, + 1099, + 1100, + 1101, + 1102, + 1103, + 1104, + 1105, + 1106, + 1107, + 1108, + 1109, + 1110, + 1111, + 1112, + 1113, + 1114, + 1115, + 1116, + 1117, + 1118, + 1119, + 1120, + 1121, + 1122, + 1123 + ] + ], + "array_value_summary": { + "shape": [ + 32, + 32 + ], + "dtype": "uint16", + "size": 1024, + "nonzero_count": 1024, + "min": 100, + "max": 1123, + "requested": true, + "included": true, + "slice_ranges": [ + [ + 0, + 32 + ], + [ + 0, + 32 + ] + ] + }, + "route_key": "origin_manual_kind_manual_projection_selected_images_e83ddc2185a63aca4b85ec471143f61c8f4eabdb08df3557ca21f2bddcda60b9", + "shape_payloads": [] + }, + { + "data_type": "image", + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w2_z001_t001.tif", + "components": { + "site": 1, + "channel": 2, + "z_index": 1, + "timepoint": 1, + "well": "A01" + }, + "axis_indices": [ + 1 + ], + "aggregate_axis_indices": [], + "summary": { + "shape": [ + 32, + 32 + ], + "dtype": "uint16", + "size": 1024, + "nonzero_count": 1024, + "min": 200, + "max": 1223, + "nonzero_min_coordinate": [ + 0, + 0 + ], + "nonzero_max_coordinate": [ + 31, + 31 + ], + "nonzero_example_coordinates": [ + [ + 0, + 0 + ], + [ + 2, + 4 + ], + [ + 4, + 8 + ], + [ + 6, + 12 + ], + [ + 8, + 16 + ], + [ + 10, + 21 + ], + [ + 12, + 25 + ], + [ + 14, + 29 + ], + [ + 17, + 1 + ], + [ + 19, + 5 + ], + [ + 21, + 10 + ], + [ + 23, + 14 + ], + [ + 25, + 18 + ], + [ + 27, + 22 + ], + [ + 29, + 26 + ], + [ + 31, + 31 + ] + ], + "source_voxel_spacing": { + "values_zyx": [ + 1.3556, + 1.3556 + ], + "unit": "micrometers" + }, + "spatial_origin_yx": [ + 0, + 0 + ], + "source_spatial_shape_yx": [ + 32, + 32 + ], + "data_type": "image", + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w2_z001_t001.tif", + "components": { + "site": 1, + "channel": 2, + "z_index": 1, + "timepoint": 1, + "well": "A01" + }, + "payload_type": "ndarray" + }, + "array_values": [ + [ + 200, + 201, + 202, + 203, + 204, + 205, + 206, + 207, + 208, + 209, + 210, + 211, + 212, + 213, + 214, + 215, + 216, + 217, + 218, + 219, + 220, + 221, + 222, + 223, + 224, + 225, + 226, + 227, + 228, + 229, + 230, + 231 + ], + [ + 232, + 233, + 234, + 235, + 236, + 237, + 238, + 239, + 240, + 241, + 242, + 243, + 244, + 245, + 246, + 247, + 248, + 249, + 250, + 251, + 252, + 253, + 254, + 255, + 256, + 257, + 258, + 259, + 260, + 261, + 262, + 263 + ], + [ + 264, + 265, + 266, + 267, + 268, + 269, + 270, + 271, + 272, + 273, + 274, + 275, + 276, + 277, + 278, + 279, + 280, + 281, + 282, + 283, + 284, + 285, + 286, + 287, + 288, + 289, + 290, + 291, + 292, + 293, + 294, + 295 + ], + [ + 296, + 297, + 298, + 299, + 300, + 301, + 302, + 303, + 304, + 305, + 306, + 307, + 308, + 309, + 310, + 311, + 312, + 313, + 314, + 315, + 316, + 317, + 318, + 319, + 320, + 321, + 322, + 323, + 324, + 325, + 326, + 327 + ], + [ + 328, + 329, + 330, + 331, + 332, + 333, + 334, + 335, + 336, + 337, + 338, + 339, + 340, + 341, + 342, + 343, + 344, + 345, + 346, + 347, + 348, + 349, + 350, + 351, + 352, + 353, + 354, + 355, + 356, + 357, + 358, + 359 + ], + [ + 360, + 361, + 362, + 363, + 364, + 365, + 366, + 367, + 368, + 369, + 370, + 371, + 372, + 373, + 374, + 375, + 376, + 377, + 378, + 379, + 380, + 381, + 382, + 383, + 384, + 385, + 386, + 387, + 388, + 389, + 390, + 391 + ], + [ + 392, + 393, + 394, + 395, + 396, + 397, + 398, + 399, + 400, + 401, + 402, + 403, + 404, + 405, + 406, + 407, + 408, + 409, + 410, + 411, + 412, + 413, + 414, + 415, + 416, + 417, + 418, + 419, + 420, + 421, + 422, + 423 + ], + [ + 424, + 425, + 426, + 427, + 428, + 429, + 430, + 431, + 432, + 433, + 434, + 435, + 436, + 437, + 438, + 439, + 440, + 441, + 442, + 443, + 444, + 445, + 446, + 447, + 448, + 449, + 450, + 451, + 452, + 453, + 454, + 455 + ], + [ + 456, + 457, + 458, + 459, + 460, + 461, + 462, + 463, + 464, + 465, + 466, + 467, + 468, + 469, + 470, + 471, + 472, + 473, + 474, + 475, + 476, + 477, + 478, + 479, + 480, + 481, + 482, + 483, + 484, + 485, + 486, + 487 + ], + [ + 488, + 489, + 490, + 491, + 492, + 493, + 494, + 495, + 496, + 497, + 498, + 499, + 500, + 501, + 502, + 503, + 504, + 505, + 506, + 507, + 508, + 509, + 510, + 511, + 512, + 513, + 514, + 515, + 516, + 517, + 518, + 519 + ], + [ + 520, + 521, + 522, + 523, + 524, + 525, + 526, + 527, + 528, + 529, + 530, + 531, + 532, + 533, + 534, + 535, + 536, + 537, + 538, + 539, + 540, + 541, + 542, + 543, + 544, + 545, + 546, + 547, + 548, + 549, + 550, + 551 + ], + [ + 552, + 553, + 554, + 555, + 556, + 557, + 558, + 559, + 560, + 561, + 562, + 563, + 564, + 565, + 566, + 567, + 568, + 569, + 570, + 571, + 572, + 573, + 574, + 575, + 576, + 577, + 578, + 579, + 580, + 581, + 582, + 583 + ], + [ + 584, + 585, + 586, + 587, + 588, + 589, + 590, + 591, + 592, + 593, + 594, + 595, + 596, + 597, + 598, + 599, + 600, + 601, + 602, + 603, + 604, + 605, + 606, + 607, + 608, + 609, + 610, + 611, + 612, + 613, + 614, + 615 + ], + [ + 616, + 617, + 618, + 619, + 620, + 621, + 622, + 623, + 624, + 625, + 626, + 627, + 628, + 629, + 630, + 631, + 632, + 633, + 634, + 635, + 636, + 637, + 638, + 639, + 640, + 641, + 642, + 643, + 644, + 645, + 646, + 647 + ], + [ + 648, + 649, + 650, + 651, + 652, + 653, + 654, + 655, + 656, + 657, + 658, + 659, + 660, + 661, + 662, + 663, + 664, + 665, + 666, + 667, + 668, + 669, + 670, + 671, + 672, + 673, + 674, + 675, + 676, + 677, + 678, + 679 + ], + [ + 680, + 681, + 682, + 683, + 684, + 685, + 686, + 687, + 688, + 689, + 690, + 691, + 692, + 693, + 694, + 695, + 696, + 697, + 698, + 699, + 700, + 701, + 702, + 703, + 704, + 705, + 706, + 707, + 708, + 709, + 710, + 711 + ], + [ + 712, + 713, + 714, + 715, + 716, + 717, + 718, + 719, + 720, + 721, + 722, + 723, + 724, + 725, + 726, + 727, + 728, + 729, + 730, + 731, + 732, + 733, + 734, + 735, + 736, + 737, + 738, + 739, + 740, + 741, + 742, + 743 + ], + [ + 744, + 745, + 746, + 747, + 748, + 749, + 750, + 751, + 752, + 753, + 754, + 755, + 756, + 757, + 758, + 759, + 760, + 761, + 762, + 763, + 764, + 765, + 766, + 767, + 768, + 769, + 770, + 771, + 772, + 773, + 774, + 775 + ], + [ + 776, + 777, + 778, + 779, + 780, + 781, + 782, + 783, + 784, + 785, + 786, + 787, + 788, + 789, + 790, + 791, + 792, + 793, + 794, + 795, + 796, + 797, + 798, + 799, + 800, + 801, + 802, + 803, + 804, + 805, + 806, + 807 + ], + [ + 808, + 809, + 810, + 811, + 812, + 813, + 814, + 815, + 816, + 817, + 818, + 819, + 820, + 821, + 822, + 823, + 824, + 825, + 826, + 827, + 828, + 829, + 830, + 831, + 832, + 833, + 834, + 835, + 836, + 837, + 838, + 839 + ], + [ + 840, + 841, + 842, + 843, + 844, + 845, + 846, + 847, + 848, + 849, + 850, + 851, + 852, + 853, + 854, + 855, + 856, + 857, + 858, + 859, + 860, + 861, + 862, + 863, + 864, + 865, + 866, + 867, + 868, + 869, + 870, + 871 + ], + [ + 872, + 873, + 874, + 875, + 876, + 877, + 878, + 879, + 880, + 881, + 882, + 883, + 884, + 885, + 886, + 887, + 888, + 889, + 890, + 891, + 892, + 893, + 894, + 895, + 896, + 897, + 898, + 899, + 900, + 901, + 902, + 903 + ], + [ + 904, + 905, + 906, + 907, + 908, + 909, + 910, + 911, + 912, + 913, + 914, + 915, + 916, + 917, + 918, + 919, + 920, + 921, + 922, + 923, + 924, + 925, + 926, + 927, + 928, + 929, + 930, + 931, + 932, + 933, + 934, + 935 + ], + [ + 936, + 937, + 938, + 939, + 940, + 941, + 942, + 943, + 944, + 945, + 946, + 947, + 948, + 949, + 950, + 951, + 952, + 953, + 954, + 955, + 956, + 957, + 958, + 959, + 960, + 961, + 962, + 963, + 964, + 965, + 966, + 967 + ], + [ + 968, + 969, + 970, + 971, + 972, + 973, + 974, + 975, + 976, + 977, + 978, + 979, + 980, + 981, + 982, + 983, + 984, + 985, + 986, + 987, + 988, + 989, + 990, + 991, + 992, + 993, + 994, + 995, + 996, + 997, + 998, + 999 + ], + [ + 1000, + 1001, + 1002, + 1003, + 1004, + 1005, + 1006, + 1007, + 1008, + 1009, + 1010, + 1011, + 1012, + 1013, + 1014, + 1015, + 1016, + 1017, + 1018, + 1019, + 1020, + 1021, + 1022, + 1023, + 1024, + 1025, + 1026, + 1027, + 1028, + 1029, + 1030, + 1031 + ], + [ + 1032, + 1033, + 1034, + 1035, + 1036, + 1037, + 1038, + 1039, + 1040, + 1041, + 1042, + 1043, + 1044, + 1045, + 1046, + 1047, + 1048, + 1049, + 1050, + 1051, + 1052, + 1053, + 1054, + 1055, + 1056, + 1057, + 1058, + 1059, + 1060, + 1061, + 1062, + 1063 + ], + [ + 1064, + 1065, + 1066, + 1067, + 1068, + 1069, + 1070, + 1071, + 1072, + 1073, + 1074, + 1075, + 1076, + 1077, + 1078, + 1079, + 1080, + 1081, + 1082, + 1083, + 1084, + 1085, + 1086, + 1087, + 1088, + 1089, + 1090, + 1091, + 1092, + 1093, + 1094, + 1095 + ], + [ + 1096, + 1097, + 1098, + 1099, + 1100, + 1101, + 1102, + 1103, + 1104, + 1105, + 1106, + 1107, + 1108, + 1109, + 1110, + 1111, + 1112, + 1113, + 1114, + 1115, + 1116, + 1117, + 1118, + 1119, + 1120, + 1121, + 1122, + 1123, + 1124, + 1125, + 1126, + 1127 + ], + [ + 1128, + 1129, + 1130, + 1131, + 1132, + 1133, + 1134, + 1135, + 1136, + 1137, + 1138, + 1139, + 1140, + 1141, + 1142, + 1143, + 1144, + 1145, + 1146, + 1147, + 1148, + 1149, + 1150, + 1151, + 1152, + 1153, + 1154, + 1155, + 1156, + 1157, + 1158, + 1159 + ], + [ + 1160, + 1161, + 1162, + 1163, + 1164, + 1165, + 1166, + 1167, + 1168, + 1169, + 1170, + 1171, + 1172, + 1173, + 1174, + 1175, + 1176, + 1177, + 1178, + 1179, + 1180, + 1181, + 1182, + 1183, + 1184, + 1185, + 1186, + 1187, + 1188, + 1189, + 1190, + 1191 + ], + [ + 1192, + 1193, + 1194, + 1195, + 1196, + 1197, + 1198, + 1199, + 1200, + 1201, + 1202, + 1203, + 1204, + 1205, + 1206, + 1207, + 1208, + 1209, + 1210, + 1211, + 1212, + 1213, + 1214, + 1215, + 1216, + 1217, + 1218, + 1219, + 1220, + 1221, + 1222, + 1223 + ] + ], + "array_value_summary": { + "shape": [ + 32, + 32 + ], + "dtype": "uint16", + "size": 1024, + "nonzero_count": 1024, + "min": 200, + "max": 1223, + "requested": true, + "included": true, + "slice_ranges": [ + [ + 0, + 32 + ], + [ + 0, + 32 + ] + ] + }, + "route_key": "origin_manual_kind_manual_projection_selected_images_e83ddc2185a63aca4b85ec471143f61c8f4eabdb08df3557ca21f2bddcda60b9", + "shape_payloads": [] + } + ] + }, + { + "route_key": "origin_manual_kind_manual_projection_A01_s001_w2_z001_t001_graph.graph.roi.zip_shapes", + "title": "A01_s001_w2_z001_t001_graph.graph.roi.zip ROIs", + "mounted": true, + "item_count": 1, + "producer_identities": [ + { + "origin": "manual", + "output_kind": "manual", + "output_key": "A01_s001_w2_z001_t001_graph.graph.roi.zip", + "projection_key": "A01_s001_w2_z001_t001_graph.graph.roi.zip", + "step_name": null, + "pipeline_position": null, + "step_scope_id": null, + "invocation_key": null, + "artifact_kind": null + } + ], + "axis_labels": [ + "site", + "channel", + "z_index", + "timepoint", + "well", + "y", + "x" + ], + "stack_axes": [ + "channel" + ], + "pending_update": false, + "payloads": [ + { + "data_type": "shapes", + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/graph_results/A01_s001_w2_z001_t001_graph.graph.roi.zip", + "components": { + "site": 1, + "channel": 2, + "z_index": 1, + "timepoint": 1, + "well": "A01" + }, + "axis_indices": [ + 0 + ], + "aggregate_axis_indices": [], + "summary": { + "nonzero_count": 2, + "item_count": 2, + "shape_payload_count": 2, + "missing_source_spatial_shape_count": 2, + "shape_coordinate_count": 4, + "shape_out_of_source_bounds_count": 0, + "shape_coordinate_bounds_yx": { + "min_yx": [ + 2.25, + 3.5 + ], + "max_yx": [ + 7.25, + 12.5 + ], + "coordinate_count": 4 + }, + "source_voxel_spacing": { + "values_zyx": [ + 1.3556, + 1.3556 + ], + "unit": "micrometers" + }, + "data_type": "shapes", + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/graph_results/A01_s001_w2_z001_t001_graph.graph.roi.zip", + "components": { + "site": 1, + "channel": 2, + "z_index": 1, + "timepoint": 1, + "well": "A01" + }, + "payload_type": "list" + }, + "array_values": [], + "array_value_summary": { + "requested": true, + "included": false, + "omitted_reason": "payload_not_ndarray" + }, + "route_key": "origin_manual_kind_manual_projection_A01_s001_w2_z001_t001_graph.graph.roi.zip_shapes", + "shape_payloads": [ + { + "type": "path", + "coordinates": [ + [ + 2.25, + 3.5 + ], + [ + 5.25, + 9.5 + ] + ], + "metadata": { + "__openhcs_object_subject__": "[\"output\",\"object_labels\",\"neurons\",\"synthetic-receiving-134\",4]", + "__openhcs_object_subject_id__": 7, + "area": 0.0, + "branch_distance_um": 8.5, + "centroid": [ + 3.75, + 6.5 + ], + "edge_id": 1, + "graph": "declared_graph", + "label": 1, + "neuron_label": 7, + "openhcs_image_payload_metadata": { + "intensity_scale": null, + "mask_defines_border": null, + "physical_border_edges_yx": null, + "plane_axis": null, + "source_channel_axis": null, + "source_dtype": null, + "source_plane_dtypes": [], + "source_plane_intensity_scales": [], + "source_provenance": { + "source_component_metadata": { + "OpenHCSSourceVoxelSpacingUnit": "micrometers", + "OpenHCSSourceVoxelSpacingZYX": "1.3555999999999999,1.3555999999999999", + "channel": "2", + "site": "1", + "timepoint": "1", + "well": "A01", + "z_index": "1" + }, + "source_image_names": [ + "raw_2" + ], + "source_image_provenance_planes": [], + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w2_z001_t001.tif" + }, + "source_spatial_domain": { + "fill_value": 0, + "origin_yx": null, + "source_shape_yx": null, + "spatial_dimensions": 2, + "value_name": "Dense array" + }, + "source_voxel_spacing": { + "unit": "micrometers", + "values_zyx": [ + 1.3556, + 1.3556 + ] + }, + "unit_interval_intensity": null + }, + "perimeter": 6.708203932499369, + "source_node_id": 1, + "target_node_id": 2 + } + }, + { + "type": "path", + "coordinates": [ + [ + 5.25, + 9.5 + ], + [ + 7.25, + 12.5 + ] + ], + "metadata": { + "__openhcs_object_subject__": "[\"output\",\"object_labels\",\"neurons\",\"synthetic-receiving-134\",4]", + "__openhcs_object_subject_id__": 7, + "area": 0.0, + "branch_distance_um": 8.5, + "centroid": [ + 6.25, + 11.0 + ], + "edge_id": 2, + "graph": "declared_graph", + "label": 2, + "neuron_label": 7, + "openhcs_image_payload_metadata": { + "intensity_scale": null, + "mask_defines_border": null, + "physical_border_edges_yx": null, + "plane_axis": null, + "source_channel_axis": null, + "source_dtype": null, + "source_plane_dtypes": [], + "source_plane_intensity_scales": [], + "source_provenance": { + "source_component_metadata": { + "OpenHCSSourceVoxelSpacingUnit": "micrometers", + "OpenHCSSourceVoxelSpacingZYX": "1.3555999999999999,1.3555999999999999", + "channel": "2", + "site": "1", + "timepoint": "1", + "well": "A01", + "z_index": "1" + }, + "source_image_names": [ + "raw_2" + ], + "source_image_provenance_planes": [], + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w2_z001_t001.tif" + }, + "source_spatial_domain": { + "fill_value": 0, + "origin_yx": null, + "source_shape_yx": null, + "spatial_dimensions": 2, + "value_name": "Dense array" + }, + "source_voxel_spacing": { + "unit": "micrometers", + "values_zyx": [ + 1.3556, + 1.3556 + ] + }, + "unit_interval_intensity": null + }, + "perimeter": 3.605551275463989, + "source_node_id": 2, + "target_node_id": 3 + } + } + ] + } + ] + } + ], + "response": {} + } + }, + { + "tool": "openhcs_summarize_viewer_window_rois", + "arguments": { + "host": "127.0.0.1", + "port": 6609, + "transport_mode": "tcp", + "route_key": "origin_manual_kind_manual_projection_A01_s001_w2_z001_t001_graph.graph.roi.zip_shapes", + "axis_indices": null, + "max_rois": 512, + "max_examples": 10 + }, + "response": { + "content": [ + { + "type": "text", + "text": "{\n \"schema_version\": \"openhcs.agent.v1\",\n \"errors\": [],\n \"warnings\": [],\n \"observed\": true,\n \"route_key\": \"origin_manual_kind_manual_projection_A01_s001_w2_z001_t001_graph.graph.roi.zip_shapes\",\n \"axis_indices\": null,\n \"layer_count\": 1,\n \"payload_record_count\": 1,\n \"payload_type_counts\": {\n \"shapes\": 1\n },\n \"roi_payload_count\": 1,\n \"total_roi_count\": 2,\n \"returned_roi_count\": 2,\n \"roi_count_exact\": true,\n \"total_roi_member_count\": 2,\n \"returned_roi_member_count\": 2,\n \"roi_payloads_truncated\": false,\n \"payloads\": [\n {\n \"layer_route_key\": \"origin_manual_kind_manual_projection_A01_s001_w2_z001_t001_graph.graph.roi.zip_shapes\",\n \"layer_title\": \"A01_s001_w2_z001_t001_graph.graph.roi.zip ROIs\",\n \"payload_route_key\": \"origin_manual_kind_manual_projection_A01_s001_w2_z001_t001_graph.graph.roi.zip_shapes\",\n \"path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/graph_results/A01_s001_w2_z001_t001_graph.graph.roi.zip\",\n \"components\": {\n \"site\": 1,\n \"channel\": 2,\n \"z_index\": 1,\n \"timepoint\": 1,\n \"well\": \"A01\"\n },\n \"axis_indices\": [\n 0\n ],\n \"roi_count\": 2,\n \"returned_roi_count\": 2,\n \"roi_count_exact\": true,\n \"roi_member_count\": 2,\n \"returned_roi_member_count\": 2,\n \"roi_duplicate_member_count\": 0,\n \"roi_payloads_truncated\": false,\n \"area\": {\n \"min\": 0.0,\n \"median\": 0.0,\n \"mean\": 0.0,\n \"max\": 0.0\n },\n \"perimeter\": {\n \"min\": 3.605551275463989,\n \"median\": 6.708203932499369,\n \"mean\": 5.1568776039816795,\n \"max\": 6.708203932499369\n },\n \"bounds_yx\": {\n \"min_yx\": [\n 2.25,\n 3.5\n ],\n \"max_yx\": [\n 7.25,\n 12.5\n ],\n \"coordinate_count\": 4\n },\n \"coordinate_count\": 4,\n \"spatial_origin_yx\": null,\n \"source_spatial_shape_yx\": null,\n \"out_of_source_bounds_count\": 0,\n \"example_rois\": [\n {\n \"type\": \"path\",\n \"label\": 1,\n \"area\": 0.0,\n \"centroid_yx\": [\n 3.75,\n 6.5\n ],\n \"bbox_yxyx\": null,\n \"perimeter\": 6.708203932499369,\n \"source_spatial_shape_yx\": null\n },\n {\n \"type\": \"path\",\n \"label\": 2,\n \"area\": 0.0,\n \"centroid_yx\": [\n 6.25,\n 11.0\n ],\n \"bbox_yxyx\": null,\n \"perimeter\": 3.605551275463989,\n \"source_spatial_shape_yx\": null\n }\n ]\n }\n ]\n}" + } + ], + "structuredContent": { + "schema_version": "openhcs.agent.v1", + "errors": [], + "warnings": [], + "observed": true, + "route_key": "origin_manual_kind_manual_projection_A01_s001_w2_z001_t001_graph.graph.roi.zip_shapes", + "axis_indices": null, + "layer_count": 1, + "payload_record_count": 1, + "payload_type_counts": { + "shapes": 1 + }, + "roi_payload_count": 1, + "total_roi_count": 2, + "returned_roi_count": 2, + "roi_count_exact": true, + "total_roi_member_count": 2, + "returned_roi_member_count": 2, + "roi_payloads_truncated": false, + "payloads": [ + { + "layer_route_key": "origin_manual_kind_manual_projection_A01_s001_w2_z001_t001_graph.graph.roi.zip_shapes", + "layer_title": "A01_s001_w2_z001_t001_graph.graph.roi.zip ROIs", + "payload_route_key": "origin_manual_kind_manual_projection_A01_s001_w2_z001_t001_graph.graph.roi.zip_shapes", + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/graph_results/A01_s001_w2_z001_t001_graph.graph.roi.zip", + "components": { + "site": 1, + "channel": 2, + "z_index": 1, + "timepoint": 1, + "well": "A01" + }, + "axis_indices": [ + 0 + ], + "roi_count": 2, + "returned_roi_count": 2, + "roi_count_exact": true, + "roi_member_count": 2, + "returned_roi_member_count": 2, + "roi_duplicate_member_count": 0, + "roi_payloads_truncated": false, + "area": { + "min": 0.0, + "median": 0.0, + "mean": 0.0, + "max": 0.0 + }, + "perimeter": { + "min": 3.605551275463989, + "median": 6.708203932499369, + "mean": 5.1568776039816795, + "max": 6.708203932499369 + }, + "bounds_yx": { + "min_yx": [ + 2.25, + 3.5 + ], + "max_yx": [ + 7.25, + 12.5 + ], + "coordinate_count": 4 + }, + "coordinate_count": 4, + "spatial_origin_yx": null, + "source_spatial_shape_yx": null, + "out_of_source_bounds_count": 0, + "example_rois": [ + { + "type": "path", + "label": 1, + "area": 0.0, + "centroid_yx": [ + 3.75, + 6.5 + ], + "bbox_yxyx": null, + "perimeter": 6.708203932499369, + "source_spatial_shape_yx": null + }, + { + "type": "path", + "label": 2, + "area": 0.0, + "centroid_yx": [ + 6.25, + 11.0 + ], + "bbox_yxyx": null, + "perimeter": 3.605551275463989, + "source_spatial_shape_yx": null + } + ] + } + ] + }, + "isError": false + }, + "payload": { + "schema_version": "openhcs.agent.v1", + "errors": [], + "warnings": [], + "observed": true, + "route_key": "origin_manual_kind_manual_projection_A01_s001_w2_z001_t001_graph.graph.roi.zip_shapes", + "axis_indices": null, + "layer_count": 1, + "payload_record_count": 1, + "payload_type_counts": { + "shapes": 1 + }, + "roi_payload_count": 1, + "total_roi_count": 2, + "returned_roi_count": 2, + "roi_count_exact": true, + "total_roi_member_count": 2, + "returned_roi_member_count": 2, + "roi_payloads_truncated": false, + "payloads": [ + { + "layer_route_key": "origin_manual_kind_manual_projection_A01_s001_w2_z001_t001_graph.graph.roi.zip_shapes", + "layer_title": "A01_s001_w2_z001_t001_graph.graph.roi.zip ROIs", + "payload_route_key": "origin_manual_kind_manual_projection_A01_s001_w2_z001_t001_graph.graph.roi.zip_shapes", + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/graph_results/A01_s001_w2_z001_t001_graph.graph.roi.zip", + "components": { + "site": 1, + "channel": 2, + "z_index": 1, + "timepoint": 1, + "well": "A01" + }, + "axis_indices": [ + 0 + ], + "roi_count": 2, + "returned_roi_count": 2, + "roi_count_exact": true, + "roi_member_count": 2, + "returned_roi_member_count": 2, + "roi_duplicate_member_count": 0, + "roi_payloads_truncated": false, + "area": { + "min": 0.0, + "median": 0.0, + "mean": 0.0, + "max": 0.0 + }, + "perimeter": { + "min": 3.605551275463989, + "median": 6.708203932499369, + "mean": 5.1568776039816795, + "max": 6.708203932499369 + }, + "bounds_yx": { + "min_yx": [ + 2.25, + 3.5 + ], + "max_yx": [ + 7.25, + 12.5 + ], + "coordinate_count": 4 + }, + "coordinate_count": 4, + "spatial_origin_yx": null, + "source_spatial_shape_yx": null, + "out_of_source_bounds_count": 0, + "example_rois": [ + { + "type": "path", + "label": 1, + "area": 0.0, + "centroid_yx": [ + 3.75, + 6.5 + ], + "bbox_yxyx": null, + "perimeter": 6.708203932499369, + "source_spatial_shape_yx": null + }, + { + "type": "path", + "label": 2, + "area": 0.0, + "centroid_yx": [ + 6.25, + 11.0 + ], + "bbox_yxyx": null, + "perimeter": 3.605551275463989, + "source_spatial_shape_yx": null + } + ] + } + ] + } + }, + { + "tool": "openhcs_get_viewer_window_payloads", + "arguments": { + "host": "127.0.0.1", + "port": 6609, + "transport_mode": "tcp", + "route_key": "origin_manual_kind_manual_projection_A01_s001_w2_z001_t001_graph.graph.roi.zip_shapes", + "axis_indices": null, + "include_array_values": false, + "max_array_elements": 4096, + "array_slices": null, + "include_shape_payloads": true, + "max_shape_payloads": 20, + "include_response": false + }, + "response": { + "content": [ + { + "type": "text", + "text": "{\n \"connection\": {\n \"host\": \"127.0.0.1\",\n \"port\": 6609,\n \"transport_mode\": \"tcp\",\n \"persistent\": true\n },\n \"schema_version\": \"openhcs.agent.v1\",\n \"errors\": [],\n \"warnings\": [],\n \"observed\": true,\n \"viewer\": {\n \"viewer_type\": \"napari\",\n \"title\": \"OpenHCS Napari Visualization\"\n },\n \"layer_count\": 1,\n \"layers\": [\n {\n \"route_key\": \"origin_manual_kind_manual_projection_A01_s001_w2_z001_t001_graph.graph.roi.zip_shapes\",\n \"title\": \"A01_s001_w2_z001_t001_graph.graph.roi.zip ROIs\",\n \"mounted\": true,\n \"item_count\": 1,\n \"producer_identities\": [\n {\n \"origin\": \"manual\",\n \"output_kind\": \"manual\",\n \"output_key\": \"A01_s001_w2_z001_t001_graph.graph.roi.zip\",\n \"projection_key\": \"A01_s001_w2_z001_t001_graph.graph.roi.zip\",\n \"step_name\": null,\n \"pipeline_position\": null,\n \"step_scope_id\": null,\n \"invocation_key\": null,\n \"artifact_kind\": null\n }\n ],\n \"axis_labels\": [\n \"site\",\n \"channel\",\n \"z_index\",\n \"timepoint\",\n \"well\",\n \"y\",\n \"x\"\n ],\n \"stack_axes\": [\n \"channel\"\n ],\n \"pending_update\": false,\n \"payloads\": [\n {\n \"data_type\": \"shapes\",\n \"path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/graph_results/A01_s001_w2_z001_t001_graph.graph.roi.zip\",\n \"components\": {\n \"site\": 1,\n \"channel\": 2,\n \"z_index\": 1,\n \"timepoint\": 1,\n \"well\": \"A01\"\n },\n \"axis_indices\": [\n 0\n ],\n \"aggregate_axis_indices\": [],\n \"summary\": {\n \"nonzero_count\": 2,\n \"item_count\": 2,\n \"shape_payload_count\": 2,\n \"missing_source_spatial_shape_count\": 2,\n \"shape_coordinate_count\": 4,\n \"shape_out_of_source_bounds_count\": 0,\n \"shape_coordinate_bounds_yx\": {\n \"min_yx\": [\n 2.25,\n 3.5\n ],\n \"max_yx\": [\n 7.25,\n 12.5\n ],\n \"coordinate_count\": 4\n },\n \"source_voxel_spacing\": {\n \"values_zyx\": [\n 1.3556,\n 1.3556\n ],\n \"unit\": \"micrometers\"\n },\n \"data_type\": \"shapes\",\n \"path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/graph_results/A01_s001_w2_z001_t001_graph.graph.roi.zip\",\n \"components\": {\n \"site\": 1,\n \"channel\": 2,\n \"z_index\": 1,\n \"timepoint\": 1,\n \"well\": \"A01\"\n },\n \"payload_type\": \"list\"\n },\n \"array_values\": [],\n \"array_value_summary\": {},\n \"route_key\": \"origin_manual_kind_manual_projection_A01_s001_w2_z001_t001_graph.graph.roi.zip_shapes\",\n \"shape_payloads\": [\n {\n \"type\": \"path\",\n \"coordinates\": [\n [\n 2.25,\n 3.5\n ],\n [\n 5.25,\n 9.5\n ]\n ],\n \"metadata\": {\n \"__openhcs_object_subject__\": \"[\\\"output\\\",\\\"object_labels\\\",\\\"neurons\\\",\\\"synthetic-receiving-134\\\",4]\",\n \"__openhcs_object_subject_id__\": 7,\n \"area\": 0.0,\n \"branch_distance_um\": 8.5,\n \"centroid\": [\n 3.75,\n 6.5\n ],\n \"edge_id\": 1,\n \"graph\": \"declared_graph\",\n \"label\": 1,\n \"neuron_label\": 7,\n \"openhcs_image_payload_metadata\": {\n \"intensity_scale\": null,\n \"mask_defines_border\": null,\n \"physical_border_edges_yx\": null,\n \"plane_axis\": null,\n \"source_channel_axis\": null,\n \"source_dtype\": null,\n \"source_plane_dtypes\": [],\n \"source_plane_intensity_scales\": [],\n \"source_provenance\": {\n \"source_component_metadata\": {\n \"OpenHCSSourceVoxelSpacingUnit\": \"micrometers\",\n \"OpenHCSSourceVoxelSpacingZYX\": \"1.3555999999999999,1.3555999999999999\",\n \"channel\": \"2\",\n \"site\": \"1\",\n \"timepoint\": \"1\",\n \"well\": \"A01\",\n \"z_index\": \"1\"\n },\n \"source_image_names\": [\n \"raw_2\"\n ],\n \"source_image_provenance_planes\": [],\n \"source_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w2_z001_t001.tif\"\n },\n \"source_spatial_domain\": {\n \"fill_value\": 0,\n \"origin_yx\": null,\n \"source_shape_yx\": null,\n \"spatial_dimensions\": 2,\n \"value_name\": \"Dense array\"\n },\n \"source_voxel_spacing\": {\n \"unit\": \"micrometers\",\n \"values_zyx\": [\n 1.3556,\n 1.3556\n ]\n },\n \"unit_interval_intensity\": null\n },\n \"perimeter\": 6.708203932499369,\n \"source_node_id\": 1,\n \"target_node_id\": 2\n }\n },\n {\n \"type\": \"path\",\n \"coordinates\": [\n [\n 5.25,\n 9.5\n ],\n [\n 7.25,\n 12.5\n ]\n ],\n \"metadata\": {\n \"__openhcs_object_subject__\": \"[\\\"output\\\",\\\"object_labels\\\",\\\"neurons\\\",\\\"synthetic-receiving-134\\\",4]\",\n \"__openhcs_object_subject_id__\": 7,\n \"area\": 0.0,\n \"branch_distance_um\": 8.5,\n \"centroid\": [\n 6.25,\n 11.0\n ],\n \"edge_id\": 2,\n \"graph\": \"declared_graph\",\n \"label\": 2,\n \"neuron_label\": 7,\n \"openhcs_image_payload_metadata\": {\n \"intensity_scale\": null,\n \"mask_defines_border\": null,\n \"physical_border_edges_yx\": null,\n \"plane_axis\": null,\n \"source_channel_axis\": null,\n \"source_dtype\": null,\n \"source_plane_dtypes\": [],\n \"source_plane_intensity_scales\": [],\n \"source_provenance\": {\n \"source_component_metadata\": {\n \"OpenHCSSourceVoxelSpacingUnit\": \"micrometers\",\n \"OpenHCSSourceVoxelSpacingZYX\": \"1.3555999999999999,1.3555999999999999\",\n \"channel\": \"2\",\n \"site\": \"1\",\n \"timepoint\": \"1\",\n \"well\": \"A01\",\n \"z_index\": \"1\"\n },\n \"source_image_names\": [\n \"raw_2\"\n ],\n \"source_image_provenance_planes\": [],\n \"source_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w2_z001_t001.tif\"\n },\n \"source_spatial_domain\": {\n \"fill_value\": 0,\n \"origin_yx\": null,\n \"source_shape_yx\": null,\n \"spatial_dimensions\": 2,\n \"value_name\": \"Dense array\"\n },\n \"source_voxel_spacing\": {\n \"unit\": \"micrometers\",\n \"values_zyx\": [\n 1.3556,\n 1.3556\n ]\n },\n \"unit_interval_intensity\": null\n },\n \"perimeter\": 3.605551275463989,\n \"source_node_id\": 2,\n \"target_node_id\": 3\n }\n }\n ]\n }\n ]\n }\n ],\n \"response\": {}\n}" + } + ], + "structuredContent": { + "connection": { + "host": "127.0.0.1", + "port": 6609, + "transport_mode": "tcp", + "persistent": true + }, + "schema_version": "openhcs.agent.v1", + "errors": [], + "warnings": [], + "observed": true, + "viewer": { + "viewer_type": "napari", + "title": "OpenHCS Napari Visualization" + }, + "layer_count": 1, + "layers": [ + { + "route_key": "origin_manual_kind_manual_projection_A01_s001_w2_z001_t001_graph.graph.roi.zip_shapes", + "title": "A01_s001_w2_z001_t001_graph.graph.roi.zip ROIs", + "mounted": true, + "item_count": 1, + "producer_identities": [ + { + "origin": "manual", + "output_kind": "manual", + "output_key": "A01_s001_w2_z001_t001_graph.graph.roi.zip", + "projection_key": "A01_s001_w2_z001_t001_graph.graph.roi.zip", + "step_name": null, + "pipeline_position": null, + "step_scope_id": null, + "invocation_key": null, + "artifact_kind": null + } + ], + "axis_labels": [ + "site", + "channel", + "z_index", + "timepoint", + "well", + "y", + "x" + ], + "stack_axes": [ + "channel" + ], + "pending_update": false, + "payloads": [ + { + "data_type": "shapes", + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/graph_results/A01_s001_w2_z001_t001_graph.graph.roi.zip", + "components": { + "site": 1, + "channel": 2, + "z_index": 1, + "timepoint": 1, + "well": "A01" + }, + "axis_indices": [ + 0 + ], + "aggregate_axis_indices": [], + "summary": { + "nonzero_count": 2, + "item_count": 2, + "shape_payload_count": 2, + "missing_source_spatial_shape_count": 2, + "shape_coordinate_count": 4, + "shape_out_of_source_bounds_count": 0, + "shape_coordinate_bounds_yx": { + "min_yx": [ + 2.25, + 3.5 + ], + "max_yx": [ + 7.25, + 12.5 + ], + "coordinate_count": 4 + }, + "source_voxel_spacing": { + "values_zyx": [ + 1.3556, + 1.3556 + ], + "unit": "micrometers" + }, + "data_type": "shapes", + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/graph_results/A01_s001_w2_z001_t001_graph.graph.roi.zip", + "components": { + "site": 1, + "channel": 2, + "z_index": 1, + "timepoint": 1, + "well": "A01" + }, + "payload_type": "list" + }, + "array_values": [], + "array_value_summary": {}, + "route_key": "origin_manual_kind_manual_projection_A01_s001_w2_z001_t001_graph.graph.roi.zip_shapes", + "shape_payloads": [ + { + "type": "path", + "coordinates": [ + [ + 2.25, + 3.5 + ], + [ + 5.25, + 9.5 + ] + ], + "metadata": { + "__openhcs_object_subject__": "[\"output\",\"object_labels\",\"neurons\",\"synthetic-receiving-134\",4]", + "__openhcs_object_subject_id__": 7, + "area": 0.0, + "branch_distance_um": 8.5, + "centroid": [ + 3.75, + 6.5 + ], + "edge_id": 1, + "graph": "declared_graph", + "label": 1, + "neuron_label": 7, + "openhcs_image_payload_metadata": { + "intensity_scale": null, + "mask_defines_border": null, + "physical_border_edges_yx": null, + "plane_axis": null, + "source_channel_axis": null, + "source_dtype": null, + "source_plane_dtypes": [], + "source_plane_intensity_scales": [], + "source_provenance": { + "source_component_metadata": { + "OpenHCSSourceVoxelSpacingUnit": "micrometers", + "OpenHCSSourceVoxelSpacingZYX": "1.3555999999999999,1.3555999999999999", + "channel": "2", + "site": "1", + "timepoint": "1", + "well": "A01", + "z_index": "1" + }, + "source_image_names": [ + "raw_2" + ], + "source_image_provenance_planes": [], + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w2_z001_t001.tif" + }, + "source_spatial_domain": { + "fill_value": 0, + "origin_yx": null, + "source_shape_yx": null, + "spatial_dimensions": 2, + "value_name": "Dense array" + }, + "source_voxel_spacing": { + "unit": "micrometers", + "values_zyx": [ + 1.3556, + 1.3556 + ] + }, + "unit_interval_intensity": null + }, + "perimeter": 6.708203932499369, + "source_node_id": 1, + "target_node_id": 2 + } + }, + { + "type": "path", + "coordinates": [ + [ + 5.25, + 9.5 + ], + [ + 7.25, + 12.5 + ] + ], + "metadata": { + "__openhcs_object_subject__": "[\"output\",\"object_labels\",\"neurons\",\"synthetic-receiving-134\",4]", + "__openhcs_object_subject_id__": 7, + "area": 0.0, + "branch_distance_um": 8.5, + "centroid": [ + 6.25, + 11.0 + ], + "edge_id": 2, + "graph": "declared_graph", + "label": 2, + "neuron_label": 7, + "openhcs_image_payload_metadata": { + "intensity_scale": null, + "mask_defines_border": null, + "physical_border_edges_yx": null, + "plane_axis": null, + "source_channel_axis": null, + "source_dtype": null, + "source_plane_dtypes": [], + "source_plane_intensity_scales": [], + "source_provenance": { + "source_component_metadata": { + "OpenHCSSourceVoxelSpacingUnit": "micrometers", + "OpenHCSSourceVoxelSpacingZYX": "1.3555999999999999,1.3555999999999999", + "channel": "2", + "site": "1", + "timepoint": "1", + "well": "A01", + "z_index": "1" + }, + "source_image_names": [ + "raw_2" + ], + "source_image_provenance_planes": [], + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w2_z001_t001.tif" + }, + "source_spatial_domain": { + "fill_value": 0, + "origin_yx": null, + "source_shape_yx": null, + "spatial_dimensions": 2, + "value_name": "Dense array" + }, + "source_voxel_spacing": { + "unit": "micrometers", + "values_zyx": [ + 1.3556, + 1.3556 + ] + }, + "unit_interval_intensity": null + }, + "perimeter": 3.605551275463989, + "source_node_id": 2, + "target_node_id": 3 + } + } + ] + } + ] + } + ], + "response": {} + }, + "isError": false + }, + "payload": { + "connection": { + "host": "127.0.0.1", + "port": 6609, + "transport_mode": "tcp", + "persistent": true + }, + "schema_version": "openhcs.agent.v1", + "errors": [], + "warnings": [], + "observed": true, + "viewer": { + "viewer_type": "napari", + "title": "OpenHCS Napari Visualization" + }, + "layer_count": 1, + "layers": [ + { + "route_key": "origin_manual_kind_manual_projection_A01_s001_w2_z001_t001_graph.graph.roi.zip_shapes", + "title": "A01_s001_w2_z001_t001_graph.graph.roi.zip ROIs", + "mounted": true, + "item_count": 1, + "producer_identities": [ + { + "origin": "manual", + "output_kind": "manual", + "output_key": "A01_s001_w2_z001_t001_graph.graph.roi.zip", + "projection_key": "A01_s001_w2_z001_t001_graph.graph.roi.zip", + "step_name": null, + "pipeline_position": null, + "step_scope_id": null, + "invocation_key": null, + "artifact_kind": null + } + ], + "axis_labels": [ + "site", + "channel", + "z_index", + "timepoint", + "well", + "y", + "x" + ], + "stack_axes": [ + "channel" + ], + "pending_update": false, + "payloads": [ + { + "data_type": "shapes", + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/graph_results/A01_s001_w2_z001_t001_graph.graph.roi.zip", + "components": { + "site": 1, + "channel": 2, + "z_index": 1, + "timepoint": 1, + "well": "A01" + }, + "axis_indices": [ + 0 + ], + "aggregate_axis_indices": [], + "summary": { + "nonzero_count": 2, + "item_count": 2, + "shape_payload_count": 2, + "missing_source_spatial_shape_count": 2, + "shape_coordinate_count": 4, + "shape_out_of_source_bounds_count": 0, + "shape_coordinate_bounds_yx": { + "min_yx": [ + 2.25, + 3.5 + ], + "max_yx": [ + 7.25, + 12.5 + ], + "coordinate_count": 4 + }, + "source_voxel_spacing": { + "values_zyx": [ + 1.3556, + 1.3556 + ], + "unit": "micrometers" + }, + "data_type": "shapes", + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/graph_results/A01_s001_w2_z001_t001_graph.graph.roi.zip", + "components": { + "site": 1, + "channel": 2, + "z_index": 1, + "timepoint": 1, + "well": "A01" + }, + "payload_type": "list" + }, + "array_values": [], + "array_value_summary": {}, + "route_key": "origin_manual_kind_manual_projection_A01_s001_w2_z001_t001_graph.graph.roi.zip_shapes", + "shape_payloads": [ + { + "type": "path", + "coordinates": [ + [ + 2.25, + 3.5 + ], + [ + 5.25, + 9.5 + ] + ], + "metadata": { + "__openhcs_object_subject__": "[\"output\",\"object_labels\",\"neurons\",\"synthetic-receiving-134\",4]", + "__openhcs_object_subject_id__": 7, + "area": 0.0, + "branch_distance_um": 8.5, + "centroid": [ + 3.75, + 6.5 + ], + "edge_id": 1, + "graph": "declared_graph", + "label": 1, + "neuron_label": 7, + "openhcs_image_payload_metadata": { + "intensity_scale": null, + "mask_defines_border": null, + "physical_border_edges_yx": null, + "plane_axis": null, + "source_channel_axis": null, + "source_dtype": null, + "source_plane_dtypes": [], + "source_plane_intensity_scales": [], + "source_provenance": { + "source_component_metadata": { + "OpenHCSSourceVoxelSpacingUnit": "micrometers", + "OpenHCSSourceVoxelSpacingZYX": "1.3555999999999999,1.3555999999999999", + "channel": "2", + "site": "1", + "timepoint": "1", + "well": "A01", + "z_index": "1" + }, + "source_image_names": [ + "raw_2" + ], + "source_image_provenance_planes": [], + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w2_z001_t001.tif" + }, + "source_spatial_domain": { + "fill_value": 0, + "origin_yx": null, + "source_shape_yx": null, + "spatial_dimensions": 2, + "value_name": "Dense array" + }, + "source_voxel_spacing": { + "unit": "micrometers", + "values_zyx": [ + 1.3556, + 1.3556 + ] + }, + "unit_interval_intensity": null + }, + "perimeter": 6.708203932499369, + "source_node_id": 1, + "target_node_id": 2 + } + }, + { + "type": "path", + "coordinates": [ + [ + 5.25, + 9.5 + ], + [ + 7.25, + 12.5 + ] + ], + "metadata": { + "__openhcs_object_subject__": "[\"output\",\"object_labels\",\"neurons\",\"synthetic-receiving-134\",4]", + "__openhcs_object_subject_id__": 7, + "area": 0.0, + "branch_distance_um": 8.5, + "centroid": [ + 6.25, + 11.0 + ], + "edge_id": 2, + "graph": "declared_graph", + "label": 2, + "neuron_label": 7, + "openhcs_image_payload_metadata": { + "intensity_scale": null, + "mask_defines_border": null, + "physical_border_edges_yx": null, + "plane_axis": null, + "source_channel_axis": null, + "source_dtype": null, + "source_plane_dtypes": [], + "source_plane_intensity_scales": [], + "source_provenance": { + "source_component_metadata": { + "OpenHCSSourceVoxelSpacingUnit": "micrometers", + "OpenHCSSourceVoxelSpacingZYX": "1.3555999999999999,1.3555999999999999", + "channel": "2", + "site": "1", + "timepoint": "1", + "well": "A01", + "z_index": "1" + }, + "source_image_names": [ + "raw_2" + ], + "source_image_provenance_planes": [], + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w2_z001_t001.tif" + }, + "source_spatial_domain": { + "fill_value": 0, + "origin_yx": null, + "source_shape_yx": null, + "spatial_dimensions": 2, + "value_name": "Dense array" + }, + "source_voxel_spacing": { + "unit": "micrometers", + "values_zyx": [ + 1.3556, + 1.3556 + ] + }, + "unit_interval_intensity": null + }, + "perimeter": 3.605551275463989, + "source_node_id": 2, + "target_node_id": 3 + } + } + ] + } + ] + } + ], + "response": {} + } + }, + { + "tool": "openhcs_isolate_viewer_window_layers", + "arguments": { + "host": "127.0.0.1", + "port": 6609, + "transport_mode": "tcp", + "visible_route_keys": [ + "origin_manual_kind_manual_projection_selected_images_e83ddc2185a63aca4b85ec471143f61c8f4eabdb08df3557ca21f2bddcda60b9" + ], + "selected_route_key": "origin_manual_kind_manual_projection_selected_images_e83ddc2185a63aca4b85ec471143f61c8f4eabdb08df3557ca21f2bddcda60b9", + "axis_indices": { + "channel": 1 + } + }, + "response": { + "content": [ + { + "type": "text", + "text": "{\n \"connection\": {\n \"host\": \"127.0.0.1\",\n \"port\": 6609,\n \"transport_mode\": \"tcp\",\n \"persistent\": true\n },\n \"schema_version\": \"openhcs.agent.v1\",\n \"errors\": [],\n \"warnings\": [],\n \"observed\": true,\n \"applied\": true,\n \"selected_route_key\": \"origin_manual_kind_manual_projection_selected_images_e83ddc2185a63aca4b85ec471143f61c8f4eabdb08df3557ca21f2bddcda60b9\",\n \"visible_route_keys\": [\n \"origin_manual_kind_manual_projection_selected_images_e83ddc2185a63aca4b85ec471143f61c8f4eabdb08df3557ca21f2bddcda60b9\"\n ],\n \"hidden_route_keys\": [\n \"origin_manual_kind_manual_projection_selected_images_8c7357d46ccc38823ca9e68096baf86f25c3004b61b63ba1eef9adea41d34fb8_scalar_stack\",\n \"origin_manual_kind_manual_projection_A01_s001_w2_z001_t001_graph.graph.roi.zip_shapes\"\n ],\n \"missing_route_keys\": [],\n \"available_layers\": [\n {\n \"route_key\": \"origin_manual_kind_manual_projection_selected_images_8c7357d46ccc38823ca9e68096baf86f25c3004b61b63ba1eef9adea41d34fb8_scalar_stack\",\n \"title\": \"selected_images image stack\",\n \"visible\": false,\n \"selected\": false\n },\n {\n \"route_key\": \"origin_manual_kind_manual_projection_selected_images_e83ddc2185a63aca4b85ec471143f61c8f4eabdb08df3557ca21f2bddcda60b9\",\n \"title\": \"selected_images\",\n \"visible\": true,\n \"selected\": true\n },\n {\n \"route_key\": \"origin_manual_kind_manual_projection_A01_s001_w2_z001_t001_graph.graph.roi.zip_shapes\",\n \"title\": \"A01_s001_w2_z001_t001_graph.graph.roi.zip ROIs\",\n \"visible\": false,\n \"selected\": false\n }\n ],\n \"changed_route_count\": 3,\n \"layer_count\": 3,\n \"active_dimension_label_route\": \"origin_manual_kind_manual_projection_selected_images_e83ddc2185a63aca4b85ec471143f61c8f4eabdb08df3557ca21f2bddcda60b9\",\n \"current_step\": [\n 0,\n 1,\n 0,\n 0,\n 0,\n 15,\n 15\n ],\n \"axis_labels\": [\n \"site\",\n \"channel\",\n \"z_index\",\n \"timepoint\",\n \"well\",\n \"y\",\n \"x\"\n ],\n \"visible_layers\": [\n {\n \"route_key\": \"origin_manual_kind_manual_projection_selected_images_e83ddc2185a63aca4b85ec471143f61c8f4eabdb08df3557ca21f2bddcda60b9\",\n \"title\": \"selected_images\",\n \"visible\": true,\n \"selected\": true\n }\n ]\n}" + } + ], + "structuredContent": { + "connection": { + "host": "127.0.0.1", + "port": 6609, + "transport_mode": "tcp", + "persistent": true + }, + "schema_version": "openhcs.agent.v1", + "errors": [], + "warnings": [], + "observed": true, + "applied": true, + "selected_route_key": "origin_manual_kind_manual_projection_selected_images_e83ddc2185a63aca4b85ec471143f61c8f4eabdb08df3557ca21f2bddcda60b9", + "visible_route_keys": [ + "origin_manual_kind_manual_projection_selected_images_e83ddc2185a63aca4b85ec471143f61c8f4eabdb08df3557ca21f2bddcda60b9" + ], + "hidden_route_keys": [ + "origin_manual_kind_manual_projection_selected_images_8c7357d46ccc38823ca9e68096baf86f25c3004b61b63ba1eef9adea41d34fb8_scalar_stack", + "origin_manual_kind_manual_projection_A01_s001_w2_z001_t001_graph.graph.roi.zip_shapes" + ], + "missing_route_keys": [], + "available_layers": [ + { + "route_key": "origin_manual_kind_manual_projection_selected_images_8c7357d46ccc38823ca9e68096baf86f25c3004b61b63ba1eef9adea41d34fb8_scalar_stack", + "title": "selected_images image stack", + "visible": false, + "selected": false + }, + { + "route_key": "origin_manual_kind_manual_projection_selected_images_e83ddc2185a63aca4b85ec471143f61c8f4eabdb08df3557ca21f2bddcda60b9", + "title": "selected_images", + "visible": true, + "selected": true + }, + { + "route_key": "origin_manual_kind_manual_projection_A01_s001_w2_z001_t001_graph.graph.roi.zip_shapes", + "title": "A01_s001_w2_z001_t001_graph.graph.roi.zip ROIs", + "visible": false, + "selected": false + } + ], + "changed_route_count": 3, + "layer_count": 3, + "active_dimension_label_route": "origin_manual_kind_manual_projection_selected_images_e83ddc2185a63aca4b85ec471143f61c8f4eabdb08df3557ca21f2bddcda60b9", + "current_step": [ + 0, + 1, + 0, + 0, + 0, + 15, + 15 + ], + "axis_labels": [ + "site", + "channel", + "z_index", + "timepoint", + "well", + "y", + "x" + ], + "visible_layers": [ + { + "route_key": "origin_manual_kind_manual_projection_selected_images_e83ddc2185a63aca4b85ec471143f61c8f4eabdb08df3557ca21f2bddcda60b9", + "title": "selected_images", + "visible": true, + "selected": true + } + ] + }, + "isError": false + }, + "payload": { + "connection": { + "host": "127.0.0.1", + "port": 6609, + "transport_mode": "tcp", + "persistent": true + }, + "schema_version": "openhcs.agent.v1", + "errors": [], + "warnings": [], + "observed": true, + "applied": true, + "selected_route_key": "origin_manual_kind_manual_projection_selected_images_e83ddc2185a63aca4b85ec471143f61c8f4eabdb08df3557ca21f2bddcda60b9", + "visible_route_keys": [ + "origin_manual_kind_manual_projection_selected_images_e83ddc2185a63aca4b85ec471143f61c8f4eabdb08df3557ca21f2bddcda60b9" + ], + "hidden_route_keys": [ + "origin_manual_kind_manual_projection_selected_images_8c7357d46ccc38823ca9e68096baf86f25c3004b61b63ba1eef9adea41d34fb8_scalar_stack", + "origin_manual_kind_manual_projection_A01_s001_w2_z001_t001_graph.graph.roi.zip_shapes" + ], + "missing_route_keys": [], + "available_layers": [ + { + "route_key": "origin_manual_kind_manual_projection_selected_images_8c7357d46ccc38823ca9e68096baf86f25c3004b61b63ba1eef9adea41d34fb8_scalar_stack", + "title": "selected_images image stack", + "visible": false, + "selected": false + }, + { + "route_key": "origin_manual_kind_manual_projection_selected_images_e83ddc2185a63aca4b85ec471143f61c8f4eabdb08df3557ca21f2bddcda60b9", + "title": "selected_images", + "visible": true, + "selected": true + }, + { + "route_key": "origin_manual_kind_manual_projection_A01_s001_w2_z001_t001_graph.graph.roi.zip_shapes", + "title": "A01_s001_w2_z001_t001_graph.graph.roi.zip ROIs", + "visible": false, + "selected": false + } + ], + "changed_route_count": 3, + "layer_count": 3, + "active_dimension_label_route": "origin_manual_kind_manual_projection_selected_images_e83ddc2185a63aca4b85ec471143f61c8f4eabdb08df3557ca21f2bddcda60b9", + "current_step": [ + 0, + 1, + 0, + 0, + 0, + 15, + 15 + ], + "axis_labels": [ + "site", + "channel", + "z_index", + "timepoint", + "well", + "y", + "x" + ], + "visible_layers": [ + { + "route_key": "origin_manual_kind_manual_projection_selected_images_e83ddc2185a63aca4b85ec471143f61c8f4eabdb08df3557ca21f2bddcda60b9", + "title": "selected_images", + "visible": true, + "selected": true + } + ] + } + }, + { + "tool": "openhcs_set_viewer_viewport", + "arguments": { + "host": "127.0.0.1", + "port": 6609, + "transport_mode": "tcp", + "presentation": { + "center": [ + 0.0, + 21.011799999999997, + 21.011799999999997 + ], + "zoom": 6.635668707583358 + } + }, + "response": { + "content": [ + { + "type": "text", + "text": "{\n \"connection\": {\n \"host\": \"127.0.0.1\",\n \"port\": 6609,\n \"transport_mode\": \"tcp\",\n \"persistent\": true\n },\n \"schema_version\": \"openhcs.agent.v1\",\n \"errors\": [],\n \"warnings\": [],\n \"observed\": true,\n \"applied\": true,\n \"native_viewport\": {\n \"center\": [\n 0.0,\n 21.011799999999997,\n 21.011799999999997\n ],\n \"zoom\": 6.635668707583358\n }\n}" + } + ], + "structuredContent": { + "connection": { + "host": "127.0.0.1", + "port": 6609, + "transport_mode": "tcp", + "persistent": true + }, + "schema_version": "openhcs.agent.v1", + "errors": [], + "warnings": [], + "observed": true, + "applied": true, + "native_viewport": { + "center": [ + 0.0, + 21.011799999999997, + 21.011799999999997 + ], + "zoom": 6.635668707583358 + } + }, + "isError": false + }, + "payload": { + "connection": { + "host": "127.0.0.1", + "port": 6609, + "transport_mode": "tcp", + "persistent": true + }, + "schema_version": "openhcs.agent.v1", + "errors": [], + "warnings": [], + "observed": true, + "applied": true, + "native_viewport": { + "center": [ + 0.0, + 21.011799999999997, + 21.011799999999997 + ], + "zoom": 6.635668707583358 + } + } + }, + { + "tool": "openhcs_get_viewer_window_state", + "arguments": { + "host": "127.0.0.1", + "port": 6609, + "transport_mode": "tcp", + "route_key": null, + "include_component_values": true, + "max_component_values_per_layer": null, + "include_payload_summaries": true, + "max_payload_summaries_per_layer": null, + "include_response": true + }, + "response": { + "content": [ + { + "type": "text", + "text": "{\n \"connection\": {\n \"host\": \"127.0.0.1\",\n \"port\": 6609,\n \"transport_mode\": \"tcp\",\n \"persistent\": true\n },\n \"schema_version\": \"openhcs.agent.v1\",\n \"errors\": [],\n \"warnings\": [],\n \"observed\": true,\n \"viewer\": {\n \"viewer_type\": \"napari\",\n \"title\": \"OpenHCS Napari Visualization\"\n },\n \"layer_count\": 3,\n \"layers\": [\n {\n \"route_key\": \"origin_manual_kind_manual_projection_selected_images_8c7357d46ccc38823ca9e68096baf86f25c3004b61b63ba1eef9adea41d34fb8_scalar_stack\",\n \"title\": \"selected_images image stack\",\n \"mounted\": true,\n \"item_count\": 1,\n \"producer_identities\": [\n {\n \"origin\": \"manual\",\n \"output_kind\": \"manual\",\n \"output_key\": \"selected_images\",\n \"projection_key\": \"selected_images_8c7357d46ccc38823ca9e68096baf86f25c3004b61b63ba1eef9adea41d34fb8\",\n \"step_name\": null,\n \"pipeline_position\": null,\n \"step_scope_id\": null,\n \"invocation_key\": null,\n \"artifact_kind\": null\n }\n ],\n \"axis_labels\": [\n \"site\",\n \"channel\",\n \"z_index\",\n \"timepoint\",\n \"well\",\n \"y\",\n \"x\"\n ],\n \"stack_axes\": [\n \"channel\"\n ],\n \"pending_update\": false,\n \"data_types\": [\n \"image\"\n ],\n \"component_values\": [\n {\n \"site\": 1,\n \"z_index\": 1,\n \"timepoint\": 1,\n \"well\": \"A01\"\n }\n ],\n \"component_value_count\": 1,\n \"component_values_truncated\": false,\n \"payload_summaries\": [\n {\n \"shape\": [\n 2,\n 32,\n 32\n ],\n \"dtype\": \"uint16\",\n \"size\": 2048,\n \"nonzero_count\": 308,\n \"min\": 0,\n \"max\": 22,\n \"nonzero_min_coordinate\": [\n 0,\n 3,\n 4\n ],\n \"nonzero_max_coordinate\": [\n 1,\n 24,\n 27\n ],\n \"nonzero_example_coordinates\": [\n [\n 0,\n 3,\n 4\n ],\n [\n 0,\n 5,\n 4\n ],\n [\n 0,\n 7,\n 4\n ],\n [\n 0,\n 9,\n 5\n ],\n [\n 0,\n 11,\n 5\n ],\n [\n 0,\n 18,\n 24\n ],\n [\n 0,\n 21,\n 20\n ],\n [\n 0,\n 23,\n 25\n ],\n [\n 1,\n 3,\n 13\n ],\n [\n 1,\n 6,\n 4\n ],\n [\n 1,\n 8,\n 4\n ],\n [\n 1,\n 10,\n 5\n ],\n [\n 1,\n 17,\n 21\n ],\n [\n 1,\n 19,\n 26\n ],\n [\n 1,\n 22,\n 22\n ],\n [\n 1,\n 24,\n 27\n ]\n ],\n \"source_voxel_spacing\": {\n \"values_zyx\": [\n 1.3556,\n 1.3556\n ],\n \"unit\": \"micrometers\"\n },\n \"spatial_origin_yx\": [\n 0,\n 0\n ],\n \"source_spatial_shape_yx\": [\n 32,\n 32\n ],\n \"aggregate_component_values\": {\n \"channel\": [\n 2,\n 1\n ]\n },\n \"data_type\": \"image\",\n \"path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/stacked_labels/A01_s001_w2_z001_t001_Labels.tif\",\n \"components\": {\n \"site\": 1,\n \"z_index\": 1,\n \"timepoint\": 1,\n \"well\": \"A01\"\n },\n \"payload_type\": \"ndarray\"\n }\n ],\n \"payload_summary_count\": 1,\n \"payload_summaries_truncated\": false,\n \"axis_offsets\": [\n 0\n ],\n \"scalar_labels\": [\n \"Site 1\",\n \"Z 1\",\n \"T 1\",\n \"Well A01\"\n ],\n \"labels\": {\n \"channel\": [\n \"Ch 1\",\n \"Ch 2\"\n ]\n },\n \"axis_component_values\": {\n \"channel\": [\n 1,\n 2\n ]\n },\n \"routed_component_values\": {\n \"channel\": [\n 1,\n 2\n ]\n },\n \"routed_component_coordinates\": [\n [\n 1\n ],\n [\n 2\n ]\n ],\n \"data_shape\": [\n 1,\n 2,\n 1,\n 1,\n 1,\n 32,\n 32\n ],\n \"native_transform\": {\n \"scale\": [\n 1.0,\n 1.0,\n 1.0,\n 1.0,\n 1.0,\n 1.3556,\n 1.3556\n ],\n \"translate\": [\n 0.0,\n 0.0,\n 0.0,\n 0.0,\n 0.0,\n 0.0,\n 0.0\n ]\n },\n \"native_intensity\": {\n \"contrast_limits\": [\n 0.0,\n 22.0\n ],\n \"gamma\": 1.0\n },\n \"visible\": false,\n \"selected\": false,\n \"feature_row_count\": 0,\n \"selected_data_indices\": []\n },\n {\n \"route_key\": \"origin_manual_kind_manual_projection_selected_images_e83ddc2185a63aca4b85ec471143f61c8f4eabdb08df3557ca21f2bddcda60b9\",\n \"title\": \"selected_images\",\n \"mounted\": true,\n \"item_count\": 2,\n \"producer_identities\": [\n {\n \"origin\": \"manual\",\n \"output_kind\": \"manual\",\n \"output_key\": \"selected_images\",\n \"projection_key\": \"selected_images_e83ddc2185a63aca4b85ec471143f61c8f4eabdb08df3557ca21f2bddcda60b9\",\n \"step_name\": null,\n \"pipeline_position\": null,\n \"step_scope_id\": null,\n \"invocation_key\": null,\n \"artifact_kind\": null\n }\n ],\n \"axis_labels\": [\n \"site\",\n \"channel\",\n \"z_index\",\n \"timepoint\",\n \"well\",\n \"y\",\n \"x\"\n ],\n \"stack_axes\": [\n \"channel\"\n ],\n \"pending_update\": false,\n \"data_types\": [\n \"image\"\n ],\n \"component_values\": [\n {\n \"site\": 1,\n \"channel\": 1,\n \"z_index\": 1,\n \"timepoint\": 1,\n \"well\": \"A01\"\n },\n {\n \"site\": 1,\n \"channel\": 2,\n \"z_index\": 1,\n \"timepoint\": 1,\n \"well\": \"A01\"\n }\n ],\n \"component_value_count\": 2,\n \"component_values_truncated\": false,\n \"payload_summaries\": [\n {\n \"shape\": [\n 32,\n 32\n ],\n \"dtype\": \"uint16\",\n \"size\": 1024,\n \"nonzero_count\": 1024,\n \"min\": 100,\n \"max\": 1123,\n \"nonzero_min_coordinate\": [\n 0,\n 0\n ],\n \"nonzero_max_coordinate\": [\n 31,\n 31\n ],\n \"nonzero_example_coordinates\": [\n [\n 0,\n 0\n ],\n [\n 2,\n 4\n ],\n [\n 4,\n 8\n ],\n [\n 6,\n 12\n ],\n [\n 8,\n 16\n ],\n [\n 10,\n 21\n ],\n [\n 12,\n 25\n ],\n [\n 14,\n 29\n ],\n [\n 17,\n 1\n ],\n [\n 19,\n 5\n ],\n [\n 21,\n 10\n ],\n [\n 23,\n 14\n ],\n [\n 25,\n 18\n ],\n [\n 27,\n 22\n ],\n [\n 29,\n 26\n ],\n [\n 31,\n 31\n ]\n ],\n \"source_voxel_spacing\": {\n \"values_zyx\": [\n 1.3556,\n 1.3556\n ],\n \"unit\": \"micrometers\"\n },\n \"spatial_origin_yx\": [\n 0,\n 0\n ],\n \"source_spatial_shape_yx\": [\n 32,\n 32\n ],\n \"data_type\": \"image\",\n \"path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w1_z001_t001.tif\",\n \"components\": {\n \"site\": 1,\n \"channel\": 1,\n \"z_index\": 1,\n \"timepoint\": 1,\n \"well\": \"A01\"\n },\n \"payload_type\": \"ndarray\"\n },\n {\n \"shape\": [\n 32,\n 32\n ],\n \"dtype\": \"uint16\",\n \"size\": 1024,\n \"nonzero_count\": 1024,\n \"min\": 200,\n \"max\": 1223,\n \"nonzero_min_coordinate\": [\n 0,\n 0\n ],\n \"nonzero_max_coordinate\": [\n 31,\n 31\n ],\n \"nonzero_example_coordinates\": [\n [\n 0,\n 0\n ],\n [\n 2,\n 4\n ],\n [\n 4,\n 8\n ],\n [\n 6,\n 12\n ],\n [\n 8,\n 16\n ],\n [\n 10,\n 21\n ],\n [\n 12,\n 25\n ],\n [\n 14,\n 29\n ],\n [\n 17,\n 1\n ],\n [\n 19,\n 5\n ],\n [\n 21,\n 10\n ],\n [\n 23,\n 14\n ],\n [\n 25,\n 18\n ],\n [\n 27,\n 22\n ],\n [\n 29,\n 26\n ],\n [\n 31,\n 31\n ]\n ],\n \"source_voxel_spacing\": {\n \"values_zyx\": [\n 1.3556,\n 1.3556\n ],\n \"unit\": \"micrometers\"\n },\n \"spatial_origin_yx\": [\n 0,\n 0\n ],\n \"source_spatial_shape_yx\": [\n 32,\n 32\n ],\n \"data_type\": \"image\",\n \"path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w2_z001_t001.tif\",\n \"components\": {\n \"site\": 1,\n \"channel\": 2,\n \"z_index\": 1,\n \"timepoint\": 1,\n \"well\": \"A01\"\n },\n \"payload_type\": \"ndarray\"\n }\n ],\n \"payload_summary_count\": 2,\n \"payload_summaries_truncated\": false,\n \"axis_offsets\": [\n 0\n ],\n \"scalar_labels\": [\n \"Site 1\",\n \"Z 1\",\n \"T 1\",\n \"Well A01\"\n ],\n \"labels\": {\n \"channel\": [\n \"Ch 1\",\n \"Ch 2\"\n ]\n },\n \"axis_component_values\": {\n \"channel\": [\n 1,\n 2\n ]\n },\n \"routed_component_values\": {\n \"channel\": [\n 1,\n 2\n ]\n },\n \"routed_component_coordinates\": [\n [\n 1\n ],\n [\n 2\n ]\n ],\n \"data_shape\": [\n 1,\n 2,\n 1,\n 1,\n 1,\n 32,\n 32\n ],\n \"native_transform\": {\n \"scale\": [\n 1.0,\n 1.0,\n 1.0,\n 1.0,\n 1.0,\n 1.3556,\n 1.3556\n ],\n \"translate\": [\n 0.0,\n 0.0,\n 0.0,\n 0.0,\n 0.0,\n 0.0,\n 0.0\n ]\n },\n \"native_intensity\": {\n \"contrast_limits\": [\n 100.0,\n 1223.0\n ],\n \"gamma\": 1.0\n },\n \"visible\": true,\n \"selected\": true,\n \"feature_row_count\": 0,\n \"selected_data_indices\": []\n },\n {\n \"route_key\": \"origin_manual_kind_manual_projection_A01_s001_w2_z001_t001_graph.graph.roi.zip_shapes\",\n \"title\": \"A01_s001_w2_z001_t001_graph.graph.roi.zip ROIs\",\n \"mounted\": true,\n \"item_count\": 1,\n \"producer_identities\": [\n {\n \"origin\": \"manual\",\n \"output_kind\": \"manual\",\n \"output_key\": \"A01_s001_w2_z001_t001_graph.graph.roi.zip\",\n \"projection_key\": \"A01_s001_w2_z001_t001_graph.graph.roi.zip\",\n \"step_name\": null,\n \"pipeline_position\": null,\n \"step_scope_id\": null,\n \"invocation_key\": null,\n \"artifact_kind\": null\n }\n ],\n \"axis_labels\": [\n \"site\",\n \"channel\",\n \"z_index\",\n \"timepoint\",\n \"well\",\n \"y\",\n \"x\"\n ],\n \"stack_axes\": [\n \"channel\"\n ],\n \"pending_update\": false,\n \"data_types\": [\n \"shapes\"\n ],\n \"component_values\": [\n {\n \"site\": 1,\n \"channel\": 2,\n \"z_index\": 1,\n \"timepoint\": 1,\n \"well\": \"A01\"\n }\n ],\n \"component_value_count\": 1,\n \"component_values_truncated\": false,\n \"payload_summaries\": [\n {\n \"nonzero_count\": 2,\n \"item_count\": 2,\n \"shape_payload_count\": 2,\n \"missing_source_spatial_shape_count\": 2,\n \"shape_coordinate_count\": 4,\n \"shape_out_of_source_bounds_count\": 0,\n \"shape_coordinate_bounds_yx\": {\n \"min_yx\": [\n 2.25,\n 3.5\n ],\n \"max_yx\": [\n 7.25,\n 12.5\n ],\n \"coordinate_count\": 4\n },\n \"source_voxel_spacing\": {\n \"values_zyx\": [\n 1.3556,\n 1.3556\n ],\n \"unit\": \"micrometers\"\n },\n \"data_type\": \"shapes\",\n \"path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/graph_results/A01_s001_w2_z001_t001_graph.graph.roi.zip\",\n \"components\": {\n \"site\": 1,\n \"channel\": 2,\n \"z_index\": 1,\n \"timepoint\": 1,\n \"well\": \"A01\"\n },\n \"payload_type\": \"list\"\n }\n ],\n \"payload_summary_count\": 1,\n \"payload_summaries_truncated\": false,\n \"axis_offsets\": [\n 1\n ],\n \"scalar_labels\": [\n \"Site 1\",\n \"Z 1\",\n \"T 1\",\n \"Well A01\"\n ],\n \"labels\": {\n \"channel\": [\n \"Ch 2\"\n ]\n },\n \"axis_component_values\": {\n \"channel\": [\n 2\n ]\n },\n \"routed_component_values\": {\n \"channel\": [\n 2\n ]\n },\n \"routed_component_coordinates\": [\n [\n 2\n ]\n ],\n \"data_shape\": [\n 2\n ],\n \"native_transform\": {\n \"scale\": [\n 1.0,\n 1.0,\n 1.0,\n 1.0,\n 1.0,\n 1.3556,\n 1.3556\n ],\n \"translate\": [\n 0.0,\n 1.0,\n 0.0,\n 0.0,\n 0.0,\n 0.0,\n 0.0\n ]\n },\n \"native_intensity\": null,\n \"visible\": false,\n \"selected\": false,\n \"feature_row_count\": 2,\n \"selected_data_indices\": []\n }\n ],\n \"active_dimension_label_route\": \"origin_manual_kind_manual_projection_selected_images_e83ddc2185a63aca4b85ec471143f61c8f4eabdb08df3557ca21f2bddcda60b9\",\n \"viewer_ndim\": 7,\n \"current_step\": [\n 0,\n 1,\n 0,\n 0,\n 0,\n 15,\n 15\n ],\n \"axis_labels\": [\n \"site\",\n \"channel\",\n \"z_index\",\n \"timepoint\",\n \"well\",\n \"y\",\n \"x\"\n ],\n \"component_group_count\": 3,\n \"component_item_count\": 4,\n \"native_viewport\": {\n \"center\": [\n 0.0,\n 21.011799999999997,\n 21.011799999999997\n ],\n \"zoom\": 6.635668707583358\n },\n \"native_dimensions\": {\n \"order\": [\n 0,\n 1,\n 2,\n 3,\n 4,\n 5,\n 6\n ],\n \"ndisplay\": 2,\n \"displayed_axes\": [\n \"y\",\n \"x\"\n ],\n \"point\": [\n 0.0,\n 1.0,\n 0.0,\n 0.0,\n 0.0,\n 20.334,\n 20.334\n ],\n \"camera_angles\": [\n 0.0,\n 0.0,\n 0.0\n ],\n \"canvas_size\": [\n 643,\n 478\n ]\n },\n \"response\": {\n \"type\": \"state_ack\",\n \"status\": \"success\",\n \"viewer\": {\n \"type\": \"napari\",\n \"title\": \"OpenHCS Napari Visualization\"\n },\n \"layer_count\": 3,\n \"layers\": [\n {\n \"route_key\": \"origin_manual_kind_manual_projection_selected_images_8c7357d46ccc38823ca9e68096baf86f25c3004b61b63ba1eef9adea41d34fb8_scalar_stack\",\n \"producer_identities\": [\n {\n \"origin\": \"manual\",\n \"output_kind\": \"manual\",\n \"output_key\": \"selected_images\",\n \"projection_key\": \"selected_images_8c7357d46ccc38823ca9e68096baf86f25c3004b61b63ba1eef9adea41d34fb8\",\n \"step_name\": null,\n \"pipeline_position\": null,\n \"step_scope_id\": null,\n \"invocation_key\": null,\n \"artifact_kind\": null\n }\n ],\n \"title\": \"selected_images image stack\",\n \"mounted\": true,\n \"item_count\": 1,\n \"data_types\": [\n \"image\"\n ],\n \"component_values\": [\n {\n \"site\": 1,\n \"z_index\": 1,\n \"timepoint\": 1,\n \"well\": \"A01\"\n }\n ],\n \"component_value_count\": 1,\n \"component_values_truncated\": false,\n \"payload_summaries\": [\n {\n \"shape\": [\n 2,\n 32,\n 32\n ],\n \"dtype\": \"uint16\",\n \"size\": 2048,\n \"nonzero_count\": 308,\n \"min\": 0,\n \"max\": 22,\n \"nonzero_min_coordinate\": [\n 0,\n 3,\n 4\n ],\n \"nonzero_max_coordinate\": [\n 1,\n 24,\n 27\n ],\n \"nonzero_example_coordinates\": [\n [\n 0,\n 3,\n 4\n ],\n [\n 0,\n 5,\n 4\n ],\n [\n 0,\n 7,\n 4\n ],\n [\n 0,\n 9,\n 5\n ],\n [\n 0,\n 11,\n 5\n ],\n [\n 0,\n 18,\n 24\n ],\n [\n 0,\n 21,\n 20\n ],\n [\n 0,\n 23,\n 25\n ],\n [\n 1,\n 3,\n 13\n ],\n [\n 1,\n 6,\n 4\n ],\n [\n 1,\n 8,\n 4\n ],\n [\n 1,\n 10,\n 5\n ],\n [\n 1,\n 17,\n 21\n ],\n [\n 1,\n 19,\n 26\n ],\n [\n 1,\n 22,\n 22\n ],\n [\n 1,\n 24,\n 27\n ]\n ],\n \"source_voxel_spacing\": {\n \"values_zyx\": [\n 1.3556,\n 1.3556\n ],\n \"unit\": \"micrometers\"\n },\n \"spatial_origin_yx\": [\n 0,\n 0\n ],\n \"source_spatial_shape_yx\": [\n 32,\n 32\n ],\n \"aggregate_component_values\": {\n \"channel\": [\n 2,\n 1\n ]\n },\n \"data_type\": \"image\",\n \"path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/stacked_labels/A01_s001_w2_z001_t001_Labels.tif\",\n \"components\": {\n \"site\": 1,\n \"z_index\": 1,\n \"timepoint\": 1,\n \"well\": \"A01\"\n },\n \"payload_type\": \"ndarray\"\n }\n ],\n \"payload_summary_count\": 1,\n \"payload_summaries_truncated\": false,\n \"axis_labels\": [\n \"site\",\n \"channel\",\n \"z_index\",\n \"timepoint\",\n \"well\",\n \"y\",\n \"x\"\n ],\n \"stack_axes\": [\n \"channel\"\n ],\n \"axis_offsets\": [\n 0\n ],\n \"scalar_labels\": [\n \"Site 1\",\n \"Z 1\",\n \"T 1\",\n \"Well A01\"\n ],\n \"labels\": {\n \"channel\": [\n \"Ch 1\",\n \"Ch 2\"\n ]\n },\n \"axis_component_values\": {\n \"channel\": [\n 1,\n 2\n ]\n },\n \"routed_component_values\": {\n \"channel\": [\n 1,\n 2\n ]\n },\n \"routed_component_coordinates\": [\n [\n 1\n ],\n [\n 2\n ]\n ],\n \"data_shape\": [\n 1,\n 2,\n 1,\n 1,\n 1,\n 32,\n 32\n ],\n \"native_transform\": {\n \"scale\": [\n 1.0,\n 1.0,\n 1.0,\n 1.0,\n 1.0,\n 1.3556,\n 1.3556\n ],\n \"translate\": [\n 0.0,\n 0.0,\n 0.0,\n 0.0,\n 0.0,\n 0.0,\n 0.0\n ]\n },\n \"native_intensity\": {\n \"contrast_limits\": [\n 0.0,\n 22.0\n ],\n \"gamma\": 1.0\n },\n \"visible\": false,\n \"selected\": false,\n \"feature_row_count\": 0,\n \"selected_data_indices\": [],\n \"pending_update\": false\n },\n {\n \"route_key\": \"origin_manual_kind_manual_projection_selected_images_e83ddc2185a63aca4b85ec471143f61c8f4eabdb08df3557ca21f2bddcda60b9\",\n \"producer_identities\": [\n {\n \"origin\": \"manual\",\n \"output_kind\": \"manual\",\n \"output_key\": \"selected_images\",\n \"projection_key\": \"selected_images_e83ddc2185a63aca4b85ec471143f61c8f4eabdb08df3557ca21f2bddcda60b9\",\n \"step_name\": null,\n \"pipeline_position\": null,\n \"step_scope_id\": null,\n \"invocation_key\": null,\n \"artifact_kind\": null\n }\n ],\n \"title\": \"selected_images\",\n \"mounted\": true,\n \"item_count\": 2,\n \"data_types\": [\n \"image\"\n ],\n \"component_values\": [\n {\n \"site\": 1,\n \"channel\": 1,\n \"z_index\": 1,\n \"timepoint\": 1,\n \"well\": \"A01\"\n },\n {\n \"site\": 1,\n \"channel\": 2,\n \"z_index\": 1,\n \"timepoint\": 1,\n \"well\": \"A01\"\n }\n ],\n \"component_value_count\": 2,\n \"component_values_truncated\": false,\n \"payload_summaries\": [\n {\n \"shape\": [\n 32,\n 32\n ],\n \"dtype\": \"uint16\",\n \"size\": 1024,\n \"nonzero_count\": 1024,\n \"min\": 100,\n \"max\": 1123,\n \"nonzero_min_coordinate\": [\n 0,\n 0\n ],\n \"nonzero_max_coordinate\": [\n 31,\n 31\n ],\n \"nonzero_example_coordinates\": [\n [\n 0,\n 0\n ],\n [\n 2,\n 4\n ],\n [\n 4,\n 8\n ],\n [\n 6,\n 12\n ],\n [\n 8,\n 16\n ],\n [\n 10,\n 21\n ],\n [\n 12,\n 25\n ],\n [\n 14,\n 29\n ],\n [\n 17,\n 1\n ],\n [\n 19,\n 5\n ],\n [\n 21,\n 10\n ],\n [\n 23,\n 14\n ],\n [\n 25,\n 18\n ],\n [\n 27,\n 22\n ],\n [\n 29,\n 26\n ],\n [\n 31,\n 31\n ]\n ],\n \"source_voxel_spacing\": {\n \"values_zyx\": [\n 1.3556,\n 1.3556\n ],\n \"unit\": \"micrometers\"\n },\n \"spatial_origin_yx\": [\n 0,\n 0\n ],\n \"source_spatial_shape_yx\": [\n 32,\n 32\n ],\n \"data_type\": \"image\",\n \"path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w1_z001_t001.tif\",\n \"components\": {\n \"site\": 1,\n \"channel\": 1,\n \"z_index\": 1,\n \"timepoint\": 1,\n \"well\": \"A01\"\n },\n \"payload_type\": \"ndarray\"\n },\n {\n \"shape\": [\n 32,\n 32\n ],\n \"dtype\": \"uint16\",\n \"size\": 1024,\n \"nonzero_count\": 1024,\n \"min\": 200,\n \"max\": 1223,\n \"nonzero_min_coordinate\": [\n 0,\n 0\n ],\n \"nonzero_max_coordinate\": [\n 31,\n 31\n ],\n \"nonzero_example_coordinates\": [\n [\n 0,\n 0\n ],\n [\n 2,\n 4\n ],\n [\n 4,\n 8\n ],\n [\n 6,\n 12\n ],\n [\n 8,\n 16\n ],\n [\n 10,\n 21\n ],\n [\n 12,\n 25\n ],\n [\n 14,\n 29\n ],\n [\n 17,\n 1\n ],\n [\n 19,\n 5\n ],\n [\n 21,\n 10\n ],\n [\n 23,\n 14\n ],\n [\n 25,\n 18\n ],\n [\n 27,\n 22\n ],\n [\n 29,\n 26\n ],\n [\n 31,\n 31\n ]\n ],\n \"source_voxel_spacing\": {\n \"values_zyx\": [\n 1.3556,\n 1.3556\n ],\n \"unit\": \"micrometers\"\n },\n \"spatial_origin_yx\": [\n 0,\n 0\n ],\n \"source_spatial_shape_yx\": [\n 32,\n 32\n ],\n \"data_type\": \"image\",\n \"path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w2_z001_t001.tif\",\n \"components\": {\n \"site\": 1,\n \"channel\": 2,\n \"z_index\": 1,\n \"timepoint\": 1,\n \"well\": \"A01\"\n },\n \"payload_type\": \"ndarray\"\n }\n ],\n \"payload_summary_count\": 2,\n \"payload_summaries_truncated\": false,\n \"axis_labels\": [\n \"site\",\n \"channel\",\n \"z_index\",\n \"timepoint\",\n \"well\",\n \"y\",\n \"x\"\n ],\n \"stack_axes\": [\n \"channel\"\n ],\n \"axis_offsets\": [\n 0\n ],\n \"scalar_labels\": [\n \"Site 1\",\n \"Z 1\",\n \"T 1\",\n \"Well A01\"\n ],\n \"labels\": {\n \"channel\": [\n \"Ch 1\",\n \"Ch 2\"\n ]\n },\n \"axis_component_values\": {\n \"channel\": [\n 1,\n 2\n ]\n },\n \"routed_component_values\": {\n \"channel\": [\n 1,\n 2\n ]\n },\n \"routed_component_coordinates\": [\n [\n 1\n ],\n [\n 2\n ]\n ],\n \"data_shape\": [\n 1,\n 2,\n 1,\n 1,\n 1,\n 32,\n 32\n ],\n \"native_transform\": {\n \"scale\": [\n 1.0,\n 1.0,\n 1.0,\n 1.0,\n 1.0,\n 1.3556,\n 1.3556\n ],\n \"translate\": [\n 0.0,\n 0.0,\n 0.0,\n 0.0,\n 0.0,\n 0.0,\n 0.0\n ]\n },\n \"native_intensity\": {\n \"contrast_limits\": [\n 100.0,\n 1223.0\n ],\n \"gamma\": 1.0\n },\n \"visible\": true,\n \"selected\": true,\n \"feature_row_count\": 0,\n \"selected_data_indices\": [],\n \"pending_update\": false\n },\n {\n \"route_key\": \"origin_manual_kind_manual_projection_A01_s001_w2_z001_t001_graph.graph.roi.zip_shapes\",\n \"producer_identities\": [\n {\n \"origin\": \"manual\",\n \"output_kind\": \"manual\",\n \"output_key\": \"A01_s001_w2_z001_t001_graph.graph.roi.zip\",\n \"projection_key\": \"A01_s001_w2_z001_t001_graph.graph.roi.zip\",\n \"step_name\": null,\n \"pipeline_position\": null,\n \"step_scope_id\": null,\n \"invocation_key\": null,\n \"artifact_kind\": null\n }\n ],\n \"title\": \"A01_s001_w2_z001_t001_graph.graph.roi.zip ROIs\",\n \"mounted\": true,\n \"item_count\": 1,\n \"data_types\": [\n \"shapes\"\n ],\n \"component_values\": [\n {\n \"site\": 1,\n \"channel\": 2,\n \"z_index\": 1,\n \"timepoint\": 1,\n \"well\": \"A01\"\n }\n ],\n \"component_value_count\": 1,\n \"component_values_truncated\": false,\n \"payload_summaries\": [\n {\n \"nonzero_count\": 2,\n \"item_count\": 2,\n \"shape_payload_count\": 2,\n \"missing_source_spatial_shape_count\": 2,\n \"shape_coordinate_count\": 4,\n \"shape_out_of_source_bounds_count\": 0,\n \"shape_coordinate_bounds_yx\": {\n \"min_yx\": [\n 2.25,\n 3.5\n ],\n \"max_yx\": [\n 7.25,\n 12.5\n ],\n \"coordinate_count\": 4\n },\n \"source_voxel_spacing\": {\n \"values_zyx\": [\n 1.3556,\n 1.3556\n ],\n \"unit\": \"micrometers\"\n },\n \"data_type\": \"shapes\",\n \"path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/graph_results/A01_s001_w2_z001_t001_graph.graph.roi.zip\",\n \"components\": {\n \"site\": 1,\n \"channel\": 2,\n \"z_index\": 1,\n \"timepoint\": 1,\n \"well\": \"A01\"\n },\n \"payload_type\": \"list\"\n }\n ],\n \"payload_summary_count\": 1,\n \"payload_summaries_truncated\": false,\n \"axis_labels\": [\n \"site\",\n \"channel\",\n \"z_index\",\n \"timepoint\",\n \"well\",\n \"y\",\n \"x\"\n ],\n \"stack_axes\": [\n \"channel\"\n ],\n \"axis_offsets\": [\n 1\n ],\n \"scalar_labels\": [\n \"Site 1\",\n \"Z 1\",\n \"T 1\",\n \"Well A01\"\n ],\n \"labels\": {\n \"channel\": [\n \"Ch 2\"\n ]\n },\n \"axis_component_values\": {\n \"channel\": [\n 2\n ]\n },\n \"routed_component_values\": {\n \"channel\": [\n 2\n ]\n },\n \"routed_component_coordinates\": [\n [\n 2\n ]\n ],\n \"data_shape\": [\n 2\n ],\n \"native_transform\": {\n \"scale\": [\n 1.0,\n 1.0,\n 1.0,\n 1.0,\n 1.0,\n 1.3556,\n 1.3556\n ],\n \"translate\": [\n 0.0,\n 1.0,\n 0.0,\n 0.0,\n 0.0,\n 0.0,\n 0.0\n ]\n },\n \"native_intensity\": null,\n \"visible\": false,\n \"selected\": false,\n \"feature_row_count\": 2,\n \"selected_data_indices\": [],\n \"pending_update\": false\n }\n ],\n \"native_viewport\": {\n \"center\": [\n 0.0,\n 21.011799999999997,\n 21.011799999999997\n ],\n \"zoom\": 6.635668707583358\n },\n \"native_dimensions\": {\n \"order\": [\n 0,\n 1,\n 2,\n 3,\n 4,\n 5,\n 6\n ],\n \"ndisplay\": 2,\n \"displayed_axes\": [\n \"y\",\n \"x\"\n ],\n \"point\": [\n 0.0,\n 1.0,\n 0.0,\n 0.0,\n 0.0,\n 20.334,\n 20.334\n ],\n \"camera_angles\": [\n 0.0,\n 0.0,\n 0.0\n ],\n \"canvas_size\": [\n 643,\n 478\n ]\n },\n \"active_dimension_label_route\": \"origin_manual_kind_manual_projection_selected_images_e83ddc2185a63aca4b85ec471143f61c8f4eabdb08df3557ca21f2bddcda60b9\",\n \"viewer_ndim\": 7,\n \"current_step\": [\n 0,\n 1,\n 0,\n 0,\n 0,\n 15,\n 15\n ],\n \"axis_labels\": [\n \"site\",\n \"channel\",\n \"z_index\",\n \"timepoint\",\n \"well\",\n \"y\",\n \"x\"\n ],\n \"component_group_count\": 3,\n \"component_item_count\": 4\n }\n}" + } + ], + "structuredContent": { + "connection": { + "host": "127.0.0.1", + "port": 6609, + "transport_mode": "tcp", + "persistent": true + }, + "schema_version": "openhcs.agent.v1", + "errors": [], + "warnings": [], + "observed": true, + "viewer": { + "viewer_type": "napari", + "title": "OpenHCS Napari Visualization" + }, + "layer_count": 3, + "layers": [ + { + "route_key": "origin_manual_kind_manual_projection_selected_images_8c7357d46ccc38823ca9e68096baf86f25c3004b61b63ba1eef9adea41d34fb8_scalar_stack", + "title": "selected_images image stack", + "mounted": true, + "item_count": 1, + "producer_identities": [ + { + "origin": "manual", + "output_kind": "manual", + "output_key": "selected_images", + "projection_key": "selected_images_8c7357d46ccc38823ca9e68096baf86f25c3004b61b63ba1eef9adea41d34fb8", + "step_name": null, + "pipeline_position": null, + "step_scope_id": null, + "invocation_key": null, + "artifact_kind": null + } + ], + "axis_labels": [ + "site", + "channel", + "z_index", + "timepoint", + "well", + "y", + "x" + ], + "stack_axes": [ + "channel" + ], + "pending_update": false, + "data_types": [ + "image" + ], + "component_values": [ + { + "site": 1, + "z_index": 1, + "timepoint": 1, + "well": "A01" + } + ], + "component_value_count": 1, + "component_values_truncated": false, + "payload_summaries": [ + { + "shape": [ + 2, + 32, + 32 + ], + "dtype": "uint16", + "size": 2048, + "nonzero_count": 308, + "min": 0, + "max": 22, + "nonzero_min_coordinate": [ + 0, + 3, + 4 + ], + "nonzero_max_coordinate": [ + 1, + 24, + 27 + ], + "nonzero_example_coordinates": [ + [ + 0, + 3, + 4 + ], + [ + 0, + 5, + 4 + ], + [ + 0, + 7, + 4 + ], + [ + 0, + 9, + 5 + ], + [ + 0, + 11, + 5 + ], + [ + 0, + 18, + 24 + ], + [ + 0, + 21, + 20 + ], + [ + 0, + 23, + 25 + ], + [ + 1, + 3, + 13 + ], + [ + 1, + 6, + 4 + ], + [ + 1, + 8, + 4 + ], + [ + 1, + 10, + 5 + ], + [ + 1, + 17, + 21 + ], + [ + 1, + 19, + 26 + ], + [ + 1, + 22, + 22 + ], + [ + 1, + 24, + 27 + ] + ], + "source_voxel_spacing": { + "values_zyx": [ + 1.3556, + 1.3556 + ], + "unit": "micrometers" + }, + "spatial_origin_yx": [ + 0, + 0 + ], + "source_spatial_shape_yx": [ + 32, + 32 + ], + "aggregate_component_values": { + "channel": [ + 2, + 1 + ] + }, + "data_type": "image", + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/stacked_labels/A01_s001_w2_z001_t001_Labels.tif", + "components": { + "site": 1, + "z_index": 1, + "timepoint": 1, + "well": "A01" + }, + "payload_type": "ndarray" + } + ], + "payload_summary_count": 1, + "payload_summaries_truncated": false, + "axis_offsets": [ + 0 + ], + "scalar_labels": [ + "Site 1", + "Z 1", + "T 1", + "Well A01" + ], + "labels": { + "channel": [ + "Ch 1", + "Ch 2" + ] + }, + "axis_component_values": { + "channel": [ + 1, + 2 + ] + }, + "routed_component_values": { + "channel": [ + 1, + 2 + ] + }, + "routed_component_coordinates": [ + [ + 1 + ], + [ + 2 + ] + ], + "data_shape": [ + 1, + 2, + 1, + 1, + 1, + 32, + 32 + ], + "native_transform": { + "scale": [ + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.3556, + 1.3556 + ], + "translate": [ + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0 + ] + }, + "native_intensity": { + "contrast_limits": [ + 0.0, + 22.0 + ], + "gamma": 1.0 + }, + "visible": false, + "selected": false, + "feature_row_count": 0, + "selected_data_indices": [] + }, + { + "route_key": "origin_manual_kind_manual_projection_selected_images_e83ddc2185a63aca4b85ec471143f61c8f4eabdb08df3557ca21f2bddcda60b9", + "title": "selected_images", + "mounted": true, + "item_count": 2, + "producer_identities": [ + { + "origin": "manual", + "output_kind": "manual", + "output_key": "selected_images", + "projection_key": "selected_images_e83ddc2185a63aca4b85ec471143f61c8f4eabdb08df3557ca21f2bddcda60b9", + "step_name": null, + "pipeline_position": null, + "step_scope_id": null, + "invocation_key": null, + "artifact_kind": null + } + ], + "axis_labels": [ + "site", + "channel", + "z_index", + "timepoint", + "well", + "y", + "x" + ], + "stack_axes": [ + "channel" + ], + "pending_update": false, + "data_types": [ + "image" + ], + "component_values": [ + { + "site": 1, + "channel": 1, + "z_index": 1, + "timepoint": 1, + "well": "A01" + }, + { + "site": 1, + "channel": 2, + "z_index": 1, + "timepoint": 1, + "well": "A01" + } + ], + "component_value_count": 2, + "component_values_truncated": false, + "payload_summaries": [ + { + "shape": [ + 32, + 32 + ], + "dtype": "uint16", + "size": 1024, + "nonzero_count": 1024, + "min": 100, + "max": 1123, + "nonzero_min_coordinate": [ + 0, + 0 + ], + "nonzero_max_coordinate": [ + 31, + 31 + ], + "nonzero_example_coordinates": [ + [ + 0, + 0 + ], + [ + 2, + 4 + ], + [ + 4, + 8 + ], + [ + 6, + 12 + ], + [ + 8, + 16 + ], + [ + 10, + 21 + ], + [ + 12, + 25 + ], + [ + 14, + 29 + ], + [ + 17, + 1 + ], + [ + 19, + 5 + ], + [ + 21, + 10 + ], + [ + 23, + 14 + ], + [ + 25, + 18 + ], + [ + 27, + 22 + ], + [ + 29, + 26 + ], + [ + 31, + 31 + ] + ], + "source_voxel_spacing": { + "values_zyx": [ + 1.3556, + 1.3556 + ], + "unit": "micrometers" + }, + "spatial_origin_yx": [ + 0, + 0 + ], + "source_spatial_shape_yx": [ + 32, + 32 + ], + "data_type": "image", + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w1_z001_t001.tif", + "components": { + "site": 1, + "channel": 1, + "z_index": 1, + "timepoint": 1, + "well": "A01" + }, + "payload_type": "ndarray" + }, + { + "shape": [ + 32, + 32 + ], + "dtype": "uint16", + "size": 1024, + "nonzero_count": 1024, + "min": 200, + "max": 1223, + "nonzero_min_coordinate": [ + 0, + 0 + ], + "nonzero_max_coordinate": [ + 31, + 31 + ], + "nonzero_example_coordinates": [ + [ + 0, + 0 + ], + [ + 2, + 4 + ], + [ + 4, + 8 + ], + [ + 6, + 12 + ], + [ + 8, + 16 + ], + [ + 10, + 21 + ], + [ + 12, + 25 + ], + [ + 14, + 29 + ], + [ + 17, + 1 + ], + [ + 19, + 5 + ], + [ + 21, + 10 + ], + [ + 23, + 14 + ], + [ + 25, + 18 + ], + [ + 27, + 22 + ], + [ + 29, + 26 + ], + [ + 31, + 31 + ] + ], + "source_voxel_spacing": { + "values_zyx": [ + 1.3556, + 1.3556 + ], + "unit": "micrometers" + }, + "spatial_origin_yx": [ + 0, + 0 + ], + "source_spatial_shape_yx": [ + 32, + 32 + ], + "data_type": "image", + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w2_z001_t001.tif", + "components": { + "site": 1, + "channel": 2, + "z_index": 1, + "timepoint": 1, + "well": "A01" + }, + "payload_type": "ndarray" + } + ], + "payload_summary_count": 2, + "payload_summaries_truncated": false, + "axis_offsets": [ + 0 + ], + "scalar_labels": [ + "Site 1", + "Z 1", + "T 1", + "Well A01" + ], + "labels": { + "channel": [ + "Ch 1", + "Ch 2" + ] + }, + "axis_component_values": { + "channel": [ + 1, + 2 + ] + }, + "routed_component_values": { + "channel": [ + 1, + 2 + ] + }, + "routed_component_coordinates": [ + [ + 1 + ], + [ + 2 + ] + ], + "data_shape": [ + 1, + 2, + 1, + 1, + 1, + 32, + 32 + ], + "native_transform": { + "scale": [ + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.3556, + 1.3556 + ], + "translate": [ + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0 + ] + }, + "native_intensity": { + "contrast_limits": [ + 100.0, + 1223.0 + ], + "gamma": 1.0 + }, + "visible": true, + "selected": true, + "feature_row_count": 0, + "selected_data_indices": [] + }, + { + "route_key": "origin_manual_kind_manual_projection_A01_s001_w2_z001_t001_graph.graph.roi.zip_shapes", + "title": "A01_s001_w2_z001_t001_graph.graph.roi.zip ROIs", + "mounted": true, + "item_count": 1, + "producer_identities": [ + { + "origin": "manual", + "output_kind": "manual", + "output_key": "A01_s001_w2_z001_t001_graph.graph.roi.zip", + "projection_key": "A01_s001_w2_z001_t001_graph.graph.roi.zip", + "step_name": null, + "pipeline_position": null, + "step_scope_id": null, + "invocation_key": null, + "artifact_kind": null + } + ], + "axis_labels": [ + "site", + "channel", + "z_index", + "timepoint", + "well", + "y", + "x" + ], + "stack_axes": [ + "channel" + ], + "pending_update": false, + "data_types": [ + "shapes" + ], + "component_values": [ + { + "site": 1, + "channel": 2, + "z_index": 1, + "timepoint": 1, + "well": "A01" + } + ], + "component_value_count": 1, + "component_values_truncated": false, + "payload_summaries": [ + { + "nonzero_count": 2, + "item_count": 2, + "shape_payload_count": 2, + "missing_source_spatial_shape_count": 2, + "shape_coordinate_count": 4, + "shape_out_of_source_bounds_count": 0, + "shape_coordinate_bounds_yx": { + "min_yx": [ + 2.25, + 3.5 + ], + "max_yx": [ + 7.25, + 12.5 + ], + "coordinate_count": 4 + }, + "source_voxel_spacing": { + "values_zyx": [ + 1.3556, + 1.3556 + ], + "unit": "micrometers" + }, + "data_type": "shapes", + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/graph_results/A01_s001_w2_z001_t001_graph.graph.roi.zip", + "components": { + "site": 1, + "channel": 2, + "z_index": 1, + "timepoint": 1, + "well": "A01" + }, + "payload_type": "list" + } + ], + "payload_summary_count": 1, + "payload_summaries_truncated": false, + "axis_offsets": [ + 1 + ], + "scalar_labels": [ + "Site 1", + "Z 1", + "T 1", + "Well A01" + ], + "labels": { + "channel": [ + "Ch 2" + ] + }, + "axis_component_values": { + "channel": [ + 2 + ] + }, + "routed_component_values": { + "channel": [ + 2 + ] + }, + "routed_component_coordinates": [ + [ + 2 + ] + ], + "data_shape": [ + 2 + ], + "native_transform": { + "scale": [ + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.3556, + 1.3556 + ], + "translate": [ + 0.0, + 1.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0 + ] + }, + "native_intensity": null, + "visible": false, + "selected": false, + "feature_row_count": 2, + "selected_data_indices": [] + } + ], + "active_dimension_label_route": "origin_manual_kind_manual_projection_selected_images_e83ddc2185a63aca4b85ec471143f61c8f4eabdb08df3557ca21f2bddcda60b9", + "viewer_ndim": 7, + "current_step": [ + 0, + 1, + 0, + 0, + 0, + 15, + 15 + ], + "axis_labels": [ + "site", + "channel", + "z_index", + "timepoint", + "well", + "y", + "x" + ], + "component_group_count": 3, + "component_item_count": 4, + "native_viewport": { + "center": [ + 0.0, + 21.011799999999997, + 21.011799999999997 + ], + "zoom": 6.635668707583358 + }, + "native_dimensions": { + "order": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6 + ], + "ndisplay": 2, + "displayed_axes": [ + "y", + "x" + ], + "point": [ + 0.0, + 1.0, + 0.0, + 0.0, + 0.0, + 20.334, + 20.334 + ], + "camera_angles": [ + 0.0, + 0.0, + 0.0 + ], + "canvas_size": [ + 643, + 478 + ] + }, + "response": { + "type": "state_ack", + "status": "success", + "viewer": { + "type": "napari", + "title": "OpenHCS Napari Visualization" + }, + "layer_count": 3, + "layers": [ + { + "route_key": "origin_manual_kind_manual_projection_selected_images_8c7357d46ccc38823ca9e68096baf86f25c3004b61b63ba1eef9adea41d34fb8_scalar_stack", + "producer_identities": [ + { + "origin": "manual", + "output_kind": "manual", + "output_key": "selected_images", + "projection_key": "selected_images_8c7357d46ccc38823ca9e68096baf86f25c3004b61b63ba1eef9adea41d34fb8", + "step_name": null, + "pipeline_position": null, + "step_scope_id": null, + "invocation_key": null, + "artifact_kind": null + } + ], + "title": "selected_images image stack", + "mounted": true, + "item_count": 1, + "data_types": [ + "image" + ], + "component_values": [ + { + "site": 1, + "z_index": 1, + "timepoint": 1, + "well": "A01" + } + ], + "component_value_count": 1, + "component_values_truncated": false, + "payload_summaries": [ + { + "shape": [ + 2, + 32, + 32 + ], + "dtype": "uint16", + "size": 2048, + "nonzero_count": 308, + "min": 0, + "max": 22, + "nonzero_min_coordinate": [ + 0, + 3, + 4 + ], + "nonzero_max_coordinate": [ + 1, + 24, + 27 + ], + "nonzero_example_coordinates": [ + [ + 0, + 3, + 4 + ], + [ + 0, + 5, + 4 + ], + [ + 0, + 7, + 4 + ], + [ + 0, + 9, + 5 + ], + [ + 0, + 11, + 5 + ], + [ + 0, + 18, + 24 + ], + [ + 0, + 21, + 20 + ], + [ + 0, + 23, + 25 + ], + [ + 1, + 3, + 13 + ], + [ + 1, + 6, + 4 + ], + [ + 1, + 8, + 4 + ], + [ + 1, + 10, + 5 + ], + [ + 1, + 17, + 21 + ], + [ + 1, + 19, + 26 + ], + [ + 1, + 22, + 22 + ], + [ + 1, + 24, + 27 + ] + ], + "source_voxel_spacing": { + "values_zyx": [ + 1.3556, + 1.3556 + ], + "unit": "micrometers" + }, + "spatial_origin_yx": [ + 0, + 0 + ], + "source_spatial_shape_yx": [ + 32, + 32 + ], + "aggregate_component_values": { + "channel": [ + 2, + 1 + ] + }, + "data_type": "image", + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/stacked_labels/A01_s001_w2_z001_t001_Labels.tif", + "components": { + "site": 1, + "z_index": 1, + "timepoint": 1, + "well": "A01" + }, + "payload_type": "ndarray" + } + ], + "payload_summary_count": 1, + "payload_summaries_truncated": false, + "axis_labels": [ + "site", + "channel", + "z_index", + "timepoint", + "well", + "y", + "x" + ], + "stack_axes": [ + "channel" + ], + "axis_offsets": [ + 0 + ], + "scalar_labels": [ + "Site 1", + "Z 1", + "T 1", + "Well A01" + ], + "labels": { + "channel": [ + "Ch 1", + "Ch 2" + ] + }, + "axis_component_values": { + "channel": [ + 1, + 2 + ] + }, + "routed_component_values": { + "channel": [ + 1, + 2 + ] + }, + "routed_component_coordinates": [ + [ + 1 + ], + [ + 2 + ] + ], + "data_shape": [ + 1, + 2, + 1, + 1, + 1, + 32, + 32 + ], + "native_transform": { + "scale": [ + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.3556, + 1.3556 + ], + "translate": [ + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0 + ] + }, + "native_intensity": { + "contrast_limits": [ + 0.0, + 22.0 + ], + "gamma": 1.0 + }, + "visible": false, + "selected": false, + "feature_row_count": 0, + "selected_data_indices": [], + "pending_update": false + }, + { + "route_key": "origin_manual_kind_manual_projection_selected_images_e83ddc2185a63aca4b85ec471143f61c8f4eabdb08df3557ca21f2bddcda60b9", + "producer_identities": [ + { + "origin": "manual", + "output_kind": "manual", + "output_key": "selected_images", + "projection_key": "selected_images_e83ddc2185a63aca4b85ec471143f61c8f4eabdb08df3557ca21f2bddcda60b9", + "step_name": null, + "pipeline_position": null, + "step_scope_id": null, + "invocation_key": null, + "artifact_kind": null + } + ], + "title": "selected_images", + "mounted": true, + "item_count": 2, + "data_types": [ + "image" + ], + "component_values": [ + { + "site": 1, + "channel": 1, + "z_index": 1, + "timepoint": 1, + "well": "A01" + }, + { + "site": 1, + "channel": 2, + "z_index": 1, + "timepoint": 1, + "well": "A01" + } + ], + "component_value_count": 2, + "component_values_truncated": false, + "payload_summaries": [ + { + "shape": [ + 32, + 32 + ], + "dtype": "uint16", + "size": 1024, + "nonzero_count": 1024, + "min": 100, + "max": 1123, + "nonzero_min_coordinate": [ + 0, + 0 + ], + "nonzero_max_coordinate": [ + 31, + 31 + ], + "nonzero_example_coordinates": [ + [ + 0, + 0 + ], + [ + 2, + 4 + ], + [ + 4, + 8 + ], + [ + 6, + 12 + ], + [ + 8, + 16 + ], + [ + 10, + 21 + ], + [ + 12, + 25 + ], + [ + 14, + 29 + ], + [ + 17, + 1 + ], + [ + 19, + 5 + ], + [ + 21, + 10 + ], + [ + 23, + 14 + ], + [ + 25, + 18 + ], + [ + 27, + 22 + ], + [ + 29, + 26 + ], + [ + 31, + 31 + ] + ], + "source_voxel_spacing": { + "values_zyx": [ + 1.3556, + 1.3556 + ], + "unit": "micrometers" + }, + "spatial_origin_yx": [ + 0, + 0 + ], + "source_spatial_shape_yx": [ + 32, + 32 + ], + "data_type": "image", + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w1_z001_t001.tif", + "components": { + "site": 1, + "channel": 1, + "z_index": 1, + "timepoint": 1, + "well": "A01" + }, + "payload_type": "ndarray" + }, + { + "shape": [ + 32, + 32 + ], + "dtype": "uint16", + "size": 1024, + "nonzero_count": 1024, + "min": 200, + "max": 1223, + "nonzero_min_coordinate": [ + 0, + 0 + ], + "nonzero_max_coordinate": [ + 31, + 31 + ], + "nonzero_example_coordinates": [ + [ + 0, + 0 + ], + [ + 2, + 4 + ], + [ + 4, + 8 + ], + [ + 6, + 12 + ], + [ + 8, + 16 + ], + [ + 10, + 21 + ], + [ + 12, + 25 + ], + [ + 14, + 29 + ], + [ + 17, + 1 + ], + [ + 19, + 5 + ], + [ + 21, + 10 + ], + [ + 23, + 14 + ], + [ + 25, + 18 + ], + [ + 27, + 22 + ], + [ + 29, + 26 + ], + [ + 31, + 31 + ] + ], + "source_voxel_spacing": { + "values_zyx": [ + 1.3556, + 1.3556 + ], + "unit": "micrometers" + }, + "spatial_origin_yx": [ + 0, + 0 + ], + "source_spatial_shape_yx": [ + 32, + 32 + ], + "data_type": "image", + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w2_z001_t001.tif", + "components": { + "site": 1, + "channel": 2, + "z_index": 1, + "timepoint": 1, + "well": "A01" + }, + "payload_type": "ndarray" + } + ], + "payload_summary_count": 2, + "payload_summaries_truncated": false, + "axis_labels": [ + "site", + "channel", + "z_index", + "timepoint", + "well", + "y", + "x" + ], + "stack_axes": [ + "channel" + ], + "axis_offsets": [ + 0 + ], + "scalar_labels": [ + "Site 1", + "Z 1", + "T 1", + "Well A01" + ], + "labels": { + "channel": [ + "Ch 1", + "Ch 2" + ] + }, + "axis_component_values": { + "channel": [ + 1, + 2 + ] + }, + "routed_component_values": { + "channel": [ + 1, + 2 + ] + }, + "routed_component_coordinates": [ + [ + 1 + ], + [ + 2 + ] + ], + "data_shape": [ + 1, + 2, + 1, + 1, + 1, + 32, + 32 + ], + "native_transform": { + "scale": [ + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.3556, + 1.3556 + ], + "translate": [ + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0 + ] + }, + "native_intensity": { + "contrast_limits": [ + 100.0, + 1223.0 + ], + "gamma": 1.0 + }, + "visible": true, + "selected": true, + "feature_row_count": 0, + "selected_data_indices": [], + "pending_update": false + }, + { + "route_key": "origin_manual_kind_manual_projection_A01_s001_w2_z001_t001_graph.graph.roi.zip_shapes", + "producer_identities": [ + { + "origin": "manual", + "output_kind": "manual", + "output_key": "A01_s001_w2_z001_t001_graph.graph.roi.zip", + "projection_key": "A01_s001_w2_z001_t001_graph.graph.roi.zip", + "step_name": null, + "pipeline_position": null, + "step_scope_id": null, + "invocation_key": null, + "artifact_kind": null + } + ], + "title": "A01_s001_w2_z001_t001_graph.graph.roi.zip ROIs", + "mounted": true, + "item_count": 1, + "data_types": [ + "shapes" + ], + "component_values": [ + { + "site": 1, + "channel": 2, + "z_index": 1, + "timepoint": 1, + "well": "A01" + } + ], + "component_value_count": 1, + "component_values_truncated": false, + "payload_summaries": [ + { + "nonzero_count": 2, + "item_count": 2, + "shape_payload_count": 2, + "missing_source_spatial_shape_count": 2, + "shape_coordinate_count": 4, + "shape_out_of_source_bounds_count": 0, + "shape_coordinate_bounds_yx": { + "min_yx": [ + 2.25, + 3.5 + ], + "max_yx": [ + 7.25, + 12.5 + ], + "coordinate_count": 4 + }, + "source_voxel_spacing": { + "values_zyx": [ + 1.3556, + 1.3556 + ], + "unit": "micrometers" + }, + "data_type": "shapes", + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/graph_results/A01_s001_w2_z001_t001_graph.graph.roi.zip", + "components": { + "site": 1, + "channel": 2, + "z_index": 1, + "timepoint": 1, + "well": "A01" + }, + "payload_type": "list" + } + ], + "payload_summary_count": 1, + "payload_summaries_truncated": false, + "axis_labels": [ + "site", + "channel", + "z_index", + "timepoint", + "well", + "y", + "x" + ], + "stack_axes": [ + "channel" + ], + "axis_offsets": [ + 1 + ], + "scalar_labels": [ + "Site 1", + "Z 1", + "T 1", + "Well A01" + ], + "labels": { + "channel": [ + "Ch 2" + ] + }, + "axis_component_values": { + "channel": [ + 2 + ] + }, + "routed_component_values": { + "channel": [ + 2 + ] + }, + "routed_component_coordinates": [ + [ + 2 + ] + ], + "data_shape": [ + 2 + ], + "native_transform": { + "scale": [ + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.3556, + 1.3556 + ], + "translate": [ + 0.0, + 1.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0 + ] + }, + "native_intensity": null, + "visible": false, + "selected": false, + "feature_row_count": 2, + "selected_data_indices": [], + "pending_update": false + } + ], + "native_viewport": { + "center": [ + 0.0, + 21.011799999999997, + 21.011799999999997 + ], + "zoom": 6.635668707583358 + }, + "native_dimensions": { + "order": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6 + ], + "ndisplay": 2, + "displayed_axes": [ + "y", + "x" + ], + "point": [ + 0.0, + 1.0, + 0.0, + 0.0, + 0.0, + 20.334, + 20.334 + ], + "camera_angles": [ + 0.0, + 0.0, + 0.0 + ], + "canvas_size": [ + 643, + 478 + ] + }, + "active_dimension_label_route": "origin_manual_kind_manual_projection_selected_images_e83ddc2185a63aca4b85ec471143f61c8f4eabdb08df3557ca21f2bddcda60b9", + "viewer_ndim": 7, + "current_step": [ + 0, + 1, + 0, + 0, + 0, + 15, + 15 + ], + "axis_labels": [ + "site", + "channel", + "z_index", + "timepoint", + "well", + "y", + "x" + ], + "component_group_count": 3, + "component_item_count": 4 + } + }, + "isError": false + }, + "payload": { + "connection": { + "host": "127.0.0.1", + "port": 6609, + "transport_mode": "tcp", + "persistent": true + }, + "schema_version": "openhcs.agent.v1", + "errors": [], + "warnings": [], + "observed": true, + "viewer": { + "viewer_type": "napari", + "title": "OpenHCS Napari Visualization" + }, + "layer_count": 3, + "layers": [ + { + "route_key": "origin_manual_kind_manual_projection_selected_images_8c7357d46ccc38823ca9e68096baf86f25c3004b61b63ba1eef9adea41d34fb8_scalar_stack", + "title": "selected_images image stack", + "mounted": true, + "item_count": 1, + "producer_identities": [ + { + "origin": "manual", + "output_kind": "manual", + "output_key": "selected_images", + "projection_key": "selected_images_8c7357d46ccc38823ca9e68096baf86f25c3004b61b63ba1eef9adea41d34fb8", + "step_name": null, + "pipeline_position": null, + "step_scope_id": null, + "invocation_key": null, + "artifact_kind": null + } + ], + "axis_labels": [ + "site", + "channel", + "z_index", + "timepoint", + "well", + "y", + "x" + ], + "stack_axes": [ + "channel" + ], + "pending_update": false, + "data_types": [ + "image" + ], + "component_values": [ + { + "site": 1, + "z_index": 1, + "timepoint": 1, + "well": "A01" + } + ], + "component_value_count": 1, + "component_values_truncated": false, + "payload_summaries": [ + { + "shape": [ + 2, + 32, + 32 + ], + "dtype": "uint16", + "size": 2048, + "nonzero_count": 308, + "min": 0, + "max": 22, + "nonzero_min_coordinate": [ + 0, + 3, + 4 + ], + "nonzero_max_coordinate": [ + 1, + 24, + 27 + ], + "nonzero_example_coordinates": [ + [ + 0, + 3, + 4 + ], + [ + 0, + 5, + 4 + ], + [ + 0, + 7, + 4 + ], + [ + 0, + 9, + 5 + ], + [ + 0, + 11, + 5 + ], + [ + 0, + 18, + 24 + ], + [ + 0, + 21, + 20 + ], + [ + 0, + 23, + 25 + ], + [ + 1, + 3, + 13 + ], + [ + 1, + 6, + 4 + ], + [ + 1, + 8, + 4 + ], + [ + 1, + 10, + 5 + ], + [ + 1, + 17, + 21 + ], + [ + 1, + 19, + 26 + ], + [ + 1, + 22, + 22 + ], + [ + 1, + 24, + 27 + ] + ], + "source_voxel_spacing": { + "values_zyx": [ + 1.3556, + 1.3556 + ], + "unit": "micrometers" + }, + "spatial_origin_yx": [ + 0, + 0 + ], + "source_spatial_shape_yx": [ + 32, + 32 + ], + "aggregate_component_values": { + "channel": [ + 2, + 1 + ] + }, + "data_type": "image", + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/stacked_labels/A01_s001_w2_z001_t001_Labels.tif", + "components": { + "site": 1, + "z_index": 1, + "timepoint": 1, + "well": "A01" + }, + "payload_type": "ndarray" + } + ], + "payload_summary_count": 1, + "payload_summaries_truncated": false, + "axis_offsets": [ + 0 + ], + "scalar_labels": [ + "Site 1", + "Z 1", + "T 1", + "Well A01" + ], + "labels": { + "channel": [ + "Ch 1", + "Ch 2" + ] + }, + "axis_component_values": { + "channel": [ + 1, + 2 + ] + }, + "routed_component_values": { + "channel": [ + 1, + 2 + ] + }, + "routed_component_coordinates": [ + [ + 1 + ], + [ + 2 + ] + ], + "data_shape": [ + 1, + 2, + 1, + 1, + 1, + 32, + 32 + ], + "native_transform": { + "scale": [ + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.3556, + 1.3556 + ], + "translate": [ + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0 + ] + }, + "native_intensity": { + "contrast_limits": [ + 0.0, + 22.0 + ], + "gamma": 1.0 + }, + "visible": false, + "selected": false, + "feature_row_count": 0, + "selected_data_indices": [] + }, + { + "route_key": "origin_manual_kind_manual_projection_selected_images_e83ddc2185a63aca4b85ec471143f61c8f4eabdb08df3557ca21f2bddcda60b9", + "title": "selected_images", + "mounted": true, + "item_count": 2, + "producer_identities": [ + { + "origin": "manual", + "output_kind": "manual", + "output_key": "selected_images", + "projection_key": "selected_images_e83ddc2185a63aca4b85ec471143f61c8f4eabdb08df3557ca21f2bddcda60b9", + "step_name": null, + "pipeline_position": null, + "step_scope_id": null, + "invocation_key": null, + "artifact_kind": null + } + ], + "axis_labels": [ + "site", + "channel", + "z_index", + "timepoint", + "well", + "y", + "x" + ], + "stack_axes": [ + "channel" + ], + "pending_update": false, + "data_types": [ + "image" + ], + "component_values": [ + { + "site": 1, + "channel": 1, + "z_index": 1, + "timepoint": 1, + "well": "A01" + }, + { + "site": 1, + "channel": 2, + "z_index": 1, + "timepoint": 1, + "well": "A01" + } + ], + "component_value_count": 2, + "component_values_truncated": false, + "payload_summaries": [ + { + "shape": [ + 32, + 32 + ], + "dtype": "uint16", + "size": 1024, + "nonzero_count": 1024, + "min": 100, + "max": 1123, + "nonzero_min_coordinate": [ + 0, + 0 + ], + "nonzero_max_coordinate": [ + 31, + 31 + ], + "nonzero_example_coordinates": [ + [ + 0, + 0 + ], + [ + 2, + 4 + ], + [ + 4, + 8 + ], + [ + 6, + 12 + ], + [ + 8, + 16 + ], + [ + 10, + 21 + ], + [ + 12, + 25 + ], + [ + 14, + 29 + ], + [ + 17, + 1 + ], + [ + 19, + 5 + ], + [ + 21, + 10 + ], + [ + 23, + 14 + ], + [ + 25, + 18 + ], + [ + 27, + 22 + ], + [ + 29, + 26 + ], + [ + 31, + 31 + ] + ], + "source_voxel_spacing": { + "values_zyx": [ + 1.3556, + 1.3556 + ], + "unit": "micrometers" + }, + "spatial_origin_yx": [ + 0, + 0 + ], + "source_spatial_shape_yx": [ + 32, + 32 + ], + "data_type": "image", + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w1_z001_t001.tif", + "components": { + "site": 1, + "channel": 1, + "z_index": 1, + "timepoint": 1, + "well": "A01" + }, + "payload_type": "ndarray" + }, + { + "shape": [ + 32, + 32 + ], + "dtype": "uint16", + "size": 1024, + "nonzero_count": 1024, + "min": 200, + "max": 1223, + "nonzero_min_coordinate": [ + 0, + 0 + ], + "nonzero_max_coordinate": [ + 31, + 31 + ], + "nonzero_example_coordinates": [ + [ + 0, + 0 + ], + [ + 2, + 4 + ], + [ + 4, + 8 + ], + [ + 6, + 12 + ], + [ + 8, + 16 + ], + [ + 10, + 21 + ], + [ + 12, + 25 + ], + [ + 14, + 29 + ], + [ + 17, + 1 + ], + [ + 19, + 5 + ], + [ + 21, + 10 + ], + [ + 23, + 14 + ], + [ + 25, + 18 + ], + [ + 27, + 22 + ], + [ + 29, + 26 + ], + [ + 31, + 31 + ] + ], + "source_voxel_spacing": { + "values_zyx": [ + 1.3556, + 1.3556 + ], + "unit": "micrometers" + }, + "spatial_origin_yx": [ + 0, + 0 + ], + "source_spatial_shape_yx": [ + 32, + 32 + ], + "data_type": "image", + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w2_z001_t001.tif", + "components": { + "site": 1, + "channel": 2, + "z_index": 1, + "timepoint": 1, + "well": "A01" + }, + "payload_type": "ndarray" + } + ], + "payload_summary_count": 2, + "payload_summaries_truncated": false, + "axis_offsets": [ + 0 + ], + "scalar_labels": [ + "Site 1", + "Z 1", + "T 1", + "Well A01" + ], + "labels": { + "channel": [ + "Ch 1", + "Ch 2" + ] + }, + "axis_component_values": { + "channel": [ + 1, + 2 + ] + }, + "routed_component_values": { + "channel": [ + 1, + 2 + ] + }, + "routed_component_coordinates": [ + [ + 1 + ], + [ + 2 + ] + ], + "data_shape": [ + 1, + 2, + 1, + 1, + 1, + 32, + 32 + ], + "native_transform": { + "scale": [ + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.3556, + 1.3556 + ], + "translate": [ + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0 + ] + }, + "native_intensity": { + "contrast_limits": [ + 100.0, + 1223.0 + ], + "gamma": 1.0 + }, + "visible": true, + "selected": true, + "feature_row_count": 0, + "selected_data_indices": [] + }, + { + "route_key": "origin_manual_kind_manual_projection_A01_s001_w2_z001_t001_graph.graph.roi.zip_shapes", + "title": "A01_s001_w2_z001_t001_graph.graph.roi.zip ROIs", + "mounted": true, + "item_count": 1, + "producer_identities": [ + { + "origin": "manual", + "output_kind": "manual", + "output_key": "A01_s001_w2_z001_t001_graph.graph.roi.zip", + "projection_key": "A01_s001_w2_z001_t001_graph.graph.roi.zip", + "step_name": null, + "pipeline_position": null, + "step_scope_id": null, + "invocation_key": null, + "artifact_kind": null + } + ], + "axis_labels": [ + "site", + "channel", + "z_index", + "timepoint", + "well", + "y", + "x" + ], + "stack_axes": [ + "channel" + ], + "pending_update": false, + "data_types": [ + "shapes" + ], + "component_values": [ + { + "site": 1, + "channel": 2, + "z_index": 1, + "timepoint": 1, + "well": "A01" + } + ], + "component_value_count": 1, + "component_values_truncated": false, + "payload_summaries": [ + { + "nonzero_count": 2, + "item_count": 2, + "shape_payload_count": 2, + "missing_source_spatial_shape_count": 2, + "shape_coordinate_count": 4, + "shape_out_of_source_bounds_count": 0, + "shape_coordinate_bounds_yx": { + "min_yx": [ + 2.25, + 3.5 + ], + "max_yx": [ + 7.25, + 12.5 + ], + "coordinate_count": 4 + }, + "source_voxel_spacing": { + "values_zyx": [ + 1.3556, + 1.3556 + ], + "unit": "micrometers" + }, + "data_type": "shapes", + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/graph_results/A01_s001_w2_z001_t001_graph.graph.roi.zip", + "components": { + "site": 1, + "channel": 2, + "z_index": 1, + "timepoint": 1, + "well": "A01" + }, + "payload_type": "list" + } + ], + "payload_summary_count": 1, + "payload_summaries_truncated": false, + "axis_offsets": [ + 1 + ], + "scalar_labels": [ + "Site 1", + "Z 1", + "T 1", + "Well A01" + ], + "labels": { + "channel": [ + "Ch 2" + ] + }, + "axis_component_values": { + "channel": [ + 2 + ] + }, + "routed_component_values": { + "channel": [ + 2 + ] + }, + "routed_component_coordinates": [ + [ + 2 + ] + ], + "data_shape": [ + 2 + ], + "native_transform": { + "scale": [ + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.3556, + 1.3556 + ], + "translate": [ + 0.0, + 1.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0 + ] + }, + "native_intensity": null, + "visible": false, + "selected": false, + "feature_row_count": 2, + "selected_data_indices": [] + } + ], + "active_dimension_label_route": "origin_manual_kind_manual_projection_selected_images_e83ddc2185a63aca4b85ec471143f61c8f4eabdb08df3557ca21f2bddcda60b9", + "viewer_ndim": 7, + "current_step": [ + 0, + 1, + 0, + 0, + 0, + 15, + 15 + ], + "axis_labels": [ + "site", + "channel", + "z_index", + "timepoint", + "well", + "y", + "x" + ], + "component_group_count": 3, + "component_item_count": 4, + "native_viewport": { + "center": [ + 0.0, + 21.011799999999997, + 21.011799999999997 + ], + "zoom": 6.635668707583358 + }, + "native_dimensions": { + "order": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6 + ], + "ndisplay": 2, + "displayed_axes": [ + "y", + "x" + ], + "point": [ + 0.0, + 1.0, + 0.0, + 0.0, + 0.0, + 20.334, + 20.334 + ], + "camera_angles": [ + 0.0, + 0.0, + 0.0 + ], + "canvas_size": [ + 643, + 478 + ] + }, + "response": { + "type": "state_ack", + "status": "success", + "viewer": { + "type": "napari", + "title": "OpenHCS Napari Visualization" + }, + "layer_count": 3, + "layers": [ + { + "route_key": "origin_manual_kind_manual_projection_selected_images_8c7357d46ccc38823ca9e68096baf86f25c3004b61b63ba1eef9adea41d34fb8_scalar_stack", + "producer_identities": [ + { + "origin": "manual", + "output_kind": "manual", + "output_key": "selected_images", + "projection_key": "selected_images_8c7357d46ccc38823ca9e68096baf86f25c3004b61b63ba1eef9adea41d34fb8", + "step_name": null, + "pipeline_position": null, + "step_scope_id": null, + "invocation_key": null, + "artifact_kind": null + } + ], + "title": "selected_images image stack", + "mounted": true, + "item_count": 1, + "data_types": [ + "image" + ], + "component_values": [ + { + "site": 1, + "z_index": 1, + "timepoint": 1, + "well": "A01" + } + ], + "component_value_count": 1, + "component_values_truncated": false, + "payload_summaries": [ + { + "shape": [ + 2, + 32, + 32 + ], + "dtype": "uint16", + "size": 2048, + "nonzero_count": 308, + "min": 0, + "max": 22, + "nonzero_min_coordinate": [ + 0, + 3, + 4 + ], + "nonzero_max_coordinate": [ + 1, + 24, + 27 + ], + "nonzero_example_coordinates": [ + [ + 0, + 3, + 4 + ], + [ + 0, + 5, + 4 + ], + [ + 0, + 7, + 4 + ], + [ + 0, + 9, + 5 + ], + [ + 0, + 11, + 5 + ], + [ + 0, + 18, + 24 + ], + [ + 0, + 21, + 20 + ], + [ + 0, + 23, + 25 + ], + [ + 1, + 3, + 13 + ], + [ + 1, + 6, + 4 + ], + [ + 1, + 8, + 4 + ], + [ + 1, + 10, + 5 + ], + [ + 1, + 17, + 21 + ], + [ + 1, + 19, + 26 + ], + [ + 1, + 22, + 22 + ], + [ + 1, + 24, + 27 + ] + ], + "source_voxel_spacing": { + "values_zyx": [ + 1.3556, + 1.3556 + ], + "unit": "micrometers" + }, + "spatial_origin_yx": [ + 0, + 0 + ], + "source_spatial_shape_yx": [ + 32, + 32 + ], + "aggregate_component_values": { + "channel": [ + 2, + 1 + ] + }, + "data_type": "image", + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/stacked_labels/A01_s001_w2_z001_t001_Labels.tif", + "components": { + "site": 1, + "z_index": 1, + "timepoint": 1, + "well": "A01" + }, + "payload_type": "ndarray" + } + ], + "payload_summary_count": 1, + "payload_summaries_truncated": false, + "axis_labels": [ + "site", + "channel", + "z_index", + "timepoint", + "well", + "y", + "x" + ], + "stack_axes": [ + "channel" + ], + "axis_offsets": [ + 0 + ], + "scalar_labels": [ + "Site 1", + "Z 1", + "T 1", + "Well A01" + ], + "labels": { + "channel": [ + "Ch 1", + "Ch 2" + ] + }, + "axis_component_values": { + "channel": [ + 1, + 2 + ] + }, + "routed_component_values": { + "channel": [ + 1, + 2 + ] + }, + "routed_component_coordinates": [ + [ + 1 + ], + [ + 2 + ] + ], + "data_shape": [ + 1, + 2, + 1, + 1, + 1, + 32, + 32 + ], + "native_transform": { + "scale": [ + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.3556, + 1.3556 + ], + "translate": [ + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0 + ] + }, + "native_intensity": { + "contrast_limits": [ + 0.0, + 22.0 + ], + "gamma": 1.0 + }, + "visible": false, + "selected": false, + "feature_row_count": 0, + "selected_data_indices": [], + "pending_update": false + }, + { + "route_key": "origin_manual_kind_manual_projection_selected_images_e83ddc2185a63aca4b85ec471143f61c8f4eabdb08df3557ca21f2bddcda60b9", + "producer_identities": [ + { + "origin": "manual", + "output_kind": "manual", + "output_key": "selected_images", + "projection_key": "selected_images_e83ddc2185a63aca4b85ec471143f61c8f4eabdb08df3557ca21f2bddcda60b9", + "step_name": null, + "pipeline_position": null, + "step_scope_id": null, + "invocation_key": null, + "artifact_kind": null + } + ], + "title": "selected_images", + "mounted": true, + "item_count": 2, + "data_types": [ + "image" + ], + "component_values": [ + { + "site": 1, + "channel": 1, + "z_index": 1, + "timepoint": 1, + "well": "A01" + }, + { + "site": 1, + "channel": 2, + "z_index": 1, + "timepoint": 1, + "well": "A01" + } + ], + "component_value_count": 2, + "component_values_truncated": false, + "payload_summaries": [ + { + "shape": [ + 32, + 32 + ], + "dtype": "uint16", + "size": 1024, + "nonzero_count": 1024, + "min": 100, + "max": 1123, + "nonzero_min_coordinate": [ + 0, + 0 + ], + "nonzero_max_coordinate": [ + 31, + 31 + ], + "nonzero_example_coordinates": [ + [ + 0, + 0 + ], + [ + 2, + 4 + ], + [ + 4, + 8 + ], + [ + 6, + 12 + ], + [ + 8, + 16 + ], + [ + 10, + 21 + ], + [ + 12, + 25 + ], + [ + 14, + 29 + ], + [ + 17, + 1 + ], + [ + 19, + 5 + ], + [ + 21, + 10 + ], + [ + 23, + 14 + ], + [ + 25, + 18 + ], + [ + 27, + 22 + ], + [ + 29, + 26 + ], + [ + 31, + 31 + ] + ], + "source_voxel_spacing": { + "values_zyx": [ + 1.3556, + 1.3556 + ], + "unit": "micrometers" + }, + "spatial_origin_yx": [ + 0, + 0 + ], + "source_spatial_shape_yx": [ + 32, + 32 + ], + "data_type": "image", + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w1_z001_t001.tif", + "components": { + "site": 1, + "channel": 1, + "z_index": 1, + "timepoint": 1, + "well": "A01" + }, + "payload_type": "ndarray" + }, + { + "shape": [ + 32, + 32 + ], + "dtype": "uint16", + "size": 1024, + "nonzero_count": 1024, + "min": 200, + "max": 1223, + "nonzero_min_coordinate": [ + 0, + 0 + ], + "nonzero_max_coordinate": [ + 31, + 31 + ], + "nonzero_example_coordinates": [ + [ + 0, + 0 + ], + [ + 2, + 4 + ], + [ + 4, + 8 + ], + [ + 6, + 12 + ], + [ + 8, + 16 + ], + [ + 10, + 21 + ], + [ + 12, + 25 + ], + [ + 14, + 29 + ], + [ + 17, + 1 + ], + [ + 19, + 5 + ], + [ + 21, + 10 + ], + [ + 23, + 14 + ], + [ + 25, + 18 + ], + [ + 27, + 22 + ], + [ + 29, + 26 + ], + [ + 31, + 31 + ] + ], + "source_voxel_spacing": { + "values_zyx": [ + 1.3556, + 1.3556 + ], + "unit": "micrometers" + }, + "spatial_origin_yx": [ + 0, + 0 + ], + "source_spatial_shape_yx": [ + 32, + 32 + ], + "data_type": "image", + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w2_z001_t001.tif", + "components": { + "site": 1, + "channel": 2, + "z_index": 1, + "timepoint": 1, + "well": "A01" + }, + "payload_type": "ndarray" + } + ], + "payload_summary_count": 2, + "payload_summaries_truncated": false, + "axis_labels": [ + "site", + "channel", + "z_index", + "timepoint", + "well", + "y", + "x" + ], + "stack_axes": [ + "channel" + ], + "axis_offsets": [ + 0 + ], + "scalar_labels": [ + "Site 1", + "Z 1", + "T 1", + "Well A01" + ], + "labels": { + "channel": [ + "Ch 1", + "Ch 2" + ] + }, + "axis_component_values": { + "channel": [ + 1, + 2 + ] + }, + "routed_component_values": { + "channel": [ + 1, + 2 + ] + }, + "routed_component_coordinates": [ + [ + 1 + ], + [ + 2 + ] + ], + "data_shape": [ + 1, + 2, + 1, + 1, + 1, + 32, + 32 + ], + "native_transform": { + "scale": [ + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.3556, + 1.3556 + ], + "translate": [ + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0 + ] + }, + "native_intensity": { + "contrast_limits": [ + 100.0, + 1223.0 + ], + "gamma": 1.0 + }, + "visible": true, + "selected": true, + "feature_row_count": 0, + "selected_data_indices": [], + "pending_update": false + }, + { + "route_key": "origin_manual_kind_manual_projection_A01_s001_w2_z001_t001_graph.graph.roi.zip_shapes", + "producer_identities": [ + { + "origin": "manual", + "output_kind": "manual", + "output_key": "A01_s001_w2_z001_t001_graph.graph.roi.zip", + "projection_key": "A01_s001_w2_z001_t001_graph.graph.roi.zip", + "step_name": null, + "pipeline_position": null, + "step_scope_id": null, + "invocation_key": null, + "artifact_kind": null + } + ], + "title": "A01_s001_w2_z001_t001_graph.graph.roi.zip ROIs", + "mounted": true, + "item_count": 1, + "data_types": [ + "shapes" + ], + "component_values": [ + { + "site": 1, + "channel": 2, + "z_index": 1, + "timepoint": 1, + "well": "A01" + } + ], + "component_value_count": 1, + "component_values_truncated": false, + "payload_summaries": [ + { + "nonzero_count": 2, + "item_count": 2, + "shape_payload_count": 2, + "missing_source_spatial_shape_count": 2, + "shape_coordinate_count": 4, + "shape_out_of_source_bounds_count": 0, + "shape_coordinate_bounds_yx": { + "min_yx": [ + 2.25, + 3.5 + ], + "max_yx": [ + 7.25, + 12.5 + ], + "coordinate_count": 4 + }, + "source_voxel_spacing": { + "values_zyx": [ + 1.3556, + 1.3556 + ], + "unit": "micrometers" + }, + "data_type": "shapes", + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/graph_results/A01_s001_w2_z001_t001_graph.graph.roi.zip", + "components": { + "site": 1, + "channel": 2, + "z_index": 1, + "timepoint": 1, + "well": "A01" + }, + "payload_type": "list" + } + ], + "payload_summary_count": 1, + "payload_summaries_truncated": false, + "axis_labels": [ + "site", + "channel", + "z_index", + "timepoint", + "well", + "y", + "x" + ], + "stack_axes": [ + "channel" + ], + "axis_offsets": [ + 1 + ], + "scalar_labels": [ + "Site 1", + "Z 1", + "T 1", + "Well A01" + ], + "labels": { + "channel": [ + "Ch 2" + ] + }, + "axis_component_values": { + "channel": [ + 2 + ] + }, + "routed_component_values": { + "channel": [ + 2 + ] + }, + "routed_component_coordinates": [ + [ + 2 + ] + ], + "data_shape": [ + 2 + ], + "native_transform": { + "scale": [ + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.3556, + 1.3556 + ], + "translate": [ + 0.0, + 1.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0 + ] + }, + "native_intensity": null, + "visible": false, + "selected": false, + "feature_row_count": 2, + "selected_data_indices": [], + "pending_update": false + } + ], + "native_viewport": { + "center": [ + 0.0, + 21.011799999999997, + 21.011799999999997 + ], + "zoom": 6.635668707583358 + }, + "native_dimensions": { + "order": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6 + ], + "ndisplay": 2, + "displayed_axes": [ + "y", + "x" + ], + "point": [ + 0.0, + 1.0, + 0.0, + 0.0, + 0.0, + 20.334, + 20.334 + ], + "camera_angles": [ + 0.0, + 0.0, + 0.0 + ], + "canvas_size": [ + 643, + 478 + ] + }, + "active_dimension_label_route": "origin_manual_kind_manual_projection_selected_images_e83ddc2185a63aca4b85ec471143f61c8f4eabdb08df3557ca21f2bddcda60b9", + "viewer_ndim": 7, + "current_step": [ + 0, + 1, + 0, + 0, + 0, + 15, + 15 + ], + "axis_labels": [ + "site", + "channel", + "z_index", + "timepoint", + "well", + "y", + "x" + ], + "component_group_count": 3, + "component_item_count": 4 + } + } + }, + { + "tool": "openhcs_viewer_snapshot_window", + "arguments": { + "host": "127.0.0.1", + "port": 6609, + "transport_mode": "tcp", + "output_dir_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/captures-live12/raw", + "capture_scope": "widget", + "frame_condition": "render_complete", + "observation_timeout_s": 2.5 + }, + "response": { + "content": [ + { + "type": "text", + "text": "{\n \"connection\": {\n \"host\": \"127.0.0.1\",\n \"port\": 6609,\n \"transport_mode\": \"tcp\",\n \"persistent\": true\n },\n \"schema_version\": \"openhcs.agent.v1\",\n \"errors\": [],\n \"warnings\": [],\n \"output_dir_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/captures-live12/raw\",\n \"capture_scope\": \"widget\",\n \"frame_condition\": \"render_complete\",\n \"observation_timeout_s\": 2.5,\n \"captured\": true,\n \"observation\": {\n \"condition\": \"render_complete\",\n \"window_identity\": 140451432015472,\n \"started_at_monotonic\": 3882702.250398891,\n \"completed_at_monotonic\": 3882702.264351425,\n \"configured_flash_duration_s\": 0.0,\n \"baseline_inactive\": true,\n \"flash_start_count\": 0,\n \"painted_frame_count\": 1,\n \"frame\": null,\n \"trace\": [],\n \"render_frame\": {\n \"window_identity\": 140451432015472,\n \"renderer_identity\": 140451432242288,\n \"completed_at_monotonic\": 3882702.264341316\n },\n \"observation_budget_s\": 2.4809327765833586,\n \"operation_deadline\": {\n \"operation\": \"viewer control request\",\n \"timeout_ms\": 5000,\n \"expires_at\": 3882707.212359763\n }\n },\n \"resource\": {\n \"uri\": \"file:///home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/captures-live12/raw/20261004T043044386798Z_napari_6609_OpenHCS_Napari_Visualization.png\",\n \"title\": \"OpenHCS Napari Visualization\",\n \"mime_type\": \"image/png\",\n \"path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/captures-live12/raw/20261004T043044386798Z_napari_6609_OpenHCS_Napari_Visualization.png\",\n \"size_bytes\": 86074,\n \"sha256\": \"f9050beeffc54c925aaca4cf4188ecf1c51b42c4fa49f2b08c5f880d47ce59d2\"\n },\n \"viewer\": {\n \"viewer_type\": \"napari\",\n \"title\": \"OpenHCS Napari Visualization\"\n },\n \"width\": 1152,\n \"height\": 963,\n \"response\": {\n \"type\": \"screenshot_ack\",\n \"status\": \"success\",\n \"viewer\": {\n \"type\": \"napari\",\n \"title\": \"OpenHCS Napari Visualization\"\n },\n \"resource\": {\n \"uri\": \"file:///home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/captures-live12/raw/20261004T043044386798Z_napari_6609_OpenHCS_Napari_Visualization.png\",\n \"title\": \"OpenHCS Napari Visualization\",\n \"mime_type\": \"image/png\",\n \"path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/captures-live12/raw/20261004T043044386798Z_napari_6609_OpenHCS_Napari_Visualization.png\",\n \"size_bytes\": 86074,\n \"sha256\": \"f9050beeffc54c925aaca4cf4188ecf1c51b42c4fa49f2b08c5f880d47ce59d2\"\n },\n \"width\": 1152,\n \"height\": 963,\n \"snapshot\": {\n \"connection\": {\n \"host\": \"127.0.0.1\",\n \"port\": 6609,\n \"transport_mode\": \"tcp\",\n \"persistent\": true\n },\n \"timeout_ms\": 5000,\n \"include_response\": true,\n \"operation_deadline\": {\n \"operation\": \"viewer control request\",\n \"timeout_ms\": 5000,\n \"expires_at\": 3882707.212359763\n },\n \"output_dir_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/captures-live12/raw\",\n \"capture_scope\": \"widget\",\n \"frame_condition\": \"render_complete\",\n \"observation_timeout_s\": 2.5\n },\n \"observation\": {\n \"condition\": \"render_complete\",\n \"window_identity\": 140451432015472,\n \"started_at_monotonic\": 3882702.250398891,\n \"completed_at_monotonic\": 3882702.264351425,\n \"configured_flash_duration_s\": 0.0,\n \"baseline_inactive\": true,\n \"flash_start_count\": 0,\n \"painted_frame_count\": 1,\n \"frame\": null,\n \"trace\": [],\n \"render_frame\": {\n \"window_identity\": 140451432015472,\n \"renderer_identity\": 140451432242288,\n \"completed_at_monotonic\": 3882702.264341316\n },\n \"observation_budget_s\": 2.4809327765833586,\n \"operation_deadline\": {\n \"operation\": \"viewer control request\",\n \"timeout_ms\": 5000,\n \"expires_at\": 3882707.212359763\n }\n },\n \"native_dimensions\": {\n \"order\": [\n 0,\n 1,\n 2,\n 3,\n 4,\n 5,\n 6\n ],\n \"ndisplay\": 2,\n \"displayed_axes\": [\n \"y\",\n \"x\"\n ],\n \"point\": [\n 0.0,\n 1.0,\n 0.0,\n 0.0,\n 0.0,\n 20.334,\n 20.334\n ],\n \"camera_angles\": [\n 0.0,\n 0.0,\n 0.0\n ],\n \"canvas_size\": [\n 643,\n 478\n ]\n }\n }\n}" + } + ], + "structuredContent": { + "connection": { + "host": "127.0.0.1", + "port": 6609, + "transport_mode": "tcp", + "persistent": true + }, + "schema_version": "openhcs.agent.v1", + "errors": [], + "warnings": [], + "output_dir_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/captures-live12/raw", + "capture_scope": "widget", + "frame_condition": "render_complete", + "observation_timeout_s": 2.5, + "captured": true, + "observation": { + "condition": "render_complete", + "window_identity": 140451432015472, + "started_at_monotonic": 3882702.250398891, + "completed_at_monotonic": 3882702.264351425, + "configured_flash_duration_s": 0.0, + "baseline_inactive": true, + "flash_start_count": 0, + "painted_frame_count": 1, + "frame": null, + "trace": [], + "render_frame": { + "window_identity": 140451432015472, + "renderer_identity": 140451432242288, + "completed_at_monotonic": 3882702.264341316 + }, + "observation_budget_s": 2.4809327765833586, + "operation_deadline": { + "operation": "viewer control request", + "timeout_ms": 5000, + "expires_at": 3882707.212359763 + } + }, + "resource": { + "uri": "file:///home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/captures-live12/raw/20261004T043044386798Z_napari_6609_OpenHCS_Napari_Visualization.png", + "title": "OpenHCS Napari Visualization", + "mime_type": "image/png", + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/captures-live12/raw/20261004T043044386798Z_napari_6609_OpenHCS_Napari_Visualization.png", + "size_bytes": 86074, + "sha256": "f9050beeffc54c925aaca4cf4188ecf1c51b42c4fa49f2b08c5f880d47ce59d2" + }, + "viewer": { + "viewer_type": "napari", + "title": "OpenHCS Napari Visualization" + }, + "width": 1152, + "height": 963, + "response": { + "type": "screenshot_ack", + "status": "success", + "viewer": { + "type": "napari", + "title": "OpenHCS Napari Visualization" + }, + "resource": { + "uri": "file:///home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/captures-live12/raw/20261004T043044386798Z_napari_6609_OpenHCS_Napari_Visualization.png", + "title": "OpenHCS Napari Visualization", + "mime_type": "image/png", + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/captures-live12/raw/20261004T043044386798Z_napari_6609_OpenHCS_Napari_Visualization.png", + "size_bytes": 86074, + "sha256": "f9050beeffc54c925aaca4cf4188ecf1c51b42c4fa49f2b08c5f880d47ce59d2" + }, + "width": 1152, + "height": 963, + "snapshot": { + "connection": { + "host": "127.0.0.1", + "port": 6609, + "transport_mode": "tcp", + "persistent": true + }, + "timeout_ms": 5000, + "include_response": true, + "operation_deadline": { + "operation": "viewer control request", + "timeout_ms": 5000, + "expires_at": 3882707.212359763 + }, + "output_dir_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/captures-live12/raw", + "capture_scope": "widget", + "frame_condition": "render_complete", + "observation_timeout_s": 2.5 + }, + "observation": { + "condition": "render_complete", + "window_identity": 140451432015472, + "started_at_monotonic": 3882702.250398891, + "completed_at_monotonic": 3882702.264351425, + "configured_flash_duration_s": 0.0, + "baseline_inactive": true, + "flash_start_count": 0, + "painted_frame_count": 1, + "frame": null, + "trace": [], + "render_frame": { + "window_identity": 140451432015472, + "renderer_identity": 140451432242288, + "completed_at_monotonic": 3882702.264341316 + }, + "observation_budget_s": 2.4809327765833586, + "operation_deadline": { + "operation": "viewer control request", + "timeout_ms": 5000, + "expires_at": 3882707.212359763 + } + }, + "native_dimensions": { + "order": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6 + ], + "ndisplay": 2, + "displayed_axes": [ + "y", + "x" + ], + "point": [ + 0.0, + 1.0, + 0.0, + 0.0, + 0.0, + 20.334, + 20.334 + ], + "camera_angles": [ + 0.0, + 0.0, + 0.0 + ], + "canvas_size": [ + 643, + 478 + ] + } + } + }, + "isError": false + }, + "payload": { + "connection": { + "host": "127.0.0.1", + "port": 6609, + "transport_mode": "tcp", + "persistent": true + }, + "schema_version": "openhcs.agent.v1", + "errors": [], + "warnings": [], + "output_dir_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/captures-live12/raw", + "capture_scope": "widget", + "frame_condition": "render_complete", + "observation_timeout_s": 2.5, + "captured": true, + "observation": { + "condition": "render_complete", + "window_identity": 140451432015472, + "started_at_monotonic": 3882702.250398891, + "completed_at_monotonic": 3882702.264351425, + "configured_flash_duration_s": 0.0, + "baseline_inactive": true, + "flash_start_count": 0, + "painted_frame_count": 1, + "frame": null, + "trace": [], + "render_frame": { + "window_identity": 140451432015472, + "renderer_identity": 140451432242288, + "completed_at_monotonic": 3882702.264341316 + }, + "observation_budget_s": 2.4809327765833586, + "operation_deadline": { + "operation": "viewer control request", + "timeout_ms": 5000, + "expires_at": 3882707.212359763 + } + }, + "resource": { + "uri": "file:///home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/captures-live12/raw/20261004T043044386798Z_napari_6609_OpenHCS_Napari_Visualization.png", + "title": "OpenHCS Napari Visualization", + "mime_type": "image/png", + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/captures-live12/raw/20261004T043044386798Z_napari_6609_OpenHCS_Napari_Visualization.png", + "size_bytes": 86074, + "sha256": "f9050beeffc54c925aaca4cf4188ecf1c51b42c4fa49f2b08c5f880d47ce59d2" + }, + "viewer": { + "viewer_type": "napari", + "title": "OpenHCS Napari Visualization" + }, + "width": 1152, + "height": 963, + "response": { + "type": "screenshot_ack", + "status": "success", + "viewer": { + "type": "napari", + "title": "OpenHCS Napari Visualization" + }, + "resource": { + "uri": "file:///home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/captures-live12/raw/20261004T043044386798Z_napari_6609_OpenHCS_Napari_Visualization.png", + "title": "OpenHCS Napari Visualization", + "mime_type": "image/png", + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/captures-live12/raw/20261004T043044386798Z_napari_6609_OpenHCS_Napari_Visualization.png", + "size_bytes": 86074, + "sha256": "f9050beeffc54c925aaca4cf4188ecf1c51b42c4fa49f2b08c5f880d47ce59d2" + }, + "width": 1152, + "height": 963, + "snapshot": { + "connection": { + "host": "127.0.0.1", + "port": 6609, + "transport_mode": "tcp", + "persistent": true + }, + "timeout_ms": 5000, + "include_response": true, + "operation_deadline": { + "operation": "viewer control request", + "timeout_ms": 5000, + "expires_at": 3882707.212359763 + }, + "output_dir_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/captures-live12/raw", + "capture_scope": "widget", + "frame_condition": "render_complete", + "observation_timeout_s": 2.5 + }, + "observation": { + "condition": "render_complete", + "window_identity": 140451432015472, + "started_at_monotonic": 3882702.250398891, + "completed_at_monotonic": 3882702.264351425, + "configured_flash_duration_s": 0.0, + "baseline_inactive": true, + "flash_start_count": 0, + "painted_frame_count": 1, + "frame": null, + "trace": [], + "render_frame": { + "window_identity": 140451432015472, + "renderer_identity": 140451432242288, + "completed_at_monotonic": 3882702.264341316 + }, + "observation_budget_s": 2.4809327765833586, + "operation_deadline": { + "operation": "viewer control request", + "timeout_ms": 5000, + "expires_at": 3882707.212359763 + } + }, + "native_dimensions": { + "order": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6 + ], + "ndisplay": 2, + "displayed_axes": [ + "y", + "x" + ], + "point": [ + 0.0, + 1.0, + 0.0, + 0.0, + 0.0, + 20.334, + 20.334 + ], + "camera_angles": [ + 0.0, + 0.0, + 0.0 + ], + "canvas_size": [ + 643, + 478 + ] + } + } + } + }, + { + "tool": "openhcs_isolate_viewer_window_layers", + "arguments": { + "host": "127.0.0.1", + "port": 6609, + "transport_mode": "tcp", + "visible_route_keys": [ + "origin_manual_kind_manual_projection_A01_s001_w2_z001_t001_graph.graph.roi.zip_shapes", + "origin_manual_kind_manual_projection_selected_images_8c7357d46ccc38823ca9e68096baf86f25c3004b61b63ba1eef9adea41d34fb8_scalar_stack" + ], + "selected_route_key": "origin_manual_kind_manual_projection_selected_images_8c7357d46ccc38823ca9e68096baf86f25c3004b61b63ba1eef9adea41d34fb8_scalar_stack", + "axis_indices": { + "channel": 1 + } + }, + "response": { + "content": [ + { + "type": "text", + "text": "{\n \"connection\": {\n \"host\": \"127.0.0.1\",\n \"port\": 6609,\n \"transport_mode\": \"tcp\",\n \"persistent\": true\n },\n \"schema_version\": \"openhcs.agent.v1\",\n \"errors\": [],\n \"warnings\": [],\n \"observed\": true,\n \"applied\": true,\n \"selected_route_key\": \"origin_manual_kind_manual_projection_selected_images_8c7357d46ccc38823ca9e68096baf86f25c3004b61b63ba1eef9adea41d34fb8_scalar_stack\",\n \"visible_route_keys\": [\n \"origin_manual_kind_manual_projection_selected_images_8c7357d46ccc38823ca9e68096baf86f25c3004b61b63ba1eef9adea41d34fb8_scalar_stack\",\n \"origin_manual_kind_manual_projection_A01_s001_w2_z001_t001_graph.graph.roi.zip_shapes\"\n ],\n \"hidden_route_keys\": [\n \"origin_manual_kind_manual_projection_selected_images_e83ddc2185a63aca4b85ec471143f61c8f4eabdb08df3557ca21f2bddcda60b9\"\n ],\n \"missing_route_keys\": [],\n \"available_layers\": [\n {\n \"route_key\": \"origin_manual_kind_manual_projection_selected_images_8c7357d46ccc38823ca9e68096baf86f25c3004b61b63ba1eef9adea41d34fb8_scalar_stack\",\n \"title\": \"selected_images image stack\",\n \"visible\": true,\n \"selected\": true\n },\n {\n \"route_key\": \"origin_manual_kind_manual_projection_selected_images_e83ddc2185a63aca4b85ec471143f61c8f4eabdb08df3557ca21f2bddcda60b9\",\n \"title\": \"selected_images\",\n \"visible\": false,\n \"selected\": false\n },\n {\n \"route_key\": \"origin_manual_kind_manual_projection_A01_s001_w2_z001_t001_graph.graph.roi.zip_shapes\",\n \"title\": \"A01_s001_w2_z001_t001_graph.graph.roi.zip ROIs\",\n \"visible\": true,\n \"selected\": false\n }\n ],\n \"changed_route_count\": 3,\n \"layer_count\": 3,\n \"active_dimension_label_route\": \"origin_manual_kind_manual_projection_selected_images_8c7357d46ccc38823ca9e68096baf86f25c3004b61b63ba1eef9adea41d34fb8_scalar_stack\",\n \"current_step\": [\n 0,\n 1,\n 0,\n 0,\n 0,\n 15,\n 15\n ],\n \"axis_labels\": [\n \"site\",\n \"channel\",\n \"z_index\",\n \"timepoint\",\n \"well\",\n \"y\",\n \"x\"\n ],\n \"visible_layers\": [\n {\n \"route_key\": \"origin_manual_kind_manual_projection_selected_images_8c7357d46ccc38823ca9e68096baf86f25c3004b61b63ba1eef9adea41d34fb8_scalar_stack\",\n \"title\": \"selected_images image stack\",\n \"visible\": true,\n \"selected\": true\n },\n {\n \"route_key\": \"origin_manual_kind_manual_projection_A01_s001_w2_z001_t001_graph.graph.roi.zip_shapes\",\n \"title\": \"A01_s001_w2_z001_t001_graph.graph.roi.zip ROIs\",\n \"visible\": true,\n \"selected\": false\n }\n ]\n}" + } + ], + "structuredContent": { + "connection": { + "host": "127.0.0.1", + "port": 6609, + "transport_mode": "tcp", + "persistent": true + }, + "schema_version": "openhcs.agent.v1", + "errors": [], + "warnings": [], + "observed": true, + "applied": true, + "selected_route_key": "origin_manual_kind_manual_projection_selected_images_8c7357d46ccc38823ca9e68096baf86f25c3004b61b63ba1eef9adea41d34fb8_scalar_stack", + "visible_route_keys": [ + "origin_manual_kind_manual_projection_selected_images_8c7357d46ccc38823ca9e68096baf86f25c3004b61b63ba1eef9adea41d34fb8_scalar_stack", + "origin_manual_kind_manual_projection_A01_s001_w2_z001_t001_graph.graph.roi.zip_shapes" + ], + "hidden_route_keys": [ + "origin_manual_kind_manual_projection_selected_images_e83ddc2185a63aca4b85ec471143f61c8f4eabdb08df3557ca21f2bddcda60b9" + ], + "missing_route_keys": [], + "available_layers": [ + { + "route_key": "origin_manual_kind_manual_projection_selected_images_8c7357d46ccc38823ca9e68096baf86f25c3004b61b63ba1eef9adea41d34fb8_scalar_stack", + "title": "selected_images image stack", + "visible": true, + "selected": true + }, + { + "route_key": "origin_manual_kind_manual_projection_selected_images_e83ddc2185a63aca4b85ec471143f61c8f4eabdb08df3557ca21f2bddcda60b9", + "title": "selected_images", + "visible": false, + "selected": false + }, + { + "route_key": "origin_manual_kind_manual_projection_A01_s001_w2_z001_t001_graph.graph.roi.zip_shapes", + "title": "A01_s001_w2_z001_t001_graph.graph.roi.zip ROIs", + "visible": true, + "selected": false + } + ], + "changed_route_count": 3, + "layer_count": 3, + "active_dimension_label_route": "origin_manual_kind_manual_projection_selected_images_8c7357d46ccc38823ca9e68096baf86f25c3004b61b63ba1eef9adea41d34fb8_scalar_stack", + "current_step": [ + 0, + 1, + 0, + 0, + 0, + 15, + 15 + ], + "axis_labels": [ + "site", + "channel", + "z_index", + "timepoint", + "well", + "y", + "x" + ], + "visible_layers": [ + { + "route_key": "origin_manual_kind_manual_projection_selected_images_8c7357d46ccc38823ca9e68096baf86f25c3004b61b63ba1eef9adea41d34fb8_scalar_stack", + "title": "selected_images image stack", + "visible": true, + "selected": true + }, + { + "route_key": "origin_manual_kind_manual_projection_A01_s001_w2_z001_t001_graph.graph.roi.zip_shapes", + "title": "A01_s001_w2_z001_t001_graph.graph.roi.zip ROIs", + "visible": true, + "selected": false + } + ] + }, + "isError": false + }, + "payload": { + "connection": { + "host": "127.0.0.1", + "port": 6609, + "transport_mode": "tcp", + "persistent": true + }, + "schema_version": "openhcs.agent.v1", + "errors": [], + "warnings": [], + "observed": true, + "applied": true, + "selected_route_key": "origin_manual_kind_manual_projection_selected_images_8c7357d46ccc38823ca9e68096baf86f25c3004b61b63ba1eef9adea41d34fb8_scalar_stack", + "visible_route_keys": [ + "origin_manual_kind_manual_projection_selected_images_8c7357d46ccc38823ca9e68096baf86f25c3004b61b63ba1eef9adea41d34fb8_scalar_stack", + "origin_manual_kind_manual_projection_A01_s001_w2_z001_t001_graph.graph.roi.zip_shapes" + ], + "hidden_route_keys": [ + "origin_manual_kind_manual_projection_selected_images_e83ddc2185a63aca4b85ec471143f61c8f4eabdb08df3557ca21f2bddcda60b9" + ], + "missing_route_keys": [], + "available_layers": [ + { + "route_key": "origin_manual_kind_manual_projection_selected_images_8c7357d46ccc38823ca9e68096baf86f25c3004b61b63ba1eef9adea41d34fb8_scalar_stack", + "title": "selected_images image stack", + "visible": true, + "selected": true + }, + { + "route_key": "origin_manual_kind_manual_projection_selected_images_e83ddc2185a63aca4b85ec471143f61c8f4eabdb08df3557ca21f2bddcda60b9", + "title": "selected_images", + "visible": false, + "selected": false + }, + { + "route_key": "origin_manual_kind_manual_projection_A01_s001_w2_z001_t001_graph.graph.roi.zip_shapes", + "title": "A01_s001_w2_z001_t001_graph.graph.roi.zip ROIs", + "visible": true, + "selected": false + } + ], + "changed_route_count": 3, + "layer_count": 3, + "active_dimension_label_route": "origin_manual_kind_manual_projection_selected_images_8c7357d46ccc38823ca9e68096baf86f25c3004b61b63ba1eef9adea41d34fb8_scalar_stack", + "current_step": [ + 0, + 1, + 0, + 0, + 0, + 15, + 15 + ], + "axis_labels": [ + "site", + "channel", + "z_index", + "timepoint", + "well", + "y", + "x" + ], + "visible_layers": [ + { + "route_key": "origin_manual_kind_manual_projection_selected_images_8c7357d46ccc38823ca9e68096baf86f25c3004b61b63ba1eef9adea41d34fb8_scalar_stack", + "title": "selected_images image stack", + "visible": true, + "selected": true + }, + { + "route_key": "origin_manual_kind_manual_projection_A01_s001_w2_z001_t001_graph.graph.roi.zip_shapes", + "title": "A01_s001_w2_z001_t001_graph.graph.roi.zip ROIs", + "visible": true, + "selected": false + } + ] + } + }, + { + "tool": "openhcs_set_viewer_viewport", + "arguments": { + "host": "127.0.0.1", + "port": 6609, + "transport_mode": "tcp", + "presentation": { + "center": [ + 0.0, + 21.011799999999997, + 21.011799999999997 + ], + "zoom": 6.635668707583358 + } + }, + "response": { + "content": [ + { + "type": "text", + "text": "{\n \"connection\": {\n \"host\": \"127.0.0.1\",\n \"port\": 6609,\n \"transport_mode\": \"tcp\",\n \"persistent\": true\n },\n \"schema_version\": \"openhcs.agent.v1\",\n \"errors\": [],\n \"warnings\": [],\n \"observed\": true,\n \"applied\": true,\n \"native_viewport\": {\n \"center\": [\n 0.0,\n 21.011799999999997,\n 21.011799999999997\n ],\n \"zoom\": 6.635668707583358\n }\n}" + } + ], + "structuredContent": { + "connection": { + "host": "127.0.0.1", + "port": 6609, + "transport_mode": "tcp", + "persistent": true + }, + "schema_version": "openhcs.agent.v1", + "errors": [], + "warnings": [], + "observed": true, + "applied": true, + "native_viewport": { + "center": [ + 0.0, + 21.011799999999997, + 21.011799999999997 + ], + "zoom": 6.635668707583358 + } + }, + "isError": false + }, + "payload": { + "connection": { + "host": "127.0.0.1", + "port": 6609, + "transport_mode": "tcp", + "persistent": true + }, + "schema_version": "openhcs.agent.v1", + "errors": [], + "warnings": [], + "observed": true, + "applied": true, + "native_viewport": { + "center": [ + 0.0, + 21.011799999999997, + 21.011799999999997 + ], + "zoom": 6.635668707583358 + } + } + }, + { + "tool": "openhcs_get_viewer_window_state", + "arguments": { + "host": "127.0.0.1", + "port": 6609, + "transport_mode": "tcp", + "route_key": null, + "include_component_values": true, + "max_component_values_per_layer": null, + "include_payload_summaries": true, + "max_payload_summaries_per_layer": null, + "include_response": true + }, + "response": { + "content": [ + { + "type": "text", + "text": "{\n \"connection\": {\n \"host\": \"127.0.0.1\",\n \"port\": 6609,\n \"transport_mode\": \"tcp\",\n \"persistent\": true\n },\n \"schema_version\": \"openhcs.agent.v1\",\n \"errors\": [],\n \"warnings\": [],\n \"observed\": true,\n \"viewer\": {\n \"viewer_type\": \"napari\",\n \"title\": \"OpenHCS Napari Visualization\"\n },\n \"layer_count\": 3,\n \"layers\": [\n {\n \"route_key\": \"origin_manual_kind_manual_projection_selected_images_8c7357d46ccc38823ca9e68096baf86f25c3004b61b63ba1eef9adea41d34fb8_scalar_stack\",\n \"title\": \"selected_images image stack\",\n \"mounted\": true,\n \"item_count\": 1,\n \"producer_identities\": [\n {\n \"origin\": \"manual\",\n \"output_kind\": \"manual\",\n \"output_key\": \"selected_images\",\n \"projection_key\": \"selected_images_8c7357d46ccc38823ca9e68096baf86f25c3004b61b63ba1eef9adea41d34fb8\",\n \"step_name\": null,\n \"pipeline_position\": null,\n \"step_scope_id\": null,\n \"invocation_key\": null,\n \"artifact_kind\": null\n }\n ],\n \"axis_labels\": [\n \"site\",\n \"channel\",\n \"z_index\",\n \"timepoint\",\n \"well\",\n \"y\",\n \"x\"\n ],\n \"stack_axes\": [\n \"channel\"\n ],\n \"pending_update\": false,\n \"data_types\": [\n \"image\"\n ],\n \"component_values\": [\n {\n \"site\": 1,\n \"z_index\": 1,\n \"timepoint\": 1,\n \"well\": \"A01\"\n }\n ],\n \"component_value_count\": 1,\n \"component_values_truncated\": false,\n \"payload_summaries\": [\n {\n \"shape\": [\n 2,\n 32,\n 32\n ],\n \"dtype\": \"uint16\",\n \"size\": 2048,\n \"nonzero_count\": 308,\n \"min\": 0,\n \"max\": 22,\n \"nonzero_min_coordinate\": [\n 0,\n 3,\n 4\n ],\n \"nonzero_max_coordinate\": [\n 1,\n 24,\n 27\n ],\n \"nonzero_example_coordinates\": [\n [\n 0,\n 3,\n 4\n ],\n [\n 0,\n 5,\n 4\n ],\n [\n 0,\n 7,\n 4\n ],\n [\n 0,\n 9,\n 5\n ],\n [\n 0,\n 11,\n 5\n ],\n [\n 0,\n 18,\n 24\n ],\n [\n 0,\n 21,\n 20\n ],\n [\n 0,\n 23,\n 25\n ],\n [\n 1,\n 3,\n 13\n ],\n [\n 1,\n 6,\n 4\n ],\n [\n 1,\n 8,\n 4\n ],\n [\n 1,\n 10,\n 5\n ],\n [\n 1,\n 17,\n 21\n ],\n [\n 1,\n 19,\n 26\n ],\n [\n 1,\n 22,\n 22\n ],\n [\n 1,\n 24,\n 27\n ]\n ],\n \"source_voxel_spacing\": {\n \"values_zyx\": [\n 1.3556,\n 1.3556\n ],\n \"unit\": \"micrometers\"\n },\n \"spatial_origin_yx\": [\n 0,\n 0\n ],\n \"source_spatial_shape_yx\": [\n 32,\n 32\n ],\n \"aggregate_component_values\": {\n \"channel\": [\n 2,\n 1\n ]\n },\n \"data_type\": \"image\",\n \"path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/stacked_labels/A01_s001_w2_z001_t001_Labels.tif\",\n \"components\": {\n \"site\": 1,\n \"z_index\": 1,\n \"timepoint\": 1,\n \"well\": \"A01\"\n },\n \"payload_type\": \"ndarray\"\n }\n ],\n \"payload_summary_count\": 1,\n \"payload_summaries_truncated\": false,\n \"axis_offsets\": [\n 0\n ],\n \"scalar_labels\": [\n \"Site 1\",\n \"Z 1\",\n \"T 1\",\n \"Well A01\"\n ],\n \"labels\": {\n \"channel\": [\n \"Ch 1\",\n \"Ch 2\"\n ]\n },\n \"axis_component_values\": {\n \"channel\": [\n 1,\n 2\n ]\n },\n \"routed_component_values\": {\n \"channel\": [\n 1,\n 2\n ]\n },\n \"routed_component_coordinates\": [\n [\n 1\n ],\n [\n 2\n ]\n ],\n \"data_shape\": [\n 1,\n 2,\n 1,\n 1,\n 1,\n 32,\n 32\n ],\n \"native_transform\": {\n \"scale\": [\n 1.0,\n 1.0,\n 1.0,\n 1.0,\n 1.0,\n 1.3556,\n 1.3556\n ],\n \"translate\": [\n 0.0,\n 0.0,\n 0.0,\n 0.0,\n 0.0,\n 0.0,\n 0.0\n ]\n },\n \"native_intensity\": {\n \"contrast_limits\": [\n 0.0,\n 22.0\n ],\n \"gamma\": 1.0\n },\n \"visible\": true,\n \"selected\": true,\n \"feature_row_count\": 0,\n \"selected_data_indices\": []\n },\n {\n \"route_key\": \"origin_manual_kind_manual_projection_selected_images_e83ddc2185a63aca4b85ec471143f61c8f4eabdb08df3557ca21f2bddcda60b9\",\n \"title\": \"selected_images\",\n \"mounted\": true,\n \"item_count\": 2,\n \"producer_identities\": [\n {\n \"origin\": \"manual\",\n \"output_kind\": \"manual\",\n \"output_key\": \"selected_images\",\n \"projection_key\": \"selected_images_e83ddc2185a63aca4b85ec471143f61c8f4eabdb08df3557ca21f2bddcda60b9\",\n \"step_name\": null,\n \"pipeline_position\": null,\n \"step_scope_id\": null,\n \"invocation_key\": null,\n \"artifact_kind\": null\n }\n ],\n \"axis_labels\": [\n \"site\",\n \"channel\",\n \"z_index\",\n \"timepoint\",\n \"well\",\n \"y\",\n \"x\"\n ],\n \"stack_axes\": [\n \"channel\"\n ],\n \"pending_update\": false,\n \"data_types\": [\n \"image\"\n ],\n \"component_values\": [\n {\n \"site\": 1,\n \"channel\": 1,\n \"z_index\": 1,\n \"timepoint\": 1,\n \"well\": \"A01\"\n },\n {\n \"site\": 1,\n \"channel\": 2,\n \"z_index\": 1,\n \"timepoint\": 1,\n \"well\": \"A01\"\n }\n ],\n \"component_value_count\": 2,\n \"component_values_truncated\": false,\n \"payload_summaries\": [\n {\n \"shape\": [\n 32,\n 32\n ],\n \"dtype\": \"uint16\",\n \"size\": 1024,\n \"nonzero_count\": 1024,\n \"min\": 100,\n \"max\": 1123,\n \"nonzero_min_coordinate\": [\n 0,\n 0\n ],\n \"nonzero_max_coordinate\": [\n 31,\n 31\n ],\n \"nonzero_example_coordinates\": [\n [\n 0,\n 0\n ],\n [\n 2,\n 4\n ],\n [\n 4,\n 8\n ],\n [\n 6,\n 12\n ],\n [\n 8,\n 16\n ],\n [\n 10,\n 21\n ],\n [\n 12,\n 25\n ],\n [\n 14,\n 29\n ],\n [\n 17,\n 1\n ],\n [\n 19,\n 5\n ],\n [\n 21,\n 10\n ],\n [\n 23,\n 14\n ],\n [\n 25,\n 18\n ],\n [\n 27,\n 22\n ],\n [\n 29,\n 26\n ],\n [\n 31,\n 31\n ]\n ],\n \"source_voxel_spacing\": {\n \"values_zyx\": [\n 1.3556,\n 1.3556\n ],\n \"unit\": \"micrometers\"\n },\n \"spatial_origin_yx\": [\n 0,\n 0\n ],\n \"source_spatial_shape_yx\": [\n 32,\n 32\n ],\n \"data_type\": \"image\",\n \"path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w1_z001_t001.tif\",\n \"components\": {\n \"site\": 1,\n \"channel\": 1,\n \"z_index\": 1,\n \"timepoint\": 1,\n \"well\": \"A01\"\n },\n \"payload_type\": \"ndarray\"\n },\n {\n \"shape\": [\n 32,\n 32\n ],\n \"dtype\": \"uint16\",\n \"size\": 1024,\n \"nonzero_count\": 1024,\n \"min\": 200,\n \"max\": 1223,\n \"nonzero_min_coordinate\": [\n 0,\n 0\n ],\n \"nonzero_max_coordinate\": [\n 31,\n 31\n ],\n \"nonzero_example_coordinates\": [\n [\n 0,\n 0\n ],\n [\n 2,\n 4\n ],\n [\n 4,\n 8\n ],\n [\n 6,\n 12\n ],\n [\n 8,\n 16\n ],\n [\n 10,\n 21\n ],\n [\n 12,\n 25\n ],\n [\n 14,\n 29\n ],\n [\n 17,\n 1\n ],\n [\n 19,\n 5\n ],\n [\n 21,\n 10\n ],\n [\n 23,\n 14\n ],\n [\n 25,\n 18\n ],\n [\n 27,\n 22\n ],\n [\n 29,\n 26\n ],\n [\n 31,\n 31\n ]\n ],\n \"source_voxel_spacing\": {\n \"values_zyx\": [\n 1.3556,\n 1.3556\n ],\n \"unit\": \"micrometers\"\n },\n \"spatial_origin_yx\": [\n 0,\n 0\n ],\n \"source_spatial_shape_yx\": [\n 32,\n 32\n ],\n \"data_type\": \"image\",\n \"path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w2_z001_t001.tif\",\n \"components\": {\n \"site\": 1,\n \"channel\": 2,\n \"z_index\": 1,\n \"timepoint\": 1,\n \"well\": \"A01\"\n },\n \"payload_type\": \"ndarray\"\n }\n ],\n \"payload_summary_count\": 2,\n \"payload_summaries_truncated\": false,\n \"axis_offsets\": [\n 0\n ],\n \"scalar_labels\": [\n \"Site 1\",\n \"Z 1\",\n \"T 1\",\n \"Well A01\"\n ],\n \"labels\": {\n \"channel\": [\n \"Ch 1\",\n \"Ch 2\"\n ]\n },\n \"axis_component_values\": {\n \"channel\": [\n 1,\n 2\n ]\n },\n \"routed_component_values\": {\n \"channel\": [\n 1,\n 2\n ]\n },\n \"routed_component_coordinates\": [\n [\n 1\n ],\n [\n 2\n ]\n ],\n \"data_shape\": [\n 1,\n 2,\n 1,\n 1,\n 1,\n 32,\n 32\n ],\n \"native_transform\": {\n \"scale\": [\n 1.0,\n 1.0,\n 1.0,\n 1.0,\n 1.0,\n 1.3556,\n 1.3556\n ],\n \"translate\": [\n 0.0,\n 0.0,\n 0.0,\n 0.0,\n 0.0,\n 0.0,\n 0.0\n ]\n },\n \"native_intensity\": {\n \"contrast_limits\": [\n 100.0,\n 1223.0\n ],\n \"gamma\": 1.0\n },\n \"visible\": false,\n \"selected\": false,\n \"feature_row_count\": 0,\n \"selected_data_indices\": []\n },\n {\n \"route_key\": \"origin_manual_kind_manual_projection_A01_s001_w2_z001_t001_graph.graph.roi.zip_shapes\",\n \"title\": \"A01_s001_w2_z001_t001_graph.graph.roi.zip ROIs\",\n \"mounted\": true,\n \"item_count\": 1,\n \"producer_identities\": [\n {\n \"origin\": \"manual\",\n \"output_kind\": \"manual\",\n \"output_key\": \"A01_s001_w2_z001_t001_graph.graph.roi.zip\",\n \"projection_key\": \"A01_s001_w2_z001_t001_graph.graph.roi.zip\",\n \"step_name\": null,\n \"pipeline_position\": null,\n \"step_scope_id\": null,\n \"invocation_key\": null,\n \"artifact_kind\": null\n }\n ],\n \"axis_labels\": [\n \"site\",\n \"channel\",\n \"z_index\",\n \"timepoint\",\n \"well\",\n \"y\",\n \"x\"\n ],\n \"stack_axes\": [\n \"channel\"\n ],\n \"pending_update\": false,\n \"data_types\": [\n \"shapes\"\n ],\n \"component_values\": [\n {\n \"site\": 1,\n \"channel\": 2,\n \"z_index\": 1,\n \"timepoint\": 1,\n \"well\": \"A01\"\n }\n ],\n \"component_value_count\": 1,\n \"component_values_truncated\": false,\n \"payload_summaries\": [\n {\n \"nonzero_count\": 2,\n \"item_count\": 2,\n \"shape_payload_count\": 2,\n \"missing_source_spatial_shape_count\": 2,\n \"shape_coordinate_count\": 4,\n \"shape_out_of_source_bounds_count\": 0,\n \"shape_coordinate_bounds_yx\": {\n \"min_yx\": [\n 2.25,\n 3.5\n ],\n \"max_yx\": [\n 7.25,\n 12.5\n ],\n \"coordinate_count\": 4\n },\n \"source_voxel_spacing\": {\n \"values_zyx\": [\n 1.3556,\n 1.3556\n ],\n \"unit\": \"micrometers\"\n },\n \"data_type\": \"shapes\",\n \"path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/graph_results/A01_s001_w2_z001_t001_graph.graph.roi.zip\",\n \"components\": {\n \"site\": 1,\n \"channel\": 2,\n \"z_index\": 1,\n \"timepoint\": 1,\n \"well\": \"A01\"\n },\n \"payload_type\": \"list\"\n }\n ],\n \"payload_summary_count\": 1,\n \"payload_summaries_truncated\": false,\n \"axis_offsets\": [\n 1\n ],\n \"scalar_labels\": [\n \"Site 1\",\n \"Z 1\",\n \"T 1\",\n \"Well A01\"\n ],\n \"labels\": {\n \"channel\": [\n \"Ch 2\"\n ]\n },\n \"axis_component_values\": {\n \"channel\": [\n 2\n ]\n },\n \"routed_component_values\": {\n \"channel\": [\n 2\n ]\n },\n \"routed_component_coordinates\": [\n [\n 2\n ]\n ],\n \"data_shape\": [\n 2\n ],\n \"native_transform\": {\n \"scale\": [\n 1.0,\n 1.0,\n 1.0,\n 1.0,\n 1.0,\n 1.3556,\n 1.3556\n ],\n \"translate\": [\n 0.0,\n 1.0,\n 0.0,\n 0.0,\n 0.0,\n 0.0,\n 0.0\n ]\n },\n \"native_intensity\": null,\n \"visible\": true,\n \"selected\": false,\n \"feature_row_count\": 2,\n \"selected_data_indices\": []\n }\n ],\n \"active_dimension_label_route\": \"origin_manual_kind_manual_projection_selected_images_8c7357d46ccc38823ca9e68096baf86f25c3004b61b63ba1eef9adea41d34fb8_scalar_stack\",\n \"viewer_ndim\": 7,\n \"current_step\": [\n 0,\n 1,\n 0,\n 0,\n 0,\n 15,\n 15\n ],\n \"axis_labels\": [\n \"site\",\n \"channel\",\n \"z_index\",\n \"timepoint\",\n \"well\",\n \"y\",\n \"x\"\n ],\n \"component_group_count\": 3,\n \"component_item_count\": 4,\n \"native_viewport\": {\n \"center\": [\n 0.0,\n 21.011799999999997,\n 21.011799999999997\n ],\n \"zoom\": 6.635668707583358\n },\n \"native_dimensions\": {\n \"order\": [\n 0,\n 1,\n 2,\n 3,\n 4,\n 5,\n 6\n ],\n \"ndisplay\": 2,\n \"displayed_axes\": [\n \"y\",\n \"x\"\n ],\n \"point\": [\n 0.0,\n 1.0,\n 0.0,\n 0.0,\n 0.0,\n 20.334,\n 20.334\n ],\n \"camera_angles\": [\n 0.0,\n 0.0,\n 0.0\n ],\n \"canvas_size\": [\n 643,\n 478\n ]\n },\n \"response\": {\n \"type\": \"state_ack\",\n \"status\": \"success\",\n \"viewer\": {\n \"type\": \"napari\",\n \"title\": \"OpenHCS Napari Visualization\"\n },\n \"layer_count\": 3,\n \"layers\": [\n {\n \"route_key\": \"origin_manual_kind_manual_projection_selected_images_8c7357d46ccc38823ca9e68096baf86f25c3004b61b63ba1eef9adea41d34fb8_scalar_stack\",\n \"producer_identities\": [\n {\n \"origin\": \"manual\",\n \"output_kind\": \"manual\",\n \"output_key\": \"selected_images\",\n \"projection_key\": \"selected_images_8c7357d46ccc38823ca9e68096baf86f25c3004b61b63ba1eef9adea41d34fb8\",\n \"step_name\": null,\n \"pipeline_position\": null,\n \"step_scope_id\": null,\n \"invocation_key\": null,\n \"artifact_kind\": null\n }\n ],\n \"title\": \"selected_images image stack\",\n \"mounted\": true,\n \"item_count\": 1,\n \"data_types\": [\n \"image\"\n ],\n \"component_values\": [\n {\n \"site\": 1,\n \"z_index\": 1,\n \"timepoint\": 1,\n \"well\": \"A01\"\n }\n ],\n \"component_value_count\": 1,\n \"component_values_truncated\": false,\n \"payload_summaries\": [\n {\n \"shape\": [\n 2,\n 32,\n 32\n ],\n \"dtype\": \"uint16\",\n \"size\": 2048,\n \"nonzero_count\": 308,\n \"min\": 0,\n \"max\": 22,\n \"nonzero_min_coordinate\": [\n 0,\n 3,\n 4\n ],\n \"nonzero_max_coordinate\": [\n 1,\n 24,\n 27\n ],\n \"nonzero_example_coordinates\": [\n [\n 0,\n 3,\n 4\n ],\n [\n 0,\n 5,\n 4\n ],\n [\n 0,\n 7,\n 4\n ],\n [\n 0,\n 9,\n 5\n ],\n [\n 0,\n 11,\n 5\n ],\n [\n 0,\n 18,\n 24\n ],\n [\n 0,\n 21,\n 20\n ],\n [\n 0,\n 23,\n 25\n ],\n [\n 1,\n 3,\n 13\n ],\n [\n 1,\n 6,\n 4\n ],\n [\n 1,\n 8,\n 4\n ],\n [\n 1,\n 10,\n 5\n ],\n [\n 1,\n 17,\n 21\n ],\n [\n 1,\n 19,\n 26\n ],\n [\n 1,\n 22,\n 22\n ],\n [\n 1,\n 24,\n 27\n ]\n ],\n \"source_voxel_spacing\": {\n \"values_zyx\": [\n 1.3556,\n 1.3556\n ],\n \"unit\": \"micrometers\"\n },\n \"spatial_origin_yx\": [\n 0,\n 0\n ],\n \"source_spatial_shape_yx\": [\n 32,\n 32\n ],\n \"aggregate_component_values\": {\n \"channel\": [\n 2,\n 1\n ]\n },\n \"data_type\": \"image\",\n \"path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/stacked_labels/A01_s001_w2_z001_t001_Labels.tif\",\n \"components\": {\n \"site\": 1,\n \"z_index\": 1,\n \"timepoint\": 1,\n \"well\": \"A01\"\n },\n \"payload_type\": \"ndarray\"\n }\n ],\n \"payload_summary_count\": 1,\n \"payload_summaries_truncated\": false,\n \"axis_labels\": [\n \"site\",\n \"channel\",\n \"z_index\",\n \"timepoint\",\n \"well\",\n \"y\",\n \"x\"\n ],\n \"stack_axes\": [\n \"channel\"\n ],\n \"axis_offsets\": [\n 0\n ],\n \"scalar_labels\": [\n \"Site 1\",\n \"Z 1\",\n \"T 1\",\n \"Well A01\"\n ],\n \"labels\": {\n \"channel\": [\n \"Ch 1\",\n \"Ch 2\"\n ]\n },\n \"axis_component_values\": {\n \"channel\": [\n 1,\n 2\n ]\n },\n \"routed_component_values\": {\n \"channel\": [\n 1,\n 2\n ]\n },\n \"routed_component_coordinates\": [\n [\n 1\n ],\n [\n 2\n ]\n ],\n \"data_shape\": [\n 1,\n 2,\n 1,\n 1,\n 1,\n 32,\n 32\n ],\n \"native_transform\": {\n \"scale\": [\n 1.0,\n 1.0,\n 1.0,\n 1.0,\n 1.0,\n 1.3556,\n 1.3556\n ],\n \"translate\": [\n 0.0,\n 0.0,\n 0.0,\n 0.0,\n 0.0,\n 0.0,\n 0.0\n ]\n },\n \"native_intensity\": {\n \"contrast_limits\": [\n 0.0,\n 22.0\n ],\n \"gamma\": 1.0\n },\n \"visible\": true,\n \"selected\": true,\n \"feature_row_count\": 0,\n \"selected_data_indices\": [],\n \"pending_update\": false\n },\n {\n \"route_key\": \"origin_manual_kind_manual_projection_selected_images_e83ddc2185a63aca4b85ec471143f61c8f4eabdb08df3557ca21f2bddcda60b9\",\n \"producer_identities\": [\n {\n \"origin\": \"manual\",\n \"output_kind\": \"manual\",\n \"output_key\": \"selected_images\",\n \"projection_key\": \"selected_images_e83ddc2185a63aca4b85ec471143f61c8f4eabdb08df3557ca21f2bddcda60b9\",\n \"step_name\": null,\n \"pipeline_position\": null,\n \"step_scope_id\": null,\n \"invocation_key\": null,\n \"artifact_kind\": null\n }\n ],\n \"title\": \"selected_images\",\n \"mounted\": true,\n \"item_count\": 2,\n \"data_types\": [\n \"image\"\n ],\n \"component_values\": [\n {\n \"site\": 1,\n \"channel\": 1,\n \"z_index\": 1,\n \"timepoint\": 1,\n \"well\": \"A01\"\n },\n {\n \"site\": 1,\n \"channel\": 2,\n \"z_index\": 1,\n \"timepoint\": 1,\n \"well\": \"A01\"\n }\n ],\n \"component_value_count\": 2,\n \"component_values_truncated\": false,\n \"payload_summaries\": [\n {\n \"shape\": [\n 32,\n 32\n ],\n \"dtype\": \"uint16\",\n \"size\": 1024,\n \"nonzero_count\": 1024,\n \"min\": 100,\n \"max\": 1123,\n \"nonzero_min_coordinate\": [\n 0,\n 0\n ],\n \"nonzero_max_coordinate\": [\n 31,\n 31\n ],\n \"nonzero_example_coordinates\": [\n [\n 0,\n 0\n ],\n [\n 2,\n 4\n ],\n [\n 4,\n 8\n ],\n [\n 6,\n 12\n ],\n [\n 8,\n 16\n ],\n [\n 10,\n 21\n ],\n [\n 12,\n 25\n ],\n [\n 14,\n 29\n ],\n [\n 17,\n 1\n ],\n [\n 19,\n 5\n ],\n [\n 21,\n 10\n ],\n [\n 23,\n 14\n ],\n [\n 25,\n 18\n ],\n [\n 27,\n 22\n ],\n [\n 29,\n 26\n ],\n [\n 31,\n 31\n ]\n ],\n \"source_voxel_spacing\": {\n \"values_zyx\": [\n 1.3556,\n 1.3556\n ],\n \"unit\": \"micrometers\"\n },\n \"spatial_origin_yx\": [\n 0,\n 0\n ],\n \"source_spatial_shape_yx\": [\n 32,\n 32\n ],\n \"data_type\": \"image\",\n \"path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w1_z001_t001.tif\",\n \"components\": {\n \"site\": 1,\n \"channel\": 1,\n \"z_index\": 1,\n \"timepoint\": 1,\n \"well\": \"A01\"\n },\n \"payload_type\": \"ndarray\"\n },\n {\n \"shape\": [\n 32,\n 32\n ],\n \"dtype\": \"uint16\",\n \"size\": 1024,\n \"nonzero_count\": 1024,\n \"min\": 200,\n \"max\": 1223,\n \"nonzero_min_coordinate\": [\n 0,\n 0\n ],\n \"nonzero_max_coordinate\": [\n 31,\n 31\n ],\n \"nonzero_example_coordinates\": [\n [\n 0,\n 0\n ],\n [\n 2,\n 4\n ],\n [\n 4,\n 8\n ],\n [\n 6,\n 12\n ],\n [\n 8,\n 16\n ],\n [\n 10,\n 21\n ],\n [\n 12,\n 25\n ],\n [\n 14,\n 29\n ],\n [\n 17,\n 1\n ],\n [\n 19,\n 5\n ],\n [\n 21,\n 10\n ],\n [\n 23,\n 14\n ],\n [\n 25,\n 18\n ],\n [\n 27,\n 22\n ],\n [\n 29,\n 26\n ],\n [\n 31,\n 31\n ]\n ],\n \"source_voxel_spacing\": {\n \"values_zyx\": [\n 1.3556,\n 1.3556\n ],\n \"unit\": \"micrometers\"\n },\n \"spatial_origin_yx\": [\n 0,\n 0\n ],\n \"source_spatial_shape_yx\": [\n 32,\n 32\n ],\n \"data_type\": \"image\",\n \"path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w2_z001_t001.tif\",\n \"components\": {\n \"site\": 1,\n \"channel\": 2,\n \"z_index\": 1,\n \"timepoint\": 1,\n \"well\": \"A01\"\n },\n \"payload_type\": \"ndarray\"\n }\n ],\n \"payload_summary_count\": 2,\n \"payload_summaries_truncated\": false,\n \"axis_labels\": [\n \"site\",\n \"channel\",\n \"z_index\",\n \"timepoint\",\n \"well\",\n \"y\",\n \"x\"\n ],\n \"stack_axes\": [\n \"channel\"\n ],\n \"axis_offsets\": [\n 0\n ],\n \"scalar_labels\": [\n \"Site 1\",\n \"Z 1\",\n \"T 1\",\n \"Well A01\"\n ],\n \"labels\": {\n \"channel\": [\n \"Ch 1\",\n \"Ch 2\"\n ]\n },\n \"axis_component_values\": {\n \"channel\": [\n 1,\n 2\n ]\n },\n \"routed_component_values\": {\n \"channel\": [\n 1,\n 2\n ]\n },\n \"routed_component_coordinates\": [\n [\n 1\n ],\n [\n 2\n ]\n ],\n \"data_shape\": [\n 1,\n 2,\n 1,\n 1,\n 1,\n 32,\n 32\n ],\n \"native_transform\": {\n \"scale\": [\n 1.0,\n 1.0,\n 1.0,\n 1.0,\n 1.0,\n 1.3556,\n 1.3556\n ],\n \"translate\": [\n 0.0,\n 0.0,\n 0.0,\n 0.0,\n 0.0,\n 0.0,\n 0.0\n ]\n },\n \"native_intensity\": {\n \"contrast_limits\": [\n 100.0,\n 1223.0\n ],\n \"gamma\": 1.0\n },\n \"visible\": false,\n \"selected\": false,\n \"feature_row_count\": 0,\n \"selected_data_indices\": [],\n \"pending_update\": false\n },\n {\n \"route_key\": \"origin_manual_kind_manual_projection_A01_s001_w2_z001_t001_graph.graph.roi.zip_shapes\",\n \"producer_identities\": [\n {\n \"origin\": \"manual\",\n \"output_kind\": \"manual\",\n \"output_key\": \"A01_s001_w2_z001_t001_graph.graph.roi.zip\",\n \"projection_key\": \"A01_s001_w2_z001_t001_graph.graph.roi.zip\",\n \"step_name\": null,\n \"pipeline_position\": null,\n \"step_scope_id\": null,\n \"invocation_key\": null,\n \"artifact_kind\": null\n }\n ],\n \"title\": \"A01_s001_w2_z001_t001_graph.graph.roi.zip ROIs\",\n \"mounted\": true,\n \"item_count\": 1,\n \"data_types\": [\n \"shapes\"\n ],\n \"component_values\": [\n {\n \"site\": 1,\n \"channel\": 2,\n \"z_index\": 1,\n \"timepoint\": 1,\n \"well\": \"A01\"\n }\n ],\n \"component_value_count\": 1,\n \"component_values_truncated\": false,\n \"payload_summaries\": [\n {\n \"nonzero_count\": 2,\n \"item_count\": 2,\n \"shape_payload_count\": 2,\n \"missing_source_spatial_shape_count\": 2,\n \"shape_coordinate_count\": 4,\n \"shape_out_of_source_bounds_count\": 0,\n \"shape_coordinate_bounds_yx\": {\n \"min_yx\": [\n 2.25,\n 3.5\n ],\n \"max_yx\": [\n 7.25,\n 12.5\n ],\n \"coordinate_count\": 4\n },\n \"source_voxel_spacing\": {\n \"values_zyx\": [\n 1.3556,\n 1.3556\n ],\n \"unit\": \"micrometers\"\n },\n \"data_type\": \"shapes\",\n \"path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/graph_results/A01_s001_w2_z001_t001_graph.graph.roi.zip\",\n \"components\": {\n \"site\": 1,\n \"channel\": 2,\n \"z_index\": 1,\n \"timepoint\": 1,\n \"well\": \"A01\"\n },\n \"payload_type\": \"list\"\n }\n ],\n \"payload_summary_count\": 1,\n \"payload_summaries_truncated\": false,\n \"axis_labels\": [\n \"site\",\n \"channel\",\n \"z_index\",\n \"timepoint\",\n \"well\",\n \"y\",\n \"x\"\n ],\n \"stack_axes\": [\n \"channel\"\n ],\n \"axis_offsets\": [\n 1\n ],\n \"scalar_labels\": [\n \"Site 1\",\n \"Z 1\",\n \"T 1\",\n \"Well A01\"\n ],\n \"labels\": {\n \"channel\": [\n \"Ch 2\"\n ]\n },\n \"axis_component_values\": {\n \"channel\": [\n 2\n ]\n },\n \"routed_component_values\": {\n \"channel\": [\n 2\n ]\n },\n \"routed_component_coordinates\": [\n [\n 2\n ]\n ],\n \"data_shape\": [\n 2\n ],\n \"native_transform\": {\n \"scale\": [\n 1.0,\n 1.0,\n 1.0,\n 1.0,\n 1.0,\n 1.3556,\n 1.3556\n ],\n \"translate\": [\n 0.0,\n 1.0,\n 0.0,\n 0.0,\n 0.0,\n 0.0,\n 0.0\n ]\n },\n \"native_intensity\": null,\n \"visible\": true,\n \"selected\": false,\n \"feature_row_count\": 2,\n \"selected_data_indices\": [],\n \"pending_update\": false\n }\n ],\n \"native_viewport\": {\n \"center\": [\n 0.0,\n 21.011799999999997,\n 21.011799999999997\n ],\n \"zoom\": 6.635668707583358\n },\n \"native_dimensions\": {\n \"order\": [\n 0,\n 1,\n 2,\n 3,\n 4,\n 5,\n 6\n ],\n \"ndisplay\": 2,\n \"displayed_axes\": [\n \"y\",\n \"x\"\n ],\n \"point\": [\n 0.0,\n 1.0,\n 0.0,\n 0.0,\n 0.0,\n 20.334,\n 20.334\n ],\n \"camera_angles\": [\n 0.0,\n 0.0,\n 0.0\n ],\n \"canvas_size\": [\n 643,\n 478\n ]\n },\n \"active_dimension_label_route\": \"origin_manual_kind_manual_projection_selected_images_8c7357d46ccc38823ca9e68096baf86f25c3004b61b63ba1eef9adea41d34fb8_scalar_stack\",\n \"viewer_ndim\": 7,\n \"current_step\": [\n 0,\n 1,\n 0,\n 0,\n 0,\n 15,\n 15\n ],\n \"axis_labels\": [\n \"site\",\n \"channel\",\n \"z_index\",\n \"timepoint\",\n \"well\",\n \"y\",\n \"x\"\n ],\n \"component_group_count\": 3,\n \"component_item_count\": 4\n }\n}" + } + ], + "structuredContent": { + "connection": { + "host": "127.0.0.1", + "port": 6609, + "transport_mode": "tcp", + "persistent": true + }, + "schema_version": "openhcs.agent.v1", + "errors": [], + "warnings": [], + "observed": true, + "viewer": { + "viewer_type": "napari", + "title": "OpenHCS Napari Visualization" + }, + "layer_count": 3, + "layers": [ + { + "route_key": "origin_manual_kind_manual_projection_selected_images_8c7357d46ccc38823ca9e68096baf86f25c3004b61b63ba1eef9adea41d34fb8_scalar_stack", + "title": "selected_images image stack", + "mounted": true, + "item_count": 1, + "producer_identities": [ + { + "origin": "manual", + "output_kind": "manual", + "output_key": "selected_images", + "projection_key": "selected_images_8c7357d46ccc38823ca9e68096baf86f25c3004b61b63ba1eef9adea41d34fb8", + "step_name": null, + "pipeline_position": null, + "step_scope_id": null, + "invocation_key": null, + "artifact_kind": null + } + ], + "axis_labels": [ + "site", + "channel", + "z_index", + "timepoint", + "well", + "y", + "x" + ], + "stack_axes": [ + "channel" + ], + "pending_update": false, + "data_types": [ + "image" + ], + "component_values": [ + { + "site": 1, + "z_index": 1, + "timepoint": 1, + "well": "A01" + } + ], + "component_value_count": 1, + "component_values_truncated": false, + "payload_summaries": [ + { + "shape": [ + 2, + 32, + 32 + ], + "dtype": "uint16", + "size": 2048, + "nonzero_count": 308, + "min": 0, + "max": 22, + "nonzero_min_coordinate": [ + 0, + 3, + 4 + ], + "nonzero_max_coordinate": [ + 1, + 24, + 27 + ], + "nonzero_example_coordinates": [ + [ + 0, + 3, + 4 + ], + [ + 0, + 5, + 4 + ], + [ + 0, + 7, + 4 + ], + [ + 0, + 9, + 5 + ], + [ + 0, + 11, + 5 + ], + [ + 0, + 18, + 24 + ], + [ + 0, + 21, + 20 + ], + [ + 0, + 23, + 25 + ], + [ + 1, + 3, + 13 + ], + [ + 1, + 6, + 4 + ], + [ + 1, + 8, + 4 + ], + [ + 1, + 10, + 5 + ], + [ + 1, + 17, + 21 + ], + [ + 1, + 19, + 26 + ], + [ + 1, + 22, + 22 + ], + [ + 1, + 24, + 27 + ] + ], + "source_voxel_spacing": { + "values_zyx": [ + 1.3556, + 1.3556 + ], + "unit": "micrometers" + }, + "spatial_origin_yx": [ + 0, + 0 + ], + "source_spatial_shape_yx": [ + 32, + 32 + ], + "aggregate_component_values": { + "channel": [ + 2, + 1 + ] + }, + "data_type": "image", + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/stacked_labels/A01_s001_w2_z001_t001_Labels.tif", + "components": { + "site": 1, + "z_index": 1, + "timepoint": 1, + "well": "A01" + }, + "payload_type": "ndarray" + } + ], + "payload_summary_count": 1, + "payload_summaries_truncated": false, + "axis_offsets": [ + 0 + ], + "scalar_labels": [ + "Site 1", + "Z 1", + "T 1", + "Well A01" + ], + "labels": { + "channel": [ + "Ch 1", + "Ch 2" + ] + }, + "axis_component_values": { + "channel": [ + 1, + 2 + ] + }, + "routed_component_values": { + "channel": [ + 1, + 2 + ] + }, + "routed_component_coordinates": [ + [ + 1 + ], + [ + 2 + ] + ], + "data_shape": [ + 1, + 2, + 1, + 1, + 1, + 32, + 32 + ], + "native_transform": { + "scale": [ + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.3556, + 1.3556 + ], + "translate": [ + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0 + ] + }, + "native_intensity": { + "contrast_limits": [ + 0.0, + 22.0 + ], + "gamma": 1.0 + }, + "visible": true, + "selected": true, + "feature_row_count": 0, + "selected_data_indices": [] + }, + { + "route_key": "origin_manual_kind_manual_projection_selected_images_e83ddc2185a63aca4b85ec471143f61c8f4eabdb08df3557ca21f2bddcda60b9", + "title": "selected_images", + "mounted": true, + "item_count": 2, + "producer_identities": [ + { + "origin": "manual", + "output_kind": "manual", + "output_key": "selected_images", + "projection_key": "selected_images_e83ddc2185a63aca4b85ec471143f61c8f4eabdb08df3557ca21f2bddcda60b9", + "step_name": null, + "pipeline_position": null, + "step_scope_id": null, + "invocation_key": null, + "artifact_kind": null + } + ], + "axis_labels": [ + "site", + "channel", + "z_index", + "timepoint", + "well", + "y", + "x" + ], + "stack_axes": [ + "channel" + ], + "pending_update": false, + "data_types": [ + "image" + ], + "component_values": [ + { + "site": 1, + "channel": 1, + "z_index": 1, + "timepoint": 1, + "well": "A01" + }, + { + "site": 1, + "channel": 2, + "z_index": 1, + "timepoint": 1, + "well": "A01" + } + ], + "component_value_count": 2, + "component_values_truncated": false, + "payload_summaries": [ + { + "shape": [ + 32, + 32 + ], + "dtype": "uint16", + "size": 1024, + "nonzero_count": 1024, + "min": 100, + "max": 1123, + "nonzero_min_coordinate": [ + 0, + 0 + ], + "nonzero_max_coordinate": [ + 31, + 31 + ], + "nonzero_example_coordinates": [ + [ + 0, + 0 + ], + [ + 2, + 4 + ], + [ + 4, + 8 + ], + [ + 6, + 12 + ], + [ + 8, + 16 + ], + [ + 10, + 21 + ], + [ + 12, + 25 + ], + [ + 14, + 29 + ], + [ + 17, + 1 + ], + [ + 19, + 5 + ], + [ + 21, + 10 + ], + [ + 23, + 14 + ], + [ + 25, + 18 + ], + [ + 27, + 22 + ], + [ + 29, + 26 + ], + [ + 31, + 31 + ] + ], + "source_voxel_spacing": { + "values_zyx": [ + 1.3556, + 1.3556 + ], + "unit": "micrometers" + }, + "spatial_origin_yx": [ + 0, + 0 + ], + "source_spatial_shape_yx": [ + 32, + 32 + ], + "data_type": "image", + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w1_z001_t001.tif", + "components": { + "site": 1, + "channel": 1, + "z_index": 1, + "timepoint": 1, + "well": "A01" + }, + "payload_type": "ndarray" + }, + { + "shape": [ + 32, + 32 + ], + "dtype": "uint16", + "size": 1024, + "nonzero_count": 1024, + "min": 200, + "max": 1223, + "nonzero_min_coordinate": [ + 0, + 0 + ], + "nonzero_max_coordinate": [ + 31, + 31 + ], + "nonzero_example_coordinates": [ + [ + 0, + 0 + ], + [ + 2, + 4 + ], + [ + 4, + 8 + ], + [ + 6, + 12 + ], + [ + 8, + 16 + ], + [ + 10, + 21 + ], + [ + 12, + 25 + ], + [ + 14, + 29 + ], + [ + 17, + 1 + ], + [ + 19, + 5 + ], + [ + 21, + 10 + ], + [ + 23, + 14 + ], + [ + 25, + 18 + ], + [ + 27, + 22 + ], + [ + 29, + 26 + ], + [ + 31, + 31 + ] + ], + "source_voxel_spacing": { + "values_zyx": [ + 1.3556, + 1.3556 + ], + "unit": "micrometers" + }, + "spatial_origin_yx": [ + 0, + 0 + ], + "source_spatial_shape_yx": [ + 32, + 32 + ], + "data_type": "image", + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w2_z001_t001.tif", + "components": { + "site": 1, + "channel": 2, + "z_index": 1, + "timepoint": 1, + "well": "A01" + }, + "payload_type": "ndarray" + } + ], + "payload_summary_count": 2, + "payload_summaries_truncated": false, + "axis_offsets": [ + 0 + ], + "scalar_labels": [ + "Site 1", + "Z 1", + "T 1", + "Well A01" + ], + "labels": { + "channel": [ + "Ch 1", + "Ch 2" + ] + }, + "axis_component_values": { + "channel": [ + 1, + 2 + ] + }, + "routed_component_values": { + "channel": [ + 1, + 2 + ] + }, + "routed_component_coordinates": [ + [ + 1 + ], + [ + 2 + ] + ], + "data_shape": [ + 1, + 2, + 1, + 1, + 1, + 32, + 32 + ], + "native_transform": { + "scale": [ + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.3556, + 1.3556 + ], + "translate": [ + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0 + ] + }, + "native_intensity": { + "contrast_limits": [ + 100.0, + 1223.0 + ], + "gamma": 1.0 + }, + "visible": false, + "selected": false, + "feature_row_count": 0, + "selected_data_indices": [] + }, + { + "route_key": "origin_manual_kind_manual_projection_A01_s001_w2_z001_t001_graph.graph.roi.zip_shapes", + "title": "A01_s001_w2_z001_t001_graph.graph.roi.zip ROIs", + "mounted": true, + "item_count": 1, + "producer_identities": [ + { + "origin": "manual", + "output_kind": "manual", + "output_key": "A01_s001_w2_z001_t001_graph.graph.roi.zip", + "projection_key": "A01_s001_w2_z001_t001_graph.graph.roi.zip", + "step_name": null, + "pipeline_position": null, + "step_scope_id": null, + "invocation_key": null, + "artifact_kind": null + } + ], + "axis_labels": [ + "site", + "channel", + "z_index", + "timepoint", + "well", + "y", + "x" + ], + "stack_axes": [ + "channel" + ], + "pending_update": false, + "data_types": [ + "shapes" + ], + "component_values": [ + { + "site": 1, + "channel": 2, + "z_index": 1, + "timepoint": 1, + "well": "A01" + } + ], + "component_value_count": 1, + "component_values_truncated": false, + "payload_summaries": [ + { + "nonzero_count": 2, + "item_count": 2, + "shape_payload_count": 2, + "missing_source_spatial_shape_count": 2, + "shape_coordinate_count": 4, + "shape_out_of_source_bounds_count": 0, + "shape_coordinate_bounds_yx": { + "min_yx": [ + 2.25, + 3.5 + ], + "max_yx": [ + 7.25, + 12.5 + ], + "coordinate_count": 4 + }, + "source_voxel_spacing": { + "values_zyx": [ + 1.3556, + 1.3556 + ], + "unit": "micrometers" + }, + "data_type": "shapes", + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/graph_results/A01_s001_w2_z001_t001_graph.graph.roi.zip", + "components": { + "site": 1, + "channel": 2, + "z_index": 1, + "timepoint": 1, + "well": "A01" + }, + "payload_type": "list" + } + ], + "payload_summary_count": 1, + "payload_summaries_truncated": false, + "axis_offsets": [ + 1 + ], + "scalar_labels": [ + "Site 1", + "Z 1", + "T 1", + "Well A01" + ], + "labels": { + "channel": [ + "Ch 2" + ] + }, + "axis_component_values": { + "channel": [ + 2 + ] + }, + "routed_component_values": { + "channel": [ + 2 + ] + }, + "routed_component_coordinates": [ + [ + 2 + ] + ], + "data_shape": [ + 2 + ], + "native_transform": { + "scale": [ + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.3556, + 1.3556 + ], + "translate": [ + 0.0, + 1.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0 + ] + }, + "native_intensity": null, + "visible": true, + "selected": false, + "feature_row_count": 2, + "selected_data_indices": [] + } + ], + "active_dimension_label_route": "origin_manual_kind_manual_projection_selected_images_8c7357d46ccc38823ca9e68096baf86f25c3004b61b63ba1eef9adea41d34fb8_scalar_stack", + "viewer_ndim": 7, + "current_step": [ + 0, + 1, + 0, + 0, + 0, + 15, + 15 + ], + "axis_labels": [ + "site", + "channel", + "z_index", + "timepoint", + "well", + "y", + "x" + ], + "component_group_count": 3, + "component_item_count": 4, + "native_viewport": { + "center": [ + 0.0, + 21.011799999999997, + 21.011799999999997 + ], + "zoom": 6.635668707583358 + }, + "native_dimensions": { + "order": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6 + ], + "ndisplay": 2, + "displayed_axes": [ + "y", + "x" + ], + "point": [ + 0.0, + 1.0, + 0.0, + 0.0, + 0.0, + 20.334, + 20.334 + ], + "camera_angles": [ + 0.0, + 0.0, + 0.0 + ], + "canvas_size": [ + 643, + 478 + ] + }, + "response": { + "type": "state_ack", + "status": "success", + "viewer": { + "type": "napari", + "title": "OpenHCS Napari Visualization" + }, + "layer_count": 3, + "layers": [ + { + "route_key": "origin_manual_kind_manual_projection_selected_images_8c7357d46ccc38823ca9e68096baf86f25c3004b61b63ba1eef9adea41d34fb8_scalar_stack", + "producer_identities": [ + { + "origin": "manual", + "output_kind": "manual", + "output_key": "selected_images", + "projection_key": "selected_images_8c7357d46ccc38823ca9e68096baf86f25c3004b61b63ba1eef9adea41d34fb8", + "step_name": null, + "pipeline_position": null, + "step_scope_id": null, + "invocation_key": null, + "artifact_kind": null + } + ], + "title": "selected_images image stack", + "mounted": true, + "item_count": 1, + "data_types": [ + "image" + ], + "component_values": [ + { + "site": 1, + "z_index": 1, + "timepoint": 1, + "well": "A01" + } + ], + "component_value_count": 1, + "component_values_truncated": false, + "payload_summaries": [ + { + "shape": [ + 2, + 32, + 32 + ], + "dtype": "uint16", + "size": 2048, + "nonzero_count": 308, + "min": 0, + "max": 22, + "nonzero_min_coordinate": [ + 0, + 3, + 4 + ], + "nonzero_max_coordinate": [ + 1, + 24, + 27 + ], + "nonzero_example_coordinates": [ + [ + 0, + 3, + 4 + ], + [ + 0, + 5, + 4 + ], + [ + 0, + 7, + 4 + ], + [ + 0, + 9, + 5 + ], + [ + 0, + 11, + 5 + ], + [ + 0, + 18, + 24 + ], + [ + 0, + 21, + 20 + ], + [ + 0, + 23, + 25 + ], + [ + 1, + 3, + 13 + ], + [ + 1, + 6, + 4 + ], + [ + 1, + 8, + 4 + ], + [ + 1, + 10, + 5 + ], + [ + 1, + 17, + 21 + ], + [ + 1, + 19, + 26 + ], + [ + 1, + 22, + 22 + ], + [ + 1, + 24, + 27 + ] + ], + "source_voxel_spacing": { + "values_zyx": [ + 1.3556, + 1.3556 + ], + "unit": "micrometers" + }, + "spatial_origin_yx": [ + 0, + 0 + ], + "source_spatial_shape_yx": [ + 32, + 32 + ], + "aggregate_component_values": { + "channel": [ + 2, + 1 + ] + }, + "data_type": "image", + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/stacked_labels/A01_s001_w2_z001_t001_Labels.tif", + "components": { + "site": 1, + "z_index": 1, + "timepoint": 1, + "well": "A01" + }, + "payload_type": "ndarray" + } + ], + "payload_summary_count": 1, + "payload_summaries_truncated": false, + "axis_labels": [ + "site", + "channel", + "z_index", + "timepoint", + "well", + "y", + "x" + ], + "stack_axes": [ + "channel" + ], + "axis_offsets": [ + 0 + ], + "scalar_labels": [ + "Site 1", + "Z 1", + "T 1", + "Well A01" + ], + "labels": { + "channel": [ + "Ch 1", + "Ch 2" + ] + }, + "axis_component_values": { + "channel": [ + 1, + 2 + ] + }, + "routed_component_values": { + "channel": [ + 1, + 2 + ] + }, + "routed_component_coordinates": [ + [ + 1 + ], + [ + 2 + ] + ], + "data_shape": [ + 1, + 2, + 1, + 1, + 1, + 32, + 32 + ], + "native_transform": { + "scale": [ + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.3556, + 1.3556 + ], + "translate": [ + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0 + ] + }, + "native_intensity": { + "contrast_limits": [ + 0.0, + 22.0 + ], + "gamma": 1.0 + }, + "visible": true, + "selected": true, + "feature_row_count": 0, + "selected_data_indices": [], + "pending_update": false + }, + { + "route_key": "origin_manual_kind_manual_projection_selected_images_e83ddc2185a63aca4b85ec471143f61c8f4eabdb08df3557ca21f2bddcda60b9", + "producer_identities": [ + { + "origin": "manual", + "output_kind": "manual", + "output_key": "selected_images", + "projection_key": "selected_images_e83ddc2185a63aca4b85ec471143f61c8f4eabdb08df3557ca21f2bddcda60b9", + "step_name": null, + "pipeline_position": null, + "step_scope_id": null, + "invocation_key": null, + "artifact_kind": null + } + ], + "title": "selected_images", + "mounted": true, + "item_count": 2, + "data_types": [ + "image" + ], + "component_values": [ + { + "site": 1, + "channel": 1, + "z_index": 1, + "timepoint": 1, + "well": "A01" + }, + { + "site": 1, + "channel": 2, + "z_index": 1, + "timepoint": 1, + "well": "A01" + } + ], + "component_value_count": 2, + "component_values_truncated": false, + "payload_summaries": [ + { + "shape": [ + 32, + 32 + ], + "dtype": "uint16", + "size": 1024, + "nonzero_count": 1024, + "min": 100, + "max": 1123, + "nonzero_min_coordinate": [ + 0, + 0 + ], + "nonzero_max_coordinate": [ + 31, + 31 + ], + "nonzero_example_coordinates": [ + [ + 0, + 0 + ], + [ + 2, + 4 + ], + [ + 4, + 8 + ], + [ + 6, + 12 + ], + [ + 8, + 16 + ], + [ + 10, + 21 + ], + [ + 12, + 25 + ], + [ + 14, + 29 + ], + [ + 17, + 1 + ], + [ + 19, + 5 + ], + [ + 21, + 10 + ], + [ + 23, + 14 + ], + [ + 25, + 18 + ], + [ + 27, + 22 + ], + [ + 29, + 26 + ], + [ + 31, + 31 + ] + ], + "source_voxel_spacing": { + "values_zyx": [ + 1.3556, + 1.3556 + ], + "unit": "micrometers" + }, + "spatial_origin_yx": [ + 0, + 0 + ], + "source_spatial_shape_yx": [ + 32, + 32 + ], + "data_type": "image", + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w1_z001_t001.tif", + "components": { + "site": 1, + "channel": 1, + "z_index": 1, + "timepoint": 1, + "well": "A01" + }, + "payload_type": "ndarray" + }, + { + "shape": [ + 32, + 32 + ], + "dtype": "uint16", + "size": 1024, + "nonzero_count": 1024, + "min": 200, + "max": 1223, + "nonzero_min_coordinate": [ + 0, + 0 + ], + "nonzero_max_coordinate": [ + 31, + 31 + ], + "nonzero_example_coordinates": [ + [ + 0, + 0 + ], + [ + 2, + 4 + ], + [ + 4, + 8 + ], + [ + 6, + 12 + ], + [ + 8, + 16 + ], + [ + 10, + 21 + ], + [ + 12, + 25 + ], + [ + 14, + 29 + ], + [ + 17, + 1 + ], + [ + 19, + 5 + ], + [ + 21, + 10 + ], + [ + 23, + 14 + ], + [ + 25, + 18 + ], + [ + 27, + 22 + ], + [ + 29, + 26 + ], + [ + 31, + 31 + ] + ], + "source_voxel_spacing": { + "values_zyx": [ + 1.3556, + 1.3556 + ], + "unit": "micrometers" + }, + "spatial_origin_yx": [ + 0, + 0 + ], + "source_spatial_shape_yx": [ + 32, + 32 + ], + "data_type": "image", + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w2_z001_t001.tif", + "components": { + "site": 1, + "channel": 2, + "z_index": 1, + "timepoint": 1, + "well": "A01" + }, + "payload_type": "ndarray" + } + ], + "payload_summary_count": 2, + "payload_summaries_truncated": false, + "axis_labels": [ + "site", + "channel", + "z_index", + "timepoint", + "well", + "y", + "x" + ], + "stack_axes": [ + "channel" + ], + "axis_offsets": [ + 0 + ], + "scalar_labels": [ + "Site 1", + "Z 1", + "T 1", + "Well A01" + ], + "labels": { + "channel": [ + "Ch 1", + "Ch 2" + ] + }, + "axis_component_values": { + "channel": [ + 1, + 2 + ] + }, + "routed_component_values": { + "channel": [ + 1, + 2 + ] + }, + "routed_component_coordinates": [ + [ + 1 + ], + [ + 2 + ] + ], + "data_shape": [ + 1, + 2, + 1, + 1, + 1, + 32, + 32 + ], + "native_transform": { + "scale": [ + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.3556, + 1.3556 + ], + "translate": [ + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0 + ] + }, + "native_intensity": { + "contrast_limits": [ + 100.0, + 1223.0 + ], + "gamma": 1.0 + }, + "visible": false, + "selected": false, + "feature_row_count": 0, + "selected_data_indices": [], + "pending_update": false + }, + { + "route_key": "origin_manual_kind_manual_projection_A01_s001_w2_z001_t001_graph.graph.roi.zip_shapes", + "producer_identities": [ + { + "origin": "manual", + "output_kind": "manual", + "output_key": "A01_s001_w2_z001_t001_graph.graph.roi.zip", + "projection_key": "A01_s001_w2_z001_t001_graph.graph.roi.zip", + "step_name": null, + "pipeline_position": null, + "step_scope_id": null, + "invocation_key": null, + "artifact_kind": null + } + ], + "title": "A01_s001_w2_z001_t001_graph.graph.roi.zip ROIs", + "mounted": true, + "item_count": 1, + "data_types": [ + "shapes" + ], + "component_values": [ + { + "site": 1, + "channel": 2, + "z_index": 1, + "timepoint": 1, + "well": "A01" + } + ], + "component_value_count": 1, + "component_values_truncated": false, + "payload_summaries": [ + { + "nonzero_count": 2, + "item_count": 2, + "shape_payload_count": 2, + "missing_source_spatial_shape_count": 2, + "shape_coordinate_count": 4, + "shape_out_of_source_bounds_count": 0, + "shape_coordinate_bounds_yx": { + "min_yx": [ + 2.25, + 3.5 + ], + "max_yx": [ + 7.25, + 12.5 + ], + "coordinate_count": 4 + }, + "source_voxel_spacing": { + "values_zyx": [ + 1.3556, + 1.3556 + ], + "unit": "micrometers" + }, + "data_type": "shapes", + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/graph_results/A01_s001_w2_z001_t001_graph.graph.roi.zip", + "components": { + "site": 1, + "channel": 2, + "z_index": 1, + "timepoint": 1, + "well": "A01" + }, + "payload_type": "list" + } + ], + "payload_summary_count": 1, + "payload_summaries_truncated": false, + "axis_labels": [ + "site", + "channel", + "z_index", + "timepoint", + "well", + "y", + "x" + ], + "stack_axes": [ + "channel" + ], + "axis_offsets": [ + 1 + ], + "scalar_labels": [ + "Site 1", + "Z 1", + "T 1", + "Well A01" + ], + "labels": { + "channel": [ + "Ch 2" + ] + }, + "axis_component_values": { + "channel": [ + 2 + ] + }, + "routed_component_values": { + "channel": [ + 2 + ] + }, + "routed_component_coordinates": [ + [ + 2 + ] + ], + "data_shape": [ + 2 + ], + "native_transform": { + "scale": [ + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.3556, + 1.3556 + ], + "translate": [ + 0.0, + 1.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0 + ] + }, + "native_intensity": null, + "visible": true, + "selected": false, + "feature_row_count": 2, + "selected_data_indices": [], + "pending_update": false + } + ], + "native_viewport": { + "center": [ + 0.0, + 21.011799999999997, + 21.011799999999997 + ], + "zoom": 6.635668707583358 + }, + "native_dimensions": { + "order": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6 + ], + "ndisplay": 2, + "displayed_axes": [ + "y", + "x" + ], + "point": [ + 0.0, + 1.0, + 0.0, + 0.0, + 0.0, + 20.334, + 20.334 + ], + "camera_angles": [ + 0.0, + 0.0, + 0.0 + ], + "canvas_size": [ + 643, + 478 + ] + }, + "active_dimension_label_route": "origin_manual_kind_manual_projection_selected_images_8c7357d46ccc38823ca9e68096baf86f25c3004b61b63ba1eef9adea41d34fb8_scalar_stack", + "viewer_ndim": 7, + "current_step": [ + 0, + 1, + 0, + 0, + 0, + 15, + 15 + ], + "axis_labels": [ + "site", + "channel", + "z_index", + "timepoint", + "well", + "y", + "x" + ], + "component_group_count": 3, + "component_item_count": 4 + } + }, + "isError": false + }, + "payload": { + "connection": { + "host": "127.0.0.1", + "port": 6609, + "transport_mode": "tcp", + "persistent": true + }, + "schema_version": "openhcs.agent.v1", + "errors": [], + "warnings": [], + "observed": true, + "viewer": { + "viewer_type": "napari", + "title": "OpenHCS Napari Visualization" + }, + "layer_count": 3, + "layers": [ + { + "route_key": "origin_manual_kind_manual_projection_selected_images_8c7357d46ccc38823ca9e68096baf86f25c3004b61b63ba1eef9adea41d34fb8_scalar_stack", + "title": "selected_images image stack", + "mounted": true, + "item_count": 1, + "producer_identities": [ + { + "origin": "manual", + "output_kind": "manual", + "output_key": "selected_images", + "projection_key": "selected_images_8c7357d46ccc38823ca9e68096baf86f25c3004b61b63ba1eef9adea41d34fb8", + "step_name": null, + "pipeline_position": null, + "step_scope_id": null, + "invocation_key": null, + "artifact_kind": null + } + ], + "axis_labels": [ + "site", + "channel", + "z_index", + "timepoint", + "well", + "y", + "x" + ], + "stack_axes": [ + "channel" + ], + "pending_update": false, + "data_types": [ + "image" + ], + "component_values": [ + { + "site": 1, + "z_index": 1, + "timepoint": 1, + "well": "A01" + } + ], + "component_value_count": 1, + "component_values_truncated": false, + "payload_summaries": [ + { + "shape": [ + 2, + 32, + 32 + ], + "dtype": "uint16", + "size": 2048, + "nonzero_count": 308, + "min": 0, + "max": 22, + "nonzero_min_coordinate": [ + 0, + 3, + 4 + ], + "nonzero_max_coordinate": [ + 1, + 24, + 27 + ], + "nonzero_example_coordinates": [ + [ + 0, + 3, + 4 + ], + [ + 0, + 5, + 4 + ], + [ + 0, + 7, + 4 + ], + [ + 0, + 9, + 5 + ], + [ + 0, + 11, + 5 + ], + [ + 0, + 18, + 24 + ], + [ + 0, + 21, + 20 + ], + [ + 0, + 23, + 25 + ], + [ + 1, + 3, + 13 + ], + [ + 1, + 6, + 4 + ], + [ + 1, + 8, + 4 + ], + [ + 1, + 10, + 5 + ], + [ + 1, + 17, + 21 + ], + [ + 1, + 19, + 26 + ], + [ + 1, + 22, + 22 + ], + [ + 1, + 24, + 27 + ] + ], + "source_voxel_spacing": { + "values_zyx": [ + 1.3556, + 1.3556 + ], + "unit": "micrometers" + }, + "spatial_origin_yx": [ + 0, + 0 + ], + "source_spatial_shape_yx": [ + 32, + 32 + ], + "aggregate_component_values": { + "channel": [ + 2, + 1 + ] + }, + "data_type": "image", + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/stacked_labels/A01_s001_w2_z001_t001_Labels.tif", + "components": { + "site": 1, + "z_index": 1, + "timepoint": 1, + "well": "A01" + }, + "payload_type": "ndarray" + } + ], + "payload_summary_count": 1, + "payload_summaries_truncated": false, + "axis_offsets": [ + 0 + ], + "scalar_labels": [ + "Site 1", + "Z 1", + "T 1", + "Well A01" + ], + "labels": { + "channel": [ + "Ch 1", + "Ch 2" + ] + }, + "axis_component_values": { + "channel": [ + 1, + 2 + ] + }, + "routed_component_values": { + "channel": [ + 1, + 2 + ] + }, + "routed_component_coordinates": [ + [ + 1 + ], + [ + 2 + ] + ], + "data_shape": [ + 1, + 2, + 1, + 1, + 1, + 32, + 32 + ], + "native_transform": { + "scale": [ + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.3556, + 1.3556 + ], + "translate": [ + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0 + ] + }, + "native_intensity": { + "contrast_limits": [ + 0.0, + 22.0 + ], + "gamma": 1.0 + }, + "visible": true, + "selected": true, + "feature_row_count": 0, + "selected_data_indices": [] + }, + { + "route_key": "origin_manual_kind_manual_projection_selected_images_e83ddc2185a63aca4b85ec471143f61c8f4eabdb08df3557ca21f2bddcda60b9", + "title": "selected_images", + "mounted": true, + "item_count": 2, + "producer_identities": [ + { + "origin": "manual", + "output_kind": "manual", + "output_key": "selected_images", + "projection_key": "selected_images_e83ddc2185a63aca4b85ec471143f61c8f4eabdb08df3557ca21f2bddcda60b9", + "step_name": null, + "pipeline_position": null, + "step_scope_id": null, + "invocation_key": null, + "artifact_kind": null + } + ], + "axis_labels": [ + "site", + "channel", + "z_index", + "timepoint", + "well", + "y", + "x" + ], + "stack_axes": [ + "channel" + ], + "pending_update": false, + "data_types": [ + "image" + ], + "component_values": [ + { + "site": 1, + "channel": 1, + "z_index": 1, + "timepoint": 1, + "well": "A01" + }, + { + "site": 1, + "channel": 2, + "z_index": 1, + "timepoint": 1, + "well": "A01" + } + ], + "component_value_count": 2, + "component_values_truncated": false, + "payload_summaries": [ + { + "shape": [ + 32, + 32 + ], + "dtype": "uint16", + "size": 1024, + "nonzero_count": 1024, + "min": 100, + "max": 1123, + "nonzero_min_coordinate": [ + 0, + 0 + ], + "nonzero_max_coordinate": [ + 31, + 31 + ], + "nonzero_example_coordinates": [ + [ + 0, + 0 + ], + [ + 2, + 4 + ], + [ + 4, + 8 + ], + [ + 6, + 12 + ], + [ + 8, + 16 + ], + [ + 10, + 21 + ], + [ + 12, + 25 + ], + [ + 14, + 29 + ], + [ + 17, + 1 + ], + [ + 19, + 5 + ], + [ + 21, + 10 + ], + [ + 23, + 14 + ], + [ + 25, + 18 + ], + [ + 27, + 22 + ], + [ + 29, + 26 + ], + [ + 31, + 31 + ] + ], + "source_voxel_spacing": { + "values_zyx": [ + 1.3556, + 1.3556 + ], + "unit": "micrometers" + }, + "spatial_origin_yx": [ + 0, + 0 + ], + "source_spatial_shape_yx": [ + 32, + 32 + ], + "data_type": "image", + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w1_z001_t001.tif", + "components": { + "site": 1, + "channel": 1, + "z_index": 1, + "timepoint": 1, + "well": "A01" + }, + "payload_type": "ndarray" + }, + { + "shape": [ + 32, + 32 + ], + "dtype": "uint16", + "size": 1024, + "nonzero_count": 1024, + "min": 200, + "max": 1223, + "nonzero_min_coordinate": [ + 0, + 0 + ], + "nonzero_max_coordinate": [ + 31, + 31 + ], + "nonzero_example_coordinates": [ + [ + 0, + 0 + ], + [ + 2, + 4 + ], + [ + 4, + 8 + ], + [ + 6, + 12 + ], + [ + 8, + 16 + ], + [ + 10, + 21 + ], + [ + 12, + 25 + ], + [ + 14, + 29 + ], + [ + 17, + 1 + ], + [ + 19, + 5 + ], + [ + 21, + 10 + ], + [ + 23, + 14 + ], + [ + 25, + 18 + ], + [ + 27, + 22 + ], + [ + 29, + 26 + ], + [ + 31, + 31 + ] + ], + "source_voxel_spacing": { + "values_zyx": [ + 1.3556, + 1.3556 + ], + "unit": "micrometers" + }, + "spatial_origin_yx": [ + 0, + 0 + ], + "source_spatial_shape_yx": [ + 32, + 32 + ], + "data_type": "image", + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w2_z001_t001.tif", + "components": { + "site": 1, + "channel": 2, + "z_index": 1, + "timepoint": 1, + "well": "A01" + }, + "payload_type": "ndarray" + } + ], + "payload_summary_count": 2, + "payload_summaries_truncated": false, + "axis_offsets": [ + 0 + ], + "scalar_labels": [ + "Site 1", + "Z 1", + "T 1", + "Well A01" + ], + "labels": { + "channel": [ + "Ch 1", + "Ch 2" + ] + }, + "axis_component_values": { + "channel": [ + 1, + 2 + ] + }, + "routed_component_values": { + "channel": [ + 1, + 2 + ] + }, + "routed_component_coordinates": [ + [ + 1 + ], + [ + 2 + ] + ], + "data_shape": [ + 1, + 2, + 1, + 1, + 1, + 32, + 32 + ], + "native_transform": { + "scale": [ + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.3556, + 1.3556 + ], + "translate": [ + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0 + ] + }, + "native_intensity": { + "contrast_limits": [ + 100.0, + 1223.0 + ], + "gamma": 1.0 + }, + "visible": false, + "selected": false, + "feature_row_count": 0, + "selected_data_indices": [] + }, + { + "route_key": "origin_manual_kind_manual_projection_A01_s001_w2_z001_t001_graph.graph.roi.zip_shapes", + "title": "A01_s001_w2_z001_t001_graph.graph.roi.zip ROIs", + "mounted": true, + "item_count": 1, + "producer_identities": [ + { + "origin": "manual", + "output_kind": "manual", + "output_key": "A01_s001_w2_z001_t001_graph.graph.roi.zip", + "projection_key": "A01_s001_w2_z001_t001_graph.graph.roi.zip", + "step_name": null, + "pipeline_position": null, + "step_scope_id": null, + "invocation_key": null, + "artifact_kind": null + } + ], + "axis_labels": [ + "site", + "channel", + "z_index", + "timepoint", + "well", + "y", + "x" + ], + "stack_axes": [ + "channel" + ], + "pending_update": false, + "data_types": [ + "shapes" + ], + "component_values": [ + { + "site": 1, + "channel": 2, + "z_index": 1, + "timepoint": 1, + "well": "A01" + } + ], + "component_value_count": 1, + "component_values_truncated": false, + "payload_summaries": [ + { + "nonzero_count": 2, + "item_count": 2, + "shape_payload_count": 2, + "missing_source_spatial_shape_count": 2, + "shape_coordinate_count": 4, + "shape_out_of_source_bounds_count": 0, + "shape_coordinate_bounds_yx": { + "min_yx": [ + 2.25, + 3.5 + ], + "max_yx": [ + 7.25, + 12.5 + ], + "coordinate_count": 4 + }, + "source_voxel_spacing": { + "values_zyx": [ + 1.3556, + 1.3556 + ], + "unit": "micrometers" + }, + "data_type": "shapes", + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/graph_results/A01_s001_w2_z001_t001_graph.graph.roi.zip", + "components": { + "site": 1, + "channel": 2, + "z_index": 1, + "timepoint": 1, + "well": "A01" + }, + "payload_type": "list" + } + ], + "payload_summary_count": 1, + "payload_summaries_truncated": false, + "axis_offsets": [ + 1 + ], + "scalar_labels": [ + "Site 1", + "Z 1", + "T 1", + "Well A01" + ], + "labels": { + "channel": [ + "Ch 2" + ] + }, + "axis_component_values": { + "channel": [ + 2 + ] + }, + "routed_component_values": { + "channel": [ + 2 + ] + }, + "routed_component_coordinates": [ + [ + 2 + ] + ], + "data_shape": [ + 2 + ], + "native_transform": { + "scale": [ + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.3556, + 1.3556 + ], + "translate": [ + 0.0, + 1.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0 + ] + }, + "native_intensity": null, + "visible": true, + "selected": false, + "feature_row_count": 2, + "selected_data_indices": [] + } + ], + "active_dimension_label_route": "origin_manual_kind_manual_projection_selected_images_8c7357d46ccc38823ca9e68096baf86f25c3004b61b63ba1eef9adea41d34fb8_scalar_stack", + "viewer_ndim": 7, + "current_step": [ + 0, + 1, + 0, + 0, + 0, + 15, + 15 + ], + "axis_labels": [ + "site", + "channel", + "z_index", + "timepoint", + "well", + "y", + "x" + ], + "component_group_count": 3, + "component_item_count": 4, + "native_viewport": { + "center": [ + 0.0, + 21.011799999999997, + 21.011799999999997 + ], + "zoom": 6.635668707583358 + }, + "native_dimensions": { + "order": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6 + ], + "ndisplay": 2, + "displayed_axes": [ + "y", + "x" + ], + "point": [ + 0.0, + 1.0, + 0.0, + 0.0, + 0.0, + 20.334, + 20.334 + ], + "camera_angles": [ + 0.0, + 0.0, + 0.0 + ], + "canvas_size": [ + 643, + 478 + ] + }, + "response": { + "type": "state_ack", + "status": "success", + "viewer": { + "type": "napari", + "title": "OpenHCS Napari Visualization" + }, + "layer_count": 3, + "layers": [ + { + "route_key": "origin_manual_kind_manual_projection_selected_images_8c7357d46ccc38823ca9e68096baf86f25c3004b61b63ba1eef9adea41d34fb8_scalar_stack", + "producer_identities": [ + { + "origin": "manual", + "output_kind": "manual", + "output_key": "selected_images", + "projection_key": "selected_images_8c7357d46ccc38823ca9e68096baf86f25c3004b61b63ba1eef9adea41d34fb8", + "step_name": null, + "pipeline_position": null, + "step_scope_id": null, + "invocation_key": null, + "artifact_kind": null + } + ], + "title": "selected_images image stack", + "mounted": true, + "item_count": 1, + "data_types": [ + "image" + ], + "component_values": [ + { + "site": 1, + "z_index": 1, + "timepoint": 1, + "well": "A01" + } + ], + "component_value_count": 1, + "component_values_truncated": false, + "payload_summaries": [ + { + "shape": [ + 2, + 32, + 32 + ], + "dtype": "uint16", + "size": 2048, + "nonzero_count": 308, + "min": 0, + "max": 22, + "nonzero_min_coordinate": [ + 0, + 3, + 4 + ], + "nonzero_max_coordinate": [ + 1, + 24, + 27 + ], + "nonzero_example_coordinates": [ + [ + 0, + 3, + 4 + ], + [ + 0, + 5, + 4 + ], + [ + 0, + 7, + 4 + ], + [ + 0, + 9, + 5 + ], + [ + 0, + 11, + 5 + ], + [ + 0, + 18, + 24 + ], + [ + 0, + 21, + 20 + ], + [ + 0, + 23, + 25 + ], + [ + 1, + 3, + 13 + ], + [ + 1, + 6, + 4 + ], + [ + 1, + 8, + 4 + ], + [ + 1, + 10, + 5 + ], + [ + 1, + 17, + 21 + ], + [ + 1, + 19, + 26 + ], + [ + 1, + 22, + 22 + ], + [ + 1, + 24, + 27 + ] + ], + "source_voxel_spacing": { + "values_zyx": [ + 1.3556, + 1.3556 + ], + "unit": "micrometers" + }, + "spatial_origin_yx": [ + 0, + 0 + ], + "source_spatial_shape_yx": [ + 32, + 32 + ], + "aggregate_component_values": { + "channel": [ + 2, + 1 + ] + }, + "data_type": "image", + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/stacked_labels/A01_s001_w2_z001_t001_Labels.tif", + "components": { + "site": 1, + "z_index": 1, + "timepoint": 1, + "well": "A01" + }, + "payload_type": "ndarray" + } + ], + "payload_summary_count": 1, + "payload_summaries_truncated": false, + "axis_labels": [ + "site", + "channel", + "z_index", + "timepoint", + "well", + "y", + "x" + ], + "stack_axes": [ + "channel" + ], + "axis_offsets": [ + 0 + ], + "scalar_labels": [ + "Site 1", + "Z 1", + "T 1", + "Well A01" + ], + "labels": { + "channel": [ + "Ch 1", + "Ch 2" + ] + }, + "axis_component_values": { + "channel": [ + 1, + 2 + ] + }, + "routed_component_values": { + "channel": [ + 1, + 2 + ] + }, + "routed_component_coordinates": [ + [ + 1 + ], + [ + 2 + ] + ], + "data_shape": [ + 1, + 2, + 1, + 1, + 1, + 32, + 32 + ], + "native_transform": { + "scale": [ + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.3556, + 1.3556 + ], + "translate": [ + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0 + ] + }, + "native_intensity": { + "contrast_limits": [ + 0.0, + 22.0 + ], + "gamma": 1.0 + }, + "visible": true, + "selected": true, + "feature_row_count": 0, + "selected_data_indices": [], + "pending_update": false + }, + { + "route_key": "origin_manual_kind_manual_projection_selected_images_e83ddc2185a63aca4b85ec471143f61c8f4eabdb08df3557ca21f2bddcda60b9", + "producer_identities": [ + { + "origin": "manual", + "output_kind": "manual", + "output_key": "selected_images", + "projection_key": "selected_images_e83ddc2185a63aca4b85ec471143f61c8f4eabdb08df3557ca21f2bddcda60b9", + "step_name": null, + "pipeline_position": null, + "step_scope_id": null, + "invocation_key": null, + "artifact_kind": null + } + ], + "title": "selected_images", + "mounted": true, + "item_count": 2, + "data_types": [ + "image" + ], + "component_values": [ + { + "site": 1, + "channel": 1, + "z_index": 1, + "timepoint": 1, + "well": "A01" + }, + { + "site": 1, + "channel": 2, + "z_index": 1, + "timepoint": 1, + "well": "A01" + } + ], + "component_value_count": 2, + "component_values_truncated": false, + "payload_summaries": [ + { + "shape": [ + 32, + 32 + ], + "dtype": "uint16", + "size": 1024, + "nonzero_count": 1024, + "min": 100, + "max": 1123, + "nonzero_min_coordinate": [ + 0, + 0 + ], + "nonzero_max_coordinate": [ + 31, + 31 + ], + "nonzero_example_coordinates": [ + [ + 0, + 0 + ], + [ + 2, + 4 + ], + [ + 4, + 8 + ], + [ + 6, + 12 + ], + [ + 8, + 16 + ], + [ + 10, + 21 + ], + [ + 12, + 25 + ], + [ + 14, + 29 + ], + [ + 17, + 1 + ], + [ + 19, + 5 + ], + [ + 21, + 10 + ], + [ + 23, + 14 + ], + [ + 25, + 18 + ], + [ + 27, + 22 + ], + [ + 29, + 26 + ], + [ + 31, + 31 + ] + ], + "source_voxel_spacing": { + "values_zyx": [ + 1.3556, + 1.3556 + ], + "unit": "micrometers" + }, + "spatial_origin_yx": [ + 0, + 0 + ], + "source_spatial_shape_yx": [ + 32, + 32 + ], + "data_type": "image", + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w1_z001_t001.tif", + "components": { + "site": 1, + "channel": 1, + "z_index": 1, + "timepoint": 1, + "well": "A01" + }, + "payload_type": "ndarray" + }, + { + "shape": [ + 32, + 32 + ], + "dtype": "uint16", + "size": 1024, + "nonzero_count": 1024, + "min": 200, + "max": 1223, + "nonzero_min_coordinate": [ + 0, + 0 + ], + "nonzero_max_coordinate": [ + 31, + 31 + ], + "nonzero_example_coordinates": [ + [ + 0, + 0 + ], + [ + 2, + 4 + ], + [ + 4, + 8 + ], + [ + 6, + 12 + ], + [ + 8, + 16 + ], + [ + 10, + 21 + ], + [ + 12, + 25 + ], + [ + 14, + 29 + ], + [ + 17, + 1 + ], + [ + 19, + 5 + ], + [ + 21, + 10 + ], + [ + 23, + 14 + ], + [ + 25, + 18 + ], + [ + 27, + 22 + ], + [ + 29, + 26 + ], + [ + 31, + 31 + ] + ], + "source_voxel_spacing": { + "values_zyx": [ + 1.3556, + 1.3556 + ], + "unit": "micrometers" + }, + "spatial_origin_yx": [ + 0, + 0 + ], + "source_spatial_shape_yx": [ + 32, + 32 + ], + "data_type": "image", + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w2_z001_t001.tif", + "components": { + "site": 1, + "channel": 2, + "z_index": 1, + "timepoint": 1, + "well": "A01" + }, + "payload_type": "ndarray" + } + ], + "payload_summary_count": 2, + "payload_summaries_truncated": false, + "axis_labels": [ + "site", + "channel", + "z_index", + "timepoint", + "well", + "y", + "x" + ], + "stack_axes": [ + "channel" + ], + "axis_offsets": [ + 0 + ], + "scalar_labels": [ + "Site 1", + "Z 1", + "T 1", + "Well A01" + ], + "labels": { + "channel": [ + "Ch 1", + "Ch 2" + ] + }, + "axis_component_values": { + "channel": [ + 1, + 2 + ] + }, + "routed_component_values": { + "channel": [ + 1, + 2 + ] + }, + "routed_component_coordinates": [ + [ + 1 + ], + [ + 2 + ] + ], + "data_shape": [ + 1, + 2, + 1, + 1, + 1, + 32, + 32 + ], + "native_transform": { + "scale": [ + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.3556, + 1.3556 + ], + "translate": [ + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0 + ] + }, + "native_intensity": { + "contrast_limits": [ + 100.0, + 1223.0 + ], + "gamma": 1.0 + }, + "visible": false, + "selected": false, + "feature_row_count": 0, + "selected_data_indices": [], + "pending_update": false + }, + { + "route_key": "origin_manual_kind_manual_projection_A01_s001_w2_z001_t001_graph.graph.roi.zip_shapes", + "producer_identities": [ + { + "origin": "manual", + "output_kind": "manual", + "output_key": "A01_s001_w2_z001_t001_graph.graph.roi.zip", + "projection_key": "A01_s001_w2_z001_t001_graph.graph.roi.zip", + "step_name": null, + "pipeline_position": null, + "step_scope_id": null, + "invocation_key": null, + "artifact_kind": null + } + ], + "title": "A01_s001_w2_z001_t001_graph.graph.roi.zip ROIs", + "mounted": true, + "item_count": 1, + "data_types": [ + "shapes" + ], + "component_values": [ + { + "site": 1, + "channel": 2, + "z_index": 1, + "timepoint": 1, + "well": "A01" + } + ], + "component_value_count": 1, + "component_values_truncated": false, + "payload_summaries": [ + { + "nonzero_count": 2, + "item_count": 2, + "shape_payload_count": 2, + "missing_source_spatial_shape_count": 2, + "shape_coordinate_count": 4, + "shape_out_of_source_bounds_count": 0, + "shape_coordinate_bounds_yx": { + "min_yx": [ + 2.25, + 3.5 + ], + "max_yx": [ + 7.25, + 12.5 + ], + "coordinate_count": 4 + }, + "source_voxel_spacing": { + "values_zyx": [ + 1.3556, + 1.3556 + ], + "unit": "micrometers" + }, + "data_type": "shapes", + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/graph_results/A01_s001_w2_z001_t001_graph.graph.roi.zip", + "components": { + "site": 1, + "channel": 2, + "z_index": 1, + "timepoint": 1, + "well": "A01" + }, + "payload_type": "list" + } + ], + "payload_summary_count": 1, + "payload_summaries_truncated": false, + "axis_labels": [ + "site", + "channel", + "z_index", + "timepoint", + "well", + "y", + "x" + ], + "stack_axes": [ + "channel" + ], + "axis_offsets": [ + 1 + ], + "scalar_labels": [ + "Site 1", + "Z 1", + "T 1", + "Well A01" + ], + "labels": { + "channel": [ + "Ch 2" + ] + }, + "axis_component_values": { + "channel": [ + 2 + ] + }, + "routed_component_values": { + "channel": [ + 2 + ] + }, + "routed_component_coordinates": [ + [ + 2 + ] + ], + "data_shape": [ + 2 + ], + "native_transform": { + "scale": [ + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.3556, + 1.3556 + ], + "translate": [ + 0.0, + 1.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0 + ] + }, + "native_intensity": null, + "visible": true, + "selected": false, + "feature_row_count": 2, + "selected_data_indices": [], + "pending_update": false + } + ], + "native_viewport": { + "center": [ + 0.0, + 21.011799999999997, + 21.011799999999997 + ], + "zoom": 6.635668707583358 + }, + "native_dimensions": { + "order": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6 + ], + "ndisplay": 2, + "displayed_axes": [ + "y", + "x" + ], + "point": [ + 0.0, + 1.0, + 0.0, + 0.0, + 0.0, + 20.334, + 20.334 + ], + "camera_angles": [ + 0.0, + 0.0, + 0.0 + ], + "canvas_size": [ + 643, + 478 + ] + }, + "active_dimension_label_route": "origin_manual_kind_manual_projection_selected_images_8c7357d46ccc38823ca9e68096baf86f25c3004b61b63ba1eef9adea41d34fb8_scalar_stack", + "viewer_ndim": 7, + "current_step": [ + 0, + 1, + 0, + 0, + 0, + 15, + 15 + ], + "axis_labels": [ + "site", + "channel", + "z_index", + "timepoint", + "well", + "y", + "x" + ], + "component_group_count": 3, + "component_item_count": 4 + } + } + }, + { + "tool": "openhcs_viewer_snapshot_window", + "arguments": { + "host": "127.0.0.1", + "port": 6609, + "transport_mode": "tcp", + "output_dir_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/captures-live12/result", + "capture_scope": "widget", + "frame_condition": "render_complete", + "observation_timeout_s": 2.5 + }, + "response": { + "content": [ + { + "type": "text", + "text": "{\n \"connection\": {\n \"host\": \"127.0.0.1\",\n \"port\": 6609,\n \"transport_mode\": \"tcp\",\n \"persistent\": true\n },\n \"schema_version\": \"openhcs.agent.v1\",\n \"errors\": [],\n \"warnings\": [],\n \"output_dir_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/captures-live12/result\",\n \"capture_scope\": \"widget\",\n \"frame_condition\": \"render_complete\",\n \"observation_timeout_s\": 2.5,\n \"captured\": true,\n \"observation\": {\n \"condition\": \"render_complete\",\n \"window_identity\": 140451432015472,\n \"started_at_monotonic\": 3882702.60035156,\n \"completed_at_monotonic\": 3882702.615018741,\n \"configured_flash_duration_s\": 0.0,\n \"baseline_inactive\": true,\n \"flash_start_count\": 0,\n \"painted_frame_count\": 1,\n \"frame\": null,\n \"trace\": [],\n \"render_frame\": {\n \"window_identity\": 140451432015472,\n \"renderer_identity\": 140451432242288,\n \"completed_at_monotonic\": 3882702.615009964\n },\n \"observation_budget_s\": 2.4823596680071205,\n \"operation_deadline\": {\n \"operation\": \"viewer control request\",\n \"timeout_ms\": 5000,\n \"expires_at\": 3882707.565189139\n }\n },\n \"resource\": {\n \"uri\": \"file:///home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/captures-live12/result/20261004T043044727006Z_napari_6609_OpenHCS_Napari_Visualization.png\",\n \"title\": \"OpenHCS Napari Visualization\",\n \"mime_type\": \"image/png\",\n \"path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/captures-live12/result/20261004T043044727006Z_napari_6609_OpenHCS_Napari_Visualization.png\",\n \"size_bytes\": 82592,\n \"sha256\": \"440488c036ff602991ecd5a4124a47241b8093dcf7a5a2c157233076978a410b\"\n },\n \"viewer\": {\n \"viewer_type\": \"napari\",\n \"title\": \"OpenHCS Napari Visualization\"\n },\n \"width\": 1152,\n \"height\": 963,\n \"response\": {\n \"type\": \"screenshot_ack\",\n \"status\": \"success\",\n \"viewer\": {\n \"type\": \"napari\",\n \"title\": \"OpenHCS Napari Visualization\"\n },\n \"resource\": {\n \"uri\": \"file:///home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/captures-live12/result/20261004T043044727006Z_napari_6609_OpenHCS_Napari_Visualization.png\",\n \"title\": \"OpenHCS Napari Visualization\",\n \"mime_type\": \"image/png\",\n \"path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/captures-live12/result/20261004T043044727006Z_napari_6609_OpenHCS_Napari_Visualization.png\",\n \"size_bytes\": 82592,\n \"sha256\": \"440488c036ff602991ecd5a4124a47241b8093dcf7a5a2c157233076978a410b\"\n },\n \"width\": 1152,\n \"height\": 963,\n \"snapshot\": {\n \"connection\": {\n \"host\": \"127.0.0.1\",\n \"port\": 6609,\n \"transport_mode\": \"tcp\",\n \"persistent\": true\n },\n \"timeout_ms\": 5000,\n \"include_response\": true,\n \"operation_deadline\": {\n \"operation\": \"viewer control request\",\n \"timeout_ms\": 5000,\n \"expires_at\": 3882707.565189139\n },\n \"output_dir_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/captures-live12/result\",\n \"capture_scope\": \"widget\",\n \"frame_condition\": \"render_complete\",\n \"observation_timeout_s\": 2.5\n },\n \"observation\": {\n \"condition\": \"render_complete\",\n \"window_identity\": 140451432015472,\n \"started_at_monotonic\": 3882702.60035156,\n \"completed_at_monotonic\": 3882702.615018741,\n \"configured_flash_duration_s\": 0.0,\n \"baseline_inactive\": true,\n \"flash_start_count\": 0,\n \"painted_frame_count\": 1,\n \"frame\": null,\n \"trace\": [],\n \"render_frame\": {\n \"window_identity\": 140451432015472,\n \"renderer_identity\": 140451432242288,\n \"completed_at_monotonic\": 3882702.615009964\n },\n \"observation_budget_s\": 2.4823596680071205,\n \"operation_deadline\": {\n \"operation\": \"viewer control request\",\n \"timeout_ms\": 5000,\n \"expires_at\": 3882707.565189139\n }\n },\n \"native_dimensions\": {\n \"order\": [\n 0,\n 1,\n 2,\n 3,\n 4,\n 5,\n 6\n ],\n \"ndisplay\": 2,\n \"displayed_axes\": [\n \"y\",\n \"x\"\n ],\n \"point\": [\n 0.0,\n 1.0,\n 0.0,\n 0.0,\n 0.0,\n 20.334,\n 20.334\n ],\n \"camera_angles\": [\n 0.0,\n 0.0,\n 0.0\n ],\n \"canvas_size\": [\n 643,\n 478\n ]\n }\n }\n}" + } + ], + "structuredContent": { + "connection": { + "host": "127.0.0.1", + "port": 6609, + "transport_mode": "tcp", + "persistent": true + }, + "schema_version": "openhcs.agent.v1", + "errors": [], + "warnings": [], + "output_dir_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/captures-live12/result", + "capture_scope": "widget", + "frame_condition": "render_complete", + "observation_timeout_s": 2.5, + "captured": true, + "observation": { + "condition": "render_complete", + "window_identity": 140451432015472, + "started_at_monotonic": 3882702.60035156, + "completed_at_monotonic": 3882702.615018741, + "configured_flash_duration_s": 0.0, + "baseline_inactive": true, + "flash_start_count": 0, + "painted_frame_count": 1, + "frame": null, + "trace": [], + "render_frame": { + "window_identity": 140451432015472, + "renderer_identity": 140451432242288, + "completed_at_monotonic": 3882702.615009964 + }, + "observation_budget_s": 2.4823596680071205, + "operation_deadline": { + "operation": "viewer control request", + "timeout_ms": 5000, + "expires_at": 3882707.565189139 + } + }, + "resource": { + "uri": "file:///home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/captures-live12/result/20261004T043044727006Z_napari_6609_OpenHCS_Napari_Visualization.png", + "title": "OpenHCS Napari Visualization", + "mime_type": "image/png", + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/captures-live12/result/20261004T043044727006Z_napari_6609_OpenHCS_Napari_Visualization.png", + "size_bytes": 82592, + "sha256": "440488c036ff602991ecd5a4124a47241b8093dcf7a5a2c157233076978a410b" + }, + "viewer": { + "viewer_type": "napari", + "title": "OpenHCS Napari Visualization" + }, + "width": 1152, + "height": 963, + "response": { + "type": "screenshot_ack", + "status": "success", + "viewer": { + "type": "napari", + "title": "OpenHCS Napari Visualization" + }, + "resource": { + "uri": "file:///home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/captures-live12/result/20261004T043044727006Z_napari_6609_OpenHCS_Napari_Visualization.png", + "title": "OpenHCS Napari Visualization", + "mime_type": "image/png", + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/captures-live12/result/20261004T043044727006Z_napari_6609_OpenHCS_Napari_Visualization.png", + "size_bytes": 82592, + "sha256": "440488c036ff602991ecd5a4124a47241b8093dcf7a5a2c157233076978a410b" + }, + "width": 1152, + "height": 963, + "snapshot": { + "connection": { + "host": "127.0.0.1", + "port": 6609, + "transport_mode": "tcp", + "persistent": true + }, + "timeout_ms": 5000, + "include_response": true, + "operation_deadline": { + "operation": "viewer control request", + "timeout_ms": 5000, + "expires_at": 3882707.565189139 + }, + "output_dir_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/captures-live12/result", + "capture_scope": "widget", + "frame_condition": "render_complete", + "observation_timeout_s": 2.5 + }, + "observation": { + "condition": "render_complete", + "window_identity": 140451432015472, + "started_at_monotonic": 3882702.60035156, + "completed_at_monotonic": 3882702.615018741, + "configured_flash_duration_s": 0.0, + "baseline_inactive": true, + "flash_start_count": 0, + "painted_frame_count": 1, + "frame": null, + "trace": [], + "render_frame": { + "window_identity": 140451432015472, + "renderer_identity": 140451432242288, + "completed_at_monotonic": 3882702.615009964 + }, + "observation_budget_s": 2.4823596680071205, + "operation_deadline": { + "operation": "viewer control request", + "timeout_ms": 5000, + "expires_at": 3882707.565189139 + } + }, + "native_dimensions": { + "order": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6 + ], + "ndisplay": 2, + "displayed_axes": [ + "y", + "x" + ], + "point": [ + 0.0, + 1.0, + 0.0, + 0.0, + 0.0, + 20.334, + 20.334 + ], + "camera_angles": [ + 0.0, + 0.0, + 0.0 + ], + "canvas_size": [ + 643, + 478 + ] + } + } + }, + "isError": false + }, + "payload": { + "connection": { + "host": "127.0.0.1", + "port": 6609, + "transport_mode": "tcp", + "persistent": true + }, + "schema_version": "openhcs.agent.v1", + "errors": [], + "warnings": [], + "output_dir_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/captures-live12/result", + "capture_scope": "widget", + "frame_condition": "render_complete", + "observation_timeout_s": 2.5, + "captured": true, + "observation": { + "condition": "render_complete", + "window_identity": 140451432015472, + "started_at_monotonic": 3882702.60035156, + "completed_at_monotonic": 3882702.615018741, + "configured_flash_duration_s": 0.0, + "baseline_inactive": true, + "flash_start_count": 0, + "painted_frame_count": 1, + "frame": null, + "trace": [], + "render_frame": { + "window_identity": 140451432015472, + "renderer_identity": 140451432242288, + "completed_at_monotonic": 3882702.615009964 + }, + "observation_budget_s": 2.4823596680071205, + "operation_deadline": { + "operation": "viewer control request", + "timeout_ms": 5000, + "expires_at": 3882707.565189139 + } + }, + "resource": { + "uri": "file:///home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/captures-live12/result/20261004T043044727006Z_napari_6609_OpenHCS_Napari_Visualization.png", + "title": "OpenHCS Napari Visualization", + "mime_type": "image/png", + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/captures-live12/result/20261004T043044727006Z_napari_6609_OpenHCS_Napari_Visualization.png", + "size_bytes": 82592, + "sha256": "440488c036ff602991ecd5a4124a47241b8093dcf7a5a2c157233076978a410b" + }, + "viewer": { + "viewer_type": "napari", + "title": "OpenHCS Napari Visualization" + }, + "width": 1152, + "height": 963, + "response": { + "type": "screenshot_ack", + "status": "success", + "viewer": { + "type": "napari", + "title": "OpenHCS Napari Visualization" + }, + "resource": { + "uri": "file:///home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/captures-live12/result/20261004T043044727006Z_napari_6609_OpenHCS_Napari_Visualization.png", + "title": "OpenHCS Napari Visualization", + "mime_type": "image/png", + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/captures-live12/result/20261004T043044727006Z_napari_6609_OpenHCS_Napari_Visualization.png", + "size_bytes": 82592, + "sha256": "440488c036ff602991ecd5a4124a47241b8093dcf7a5a2c157233076978a410b" + }, + "width": 1152, + "height": 963, + "snapshot": { + "connection": { + "host": "127.0.0.1", + "port": 6609, + "transport_mode": "tcp", + "persistent": true + }, + "timeout_ms": 5000, + "include_response": true, + "operation_deadline": { + "operation": "viewer control request", + "timeout_ms": 5000, + "expires_at": 3882707.565189139 + }, + "output_dir_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/captures-live12/result", + "capture_scope": "widget", + "frame_condition": "render_complete", + "observation_timeout_s": 2.5 + }, + "observation": { + "condition": "render_complete", + "window_identity": 140451432015472, + "started_at_monotonic": 3882702.60035156, + "completed_at_monotonic": 3882702.615018741, + "configured_flash_duration_s": 0.0, + "baseline_inactive": true, + "flash_start_count": 0, + "painted_frame_count": 1, + "frame": null, + "trace": [], + "render_frame": { + "window_identity": 140451432015472, + "renderer_identity": 140451432242288, + "completed_at_monotonic": 3882702.615009964 + }, + "observation_budget_s": 2.4823596680071205, + "operation_deadline": { + "operation": "viewer control request", + "timeout_ms": 5000, + "expires_at": 3882707.565189139 + } + }, + "native_dimensions": { + "order": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6 + ], + "ndisplay": 2, + "displayed_axes": [ + "y", + "x" + ], + "point": [ + 0.0, + 1.0, + 0.0, + 0.0, + 0.0, + 20.334, + 20.334 + ], + "camera_angles": [ + 0.0, + 0.0, + 0.0 + ], + "canvas_size": [ + 643, + 478 + ] + } + } + } + }, + { + "tool": "openhcs_isolate_viewer_window_layers", + "arguments": { + "host": "127.0.0.1", + "port": 6609, + "transport_mode": "tcp", + "visible_route_keys": [ + "origin_manual_kind_manual_projection_A01_s001_w2_z001_t001_graph.graph.roi.zip_shapes", + "origin_manual_kind_manual_projection_selected_images_8c7357d46ccc38823ca9e68096baf86f25c3004b61b63ba1eef9adea41d34fb8_scalar_stack", + "origin_manual_kind_manual_projection_selected_images_e83ddc2185a63aca4b85ec471143f61c8f4eabdb08df3557ca21f2bddcda60b9" + ], + "selected_route_key": "origin_manual_kind_manual_projection_selected_images_8c7357d46ccc38823ca9e68096baf86f25c3004b61b63ba1eef9adea41d34fb8_scalar_stack", + "axis_indices": { + "channel": 1 + } + }, + "response": { + "content": [ + { + "type": "text", + "text": "{\n \"connection\": {\n \"host\": \"127.0.0.1\",\n \"port\": 6609,\n \"transport_mode\": \"tcp\",\n \"persistent\": true\n },\n \"schema_version\": \"openhcs.agent.v1\",\n \"errors\": [],\n \"warnings\": [],\n \"observed\": true,\n \"applied\": true,\n \"selected_route_key\": \"origin_manual_kind_manual_projection_selected_images_8c7357d46ccc38823ca9e68096baf86f25c3004b61b63ba1eef9adea41d34fb8_scalar_stack\",\n \"visible_route_keys\": [\n \"origin_manual_kind_manual_projection_selected_images_8c7357d46ccc38823ca9e68096baf86f25c3004b61b63ba1eef9adea41d34fb8_scalar_stack\",\n \"origin_manual_kind_manual_projection_selected_images_e83ddc2185a63aca4b85ec471143f61c8f4eabdb08df3557ca21f2bddcda60b9\",\n \"origin_manual_kind_manual_projection_A01_s001_w2_z001_t001_graph.graph.roi.zip_shapes\"\n ],\n \"hidden_route_keys\": [],\n \"missing_route_keys\": [],\n \"available_layers\": [\n {\n \"route_key\": \"origin_manual_kind_manual_projection_selected_images_8c7357d46ccc38823ca9e68096baf86f25c3004b61b63ba1eef9adea41d34fb8_scalar_stack\",\n \"title\": \"selected_images image stack\",\n \"visible\": true,\n \"selected\": true\n },\n {\n \"route_key\": \"origin_manual_kind_manual_projection_selected_images_e83ddc2185a63aca4b85ec471143f61c8f4eabdb08df3557ca21f2bddcda60b9\",\n \"title\": \"selected_images\",\n \"visible\": true,\n \"selected\": false\n },\n {\n \"route_key\": \"origin_manual_kind_manual_projection_A01_s001_w2_z001_t001_graph.graph.roi.zip_shapes\",\n \"title\": \"A01_s001_w2_z001_t001_graph.graph.roi.zip ROIs\",\n \"visible\": true,\n \"selected\": false\n }\n ],\n \"changed_route_count\": 1,\n \"layer_count\": 3,\n \"active_dimension_label_route\": \"origin_manual_kind_manual_projection_selected_images_8c7357d46ccc38823ca9e68096baf86f25c3004b61b63ba1eef9adea41d34fb8_scalar_stack\",\n \"current_step\": [\n 0,\n 1,\n 0,\n 0,\n 0,\n 15,\n 15\n ],\n \"axis_labels\": [\n \"site\",\n \"channel\",\n \"z_index\",\n \"timepoint\",\n \"well\",\n \"y\",\n \"x\"\n ],\n \"visible_layers\": [\n {\n \"route_key\": \"origin_manual_kind_manual_projection_selected_images_8c7357d46ccc38823ca9e68096baf86f25c3004b61b63ba1eef9adea41d34fb8_scalar_stack\",\n \"title\": \"selected_images image stack\",\n \"visible\": true,\n \"selected\": true\n },\n {\n \"route_key\": \"origin_manual_kind_manual_projection_selected_images_e83ddc2185a63aca4b85ec471143f61c8f4eabdb08df3557ca21f2bddcda60b9\",\n \"title\": \"selected_images\",\n \"visible\": true,\n \"selected\": false\n },\n {\n \"route_key\": \"origin_manual_kind_manual_projection_A01_s001_w2_z001_t001_graph.graph.roi.zip_shapes\",\n \"title\": \"A01_s001_w2_z001_t001_graph.graph.roi.zip ROIs\",\n \"visible\": true,\n \"selected\": false\n }\n ]\n}" + } + ], + "structuredContent": { + "connection": { + "host": "127.0.0.1", + "port": 6609, + "transport_mode": "tcp", + "persistent": true + }, + "schema_version": "openhcs.agent.v1", + "errors": [], + "warnings": [], + "observed": true, + "applied": true, + "selected_route_key": "origin_manual_kind_manual_projection_selected_images_8c7357d46ccc38823ca9e68096baf86f25c3004b61b63ba1eef9adea41d34fb8_scalar_stack", + "visible_route_keys": [ + "origin_manual_kind_manual_projection_selected_images_8c7357d46ccc38823ca9e68096baf86f25c3004b61b63ba1eef9adea41d34fb8_scalar_stack", + "origin_manual_kind_manual_projection_selected_images_e83ddc2185a63aca4b85ec471143f61c8f4eabdb08df3557ca21f2bddcda60b9", + "origin_manual_kind_manual_projection_A01_s001_w2_z001_t001_graph.graph.roi.zip_shapes" + ], + "hidden_route_keys": [], + "missing_route_keys": [], + "available_layers": [ + { + "route_key": "origin_manual_kind_manual_projection_selected_images_8c7357d46ccc38823ca9e68096baf86f25c3004b61b63ba1eef9adea41d34fb8_scalar_stack", + "title": "selected_images image stack", + "visible": true, + "selected": true + }, + { + "route_key": "origin_manual_kind_manual_projection_selected_images_e83ddc2185a63aca4b85ec471143f61c8f4eabdb08df3557ca21f2bddcda60b9", + "title": "selected_images", + "visible": true, + "selected": false + }, + { + "route_key": "origin_manual_kind_manual_projection_A01_s001_w2_z001_t001_graph.graph.roi.zip_shapes", + "title": "A01_s001_w2_z001_t001_graph.graph.roi.zip ROIs", + "visible": true, + "selected": false + } + ], + "changed_route_count": 1, + "layer_count": 3, + "active_dimension_label_route": "origin_manual_kind_manual_projection_selected_images_8c7357d46ccc38823ca9e68096baf86f25c3004b61b63ba1eef9adea41d34fb8_scalar_stack", + "current_step": [ + 0, + 1, + 0, + 0, + 0, + 15, + 15 + ], + "axis_labels": [ + "site", + "channel", + "z_index", + "timepoint", + "well", + "y", + "x" + ], + "visible_layers": [ + { + "route_key": "origin_manual_kind_manual_projection_selected_images_8c7357d46ccc38823ca9e68096baf86f25c3004b61b63ba1eef9adea41d34fb8_scalar_stack", + "title": "selected_images image stack", + "visible": true, + "selected": true + }, + { + "route_key": "origin_manual_kind_manual_projection_selected_images_e83ddc2185a63aca4b85ec471143f61c8f4eabdb08df3557ca21f2bddcda60b9", + "title": "selected_images", + "visible": true, + "selected": false + }, + { + "route_key": "origin_manual_kind_manual_projection_A01_s001_w2_z001_t001_graph.graph.roi.zip_shapes", + "title": "A01_s001_w2_z001_t001_graph.graph.roi.zip ROIs", + "visible": true, + "selected": false + } + ] + }, + "isError": false + }, + "payload": { + "connection": { + "host": "127.0.0.1", + "port": 6609, + "transport_mode": "tcp", + "persistent": true + }, + "schema_version": "openhcs.agent.v1", + "errors": [], + "warnings": [], + "observed": true, + "applied": true, + "selected_route_key": "origin_manual_kind_manual_projection_selected_images_8c7357d46ccc38823ca9e68096baf86f25c3004b61b63ba1eef9adea41d34fb8_scalar_stack", + "visible_route_keys": [ + "origin_manual_kind_manual_projection_selected_images_8c7357d46ccc38823ca9e68096baf86f25c3004b61b63ba1eef9adea41d34fb8_scalar_stack", + "origin_manual_kind_manual_projection_selected_images_e83ddc2185a63aca4b85ec471143f61c8f4eabdb08df3557ca21f2bddcda60b9", + "origin_manual_kind_manual_projection_A01_s001_w2_z001_t001_graph.graph.roi.zip_shapes" + ], + "hidden_route_keys": [], + "missing_route_keys": [], + "available_layers": [ + { + "route_key": "origin_manual_kind_manual_projection_selected_images_8c7357d46ccc38823ca9e68096baf86f25c3004b61b63ba1eef9adea41d34fb8_scalar_stack", + "title": "selected_images image stack", + "visible": true, + "selected": true + }, + { + "route_key": "origin_manual_kind_manual_projection_selected_images_e83ddc2185a63aca4b85ec471143f61c8f4eabdb08df3557ca21f2bddcda60b9", + "title": "selected_images", + "visible": true, + "selected": false + }, + { + "route_key": "origin_manual_kind_manual_projection_A01_s001_w2_z001_t001_graph.graph.roi.zip_shapes", + "title": "A01_s001_w2_z001_t001_graph.graph.roi.zip ROIs", + "visible": true, + "selected": false + } + ], + "changed_route_count": 1, + "layer_count": 3, + "active_dimension_label_route": "origin_manual_kind_manual_projection_selected_images_8c7357d46ccc38823ca9e68096baf86f25c3004b61b63ba1eef9adea41d34fb8_scalar_stack", + "current_step": [ + 0, + 1, + 0, + 0, + 0, + 15, + 15 + ], + "axis_labels": [ + "site", + "channel", + "z_index", + "timepoint", + "well", + "y", + "x" + ], + "visible_layers": [ + { + "route_key": "origin_manual_kind_manual_projection_selected_images_8c7357d46ccc38823ca9e68096baf86f25c3004b61b63ba1eef9adea41d34fb8_scalar_stack", + "title": "selected_images image stack", + "visible": true, + "selected": true + }, + { + "route_key": "origin_manual_kind_manual_projection_selected_images_e83ddc2185a63aca4b85ec471143f61c8f4eabdb08df3557ca21f2bddcda60b9", + "title": "selected_images", + "visible": true, + "selected": false + }, + { + "route_key": "origin_manual_kind_manual_projection_A01_s001_w2_z001_t001_graph.graph.roi.zip_shapes", + "title": "A01_s001_w2_z001_t001_graph.graph.roi.zip ROIs", + "visible": true, + "selected": false + } + ] + } + }, + { + "tool": "openhcs_set_viewer_viewport", + "arguments": { + "host": "127.0.0.1", + "port": 6609, + "transport_mode": "tcp", + "presentation": { + "center": [ + 0.0, + 21.011799999999997, + 21.011799999999997 + ], + "zoom": 6.635668707583358 + } + }, + "response": { + "content": [ + { + "type": "text", + "text": "{\n \"connection\": {\n \"host\": \"127.0.0.1\",\n \"port\": 6609,\n \"transport_mode\": \"tcp\",\n \"persistent\": true\n },\n \"schema_version\": \"openhcs.agent.v1\",\n \"errors\": [],\n \"warnings\": [],\n \"observed\": true,\n \"applied\": true,\n \"native_viewport\": {\n \"center\": [\n 0.0,\n 21.011799999999997,\n 21.011799999999997\n ],\n \"zoom\": 6.635668707583358\n }\n}" + } + ], + "structuredContent": { + "connection": { + "host": "127.0.0.1", + "port": 6609, + "transport_mode": "tcp", + "persistent": true + }, + "schema_version": "openhcs.agent.v1", + "errors": [], + "warnings": [], + "observed": true, + "applied": true, + "native_viewport": { + "center": [ + 0.0, + 21.011799999999997, + 21.011799999999997 + ], + "zoom": 6.635668707583358 + } + }, + "isError": false + }, + "payload": { + "connection": { + "host": "127.0.0.1", + "port": 6609, + "transport_mode": "tcp", + "persistent": true + }, + "schema_version": "openhcs.agent.v1", + "errors": [], + "warnings": [], + "observed": true, + "applied": true, + "native_viewport": { + "center": [ + 0.0, + 21.011799999999997, + 21.011799999999997 + ], + "zoom": 6.635668707583358 + } + } + }, + { + "tool": "openhcs_get_viewer_window_state", + "arguments": { + "host": "127.0.0.1", + "port": 6609, + "transport_mode": "tcp", + "route_key": null, + "include_component_values": true, + "max_component_values_per_layer": null, + "include_payload_summaries": true, + "max_payload_summaries_per_layer": null, + "include_response": true + }, + "response": { + "content": [ + { + "type": "text", + "text": "{\n \"connection\": {\n \"host\": \"127.0.0.1\",\n \"port\": 6609,\n \"transport_mode\": \"tcp\",\n \"persistent\": true\n },\n \"schema_version\": \"openhcs.agent.v1\",\n \"errors\": [],\n \"warnings\": [],\n \"observed\": true,\n \"viewer\": {\n \"viewer_type\": \"napari\",\n \"title\": \"OpenHCS Napari Visualization\"\n },\n \"layer_count\": 3,\n \"layers\": [\n {\n \"route_key\": \"origin_manual_kind_manual_projection_selected_images_8c7357d46ccc38823ca9e68096baf86f25c3004b61b63ba1eef9adea41d34fb8_scalar_stack\",\n \"title\": \"selected_images image stack\",\n \"mounted\": true,\n \"item_count\": 1,\n \"producer_identities\": [\n {\n \"origin\": \"manual\",\n \"output_kind\": \"manual\",\n \"output_key\": \"selected_images\",\n \"projection_key\": \"selected_images_8c7357d46ccc38823ca9e68096baf86f25c3004b61b63ba1eef9adea41d34fb8\",\n \"step_name\": null,\n \"pipeline_position\": null,\n \"step_scope_id\": null,\n \"invocation_key\": null,\n \"artifact_kind\": null\n }\n ],\n \"axis_labels\": [\n \"site\",\n \"channel\",\n \"z_index\",\n \"timepoint\",\n \"well\",\n \"y\",\n \"x\"\n ],\n \"stack_axes\": [\n \"channel\"\n ],\n \"pending_update\": false,\n \"data_types\": [\n \"image\"\n ],\n \"component_values\": [\n {\n \"site\": 1,\n \"z_index\": 1,\n \"timepoint\": 1,\n \"well\": \"A01\"\n }\n ],\n \"component_value_count\": 1,\n \"component_values_truncated\": false,\n \"payload_summaries\": [\n {\n \"shape\": [\n 2,\n 32,\n 32\n ],\n \"dtype\": \"uint16\",\n \"size\": 2048,\n \"nonzero_count\": 308,\n \"min\": 0,\n \"max\": 22,\n \"nonzero_min_coordinate\": [\n 0,\n 3,\n 4\n ],\n \"nonzero_max_coordinate\": [\n 1,\n 24,\n 27\n ],\n \"nonzero_example_coordinates\": [\n [\n 0,\n 3,\n 4\n ],\n [\n 0,\n 5,\n 4\n ],\n [\n 0,\n 7,\n 4\n ],\n [\n 0,\n 9,\n 5\n ],\n [\n 0,\n 11,\n 5\n ],\n [\n 0,\n 18,\n 24\n ],\n [\n 0,\n 21,\n 20\n ],\n [\n 0,\n 23,\n 25\n ],\n [\n 1,\n 3,\n 13\n ],\n [\n 1,\n 6,\n 4\n ],\n [\n 1,\n 8,\n 4\n ],\n [\n 1,\n 10,\n 5\n ],\n [\n 1,\n 17,\n 21\n ],\n [\n 1,\n 19,\n 26\n ],\n [\n 1,\n 22,\n 22\n ],\n [\n 1,\n 24,\n 27\n ]\n ],\n \"source_voxel_spacing\": {\n \"values_zyx\": [\n 1.3556,\n 1.3556\n ],\n \"unit\": \"micrometers\"\n },\n \"spatial_origin_yx\": [\n 0,\n 0\n ],\n \"source_spatial_shape_yx\": [\n 32,\n 32\n ],\n \"aggregate_component_values\": {\n \"channel\": [\n 2,\n 1\n ]\n },\n \"data_type\": \"image\",\n \"path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/stacked_labels/A01_s001_w2_z001_t001_Labels.tif\",\n \"components\": {\n \"site\": 1,\n \"z_index\": 1,\n \"timepoint\": 1,\n \"well\": \"A01\"\n },\n \"payload_type\": \"ndarray\"\n }\n ],\n \"payload_summary_count\": 1,\n \"payload_summaries_truncated\": false,\n \"axis_offsets\": [\n 0\n ],\n \"scalar_labels\": [\n \"Site 1\",\n \"Z 1\",\n \"T 1\",\n \"Well A01\"\n ],\n \"labels\": {\n \"channel\": [\n \"Ch 1\",\n \"Ch 2\"\n ]\n },\n \"axis_component_values\": {\n \"channel\": [\n 1,\n 2\n ]\n },\n \"routed_component_values\": {\n \"channel\": [\n 1,\n 2\n ]\n },\n \"routed_component_coordinates\": [\n [\n 1\n ],\n [\n 2\n ]\n ],\n \"data_shape\": [\n 1,\n 2,\n 1,\n 1,\n 1,\n 32,\n 32\n ],\n \"native_transform\": {\n \"scale\": [\n 1.0,\n 1.0,\n 1.0,\n 1.0,\n 1.0,\n 1.3556,\n 1.3556\n ],\n \"translate\": [\n 0.0,\n 0.0,\n 0.0,\n 0.0,\n 0.0,\n 0.0,\n 0.0\n ]\n },\n \"native_intensity\": {\n \"contrast_limits\": [\n 0.0,\n 22.0\n ],\n \"gamma\": 1.0\n },\n \"visible\": true,\n \"selected\": true,\n \"feature_row_count\": 0,\n \"selected_data_indices\": []\n },\n {\n \"route_key\": \"origin_manual_kind_manual_projection_selected_images_e83ddc2185a63aca4b85ec471143f61c8f4eabdb08df3557ca21f2bddcda60b9\",\n \"title\": \"selected_images\",\n \"mounted\": true,\n \"item_count\": 2,\n \"producer_identities\": [\n {\n \"origin\": \"manual\",\n \"output_kind\": \"manual\",\n \"output_key\": \"selected_images\",\n \"projection_key\": \"selected_images_e83ddc2185a63aca4b85ec471143f61c8f4eabdb08df3557ca21f2bddcda60b9\",\n \"step_name\": null,\n \"pipeline_position\": null,\n \"step_scope_id\": null,\n \"invocation_key\": null,\n \"artifact_kind\": null\n }\n ],\n \"axis_labels\": [\n \"site\",\n \"channel\",\n \"z_index\",\n \"timepoint\",\n \"well\",\n \"y\",\n \"x\"\n ],\n \"stack_axes\": [\n \"channel\"\n ],\n \"pending_update\": false,\n \"data_types\": [\n \"image\"\n ],\n \"component_values\": [\n {\n \"site\": 1,\n \"channel\": 1,\n \"z_index\": 1,\n \"timepoint\": 1,\n \"well\": \"A01\"\n },\n {\n \"site\": 1,\n \"channel\": 2,\n \"z_index\": 1,\n \"timepoint\": 1,\n \"well\": \"A01\"\n }\n ],\n \"component_value_count\": 2,\n \"component_values_truncated\": false,\n \"payload_summaries\": [\n {\n \"shape\": [\n 32,\n 32\n ],\n \"dtype\": \"uint16\",\n \"size\": 1024,\n \"nonzero_count\": 1024,\n \"min\": 100,\n \"max\": 1123,\n \"nonzero_min_coordinate\": [\n 0,\n 0\n ],\n \"nonzero_max_coordinate\": [\n 31,\n 31\n ],\n \"nonzero_example_coordinates\": [\n [\n 0,\n 0\n ],\n [\n 2,\n 4\n ],\n [\n 4,\n 8\n ],\n [\n 6,\n 12\n ],\n [\n 8,\n 16\n ],\n [\n 10,\n 21\n ],\n [\n 12,\n 25\n ],\n [\n 14,\n 29\n ],\n [\n 17,\n 1\n ],\n [\n 19,\n 5\n ],\n [\n 21,\n 10\n ],\n [\n 23,\n 14\n ],\n [\n 25,\n 18\n ],\n [\n 27,\n 22\n ],\n [\n 29,\n 26\n ],\n [\n 31,\n 31\n ]\n ],\n \"source_voxel_spacing\": {\n \"values_zyx\": [\n 1.3556,\n 1.3556\n ],\n \"unit\": \"micrometers\"\n },\n \"spatial_origin_yx\": [\n 0,\n 0\n ],\n \"source_spatial_shape_yx\": [\n 32,\n 32\n ],\n \"data_type\": \"image\",\n \"path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w1_z001_t001.tif\",\n \"components\": {\n \"site\": 1,\n \"channel\": 1,\n \"z_index\": 1,\n \"timepoint\": 1,\n \"well\": \"A01\"\n },\n \"payload_type\": \"ndarray\"\n },\n {\n \"shape\": [\n 32,\n 32\n ],\n \"dtype\": \"uint16\",\n \"size\": 1024,\n \"nonzero_count\": 1024,\n \"min\": 200,\n \"max\": 1223,\n \"nonzero_min_coordinate\": [\n 0,\n 0\n ],\n \"nonzero_max_coordinate\": [\n 31,\n 31\n ],\n \"nonzero_example_coordinates\": [\n [\n 0,\n 0\n ],\n [\n 2,\n 4\n ],\n [\n 4,\n 8\n ],\n [\n 6,\n 12\n ],\n [\n 8,\n 16\n ],\n [\n 10,\n 21\n ],\n [\n 12,\n 25\n ],\n [\n 14,\n 29\n ],\n [\n 17,\n 1\n ],\n [\n 19,\n 5\n ],\n [\n 21,\n 10\n ],\n [\n 23,\n 14\n ],\n [\n 25,\n 18\n ],\n [\n 27,\n 22\n ],\n [\n 29,\n 26\n ],\n [\n 31,\n 31\n ]\n ],\n \"source_voxel_spacing\": {\n \"values_zyx\": [\n 1.3556,\n 1.3556\n ],\n \"unit\": \"micrometers\"\n },\n \"spatial_origin_yx\": [\n 0,\n 0\n ],\n \"source_spatial_shape_yx\": [\n 32,\n 32\n ],\n \"data_type\": \"image\",\n \"path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w2_z001_t001.tif\",\n \"components\": {\n \"site\": 1,\n \"channel\": 2,\n \"z_index\": 1,\n \"timepoint\": 1,\n \"well\": \"A01\"\n },\n \"payload_type\": \"ndarray\"\n }\n ],\n \"payload_summary_count\": 2,\n \"payload_summaries_truncated\": false,\n \"axis_offsets\": [\n 0\n ],\n \"scalar_labels\": [\n \"Site 1\",\n \"Z 1\",\n \"T 1\",\n \"Well A01\"\n ],\n \"labels\": {\n \"channel\": [\n \"Ch 1\",\n \"Ch 2\"\n ]\n },\n \"axis_component_values\": {\n \"channel\": [\n 1,\n 2\n ]\n },\n \"routed_component_values\": {\n \"channel\": [\n 1,\n 2\n ]\n },\n \"routed_component_coordinates\": [\n [\n 1\n ],\n [\n 2\n ]\n ],\n \"data_shape\": [\n 1,\n 2,\n 1,\n 1,\n 1,\n 32,\n 32\n ],\n \"native_transform\": {\n \"scale\": [\n 1.0,\n 1.0,\n 1.0,\n 1.0,\n 1.0,\n 1.3556,\n 1.3556\n ],\n \"translate\": [\n 0.0,\n 0.0,\n 0.0,\n 0.0,\n 0.0,\n 0.0,\n 0.0\n ]\n },\n \"native_intensity\": {\n \"contrast_limits\": [\n 100.0,\n 1223.0\n ],\n \"gamma\": 1.0\n },\n \"visible\": true,\n \"selected\": false,\n \"feature_row_count\": 0,\n \"selected_data_indices\": []\n },\n {\n \"route_key\": \"origin_manual_kind_manual_projection_A01_s001_w2_z001_t001_graph.graph.roi.zip_shapes\",\n \"title\": \"A01_s001_w2_z001_t001_graph.graph.roi.zip ROIs\",\n \"mounted\": true,\n \"item_count\": 1,\n \"producer_identities\": [\n {\n \"origin\": \"manual\",\n \"output_kind\": \"manual\",\n \"output_key\": \"A01_s001_w2_z001_t001_graph.graph.roi.zip\",\n \"projection_key\": \"A01_s001_w2_z001_t001_graph.graph.roi.zip\",\n \"step_name\": null,\n \"pipeline_position\": null,\n \"step_scope_id\": null,\n \"invocation_key\": null,\n \"artifact_kind\": null\n }\n ],\n \"axis_labels\": [\n \"site\",\n \"channel\",\n \"z_index\",\n \"timepoint\",\n \"well\",\n \"y\",\n \"x\"\n ],\n \"stack_axes\": [\n \"channel\"\n ],\n \"pending_update\": false,\n \"data_types\": [\n \"shapes\"\n ],\n \"component_values\": [\n {\n \"site\": 1,\n \"channel\": 2,\n \"z_index\": 1,\n \"timepoint\": 1,\n \"well\": \"A01\"\n }\n ],\n \"component_value_count\": 1,\n \"component_values_truncated\": false,\n \"payload_summaries\": [\n {\n \"nonzero_count\": 2,\n \"item_count\": 2,\n \"shape_payload_count\": 2,\n \"missing_source_spatial_shape_count\": 2,\n \"shape_coordinate_count\": 4,\n \"shape_out_of_source_bounds_count\": 0,\n \"shape_coordinate_bounds_yx\": {\n \"min_yx\": [\n 2.25,\n 3.5\n ],\n \"max_yx\": [\n 7.25,\n 12.5\n ],\n \"coordinate_count\": 4\n },\n \"source_voxel_spacing\": {\n \"values_zyx\": [\n 1.3556,\n 1.3556\n ],\n \"unit\": \"micrometers\"\n },\n \"data_type\": \"shapes\",\n \"path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/graph_results/A01_s001_w2_z001_t001_graph.graph.roi.zip\",\n \"components\": {\n \"site\": 1,\n \"channel\": 2,\n \"z_index\": 1,\n \"timepoint\": 1,\n \"well\": \"A01\"\n },\n \"payload_type\": \"list\"\n }\n ],\n \"payload_summary_count\": 1,\n \"payload_summaries_truncated\": false,\n \"axis_offsets\": [\n 1\n ],\n \"scalar_labels\": [\n \"Site 1\",\n \"Z 1\",\n \"T 1\",\n \"Well A01\"\n ],\n \"labels\": {\n \"channel\": [\n \"Ch 2\"\n ]\n },\n \"axis_component_values\": {\n \"channel\": [\n 2\n ]\n },\n \"routed_component_values\": {\n \"channel\": [\n 2\n ]\n },\n \"routed_component_coordinates\": [\n [\n 2\n ]\n ],\n \"data_shape\": [\n 2\n ],\n \"native_transform\": {\n \"scale\": [\n 1.0,\n 1.0,\n 1.0,\n 1.0,\n 1.0,\n 1.3556,\n 1.3556\n ],\n \"translate\": [\n 0.0,\n 1.0,\n 0.0,\n 0.0,\n 0.0,\n 0.0,\n 0.0\n ]\n },\n \"native_intensity\": null,\n \"visible\": true,\n \"selected\": false,\n \"feature_row_count\": 2,\n \"selected_data_indices\": []\n }\n ],\n \"active_dimension_label_route\": \"origin_manual_kind_manual_projection_selected_images_8c7357d46ccc38823ca9e68096baf86f25c3004b61b63ba1eef9adea41d34fb8_scalar_stack\",\n \"viewer_ndim\": 7,\n \"current_step\": [\n 0,\n 1,\n 0,\n 0,\n 0,\n 15,\n 15\n ],\n \"axis_labels\": [\n \"site\",\n \"channel\",\n \"z_index\",\n \"timepoint\",\n \"well\",\n \"y\",\n \"x\"\n ],\n \"component_group_count\": 3,\n \"component_item_count\": 4,\n \"native_viewport\": {\n \"center\": [\n 0.0,\n 21.011799999999997,\n 21.011799999999997\n ],\n \"zoom\": 6.635668707583358\n },\n \"native_dimensions\": {\n \"order\": [\n 0,\n 1,\n 2,\n 3,\n 4,\n 5,\n 6\n ],\n \"ndisplay\": 2,\n \"displayed_axes\": [\n \"y\",\n \"x\"\n ],\n \"point\": [\n 0.0,\n 1.0,\n 0.0,\n 0.0,\n 0.0,\n 20.334,\n 20.334\n ],\n \"camera_angles\": [\n 0.0,\n 0.0,\n 0.0\n ],\n \"canvas_size\": [\n 643,\n 478\n ]\n },\n \"response\": {\n \"type\": \"state_ack\",\n \"status\": \"success\",\n \"viewer\": {\n \"type\": \"napari\",\n \"title\": \"OpenHCS Napari Visualization\"\n },\n \"layer_count\": 3,\n \"layers\": [\n {\n \"route_key\": \"origin_manual_kind_manual_projection_selected_images_8c7357d46ccc38823ca9e68096baf86f25c3004b61b63ba1eef9adea41d34fb8_scalar_stack\",\n \"producer_identities\": [\n {\n \"origin\": \"manual\",\n \"output_kind\": \"manual\",\n \"output_key\": \"selected_images\",\n \"projection_key\": \"selected_images_8c7357d46ccc38823ca9e68096baf86f25c3004b61b63ba1eef9adea41d34fb8\",\n \"step_name\": null,\n \"pipeline_position\": null,\n \"step_scope_id\": null,\n \"invocation_key\": null,\n \"artifact_kind\": null\n }\n ],\n \"title\": \"selected_images image stack\",\n \"mounted\": true,\n \"item_count\": 1,\n \"data_types\": [\n \"image\"\n ],\n \"component_values\": [\n {\n \"site\": 1,\n \"z_index\": 1,\n \"timepoint\": 1,\n \"well\": \"A01\"\n }\n ],\n \"component_value_count\": 1,\n \"component_values_truncated\": false,\n \"payload_summaries\": [\n {\n \"shape\": [\n 2,\n 32,\n 32\n ],\n \"dtype\": \"uint16\",\n \"size\": 2048,\n \"nonzero_count\": 308,\n \"min\": 0,\n \"max\": 22,\n \"nonzero_min_coordinate\": [\n 0,\n 3,\n 4\n ],\n \"nonzero_max_coordinate\": [\n 1,\n 24,\n 27\n ],\n \"nonzero_example_coordinates\": [\n [\n 0,\n 3,\n 4\n ],\n [\n 0,\n 5,\n 4\n ],\n [\n 0,\n 7,\n 4\n ],\n [\n 0,\n 9,\n 5\n ],\n [\n 0,\n 11,\n 5\n ],\n [\n 0,\n 18,\n 24\n ],\n [\n 0,\n 21,\n 20\n ],\n [\n 0,\n 23,\n 25\n ],\n [\n 1,\n 3,\n 13\n ],\n [\n 1,\n 6,\n 4\n ],\n [\n 1,\n 8,\n 4\n ],\n [\n 1,\n 10,\n 5\n ],\n [\n 1,\n 17,\n 21\n ],\n [\n 1,\n 19,\n 26\n ],\n [\n 1,\n 22,\n 22\n ],\n [\n 1,\n 24,\n 27\n ]\n ],\n \"source_voxel_spacing\": {\n \"values_zyx\": [\n 1.3556,\n 1.3556\n ],\n \"unit\": \"micrometers\"\n },\n \"spatial_origin_yx\": [\n 0,\n 0\n ],\n \"source_spatial_shape_yx\": [\n 32,\n 32\n ],\n \"aggregate_component_values\": {\n \"channel\": [\n 2,\n 1\n ]\n },\n \"data_type\": \"image\",\n \"path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/stacked_labels/A01_s001_w2_z001_t001_Labels.tif\",\n \"components\": {\n \"site\": 1,\n \"z_index\": 1,\n \"timepoint\": 1,\n \"well\": \"A01\"\n },\n \"payload_type\": \"ndarray\"\n }\n ],\n \"payload_summary_count\": 1,\n \"payload_summaries_truncated\": false,\n \"axis_labels\": [\n \"site\",\n \"channel\",\n \"z_index\",\n \"timepoint\",\n \"well\",\n \"y\",\n \"x\"\n ],\n \"stack_axes\": [\n \"channel\"\n ],\n \"axis_offsets\": [\n 0\n ],\n \"scalar_labels\": [\n \"Site 1\",\n \"Z 1\",\n \"T 1\",\n \"Well A01\"\n ],\n \"labels\": {\n \"channel\": [\n \"Ch 1\",\n \"Ch 2\"\n ]\n },\n \"axis_component_values\": {\n \"channel\": [\n 1,\n 2\n ]\n },\n \"routed_component_values\": {\n \"channel\": [\n 1,\n 2\n ]\n },\n \"routed_component_coordinates\": [\n [\n 1\n ],\n [\n 2\n ]\n ],\n \"data_shape\": [\n 1,\n 2,\n 1,\n 1,\n 1,\n 32,\n 32\n ],\n \"native_transform\": {\n \"scale\": [\n 1.0,\n 1.0,\n 1.0,\n 1.0,\n 1.0,\n 1.3556,\n 1.3556\n ],\n \"translate\": [\n 0.0,\n 0.0,\n 0.0,\n 0.0,\n 0.0,\n 0.0,\n 0.0\n ]\n },\n \"native_intensity\": {\n \"contrast_limits\": [\n 0.0,\n 22.0\n ],\n \"gamma\": 1.0\n },\n \"visible\": true,\n \"selected\": true,\n \"feature_row_count\": 0,\n \"selected_data_indices\": [],\n \"pending_update\": false\n },\n {\n \"route_key\": \"origin_manual_kind_manual_projection_selected_images_e83ddc2185a63aca4b85ec471143f61c8f4eabdb08df3557ca21f2bddcda60b9\",\n \"producer_identities\": [\n {\n \"origin\": \"manual\",\n \"output_kind\": \"manual\",\n \"output_key\": \"selected_images\",\n \"projection_key\": \"selected_images_e83ddc2185a63aca4b85ec471143f61c8f4eabdb08df3557ca21f2bddcda60b9\",\n \"step_name\": null,\n \"pipeline_position\": null,\n \"step_scope_id\": null,\n \"invocation_key\": null,\n \"artifact_kind\": null\n }\n ],\n \"title\": \"selected_images\",\n \"mounted\": true,\n \"item_count\": 2,\n \"data_types\": [\n \"image\"\n ],\n \"component_values\": [\n {\n \"site\": 1,\n \"channel\": 1,\n \"z_index\": 1,\n \"timepoint\": 1,\n \"well\": \"A01\"\n },\n {\n \"site\": 1,\n \"channel\": 2,\n \"z_index\": 1,\n \"timepoint\": 1,\n \"well\": \"A01\"\n }\n ],\n \"component_value_count\": 2,\n \"component_values_truncated\": false,\n \"payload_summaries\": [\n {\n \"shape\": [\n 32,\n 32\n ],\n \"dtype\": \"uint16\",\n \"size\": 1024,\n \"nonzero_count\": 1024,\n \"min\": 100,\n \"max\": 1123,\n \"nonzero_min_coordinate\": [\n 0,\n 0\n ],\n \"nonzero_max_coordinate\": [\n 31,\n 31\n ],\n \"nonzero_example_coordinates\": [\n [\n 0,\n 0\n ],\n [\n 2,\n 4\n ],\n [\n 4,\n 8\n ],\n [\n 6,\n 12\n ],\n [\n 8,\n 16\n ],\n [\n 10,\n 21\n ],\n [\n 12,\n 25\n ],\n [\n 14,\n 29\n ],\n [\n 17,\n 1\n ],\n [\n 19,\n 5\n ],\n [\n 21,\n 10\n ],\n [\n 23,\n 14\n ],\n [\n 25,\n 18\n ],\n [\n 27,\n 22\n ],\n [\n 29,\n 26\n ],\n [\n 31,\n 31\n ]\n ],\n \"source_voxel_spacing\": {\n \"values_zyx\": [\n 1.3556,\n 1.3556\n ],\n \"unit\": \"micrometers\"\n },\n \"spatial_origin_yx\": [\n 0,\n 0\n ],\n \"source_spatial_shape_yx\": [\n 32,\n 32\n ],\n \"data_type\": \"image\",\n \"path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w1_z001_t001.tif\",\n \"components\": {\n \"site\": 1,\n \"channel\": 1,\n \"z_index\": 1,\n \"timepoint\": 1,\n \"well\": \"A01\"\n },\n \"payload_type\": \"ndarray\"\n },\n {\n \"shape\": [\n 32,\n 32\n ],\n \"dtype\": \"uint16\",\n \"size\": 1024,\n \"nonzero_count\": 1024,\n \"min\": 200,\n \"max\": 1223,\n \"nonzero_min_coordinate\": [\n 0,\n 0\n ],\n \"nonzero_max_coordinate\": [\n 31,\n 31\n ],\n \"nonzero_example_coordinates\": [\n [\n 0,\n 0\n ],\n [\n 2,\n 4\n ],\n [\n 4,\n 8\n ],\n [\n 6,\n 12\n ],\n [\n 8,\n 16\n ],\n [\n 10,\n 21\n ],\n [\n 12,\n 25\n ],\n [\n 14,\n 29\n ],\n [\n 17,\n 1\n ],\n [\n 19,\n 5\n ],\n [\n 21,\n 10\n ],\n [\n 23,\n 14\n ],\n [\n 25,\n 18\n ],\n [\n 27,\n 22\n ],\n [\n 29,\n 26\n ],\n [\n 31,\n 31\n ]\n ],\n \"source_voxel_spacing\": {\n \"values_zyx\": [\n 1.3556,\n 1.3556\n ],\n \"unit\": \"micrometers\"\n },\n \"spatial_origin_yx\": [\n 0,\n 0\n ],\n \"source_spatial_shape_yx\": [\n 32,\n 32\n ],\n \"data_type\": \"image\",\n \"path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w2_z001_t001.tif\",\n \"components\": {\n \"site\": 1,\n \"channel\": 2,\n \"z_index\": 1,\n \"timepoint\": 1,\n \"well\": \"A01\"\n },\n \"payload_type\": \"ndarray\"\n }\n ],\n \"payload_summary_count\": 2,\n \"payload_summaries_truncated\": false,\n \"axis_labels\": [\n \"site\",\n \"channel\",\n \"z_index\",\n \"timepoint\",\n \"well\",\n \"y\",\n \"x\"\n ],\n \"stack_axes\": [\n \"channel\"\n ],\n \"axis_offsets\": [\n 0\n ],\n \"scalar_labels\": [\n \"Site 1\",\n \"Z 1\",\n \"T 1\",\n \"Well A01\"\n ],\n \"labels\": {\n \"channel\": [\n \"Ch 1\",\n \"Ch 2\"\n ]\n },\n \"axis_component_values\": {\n \"channel\": [\n 1,\n 2\n ]\n },\n \"routed_component_values\": {\n \"channel\": [\n 1,\n 2\n ]\n },\n \"routed_component_coordinates\": [\n [\n 1\n ],\n [\n 2\n ]\n ],\n \"data_shape\": [\n 1,\n 2,\n 1,\n 1,\n 1,\n 32,\n 32\n ],\n \"native_transform\": {\n \"scale\": [\n 1.0,\n 1.0,\n 1.0,\n 1.0,\n 1.0,\n 1.3556,\n 1.3556\n ],\n \"translate\": [\n 0.0,\n 0.0,\n 0.0,\n 0.0,\n 0.0,\n 0.0,\n 0.0\n ]\n },\n \"native_intensity\": {\n \"contrast_limits\": [\n 100.0,\n 1223.0\n ],\n \"gamma\": 1.0\n },\n \"visible\": true,\n \"selected\": false,\n \"feature_row_count\": 0,\n \"selected_data_indices\": [],\n \"pending_update\": false\n },\n {\n \"route_key\": \"origin_manual_kind_manual_projection_A01_s001_w2_z001_t001_graph.graph.roi.zip_shapes\",\n \"producer_identities\": [\n {\n \"origin\": \"manual\",\n \"output_kind\": \"manual\",\n \"output_key\": \"A01_s001_w2_z001_t001_graph.graph.roi.zip\",\n \"projection_key\": \"A01_s001_w2_z001_t001_graph.graph.roi.zip\",\n \"step_name\": null,\n \"pipeline_position\": null,\n \"step_scope_id\": null,\n \"invocation_key\": null,\n \"artifact_kind\": null\n }\n ],\n \"title\": \"A01_s001_w2_z001_t001_graph.graph.roi.zip ROIs\",\n \"mounted\": true,\n \"item_count\": 1,\n \"data_types\": [\n \"shapes\"\n ],\n \"component_values\": [\n {\n \"site\": 1,\n \"channel\": 2,\n \"z_index\": 1,\n \"timepoint\": 1,\n \"well\": \"A01\"\n }\n ],\n \"component_value_count\": 1,\n \"component_values_truncated\": false,\n \"payload_summaries\": [\n {\n \"nonzero_count\": 2,\n \"item_count\": 2,\n \"shape_payload_count\": 2,\n \"missing_source_spatial_shape_count\": 2,\n \"shape_coordinate_count\": 4,\n \"shape_out_of_source_bounds_count\": 0,\n \"shape_coordinate_bounds_yx\": {\n \"min_yx\": [\n 2.25,\n 3.5\n ],\n \"max_yx\": [\n 7.25,\n 12.5\n ],\n \"coordinate_count\": 4\n },\n \"source_voxel_spacing\": {\n \"values_zyx\": [\n 1.3556,\n 1.3556\n ],\n \"unit\": \"micrometers\"\n },\n \"data_type\": \"shapes\",\n \"path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/graph_results/A01_s001_w2_z001_t001_graph.graph.roi.zip\",\n \"components\": {\n \"site\": 1,\n \"channel\": 2,\n \"z_index\": 1,\n \"timepoint\": 1,\n \"well\": \"A01\"\n },\n \"payload_type\": \"list\"\n }\n ],\n \"payload_summary_count\": 1,\n \"payload_summaries_truncated\": false,\n \"axis_labels\": [\n \"site\",\n \"channel\",\n \"z_index\",\n \"timepoint\",\n \"well\",\n \"y\",\n \"x\"\n ],\n \"stack_axes\": [\n \"channel\"\n ],\n \"axis_offsets\": [\n 1\n ],\n \"scalar_labels\": [\n \"Site 1\",\n \"Z 1\",\n \"T 1\",\n \"Well A01\"\n ],\n \"labels\": {\n \"channel\": [\n \"Ch 2\"\n ]\n },\n \"axis_component_values\": {\n \"channel\": [\n 2\n ]\n },\n \"routed_component_values\": {\n \"channel\": [\n 2\n ]\n },\n \"routed_component_coordinates\": [\n [\n 2\n ]\n ],\n \"data_shape\": [\n 2\n ],\n \"native_transform\": {\n \"scale\": [\n 1.0,\n 1.0,\n 1.0,\n 1.0,\n 1.0,\n 1.3556,\n 1.3556\n ],\n \"translate\": [\n 0.0,\n 1.0,\n 0.0,\n 0.0,\n 0.0,\n 0.0,\n 0.0\n ]\n },\n \"native_intensity\": null,\n \"visible\": true,\n \"selected\": false,\n \"feature_row_count\": 2,\n \"selected_data_indices\": [],\n \"pending_update\": false\n }\n ],\n \"native_viewport\": {\n \"center\": [\n 0.0,\n 21.011799999999997,\n 21.011799999999997\n ],\n \"zoom\": 6.635668707583358\n },\n \"native_dimensions\": {\n \"order\": [\n 0,\n 1,\n 2,\n 3,\n 4,\n 5,\n 6\n ],\n \"ndisplay\": 2,\n \"displayed_axes\": [\n \"y\",\n \"x\"\n ],\n \"point\": [\n 0.0,\n 1.0,\n 0.0,\n 0.0,\n 0.0,\n 20.334,\n 20.334\n ],\n \"camera_angles\": [\n 0.0,\n 0.0,\n 0.0\n ],\n \"canvas_size\": [\n 643,\n 478\n ]\n },\n \"active_dimension_label_route\": \"origin_manual_kind_manual_projection_selected_images_8c7357d46ccc38823ca9e68096baf86f25c3004b61b63ba1eef9adea41d34fb8_scalar_stack\",\n \"viewer_ndim\": 7,\n \"current_step\": [\n 0,\n 1,\n 0,\n 0,\n 0,\n 15,\n 15\n ],\n \"axis_labels\": [\n \"site\",\n \"channel\",\n \"z_index\",\n \"timepoint\",\n \"well\",\n \"y\",\n \"x\"\n ],\n \"component_group_count\": 3,\n \"component_item_count\": 4\n }\n}" + } + ], + "structuredContent": { + "connection": { + "host": "127.0.0.1", + "port": 6609, + "transport_mode": "tcp", + "persistent": true + }, + "schema_version": "openhcs.agent.v1", + "errors": [], + "warnings": [], + "observed": true, + "viewer": { + "viewer_type": "napari", + "title": "OpenHCS Napari Visualization" + }, + "layer_count": 3, + "layers": [ + { + "route_key": "origin_manual_kind_manual_projection_selected_images_8c7357d46ccc38823ca9e68096baf86f25c3004b61b63ba1eef9adea41d34fb8_scalar_stack", + "title": "selected_images image stack", + "mounted": true, + "item_count": 1, + "producer_identities": [ + { + "origin": "manual", + "output_kind": "manual", + "output_key": "selected_images", + "projection_key": "selected_images_8c7357d46ccc38823ca9e68096baf86f25c3004b61b63ba1eef9adea41d34fb8", + "step_name": null, + "pipeline_position": null, + "step_scope_id": null, + "invocation_key": null, + "artifact_kind": null + } + ], + "axis_labels": [ + "site", + "channel", + "z_index", + "timepoint", + "well", + "y", + "x" + ], + "stack_axes": [ + "channel" + ], + "pending_update": false, + "data_types": [ + "image" + ], + "component_values": [ + { + "site": 1, + "z_index": 1, + "timepoint": 1, + "well": "A01" + } + ], + "component_value_count": 1, + "component_values_truncated": false, + "payload_summaries": [ + { + "shape": [ + 2, + 32, + 32 + ], + "dtype": "uint16", + "size": 2048, + "nonzero_count": 308, + "min": 0, + "max": 22, + "nonzero_min_coordinate": [ + 0, + 3, + 4 + ], + "nonzero_max_coordinate": [ + 1, + 24, + 27 + ], + "nonzero_example_coordinates": [ + [ + 0, + 3, + 4 + ], + [ + 0, + 5, + 4 + ], + [ + 0, + 7, + 4 + ], + [ + 0, + 9, + 5 + ], + [ + 0, + 11, + 5 + ], + [ + 0, + 18, + 24 + ], + [ + 0, + 21, + 20 + ], + [ + 0, + 23, + 25 + ], + [ + 1, + 3, + 13 + ], + [ + 1, + 6, + 4 + ], + [ + 1, + 8, + 4 + ], + [ + 1, + 10, + 5 + ], + [ + 1, + 17, + 21 + ], + [ + 1, + 19, + 26 + ], + [ + 1, + 22, + 22 + ], + [ + 1, + 24, + 27 + ] + ], + "source_voxel_spacing": { + "values_zyx": [ + 1.3556, + 1.3556 + ], + "unit": "micrometers" + }, + "spatial_origin_yx": [ + 0, + 0 + ], + "source_spatial_shape_yx": [ + 32, + 32 + ], + "aggregate_component_values": { + "channel": [ + 2, + 1 + ] + }, + "data_type": "image", + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/stacked_labels/A01_s001_w2_z001_t001_Labels.tif", + "components": { + "site": 1, + "z_index": 1, + "timepoint": 1, + "well": "A01" + }, + "payload_type": "ndarray" + } + ], + "payload_summary_count": 1, + "payload_summaries_truncated": false, + "axis_offsets": [ + 0 + ], + "scalar_labels": [ + "Site 1", + "Z 1", + "T 1", + "Well A01" + ], + "labels": { + "channel": [ + "Ch 1", + "Ch 2" + ] + }, + "axis_component_values": { + "channel": [ + 1, + 2 + ] + }, + "routed_component_values": { + "channel": [ + 1, + 2 + ] + }, + "routed_component_coordinates": [ + [ + 1 + ], + [ + 2 + ] + ], + "data_shape": [ + 1, + 2, + 1, + 1, + 1, + 32, + 32 + ], + "native_transform": { + "scale": [ + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.3556, + 1.3556 + ], + "translate": [ + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0 + ] + }, + "native_intensity": { + "contrast_limits": [ + 0.0, + 22.0 + ], + "gamma": 1.0 + }, + "visible": true, + "selected": true, + "feature_row_count": 0, + "selected_data_indices": [] + }, + { + "route_key": "origin_manual_kind_manual_projection_selected_images_e83ddc2185a63aca4b85ec471143f61c8f4eabdb08df3557ca21f2bddcda60b9", + "title": "selected_images", + "mounted": true, + "item_count": 2, + "producer_identities": [ + { + "origin": "manual", + "output_kind": "manual", + "output_key": "selected_images", + "projection_key": "selected_images_e83ddc2185a63aca4b85ec471143f61c8f4eabdb08df3557ca21f2bddcda60b9", + "step_name": null, + "pipeline_position": null, + "step_scope_id": null, + "invocation_key": null, + "artifact_kind": null + } + ], + "axis_labels": [ + "site", + "channel", + "z_index", + "timepoint", + "well", + "y", + "x" + ], + "stack_axes": [ + "channel" + ], + "pending_update": false, + "data_types": [ + "image" + ], + "component_values": [ + { + "site": 1, + "channel": 1, + "z_index": 1, + "timepoint": 1, + "well": "A01" + }, + { + "site": 1, + "channel": 2, + "z_index": 1, + "timepoint": 1, + "well": "A01" + } + ], + "component_value_count": 2, + "component_values_truncated": false, + "payload_summaries": [ + { + "shape": [ + 32, + 32 + ], + "dtype": "uint16", + "size": 1024, + "nonzero_count": 1024, + "min": 100, + "max": 1123, + "nonzero_min_coordinate": [ + 0, + 0 + ], + "nonzero_max_coordinate": [ + 31, + 31 + ], + "nonzero_example_coordinates": [ + [ + 0, + 0 + ], + [ + 2, + 4 + ], + [ + 4, + 8 + ], + [ + 6, + 12 + ], + [ + 8, + 16 + ], + [ + 10, + 21 + ], + [ + 12, + 25 + ], + [ + 14, + 29 + ], + [ + 17, + 1 + ], + [ + 19, + 5 + ], + [ + 21, + 10 + ], + [ + 23, + 14 + ], + [ + 25, + 18 + ], + [ + 27, + 22 + ], + [ + 29, + 26 + ], + [ + 31, + 31 + ] + ], + "source_voxel_spacing": { + "values_zyx": [ + 1.3556, + 1.3556 + ], + "unit": "micrometers" + }, + "spatial_origin_yx": [ + 0, + 0 + ], + "source_spatial_shape_yx": [ + 32, + 32 + ], + "data_type": "image", + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w1_z001_t001.tif", + "components": { + "site": 1, + "channel": 1, + "z_index": 1, + "timepoint": 1, + "well": "A01" + }, + "payload_type": "ndarray" + }, + { + "shape": [ + 32, + 32 + ], + "dtype": "uint16", + "size": 1024, + "nonzero_count": 1024, + "min": 200, + "max": 1223, + "nonzero_min_coordinate": [ + 0, + 0 + ], + "nonzero_max_coordinate": [ + 31, + 31 + ], + "nonzero_example_coordinates": [ + [ + 0, + 0 + ], + [ + 2, + 4 + ], + [ + 4, + 8 + ], + [ + 6, + 12 + ], + [ + 8, + 16 + ], + [ + 10, + 21 + ], + [ + 12, + 25 + ], + [ + 14, + 29 + ], + [ + 17, + 1 + ], + [ + 19, + 5 + ], + [ + 21, + 10 + ], + [ + 23, + 14 + ], + [ + 25, + 18 + ], + [ + 27, + 22 + ], + [ + 29, + 26 + ], + [ + 31, + 31 + ] + ], + "source_voxel_spacing": { + "values_zyx": [ + 1.3556, + 1.3556 + ], + "unit": "micrometers" + }, + "spatial_origin_yx": [ + 0, + 0 + ], + "source_spatial_shape_yx": [ + 32, + 32 + ], + "data_type": "image", + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w2_z001_t001.tif", + "components": { + "site": 1, + "channel": 2, + "z_index": 1, + "timepoint": 1, + "well": "A01" + }, + "payload_type": "ndarray" + } + ], + "payload_summary_count": 2, + "payload_summaries_truncated": false, + "axis_offsets": [ + 0 + ], + "scalar_labels": [ + "Site 1", + "Z 1", + "T 1", + "Well A01" + ], + "labels": { + "channel": [ + "Ch 1", + "Ch 2" + ] + }, + "axis_component_values": { + "channel": [ + 1, + 2 + ] + }, + "routed_component_values": { + "channel": [ + 1, + 2 + ] + }, + "routed_component_coordinates": [ + [ + 1 + ], + [ + 2 + ] + ], + "data_shape": [ + 1, + 2, + 1, + 1, + 1, + 32, + 32 + ], + "native_transform": { + "scale": [ + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.3556, + 1.3556 + ], + "translate": [ + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0 + ] + }, + "native_intensity": { + "contrast_limits": [ + 100.0, + 1223.0 + ], + "gamma": 1.0 + }, + "visible": true, + "selected": false, + "feature_row_count": 0, + "selected_data_indices": [] + }, + { + "route_key": "origin_manual_kind_manual_projection_A01_s001_w2_z001_t001_graph.graph.roi.zip_shapes", + "title": "A01_s001_w2_z001_t001_graph.graph.roi.zip ROIs", + "mounted": true, + "item_count": 1, + "producer_identities": [ + { + "origin": "manual", + "output_kind": "manual", + "output_key": "A01_s001_w2_z001_t001_graph.graph.roi.zip", + "projection_key": "A01_s001_w2_z001_t001_graph.graph.roi.zip", + "step_name": null, + "pipeline_position": null, + "step_scope_id": null, + "invocation_key": null, + "artifact_kind": null + } + ], + "axis_labels": [ + "site", + "channel", + "z_index", + "timepoint", + "well", + "y", + "x" + ], + "stack_axes": [ + "channel" + ], + "pending_update": false, + "data_types": [ + "shapes" + ], + "component_values": [ + { + "site": 1, + "channel": 2, + "z_index": 1, + "timepoint": 1, + "well": "A01" + } + ], + "component_value_count": 1, + "component_values_truncated": false, + "payload_summaries": [ + { + "nonzero_count": 2, + "item_count": 2, + "shape_payload_count": 2, + "missing_source_spatial_shape_count": 2, + "shape_coordinate_count": 4, + "shape_out_of_source_bounds_count": 0, + "shape_coordinate_bounds_yx": { + "min_yx": [ + 2.25, + 3.5 + ], + "max_yx": [ + 7.25, + 12.5 + ], + "coordinate_count": 4 + }, + "source_voxel_spacing": { + "values_zyx": [ + 1.3556, + 1.3556 + ], + "unit": "micrometers" + }, + "data_type": "shapes", + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/graph_results/A01_s001_w2_z001_t001_graph.graph.roi.zip", + "components": { + "site": 1, + "channel": 2, + "z_index": 1, + "timepoint": 1, + "well": "A01" + }, + "payload_type": "list" + } + ], + "payload_summary_count": 1, + "payload_summaries_truncated": false, + "axis_offsets": [ + 1 + ], + "scalar_labels": [ + "Site 1", + "Z 1", + "T 1", + "Well A01" + ], + "labels": { + "channel": [ + "Ch 2" + ] + }, + "axis_component_values": { + "channel": [ + 2 + ] + }, + "routed_component_values": { + "channel": [ + 2 + ] + }, + "routed_component_coordinates": [ + [ + 2 + ] + ], + "data_shape": [ + 2 + ], + "native_transform": { + "scale": [ + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.3556, + 1.3556 + ], + "translate": [ + 0.0, + 1.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0 + ] + }, + "native_intensity": null, + "visible": true, + "selected": false, + "feature_row_count": 2, + "selected_data_indices": [] + } + ], + "active_dimension_label_route": "origin_manual_kind_manual_projection_selected_images_8c7357d46ccc38823ca9e68096baf86f25c3004b61b63ba1eef9adea41d34fb8_scalar_stack", + "viewer_ndim": 7, + "current_step": [ + 0, + 1, + 0, + 0, + 0, + 15, + 15 + ], + "axis_labels": [ + "site", + "channel", + "z_index", + "timepoint", + "well", + "y", + "x" + ], + "component_group_count": 3, + "component_item_count": 4, + "native_viewport": { + "center": [ + 0.0, + 21.011799999999997, + 21.011799999999997 + ], + "zoom": 6.635668707583358 + }, + "native_dimensions": { + "order": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6 + ], + "ndisplay": 2, + "displayed_axes": [ + "y", + "x" + ], + "point": [ + 0.0, + 1.0, + 0.0, + 0.0, + 0.0, + 20.334, + 20.334 + ], + "camera_angles": [ + 0.0, + 0.0, + 0.0 + ], + "canvas_size": [ + 643, + 478 + ] + }, + "response": { + "type": "state_ack", + "status": "success", + "viewer": { + "type": "napari", + "title": "OpenHCS Napari Visualization" + }, + "layer_count": 3, + "layers": [ + { + "route_key": "origin_manual_kind_manual_projection_selected_images_8c7357d46ccc38823ca9e68096baf86f25c3004b61b63ba1eef9adea41d34fb8_scalar_stack", + "producer_identities": [ + { + "origin": "manual", + "output_kind": "manual", + "output_key": "selected_images", + "projection_key": "selected_images_8c7357d46ccc38823ca9e68096baf86f25c3004b61b63ba1eef9adea41d34fb8", + "step_name": null, + "pipeline_position": null, + "step_scope_id": null, + "invocation_key": null, + "artifact_kind": null + } + ], + "title": "selected_images image stack", + "mounted": true, + "item_count": 1, + "data_types": [ + "image" + ], + "component_values": [ + { + "site": 1, + "z_index": 1, + "timepoint": 1, + "well": "A01" + } + ], + "component_value_count": 1, + "component_values_truncated": false, + "payload_summaries": [ + { + "shape": [ + 2, + 32, + 32 + ], + "dtype": "uint16", + "size": 2048, + "nonzero_count": 308, + "min": 0, + "max": 22, + "nonzero_min_coordinate": [ + 0, + 3, + 4 + ], + "nonzero_max_coordinate": [ + 1, + 24, + 27 + ], + "nonzero_example_coordinates": [ + [ + 0, + 3, + 4 + ], + [ + 0, + 5, + 4 + ], + [ + 0, + 7, + 4 + ], + [ + 0, + 9, + 5 + ], + [ + 0, + 11, + 5 + ], + [ + 0, + 18, + 24 + ], + [ + 0, + 21, + 20 + ], + [ + 0, + 23, + 25 + ], + [ + 1, + 3, + 13 + ], + [ + 1, + 6, + 4 + ], + [ + 1, + 8, + 4 + ], + [ + 1, + 10, + 5 + ], + [ + 1, + 17, + 21 + ], + [ + 1, + 19, + 26 + ], + [ + 1, + 22, + 22 + ], + [ + 1, + 24, + 27 + ] + ], + "source_voxel_spacing": { + "values_zyx": [ + 1.3556, + 1.3556 + ], + "unit": "micrometers" + }, + "spatial_origin_yx": [ + 0, + 0 + ], + "source_spatial_shape_yx": [ + 32, + 32 + ], + "aggregate_component_values": { + "channel": [ + 2, + 1 + ] + }, + "data_type": "image", + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/stacked_labels/A01_s001_w2_z001_t001_Labels.tif", + "components": { + "site": 1, + "z_index": 1, + "timepoint": 1, + "well": "A01" + }, + "payload_type": "ndarray" + } + ], + "payload_summary_count": 1, + "payload_summaries_truncated": false, + "axis_labels": [ + "site", + "channel", + "z_index", + "timepoint", + "well", + "y", + "x" + ], + "stack_axes": [ + "channel" + ], + "axis_offsets": [ + 0 + ], + "scalar_labels": [ + "Site 1", + "Z 1", + "T 1", + "Well A01" + ], + "labels": { + "channel": [ + "Ch 1", + "Ch 2" + ] + }, + "axis_component_values": { + "channel": [ + 1, + 2 + ] + }, + "routed_component_values": { + "channel": [ + 1, + 2 + ] + }, + "routed_component_coordinates": [ + [ + 1 + ], + [ + 2 + ] + ], + "data_shape": [ + 1, + 2, + 1, + 1, + 1, + 32, + 32 + ], + "native_transform": { + "scale": [ + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.3556, + 1.3556 + ], + "translate": [ + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0 + ] + }, + "native_intensity": { + "contrast_limits": [ + 0.0, + 22.0 + ], + "gamma": 1.0 + }, + "visible": true, + "selected": true, + "feature_row_count": 0, + "selected_data_indices": [], + "pending_update": false + }, + { + "route_key": "origin_manual_kind_manual_projection_selected_images_e83ddc2185a63aca4b85ec471143f61c8f4eabdb08df3557ca21f2bddcda60b9", + "producer_identities": [ + { + "origin": "manual", + "output_kind": "manual", + "output_key": "selected_images", + "projection_key": "selected_images_e83ddc2185a63aca4b85ec471143f61c8f4eabdb08df3557ca21f2bddcda60b9", + "step_name": null, + "pipeline_position": null, + "step_scope_id": null, + "invocation_key": null, + "artifact_kind": null + } + ], + "title": "selected_images", + "mounted": true, + "item_count": 2, + "data_types": [ + "image" + ], + "component_values": [ + { + "site": 1, + "channel": 1, + "z_index": 1, + "timepoint": 1, + "well": "A01" + }, + { + "site": 1, + "channel": 2, + "z_index": 1, + "timepoint": 1, + "well": "A01" + } + ], + "component_value_count": 2, + "component_values_truncated": false, + "payload_summaries": [ + { + "shape": [ + 32, + 32 + ], + "dtype": "uint16", + "size": 1024, + "nonzero_count": 1024, + "min": 100, + "max": 1123, + "nonzero_min_coordinate": [ + 0, + 0 + ], + "nonzero_max_coordinate": [ + 31, + 31 + ], + "nonzero_example_coordinates": [ + [ + 0, + 0 + ], + [ + 2, + 4 + ], + [ + 4, + 8 + ], + [ + 6, + 12 + ], + [ + 8, + 16 + ], + [ + 10, + 21 + ], + [ + 12, + 25 + ], + [ + 14, + 29 + ], + [ + 17, + 1 + ], + [ + 19, + 5 + ], + [ + 21, + 10 + ], + [ + 23, + 14 + ], + [ + 25, + 18 + ], + [ + 27, + 22 + ], + [ + 29, + 26 + ], + [ + 31, + 31 + ] + ], + "source_voxel_spacing": { + "values_zyx": [ + 1.3556, + 1.3556 + ], + "unit": "micrometers" + }, + "spatial_origin_yx": [ + 0, + 0 + ], + "source_spatial_shape_yx": [ + 32, + 32 + ], + "data_type": "image", + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w1_z001_t001.tif", + "components": { + "site": 1, + "channel": 1, + "z_index": 1, + "timepoint": 1, + "well": "A01" + }, + "payload_type": "ndarray" + }, + { + "shape": [ + 32, + 32 + ], + "dtype": "uint16", + "size": 1024, + "nonzero_count": 1024, + "min": 200, + "max": 1223, + "nonzero_min_coordinate": [ + 0, + 0 + ], + "nonzero_max_coordinate": [ + 31, + 31 + ], + "nonzero_example_coordinates": [ + [ + 0, + 0 + ], + [ + 2, + 4 + ], + [ + 4, + 8 + ], + [ + 6, + 12 + ], + [ + 8, + 16 + ], + [ + 10, + 21 + ], + [ + 12, + 25 + ], + [ + 14, + 29 + ], + [ + 17, + 1 + ], + [ + 19, + 5 + ], + [ + 21, + 10 + ], + [ + 23, + 14 + ], + [ + 25, + 18 + ], + [ + 27, + 22 + ], + [ + 29, + 26 + ], + [ + 31, + 31 + ] + ], + "source_voxel_spacing": { + "values_zyx": [ + 1.3556, + 1.3556 + ], + "unit": "micrometers" + }, + "spatial_origin_yx": [ + 0, + 0 + ], + "source_spatial_shape_yx": [ + 32, + 32 + ], + "data_type": "image", + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w2_z001_t001.tif", + "components": { + "site": 1, + "channel": 2, + "z_index": 1, + "timepoint": 1, + "well": "A01" + }, + "payload_type": "ndarray" + } + ], + "payload_summary_count": 2, + "payload_summaries_truncated": false, + "axis_labels": [ + "site", + "channel", + "z_index", + "timepoint", + "well", + "y", + "x" + ], + "stack_axes": [ + "channel" + ], + "axis_offsets": [ + 0 + ], + "scalar_labels": [ + "Site 1", + "Z 1", + "T 1", + "Well A01" + ], + "labels": { + "channel": [ + "Ch 1", + "Ch 2" + ] + }, + "axis_component_values": { + "channel": [ + 1, + 2 + ] + }, + "routed_component_values": { + "channel": [ + 1, + 2 + ] + }, + "routed_component_coordinates": [ + [ + 1 + ], + [ + 2 + ] + ], + "data_shape": [ + 1, + 2, + 1, + 1, + 1, + 32, + 32 + ], + "native_transform": { + "scale": [ + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.3556, + 1.3556 + ], + "translate": [ + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0 + ] + }, + "native_intensity": { + "contrast_limits": [ + 100.0, + 1223.0 + ], + "gamma": 1.0 + }, + "visible": true, + "selected": false, + "feature_row_count": 0, + "selected_data_indices": [], + "pending_update": false + }, + { + "route_key": "origin_manual_kind_manual_projection_A01_s001_w2_z001_t001_graph.graph.roi.zip_shapes", + "producer_identities": [ + { + "origin": "manual", + "output_kind": "manual", + "output_key": "A01_s001_w2_z001_t001_graph.graph.roi.zip", + "projection_key": "A01_s001_w2_z001_t001_graph.graph.roi.zip", + "step_name": null, + "pipeline_position": null, + "step_scope_id": null, + "invocation_key": null, + "artifact_kind": null + } + ], + "title": "A01_s001_w2_z001_t001_graph.graph.roi.zip ROIs", + "mounted": true, + "item_count": 1, + "data_types": [ + "shapes" + ], + "component_values": [ + { + "site": 1, + "channel": 2, + "z_index": 1, + "timepoint": 1, + "well": "A01" + } + ], + "component_value_count": 1, + "component_values_truncated": false, + "payload_summaries": [ + { + "nonzero_count": 2, + "item_count": 2, + "shape_payload_count": 2, + "missing_source_spatial_shape_count": 2, + "shape_coordinate_count": 4, + "shape_out_of_source_bounds_count": 0, + "shape_coordinate_bounds_yx": { + "min_yx": [ + 2.25, + 3.5 + ], + "max_yx": [ + 7.25, + 12.5 + ], + "coordinate_count": 4 + }, + "source_voxel_spacing": { + "values_zyx": [ + 1.3556, + 1.3556 + ], + "unit": "micrometers" + }, + "data_type": "shapes", + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/graph_results/A01_s001_w2_z001_t001_graph.graph.roi.zip", + "components": { + "site": 1, + "channel": 2, + "z_index": 1, + "timepoint": 1, + "well": "A01" + }, + "payload_type": "list" + } + ], + "payload_summary_count": 1, + "payload_summaries_truncated": false, + "axis_labels": [ + "site", + "channel", + "z_index", + "timepoint", + "well", + "y", + "x" + ], + "stack_axes": [ + "channel" + ], + "axis_offsets": [ + 1 + ], + "scalar_labels": [ + "Site 1", + "Z 1", + "T 1", + "Well A01" + ], + "labels": { + "channel": [ + "Ch 2" + ] + }, + "axis_component_values": { + "channel": [ + 2 + ] + }, + "routed_component_values": { + "channel": [ + 2 + ] + }, + "routed_component_coordinates": [ + [ + 2 + ] + ], + "data_shape": [ + 2 + ], + "native_transform": { + "scale": [ + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.3556, + 1.3556 + ], + "translate": [ + 0.0, + 1.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0 + ] + }, + "native_intensity": null, + "visible": true, + "selected": false, + "feature_row_count": 2, + "selected_data_indices": [], + "pending_update": false + } + ], + "native_viewport": { + "center": [ + 0.0, + 21.011799999999997, + 21.011799999999997 + ], + "zoom": 6.635668707583358 + }, + "native_dimensions": { + "order": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6 + ], + "ndisplay": 2, + "displayed_axes": [ + "y", + "x" + ], + "point": [ + 0.0, + 1.0, + 0.0, + 0.0, + 0.0, + 20.334, + 20.334 + ], + "camera_angles": [ + 0.0, + 0.0, + 0.0 + ], + "canvas_size": [ + 643, + 478 + ] + }, + "active_dimension_label_route": "origin_manual_kind_manual_projection_selected_images_8c7357d46ccc38823ca9e68096baf86f25c3004b61b63ba1eef9adea41d34fb8_scalar_stack", + "viewer_ndim": 7, + "current_step": [ + 0, + 1, + 0, + 0, + 0, + 15, + 15 + ], + "axis_labels": [ + "site", + "channel", + "z_index", + "timepoint", + "well", + "y", + "x" + ], + "component_group_count": 3, + "component_item_count": 4 + } + }, + "isError": false + }, + "payload": { + "connection": { + "host": "127.0.0.1", + "port": 6609, + "transport_mode": "tcp", + "persistent": true + }, + "schema_version": "openhcs.agent.v1", + "errors": [], + "warnings": [], + "observed": true, + "viewer": { + "viewer_type": "napari", + "title": "OpenHCS Napari Visualization" + }, + "layer_count": 3, + "layers": [ + { + "route_key": "origin_manual_kind_manual_projection_selected_images_8c7357d46ccc38823ca9e68096baf86f25c3004b61b63ba1eef9adea41d34fb8_scalar_stack", + "title": "selected_images image stack", + "mounted": true, + "item_count": 1, + "producer_identities": [ + { + "origin": "manual", + "output_kind": "manual", + "output_key": "selected_images", + "projection_key": "selected_images_8c7357d46ccc38823ca9e68096baf86f25c3004b61b63ba1eef9adea41d34fb8", + "step_name": null, + "pipeline_position": null, + "step_scope_id": null, + "invocation_key": null, + "artifact_kind": null + } + ], + "axis_labels": [ + "site", + "channel", + "z_index", + "timepoint", + "well", + "y", + "x" + ], + "stack_axes": [ + "channel" + ], + "pending_update": false, + "data_types": [ + "image" + ], + "component_values": [ + { + "site": 1, + "z_index": 1, + "timepoint": 1, + "well": "A01" + } + ], + "component_value_count": 1, + "component_values_truncated": false, + "payload_summaries": [ + { + "shape": [ + 2, + 32, + 32 + ], + "dtype": "uint16", + "size": 2048, + "nonzero_count": 308, + "min": 0, + "max": 22, + "nonzero_min_coordinate": [ + 0, + 3, + 4 + ], + "nonzero_max_coordinate": [ + 1, + 24, + 27 + ], + "nonzero_example_coordinates": [ + [ + 0, + 3, + 4 + ], + [ + 0, + 5, + 4 + ], + [ + 0, + 7, + 4 + ], + [ + 0, + 9, + 5 + ], + [ + 0, + 11, + 5 + ], + [ + 0, + 18, + 24 + ], + [ + 0, + 21, + 20 + ], + [ + 0, + 23, + 25 + ], + [ + 1, + 3, + 13 + ], + [ + 1, + 6, + 4 + ], + [ + 1, + 8, + 4 + ], + [ + 1, + 10, + 5 + ], + [ + 1, + 17, + 21 + ], + [ + 1, + 19, + 26 + ], + [ + 1, + 22, + 22 + ], + [ + 1, + 24, + 27 + ] + ], + "source_voxel_spacing": { + "values_zyx": [ + 1.3556, + 1.3556 + ], + "unit": "micrometers" + }, + "spatial_origin_yx": [ + 0, + 0 + ], + "source_spatial_shape_yx": [ + 32, + 32 + ], + "aggregate_component_values": { + "channel": [ + 2, + 1 + ] + }, + "data_type": "image", + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/stacked_labels/A01_s001_w2_z001_t001_Labels.tif", + "components": { + "site": 1, + "z_index": 1, + "timepoint": 1, + "well": "A01" + }, + "payload_type": "ndarray" + } + ], + "payload_summary_count": 1, + "payload_summaries_truncated": false, + "axis_offsets": [ + 0 + ], + "scalar_labels": [ + "Site 1", + "Z 1", + "T 1", + "Well A01" + ], + "labels": { + "channel": [ + "Ch 1", + "Ch 2" + ] + }, + "axis_component_values": { + "channel": [ + 1, + 2 + ] + }, + "routed_component_values": { + "channel": [ + 1, + 2 + ] + }, + "routed_component_coordinates": [ + [ + 1 + ], + [ + 2 + ] + ], + "data_shape": [ + 1, + 2, + 1, + 1, + 1, + 32, + 32 + ], + "native_transform": { + "scale": [ + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.3556, + 1.3556 + ], + "translate": [ + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0 + ] + }, + "native_intensity": { + "contrast_limits": [ + 0.0, + 22.0 + ], + "gamma": 1.0 + }, + "visible": true, + "selected": true, + "feature_row_count": 0, + "selected_data_indices": [] + }, + { + "route_key": "origin_manual_kind_manual_projection_selected_images_e83ddc2185a63aca4b85ec471143f61c8f4eabdb08df3557ca21f2bddcda60b9", + "title": "selected_images", + "mounted": true, + "item_count": 2, + "producer_identities": [ + { + "origin": "manual", + "output_kind": "manual", + "output_key": "selected_images", + "projection_key": "selected_images_e83ddc2185a63aca4b85ec471143f61c8f4eabdb08df3557ca21f2bddcda60b9", + "step_name": null, + "pipeline_position": null, + "step_scope_id": null, + "invocation_key": null, + "artifact_kind": null + } + ], + "axis_labels": [ + "site", + "channel", + "z_index", + "timepoint", + "well", + "y", + "x" + ], + "stack_axes": [ + "channel" + ], + "pending_update": false, + "data_types": [ + "image" + ], + "component_values": [ + { + "site": 1, + "channel": 1, + "z_index": 1, + "timepoint": 1, + "well": "A01" + }, + { + "site": 1, + "channel": 2, + "z_index": 1, + "timepoint": 1, + "well": "A01" + } + ], + "component_value_count": 2, + "component_values_truncated": false, + "payload_summaries": [ + { + "shape": [ + 32, + 32 + ], + "dtype": "uint16", + "size": 1024, + "nonzero_count": 1024, + "min": 100, + "max": 1123, + "nonzero_min_coordinate": [ + 0, + 0 + ], + "nonzero_max_coordinate": [ + 31, + 31 + ], + "nonzero_example_coordinates": [ + [ + 0, + 0 + ], + [ + 2, + 4 + ], + [ + 4, + 8 + ], + [ + 6, + 12 + ], + [ + 8, + 16 + ], + [ + 10, + 21 + ], + [ + 12, + 25 + ], + [ + 14, + 29 + ], + [ + 17, + 1 + ], + [ + 19, + 5 + ], + [ + 21, + 10 + ], + [ + 23, + 14 + ], + [ + 25, + 18 + ], + [ + 27, + 22 + ], + [ + 29, + 26 + ], + [ + 31, + 31 + ] + ], + "source_voxel_spacing": { + "values_zyx": [ + 1.3556, + 1.3556 + ], + "unit": "micrometers" + }, + "spatial_origin_yx": [ + 0, + 0 + ], + "source_spatial_shape_yx": [ + 32, + 32 + ], + "data_type": "image", + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w1_z001_t001.tif", + "components": { + "site": 1, + "channel": 1, + "z_index": 1, + "timepoint": 1, + "well": "A01" + }, + "payload_type": "ndarray" + }, + { + "shape": [ + 32, + 32 + ], + "dtype": "uint16", + "size": 1024, + "nonzero_count": 1024, + "min": 200, + "max": 1223, + "nonzero_min_coordinate": [ + 0, + 0 + ], + "nonzero_max_coordinate": [ + 31, + 31 + ], + "nonzero_example_coordinates": [ + [ + 0, + 0 + ], + [ + 2, + 4 + ], + [ + 4, + 8 + ], + [ + 6, + 12 + ], + [ + 8, + 16 + ], + [ + 10, + 21 + ], + [ + 12, + 25 + ], + [ + 14, + 29 + ], + [ + 17, + 1 + ], + [ + 19, + 5 + ], + [ + 21, + 10 + ], + [ + 23, + 14 + ], + [ + 25, + 18 + ], + [ + 27, + 22 + ], + [ + 29, + 26 + ], + [ + 31, + 31 + ] + ], + "source_voxel_spacing": { + "values_zyx": [ + 1.3556, + 1.3556 + ], + "unit": "micrometers" + }, + "spatial_origin_yx": [ + 0, + 0 + ], + "source_spatial_shape_yx": [ + 32, + 32 + ], + "data_type": "image", + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w2_z001_t001.tif", + "components": { + "site": 1, + "channel": 2, + "z_index": 1, + "timepoint": 1, + "well": "A01" + }, + "payload_type": "ndarray" + } + ], + "payload_summary_count": 2, + "payload_summaries_truncated": false, + "axis_offsets": [ + 0 + ], + "scalar_labels": [ + "Site 1", + "Z 1", + "T 1", + "Well A01" + ], + "labels": { + "channel": [ + "Ch 1", + "Ch 2" + ] + }, + "axis_component_values": { + "channel": [ + 1, + 2 + ] + }, + "routed_component_values": { + "channel": [ + 1, + 2 + ] + }, + "routed_component_coordinates": [ + [ + 1 + ], + [ + 2 + ] + ], + "data_shape": [ + 1, + 2, + 1, + 1, + 1, + 32, + 32 + ], + "native_transform": { + "scale": [ + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.3556, + 1.3556 + ], + "translate": [ + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0 + ] + }, + "native_intensity": { + "contrast_limits": [ + 100.0, + 1223.0 + ], + "gamma": 1.0 + }, + "visible": true, + "selected": false, + "feature_row_count": 0, + "selected_data_indices": [] + }, + { + "route_key": "origin_manual_kind_manual_projection_A01_s001_w2_z001_t001_graph.graph.roi.zip_shapes", + "title": "A01_s001_w2_z001_t001_graph.graph.roi.zip ROIs", + "mounted": true, + "item_count": 1, + "producer_identities": [ + { + "origin": "manual", + "output_kind": "manual", + "output_key": "A01_s001_w2_z001_t001_graph.graph.roi.zip", + "projection_key": "A01_s001_w2_z001_t001_graph.graph.roi.zip", + "step_name": null, + "pipeline_position": null, + "step_scope_id": null, + "invocation_key": null, + "artifact_kind": null + } + ], + "axis_labels": [ + "site", + "channel", + "z_index", + "timepoint", + "well", + "y", + "x" + ], + "stack_axes": [ + "channel" + ], + "pending_update": false, + "data_types": [ + "shapes" + ], + "component_values": [ + { + "site": 1, + "channel": 2, + "z_index": 1, + "timepoint": 1, + "well": "A01" + } + ], + "component_value_count": 1, + "component_values_truncated": false, + "payload_summaries": [ + { + "nonzero_count": 2, + "item_count": 2, + "shape_payload_count": 2, + "missing_source_spatial_shape_count": 2, + "shape_coordinate_count": 4, + "shape_out_of_source_bounds_count": 0, + "shape_coordinate_bounds_yx": { + "min_yx": [ + 2.25, + 3.5 + ], + "max_yx": [ + 7.25, + 12.5 + ], + "coordinate_count": 4 + }, + "source_voxel_spacing": { + "values_zyx": [ + 1.3556, + 1.3556 + ], + "unit": "micrometers" + }, + "data_type": "shapes", + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/graph_results/A01_s001_w2_z001_t001_graph.graph.roi.zip", + "components": { + "site": 1, + "channel": 2, + "z_index": 1, + "timepoint": 1, + "well": "A01" + }, + "payload_type": "list" + } + ], + "payload_summary_count": 1, + "payload_summaries_truncated": false, + "axis_offsets": [ + 1 + ], + "scalar_labels": [ + "Site 1", + "Z 1", + "T 1", + "Well A01" + ], + "labels": { + "channel": [ + "Ch 2" + ] + }, + "axis_component_values": { + "channel": [ + 2 + ] + }, + "routed_component_values": { + "channel": [ + 2 + ] + }, + "routed_component_coordinates": [ + [ + 2 + ] + ], + "data_shape": [ + 2 + ], + "native_transform": { + "scale": [ + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.3556, + 1.3556 + ], + "translate": [ + 0.0, + 1.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0 + ] + }, + "native_intensity": null, + "visible": true, + "selected": false, + "feature_row_count": 2, + "selected_data_indices": [] + } + ], + "active_dimension_label_route": "origin_manual_kind_manual_projection_selected_images_8c7357d46ccc38823ca9e68096baf86f25c3004b61b63ba1eef9adea41d34fb8_scalar_stack", + "viewer_ndim": 7, + "current_step": [ + 0, + 1, + 0, + 0, + 0, + 15, + 15 + ], + "axis_labels": [ + "site", + "channel", + "z_index", + "timepoint", + "well", + "y", + "x" + ], + "component_group_count": 3, + "component_item_count": 4, + "native_viewport": { + "center": [ + 0.0, + 21.011799999999997, + 21.011799999999997 + ], + "zoom": 6.635668707583358 + }, + "native_dimensions": { + "order": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6 + ], + "ndisplay": 2, + "displayed_axes": [ + "y", + "x" + ], + "point": [ + 0.0, + 1.0, + 0.0, + 0.0, + 0.0, + 20.334, + 20.334 + ], + "camera_angles": [ + 0.0, + 0.0, + 0.0 + ], + "canvas_size": [ + 643, + 478 + ] + }, + "response": { + "type": "state_ack", + "status": "success", + "viewer": { + "type": "napari", + "title": "OpenHCS Napari Visualization" + }, + "layer_count": 3, + "layers": [ + { + "route_key": "origin_manual_kind_manual_projection_selected_images_8c7357d46ccc38823ca9e68096baf86f25c3004b61b63ba1eef9adea41d34fb8_scalar_stack", + "producer_identities": [ + { + "origin": "manual", + "output_kind": "manual", + "output_key": "selected_images", + "projection_key": "selected_images_8c7357d46ccc38823ca9e68096baf86f25c3004b61b63ba1eef9adea41d34fb8", + "step_name": null, + "pipeline_position": null, + "step_scope_id": null, + "invocation_key": null, + "artifact_kind": null + } + ], + "title": "selected_images image stack", + "mounted": true, + "item_count": 1, + "data_types": [ + "image" + ], + "component_values": [ + { + "site": 1, + "z_index": 1, + "timepoint": 1, + "well": "A01" + } + ], + "component_value_count": 1, + "component_values_truncated": false, + "payload_summaries": [ + { + "shape": [ + 2, + 32, + 32 + ], + "dtype": "uint16", + "size": 2048, + "nonzero_count": 308, + "min": 0, + "max": 22, + "nonzero_min_coordinate": [ + 0, + 3, + 4 + ], + "nonzero_max_coordinate": [ + 1, + 24, + 27 + ], + "nonzero_example_coordinates": [ + [ + 0, + 3, + 4 + ], + [ + 0, + 5, + 4 + ], + [ + 0, + 7, + 4 + ], + [ + 0, + 9, + 5 + ], + [ + 0, + 11, + 5 + ], + [ + 0, + 18, + 24 + ], + [ + 0, + 21, + 20 + ], + [ + 0, + 23, + 25 + ], + [ + 1, + 3, + 13 + ], + [ + 1, + 6, + 4 + ], + [ + 1, + 8, + 4 + ], + [ + 1, + 10, + 5 + ], + [ + 1, + 17, + 21 + ], + [ + 1, + 19, + 26 + ], + [ + 1, + 22, + 22 + ], + [ + 1, + 24, + 27 + ] + ], + "source_voxel_spacing": { + "values_zyx": [ + 1.3556, + 1.3556 + ], + "unit": "micrometers" + }, + "spatial_origin_yx": [ + 0, + 0 + ], + "source_spatial_shape_yx": [ + 32, + 32 + ], + "aggregate_component_values": { + "channel": [ + 2, + 1 + ] + }, + "data_type": "image", + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/stacked_labels/A01_s001_w2_z001_t001_Labels.tif", + "components": { + "site": 1, + "z_index": 1, + "timepoint": 1, + "well": "A01" + }, + "payload_type": "ndarray" + } + ], + "payload_summary_count": 1, + "payload_summaries_truncated": false, + "axis_labels": [ + "site", + "channel", + "z_index", + "timepoint", + "well", + "y", + "x" + ], + "stack_axes": [ + "channel" + ], + "axis_offsets": [ + 0 + ], + "scalar_labels": [ + "Site 1", + "Z 1", + "T 1", + "Well A01" + ], + "labels": { + "channel": [ + "Ch 1", + "Ch 2" + ] + }, + "axis_component_values": { + "channel": [ + 1, + 2 + ] + }, + "routed_component_values": { + "channel": [ + 1, + 2 + ] + }, + "routed_component_coordinates": [ + [ + 1 + ], + [ + 2 + ] + ], + "data_shape": [ + 1, + 2, + 1, + 1, + 1, + 32, + 32 + ], + "native_transform": { + "scale": [ + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.3556, + 1.3556 + ], + "translate": [ + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0 + ] + }, + "native_intensity": { + "contrast_limits": [ + 0.0, + 22.0 + ], + "gamma": 1.0 + }, + "visible": true, + "selected": true, + "feature_row_count": 0, + "selected_data_indices": [], + "pending_update": false + }, + { + "route_key": "origin_manual_kind_manual_projection_selected_images_e83ddc2185a63aca4b85ec471143f61c8f4eabdb08df3557ca21f2bddcda60b9", + "producer_identities": [ + { + "origin": "manual", + "output_kind": "manual", + "output_key": "selected_images", + "projection_key": "selected_images_e83ddc2185a63aca4b85ec471143f61c8f4eabdb08df3557ca21f2bddcda60b9", + "step_name": null, + "pipeline_position": null, + "step_scope_id": null, + "invocation_key": null, + "artifact_kind": null + } + ], + "title": "selected_images", + "mounted": true, + "item_count": 2, + "data_types": [ + "image" + ], + "component_values": [ + { + "site": 1, + "channel": 1, + "z_index": 1, + "timepoint": 1, + "well": "A01" + }, + { + "site": 1, + "channel": 2, + "z_index": 1, + "timepoint": 1, + "well": "A01" + } + ], + "component_value_count": 2, + "component_values_truncated": false, + "payload_summaries": [ + { + "shape": [ + 32, + 32 + ], + "dtype": "uint16", + "size": 1024, + "nonzero_count": 1024, + "min": 100, + "max": 1123, + "nonzero_min_coordinate": [ + 0, + 0 + ], + "nonzero_max_coordinate": [ + 31, + 31 + ], + "nonzero_example_coordinates": [ + [ + 0, + 0 + ], + [ + 2, + 4 + ], + [ + 4, + 8 + ], + [ + 6, + 12 + ], + [ + 8, + 16 + ], + [ + 10, + 21 + ], + [ + 12, + 25 + ], + [ + 14, + 29 + ], + [ + 17, + 1 + ], + [ + 19, + 5 + ], + [ + 21, + 10 + ], + [ + 23, + 14 + ], + [ + 25, + 18 + ], + [ + 27, + 22 + ], + [ + 29, + 26 + ], + [ + 31, + 31 + ] + ], + "source_voxel_spacing": { + "values_zyx": [ + 1.3556, + 1.3556 + ], + "unit": "micrometers" + }, + "spatial_origin_yx": [ + 0, + 0 + ], + "source_spatial_shape_yx": [ + 32, + 32 + ], + "data_type": "image", + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w1_z001_t001.tif", + "components": { + "site": 1, + "channel": 1, + "z_index": 1, + "timepoint": 1, + "well": "A01" + }, + "payload_type": "ndarray" + }, + { + "shape": [ + 32, + 32 + ], + "dtype": "uint16", + "size": 1024, + "nonzero_count": 1024, + "min": 200, + "max": 1223, + "nonzero_min_coordinate": [ + 0, + 0 + ], + "nonzero_max_coordinate": [ + 31, + 31 + ], + "nonzero_example_coordinates": [ + [ + 0, + 0 + ], + [ + 2, + 4 + ], + [ + 4, + 8 + ], + [ + 6, + 12 + ], + [ + 8, + 16 + ], + [ + 10, + 21 + ], + [ + 12, + 25 + ], + [ + 14, + 29 + ], + [ + 17, + 1 + ], + [ + 19, + 5 + ], + [ + 21, + 10 + ], + [ + 23, + 14 + ], + [ + 25, + 18 + ], + [ + 27, + 22 + ], + [ + 29, + 26 + ], + [ + 31, + 31 + ] + ], + "source_voxel_spacing": { + "values_zyx": [ + 1.3556, + 1.3556 + ], + "unit": "micrometers" + }, + "spatial_origin_yx": [ + 0, + 0 + ], + "source_spatial_shape_yx": [ + 32, + 32 + ], + "data_type": "image", + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w2_z001_t001.tif", + "components": { + "site": 1, + "channel": 2, + "z_index": 1, + "timepoint": 1, + "well": "A01" + }, + "payload_type": "ndarray" + } + ], + "payload_summary_count": 2, + "payload_summaries_truncated": false, + "axis_labels": [ + "site", + "channel", + "z_index", + "timepoint", + "well", + "y", + "x" + ], + "stack_axes": [ + "channel" + ], + "axis_offsets": [ + 0 + ], + "scalar_labels": [ + "Site 1", + "Z 1", + "T 1", + "Well A01" + ], + "labels": { + "channel": [ + "Ch 1", + "Ch 2" + ] + }, + "axis_component_values": { + "channel": [ + 1, + 2 + ] + }, + "routed_component_values": { + "channel": [ + 1, + 2 + ] + }, + "routed_component_coordinates": [ + [ + 1 + ], + [ + 2 + ] + ], + "data_shape": [ + 1, + 2, + 1, + 1, + 1, + 32, + 32 + ], + "native_transform": { + "scale": [ + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.3556, + 1.3556 + ], + "translate": [ + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0 + ] + }, + "native_intensity": { + "contrast_limits": [ + 100.0, + 1223.0 + ], + "gamma": 1.0 + }, + "visible": true, + "selected": false, + "feature_row_count": 0, + "selected_data_indices": [], + "pending_update": false + }, + { + "route_key": "origin_manual_kind_manual_projection_A01_s001_w2_z001_t001_graph.graph.roi.zip_shapes", + "producer_identities": [ + { + "origin": "manual", + "output_kind": "manual", + "output_key": "A01_s001_w2_z001_t001_graph.graph.roi.zip", + "projection_key": "A01_s001_w2_z001_t001_graph.graph.roi.zip", + "step_name": null, + "pipeline_position": null, + "step_scope_id": null, + "invocation_key": null, + "artifact_kind": null + } + ], + "title": "A01_s001_w2_z001_t001_graph.graph.roi.zip ROIs", + "mounted": true, + "item_count": 1, + "data_types": [ + "shapes" + ], + "component_values": [ + { + "site": 1, + "channel": 2, + "z_index": 1, + "timepoint": 1, + "well": "A01" + } + ], + "component_value_count": 1, + "component_values_truncated": false, + "payload_summaries": [ + { + "nonzero_count": 2, + "item_count": 2, + "shape_payload_count": 2, + "missing_source_spatial_shape_count": 2, + "shape_coordinate_count": 4, + "shape_out_of_source_bounds_count": 0, + "shape_coordinate_bounds_yx": { + "min_yx": [ + 2.25, + 3.5 + ], + "max_yx": [ + 7.25, + 12.5 + ], + "coordinate_count": 4 + }, + "source_voxel_spacing": { + "values_zyx": [ + 1.3556, + 1.3556 + ], + "unit": "micrometers" + }, + "data_type": "shapes", + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/graph_results/A01_s001_w2_z001_t001_graph.graph.roi.zip", + "components": { + "site": 1, + "channel": 2, + "z_index": 1, + "timepoint": 1, + "well": "A01" + }, + "payload_type": "list" + } + ], + "payload_summary_count": 1, + "payload_summaries_truncated": false, + "axis_labels": [ + "site", + "channel", + "z_index", + "timepoint", + "well", + "y", + "x" + ], + "stack_axes": [ + "channel" + ], + "axis_offsets": [ + 1 + ], + "scalar_labels": [ + "Site 1", + "Z 1", + "T 1", + "Well A01" + ], + "labels": { + "channel": [ + "Ch 2" + ] + }, + "axis_component_values": { + "channel": [ + 2 + ] + }, + "routed_component_values": { + "channel": [ + 2 + ] + }, + "routed_component_coordinates": [ + [ + 2 + ] + ], + "data_shape": [ + 2 + ], + "native_transform": { + "scale": [ + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.3556, + 1.3556 + ], + "translate": [ + 0.0, + 1.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0 + ] + }, + "native_intensity": null, + "visible": true, + "selected": false, + "feature_row_count": 2, + "selected_data_indices": [], + "pending_update": false + } + ], + "native_viewport": { + "center": [ + 0.0, + 21.011799999999997, + 21.011799999999997 + ], + "zoom": 6.635668707583358 + }, + "native_dimensions": { + "order": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6 + ], + "ndisplay": 2, + "displayed_axes": [ + "y", + "x" + ], + "point": [ + 0.0, + 1.0, + 0.0, + 0.0, + 0.0, + 20.334, + 20.334 + ], + "camera_angles": [ + 0.0, + 0.0, + 0.0 + ], + "canvas_size": [ + 643, + 478 + ] + }, + "active_dimension_label_route": "origin_manual_kind_manual_projection_selected_images_8c7357d46ccc38823ca9e68096baf86f25c3004b61b63ba1eef9adea41d34fb8_scalar_stack", + "viewer_ndim": 7, + "current_step": [ + 0, + 1, + 0, + 0, + 0, + 15, + 15 + ], + "axis_labels": [ + "site", + "channel", + "z_index", + "timepoint", + "well", + "y", + "x" + ], + "component_group_count": 3, + "component_item_count": 4 + } + } + }, + { + "tool": "openhcs_viewer_snapshot_window", + "arguments": { + "host": "127.0.0.1", + "port": 6609, + "transport_mode": "tcp", + "output_dir_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/captures-live12/combined", + "capture_scope": "widget", + "frame_condition": "render_complete", + "observation_timeout_s": 2.5 + }, + "response": { + "content": [ + { + "type": "text", + "text": "{\n \"connection\": {\n \"host\": \"127.0.0.1\",\n \"port\": 6609,\n \"transport_mode\": \"tcp\",\n \"persistent\": true\n },\n \"schema_version\": \"openhcs.agent.v1\",\n \"errors\": [],\n \"warnings\": [],\n \"output_dir_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/captures-live12/combined\",\n \"capture_scope\": \"widget\",\n \"frame_condition\": \"render_complete\",\n \"observation_timeout_s\": 2.5,\n \"captured\": true,\n \"observation\": {\n \"condition\": \"render_complete\",\n \"window_identity\": 140451432015472,\n \"started_at_monotonic\": 3882702.950358863,\n \"completed_at_monotonic\": 3882702.966401873,\n \"configured_flash_duration_s\": 0.0,\n \"baseline_inactive\": true,\n \"flash_start_count\": 0,\n \"painted_frame_count\": 1,\n \"frame\": null,\n \"trace\": [],\n \"render_frame\": {\n \"window_identity\": 140451432015472,\n \"renderer_identity\": 140451432242288,\n \"completed_at_monotonic\": 3882702.966394539\n },\n \"observation_budget_s\": 2.4821014215704054,\n \"operation_deadline\": {\n \"operation\": \"viewer control request\",\n \"timeout_ms\": 5000,\n \"expires_at\": 3882707.914646516\n }\n },\n \"resource\": {\n \"uri\": \"file:///home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/captures-live12/combined/20261004T043045079650Z_napari_6609_OpenHCS_Napari_Visualization.png\",\n \"title\": \"OpenHCS Napari Visualization\",\n \"mime_type\": \"image/png\",\n \"path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/captures-live12/combined/20261004T043045079650Z_napari_6609_OpenHCS_Napari_Visualization.png\",\n \"size_bytes\": 83684,\n \"sha256\": \"a0b0492b919e4ecbc1c9eca2bff5f9fc0580a8d38365499ffddb9ea127ecec84\"\n },\n \"viewer\": {\n \"viewer_type\": \"napari\",\n \"title\": \"OpenHCS Napari Visualization\"\n },\n \"width\": 1152,\n \"height\": 963,\n \"response\": {\n \"type\": \"screenshot_ack\",\n \"status\": \"success\",\n \"viewer\": {\n \"type\": \"napari\",\n \"title\": \"OpenHCS Napari Visualization\"\n },\n \"resource\": {\n \"uri\": \"file:///home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/captures-live12/combined/20261004T043045079650Z_napari_6609_OpenHCS_Napari_Visualization.png\",\n \"title\": \"OpenHCS Napari Visualization\",\n \"mime_type\": \"image/png\",\n \"path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/captures-live12/combined/20261004T043045079650Z_napari_6609_OpenHCS_Napari_Visualization.png\",\n \"size_bytes\": 83684,\n \"sha256\": \"a0b0492b919e4ecbc1c9eca2bff5f9fc0580a8d38365499ffddb9ea127ecec84\"\n },\n \"width\": 1152,\n \"height\": 963,\n \"snapshot\": {\n \"connection\": {\n \"host\": \"127.0.0.1\",\n \"port\": 6609,\n \"transport_mode\": \"tcp\",\n \"persistent\": true\n },\n \"timeout_ms\": 5000,\n \"include_response\": true,\n \"operation_deadline\": {\n \"operation\": \"viewer control request\",\n \"timeout_ms\": 5000,\n \"expires_at\": 3882707.914646516\n },\n \"output_dir_path\": \"/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/captures-live12/combined\",\n \"capture_scope\": \"widget\",\n \"frame_condition\": \"render_complete\",\n \"observation_timeout_s\": 2.5\n },\n \"observation\": {\n \"condition\": \"render_complete\",\n \"window_identity\": 140451432015472,\n \"started_at_monotonic\": 3882702.950358863,\n \"completed_at_monotonic\": 3882702.966401873,\n \"configured_flash_duration_s\": 0.0,\n \"baseline_inactive\": true,\n \"flash_start_count\": 0,\n \"painted_frame_count\": 1,\n \"frame\": null,\n \"trace\": [],\n \"render_frame\": {\n \"window_identity\": 140451432015472,\n \"renderer_identity\": 140451432242288,\n \"completed_at_monotonic\": 3882702.966394539\n },\n \"observation_budget_s\": 2.4821014215704054,\n \"operation_deadline\": {\n \"operation\": \"viewer control request\",\n \"timeout_ms\": 5000,\n \"expires_at\": 3882707.914646516\n }\n },\n \"native_dimensions\": {\n \"order\": [\n 0,\n 1,\n 2,\n 3,\n 4,\n 5,\n 6\n ],\n \"ndisplay\": 2,\n \"displayed_axes\": [\n \"y\",\n \"x\"\n ],\n \"point\": [\n 0.0,\n 1.0,\n 0.0,\n 0.0,\n 0.0,\n 20.334,\n 20.334\n ],\n \"camera_angles\": [\n 0.0,\n 0.0,\n 0.0\n ],\n \"canvas_size\": [\n 643,\n 478\n ]\n }\n }\n}" + } + ], + "structuredContent": { + "connection": { + "host": "127.0.0.1", + "port": 6609, + "transport_mode": "tcp", + "persistent": true + }, + "schema_version": "openhcs.agent.v1", + "errors": [], + "warnings": [], + "output_dir_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/captures-live12/combined", + "capture_scope": "widget", + "frame_condition": "render_complete", + "observation_timeout_s": 2.5, + "captured": true, + "observation": { + "condition": "render_complete", + "window_identity": 140451432015472, + "started_at_monotonic": 3882702.950358863, + "completed_at_monotonic": 3882702.966401873, + "configured_flash_duration_s": 0.0, + "baseline_inactive": true, + "flash_start_count": 0, + "painted_frame_count": 1, + "frame": null, + "trace": [], + "render_frame": { + "window_identity": 140451432015472, + "renderer_identity": 140451432242288, + "completed_at_monotonic": 3882702.966394539 + }, + "observation_budget_s": 2.4821014215704054, + "operation_deadline": { + "operation": "viewer control request", + "timeout_ms": 5000, + "expires_at": 3882707.914646516 + } + }, + "resource": { + "uri": "file:///home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/captures-live12/combined/20261004T043045079650Z_napari_6609_OpenHCS_Napari_Visualization.png", + "title": "OpenHCS Napari Visualization", + "mime_type": "image/png", + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/captures-live12/combined/20261004T043045079650Z_napari_6609_OpenHCS_Napari_Visualization.png", + "size_bytes": 83684, + "sha256": "a0b0492b919e4ecbc1c9eca2bff5f9fc0580a8d38365499ffddb9ea127ecec84" + }, + "viewer": { + "viewer_type": "napari", + "title": "OpenHCS Napari Visualization" + }, + "width": 1152, + "height": 963, + "response": { + "type": "screenshot_ack", + "status": "success", + "viewer": { + "type": "napari", + "title": "OpenHCS Napari Visualization" + }, + "resource": { + "uri": "file:///home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/captures-live12/combined/20261004T043045079650Z_napari_6609_OpenHCS_Napari_Visualization.png", + "title": "OpenHCS Napari Visualization", + "mime_type": "image/png", + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/captures-live12/combined/20261004T043045079650Z_napari_6609_OpenHCS_Napari_Visualization.png", + "size_bytes": 83684, + "sha256": "a0b0492b919e4ecbc1c9eca2bff5f9fc0580a8d38365499ffddb9ea127ecec84" + }, + "width": 1152, + "height": 963, + "snapshot": { + "connection": { + "host": "127.0.0.1", + "port": 6609, + "transport_mode": "tcp", + "persistent": true + }, + "timeout_ms": 5000, + "include_response": true, + "operation_deadline": { + "operation": "viewer control request", + "timeout_ms": 5000, + "expires_at": 3882707.914646516 + }, + "output_dir_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/captures-live12/combined", + "capture_scope": "widget", + "frame_condition": "render_complete", + "observation_timeout_s": 2.5 + }, + "observation": { + "condition": "render_complete", + "window_identity": 140451432015472, + "started_at_monotonic": 3882702.950358863, + "completed_at_monotonic": 3882702.966401873, + "configured_flash_duration_s": 0.0, + "baseline_inactive": true, + "flash_start_count": 0, + "painted_frame_count": 1, + "frame": null, + "trace": [], + "render_frame": { + "window_identity": 140451432015472, + "renderer_identity": 140451432242288, + "completed_at_monotonic": 3882702.966394539 + }, + "observation_budget_s": 2.4821014215704054, + "operation_deadline": { + "operation": "viewer control request", + "timeout_ms": 5000, + "expires_at": 3882707.914646516 + } + }, + "native_dimensions": { + "order": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6 + ], + "ndisplay": 2, + "displayed_axes": [ + "y", + "x" + ], + "point": [ + 0.0, + 1.0, + 0.0, + 0.0, + 0.0, + 20.334, + 20.334 + ], + "camera_angles": [ + 0.0, + 0.0, + 0.0 + ], + "canvas_size": [ + 643, + 478 + ] + } + } + }, + "isError": false + }, + "payload": { + "connection": { + "host": "127.0.0.1", + "port": 6609, + "transport_mode": "tcp", + "persistent": true + }, + "schema_version": "openhcs.agent.v1", + "errors": [], + "warnings": [], + "output_dir_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/captures-live12/combined", + "capture_scope": "widget", + "frame_condition": "render_complete", + "observation_timeout_s": 2.5, + "captured": true, + "observation": { + "condition": "render_complete", + "window_identity": 140451432015472, + "started_at_monotonic": 3882702.950358863, + "completed_at_monotonic": 3882702.966401873, + "configured_flash_duration_s": 0.0, + "baseline_inactive": true, + "flash_start_count": 0, + "painted_frame_count": 1, + "frame": null, + "trace": [], + "render_frame": { + "window_identity": 140451432015472, + "renderer_identity": 140451432242288, + "completed_at_monotonic": 3882702.966394539 + }, + "observation_budget_s": 2.4821014215704054, + "operation_deadline": { + "operation": "viewer control request", + "timeout_ms": 5000, + "expires_at": 3882707.914646516 + } + }, + "resource": { + "uri": "file:///home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/captures-live12/combined/20261004T043045079650Z_napari_6609_OpenHCS_Napari_Visualization.png", + "title": "OpenHCS Napari Visualization", + "mime_type": "image/png", + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/captures-live12/combined/20261004T043045079650Z_napari_6609_OpenHCS_Napari_Visualization.png", + "size_bytes": 83684, + "sha256": "a0b0492b919e4ecbc1c9eca2bff5f9fc0580a8d38365499ffddb9ea127ecec84" + }, + "viewer": { + "viewer_type": "napari", + "title": "OpenHCS Napari Visualization" + }, + "width": 1152, + "height": 963, + "response": { + "type": "screenshot_ack", + "status": "success", + "viewer": { + "type": "napari", + "title": "OpenHCS Napari Visualization" + }, + "resource": { + "uri": "file:///home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/captures-live12/combined/20261004T043045079650Z_napari_6609_OpenHCS_Napari_Visualization.png", + "title": "OpenHCS Napari Visualization", + "mime_type": "image/png", + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/captures-live12/combined/20261004T043045079650Z_napari_6609_OpenHCS_Napari_Visualization.png", + "size_bytes": 83684, + "sha256": "a0b0492b919e4ecbc1c9eca2bff5f9fc0580a8d38365499ffddb9ea127ecec84" + }, + "width": 1152, + "height": 963, + "snapshot": { + "connection": { + "host": "127.0.0.1", + "port": 6609, + "transport_mode": "tcp", + "persistent": true + }, + "timeout_ms": 5000, + "include_response": true, + "operation_deadline": { + "operation": "viewer control request", + "timeout_ms": 5000, + "expires_at": 3882707.914646516 + }, + "output_dir_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/captures-live12/combined", + "capture_scope": "widget", + "frame_condition": "render_complete", + "observation_timeout_s": 2.5 + }, + "observation": { + "condition": "render_complete", + "window_identity": 140451432015472, + "started_at_monotonic": 3882702.950358863, + "completed_at_monotonic": 3882702.966401873, + "configured_flash_duration_s": 0.0, + "baseline_inactive": true, + "flash_start_count": 0, + "painted_frame_count": 1, + "frame": null, + "trace": [], + "render_frame": { + "window_identity": 140451432015472, + "renderer_identity": 140451432242288, + "completed_at_monotonic": 3882702.966394539 + }, + "observation_budget_s": 2.4821014215704054, + "operation_deadline": { + "operation": "viewer control request", + "timeout_ms": 5000, + "expires_at": 3882707.914646516 + } + }, + "native_dimensions": { + "order": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6 + ], + "ndisplay": 2, + "displayed_axes": [ + "y", + "x" + ], + "point": [ + 0.0, + 1.0, + 0.0, + 0.0, + 0.0, + 20.334, + 20.334 + ], + "camera_angles": [ + 0.0, + 0.0, + 0.0 + ], + "canvas_size": [ + 643, + 478 + ] + } + } + } + }, + { + "tool": "openhcs_close_viewer_window", + "arguments": { + "host": "127.0.0.1", + "port": 6609, + "transport_mode": "tcp", + "confirmed": true + }, + "response": { + "content": [ + { + "type": "text", + "text": "{\n \"succeeded\": true,\n \"endpoint_terminated\": true,\n \"process_identity\": {\n \"pid\": 4094352,\n \"create_time\": 1791088238.94\n },\n \"process_exited\": true,\n \"request_attempted\": true,\n \"acknowledged\": true\n}" + } + ], + "structuredContent": { + "succeeded": true, + "endpoint_terminated": true, + "process_identity": { + "pid": 4094352, + "create_time": 1791088238.94 + }, + "process_exited": true, + "request_attempted": true, + "acknowledged": true + }, + "isError": false + }, + "payload": { + "succeeded": true, + "endpoint_terminated": true, + "process_identity": { + "pid": 4094352, + "create_time": 1791088238.94 + }, + "process_exited": true, + "request_attempted": true, + "acknowledged": true + } + } + ], + "failure": null, + "children": [], + "installed_dependencies": { + "python-introspect": "0.1.16", + "polystore": "0.3.1", + "zmqruntime": "0.3.1", + "napari": "0.9.2", + "numpy": "2.5.3", + "PyQt6": "6.11.0" + }, + "owned_ports": [ + 6609, + 7609 + ], + "fixture": { + "raw": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate", + "labels": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate", + "label_paths": [ + "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/stacked_labels/A01_s001_w2_z001_t001_Labels.tif" + ], + "graph": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/graph_results/A01_s001_w2_z001_t001_graph.graph.roi.zip", + "metadata": { + "source_voxel_spacing": { + "values_zyx": [ + 1.3556, + 1.3556 + ], + "unit": "micrometers" + }, + "source_spatial_domain": { + "origin_yx": null, + "source_shape_yx": null, + "fill_value": 0, + "value_name": "Dense array", + "spatial_dimensions": 2 + }, + "source_provenance": { + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w2_z001_t001.tif", + "source_component_metadata": { + "OpenHCSSourceVoxelSpacingUnit": "micrometers", + "OpenHCSSourceVoxelSpacingZYX": "1.3555999999999999,1.3555999999999999", + "channel": "2", + "site": "1", + "timepoint": "1", + "well": "A01", + "z_index": "1" + }, + "source_image_provenance_planes": [], + "source_image_names": [ + "raw_2" + ] + }, + "intensity_scale": null, + "source_dtype": null, + "unit_interval_intensity": null, + "source_plane_intensity_scales": [], + "source_plane_dtypes": [], + "physical_border_edges_yx": null, + "mask_defines_border": null, + "source_channel_axis": null, + "plane_axis": null + }, + "label_metadata": { + "source_voxel_spacing": { + "values_zyx": [ + 1.3556, + 1.3556 + ], + "unit": "micrometers" + }, + "source_spatial_domain": { + "origin_yx": [ + 0, + 0 + ], + "source_shape_yx": [ + 32, + 32 + ], + "fill_value": 0, + "value_name": "Dense array", + "spatial_dimensions": 2 + }, + "source_provenance": { + "source_path": null, + "source_component_metadata": null, + "source_image_provenance_planes": [ + { + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w2_z001_t001.tif", + "component_metadata": { + "well": "A01", + "site": "1", + "channel": "2", + "z_index": "1", + "timepoint": "1", + "OpenHCSSourceVoxelSpacingZYX": "1.3555999999999999,1.3555999999999999", + "OpenHCSSourceVoxelSpacingUnit": "micrometers" + }, + "identity_kind": "runtime_plane", + "source_image_name": null, + "contributors": [] + }, + { + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w1_z001_t001.tif", + "component_metadata": { + "well": "A01", + "site": "1", + "channel": "1", + "z_index": "1", + "timepoint": "1", + "OpenHCSSourceVoxelSpacingZYX": "1.3555999999999999,1.3555999999999999", + "OpenHCSSourceVoxelSpacingUnit": "micrometers" + }, + "identity_kind": "runtime_plane", + "source_image_name": null, + "contributors": [] + } + ], + "source_image_names": [ + "raw_2", + "raw_1" + ] + }, + "intensity_scale": null, + "source_dtype": null, + "unit_interval_intensity": null, + "source_plane_intensity_scales": [], + "source_plane_dtypes": [], + "physical_border_edges_yx": null, + "mask_defines_border": null, + "source_channel_axis": null, + "plane_axis": "runtime_slice" + }, + "roi_features": [ + { + "__openhcs_object_subject__": "[\"output\",\"object_labels\",\"neurons\",\"synthetic-receiving-134\",4]", + "__openhcs_object_subject_id__": 7, + "area": 0.0, + "branch_distance_um": 8.5, + "centroid": [ + 3.75, + 6.5 + ], + "edge_id": 1, + "graph": "declared_graph", + "label": 1, + "neuron_label": 7, + "openhcs_image_payload_metadata": { + "intensity_scale": null, + "mask_defines_border": null, + "physical_border_edges_yx": null, + "plane_axis": null, + "source_channel_axis": null, + "source_dtype": null, + "source_plane_dtypes": [], + "source_plane_intensity_scales": [], + "source_provenance": { + "source_component_metadata": { + "OpenHCSSourceVoxelSpacingUnit": "micrometers", + "OpenHCSSourceVoxelSpacingZYX": "1.3555999999999999,1.3555999999999999", + "channel": "2", + "site": "1", + "timepoint": "1", + "well": "A01", + "z_index": "1" + }, + "source_image_names": [ + "raw_2" + ], + "source_image_provenance_planes": [], + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w2_z001_t001.tif" + }, + "source_spatial_domain": { + "fill_value": 0, + "origin_yx": null, + "source_shape_yx": null, + "spatial_dimensions": 2, + "value_name": "Dense array" + }, + "source_voxel_spacing": { + "unit": "micrometers", + "values_zyx": [ + 1.3556, + 1.3556 + ] + }, + "unit_interval_intensity": null + }, + "perimeter": 6.708203932499369, + "source_node_id": 1, + "target_node_id": 2 + }, + { + "__openhcs_object_subject__": "[\"output\",\"object_labels\",\"neurons\",\"synthetic-receiving-134\",4]", + "__openhcs_object_subject_id__": 7, + "area": 0.0, + "branch_distance_um": 8.5, + "centroid": [ + 6.25, + 11.0 + ], + "edge_id": 2, + "graph": "declared_graph", + "label": 2, + "neuron_label": 7, + "openhcs_image_payload_metadata": { + "intensity_scale": null, + "mask_defines_border": null, + "physical_border_edges_yx": null, + "plane_axis": null, + "source_channel_axis": null, + "source_dtype": null, + "source_plane_dtypes": [], + "source_plane_intensity_scales": [], + "source_provenance": { + "source_component_metadata": { + "OpenHCSSourceVoxelSpacingUnit": "micrometers", + "OpenHCSSourceVoxelSpacingZYX": "1.3555999999999999,1.3555999999999999", + "channel": "2", + "site": "1", + "timepoint": "1", + "well": "A01", + "z_index": "1" + }, + "source_image_names": [ + "raw_2" + ], + "source_image_provenance_planes": [], + "source_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w2_z001_t001.tif" + }, + "source_spatial_domain": { + "fill_value": 0, + "origin_yx": null, + "source_shape_yx": null, + "spatial_dimensions": 2, + "value_name": "Dense array" + }, + "source_voxel_spacing": { + "unit": "micrometers", + "values_zyx": [ + 1.3556, + 1.3556 + ] + }, + "unit_interval_intensity": null + }, + "perimeter": 3.605551275463989, + "source_node_id": 2, + "target_node_id": 3 + } + ], + "files": { + "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/openhcs_metadata.json": "161c3d91e37676747a87378b777e19aae2f1e061e113327b1b4a5dd5015afb73", + "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/openhcs_metadata.json.lock": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w1_z001_t001.tif": "be9b564f5a1b47703b2c1ef735bf3a7bf94b2f4d4946c005822ea2c663945d72", + "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w2_z001_t001.tif": "dc0f36bd0c959deb5a79b0aa7242d1dcdcf2034cafedb58b28a222555935859d", + "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/openhcs_metadata.json": "8302fc6c5220cc3830a8f2ff125f294db6ad2c6e341b877ecce205ed3ea89ab3", + "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/openhcs_metadata.json.lock": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/stacked_labels/A01_s001_w2_z001_t001_Labels.tif": "2a0f0ecf0e16d4d909307ddc95992b9263db367ffec74a565958ed7d4a25b450", + "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/images/A01_s001_w1_z001_t001.tif": "0d3fdc7fac223acdae9b48685b66ee5179a97525376c148efa23463b0f9e8b94", + "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/images/A01_s001_w2_z001_t001.tif": "031d3f3546cf450105d148e1744cb56ae91bf67cd3b0304b9798953eea613b89", + "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/graph_results/A01_s001_w2_z001_t001_graph.graph.roi.zip": "e76fed9f2115efbfb093bfafb499fb7ad2691ee0d8defd1116a0505039f87b59" + }, + "expected_pixels": { + "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w2_z001_t001.tif": [ + [ + 200, + 201, + 202, + 203, + 204, + 205, + 206, + 207, + 208, + 209, + 210, + 211, + 212, + 213, + 214, + 215, + 216, + 217, + 218, + 219, + 220, + 221, + 222, + 223, + 224, + 225, + 226, + 227, + 228, + 229, + 230, + 231 + ], + [ + 232, + 233, + 234, + 235, + 236, + 237, + 238, + 239, + 240, + 241, + 242, + 243, + 244, + 245, + 246, + 247, + 248, + 249, + 250, + 251, + 252, + 253, + 254, + 255, + 256, + 257, + 258, + 259, + 260, + 261, + 262, + 263 + ], + [ + 264, + 265, + 266, + 267, + 268, + 269, + 270, + 271, + 272, + 273, + 274, + 275, + 276, + 277, + 278, + 279, + 280, + 281, + 282, + 283, + 284, + 285, + 286, + 287, + 288, + 289, + 290, + 291, + 292, + 293, + 294, + 295 + ], + [ + 296, + 297, + 298, + 299, + 300, + 301, + 302, + 303, + 304, + 305, + 306, + 307, + 308, + 309, + 310, + 311, + 312, + 313, + 314, + 315, + 316, + 317, + 318, + 319, + 320, + 321, + 322, + 323, + 324, + 325, + 326, + 327 + ], + [ + 328, + 329, + 330, + 331, + 332, + 333, + 334, + 335, + 336, + 337, + 338, + 339, + 340, + 341, + 342, + 343, + 344, + 345, + 346, + 347, + 348, + 349, + 350, + 351, + 352, + 353, + 354, + 355, + 356, + 357, + 358, + 359 + ], + [ + 360, + 361, + 362, + 363, + 364, + 365, + 366, + 367, + 368, + 369, + 370, + 371, + 372, + 373, + 374, + 375, + 376, + 377, + 378, + 379, + 380, + 381, + 382, + 383, + 384, + 385, + 386, + 387, + 388, + 389, + 390, + 391 + ], + [ + 392, + 393, + 394, + 395, + 396, + 397, + 398, + 399, + 400, + 401, + 402, + 403, + 404, + 405, + 406, + 407, + 408, + 409, + 410, + 411, + 412, + 413, + 414, + 415, + 416, + 417, + 418, + 419, + 420, + 421, + 422, + 423 + ], + [ + 424, + 425, + 426, + 427, + 428, + 429, + 430, + 431, + 432, + 433, + 434, + 435, + 436, + 437, + 438, + 439, + 440, + 441, + 442, + 443, + 444, + 445, + 446, + 447, + 448, + 449, + 450, + 451, + 452, + 453, + 454, + 455 + ], + [ + 456, + 457, + 458, + 459, + 460, + 461, + 462, + 463, + 464, + 465, + 466, + 467, + 468, + 469, + 470, + 471, + 472, + 473, + 474, + 475, + 476, + 477, + 478, + 479, + 480, + 481, + 482, + 483, + 484, + 485, + 486, + 487 + ], + [ + 488, + 489, + 490, + 491, + 492, + 493, + 494, + 495, + 496, + 497, + 498, + 499, + 500, + 501, + 502, + 503, + 504, + 505, + 506, + 507, + 508, + 509, + 510, + 511, + 512, + 513, + 514, + 515, + 516, + 517, + 518, + 519 + ], + [ + 520, + 521, + 522, + 523, + 524, + 525, + 526, + 527, + 528, + 529, + 530, + 531, + 532, + 533, + 534, + 535, + 536, + 537, + 538, + 539, + 540, + 541, + 542, + 543, + 544, + 545, + 546, + 547, + 548, + 549, + 550, + 551 + ], + [ + 552, + 553, + 554, + 555, + 556, + 557, + 558, + 559, + 560, + 561, + 562, + 563, + 564, + 565, + 566, + 567, + 568, + 569, + 570, + 571, + 572, + 573, + 574, + 575, + 576, + 577, + 578, + 579, + 580, + 581, + 582, + 583 + ], + [ + 584, + 585, + 586, + 587, + 588, + 589, + 590, + 591, + 592, + 593, + 594, + 595, + 596, + 597, + 598, + 599, + 600, + 601, + 602, + 603, + 604, + 605, + 606, + 607, + 608, + 609, + 610, + 611, + 612, + 613, + 614, + 615 + ], + [ + 616, + 617, + 618, + 619, + 620, + 621, + 622, + 623, + 624, + 625, + 626, + 627, + 628, + 629, + 630, + 631, + 632, + 633, + 634, + 635, + 636, + 637, + 638, + 639, + 640, + 641, + 642, + 643, + 644, + 645, + 646, + 647 + ], + [ + 648, + 649, + 650, + 651, + 652, + 653, + 654, + 655, + 656, + 657, + 658, + 659, + 660, + 661, + 662, + 663, + 664, + 665, + 666, + 667, + 668, + 669, + 670, + 671, + 672, + 673, + 674, + 675, + 676, + 677, + 678, + 679 + ], + [ + 680, + 681, + 682, + 683, + 684, + 685, + 686, + 687, + 688, + 689, + 690, + 691, + 692, + 693, + 694, + 695, + 696, + 697, + 698, + 699, + 700, + 701, + 702, + 703, + 704, + 705, + 706, + 707, + 708, + 709, + 710, + 711 + ], + [ + 712, + 713, + 714, + 715, + 716, + 717, + 718, + 719, + 720, + 721, + 722, + 723, + 724, + 725, + 726, + 727, + 728, + 729, + 730, + 731, + 732, + 733, + 734, + 735, + 736, + 737, + 738, + 739, + 740, + 741, + 742, + 743 + ], + [ + 744, + 745, + 746, + 747, + 748, + 749, + 750, + 751, + 752, + 753, + 754, + 755, + 756, + 757, + 758, + 759, + 760, + 761, + 762, + 763, + 764, + 765, + 766, + 767, + 768, + 769, + 770, + 771, + 772, + 773, + 774, + 775 + ], + [ + 776, + 777, + 778, + 779, + 780, + 781, + 782, + 783, + 784, + 785, + 786, + 787, + 788, + 789, + 790, + 791, + 792, + 793, + 794, + 795, + 796, + 797, + 798, + 799, + 800, + 801, + 802, + 803, + 804, + 805, + 806, + 807 + ], + [ + 808, + 809, + 810, + 811, + 812, + 813, + 814, + 815, + 816, + 817, + 818, + 819, + 820, + 821, + 822, + 823, + 824, + 825, + 826, + 827, + 828, + 829, + 830, + 831, + 832, + 833, + 834, + 835, + 836, + 837, + 838, + 839 + ], + [ + 840, + 841, + 842, + 843, + 844, + 845, + 846, + 847, + 848, + 849, + 850, + 851, + 852, + 853, + 854, + 855, + 856, + 857, + 858, + 859, + 860, + 861, + 862, + 863, + 864, + 865, + 866, + 867, + 868, + 869, + 870, + 871 + ], + [ + 872, + 873, + 874, + 875, + 876, + 877, + 878, + 879, + 880, + 881, + 882, + 883, + 884, + 885, + 886, + 887, + 888, + 889, + 890, + 891, + 892, + 893, + 894, + 895, + 896, + 897, + 898, + 899, + 900, + 901, + 902, + 903 + ], + [ + 904, + 905, + 906, + 907, + 908, + 909, + 910, + 911, + 912, + 913, + 914, + 915, + 916, + 917, + 918, + 919, + 920, + 921, + 922, + 923, + 924, + 925, + 926, + 927, + 928, + 929, + 930, + 931, + 932, + 933, + 934, + 935 + ], + [ + 936, + 937, + 938, + 939, + 940, + 941, + 942, + 943, + 944, + 945, + 946, + 947, + 948, + 949, + 950, + 951, + 952, + 953, + 954, + 955, + 956, + 957, + 958, + 959, + 960, + 961, + 962, + 963, + 964, + 965, + 966, + 967 + ], + [ + 968, + 969, + 970, + 971, + 972, + 973, + 974, + 975, + 976, + 977, + 978, + 979, + 980, + 981, + 982, + 983, + 984, + 985, + 986, + 987, + 988, + 989, + 990, + 991, + 992, + 993, + 994, + 995, + 996, + 997, + 998, + 999 + ], + [ + 1000, + 1001, + 1002, + 1003, + 1004, + 1005, + 1006, + 1007, + 1008, + 1009, + 1010, + 1011, + 1012, + 1013, + 1014, + 1015, + 1016, + 1017, + 1018, + 1019, + 1020, + 1021, + 1022, + 1023, + 1024, + 1025, + 1026, + 1027, + 1028, + 1029, + 1030, + 1031 + ], + [ + 1032, + 1033, + 1034, + 1035, + 1036, + 1037, + 1038, + 1039, + 1040, + 1041, + 1042, + 1043, + 1044, + 1045, + 1046, + 1047, + 1048, + 1049, + 1050, + 1051, + 1052, + 1053, + 1054, + 1055, + 1056, + 1057, + 1058, + 1059, + 1060, + 1061, + 1062, + 1063 + ], + [ + 1064, + 1065, + 1066, + 1067, + 1068, + 1069, + 1070, + 1071, + 1072, + 1073, + 1074, + 1075, + 1076, + 1077, + 1078, + 1079, + 1080, + 1081, + 1082, + 1083, + 1084, + 1085, + 1086, + 1087, + 1088, + 1089, + 1090, + 1091, + 1092, + 1093, + 1094, + 1095 + ], + [ + 1096, + 1097, + 1098, + 1099, + 1100, + 1101, + 1102, + 1103, + 1104, + 1105, + 1106, + 1107, + 1108, + 1109, + 1110, + 1111, + 1112, + 1113, + 1114, + 1115, + 1116, + 1117, + 1118, + 1119, + 1120, + 1121, + 1122, + 1123, + 1124, + 1125, + 1126, + 1127 + ], + [ + 1128, + 1129, + 1130, + 1131, + 1132, + 1133, + 1134, + 1135, + 1136, + 1137, + 1138, + 1139, + 1140, + 1141, + 1142, + 1143, + 1144, + 1145, + 1146, + 1147, + 1148, + 1149, + 1150, + 1151, + 1152, + 1153, + 1154, + 1155, + 1156, + 1157, + 1158, + 1159 + ], + [ + 1160, + 1161, + 1162, + 1163, + 1164, + 1165, + 1166, + 1167, + 1168, + 1169, + 1170, + 1171, + 1172, + 1173, + 1174, + 1175, + 1176, + 1177, + 1178, + 1179, + 1180, + 1181, + 1182, + 1183, + 1184, + 1185, + 1186, + 1187, + 1188, + 1189, + 1190, + 1191 + ], + [ + 1192, + 1193, + 1194, + 1195, + 1196, + 1197, + 1198, + 1199, + 1200, + 1201, + 1202, + 1203, + 1204, + 1205, + 1206, + 1207, + 1208, + 1209, + 1210, + 1211, + 1212, + 1213, + 1214, + 1215, + 1216, + 1217, + 1218, + 1219, + 1220, + 1221, + 1222, + 1223 + ] + ], + "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w1_z001_t001.tif": [ + [ + 100, + 101, + 102, + 103, + 104, + 105, + 106, + 107, + 108, + 109, + 110, + 111, + 112, + 113, + 114, + 115, + 116, + 117, + 118, + 119, + 120, + 121, + 122, + 123, + 124, + 125, + 126, + 127, + 128, + 129, + 130, + 131 + ], + [ + 132, + 133, + 134, + 135, + 136, + 137, + 138, + 139, + 140, + 141, + 142, + 143, + 144, + 145, + 146, + 147, + 148, + 149, + 150, + 151, + 152, + 153, + 154, + 155, + 156, + 157, + 158, + 159, + 160, + 161, + 162, + 163 + ], + [ + 164, + 165, + 166, + 167, + 168, + 169, + 170, + 171, + 172, + 173, + 174, + 175, + 176, + 177, + 178, + 179, + 180, + 181, + 182, + 183, + 184, + 185, + 186, + 187, + 188, + 189, + 190, + 191, + 192, + 193, + 194, + 195 + ], + [ + 196, + 197, + 198, + 199, + 200, + 201, + 202, + 203, + 204, + 205, + 206, + 207, + 208, + 209, + 210, + 211, + 212, + 213, + 214, + 215, + 216, + 217, + 218, + 219, + 220, + 221, + 222, + 223, + 224, + 225, + 226, + 227 + ], + [ + 228, + 229, + 230, + 231, + 232, + 233, + 234, + 235, + 236, + 237, + 238, + 239, + 240, + 241, + 242, + 243, + 244, + 245, + 246, + 247, + 248, + 249, + 250, + 251, + 252, + 253, + 254, + 255, + 256, + 257, + 258, + 259 + ], + [ + 260, + 261, + 262, + 263, + 264, + 265, + 266, + 267, + 268, + 269, + 270, + 271, + 272, + 273, + 274, + 275, + 276, + 277, + 278, + 279, + 280, + 281, + 282, + 283, + 284, + 285, + 286, + 287, + 288, + 289, + 290, + 291 + ], + [ + 292, + 293, + 294, + 295, + 296, + 297, + 298, + 299, + 300, + 301, + 302, + 303, + 304, + 305, + 306, + 307, + 308, + 309, + 310, + 311, + 312, + 313, + 314, + 315, + 316, + 317, + 318, + 319, + 320, + 321, + 322, + 323 + ], + [ + 324, + 325, + 326, + 327, + 328, + 329, + 330, + 331, + 332, + 333, + 334, + 335, + 336, + 337, + 338, + 339, + 340, + 341, + 342, + 343, + 344, + 345, + 346, + 347, + 348, + 349, + 350, + 351, + 352, + 353, + 354, + 355 + ], + [ + 356, + 357, + 358, + 359, + 360, + 361, + 362, + 363, + 364, + 365, + 366, + 367, + 368, + 369, + 370, + 371, + 372, + 373, + 374, + 375, + 376, + 377, + 378, + 379, + 380, + 381, + 382, + 383, + 384, + 385, + 386, + 387 + ], + [ + 388, + 389, + 390, + 391, + 392, + 393, + 394, + 395, + 396, + 397, + 398, + 399, + 400, + 401, + 402, + 403, + 404, + 405, + 406, + 407, + 408, + 409, + 410, + 411, + 412, + 413, + 414, + 415, + 416, + 417, + 418, + 419 + ], + [ + 420, + 421, + 422, + 423, + 424, + 425, + 426, + 427, + 428, + 429, + 430, + 431, + 432, + 433, + 434, + 435, + 436, + 437, + 438, + 439, + 440, + 441, + 442, + 443, + 444, + 445, + 446, + 447, + 448, + 449, + 450, + 451 + ], + [ + 452, + 453, + 454, + 455, + 456, + 457, + 458, + 459, + 460, + 461, + 462, + 463, + 464, + 465, + 466, + 467, + 468, + 469, + 470, + 471, + 472, + 473, + 474, + 475, + 476, + 477, + 478, + 479, + 480, + 481, + 482, + 483 + ], + [ + 484, + 485, + 486, + 487, + 488, + 489, + 490, + 491, + 492, + 493, + 494, + 495, + 496, + 497, + 498, + 499, + 500, + 501, + 502, + 503, + 504, + 505, + 506, + 507, + 508, + 509, + 510, + 511, + 512, + 513, + 514, + 515 + ], + [ + 516, + 517, + 518, + 519, + 520, + 521, + 522, + 523, + 524, + 525, + 526, + 527, + 528, + 529, + 530, + 531, + 532, + 533, + 534, + 535, + 536, + 537, + 538, + 539, + 540, + 541, + 542, + 543, + 544, + 545, + 546, + 547 + ], + [ + 548, + 549, + 550, + 551, + 552, + 553, + 554, + 555, + 556, + 557, + 558, + 559, + 560, + 561, + 562, + 563, + 564, + 565, + 566, + 567, + 568, + 569, + 570, + 571, + 572, + 573, + 574, + 575, + 576, + 577, + 578, + 579 + ], + [ + 580, + 581, + 582, + 583, + 584, + 585, + 586, + 587, + 588, + 589, + 590, + 591, + 592, + 593, + 594, + 595, + 596, + 597, + 598, + 599, + 600, + 601, + 602, + 603, + 604, + 605, + 606, + 607, + 608, + 609, + 610, + 611 + ], + [ + 612, + 613, + 614, + 615, + 616, + 617, + 618, + 619, + 620, + 621, + 622, + 623, + 624, + 625, + 626, + 627, + 628, + 629, + 630, + 631, + 632, + 633, + 634, + 635, + 636, + 637, + 638, + 639, + 640, + 641, + 642, + 643 + ], + [ + 644, + 645, + 646, + 647, + 648, + 649, + 650, + 651, + 652, + 653, + 654, + 655, + 656, + 657, + 658, + 659, + 660, + 661, + 662, + 663, + 664, + 665, + 666, + 667, + 668, + 669, + 670, + 671, + 672, + 673, + 674, + 675 + ], + [ + 676, + 677, + 678, + 679, + 680, + 681, + 682, + 683, + 684, + 685, + 686, + 687, + 688, + 689, + 690, + 691, + 692, + 693, + 694, + 695, + 696, + 697, + 698, + 699, + 700, + 701, + 702, + 703, + 704, + 705, + 706, + 707 + ], + [ + 708, + 709, + 710, + 711, + 712, + 713, + 714, + 715, + 716, + 717, + 718, + 719, + 720, + 721, + 722, + 723, + 724, + 725, + 726, + 727, + 728, + 729, + 730, + 731, + 732, + 733, + 734, + 735, + 736, + 737, + 738, + 739 + ], + [ + 740, + 741, + 742, + 743, + 744, + 745, + 746, + 747, + 748, + 749, + 750, + 751, + 752, + 753, + 754, + 755, + 756, + 757, + 758, + 759, + 760, + 761, + 762, + 763, + 764, + 765, + 766, + 767, + 768, + 769, + 770, + 771 + ], + [ + 772, + 773, + 774, + 775, + 776, + 777, + 778, + 779, + 780, + 781, + 782, + 783, + 784, + 785, + 786, + 787, + 788, + 789, + 790, + 791, + 792, + 793, + 794, + 795, + 796, + 797, + 798, + 799, + 800, + 801, + 802, + 803 + ], + [ + 804, + 805, + 806, + 807, + 808, + 809, + 810, + 811, + 812, + 813, + 814, + 815, + 816, + 817, + 818, + 819, + 820, + 821, + 822, + 823, + 824, + 825, + 826, + 827, + 828, + 829, + 830, + 831, + 832, + 833, + 834, + 835 + ], + [ + 836, + 837, + 838, + 839, + 840, + 841, + 842, + 843, + 844, + 845, + 846, + 847, + 848, + 849, + 850, + 851, + 852, + 853, + 854, + 855, + 856, + 857, + 858, + 859, + 860, + 861, + 862, + 863, + 864, + 865, + 866, + 867 + ], + [ + 868, + 869, + 870, + 871, + 872, + 873, + 874, + 875, + 876, + 877, + 878, + 879, + 880, + 881, + 882, + 883, + 884, + 885, + 886, + 887, + 888, + 889, + 890, + 891, + 892, + 893, + 894, + 895, + 896, + 897, + 898, + 899 + ], + [ + 900, + 901, + 902, + 903, + 904, + 905, + 906, + 907, + 908, + 909, + 910, + 911, + 912, + 913, + 914, + 915, + 916, + 917, + 918, + 919, + 920, + 921, + 922, + 923, + 924, + 925, + 926, + 927, + 928, + 929, + 930, + 931 + ], + [ + 932, + 933, + 934, + 935, + 936, + 937, + 938, + 939, + 940, + 941, + 942, + 943, + 944, + 945, + 946, + 947, + 948, + 949, + 950, + 951, + 952, + 953, + 954, + 955, + 956, + 957, + 958, + 959, + 960, + 961, + 962, + 963 + ], + [ + 964, + 965, + 966, + 967, + 968, + 969, + 970, + 971, + 972, + 973, + 974, + 975, + 976, + 977, + 978, + 979, + 980, + 981, + 982, + 983, + 984, + 985, + 986, + 987, + 988, + 989, + 990, + 991, + 992, + 993, + 994, + 995 + ], + [ + 996, + 997, + 998, + 999, + 1000, + 1001, + 1002, + 1003, + 1004, + 1005, + 1006, + 1007, + 1008, + 1009, + 1010, + 1011, + 1012, + 1013, + 1014, + 1015, + 1016, + 1017, + 1018, + 1019, + 1020, + 1021, + 1022, + 1023, + 1024, + 1025, + 1026, + 1027 + ], + [ + 1028, + 1029, + 1030, + 1031, + 1032, + 1033, + 1034, + 1035, + 1036, + 1037, + 1038, + 1039, + 1040, + 1041, + 1042, + 1043, + 1044, + 1045, + 1046, + 1047, + 1048, + 1049, + 1050, + 1051, + 1052, + 1053, + 1054, + 1055, + 1056, + 1057, + 1058, + 1059 + ], + [ + 1060, + 1061, + 1062, + 1063, + 1064, + 1065, + 1066, + 1067, + 1068, + 1069, + 1070, + 1071, + 1072, + 1073, + 1074, + 1075, + 1076, + 1077, + 1078, + 1079, + 1080, + 1081, + 1082, + 1083, + 1084, + 1085, + 1086, + 1087, + 1088, + 1089, + 1090, + 1091 + ], + [ + 1092, + 1093, + 1094, + 1095, + 1096, + 1097, + 1098, + 1099, + 1100, + 1101, + 1102, + 1103, + 1104, + 1105, + 1106, + 1107, + 1108, + 1109, + 1110, + 1111, + 1112, + 1113, + 1114, + 1115, + 1116, + 1117, + 1118, + 1119, + 1120, + 1121, + 1122, + 1123 + ] + ], + "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/stacked_labels/A01_s001_w2_z001_t001_Labels.tif": [ + [ + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 14, + 14, + 14, + 14, + 14, + 14, + 14, + 14, + 14, + 14, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 14, + 14, + 14, + 14, + 14, + 14, + 14, + 14, + 14, + 14, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 14, + 14, + 14, + 14, + 14, + 14, + 14, + 14, + 14, + 14, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 14, + 14, + 14, + 14, + 14, + 14, + 14, + 14, + 14, + 14, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 14, + 14, + 14, + 14, + 14, + 14, + 14, + 14, + 14, + 14, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 14, + 14, + 14, + 14, + 14, + 14, + 14, + 14, + 14, + 14, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 14, + 14, + 14, + 14, + 14, + 14, + 14, + 14, + 14, + 14, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 14, + 14, + 14, + 14, + 14, + 14, + 14, + 14, + 14, + 14, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 14, + 14, + 14, + 14, + 14, + 14, + 14, + 14, + 14, + 14, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 22, + 22, + 22, + 22, + 22, + 22, + 22, + 22, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 22, + 22, + 22, + 22, + 22, + 22, + 22, + 22, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 22, + 22, + 22, + 22, + 22, + 22, + 22, + 22, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 22, + 22, + 22, + 22, + 22, + 22, + 22, + 22, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 22, + 22, + 22, + 22, + 22, + 22, + 22, + 22, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 22, + 22, + 22, + 22, + 22, + 22, + 22, + 22, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 22, + 22, + 22, + 22, + 22, + 22, + 22, + 22, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 22, + 22, + 22, + 22, + 22, + 22, + 22, + 22, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ] + ], + [ + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 11, + 11, + 11, + 11, + 11, + 11, + 11, + 11, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 11, + 11, + 11, + 11, + 11, + 11, + 11, + 11, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 11, + 11, + 11, + 11, + 11, + 11, + 11, + 11, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 11, + 11, + 11, + 11, + 11, + 11, + 11, + 11, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 11, + 11, + 11, + 11, + 11, + 11, + 11, + 11, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 11, + 11, + 11, + 11, + 11, + 11, + 11, + 11, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 11, + 11, + 11, + 11, + 11, + 11, + 11, + 11, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 11, + 11, + 11, + 11, + 11, + 11, + 11, + 11, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ] + ] + ] + }, + "retained_failed_receipts": [ + "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/journey-live.json", + "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/journey-live2.json", + "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/journey-live3.json", + "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/journey-live4.json", + "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/journey-live5.json" + ] + }, + "xserver_pid": 4094093, + "initial_native_qualification": { + "receipt": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/journey-live8.json", + "sha256": "26421ba0f9b803959531ba7aba93c6c85ff7081f116b386a80cd882278bfec66", + "native_state": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/label-source-receipt.json", + "state_sha256": "98ec069b91300ccfb716c9b34bf48dfecb4ee81013471262be95ff05063a1679" + }, + "captures": { + "raw": { + "connection": { + "host": "127.0.0.1", + "port": 6609, + "transport_mode": "tcp", + "persistent": true + }, + "schema_version": "openhcs.agent.v1", + "errors": [], + "warnings": [], + "output_dir_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/captures-live12/raw", + "capture_scope": "widget", + "frame_condition": "render_complete", + "observation_timeout_s": 2.5, + "captured": true, + "observation": { + "condition": "render_complete", + "window_identity": 140451432015472, + "started_at_monotonic": 3882702.250398891, + "completed_at_monotonic": 3882702.264351425, + "configured_flash_duration_s": 0.0, + "baseline_inactive": true, + "flash_start_count": 0, + "painted_frame_count": 1, + "frame": null, + "trace": [], + "render_frame": { + "window_identity": 140451432015472, + "renderer_identity": 140451432242288, + "completed_at_monotonic": 3882702.264341316 + }, + "observation_budget_s": 2.4809327765833586, + "operation_deadline": { + "operation": "viewer control request", + "timeout_ms": 5000, + "expires_at": 3882707.212359763 + } + }, + "resource": { + "uri": "file:///home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/captures-live12/raw/20261004T043044386798Z_napari_6609_OpenHCS_Napari_Visualization.png", + "title": "OpenHCS Napari Visualization", + "mime_type": "image/png", + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/captures-live12/raw/20261004T043044386798Z_napari_6609_OpenHCS_Napari_Visualization.png", + "size_bytes": 86074, + "sha256": "f9050beeffc54c925aaca4cf4188ecf1c51b42c4fa49f2b08c5f880d47ce59d2" + }, + "viewer": { + "viewer_type": "napari", + "title": "OpenHCS Napari Visualization" + }, + "width": 1152, + "height": 963, + "response": { + "type": "screenshot_ack", + "status": "success", + "viewer": { + "type": "napari", + "title": "OpenHCS Napari Visualization" + }, + "resource": { + "uri": "file:///home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/captures-live12/raw/20261004T043044386798Z_napari_6609_OpenHCS_Napari_Visualization.png", + "title": "OpenHCS Napari Visualization", + "mime_type": "image/png", + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/captures-live12/raw/20261004T043044386798Z_napari_6609_OpenHCS_Napari_Visualization.png", + "size_bytes": 86074, + "sha256": "f9050beeffc54c925aaca4cf4188ecf1c51b42c4fa49f2b08c5f880d47ce59d2" + }, + "width": 1152, + "height": 963, + "snapshot": { + "connection": { + "host": "127.0.0.1", + "port": 6609, + "transport_mode": "tcp", + "persistent": true + }, + "timeout_ms": 5000, + "include_response": true, + "operation_deadline": { + "operation": "viewer control request", + "timeout_ms": 5000, + "expires_at": 3882707.212359763 + }, + "output_dir_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/captures-live12/raw", + "capture_scope": "widget", + "frame_condition": "render_complete", + "observation_timeout_s": 2.5 + }, + "observation": { + "condition": "render_complete", + "window_identity": 140451432015472, + "started_at_monotonic": 3882702.250398891, + "completed_at_monotonic": 3882702.264351425, + "configured_flash_duration_s": 0.0, + "baseline_inactive": true, + "flash_start_count": 0, + "painted_frame_count": 1, + "frame": null, + "trace": [], + "render_frame": { + "window_identity": 140451432015472, + "renderer_identity": 140451432242288, + "completed_at_monotonic": 3882702.264341316 + }, + "observation_budget_s": 2.4809327765833586, + "operation_deadline": { + "operation": "viewer control request", + "timeout_ms": 5000, + "expires_at": 3882707.212359763 + } + }, + "native_dimensions": { + "order": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6 + ], + "ndisplay": 2, + "displayed_axes": [ + "y", + "x" + ], + "point": [ + 0.0, + 1.0, + 0.0, + 0.0, + 0.0, + 20.334, + 20.334 + ], + "camera_angles": [ + 0.0, + 0.0, + 0.0 + ], + "canvas_size": [ + 643, + 478 + ] + } + } + }, + "result": { + "connection": { + "host": "127.0.0.1", + "port": 6609, + "transport_mode": "tcp", + "persistent": true + }, + "schema_version": "openhcs.agent.v1", + "errors": [], + "warnings": [], + "output_dir_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/captures-live12/result", + "capture_scope": "widget", + "frame_condition": "render_complete", + "observation_timeout_s": 2.5, + "captured": true, + "observation": { + "condition": "render_complete", + "window_identity": 140451432015472, + "started_at_monotonic": 3882702.60035156, + "completed_at_monotonic": 3882702.615018741, + "configured_flash_duration_s": 0.0, + "baseline_inactive": true, + "flash_start_count": 0, + "painted_frame_count": 1, + "frame": null, + "trace": [], + "render_frame": { + "window_identity": 140451432015472, + "renderer_identity": 140451432242288, + "completed_at_monotonic": 3882702.615009964 + }, + "observation_budget_s": 2.4823596680071205, + "operation_deadline": { + "operation": "viewer control request", + "timeout_ms": 5000, + "expires_at": 3882707.565189139 + } + }, + "resource": { + "uri": "file:///home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/captures-live12/result/20261004T043044727006Z_napari_6609_OpenHCS_Napari_Visualization.png", + "title": "OpenHCS Napari Visualization", + "mime_type": "image/png", + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/captures-live12/result/20261004T043044727006Z_napari_6609_OpenHCS_Napari_Visualization.png", + "size_bytes": 82592, + "sha256": "440488c036ff602991ecd5a4124a47241b8093dcf7a5a2c157233076978a410b" + }, + "viewer": { + "viewer_type": "napari", + "title": "OpenHCS Napari Visualization" + }, + "width": 1152, + "height": 963, + "response": { + "type": "screenshot_ack", + "status": "success", + "viewer": { + "type": "napari", + "title": "OpenHCS Napari Visualization" + }, + "resource": { + "uri": "file:///home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/captures-live12/result/20261004T043044727006Z_napari_6609_OpenHCS_Napari_Visualization.png", + "title": "OpenHCS Napari Visualization", + "mime_type": "image/png", + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/captures-live12/result/20261004T043044727006Z_napari_6609_OpenHCS_Napari_Visualization.png", + "size_bytes": 82592, + "sha256": "440488c036ff602991ecd5a4124a47241b8093dcf7a5a2c157233076978a410b" + }, + "width": 1152, + "height": 963, + "snapshot": { + "connection": { + "host": "127.0.0.1", + "port": 6609, + "transport_mode": "tcp", + "persistent": true + }, + "timeout_ms": 5000, + "include_response": true, + "operation_deadline": { + "operation": "viewer control request", + "timeout_ms": 5000, + "expires_at": 3882707.565189139 + }, + "output_dir_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/captures-live12/result", + "capture_scope": "widget", + "frame_condition": "render_complete", + "observation_timeout_s": 2.5 + }, + "observation": { + "condition": "render_complete", + "window_identity": 140451432015472, + "started_at_monotonic": 3882702.60035156, + "completed_at_monotonic": 3882702.615018741, + "configured_flash_duration_s": 0.0, + "baseline_inactive": true, + "flash_start_count": 0, + "painted_frame_count": 1, + "frame": null, + "trace": [], + "render_frame": { + "window_identity": 140451432015472, + "renderer_identity": 140451432242288, + "completed_at_monotonic": 3882702.615009964 + }, + "observation_budget_s": 2.4823596680071205, + "operation_deadline": { + "operation": "viewer control request", + "timeout_ms": 5000, + "expires_at": 3882707.565189139 + } + }, + "native_dimensions": { + "order": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6 + ], + "ndisplay": 2, + "displayed_axes": [ + "y", + "x" + ], + "point": [ + 0.0, + 1.0, + 0.0, + 0.0, + 0.0, + 20.334, + 20.334 + ], + "camera_angles": [ + 0.0, + 0.0, + 0.0 + ], + "canvas_size": [ + 643, + 478 + ] + } + } + }, + "combined": { + "connection": { + "host": "127.0.0.1", + "port": 6609, + "transport_mode": "tcp", + "persistent": true + }, + "schema_version": "openhcs.agent.v1", + "errors": [], + "warnings": [], + "output_dir_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/captures-live12/combined", + "capture_scope": "widget", + "frame_condition": "render_complete", + "observation_timeout_s": 2.5, + "captured": true, + "observation": { + "condition": "render_complete", + "window_identity": 140451432015472, + "started_at_monotonic": 3882702.950358863, + "completed_at_monotonic": 3882702.966401873, + "configured_flash_duration_s": 0.0, + "baseline_inactive": true, + "flash_start_count": 0, + "painted_frame_count": 1, + "frame": null, + "trace": [], + "render_frame": { + "window_identity": 140451432015472, + "renderer_identity": 140451432242288, + "completed_at_monotonic": 3882702.966394539 + }, + "observation_budget_s": 2.4821014215704054, + "operation_deadline": { + "operation": "viewer control request", + "timeout_ms": 5000, + "expires_at": 3882707.914646516 + } + }, + "resource": { + "uri": "file:///home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/captures-live12/combined/20261004T043045079650Z_napari_6609_OpenHCS_Napari_Visualization.png", + "title": "OpenHCS Napari Visualization", + "mime_type": "image/png", + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/captures-live12/combined/20261004T043045079650Z_napari_6609_OpenHCS_Napari_Visualization.png", + "size_bytes": 83684, + "sha256": "a0b0492b919e4ecbc1c9eca2bff5f9fc0580a8d38365499ffddb9ea127ecec84" + }, + "viewer": { + "viewer_type": "napari", + "title": "OpenHCS Napari Visualization" + }, + "width": 1152, + "height": 963, + "response": { + "type": "screenshot_ack", + "status": "success", + "viewer": { + "type": "napari", + "title": "OpenHCS Napari Visualization" + }, + "resource": { + "uri": "file:///home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/captures-live12/combined/20261004T043045079650Z_napari_6609_OpenHCS_Napari_Visualization.png", + "title": "OpenHCS Napari Visualization", + "mime_type": "image/png", + "path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/captures-live12/combined/20261004T043045079650Z_napari_6609_OpenHCS_Napari_Visualization.png", + "size_bytes": 83684, + "sha256": "a0b0492b919e4ecbc1c9eca2bff5f9fc0580a8d38365499ffddb9ea127ecec84" + }, + "width": 1152, + "height": 963, + "snapshot": { + "connection": { + "host": "127.0.0.1", + "port": 6609, + "transport_mode": "tcp", + "persistent": true + }, + "timeout_ms": 5000, + "include_response": true, + "operation_deadline": { + "operation": "viewer control request", + "timeout_ms": 5000, + "expires_at": 3882707.914646516 + }, + "output_dir_path": "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/captures-live12/combined", + "capture_scope": "widget", + "frame_condition": "render_complete", + "observation_timeout_s": 2.5 + }, + "observation": { + "condition": "render_complete", + "window_identity": 140451432015472, + "started_at_monotonic": 3882702.950358863, + "completed_at_monotonic": 3882702.966401873, + "configured_flash_duration_s": 0.0, + "baseline_inactive": true, + "flash_start_count": 0, + "painted_frame_count": 1, + "frame": null, + "trace": [], + "render_frame": { + "window_identity": 140451432015472, + "renderer_identity": 140451432242288, + "completed_at_monotonic": 3882702.966394539 + }, + "observation_budget_s": 2.4821014215704054, + "operation_deadline": { + "operation": "viewer control request", + "timeout_ms": 5000, + "expires_at": 3882707.914646516 + } + }, + "native_dimensions": { + "order": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6 + ], + "ndisplay": 2, + "displayed_axes": [ + "y", + "x" + ], + "point": [ + 0.0, + 1.0, + 0.0, + 0.0, + 0.0, + 20.334, + 20.334 + ], + "camera_angles": [ + 0.0, + 0.0, + 0.0 + ], + "canvas_size": [ + 643, + 478 + ] + } + } + } + }, + "complete_native_pixel_paths": [ + [ + "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/stacked_labels/A01_s001_w2_z001_t001_Labels.tif", + 0 + ], + [ + "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/labels_plate/stacked_labels/A01_s001_w2_z001_t001_Labels.tif", + 1 + ], + [ + "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w1_z001_t001.tif", + null + ], + [ + "/home/ts/.local/state/openhcs-maintenance/20261004/receiving-134-native/raw_plate/images/A01_s001_w2_z001_t001.tif", + null + ] + ], + "xserver_returncode": 0, + "dependencies_unchanged": true, + "mcp_children": [ + { + "pid": 4094137, + "returncode": 0 + } + ] +} diff --git a/docs/refactor/receipts/public-native-receiving-134-20261004/retained-evidence.tar.gz b/docs/refactor/receipts/public-native-receiving-134-20261004/retained-evidence.tar.gz new file mode 100644 index 0000000000..f6bc9098c5 Binary files /dev/null and b/docs/refactor/receipts/public-native-receiving-134-20261004/retained-evidence.tar.gz differ diff --git a/docs/refactor/receipts/runtime-current-science-20261004/README.rst b/docs/refactor/receipts/runtime-current-science-20261004/README.rst new file mode 100644 index 0000000000..6f75243f31 --- /dev/null +++ b/docs/refactor/receipts/runtime-current-science-20261004/README.rst @@ -0,0 +1,21 @@ +Current source science acceptance +================================= + +The completed ordinary outputs from source +``9e838be5646a0dd414630f8b84951238387df2e7`` pass six comparisons +against both retained, qualified v12 native outputs for the original 3D +monolayer, Speckles and Beginner pipelines. The existing full measurement, +directed relationship, physical inventory and image policies are unchanged. +Both original 3D volumes require exact pixels. Ordered source-reference +counts remain 180/2/10; current input and retained native output hashes match. +The result file retains each comparison and every compared output hash. + +This validates the integrated physical-column, source-metadata, output-kind +ownership and RelateObjects reader changes on current dependencies. + +The v13 timing campaign remains rejected: Speckles produced a successful +authoritative W001 outcome and its three CSVs, but its asynchronous progress +stream lost the completion tail. All jobs are terminal and guards pass. No +second ordinary sweep or fresh native worker ran. These six comparisons are +science-only acceptance against retained native data, not a fresh paired +performance result or the retired original #496 bounded graph proof. diff --git a/docs/refactor/receipts/runtime-current-science-20261004/strict-science-retained-v12-native.json b/docs/refactor/receipts/runtime-current-science-20261004/strict-science-retained-v12-native.json new file mode 100644 index 0000000000..4838a59d6e --- /dev/null +++ b/docs/refactor/receipts/runtime-current-science-20261004/strict-science-retained-v12-native.json @@ -0,0 +1,257 @@ +{ + "status": "PASS", + "comparisons": [ + { + "case": "cp_tutorial_3d_monolayer", + "ordinary_repeat": 0, + "native_repeat": 0, + "measurement_differences": 0, + "image_differences": 0, + "tables": [ + 7, + 6 + ], + "physical_images": [ + 2, + 2 + ], + "logical_images": [ + 2, + 2 + ], + "known_relationship_keys": [ + 3, + 3 + ], + "ordinary_receipt_sha256": "633d57c188c7701d05105ba96d1f8c3cd33ef2910a22dae00ca93dd028cb8618", + "output_hashes": { + "/home/ts/.local/state/openhcs-maintenance/20261004/canonical-runtime-cache-client-paired-v12-qualified/native/cp_tutorial_3d_monolayer/outputs/0/3d_monolayer_xy1_ch0_CellsLabels.tiff": "aaed9ed23179a162ee7f5a7e8d1d88f1fa342ca55172b7fccd4cbf67f7841d81", + "/home/ts/.local/state/openhcs-maintenance/20261004/canonical-runtime-cache-client-paired-v12-qualified/native/cp_tutorial_3d_monolayer/outputs/0/3d_monolayer_Experiment.csv": "0f58915fe15ec67558af05090093a38ca3622f81321e369e7dd30ce8538f1ea9", + "/home/ts/.local/state/openhcs-maintenance/20261004/canonical-runtime-cache-client-paired-v12-qualified/native/cp_tutorial_3d_monolayer/outputs/0/3d_monolayer_downsizedNuclei.csv": "2c66bc7b17de52147d5a875403f9a9746019ac61371c08157979044c6ed818dd", + "/home/ts/.local/state/openhcs-maintenance/20261004/canonical-runtime-cache-client-paired-v12-qualified/native/cp_tutorial_3d_monolayer/outputs/0/3d_monolayer_Image.csv": "4a59e7c318d943cb6a45d88ec61ce997224c9d247153b6ba413f8bbc84470fa3", + "/home/ts/.local/state/openhcs-maintenance/20261004/canonical-runtime-cache-client-paired-v12-qualified/native/cp_tutorial_3d_monolayer/outputs/0/3d_monolayer_erodedDownsizedNuclei.csv": "527a0cce497d2a618478be84d1a0bf174049f58aa2a666e37626a990fdca0116", + "/home/ts/.local/state/openhcs-maintenance/20261004/canonical-runtime-cache-client-paired-v12-qualified/native/cp_tutorial_3d_monolayer/outputs/0/3d_monolayer_erodedResizedNuclei.csv": "66a58f78cab0cfdbe907468e8ba383fc59fab49025b84b589855bdfa04854609", + "/home/ts/.local/state/openhcs-maintenance/20261004/canonical-runtime-cache-client-paired-v12-qualified/native/cp_tutorial_3d_monolayer/outputs/0/3d_monolayer_xy1_ch2_NucleiLabels.tiff": "340bbd795541e4031749d1fff767fa4fcdcac10f5b97879056b25dac9fd7674b", + "/home/ts/.local/state/openhcs-maintenance/20261004/canonical-runtime-cache-client-paired-v12-qualified/native/cp_tutorial_3d_monolayer/outputs/0/3d_monolayer_Nuclei.csv": "440c33edc7e8cb5611910a835454db62390301a7af617a542349f60aece57561", + "/home/ts/.local/state/openhcs-maintenance/20261004/canonical-runtime-cache-client-paired-v12-qualified/native/cp_tutorial_3d_monolayer/outputs/0/3d_monolayer_Cells.csv": "cc34681db8a66c38ca77bc47db496b26703f21e4d7c7628dd74e30c33250859f", + "/home/ts/.local/state/openhcs-maintenance/20261004/canonical-runtime-coherent-paired-v13-qualified/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/results/3d_monolayer_downsizedNuclei.csv": "a7b998c5a524e11747fc5452fd763fc3d9abe16f46e961f62e09e9393b6a8adf", + "/home/ts/.local/state/openhcs-maintenance/20261004/canonical-runtime-coherent-paired-v13-qualified/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/results/3d_monolayer_Nuclei.csv": "17500f5d4321bbf255df31f7a3503339029c2b077045a6c10e4d4f6f0db9ad1e", + "/home/ts/.local/state/openhcs-maintenance/20261004/canonical-runtime-coherent-paired-v13-qualified/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z001_t001_CellsLabels.tiff": "64e6fc421b929e67b440b8a7a14a0c36ed42a8d1831fd1a2685103ee18023471", + "/home/ts/.local/state/openhcs-maintenance/20261004/canonical-runtime-coherent-paired-v13-qualified/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/results/3d_monolayer_Image.csv": "75ac32ff5ef57bc285ec4eae1c9b501c27a35b486bf35435af5d499d856d34a4", + "/home/ts/.local/state/openhcs-maintenance/20261004/canonical-runtime-coherent-paired-v13-qualified/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/results/3d_monolayer_erodedResizedNuclei.csv": "cca23f86a85bb3ee7a5c3a1d174c34b5f026ca7f399be98458e1a8c6e12d5c77", + "/home/ts/.local/state/openhcs-maintenance/20261004/canonical-runtime-coherent-paired-v13-qualified/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/results/3d_monolayer_erodedDownsizedNuclei.csv": "ee507fb9c2387f86fc768184baf2596ebe1f8e40f7fc5eb24f252345fee63ae6", + "/home/ts/.local/state/openhcs-maintenance/20261004/canonical-runtime-coherent-paired-v13-qualified/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/openhcs_metadata.json.lock": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "/home/ts/.local/state/openhcs-maintenance/20261004/canonical-runtime-coherent-paired-v13-qualified/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/results/3d_monolayer_Cells.csv": "6f6e7431171ed5ea73a01784105147eca0e43a6e3e41f8720df93106353c9c79", + "/home/ts/.local/state/openhcs-maintenance/20261004/canonical-runtime-coherent-paired-v13-qualified/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z001_t001_NucleiLabels.tiff": "ca1a92ddcb7bf58230bb912458caac5c8277f16e84dd67354ac1ef421ef26f67", + "/home/ts/.local/state/openhcs-maintenance/20261004/canonical-runtime-coherent-paired-v13-qualified/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/openhcs_metadata.json": "7abeed37c6bb569dae7578de336df9cf66ecb9c1cfd5d2227513d87b56212e96" + } + }, + { + "case": "cp_tutorial_3d_monolayer", + "ordinary_repeat": 0, + "native_repeat": 1, + "measurement_differences": 0, + "image_differences": 0, + "tables": [ + 7, + 6 + ], + "physical_images": [ + 2, + 2 + ], + "logical_images": [ + 2, + 2 + ], + "known_relationship_keys": [ + 3, + 3 + ], + "ordinary_receipt_sha256": "633d57c188c7701d05105ba96d1f8c3cd33ef2910a22dae00ca93dd028cb8618", + "output_hashes": { + "/home/ts/.local/state/openhcs-maintenance/20261004/canonical-runtime-cache-client-paired-v12-qualified/native/cp_tutorial_3d_monolayer/outputs/1/3d_monolayer_xy1_ch0_CellsLabels.tiff": "aaed9ed23179a162ee7f5a7e8d1d88f1fa342ca55172b7fccd4cbf67f7841d81", + "/home/ts/.local/state/openhcs-maintenance/20261004/canonical-runtime-cache-client-paired-v12-qualified/native/cp_tutorial_3d_monolayer/outputs/1/3d_monolayer_Nuclei.csv": "440c33edc7e8cb5611910a835454db62390301a7af617a542349f60aece57561", + "/home/ts/.local/state/openhcs-maintenance/20261004/canonical-runtime-cache-client-paired-v12-qualified/native/cp_tutorial_3d_monolayer/outputs/1/3d_monolayer_erodedDownsizedNuclei.csv": "527a0cce497d2a618478be84d1a0bf174049f58aa2a666e37626a990fdca0116", + "/home/ts/.local/state/openhcs-maintenance/20261004/canonical-runtime-cache-client-paired-v12-qualified/native/cp_tutorial_3d_monolayer/outputs/1/3d_monolayer_Experiment.csv": "ae3bf6c4967656a3cbad7de214db7b56a42452ef6db777f8458d89061f8b15e7", + "/home/ts/.local/state/openhcs-maintenance/20261004/canonical-runtime-cache-client-paired-v12-qualified/native/cp_tutorial_3d_monolayer/outputs/1/3d_monolayer_downsizedNuclei.csv": "2c66bc7b17de52147d5a875403f9a9746019ac61371c08157979044c6ed818dd", + "/home/ts/.local/state/openhcs-maintenance/20261004/canonical-runtime-cache-client-paired-v12-qualified/native/cp_tutorial_3d_monolayer/outputs/1/3d_monolayer_Cells.csv": "cc34681db8a66c38ca77bc47db496b26703f21e4d7c7628dd74e30c33250859f", + "/home/ts/.local/state/openhcs-maintenance/20261004/canonical-runtime-cache-client-paired-v12-qualified/native/cp_tutorial_3d_monolayer/outputs/1/3d_monolayer_Image.csv": "8b58906e58685d5433f651c69e1b1dcbe69a6c76d32ccd166e6673654127447f", + "/home/ts/.local/state/openhcs-maintenance/20261004/canonical-runtime-cache-client-paired-v12-qualified/native/cp_tutorial_3d_monolayer/outputs/1/3d_monolayer_xy1_ch2_NucleiLabels.tiff": "340bbd795541e4031749d1fff767fa4fcdcac10f5b97879056b25dac9fd7674b", + "/home/ts/.local/state/openhcs-maintenance/20261004/canonical-runtime-cache-client-paired-v12-qualified/native/cp_tutorial_3d_monolayer/outputs/1/3d_monolayer_erodedResizedNuclei.csv": "66a58f78cab0cfdbe907468e8ba383fc59fab49025b84b589855bdfa04854609", + "/home/ts/.local/state/openhcs-maintenance/20261004/canonical-runtime-coherent-paired-v13-qualified/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/results/3d_monolayer_downsizedNuclei.csv": "a7b998c5a524e11747fc5452fd763fc3d9abe16f46e961f62e09e9393b6a8adf", + "/home/ts/.local/state/openhcs-maintenance/20261004/canonical-runtime-coherent-paired-v13-qualified/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/results/3d_monolayer_Nuclei.csv": "17500f5d4321bbf255df31f7a3503339029c2b077045a6c10e4d4f6f0db9ad1e", + "/home/ts/.local/state/openhcs-maintenance/20261004/canonical-runtime-coherent-paired-v13-qualified/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w0_z001_t001_CellsLabels.tiff": "64e6fc421b929e67b440b8a7a14a0c36ed42a8d1831fd1a2685103ee18023471", + "/home/ts/.local/state/openhcs-maintenance/20261004/canonical-runtime-coherent-paired-v13-qualified/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/results/3d_monolayer_Image.csv": "75ac32ff5ef57bc285ec4eae1c9b501c27a35b486bf35435af5d499d856d34a4", + "/home/ts/.local/state/openhcs-maintenance/20261004/canonical-runtime-coherent-paired-v13-qualified/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/results/3d_monolayer_erodedResizedNuclei.csv": "cca23f86a85bb3ee7a5c3a1d174c34b5f026ca7f399be98458e1a8c6e12d5c77", + "/home/ts/.local/state/openhcs-maintenance/20261004/canonical-runtime-coherent-paired-v13-qualified/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/results/3d_monolayer_erodedDownsizedNuclei.csv": "ee507fb9c2387f86fc768184baf2596ebe1f8e40f7fc5eb24f252345fee63ae6", + "/home/ts/.local/state/openhcs-maintenance/20261004/canonical-runtime-coherent-paired-v13-qualified/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/openhcs_metadata.json.lock": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "/home/ts/.local/state/openhcs-maintenance/20261004/canonical-runtime-coherent-paired-v13-qualified/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/results/3d_monolayer_Cells.csv": "6f6e7431171ed5ea73a01784105147eca0e43a6e3e41f8720df93106353c9c79", + "/home/ts/.local/state/openhcs-maintenance/20261004/canonical-runtime-coherent-paired-v13-qualified/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/images/W001_s001_w2_z001_t001_NucleiLabels.tiff": "ca1a92ddcb7bf58230bb912458caac5c8277f16e84dd67354ac1ef421ef26f67", + "/home/ts/.local/state/openhcs-maintenance/20261004/canonical-runtime-coherent-paired-v13-qualified/ordinary-0/cp_tutorial_3d_monolayer/wells_1/workers_1/images_3d_monolayer_final_source_workspace_well_throughput/openhcs_metadata.json": "7abeed37c6bb569dae7578de336df9cf66ecb9c1cfd5d2227513d87b56212e96" + } + }, + { + "case": "ExampleSpeckles", + "ordinary_repeat": 0, + "native_repeat": 0, + "measurement_differences": 0, + "image_differences": 0, + "tables": [ + 3, + 3 + ], + "physical_images": [ + 0, + 0 + ], + "logical_images": [ + 0, + 0 + ], + "known_relationship_keys": [ + 1, + 1 + ], + "ordinary_receipt_sha256": "09ae9829478d3948a6e1dcfd457fd83cc9f33f20ca9af3ca1b6d972d41bbd7ed", + "output_hashes": { + "/home/ts/.local/state/openhcs-maintenance/20261004/canonical-runtime-cache-client-paired-v12-qualified/native/ExampleSpeckles/outputs/0/h2ax.csv": "0f54fc72ccdeb7e1a68bab9dc3a8d9d49788cdf81dbbc109ed119e589c09538a", + "/home/ts/.local/state/openhcs-maintenance/20261004/canonical-runtime-cache-client-paired-v12-qualified/native/ExampleSpeckles/outputs/0/Nuclei.csv": "15af7cac08d651c19b3e3f409b2b0d7fc4f96011c9b53394aa9a35969a8936a6", + "/home/ts/.local/state/openhcs-maintenance/20261004/canonical-runtime-cache-client-paired-v12-qualified/native/ExampleSpeckles/outputs/0/Image.csv": "ecf5dc33df4e9252eeff914df33376fc233be116c407e1c20056d6f5448e8c20", + "/home/ts/.local/state/openhcs-maintenance/20261004/canonical-runtime-coherent-paired-v13-qualified/ordinary-0/ExampleSpeckles/wells_1/workers_1/images_ExampleSpeckles_source_workspace_well_throughput/openhcs_metadata.json.lock": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "/home/ts/.local/state/openhcs-maintenance/20261004/canonical-runtime-coherent-paired-v13-qualified/ordinary-0/ExampleSpeckles/wells_1/workers_1/images_ExampleSpeckles_source_workspace_well_throughput/results/Image.csv": "85ef16f24e75f03dc7055215cf2e6cb196b1dc0a0d73713a4c5999f698d4f96e", + "/home/ts/.local/state/openhcs-maintenance/20261004/canonical-runtime-coherent-paired-v13-qualified/ordinary-0/ExampleSpeckles/wells_1/workers_1/images_ExampleSpeckles_source_workspace_well_throughput/openhcs_metadata.json": "71582c62cabb2571ebf8a0de57f92fdf82c55a7ece3dac0bf2a6eca95cad84c9", + "/home/ts/.local/state/openhcs-maintenance/20261004/canonical-runtime-coherent-paired-v13-qualified/ordinary-0/ExampleSpeckles/wells_1/workers_1/images_ExampleSpeckles_source_workspace_well_throughput/results/Nuclei.csv": "e50cb9f8c23f65e9ce8db25132263cf4a4448ed65fc1088d782536abf74c5670", + "/home/ts/.local/state/openhcs-maintenance/20261004/canonical-runtime-coherent-paired-v13-qualified/ordinary-0/ExampleSpeckles/wells_1/workers_1/images_ExampleSpeckles_source_workspace_well_throughput/results/h2ax.csv": "eb453565f3b79ac932eeb5cde8605888b72e58c80f42edbbf0b1ba37f34fd6f8" + } + }, + { + "case": "ExampleSpeckles", + "ordinary_repeat": 0, + "native_repeat": 1, + "measurement_differences": 0, + "image_differences": 0, + "tables": [ + 3, + 3 + ], + "physical_images": [ + 0, + 0 + ], + "logical_images": [ + 0, + 0 + ], + "known_relationship_keys": [ + 1, + 1 + ], + "ordinary_receipt_sha256": "09ae9829478d3948a6e1dcfd457fd83cc9f33f20ca9af3ca1b6d972d41bbd7ed", + "output_hashes": { + "/home/ts/.local/state/openhcs-maintenance/20261004/canonical-runtime-cache-client-paired-v12-qualified/native/ExampleSpeckles/outputs/1/Nuclei.csv": "15af7cac08d651c19b3e3f409b2b0d7fc4f96011c9b53394aa9a35969a8936a6", + "/home/ts/.local/state/openhcs-maintenance/20261004/canonical-runtime-cache-client-paired-v12-qualified/native/ExampleSpeckles/outputs/1/Image.csv": "e87fca015a2cfc9ac2b626c3c52a24d415c95a37fb7c5c075138a16fb42ba464", + "/home/ts/.local/state/openhcs-maintenance/20261004/canonical-runtime-cache-client-paired-v12-qualified/native/ExampleSpeckles/outputs/1/h2ax.csv": "0f54fc72ccdeb7e1a68bab9dc3a8d9d49788cdf81dbbc109ed119e589c09538a", + "/home/ts/.local/state/openhcs-maintenance/20261004/canonical-runtime-coherent-paired-v13-qualified/ordinary-0/ExampleSpeckles/wells_1/workers_1/images_ExampleSpeckles_source_workspace_well_throughput/openhcs_metadata.json.lock": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "/home/ts/.local/state/openhcs-maintenance/20261004/canonical-runtime-coherent-paired-v13-qualified/ordinary-0/ExampleSpeckles/wells_1/workers_1/images_ExampleSpeckles_source_workspace_well_throughput/results/Image.csv": "85ef16f24e75f03dc7055215cf2e6cb196b1dc0a0d73713a4c5999f698d4f96e", + "/home/ts/.local/state/openhcs-maintenance/20261004/canonical-runtime-coherent-paired-v13-qualified/ordinary-0/ExampleSpeckles/wells_1/workers_1/images_ExampleSpeckles_source_workspace_well_throughput/openhcs_metadata.json": "71582c62cabb2571ebf8a0de57f92fdf82c55a7ece3dac0bf2a6eca95cad84c9", + "/home/ts/.local/state/openhcs-maintenance/20261004/canonical-runtime-coherent-paired-v13-qualified/ordinary-0/ExampleSpeckles/wells_1/workers_1/images_ExampleSpeckles_source_workspace_well_throughput/results/Nuclei.csv": "e50cb9f8c23f65e9ce8db25132263cf4a4448ed65fc1088d782536abf74c5670", + "/home/ts/.local/state/openhcs-maintenance/20261004/canonical-runtime-coherent-paired-v13-qualified/ordinary-0/ExampleSpeckles/wells_1/workers_1/images_ExampleSpeckles_source_workspace_well_throughput/results/h2ax.csv": "eb453565f3b79ac932eeb5cde8605888b72e58c80f42edbbf0b1ba37f34fd6f8" + } + }, + { + "case": "cp_tutorial_beginner_segmentation_final", + "ordinary_repeat": 0, + "native_repeat": 0, + "measurement_differences": 0, + "image_differences": 0, + "tables": [ + 7, + 7 + ], + "physical_images": [ + 2, + 2 + ], + "logical_images": [ + 2, + 2 + ], + "known_relationship_keys": [ + 5, + 5 + ], + "ordinary_receipt_sha256": "58b16de63936ba96b993b01f23119dc584e8b99a11fb12639cc6fc6ac0c1de6b", + "output_hashes": { + "/home/ts/.local/state/openhcs-maintenance/20261004/canonical-runtime-cache-client-paired-v12-qualified/native/cp_tutorial_beginner_segmentation_final/outputs/0/MyExpt_Nucleoli.csv": "6c7ae52b3b3d3dbfa7cbbb8e088cf9cb2aa4d9c14c608867b8a18b29eb783f2a", + "/home/ts/.local/state/openhcs-maintenance/20261004/canonical-runtime-cache-client-paired-v12-qualified/native/cp_tutorial_beginner_segmentation_final/outputs/0/MyExpt_NucleoliChildObjects.csv": "bd75ae8a5ae880fa090956729f7826a6242164ab763172084309db29b01b5cb6", + "/home/ts/.local/state/openhcs-maintenance/20261004/canonical-runtime-cache-client-paired-v12-qualified/native/cp_tutorial_beginner_segmentation_final/outputs/0/MyExpt_Cells.csv": "990c806a68d7f44addfc5294acd50bd42ff6cfcab23fb11b5c39e5f45f9be505", + "/home/ts/.local/state/openhcs-maintenance/20261004/canonical-runtime-cache-client-paired-v12-qualified/native/cp_tutorial_beginner_segmentation_final/outputs/0/MyExpt_Experiment.csv": "ddf5fa4028a6593d3bf112279f963f42c011c6ee1c934af485cfe9fcc6b342f3", + "/home/ts/.local/state/openhcs-maintenance/20261004/canonical-runtime-cache-client-paired-v12-qualified/native/cp_tutorial_beginner_segmentation_final/outputs/0/overlay_images/plate1_A14_site2_Ch3_overlay.tiff": "89888a6d23423bb99118578d423fb5efa13641c1346ddb09547792fd294d6981", + "/home/ts/.local/state/openhcs-maintenance/20261004/canonical-runtime-cache-client-paired-v12-qualified/native/cp_tutorial_beginner_segmentation_final/outputs/0/MyExpt_Image.csv": "8b4fa44d6178a4c3e8fe113f0a6d64841436b100968f16b9627a3996699948dc", + "/home/ts/.local/state/openhcs-maintenance/20261004/canonical-runtime-cache-client-paired-v12-qualified/native/cp_tutorial_beginner_segmentation_final/outputs/0/MyExpt_Nuclei.csv": "80496e920f2098aa181c8d6f7efd435c9b9da62cf28780d61e898fa899b62304", + "/home/ts/.local/state/openhcs-maintenance/20261004/canonical-runtime-cache-client-paired-v12-qualified/native/cp_tutorial_beginner_segmentation_final/outputs/0/overlay_images/plate1_A14_site1_Ch3_overlay.tiff": "05a85674095f244ab4d85aad6644e04420ac2e8394d01d781ec968ecb5ff59f1", + "/home/ts/.local/state/openhcs-maintenance/20261004/canonical-runtime-cache-client-paired-v12-qualified/native/cp_tutorial_beginner_segmentation_final/outputs/0/MyExpt_Cytoplasm.csv": "f918da3280f8e88f70b048249ed10f9815ef04f5381fe0fe016cbc0ed0b19c2f", + "/home/ts/.local/state/openhcs-maintenance/20261004/canonical-runtime-coherent-paired-v13-qualified/ordinary-0/cp_tutorial_beginner_segmentation_final/wells_1/workers_1/images_Illum-corrected_segmentation_final_source_workspace_well_throughput/results/MyExpt_Cytoplasm.csv": "0e843133986efdcc44443575f8dca408ebdb6a45c13ed9d33a0691046f365bfd", + "/home/ts/.local/state/openhcs-maintenance/20261004/canonical-runtime-coherent-paired-v13-qualified/ordinary-0/cp_tutorial_beginner_segmentation_final/wells_1/workers_1/images_Illum-corrected_segmentation_final_source_workspace_well_throughput/results/MyExpt_Nuclei.csv": "82e6bf71dd73a17b0fe97ec96b93055cc09918ec36d7e9bc443818e15133cf5b", + "/home/ts/.local/state/openhcs-maintenance/20261004/canonical-runtime-coherent-paired-v13-qualified/ordinary-0/cp_tutorial_beginner_segmentation_final/wells_1/workers_1/images_Illum-corrected_segmentation_final_source_workspace_well_throughput/images/W001_s001_w3_z001_t001_overlay.tiff": "a623e96717783cf919c95f0005dc6dfc45677e7d52a36d0a2720b120f89abe16", + "/home/ts/.local/state/openhcs-maintenance/20261004/canonical-runtime-coherent-paired-v13-qualified/ordinary-0/cp_tutorial_beginner_segmentation_final/wells_1/workers_1/images_Illum-corrected_segmentation_final_source_workspace_well_throughput/results/MyExpt_Image.csv": "481cd40bba32dc50883007662cf0885326e83aa3efa8d18250426bad2fd719a7", + "/home/ts/.local/state/openhcs-maintenance/20261004/canonical-runtime-coherent-paired-v13-qualified/ordinary-0/cp_tutorial_beginner_segmentation_final/wells_1/workers_1/images_Illum-corrected_segmentation_final_source_workspace_well_throughput/results/MyExpt_Nucleoli.csv": "845b39e07d694b1864c3e65bd4980d89bda24ba14fea34e63a148767b64fa30c", + "/home/ts/.local/state/openhcs-maintenance/20261004/canonical-runtime-coherent-paired-v13-qualified/ordinary-0/cp_tutorial_beginner_segmentation_final/wells_1/workers_1/images_Illum-corrected_segmentation_final_source_workspace_well_throughput/results/MyExpt_Cells.csv": "e72abca3ccfc5ffdb4e24a955c8f9ecddfab8e657c8e9df1e3552c6efdf3f23e", + "/home/ts/.local/state/openhcs-maintenance/20261004/canonical-runtime-coherent-paired-v13-qualified/ordinary-0/cp_tutorial_beginner_segmentation_final/wells_1/workers_1/images_Illum-corrected_segmentation_final_source_workspace_well_throughput/results/MyExpt_NucleoliChildObjects.csv": "5f06dd1b2b81f4f527d5ade9c608e10c61befd9dc55ffce10234d0bb8ad89491", + "/home/ts/.local/state/openhcs-maintenance/20261004/canonical-runtime-coherent-paired-v13-qualified/ordinary-0/cp_tutorial_beginner_segmentation_final/wells_1/workers_1/images_Illum-corrected_segmentation_final_source_workspace_well_throughput/openhcs_metadata.json": "a9688ee0d51600ef559c5ae52cb2f840044f84834f630038ae37b26c6fb22eac", + "/home/ts/.local/state/openhcs-maintenance/20261004/canonical-runtime-coherent-paired-v13-qualified/ordinary-0/cp_tutorial_beginner_segmentation_final/wells_1/workers_1/images_Illum-corrected_segmentation_final_source_workspace_well_throughput/results/MyExpt_Object relationships.csv": "99a65fd24408eaf57a323035adbfea18a2cd336c827ba9d65095e30dd0b87393", + "/home/ts/.local/state/openhcs-maintenance/20261004/canonical-runtime-coherent-paired-v13-qualified/ordinary-0/cp_tutorial_beginner_segmentation_final/wells_1/workers_1/images_Illum-corrected_segmentation_final_source_workspace_well_throughput/images/W001_s002_w3_z001_t001_overlay.tiff": "0ea08cc6991124dbed3643a6d8a3d3190eb86a5c7b49a98ec9406d987196ddc8", + "/home/ts/.local/state/openhcs-maintenance/20261004/canonical-runtime-coherent-paired-v13-qualified/ordinary-0/cp_tutorial_beginner_segmentation_final/wells_1/workers_1/images_Illum-corrected_segmentation_final_source_workspace_well_throughput/openhcs_metadata.json.lock": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + } + }, + { + "case": "cp_tutorial_beginner_segmentation_final", + "ordinary_repeat": 0, + "native_repeat": 1, + "measurement_differences": 0, + "image_differences": 0, + "tables": [ + 7, + 7 + ], + "physical_images": [ + 2, + 2 + ], + "logical_images": [ + 2, + 2 + ], + "known_relationship_keys": [ + 5, + 5 + ], + "ordinary_receipt_sha256": "58b16de63936ba96b993b01f23119dc584e8b99a11fb12639cc6fc6ac0c1de6b", + "output_hashes": { + "/home/ts/.local/state/openhcs-maintenance/20261004/canonical-runtime-cache-client-paired-v12-qualified/native/cp_tutorial_beginner_segmentation_final/outputs/1/MyExpt_Nuclei.csv": "80496e920f2098aa181c8d6f7efd435c9b9da62cf28780d61e898fa899b62304", + "/home/ts/.local/state/openhcs-maintenance/20261004/canonical-runtime-cache-client-paired-v12-qualified/native/cp_tutorial_beginner_segmentation_final/outputs/1/MyExpt_Image.csv": "236f19d9fa89b84c3b4ec3eecd15f7b98a9cf2581cb1318050788009ad50a9ea", + "/home/ts/.local/state/openhcs-maintenance/20261004/canonical-runtime-cache-client-paired-v12-qualified/native/cp_tutorial_beginner_segmentation_final/outputs/1/MyExpt_NucleoliChildObjects.csv": "bd75ae8a5ae880fa090956729f7826a6242164ab763172084309db29b01b5cb6", + "/home/ts/.local/state/openhcs-maintenance/20261004/canonical-runtime-cache-client-paired-v12-qualified/native/cp_tutorial_beginner_segmentation_final/outputs/1/MyExpt_Cells.csv": "990c806a68d7f44addfc5294acd50bd42ff6cfcab23fb11b5c39e5f45f9be505", + "/home/ts/.local/state/openhcs-maintenance/20261004/canonical-runtime-cache-client-paired-v12-qualified/native/cp_tutorial_beginner_segmentation_final/outputs/1/MyExpt_Cytoplasm.csv": "f918da3280f8e88f70b048249ed10f9815ef04f5381fe0fe016cbc0ed0b19c2f", + "/home/ts/.local/state/openhcs-maintenance/20261004/canonical-runtime-cache-client-paired-v12-qualified/native/cp_tutorial_beginner_segmentation_final/outputs/1/MyExpt_Experiment.csv": "8c9d0ded37816301e8ae329e33fa8e442563c2a83f2b023213715f6793b7c926", + "/home/ts/.local/state/openhcs-maintenance/20261004/canonical-runtime-cache-client-paired-v12-qualified/native/cp_tutorial_beginner_segmentation_final/outputs/1/overlay_images/plate1_A14_site2_Ch3_overlay.tiff": "89888a6d23423bb99118578d423fb5efa13641c1346ddb09547792fd294d6981", + "/home/ts/.local/state/openhcs-maintenance/20261004/canonical-runtime-cache-client-paired-v12-qualified/native/cp_tutorial_beginner_segmentation_final/outputs/1/MyExpt_Nucleoli.csv": "6c7ae52b3b3d3dbfa7cbbb8e088cf9cb2aa4d9c14c608867b8a18b29eb783f2a", + "/home/ts/.local/state/openhcs-maintenance/20261004/canonical-runtime-cache-client-paired-v12-qualified/native/cp_tutorial_beginner_segmentation_final/outputs/1/overlay_images/plate1_A14_site1_Ch3_overlay.tiff": "05a85674095f244ab4d85aad6644e04420ac2e8394d01d781ec968ecb5ff59f1", + "/home/ts/.local/state/openhcs-maintenance/20261004/canonical-runtime-coherent-paired-v13-qualified/ordinary-0/cp_tutorial_beginner_segmentation_final/wells_1/workers_1/images_Illum-corrected_segmentation_final_source_workspace_well_throughput/results/MyExpt_Cytoplasm.csv": "0e843133986efdcc44443575f8dca408ebdb6a45c13ed9d33a0691046f365bfd", + "/home/ts/.local/state/openhcs-maintenance/20261004/canonical-runtime-coherent-paired-v13-qualified/ordinary-0/cp_tutorial_beginner_segmentation_final/wells_1/workers_1/images_Illum-corrected_segmentation_final_source_workspace_well_throughput/results/MyExpt_Nuclei.csv": "82e6bf71dd73a17b0fe97ec96b93055cc09918ec36d7e9bc443818e15133cf5b", + "/home/ts/.local/state/openhcs-maintenance/20261004/canonical-runtime-coherent-paired-v13-qualified/ordinary-0/cp_tutorial_beginner_segmentation_final/wells_1/workers_1/images_Illum-corrected_segmentation_final_source_workspace_well_throughput/images/W001_s001_w3_z001_t001_overlay.tiff": "a623e96717783cf919c95f0005dc6dfc45677e7d52a36d0a2720b120f89abe16", + "/home/ts/.local/state/openhcs-maintenance/20261004/canonical-runtime-coherent-paired-v13-qualified/ordinary-0/cp_tutorial_beginner_segmentation_final/wells_1/workers_1/images_Illum-corrected_segmentation_final_source_workspace_well_throughput/results/MyExpt_Image.csv": "481cd40bba32dc50883007662cf0885326e83aa3efa8d18250426bad2fd719a7", + "/home/ts/.local/state/openhcs-maintenance/20261004/canonical-runtime-coherent-paired-v13-qualified/ordinary-0/cp_tutorial_beginner_segmentation_final/wells_1/workers_1/images_Illum-corrected_segmentation_final_source_workspace_well_throughput/results/MyExpt_Nucleoli.csv": "845b39e07d694b1864c3e65bd4980d89bda24ba14fea34e63a148767b64fa30c", + "/home/ts/.local/state/openhcs-maintenance/20261004/canonical-runtime-coherent-paired-v13-qualified/ordinary-0/cp_tutorial_beginner_segmentation_final/wells_1/workers_1/images_Illum-corrected_segmentation_final_source_workspace_well_throughput/results/MyExpt_Cells.csv": "e72abca3ccfc5ffdb4e24a955c8f9ecddfab8e657c8e9df1e3552c6efdf3f23e", + "/home/ts/.local/state/openhcs-maintenance/20261004/canonical-runtime-coherent-paired-v13-qualified/ordinary-0/cp_tutorial_beginner_segmentation_final/wells_1/workers_1/images_Illum-corrected_segmentation_final_source_workspace_well_throughput/results/MyExpt_NucleoliChildObjects.csv": "5f06dd1b2b81f4f527d5ade9c608e10c61befd9dc55ffce10234d0bb8ad89491", + "/home/ts/.local/state/openhcs-maintenance/20261004/canonical-runtime-coherent-paired-v13-qualified/ordinary-0/cp_tutorial_beginner_segmentation_final/wells_1/workers_1/images_Illum-corrected_segmentation_final_source_workspace_well_throughput/openhcs_metadata.json": "a9688ee0d51600ef559c5ae52cb2f840044f84834f630038ae37b26c6fb22eac", + "/home/ts/.local/state/openhcs-maintenance/20261004/canonical-runtime-coherent-paired-v13-qualified/ordinary-0/cp_tutorial_beginner_segmentation_final/wells_1/workers_1/images_Illum-corrected_segmentation_final_source_workspace_well_throughput/results/MyExpt_Object relationships.csv": "99a65fd24408eaf57a323035adbfea18a2cd336c827ba9d65095e30dd0b87393", + "/home/ts/.local/state/openhcs-maintenance/20261004/canonical-runtime-coherent-paired-v13-qualified/ordinary-0/cp_tutorial_beginner_segmentation_final/wells_1/workers_1/images_Illum-corrected_segmentation_final_source_workspace_well_throughput/images/W001_s002_w3_z001_t001_overlay.tiff": "0ea08cc6991124dbed3643a6d8a3d3190eb86a5c7b49a98ec9406d987196ddc8", + "/home/ts/.local/state/openhcs-maintenance/20261004/canonical-runtime-coherent-paired-v13-qualified/ordinary-0/cp_tutorial_beginner_segmentation_final/wells_1/workers_1/images_Illum-corrected_segmentation_final_source_workspace_well_throughput/openhcs_metadata.json.lock": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + } + } + ], + "source_head": "9e838be5646a0dd414630f8b84951238387df2e7", + "scope": "SCIENCE ONLY: current 9e838 ordinary repeat0 versus BOTH RETAINED qualified v12 native sets. V13 campaign remains RED for terminal progress coverage; no fresh-native or timing qualification." +} diff --git a/docs/refactor/receipts/runtime-owner-consolidation-20261003.rst b/docs/refactor/receipts/runtime-owner-consolidation-20261003.rst new file mode 100644 index 0000000000..1139d5b28f --- /dev/null +++ b/docs/refactor/receipts/runtime-owner-consolidation-20261003.rst @@ -0,0 +1,345 @@ +Runtime owner consolidation +=========================== + +These changes remove parallel runtime representations and move their behavior +onto existing authorities. They support further optimization; class deletion is +not evidence of an end-to-end speedup. + +Ownership and consumer closure +------------------------------ + +``RuntimeArtifactInputRequest`` is removed. The existing CP artifact strategy +family consumes ``ArtifactSpec`` and the resolved value directly. Input +selection, raw versus normalized values, source axes and post-call source +resolution retain their existing owners. This change is merged into main as +PR #535, closing #534. The clean main candidate ``c828acaee`` passes all 541 +module, shape, source, store and direct-value controls. Shape fixtures follow +the current declared label domain and completed CP ordinals, including missing +entries; original stale-fixture failures are retained. + +``PatternGroupOutputData`` and its validation/unstack endpoint are removed. +``PatternGroupRuntime`` publishes the original output. ``AlignedImageStack`` +owns topology; ``ImagePayloadStackComposition`` owns independent buffers and +saved context; produced records determine cleanup. The sole-consumer +``RuntimeSliceAlignedImageOutputContext`` is also removed, with its algorithm +on the existing source strategy. The source-qualified output gate passes 238 +tests, including real partial writes, masks, opaque/source-bound domains, +duplicate-path preservation and subclass effects. + +The attempted deletion of ``ProjectedFunctionOutputContextStrategy`` failed +the registered-family gate: its inheritance carries fallback precedence. +The class remains and owns the actual common algorithm. The obsolete +grandparent-forwarding implementation is removed. The selector is unchanged. +The initial failed source and control receipts are retained. + +``FunctionInvocationArtifactScope`` is folded into its only concrete consumer, +``FunctionCoreExecutor``. The existing seven field declarations and method +bodies are unchanged. Constructor order, frozen slots, pickle, metadata-edge +polymorphism, debug behavior and first errors pass 158 controls. Historical +reports naming the old scope remain as evidence of their original source. + +``RuntimeImageRequest`` and ``RuntimeFunctionInvocationRequest`` are removed. +``CellProfilerImageRequest`` owns the image domain and actual callable kwargs +through execution and output recording, eliminating the five-field copy-back +step. Original aliases survive object-driven changes in image shape/count. +The shared ``RuntimeImageExecutionContext`` remains the parent for genuine +batch and measurement consumers. This lane is merged into main as PR #538, +closing #537. The clean main candidate ``7e2f97f80`` passes all 780 tests in +the 17-file execution, library, recording, binding, axis and stream gate. +The pre-existing retained-plane shape fixture now explicitly declares its +object plane domain; its Area and true-volume assertions remain intact. + +The parsed-module contract boundary now uses the existing prepared-callable +factory, matching authored compilation. The original Crop equality failure +reproduces before the carrier deletion. Commit ``5c3e12ecd`` fixes its actual +production boundary; all 641 execution/library/binding controls pass without +removing signature fields from equality or changing the original assertion. +Two additional declaration fixtures failed identically before that fix: they +omitted the existing seven QA outputs and the step-owned Costes runtime input. +Their updated assertions retain original ABI counts and add complete diagnostic +names/roles and runtime parameter checks. The final six-module contract gate +passes all 100 tests. After merging PR #538, the exact retained-plane and alias +controls pass all ten tests; an identical test duplicated by Git's merge is +removed, leaving its original definition intact. + +``CellProfilerOutputRecordRequest`` now specializes the existing input-binding +owner. Adapter, kwargs and current image are inherited once, and two temporary +binding-holder constructions are removed. The binding edge operation remains +``artifact_value(edge)``; the record's distinct declaration operation is +``declared_artifact_value(spec)``. Output-plan admission, exact endpoints, +reference broadcasts, live per-read validation and mutation epochs remain +separate and tested. Explicit subsets satisfy the inherited admission law; +record construction is keyword-only. PR #544 is merged, closing #542. After +merging latest main ``8ab4a0df7``, its clean candidate ``a23978e3c`` passes +all 470 tests in the seven-file CP gate. No pipeline timing gain is claimed +for this lane. + +``PatternGroupData`` now specializes ``PatternGroupExecutionScope`` and owns +one complete loaded cohort. ``FunctionRuntimeScope`` and its execution bridge +are deleted. ``FunctionCoreExecutor`` consumes the cohort directly; the two +adapter factories and the artifact-input forwarding helper are removed. +Image composition moves to the existing ``ImagePayloadStackComposition`` owner. +Initial source coordinates and plane count remain captured at their original +load boundary; mutable plan selectors remain live, and later image/memory +progression remains separate from that initial cohort. Frozen slots, transport +serialization, first errors, debug events and alias/mutation controls pass. +The exact migration has 844 wholly passing tests. An additional consumer shard +has 167 passes and three dynamic producer-record failures reproduced unchanged +with the three original production modules. Those failures remain open consumer +work, not waived tests. The bounded NRA census changes from 164 to 163 classes. +No pipeline timing gain is claimed; this is part of a larger semantic batch. + +The next coherent batch removes four producer/stream representations: +``FunctionStepOutputProducerIdentityRequest``, +``FunctionStepOutputProducerIdentityAuthority``, ``ProducedMemoryPathsAuthority`` +and ``StreamOutputProjectionRequest``. ``CompiledStepPlan`` derives producer +identity from the original main-flow/artifact declaration; ``ProducedOutputSemantics`` +derives memory paths and current source metadata; ``StepOutputManifestStore`` +selects current image cohorts. Save, materialization, viewer validation, +publication and all three preset consumers migrate together. ``StreamOutputBatch`` +owns admission and projection. Correlated one-pass grouping replaces a complete +record scan for each producer projection, preserving first-seen group order, +within-group order, frozen input-list structure and original projector errors. +Actual writer reloads and persisted-format decisions retain their original epochs. +The producer/source gate passes 112 tests, stream/output gate 70 and +artifact/viewer gate 79. Three stale CP fixtures now declare their producer-owned +locations; all 248 related tests pass, including missing/wrong-location rejection. +The production input-selection law is unchanged. + +The same batch removes ``AlignedImageStackKwargResolutionStrategy`` and its +seven concrete leaves. Their operation now belongs to the existing +``RuntimeSliceProjectionStrategy`` family. Ordinary projection and argument +alignment remain distinct operations: tuple recursion versus list passthrough, +whole image spatial alignment, label projection before spatial alignment, and +nested outer-stack selection keep their original laws. Operation participation +and nominal members derive from existing declarations and method ownership, +with one shared MRO ordering algorithm and cached type selection. Narrower child +declarations and dynamic extensions are covered by the 517-test family/CP gate. +External extensions must use the existing projection family; equal-distance +virtual-ABC ties follow its stable registration order. The separate registry's +independent tie order and removed APIs have no compatibility aliases. +A genuine old aligned-value bug also closes: the removed strategy called a +nonexistent ``projection_axis.aligned_value``. The merged leaf invokes the +existing value owner's ``value_for_aligned_slice`` capability, with exact outer +count/index controls. Original ``AttributeError`` evidence is retained. + +The combined 22-file execution, projection, image topology, save, +publication, artifact, debug, framework, path and CP gate passes all 1,247 tests +in 18.97 seconds. This validates the structural batch together. The subsequent +paired measurement below does not establish a material speedup. An isolated main +cherry-pick of the loaded-cohort change was rejected because it depends on the +earlier executor/output consolidation; that temporary operation was aborted, +its conflict evidence retained, and the empty branch removed. The coherent +implementation remains in the formally linked draft PR #394. + +Publication reader consolidation uses the existing document handler and source +projection builder. Required projection-only viewer consumers remain. Its 94 +reader controls pass; four saved-operand replays remove 151ms median locally +while preserving ordered paths and five complete atomic transaction results. +This duplicate read exists in the draft branch. Main already reads once, so +no separate main performance PR is warranted for this change. + +Checkpoint ownership correction +------------------------------- + +The identical current-main checkpoint fixture passes its required 48 files +while the draft branch originally produced only 24 named files. Issue #536 +tracks this branch regression. Named artifact materialization and ordinary +checkpoint publication were assigning the same artifact-name qualifier. + +Commit ``0dd77da46`` derives topology once at the existing save boundary. +Unwrapped canonical returns use ordinary source filenames while retaining +typed producer context; explicit named aligned outputs retain qualifiers. +The materialization owner keeps its explicit artifact-name policy. No extra +copy, wrapper or per-function flag is introduced. All 199 relevant controls +pass, including unchanged 48-file inventories, metadata reopening, yeast, +labels, table passthrough and opaque domains. The original saver reproduces +the new unwrapped-path control failure. + +Typed publication and input source resolution +-------------------------------------------- + +Produced output projections now stay typed through the atomic publication +transaction. The existing ``VirtualWorkspaceSourceProjectionEntries`` admits +incoming projection/path pairs, merges them with the current durable document, +and supplies serialization at the disk boundary. Producer ``metadata_dict`` +construction and the atomic writer's raw-field merge are deleted. Incoming +projections are not decoded; unreplaced durable records are decoded once. +The shared owner retains duplicate-identity admission, replacement repair, +path order, concurrent-well retention and final reconciliation pruning. +Metadata-disabled transactions retain opaque existing wire annotations and +orphan mapping entries. The internal incoming API intentionally requires typed +entries; persisted JSON remains the external format. + +Input source-context queries now consume the value already bound and projected +by ``RuntimeInputBindingRequest``. They no longer repeat image aliasing, +intensity normalization or object-label binding. Each post-call source read +still resolves the current input, including callback mutations. + +One output identity owner +------------------------- + +``FunctionOutputIdentity`` now owns construction, component and extension +normalization, qualifiers, filenames and paths. ``ProducedOutputSemantics`` +inherits these operations. The five detached identity/path/component/extension/ +qualifier facades are deleted and their production consumers migrated. +Semantic coordinates remain distinct from storage filename coordinates; +the external parser and execution-local caches retain their own roles. + +The unused five-class ``core.progress.emitters`` family and its public +reexports are deleted. Actual emission still uses the required progress queue, +the execution server's emitter, and the GUI's event registry. + +The publication, source-binding, identity and progress changes pass one coupled +22-file gate covering execution, recording, masks, live mutations, materialization, +persisted reopening, projection and progress (971 controls, 10.92s). This is a +behavioral check of the combined source, not evidence of speedup. + +The proposed metadata-only input lane was withdrawn before publication. A real +compile-only inventory admitted seven 3D groups and no Speckles groups; existing +cache hits already avoid assembly. The proposed broader lazy composition was +also rejected: eliminating source snapshots changes in-place callable isolation, +while preserving them retains the copying cost. Neither route is promoted as +an unconsumed capability or a dominant performance fix. + +Canonical producer transport and measurement rosters +--------------------------------------------------- + +An input edge now retains its exact producer storage independently of its +semantic primary-image projection. The redundant ``consumes_main_flow`` flag +is removed. Artifact-owned execution admits an independent pixel/mask buffer +directly from those producers instead of unstacking, saving, discovering and +reloading an unnamed checkpoint. ``CompiledStepPlan`` derives checkpoint demand +from actual consumers and propagates that demand through preserved main flow. +Path-based conversion, sequential filters, implicit raw inputs and unavailable +same-step producers retain their required transport. + +``RuntimeArtifactInput`` owns producer selection and candidate coordinates; +runtime scope joins retain whole correlated rows and permit compatible partial +contexts. Original filename metadata does not replace producer coordinates. +The existing artifact type owns image-context extraction, and the existing +stack composition owns independent buffer admission. No address or data cache +is introduced. + +The importer preserves a native measurement module's full image/object roster. +The existing measurement executor owns its Cartesian measurement traversal and +batch kernels. NATURAL object measurements resolve that roster once, without +building an unused composed image request; COMPOSED and selected-plane source +identity retain their declared behavior. + +Explicit roster compilation belongs to the adapter and declaration owners, +while raw scalar argument multiplicity remains on the raw binder. Omitted +object selection still fails when more than one subject is available. Recorded +measurement payload owners validate named subject multiplicity after the common +row scope/id-field checks. + +Invocation selection now also owns the source-origin view: represented inputs +retain the current payload epoch, and unrepresented explicit original images +resolve through their exact matched source binding. The separate source-input +selection pass is removed. An absent stored primary cannot be replaced by its +producer's older value. Exact producer-group selection is distinct from +additional image-set fixed coordinates; discovery retains actual produced +coordinates, while site, time, Z and genuinely fixed-channel constraints remain. +Physical publication loads original memory addresses and writes manifest-owned +destinations under the current output root; preserved outputs no longer write +back into the input plate. + +Current runtime and transport boundaries +---------------------------------------- + +Commit ``9d79c4289`` repairs the declared runtime/transport ownership boundary +(#558). Objectstate serialization resolution returns ordinary processing +contexts unchanged; the two bundle maps therefore previously shared plans, +and transport normalization rewrote the prepared runtime graph. The existing +bundle now derives separate transport context/plan snapshots. Inline, fork and +thread resources consume rich contexts directly; queued process workers and +public serialization consume transport snapshots. Stores, pixels, configuration +and service lifetimes retain their existing sharing. This is not a claim that +all compiled plans have been sealed. Actual warmed callable identity and pickle +roundtrip controls pass. Commit ``65a76d7e9`` also strips process-local hooks +from the compiled contract metadata on its transport view, preserving the +rich contract identity; both callable-reference and contract fields are +covered by the same real pickle control. + +Commit ``ad4670f20`` folds producer path admission into +``ProducedPathRecordIndex``. ``ProducedPathSet``, ``ProducedPathPatternSelector`` +and the detached producer-pattern path cache are removed. A loader resolves one +current record cohort and derives its paths, retaining cardinality admission +after source-context construction and before cache/pixel access. Source-only +and pipeline-start requests do not acquire producer records. + +The same batch puts source transformations on ``NamedSourceBinding`` and deletes +``source_image_semantics.py``. The physical metadata context retains header, +calibration and crop geometry; a binding's already-resolved channel axis remains +authoritative after missing-context merge, including declared grayscale absence. +Mutable scalar provenance remains independent. One coupled source, producer, +calibration and original measurement journey gate passes 236 controls. This +later source is not included in the paired performance evidence below; no +additional speedup is claimed before its scientific comparison. + +Evidence scope +-------------- + +The source-qualified gates above overlap and refer to separate revisions; +their counts are not a combined whole-branch pass. NRA original-class census, +family projection and method comparison support ownership inspection, not +complete runtime equivalence. Unchanged method bodies do not prove constructor +or effect behavior; those have separate executed controls. + +Fresh paired evidence at ``c59eaa55f`` is retained under +``benchmark/results/perf_invocation_owner_paired_20261003``. All eight strict +scientific comparisons pass. Mean 3D execution is 9.021577s versus native +14.793260s (1.640x); Speckles is 1.554196s versus 1.964025s (1.264x). +Two observations have substantial spread and do not establish a causal gain. +This source precedes the output-record specialization. Its remaining execution +gap to 2x is 1.624947s for 3D and 0.572183s for Speckles. + +The subsequent ordinary paired run at ``74693f589`` measures mean 3D execution +8.841s, total 10.823s and native warm invocation 15.230s: 1.723x execution and +1.407x total. Speckles measures execution 1.415s, total 2.216s and native +1.896s: 1.340x execution and 0.856x total. All eight scientific comparisons +pass. The 0.180s difference from the previous 3D execution mean lies within +the observed spread and is not a causal performance claim. The execution gap +to 2x native remains 1.227s. Local timing and qualification records are retained +under ``owner-consolidation-746-paired-v1`` and its preparation sibling in the +20261003 maintenance evidence root. The typed publication, input binding and +identity changes described above follow this measurement and remain unmeasured. + +The original-pipeline campaigns under ``canonical-producer-transport-paired-v1`` +and ``v2`` failed at compilation and runtime respectively; their clocks are not +qualified performance evidence. The ``v3`` campaign at ``c50a947f4`` completed +both ordinary sweeps and fresh native runs but failed strict comparison with +42 missing origMemb intensity features. Its faster timings are also unqualified. +The missing explicit source-roster edge is repaired by the invocation selector; +the corrected scientific comparison below covers both original pipelines. +All failed campaigns are retained, and no output exclusion or tolerance change +is admitted. + +The corrected ``canonical-producer-transport-paired-v5`` campaign at +``102d6e491`` passes all eight strict scientific comparisons, including complete +measurement inventories and images with existing CP tolerances. Active source +aliases derive from the current payload for each invocation, preserving outputs +and mutations within a function chain. The existing artifact source-relation +family supplies the explicitly selected image-set context to object inputs; +exact producer addresses and unrelated fixed coordinates remain strict. + +Means of two independent ordinary and two fresh native observations are: + +* 3D: compile 1.112773s, execution 7.401238s, total 9.284819s, native invocation + 14.204229s; 1.919169x execution and 1.529834x total. +* Speckles: compile 0.677950s, execution 1.290954s, total 2.292555s, native + invocation 1.930783s; 1.495625x execution and 0.842197x total. + +These observations do not establish a causal gain or full30/scaling behavior. +Speckles still loses on total. The existing benchmark figure owner produces +fresh PNG/SVG runtime and speedup figures in the campaign's ``figures-v2`` +directory (corrected target labels in ``figures-v3``). Native invocation includes its pre-first-module work; startup, +imports/JVM setup and the excluded warmup observation are outside this clock. +Ordinary total includes compilation and normal OUTCOMES/RSS completion. +The ``v4`` namespace is explicitly aborted before measurement, after independent +review found stale binding selection within a multi-function chain. + +PR #394 remains draft. Its original whole-branch R0/R1 obligations, installed +consumer acceptance, full-catalog parity and fresh full30/scaling figures +remain open. Startup and required library/kernel preparation remain outside +pipeline clocks. The performance goal remains active. diff --git a/docs/refactor/receipts/runtime-paired-v11-20261004/README.rst b/docs/refactor/receipts/runtime-paired-v11-20261004/README.rst new file mode 100644 index 0000000000..98c3bb5068 --- /dev/null +++ b/docs/refactor/receipts/runtime-paired-v11-20261004/README.rst @@ -0,0 +1,87 @@ +Fresh ordinary and native runtime comparison +============================================ + +Measured source: ``771950f652e5237b71bf0b21b0b8050bda48e011``, integrated +through main ``32ededf24`` with eight current editable dependency sources and +matching repository pins. Subsequent alignment-owner consolidation and main +#577 integration are not included in these observations. + +All twelve strict comparisons pass: two ordinary observations against two +fresh native observations for each of three original pipelines. Complete +measurements, relationships and image inventories use the existing CellProfiler +tolerances. The 3D image comparison additionally requires exact pixels for both +original 60 x 256 x 256 uint16 volumes. Original source reference counts remain +180 for 3D, two for Speckles and ten for Beginner. + +Means of two observations +------------------------- + +.. list-table:: Single well, single worker; seconds and ratios of means + :header-rows: 1 + + * - Pipeline + - Compile + - Execution + - Total + - Native invocation + - Execution speedup + - Total speedup + * - 3D monolayer + - 1.032 + - 5.674 + - 7.423 + - 14.505 + - 2.556x + - 1.954x + * - Speckles + - 0.478 + - 1.042 + - 1.852 + - 1.939 + - 1.861x + - 1.047x + * - Beginner + - 0.607 + - 4.053 + - 5.123 + - 15.028 + - 3.708x + - 2.934x + +Clock and interpretation +------------------------ + +Server startup, function-library/kernel readiness and shutdown are outside +OpenHCS pipeline clocks. Execution includes the generic runtime, rather than +only callable time. Total includes compilation and ordinary OUTCOMES/RSS +completion. Native uses the same full invocation clock as the previous v7 +comparison, excluding imports, JVM startup, input loading and the warmup +observation. Its separate first-module-through-post-run clock is retained in +the JSON but is not used for the ratios. + +Both observations are retained and visible in ``matched_runtime_samples``. +These are descriptive observations, not confidence intervals or attribution +to any individual refactor. The 3D execution samples range from 5.016 to +6.333 seconds. Speckles execution ranges from 0.907 to 1.177 seconds. +The total-time target remains unmet for 3D and Speckles; Speckles is only +1.047x faster than native on total. Full-catalog and multi-well scaling +qualification remain outstanding. + +The saved-output/consolidation cleanup is included in the measured source, +but this benchmark disables consolidation. No benchmark gain is attributed +to that fix. Later diagnostic profiling is separate and does not replace +these uninstrumented ordinary observations. + +Retained artifacts +------------------ + +The adjacent PNG/SVG figures, ``metrics.csv``, ``timing_summary.json`` and +``qualification.json`` contain all measured samples, clock definitions, +dependency identities and twelve scientific comparison results. The complete +unchanged campaign is retained at:: + + /home/ts/.local/state/openhcs-maintenance/20261004/canonical-runtime-chains-paired-v11-qualified + +Scientific result SHA-256:: + + 608a83ff5903f51652ff3d0d61793cad4efaf27b9085dda958174d1139e60a52 diff --git a/docs/refactor/receipts/runtime-paired-v11-20261004/matched_runtime.png b/docs/refactor/receipts/runtime-paired-v11-20261004/matched_runtime.png new file mode 100644 index 0000000000..a51d516b94 Binary files /dev/null and b/docs/refactor/receipts/runtime-paired-v11-20261004/matched_runtime.png differ diff --git a/docs/refactor/receipts/runtime-paired-v11-20261004/matched_runtime.svg b/docs/refactor/receipts/runtime-paired-v11-20261004/matched_runtime.svg new file mode 100644 index 0000000000..7030178d5a --- /dev/null +++ b/docs/refactor/receipts/runtime-paired-v11-20261004/matched_runtime.svg @@ -0,0 +1,1815 @@ + + + + + + + + 2026-10-03T22:24:51.485939 + image/svg+xml + + + Matplotlib v3.11.2, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/refactor/receipts/runtime-paired-v11-20261004/matched_runtime_samples.png b/docs/refactor/receipts/runtime-paired-v11-20261004/matched_runtime_samples.png new file mode 100644 index 0000000000..89a09ce75a Binary files /dev/null and b/docs/refactor/receipts/runtime-paired-v11-20261004/matched_runtime_samples.png differ diff --git a/docs/refactor/receipts/runtime-paired-v11-20261004/matched_runtime_samples.svg b/docs/refactor/receipts/runtime-paired-v11-20261004/matched_runtime_samples.svg new file mode 100644 index 0000000000..50e8bea0c7 --- /dev/null +++ b/docs/refactor/receipts/runtime-paired-v11-20261004/matched_runtime_samples.svg @@ -0,0 +1,2090 @@ + + + + + + + + 2026-10-03T22:24:52.297611 + image/svg+xml + + + Matplotlib v3.11.2, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/refactor/receipts/runtime-paired-v11-20261004/matched_speedup.png b/docs/refactor/receipts/runtime-paired-v11-20261004/matched_speedup.png new file mode 100644 index 0000000000..9f02adae2b Binary files /dev/null and b/docs/refactor/receipts/runtime-paired-v11-20261004/matched_speedup.png differ diff --git a/docs/refactor/receipts/runtime-paired-v11-20261004/matched_speedup.svg b/docs/refactor/receipts/runtime-paired-v11-20261004/matched_speedup.svg new file mode 100644 index 0000000000..78007d61ba --- /dev/null +++ b/docs/refactor/receipts/runtime-paired-v11-20261004/matched_speedup.svg @@ -0,0 +1,1756 @@ + + + + + + + + 2026-10-03T22:24:51.855028 + image/svg+xml + + + Matplotlib v3.11.2, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/refactor/receipts/runtime-paired-v11-20261004/metrics.csv b/docs/refactor/receipts/runtime-paired-v11-20261004/metrics.csv new file mode 100644 index 0000000000..882f4da3a4 --- /dev/null +++ b/docs/refactor/receipts/runtime-paired-v11-20261004/metrics.csv @@ -0,0 +1,28 @@ +pipeline_name,method,assay_category,module_category,accuracy_fraction,raw_seconds,speedup,peak_memory_mb +cp_tutorial_3d_monolayer,CellProfiler,,,1.0,14.504645670065656,1.0, +cp_tutorial_3d_monolayer,OH execution,,,1.0,5.674471020698547,2.5561229614456793, +cp_tutorial_3d_monolayer,OH total,,,1.0,7.423485984560102,1.9538860449435018, +ExampleSpeckles,CellProfiler,,,1.0,1.9391879816539586,1.0, +ExampleSpeckles,OH execution,,,1.0,1.04183030128479,1.8613280677885282, +ExampleSpeckles,OH total,,,1.0,1.851556861307472,1.0473283441506658, +cp_tutorial_beginner_segmentation_final,CellProfiler,,,1.0,15.028485956136137,1.0, +cp_tutorial_beginner_segmentation_final,OH execution,,,1.0,4.052742838859558,3.7082258987755448, +cp_tutorial_beginner_segmentation_final,OH total,,,1.0,5.122567740967497,2.933779837784578, +cp_tutorial_3d_monolayer,CellProfiler run 1,,,1.0,14.757951722946018,, +cp_tutorial_3d_monolayer,CellProfiler run 2,,,1.0,14.251339617185295,, +cp_tutorial_3d_monolayer,OH execution run 1,,,1.0,5.0158140659332275,, +cp_tutorial_3d_monolayer,OH execution run 2,,,1.0,6.333127975463867,, +cp_tutorial_3d_monolayer,OH total run 1,,,1.0,6.781453618314117,, +cp_tutorial_3d_monolayer,OH total run 2,,,1.0,8.065518350806087,, +ExampleSpeckles,CellProfiler run 1,,,1.0,2.0039482093416154,, +ExampleSpeckles,CellProfiler run 2,,,1.0,1.8744277539663017,, +ExampleSpeckles,OH execution run 1,,,1.0,0.9069628715515137,, +ExampleSpeckles,OH execution run 2,,,1.0,1.1766977310180664,, +ExampleSpeckles,OH total run 1,,,1.0,1.6977782007306814,, +ExampleSpeckles,OH total run 2,,,1.0,2.0053355218842626,, +cp_tutorial_beginner_segmentation_final,CellProfiler run 1,,,1.0,15.272316726390272,, +cp_tutorial_beginner_segmentation_final,CellProfiler run 2,,,1.0,14.784655185882002,, +cp_tutorial_beginner_segmentation_final,OH execution run 1,,,1.0,3.902729034423828,, +cp_tutorial_beginner_segmentation_final,OH execution run 2,,,1.0,4.202756643295288,, +cp_tutorial_beginner_segmentation_final,OH total run 1,,,1.0,4.9476758115924895,, +cp_tutorial_beginner_segmentation_final,OH total run 2,,,1.0,5.297459670342505,, diff --git a/docs/refactor/receipts/runtime-paired-v11-20261004/qualification.json b/docs/refactor/receipts/runtime-paired-v11-20261004/qualification.json new file mode 100644 index 0000000000..f35a854e8a --- /dev/null +++ b/docs/refactor/receipts/runtime-paired-v11-20261004/qualification.json @@ -0,0 +1,326 @@ +{ + "status": "PASS", + "source_head": "771950f652e5237b71bf0b21b0b8050bda48e011", + "origin_main": "32ededf2421ac79df147628c1732785c139d0970", + "science_path": "/home/ts/.local/state/openhcs-maintenance/20261004/canonical-runtime-chains-paired-v11-qualified/strict-science.json", + "science_sha256": "608a83ff5903f51652ff3d0d61793cad4efaf27b9085dda958174d1139e60a52", + "source_freeze_path": "/home/ts/.local/state/openhcs-maintenance/20261004/canonical-runtime-chains-paired-v11-qualified/source-freeze.json", + "source_freeze_sha256": "feefec8c0fadd3da87b29c1c61495e939802f5729b274192f99a1e673b044be9", + "source_environment_sha256": "b579dda9991d0de75047d9dd84591f556085ef401bafa1f1f8bc9c86ca588ecc", + "dependency_heads": { + "external/ObjectState": "9fb5b7eeea96f3b7bb0579de30718bbcc0018823", + "external/python-introspect": "ed1e4eb15f7a0bf8315274d3e47858fa2b4372bb", + "external/arraybridge": "1e53d03d9f468322a1c085c8be29485fb139caf2", + "external/metaclass-registry": "393a7e03003cdc56df9013f932ed4f26e632d77a", + "external/zmqruntime": "f7b80c871eb4773757368bb21f108920bf461881", + "external/pycodify": "108a8edbf25de258168756bac22c7572f018fa90", + "external/PolyStore": "89deeef3662eabb11bc520fad9acd976698636bd", + "external/pyqt-reactive": "b64ed2eca96fcdad29ba90beb545caa669a4d3d8" + }, + "actual_import_dependency_heads": { + "external/ObjectState": "9fb5b7eeea96f3b7bb0579de30718bbcc0018823", + "external/PolyStore": "89deeef3662eabb11bc520fad9acd976698636bd", + "external/arraybridge": "1e53d03d9f468322a1c085c8be29485fb139caf2", + "external/metaclass-registry": "393a7e03003cdc56df9013f932ed4f26e632d77a", + "external/pycodify": "108a8edbf25de258168756bac22c7572f018fa90", + "external/pyqt-reactive": "b64ed2eca96fcdad29ba90beb545caa669a4d3d8", + "external/python-introspect": "ed1e4eb15f7a0bf8315274d3e47858fa2b4372bb", + "external/zmqruntime": "f7b80c871eb4773757368bb21f108920bf461881" + }, + "ordered_source_ref_counts": { + "cp_tutorial_3d_monolayer": 180, + "ExampleSpeckles": 2, + "cp_tutorial_beginner_segmentation_final": 10 + }, + "comparisons": [ + { + "case": "cp_tutorial_3d_monolayer", + "ordinary_repeat": 0, + "native_repeat": 0, + "measurement_differences": 0, + "image_differences": 0, + "tables": [ + 7, + 6 + ], + "physical_images": [ + 2, + 2 + ], + "logical_images": [ + 2, + 2 + ], + "known_relationship_keys": [ + 3, + 3 + ], + "ordinary_receipt_sha256": "465cf0eac54e4ff82845ec3f98f3402d5b7ab802badfb2bc2434753a59b999ad" + }, + { + "case": "cp_tutorial_3d_monolayer", + "ordinary_repeat": 0, + "native_repeat": 1, + "measurement_differences": 0, + "image_differences": 0, + "tables": [ + 7, + 6 + ], + "physical_images": [ + 2, + 2 + ], + "logical_images": [ + 2, + 2 + ], + "known_relationship_keys": [ + 3, + 3 + ], + "ordinary_receipt_sha256": "465cf0eac54e4ff82845ec3f98f3402d5b7ab802badfb2bc2434753a59b999ad" + }, + { + "case": "ExampleSpeckles", + "ordinary_repeat": 0, + "native_repeat": 0, + "measurement_differences": 0, + "image_differences": 0, + "tables": [ + 3, + 3 + ], + "physical_images": [ + 0, + 0 + ], + "logical_images": [ + 0, + 0 + ], + "known_relationship_keys": [ + 1, + 1 + ], + "ordinary_receipt_sha256": "3831b86c470132b166b1034305d771dba222c1dd8fb42f54093e3b5eaf6d0cf5" + }, + { + "case": "ExampleSpeckles", + "ordinary_repeat": 0, + "native_repeat": 1, + "measurement_differences": 0, + "image_differences": 0, + "tables": [ + 3, + 3 + ], + "physical_images": [ + 0, + 0 + ], + "logical_images": [ + 0, + 0 + ], + "known_relationship_keys": [ + 1, + 1 + ], + "ordinary_receipt_sha256": "3831b86c470132b166b1034305d771dba222c1dd8fb42f54093e3b5eaf6d0cf5" + }, + { + "case": "cp_tutorial_beginner_segmentation_final", + "ordinary_repeat": 0, + "native_repeat": 0, + "measurement_differences": 0, + "image_differences": 0, + "tables": [ + 7, + 7 + ], + "physical_images": [ + 2, + 2 + ], + "logical_images": [ + 2, + 2 + ], + "known_relationship_keys": [ + 5, + 5 + ], + "ordinary_receipt_sha256": "559ecdbb4e6a856c0a911d67e60171458a77e01f8d63f3b49326cc04fd6b2d38" + }, + { + "case": "cp_tutorial_beginner_segmentation_final", + "ordinary_repeat": 0, + "native_repeat": 1, + "measurement_differences": 0, + "image_differences": 0, + "tables": [ + 7, + 7 + ], + "physical_images": [ + 2, + 2 + ], + "logical_images": [ + 2, + 2 + ], + "known_relationship_keys": [ + 5, + 5 + ], + "ordinary_receipt_sha256": "559ecdbb4e6a856c0a911d67e60171458a77e01f8d63f3b49326cc04fd6b2d38" + }, + { + "case": "cp_tutorial_3d_monolayer", + "ordinary_repeat": 1, + "native_repeat": 0, + "measurement_differences": 0, + "image_differences": 0, + "tables": [ + 7, + 6 + ], + "physical_images": [ + 2, + 2 + ], + "logical_images": [ + 2, + 2 + ], + "known_relationship_keys": [ + 3, + 3 + ], + "ordinary_receipt_sha256": "9cecd2752cde33d1860a928dc04ccbcf06275e5319a7c586646d3b1e13222742" + }, + { + "case": "cp_tutorial_3d_monolayer", + "ordinary_repeat": 1, + "native_repeat": 1, + "measurement_differences": 0, + "image_differences": 0, + "tables": [ + 7, + 6 + ], + "physical_images": [ + 2, + 2 + ], + "logical_images": [ + 2, + 2 + ], + "known_relationship_keys": [ + 3, + 3 + ], + "ordinary_receipt_sha256": "9cecd2752cde33d1860a928dc04ccbcf06275e5319a7c586646d3b1e13222742" + }, + { + "case": "ExampleSpeckles", + "ordinary_repeat": 1, + "native_repeat": 0, + "measurement_differences": 0, + "image_differences": 0, + "tables": [ + 3, + 3 + ], + "physical_images": [ + 0, + 0 + ], + "logical_images": [ + 0, + 0 + ], + "known_relationship_keys": [ + 1, + 1 + ], + "ordinary_receipt_sha256": "5d6d7f02523bba49204b9f6f4626b4b33425690c1ba796423ab47aade5d119c5" + }, + { + "case": "ExampleSpeckles", + "ordinary_repeat": 1, + "native_repeat": 1, + "measurement_differences": 0, + "image_differences": 0, + "tables": [ + 3, + 3 + ], + "physical_images": [ + 0, + 0 + ], + "logical_images": [ + 0, + 0 + ], + "known_relationship_keys": [ + 1, + 1 + ], + "ordinary_receipt_sha256": "5d6d7f02523bba49204b9f6f4626b4b33425690c1ba796423ab47aade5d119c5" + }, + { + "case": "cp_tutorial_beginner_segmentation_final", + "ordinary_repeat": 1, + "native_repeat": 0, + "measurement_differences": 0, + "image_differences": 0, + "tables": [ + 7, + 7 + ], + "physical_images": [ + 2, + 2 + ], + "logical_images": [ + 2, + 2 + ], + "known_relationship_keys": [ + 5, + 5 + ], + "ordinary_receipt_sha256": "1595af0e768d7c7b287a6ac21b689f8c6f866b2d5540c751a91e226bad97eb95" + }, + { + "case": "cp_tutorial_beginner_segmentation_final", + "ordinary_repeat": 1, + "native_repeat": 1, + "measurement_differences": 0, + "image_differences": 0, + "tables": [ + 7, + 7 + ], + "physical_images": [ + 2, + 2 + ], + "logical_images": [ + 2, + 2 + ], + "known_relationship_keys": [ + 5, + 5 + ], + "ordinary_receipt_sha256": "1595af0e768d7c7b287a6ac21b689f8c6f866b2d5540c751a91e226bad97eb95" + } + ], + "scope": "Both ordinary observations versus both native measured observations; full strict files/values/correlation policy; descriptive two-repeat clocks, not full30 acceptance." +} diff --git a/docs/refactor/receipts/runtime-paired-v11-20261004/timing_summary.json b/docs/refactor/receipts/runtime-paired-v11-20261004/timing_summary.json new file mode 100644 index 0000000000..d7218959f9 --- /dev/null +++ b/docs/refactor/receipts/runtime-paired-v11-20261004/timing_summary.json @@ -0,0 +1,507 @@ +{ + "source_head": "771950f652e5237b71bf0b21b0b8050bda48e011", + "cases": { + "cp_tutorial_3d_monolayer": { + "native_invocation_seconds": [ + 14.757951722946018, + 14.251339617185295 + ], + "native_mean_seconds": 14.504645670065656, + "native_first_module_through_post_run_seconds": [ + 14.628245717845857, + 14.132655873894691 + ], + "native_first_module_through_post_run_mean_seconds": 14.380450795870274, + "ordinary_samples": { + "compile_seconds": [ + 1.027512788772583, + 1.0361676216125488 + ], + "execute_seconds": [ + 5.0158140659332275, + 6.333127975463867 + ], + "total_seconds": [ + 6.781453618314117, + 8.065518350806087 + ] + }, + "ordinary_means": { + "compile_seconds": 1.031840205192566, + "execute_seconds": 5.674471020698547, + "total_seconds": 7.423485984560102 + }, + "observed_ranges_seconds": { + "native_invocation_seconds": { + "minimum": 14.251339617185295, + "maximum": 14.757951722946018 + }, + "compile_seconds": { + "minimum": 1.027512788772583, + "maximum": 1.0361676216125488 + }, + "execute_seconds": { + "minimum": 5.0158140659332275, + "maximum": 6.333127975463867 + }, + "total_seconds": { + "minimum": 6.781453618314117, + "maximum": 8.065518350806087 + } + }, + "other_total_seconds_mean": 0.7171747586689889, + "execution_speedup_ratio_of_means": 2.5561229614456793, + "total_speedup_ratio_of_means": 1.9538860449435018 + }, + "ExampleSpeckles": { + "native_invocation_seconds": [ + 2.0039482093416154, + 1.8744277539663017 + ], + "native_mean_seconds": 1.9391879816539586, + "native_first_module_through_post_run_seconds": [ + 1.9125203830190003, + 1.793057702947408 + ], + "native_first_module_through_post_run_mean_seconds": 1.8527890429832041, + "ordinary_samples": { + "compile_seconds": [ + 0.4752085208892822, + 0.48175573348999023 + ], + "execute_seconds": [ + 0.9069628715515137, + 1.1766977310180664 + ], + "total_seconds": [ + 1.6977782007306814, + 2.0053355218842626 + ] + }, + "ordinary_means": { + "compile_seconds": 0.47848212718963623, + "execute_seconds": 1.04183030128479, + "total_seconds": 1.851556861307472 + }, + "observed_ranges_seconds": { + "native_invocation_seconds": { + "minimum": 1.8744277539663017, + "maximum": 2.0039482093416154 + }, + "compile_seconds": { + "minimum": 0.4752085208892822, + "maximum": 0.48175573348999023 + }, + "execute_seconds": { + "minimum": 0.9069628715515137, + "maximum": 1.1766977310180664 + }, + "total_seconds": { + "minimum": 1.6977782007306814, + "maximum": 2.0053355218842626 + } + }, + "other_total_seconds_mean": 0.3312444328330457, + "execution_speedup_ratio_of_means": 1.8613280677885282, + "total_speedup_ratio_of_means": 1.0473283441506658 + }, + "cp_tutorial_beginner_segmentation_final": { + "native_invocation_seconds": [ + 15.272316726390272, + 14.784655185882002 + ], + "native_mean_seconds": 15.028485956136137, + "native_first_module_through_post_run_seconds": [ + 15.028584334999323, + 14.578100933227688 + ], + "native_first_module_through_post_run_mean_seconds": 14.803342634113505, + "ordinary_samples": { + "compile_seconds": [ + 0.6007773876190186, + 0.6125655174255371 + ], + "execute_seconds": [ + 3.902729034423828, + 4.202756643295288 + ], + "total_seconds": [ + 4.9476758115924895, + 5.297459670342505 + ] + }, + "ordinary_means": { + "compile_seconds": 0.6066714525222778, + "execute_seconds": 4.052742838859558, + "total_seconds": 5.122567740967497 + }, + "observed_ranges_seconds": { + "native_invocation_seconds": { + "minimum": 14.784655185882002, + "maximum": 15.272316726390272 + }, + "compile_seconds": { + "minimum": 0.6007773876190186, + "maximum": 0.6125655174255371 + }, + "execute_seconds": { + "minimum": 3.902729034423828, + "maximum": 4.202756643295288 + }, + "total_seconds": { + "minimum": 4.9476758115924895, + "maximum": 5.297459670342505 + } + }, + "other_total_seconds_mean": 0.4631534495856613, + "execution_speedup_ratio_of_means": 3.7082258987755448, + "total_speedup_ratio_of_means": 2.933779837784578 + } + }, + "clock_definitions": { + "native_invocation_seconds": "Full existing native invocation clock: pre-first-module work plus first-module-through-post-run. Process imports, JVM startup, input loading and full warmup excluded. This is the same clock used by V7 ratios.", + "native_first_module_through_post_run_seconds": "Separate diagnostic clock, excluding native pre-first-module work. Not used for the plotted speedup ratios.", + "openhcs_execute_seconds": "Ordinary pipeline execution including generic runtime plumbing; not pure callable or kernel time.", + "openhcs_total_seconds": "Ordinary compilation plus execution and default OUTCOMES/RSS completion. ZMQ server READY startup/shutdown excluded." + }, + "scope": "Three current pipelines, one selected well and one worker; two observations per method. Means and observed min/max are descriptive, not confidence intervals or per-cut causal gains. No full30 or scaling claim. All measured samples shown separately; no synthetic pairing of native and OpenHCS repetitions.", + "qualification": { + "status": "PASS", + "source_head": "771950f652e5237b71bf0b21b0b8050bda48e011", + "origin_main": "32ededf2421ac79df147628c1732785c139d0970", + "science_path": "/home/ts/.local/state/openhcs-maintenance/20261004/canonical-runtime-chains-paired-v11-qualified/strict-science.json", + "science_sha256": "608a83ff5903f51652ff3d0d61793cad4efaf27b9085dda958174d1139e60a52", + "source_freeze_path": "/home/ts/.local/state/openhcs-maintenance/20261004/canonical-runtime-chains-paired-v11-qualified/source-freeze.json", + "source_freeze_sha256": "feefec8c0fadd3da87b29c1c61495e939802f5729b274192f99a1e673b044be9", + "source_environment_sha256": "b579dda9991d0de75047d9dd84591f556085ef401bafa1f1f8bc9c86ca588ecc", + "dependency_heads": { + "external/ObjectState": "9fb5b7eeea96f3b7bb0579de30718bbcc0018823", + "external/python-introspect": "ed1e4eb15f7a0bf8315274d3e47858fa2b4372bb", + "external/arraybridge": "1e53d03d9f468322a1c085c8be29485fb139caf2", + "external/metaclass-registry": "393a7e03003cdc56df9013f932ed4f26e632d77a", + "external/zmqruntime": "f7b80c871eb4773757368bb21f108920bf461881", + "external/pycodify": "108a8edbf25de258168756bac22c7572f018fa90", + "external/PolyStore": "89deeef3662eabb11bc520fad9acd976698636bd", + "external/pyqt-reactive": "b64ed2eca96fcdad29ba90beb545caa669a4d3d8" + }, + "actual_import_dependency_heads": { + "external/ObjectState": "9fb5b7eeea96f3b7bb0579de30718bbcc0018823", + "external/PolyStore": "89deeef3662eabb11bc520fad9acd976698636bd", + "external/arraybridge": "1e53d03d9f468322a1c085c8be29485fb139caf2", + "external/metaclass-registry": "393a7e03003cdc56df9013f932ed4f26e632d77a", + "external/pycodify": "108a8edbf25de258168756bac22c7572f018fa90", + "external/pyqt-reactive": "b64ed2eca96fcdad29ba90beb545caa669a4d3d8", + "external/python-introspect": "ed1e4eb15f7a0bf8315274d3e47858fa2b4372bb", + "external/zmqruntime": "f7b80c871eb4773757368bb21f108920bf461881" + }, + "ordered_source_ref_counts": { + "cp_tutorial_3d_monolayer": 180, + "ExampleSpeckles": 2, + "cp_tutorial_beginner_segmentation_final": 10 + }, + "comparisons": [ + { + "case": "cp_tutorial_3d_monolayer", + "ordinary_repeat": 0, + "native_repeat": 0, + "measurement_differences": 0, + "image_differences": 0, + "tables": [ + 7, + 6 + ], + "physical_images": [ + 2, + 2 + ], + "logical_images": [ + 2, + 2 + ], + "known_relationship_keys": [ + 3, + 3 + ], + "ordinary_receipt_sha256": "465cf0eac54e4ff82845ec3f98f3402d5b7ab802badfb2bc2434753a59b999ad" + }, + { + "case": "cp_tutorial_3d_monolayer", + "ordinary_repeat": 0, + "native_repeat": 1, + "measurement_differences": 0, + "image_differences": 0, + "tables": [ + 7, + 6 + ], + "physical_images": [ + 2, + 2 + ], + "logical_images": [ + 2, + 2 + ], + "known_relationship_keys": [ + 3, + 3 + ], + "ordinary_receipt_sha256": "465cf0eac54e4ff82845ec3f98f3402d5b7ab802badfb2bc2434753a59b999ad" + }, + { + "case": "ExampleSpeckles", + "ordinary_repeat": 0, + "native_repeat": 0, + "measurement_differences": 0, + "image_differences": 0, + "tables": [ + 3, + 3 + ], + "physical_images": [ + 0, + 0 + ], + "logical_images": [ + 0, + 0 + ], + "known_relationship_keys": [ + 1, + 1 + ], + "ordinary_receipt_sha256": "3831b86c470132b166b1034305d771dba222c1dd8fb42f54093e3b5eaf6d0cf5" + }, + { + "case": "ExampleSpeckles", + "ordinary_repeat": 0, + "native_repeat": 1, + "measurement_differences": 0, + "image_differences": 0, + "tables": [ + 3, + 3 + ], + "physical_images": [ + 0, + 0 + ], + "logical_images": [ + 0, + 0 + ], + "known_relationship_keys": [ + 1, + 1 + ], + "ordinary_receipt_sha256": "3831b86c470132b166b1034305d771dba222c1dd8fb42f54093e3b5eaf6d0cf5" + }, + { + "case": "cp_tutorial_beginner_segmentation_final", + "ordinary_repeat": 0, + "native_repeat": 0, + "measurement_differences": 0, + "image_differences": 0, + "tables": [ + 7, + 7 + ], + "physical_images": [ + 2, + 2 + ], + "logical_images": [ + 2, + 2 + ], + "known_relationship_keys": [ + 5, + 5 + ], + "ordinary_receipt_sha256": "559ecdbb4e6a856c0a911d67e60171458a77e01f8d63f3b49326cc04fd6b2d38" + }, + { + "case": "cp_tutorial_beginner_segmentation_final", + "ordinary_repeat": 0, + "native_repeat": 1, + "measurement_differences": 0, + "image_differences": 0, + "tables": [ + 7, + 7 + ], + "physical_images": [ + 2, + 2 + ], + "logical_images": [ + 2, + 2 + ], + "known_relationship_keys": [ + 5, + 5 + ], + "ordinary_receipt_sha256": "559ecdbb4e6a856c0a911d67e60171458a77e01f8d63f3b49326cc04fd6b2d38" + }, + { + "case": "cp_tutorial_3d_monolayer", + "ordinary_repeat": 1, + "native_repeat": 0, + "measurement_differences": 0, + "image_differences": 0, + "tables": [ + 7, + 6 + ], + "physical_images": [ + 2, + 2 + ], + "logical_images": [ + 2, + 2 + ], + "known_relationship_keys": [ + 3, + 3 + ], + "ordinary_receipt_sha256": "9cecd2752cde33d1860a928dc04ccbcf06275e5319a7c586646d3b1e13222742" + }, + { + "case": "cp_tutorial_3d_monolayer", + "ordinary_repeat": 1, + "native_repeat": 1, + "measurement_differences": 0, + "image_differences": 0, + "tables": [ + 7, + 6 + ], + "physical_images": [ + 2, + 2 + ], + "logical_images": [ + 2, + 2 + ], + "known_relationship_keys": [ + 3, + 3 + ], + "ordinary_receipt_sha256": "9cecd2752cde33d1860a928dc04ccbcf06275e5319a7c586646d3b1e13222742" + }, + { + "case": "ExampleSpeckles", + "ordinary_repeat": 1, + "native_repeat": 0, + "measurement_differences": 0, + "image_differences": 0, + "tables": [ + 3, + 3 + ], + "physical_images": [ + 0, + 0 + ], + "logical_images": [ + 0, + 0 + ], + "known_relationship_keys": [ + 1, + 1 + ], + "ordinary_receipt_sha256": "5d6d7f02523bba49204b9f6f4626b4b33425690c1ba796423ab47aade5d119c5" + }, + { + "case": "ExampleSpeckles", + "ordinary_repeat": 1, + "native_repeat": 1, + "measurement_differences": 0, + "image_differences": 0, + "tables": [ + 3, + 3 + ], + "physical_images": [ + 0, + 0 + ], + "logical_images": [ + 0, + 0 + ], + "known_relationship_keys": [ + 1, + 1 + ], + "ordinary_receipt_sha256": "5d6d7f02523bba49204b9f6f4626b4b33425690c1ba796423ab47aade5d119c5" + }, + { + "case": "cp_tutorial_beginner_segmentation_final", + "ordinary_repeat": 1, + "native_repeat": 0, + "measurement_differences": 0, + "image_differences": 0, + "tables": [ + 7, + 7 + ], + "physical_images": [ + 2, + 2 + ], + "logical_images": [ + 2, + 2 + ], + "known_relationship_keys": [ + 5, + 5 + ], + "ordinary_receipt_sha256": "1595af0e768d7c7b287a6ac21b689f8c6f866b2d5540c751a91e226bad97eb95" + }, + { + "case": "cp_tutorial_beginner_segmentation_final", + "ordinary_repeat": 1, + "native_repeat": 1, + "measurement_differences": 0, + "image_differences": 0, + "tables": [ + 7, + 7 + ], + "physical_images": [ + 2, + 2 + ], + "logical_images": [ + 2, + 2 + ], + "known_relationship_keys": [ + 5, + 5 + ], + "ordinary_receipt_sha256": "1595af0e768d7c7b287a6ac21b689f8c6f866b2d5540c751a91e226bad97eb95" + } + ], + "scope": "Both ordinary observations versus both native measured observations; full strict files/values/correlation policy; descriptive two-repeat clocks, not full30 acceptance." + }, + "plot_script_sha256": "d6b40f6cb13c5e65b8974371a15b1a22f2a1a3b8eca7e73111332ce82e4980a4", + "figure_owner_sha256": "bb1bf777c5c5d95507b0f751310652e29ab8b3919387334871a890bfe667f3c1", + "v7_plot_script_sha256": "28f92861b2f69908e44e30ee6dd009ac839d8eb76f32326d18a6a12b87a9dd29", + "artifacts": { + "/home/ts/.local/state/openhcs-maintenance/20261004/canonical-runtime-chains-paired-v11-qualified/figures/metrics.csv": "c8959ed19a6812631a8ca672b608c9ea59803904f64cd9a22cb900c0bbfc030b", + "/home/ts/.local/state/openhcs-maintenance/20261004/canonical-runtime-chains-paired-v11-qualified/figures/qualification.json": "bf1ad5acbb60be7582d4ef8eaacfff2327f2eaa356866512ca2fa781f034f127", + "/home/ts/.local/state/openhcs-maintenance/20261004/canonical-runtime-chains-paired-v11-qualified/figures/matched_runtime.png": "0336e6bf17b761fca37440ad6b31e5813fd322ad10987d073511898fa7812224", + "/home/ts/.local/state/openhcs-maintenance/20261004/canonical-runtime-chains-paired-v11-qualified/figures/matched_runtime.svg": "5421554a3b9ddc6a4d661b2e8c98e79a29673865d0079e7de439e6dfd6781368", + "/home/ts/.local/state/openhcs-maintenance/20261004/canonical-runtime-chains-paired-v11-qualified/figures/matched_speedup.png": "6058479d8334a1ea073448fd93082b00ecc2cb2269fa711ef6ae7ea2dcf987b1", + "/home/ts/.local/state/openhcs-maintenance/20261004/canonical-runtime-chains-paired-v11-qualified/figures/matched_speedup.svg": "8fd3e4d1a08db96b277e83d6969805402ea2b73cbea7f95bb627514b5988c8dd", + "/home/ts/.local/state/openhcs-maintenance/20261004/canonical-runtime-chains-paired-v11-qualified/figures/matched_runtime_samples.png": "7b1dff465d7a416a64dff6d2d6106a3444b2edca441d4f77bb64489132ee412b", + "/home/ts/.local/state/openhcs-maintenance/20261004/canonical-runtime-chains-paired-v11-qualified/figures/matched_runtime_samples.svg": "972c877946f42ac06b875f5e9932c5a10784a411d8ba41e157c1fb3f74881c2e" + } +} diff --git a/docs/refactor/receipts/runtime-paired-v12-20261004/README.rst b/docs/refactor/receipts/runtime-paired-v12-20261004/README.rst new file mode 100644 index 0000000000..81a62da6a4 --- /dev/null +++ b/docs/refactor/receipts/runtime-paired-v12-20261004/README.rst @@ -0,0 +1,134 @@ +Fresh paired runtime and output qualification +============================================= + +Measured source: ``cc4461bc8a58c90c2ae13a5dd3870a67e1d8fc0a``, synchronized +with main ``2df0918353b47fa07d19fe4b6cc8b52b5e4c1695``. All eight actual editable +dependency heads match the snapshot's repository pins. This snapshot includes +compiled-client submission/terminal-record reuse, the measurement query and +row-cache deletions, correlated feature batching, and exact saved-physical +source fallback. Subsequent compiler and public source cleanup is not measured. + +All twelve strict comparisons pass: both ordinary observations against both +fresh native observations for each of the three original pipelines. Complete +measurement values, directed relationship correlations, pixels and physical +file inventories are compared using the existing CellProfiler policy. The 3D +pixel comparison requires exact equality. Original ordered source references +remain 180 for 3D, two for Speckles and ten for Beginner; native image-set counts +remain one, one and two, respectively. + +Means of two observations +------------------------- + +.. list-table:: One selected well, one worker, one thread; seconds and ratios of means + :header-rows: 1 + + * - Pipeline + - Compile + - Execution + - Total + - Native invocation + - Execution speedup + - Total speedup + * - 3D monolayer + - 1.049 + - 5.757 + - 7.057 + - 16.144 + - 2.804x + - 2.288x + * - Speckles + - 0.482 + - 0.982 + - 1.674 + - 1.922 + - 1.957x + - 1.149x + * - Beginner + - 0.615 + - 3.792 + - 4.633 + - 15.014 + - 3.959x + - 3.241x + +Every measured sample +--------------------- + +.. list-table:: Two independent observations per method; seconds + :header-rows: 1 + + * - Pipeline + - Compile samples + - Execution samples + - Total samples + - Native invocation samples + * - 3D monolayer + - 1.028707 / 1.068334 + - 5.278847 / 6.235180 + - 6.573325 / 7.540294 + - 14.833275 / 17.454537 + * - Speckles + - 0.481356 / 0.482515 + - 1.005144 / 0.959042 + - 1.696810 / 1.650728 + - 1.960386 / 1.884385 + * - Beginner + - 0.605824 / 0.623433 + - 3.631471 / 3.952364 + - 4.468181 / 4.797630 + - 15.154002 / 14.873502 + +Clock and interpretation +------------------------ + +OpenHCS server startup, mandatory function-library/kernel readiness and shutdown +are outside pipeline clocks. Execution includes generic runtime plumbing. +Total includes compilation and default OUTCOMES/RSS completion. Native ratios +use the existing full invocation clock, including pre-first-module work and +first-module-through-post-run work; process/import/JVM startup, input preparation +and the full warmup observation are excluded. The separate native +first-module-through-post-run clock is retained but does not replace invocation +in either plotted ratio. + +Both samples are retained without outlier removal. Means and observed ranges +are descriptive; these are not confidence intervals or individual-patch causal +gains. The 3D execution spread is 0.956 seconds and its native invocation spread +is 2.621 seconds. Relative to v11, ordinary total means decrease by 0.367 seconds +for 3D, 0.178 for Speckles and 0.490 for Beginner. The 3D execution mean increases +by 0.083 seconds within that observed spread; its native mean increases from +14.505 to 16.144 seconds, contributing to the larger speedup ratio. + +Mean total-minus-compilation-minus-execution is 0.251 seconds for 3D, 0.210 for +Speckles and 0.226 for Beginner. These clock differences are not disjoint causal +attributions to individual client or observer operations. Speckles remains the +slowest relative workload: its mean execution speedup is below the 2x target, +and its total speedup is 1.149x. Full-catalog and multi-well scaling acceptance +remain open. Two reused READY servers each complete the three-case sweep; this +bounded memory observation does not close the historical full-catalog OOM issue. + +The earlier analysis-consolidation cleanup is present, but this benchmark +explicitly disables consolidation; no timing benefit is attributed to it. + +Artifacts and reproduction +-------------------------- + +Adjacent PNG/SVG figures, ``metrics.csv``, ``timing_summary.json`` and +``qualification.json`` retain means, all samples, clock definitions, actual +dependency identities and all twelve scientific comparison results. Rendering +uses the existing v11 driver and v7 repository figure owner; no scientific run +or new plotting framework is introduced. The exact renderer is retained at:: + + /home/ts/.local/state/openhcs-maintenance/20261004/plot_current_paired_timings_v12.py + +The original immutable campaign and existing controller are retained at:: + + /home/ts/.local/state/openhcs-maintenance/20261004/canonical-runtime-cache-client-paired-v12-qualified + /home/ts/.local/state/openhcs-maintenance/20261004/canonical-runtime-cache-client-paired-v12-preparation + +Scientific result SHA-256:: + + df61eca666cd741f238d96b6f7fd2c22b10c14dc577b64a381969a36a0bb5906 + +Source/environment/input freeze SHA-256:: + + 24b4277094722d66ffe6bcccdbb3f543d197463c6a3990c9e764c9390affccda diff --git a/docs/refactor/receipts/runtime-paired-v12-20261004/matched_runtime.png b/docs/refactor/receipts/runtime-paired-v12-20261004/matched_runtime.png new file mode 100644 index 0000000000..300bffa7b2 Binary files /dev/null and b/docs/refactor/receipts/runtime-paired-v12-20261004/matched_runtime.png differ diff --git a/docs/refactor/receipts/runtime-paired-v12-20261004/matched_runtime.svg b/docs/refactor/receipts/runtime-paired-v12-20261004/matched_runtime.svg new file mode 100644 index 0000000000..bd8f7364a4 --- /dev/null +++ b/docs/refactor/receipts/runtime-paired-v12-20261004/matched_runtime.svg @@ -0,0 +1,1815 @@ + + + + + + + + 2026-10-03T23:46:35.219556 + image/svg+xml + + + Matplotlib v3.11.2, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/refactor/receipts/runtime-paired-v12-20261004/matched_runtime_samples.png b/docs/refactor/receipts/runtime-paired-v12-20261004/matched_runtime_samples.png new file mode 100644 index 0000000000..409a11374a Binary files /dev/null and b/docs/refactor/receipts/runtime-paired-v12-20261004/matched_runtime_samples.png differ diff --git a/docs/refactor/receipts/runtime-paired-v12-20261004/matched_runtime_samples.svg b/docs/refactor/receipts/runtime-paired-v12-20261004/matched_runtime_samples.svg new file mode 100644 index 0000000000..5f90b5166e --- /dev/null +++ b/docs/refactor/receipts/runtime-paired-v12-20261004/matched_runtime_samples.svg @@ -0,0 +1,2111 @@ + + + + + + + + 2026-10-03T23:46:36.060050 + image/svg+xml + + + Matplotlib v3.11.2, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/refactor/receipts/runtime-paired-v12-20261004/matched_speedup.png b/docs/refactor/receipts/runtime-paired-v12-20261004/matched_speedup.png new file mode 100644 index 0000000000..89d4217398 Binary files /dev/null and b/docs/refactor/receipts/runtime-paired-v12-20261004/matched_speedup.png differ diff --git a/docs/refactor/receipts/runtime-paired-v12-20261004/matched_speedup.svg b/docs/refactor/receipts/runtime-paired-v12-20261004/matched_speedup.svg new file mode 100644 index 0000000000..2fc556e221 --- /dev/null +++ b/docs/refactor/receipts/runtime-paired-v12-20261004/matched_speedup.svg @@ -0,0 +1,1756 @@ + + + + + + + + 2026-10-03T23:46:35.597898 + image/svg+xml + + + Matplotlib v3.11.2, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/refactor/receipts/runtime-paired-v12-20261004/metrics.csv b/docs/refactor/receipts/runtime-paired-v12-20261004/metrics.csv new file mode 100644 index 0000000000..0a153c22a2 --- /dev/null +++ b/docs/refactor/receipts/runtime-paired-v12-20261004/metrics.csv @@ -0,0 +1,28 @@ +pipeline_name,method,assay_category,module_category,accuracy_fraction,raw_seconds,speedup,peak_memory_mb +cp_tutorial_3d_monolayer,CellProfiler,,,1.0,16.14390598447062,1.0, +cp_tutorial_3d_monolayer,OH execution,,,1.0,5.757013440132141,2.804215441279232, +cp_tutorial_3d_monolayer,OH total,,,1.0,7.056809307541698,2.2877061403965433, +ExampleSpeckles,CellProfiler,,,1.0,1.9223856017924845,1.0, +ExampleSpeckles,OH execution,,,1.0,0.9820932149887085,1.9574370054217174, +ExampleSpeckles,OH total,,,1.0,1.6737687408458441,1.148537163396301, +cp_tutorial_beginner_segmentation_final,CellProfiler,,,1.0,15.013752169208601,1.0, +cp_tutorial_beginner_segmentation_final,OH execution,,,1.0,3.7919174432754517,3.959409030867441, +cp_tutorial_beginner_segmentation_final,OH total,,,1.0,4.632905498612672,3.240677405076465, +cp_tutorial_3d_monolayer,CellProfiler run 1,,,1.0,14.833274588920176,, +cp_tutorial_3d_monolayer,CellProfiler run 2,,,1.0,17.454537380021065,, +cp_tutorial_3d_monolayer,OH execution run 1,,,1.0,5.278846979141235,, +cp_tutorial_3d_monolayer,OH execution run 2,,,1.0,6.235179901123047,, +cp_tutorial_3d_monolayer,OH total run 1,,,1.0,6.573324916884303,, +cp_tutorial_3d_monolayer,OH total run 2,,,1.0,7.540293698199093,, +ExampleSpeckles,CellProfiler run 1,,,1.0,1.9603862748481333,, +ExampleSpeckles,CellProfiler run 2,,,1.0,1.8843849287368357,, +ExampleSpeckles,OH execution run 1,,,1.0,1.0051443576812744,, +ExampleSpeckles,OH execution run 2,,,1.0,0.9590420722961426,, +ExampleSpeckles,OH total run 1,,,1.0,1.6968098748475313,, +ExampleSpeckles,OH total run 2,,,1.0,1.650727606844157,, +cp_tutorial_beginner_segmentation_final,CellProfiler run 1,,,1.0,15.15400242106989,, +cp_tutorial_beginner_segmentation_final,CellProfiler run 2,,,1.0,14.873501917347312,, +cp_tutorial_beginner_segmentation_final,OH execution run 1,,,1.0,3.6314709186553955,, +cp_tutorial_beginner_segmentation_final,OH execution run 2,,,1.0,3.952363967895508,, +cp_tutorial_beginner_segmentation_final,OH total run 1,,,1.0,4.468180731404573,, +cp_tutorial_beginner_segmentation_final,OH total run 2,,,1.0,4.7976302658207715,, diff --git a/docs/refactor/receipts/runtime-paired-v12-20261004/qualification.json b/docs/refactor/receipts/runtime-paired-v12-20261004/qualification.json new file mode 100644 index 0000000000..9d96dc2e2c --- /dev/null +++ b/docs/refactor/receipts/runtime-paired-v12-20261004/qualification.json @@ -0,0 +1,326 @@ +{ + "status": "PASS", + "source_head": "cc4461bc8a58c90c2ae13a5dd3870a67e1d8fc0a", + "origin_main": "2df0918353b47fa07d19fe4b6cc8b52b5e4c1695", + "science_path": "/home/ts/.local/state/openhcs-maintenance/20261004/canonical-runtime-cache-client-paired-v12-qualified/strict-science.json", + "science_sha256": "df61eca666cd741f238d96b6f7fd2c22b10c14dc577b64a381969a36a0bb5906", + "source_freeze_path": "/home/ts/.local/state/openhcs-maintenance/20261004/canonical-runtime-cache-client-paired-v12-qualified/source-freeze.json", + "source_freeze_sha256": "24b4277094722d66ffe6bcccdbb3f543d197463c6a3990c9e764c9390affccda", + "source_environment_sha256": "d51ddede016d054acbc7abde82a533bca07a2a39d41c85939c2acf3f35b8cc68", + "dependency_heads": { + "external/ObjectState": "9fb5b7eeea96f3b7bb0579de30718bbcc0018823", + "external/python-introspect": "ed1e4eb15f7a0bf8315274d3e47858fa2b4372bb", + "external/arraybridge": "1e53d03d9f468322a1c085c8be29485fb139caf2", + "external/metaclass-registry": "393a7e03003cdc56df9013f932ed4f26e632d77a", + "external/zmqruntime": "be67b58f2e2fc31cba1b829842934df101ef8320", + "external/pycodify": "108a8edbf25de258168756bac22c7572f018fa90", + "external/PolyStore": "89deeef3662eabb11bc520fad9acd976698636bd", + "external/pyqt-reactive": "b64ed2eca96fcdad29ba90beb545caa669a4d3d8" + }, + "actual_import_dependency_heads": { + "external/ObjectState": "9fb5b7eeea96f3b7bb0579de30718bbcc0018823", + "external/PolyStore": "89deeef3662eabb11bc520fad9acd976698636bd", + "external/arraybridge": "1e53d03d9f468322a1c085c8be29485fb139caf2", + "external/metaclass-registry": "393a7e03003cdc56df9013f932ed4f26e632d77a", + "external/pycodify": "108a8edbf25de258168756bac22c7572f018fa90", + "external/pyqt-reactive": "b64ed2eca96fcdad29ba90beb545caa669a4d3d8", + "external/python-introspect": "ed1e4eb15f7a0bf8315274d3e47858fa2b4372bb", + "external/zmqruntime": "be67b58f2e2fc31cba1b829842934df101ef8320" + }, + "ordered_source_ref_counts": { + "cp_tutorial_3d_monolayer": 180, + "ExampleSpeckles": 2, + "cp_tutorial_beginner_segmentation_final": 10 + }, + "comparisons": [ + { + "case": "cp_tutorial_3d_monolayer", + "ordinary_repeat": 0, + "native_repeat": 0, + "measurement_differences": 0, + "image_differences": 0, + "tables": [ + 7, + 6 + ], + "physical_images": [ + 2, + 2 + ], + "logical_images": [ + 2, + 2 + ], + "known_relationship_keys": [ + 3, + 3 + ], + "ordinary_receipt_sha256": "e1cf139b74e09476f5e4c936a508d9fe99cbe965b97776f1ce3ca5f5a2507fe0" + }, + { + "case": "cp_tutorial_3d_monolayer", + "ordinary_repeat": 0, + "native_repeat": 1, + "measurement_differences": 0, + "image_differences": 0, + "tables": [ + 7, + 6 + ], + "physical_images": [ + 2, + 2 + ], + "logical_images": [ + 2, + 2 + ], + "known_relationship_keys": [ + 3, + 3 + ], + "ordinary_receipt_sha256": "e1cf139b74e09476f5e4c936a508d9fe99cbe965b97776f1ce3ca5f5a2507fe0" + }, + { + "case": "ExampleSpeckles", + "ordinary_repeat": 0, + "native_repeat": 0, + "measurement_differences": 0, + "image_differences": 0, + "tables": [ + 3, + 3 + ], + "physical_images": [ + 0, + 0 + ], + "logical_images": [ + 0, + 0 + ], + "known_relationship_keys": [ + 1, + 1 + ], + "ordinary_receipt_sha256": "1697be961417fe7f3cb150c3a11a9980000ed321a8f72d391430c15b0a925dad" + }, + { + "case": "ExampleSpeckles", + "ordinary_repeat": 0, + "native_repeat": 1, + "measurement_differences": 0, + "image_differences": 0, + "tables": [ + 3, + 3 + ], + "physical_images": [ + 0, + 0 + ], + "logical_images": [ + 0, + 0 + ], + "known_relationship_keys": [ + 1, + 1 + ], + "ordinary_receipt_sha256": "1697be961417fe7f3cb150c3a11a9980000ed321a8f72d391430c15b0a925dad" + }, + { + "case": "cp_tutorial_beginner_segmentation_final", + "ordinary_repeat": 0, + "native_repeat": 0, + "measurement_differences": 0, + "image_differences": 0, + "tables": [ + 7, + 7 + ], + "physical_images": [ + 2, + 2 + ], + "logical_images": [ + 2, + 2 + ], + "known_relationship_keys": [ + 5, + 5 + ], + "ordinary_receipt_sha256": "602950243a8bc371cb49c817579d41c3b0e9ebebd95478fd9af97c60aab763d8" + }, + { + "case": "cp_tutorial_beginner_segmentation_final", + "ordinary_repeat": 0, + "native_repeat": 1, + "measurement_differences": 0, + "image_differences": 0, + "tables": [ + 7, + 7 + ], + "physical_images": [ + 2, + 2 + ], + "logical_images": [ + 2, + 2 + ], + "known_relationship_keys": [ + 5, + 5 + ], + "ordinary_receipt_sha256": "602950243a8bc371cb49c817579d41c3b0e9ebebd95478fd9af97c60aab763d8" + }, + { + "case": "cp_tutorial_3d_monolayer", + "ordinary_repeat": 1, + "native_repeat": 0, + "measurement_differences": 0, + "image_differences": 0, + "tables": [ + 7, + 6 + ], + "physical_images": [ + 2, + 2 + ], + "logical_images": [ + 2, + 2 + ], + "known_relationship_keys": [ + 3, + 3 + ], + "ordinary_receipt_sha256": "48112dba84d49dd5117a9d0c0d6e6feaeaa6740dc7add4e839f62e74787b5409" + }, + { + "case": "cp_tutorial_3d_monolayer", + "ordinary_repeat": 1, + "native_repeat": 1, + "measurement_differences": 0, + "image_differences": 0, + "tables": [ + 7, + 6 + ], + "physical_images": [ + 2, + 2 + ], + "logical_images": [ + 2, + 2 + ], + "known_relationship_keys": [ + 3, + 3 + ], + "ordinary_receipt_sha256": "48112dba84d49dd5117a9d0c0d6e6feaeaa6740dc7add4e839f62e74787b5409" + }, + { + "case": "ExampleSpeckles", + "ordinary_repeat": 1, + "native_repeat": 0, + "measurement_differences": 0, + "image_differences": 0, + "tables": [ + 3, + 3 + ], + "physical_images": [ + 0, + 0 + ], + "logical_images": [ + 0, + 0 + ], + "known_relationship_keys": [ + 1, + 1 + ], + "ordinary_receipt_sha256": "88b61cca321772ff009f4357af086651719ca62d8e26723f93623cebadd76ea9" + }, + { + "case": "ExampleSpeckles", + "ordinary_repeat": 1, + "native_repeat": 1, + "measurement_differences": 0, + "image_differences": 0, + "tables": [ + 3, + 3 + ], + "physical_images": [ + 0, + 0 + ], + "logical_images": [ + 0, + 0 + ], + "known_relationship_keys": [ + 1, + 1 + ], + "ordinary_receipt_sha256": "88b61cca321772ff009f4357af086651719ca62d8e26723f93623cebadd76ea9" + }, + { + "case": "cp_tutorial_beginner_segmentation_final", + "ordinary_repeat": 1, + "native_repeat": 0, + "measurement_differences": 0, + "image_differences": 0, + "tables": [ + 7, + 7 + ], + "physical_images": [ + 2, + 2 + ], + "logical_images": [ + 2, + 2 + ], + "known_relationship_keys": [ + 5, + 5 + ], + "ordinary_receipt_sha256": "3ed28b56c0952842a268e36d843c9a2b1a8ca662669268b688a6d7e395600ac8" + }, + { + "case": "cp_tutorial_beginner_segmentation_final", + "ordinary_repeat": 1, + "native_repeat": 1, + "measurement_differences": 0, + "image_differences": 0, + "tables": [ + 7, + 7 + ], + "physical_images": [ + 2, + 2 + ], + "logical_images": [ + 2, + 2 + ], + "known_relationship_keys": [ + 5, + 5 + ], + "ordinary_receipt_sha256": "3ed28b56c0952842a268e36d843c9a2b1a8ca662669268b688a6d7e395600ac8" + } + ], + "scope": "Both ordinary observations versus both native measured observations; full strict files/values/correlation policy; descriptive two-repeat clocks, not full30 acceptance." +} diff --git a/docs/refactor/receipts/runtime-paired-v12-20261004/timing_summary.json b/docs/refactor/receipts/runtime-paired-v12-20261004/timing_summary.json new file mode 100644 index 0000000000..758d49b95f --- /dev/null +++ b/docs/refactor/receipts/runtime-paired-v12-20261004/timing_summary.json @@ -0,0 +1,507 @@ +{ + "source_head": "cc4461bc8a58c90c2ae13a5dd3870a67e1d8fc0a", + "cases": { + "cp_tutorial_3d_monolayer": { + "native_invocation_seconds": [ + 14.833274588920176, + 17.454537380021065 + ], + "native_mean_seconds": 16.14390598447062, + "native_first_module_through_post_run_seconds": [ + 14.70573168899864, + 17.332816150039434 + ], + "native_first_module_through_post_run_mean_seconds": 16.019273919519037, + "ordinary_samples": { + "compile_seconds": [ + 1.0287065505981445, + 1.068333625793457 + ], + "execute_seconds": [ + 5.278846979141235, + 6.235179901123047 + ], + "total_seconds": [ + 6.573324916884303, + 7.540293698199093 + ] + }, + "ordinary_means": { + "compile_seconds": 1.0485200881958008, + "execute_seconds": 5.757013440132141, + "total_seconds": 7.056809307541698 + }, + "observed_ranges_seconds": { + "native_invocation_seconds": { + "minimum": 14.833274588920176, + "maximum": 17.454537380021065 + }, + "compile_seconds": { + "minimum": 1.0287065505981445, + "maximum": 1.068333625793457 + }, + "execute_seconds": { + "minimum": 5.278846979141235, + "maximum": 6.235179901123047 + }, + "total_seconds": { + "minimum": 6.573324916884303, + "maximum": 7.540293698199093 + } + }, + "other_total_seconds_mean": 0.2512757792137563, + "execution_speedup_ratio_of_means": 2.804215441279232, + "total_speedup_ratio_of_means": 2.2877061403965433 + }, + "ExampleSpeckles": { + "native_invocation_seconds": [ + 1.9603862748481333, + 1.8843849287368357 + ], + "native_mean_seconds": 1.9223856017924845, + "native_first_module_through_post_run_seconds": [ + 1.868687608744949, + 1.8083019987680018 + ], + "native_first_module_through_post_run_mean_seconds": 1.8384948037564754, + "ordinary_samples": { + "compile_seconds": [ + 0.4813556671142578, + 0.4825153350830078 + ], + "execute_seconds": [ + 1.0051443576812744, + 0.9590420722961426 + ], + "total_seconds": [ + 1.6968098748475313, + 1.650727606844157 + ] + }, + "ordinary_means": { + "compile_seconds": 0.4819355010986328, + "execute_seconds": 0.9820932149887085, + "total_seconds": 1.6737687408458441 + }, + "observed_ranges_seconds": { + "native_invocation_seconds": { + "minimum": 1.8843849287368357, + "maximum": 1.9603862748481333 + }, + "compile_seconds": { + "minimum": 0.4813556671142578, + "maximum": 0.4825153350830078 + }, + "execute_seconds": { + "minimum": 0.9590420722961426, + "maximum": 1.0051443576812744 + }, + "total_seconds": { + "minimum": 1.650727606844157, + "maximum": 1.6968098748475313 + } + }, + "other_total_seconds_mean": 0.20974002475850284, + "execution_speedup_ratio_of_means": 1.9574370054217174, + "total_speedup_ratio_of_means": 1.148537163396301 + }, + "cp_tutorial_beginner_segmentation_final": { + "native_invocation_seconds": [ + 15.15400242106989, + 14.873501917347312 + ], + "native_mean_seconds": 15.013752169208601, + "native_first_module_through_post_run_seconds": [ + 14.923018519766629, + 14.67788502201438 + ], + "native_first_module_through_post_run_mean_seconds": 14.800451770890504, + "ordinary_samples": { + "compile_seconds": [ + 0.6058239936828613, + 0.6234328746795654 + ], + "execute_seconds": [ + 3.6314709186553955, + 3.952363967895508 + ], + "total_seconds": [ + 4.468180731404573, + 4.7976302658207715 + ] + }, + "ordinary_means": { + "compile_seconds": 0.6146284341812134, + "execute_seconds": 3.7919174432754517, + "total_seconds": 4.632905498612672 + }, + "observed_ranges_seconds": { + "native_invocation_seconds": { + "minimum": 14.873501917347312, + "maximum": 15.15400242106989 + }, + "compile_seconds": { + "minimum": 0.6058239936828613, + "maximum": 0.6234328746795654 + }, + "execute_seconds": { + "minimum": 3.6314709186553955, + "maximum": 3.952363967895508 + }, + "total_seconds": { + "minimum": 4.468180731404573, + "maximum": 4.7976302658207715 + } + }, + "other_total_seconds_mean": 0.22635962115600705, + "execution_speedup_ratio_of_means": 3.959409030867441, + "total_speedup_ratio_of_means": 3.240677405076465 + } + }, + "clock_definitions": { + "native_invocation_seconds": "Full existing native invocation clock: pre-first-module work plus first-module-through-post-run. Process imports, JVM startup, input loading and full warmup excluded. This is the same clock used by V7 ratios.", + "native_first_module_through_post_run_seconds": "Separate diagnostic clock, excluding native pre-first-module work. Not used for the plotted speedup ratios.", + "openhcs_execute_seconds": "Ordinary pipeline execution including generic runtime plumbing; not pure callable or kernel time.", + "openhcs_total_seconds": "Ordinary compilation plus execution and default OUTCOMES/RSS completion. ZMQ server READY startup/shutdown excluded." + }, + "scope": "Three current pipelines, one selected well and one worker; two observations per method. Means and observed min/max are descriptive, not confidence intervals or per-cut causal gains. No full30 or scaling claim. All measured samples shown separately; no synthetic pairing of native and OpenHCS repetitions.", + "qualification": { + "status": "PASS", + "source_head": "cc4461bc8a58c90c2ae13a5dd3870a67e1d8fc0a", + "origin_main": "2df0918353b47fa07d19fe4b6cc8b52b5e4c1695", + "science_path": "/home/ts/.local/state/openhcs-maintenance/20261004/canonical-runtime-cache-client-paired-v12-qualified/strict-science.json", + "science_sha256": "df61eca666cd741f238d96b6f7fd2c22b10c14dc577b64a381969a36a0bb5906", + "source_freeze_path": "/home/ts/.local/state/openhcs-maintenance/20261004/canonical-runtime-cache-client-paired-v12-qualified/source-freeze.json", + "source_freeze_sha256": "24b4277094722d66ffe6bcccdbb3f543d197463c6a3990c9e764c9390affccda", + "source_environment_sha256": "d51ddede016d054acbc7abde82a533bca07a2a39d41c85939c2acf3f35b8cc68", + "dependency_heads": { + "external/ObjectState": "9fb5b7eeea96f3b7bb0579de30718bbcc0018823", + "external/python-introspect": "ed1e4eb15f7a0bf8315274d3e47858fa2b4372bb", + "external/arraybridge": "1e53d03d9f468322a1c085c8be29485fb139caf2", + "external/metaclass-registry": "393a7e03003cdc56df9013f932ed4f26e632d77a", + "external/zmqruntime": "be67b58f2e2fc31cba1b829842934df101ef8320", + "external/pycodify": "108a8edbf25de258168756bac22c7572f018fa90", + "external/PolyStore": "89deeef3662eabb11bc520fad9acd976698636bd", + "external/pyqt-reactive": "b64ed2eca96fcdad29ba90beb545caa669a4d3d8" + }, + "actual_import_dependency_heads": { + "external/ObjectState": "9fb5b7eeea96f3b7bb0579de30718bbcc0018823", + "external/PolyStore": "89deeef3662eabb11bc520fad9acd976698636bd", + "external/arraybridge": "1e53d03d9f468322a1c085c8be29485fb139caf2", + "external/metaclass-registry": "393a7e03003cdc56df9013f932ed4f26e632d77a", + "external/pycodify": "108a8edbf25de258168756bac22c7572f018fa90", + "external/pyqt-reactive": "b64ed2eca96fcdad29ba90beb545caa669a4d3d8", + "external/python-introspect": "ed1e4eb15f7a0bf8315274d3e47858fa2b4372bb", + "external/zmqruntime": "be67b58f2e2fc31cba1b829842934df101ef8320" + }, + "ordered_source_ref_counts": { + "cp_tutorial_3d_monolayer": 180, + "ExampleSpeckles": 2, + "cp_tutorial_beginner_segmentation_final": 10 + }, + "comparisons": [ + { + "case": "cp_tutorial_3d_monolayer", + "ordinary_repeat": 0, + "native_repeat": 0, + "measurement_differences": 0, + "image_differences": 0, + "tables": [ + 7, + 6 + ], + "physical_images": [ + 2, + 2 + ], + "logical_images": [ + 2, + 2 + ], + "known_relationship_keys": [ + 3, + 3 + ], + "ordinary_receipt_sha256": "e1cf139b74e09476f5e4c936a508d9fe99cbe965b97776f1ce3ca5f5a2507fe0" + }, + { + "case": "cp_tutorial_3d_monolayer", + "ordinary_repeat": 0, + "native_repeat": 1, + "measurement_differences": 0, + "image_differences": 0, + "tables": [ + 7, + 6 + ], + "physical_images": [ + 2, + 2 + ], + "logical_images": [ + 2, + 2 + ], + "known_relationship_keys": [ + 3, + 3 + ], + "ordinary_receipt_sha256": "e1cf139b74e09476f5e4c936a508d9fe99cbe965b97776f1ce3ca5f5a2507fe0" + }, + { + "case": "ExampleSpeckles", + "ordinary_repeat": 0, + "native_repeat": 0, + "measurement_differences": 0, + "image_differences": 0, + "tables": [ + 3, + 3 + ], + "physical_images": [ + 0, + 0 + ], + "logical_images": [ + 0, + 0 + ], + "known_relationship_keys": [ + 1, + 1 + ], + "ordinary_receipt_sha256": "1697be961417fe7f3cb150c3a11a9980000ed321a8f72d391430c15b0a925dad" + }, + { + "case": "ExampleSpeckles", + "ordinary_repeat": 0, + "native_repeat": 1, + "measurement_differences": 0, + "image_differences": 0, + "tables": [ + 3, + 3 + ], + "physical_images": [ + 0, + 0 + ], + "logical_images": [ + 0, + 0 + ], + "known_relationship_keys": [ + 1, + 1 + ], + "ordinary_receipt_sha256": "1697be961417fe7f3cb150c3a11a9980000ed321a8f72d391430c15b0a925dad" + }, + { + "case": "cp_tutorial_beginner_segmentation_final", + "ordinary_repeat": 0, + "native_repeat": 0, + "measurement_differences": 0, + "image_differences": 0, + "tables": [ + 7, + 7 + ], + "physical_images": [ + 2, + 2 + ], + "logical_images": [ + 2, + 2 + ], + "known_relationship_keys": [ + 5, + 5 + ], + "ordinary_receipt_sha256": "602950243a8bc371cb49c817579d41c3b0e9ebebd95478fd9af97c60aab763d8" + }, + { + "case": "cp_tutorial_beginner_segmentation_final", + "ordinary_repeat": 0, + "native_repeat": 1, + "measurement_differences": 0, + "image_differences": 0, + "tables": [ + 7, + 7 + ], + "physical_images": [ + 2, + 2 + ], + "logical_images": [ + 2, + 2 + ], + "known_relationship_keys": [ + 5, + 5 + ], + "ordinary_receipt_sha256": "602950243a8bc371cb49c817579d41c3b0e9ebebd95478fd9af97c60aab763d8" + }, + { + "case": "cp_tutorial_3d_monolayer", + "ordinary_repeat": 1, + "native_repeat": 0, + "measurement_differences": 0, + "image_differences": 0, + "tables": [ + 7, + 6 + ], + "physical_images": [ + 2, + 2 + ], + "logical_images": [ + 2, + 2 + ], + "known_relationship_keys": [ + 3, + 3 + ], + "ordinary_receipt_sha256": "48112dba84d49dd5117a9d0c0d6e6feaeaa6740dc7add4e839f62e74787b5409" + }, + { + "case": "cp_tutorial_3d_monolayer", + "ordinary_repeat": 1, + "native_repeat": 1, + "measurement_differences": 0, + "image_differences": 0, + "tables": [ + 7, + 6 + ], + "physical_images": [ + 2, + 2 + ], + "logical_images": [ + 2, + 2 + ], + "known_relationship_keys": [ + 3, + 3 + ], + "ordinary_receipt_sha256": "48112dba84d49dd5117a9d0c0d6e6feaeaa6740dc7add4e839f62e74787b5409" + }, + { + "case": "ExampleSpeckles", + "ordinary_repeat": 1, + "native_repeat": 0, + "measurement_differences": 0, + "image_differences": 0, + "tables": [ + 3, + 3 + ], + "physical_images": [ + 0, + 0 + ], + "logical_images": [ + 0, + 0 + ], + "known_relationship_keys": [ + 1, + 1 + ], + "ordinary_receipt_sha256": "88b61cca321772ff009f4357af086651719ca62d8e26723f93623cebadd76ea9" + }, + { + "case": "ExampleSpeckles", + "ordinary_repeat": 1, + "native_repeat": 1, + "measurement_differences": 0, + "image_differences": 0, + "tables": [ + 3, + 3 + ], + "physical_images": [ + 0, + 0 + ], + "logical_images": [ + 0, + 0 + ], + "known_relationship_keys": [ + 1, + 1 + ], + "ordinary_receipt_sha256": "88b61cca321772ff009f4357af086651719ca62d8e26723f93623cebadd76ea9" + }, + { + "case": "cp_tutorial_beginner_segmentation_final", + "ordinary_repeat": 1, + "native_repeat": 0, + "measurement_differences": 0, + "image_differences": 0, + "tables": [ + 7, + 7 + ], + "physical_images": [ + 2, + 2 + ], + "logical_images": [ + 2, + 2 + ], + "known_relationship_keys": [ + 5, + 5 + ], + "ordinary_receipt_sha256": "3ed28b56c0952842a268e36d843c9a2b1a8ca662669268b688a6d7e395600ac8" + }, + { + "case": "cp_tutorial_beginner_segmentation_final", + "ordinary_repeat": 1, + "native_repeat": 1, + "measurement_differences": 0, + "image_differences": 0, + "tables": [ + 7, + 7 + ], + "physical_images": [ + 2, + 2 + ], + "logical_images": [ + 2, + 2 + ], + "known_relationship_keys": [ + 5, + 5 + ], + "ordinary_receipt_sha256": "3ed28b56c0952842a268e36d843c9a2b1a8ca662669268b688a6d7e395600ac8" + } + ], + "scope": "Both ordinary observations versus both native measured observations; full strict files/values/correlation policy; descriptive two-repeat clocks, not full30 acceptance." + }, + "plot_script_sha256": "0b1aca579a1d4decd5a55dc59ec06d867b0571053ebf29a630b5e00ba1a1f5ea", + "figure_owner_sha256": "bb1bf777c5c5d95507b0f751310652e29ab8b3919387334871a890bfe667f3c1", + "v7_plot_script_sha256": "28f92861b2f69908e44e30ee6dd009ac839d8eb76f32326d18a6a12b87a9dd29", + "artifacts": { + "/home/ts/.local/state/openhcs-maintenance/20261004/canonical-runtime-cache-client-paired-v12-qualified/figures/metrics.csv": "9b7d6088eafa2e63341d13180974742dcdf3c11742a3b2d4d0861cf64afba946", + "/home/ts/.local/state/openhcs-maintenance/20261004/canonical-runtime-cache-client-paired-v12-qualified/figures/qualification.json": "dc1d6986e05ad3acd8c36d53aac242cc8f0117827f35790f5b61d7eec438f512", + "/home/ts/.local/state/openhcs-maintenance/20261004/canonical-runtime-cache-client-paired-v12-qualified/figures/matched_runtime.png": "41da13bf363a0305b842eb589809919c1407a589c2cfe39d3a7d392648305006", + "/home/ts/.local/state/openhcs-maintenance/20261004/canonical-runtime-cache-client-paired-v12-qualified/figures/matched_runtime.svg": "8f9524409fd3bb9b095f96d6e057c5efc1d1dd457e74587c4424f20d5af13c31", + "/home/ts/.local/state/openhcs-maintenance/20261004/canonical-runtime-cache-client-paired-v12-qualified/figures/matched_speedup.png": "3c561e52ce3c15a24b4385136b1ee364d827e559a94979810145fc1ae96961cd", + "/home/ts/.local/state/openhcs-maintenance/20261004/canonical-runtime-cache-client-paired-v12-qualified/figures/matched_speedup.svg": "73ba1f3efa5501445c2e4b2517a2a62d7ac8771c29d119f73fb06e1ce4e5abc2", + "/home/ts/.local/state/openhcs-maintenance/20261004/canonical-runtime-cache-client-paired-v12-qualified/figures/matched_runtime_samples.png": "c15d09863f4f4cf7f1ae9de3dab88a5738d3dd587e3f87fd8f37613bd18fb02f", + "/home/ts/.local/state/openhcs-maintenance/20261004/canonical-runtime-cache-client-paired-v12-qualified/figures/matched_runtime_samples.svg": "509f940cab41b9d41b6e1e10bf73382b83c36a5b5fda08476ad81ef6ad9f8da9" + } +} diff --git a/docs/refactor/receipts/runtime-paired-v15-20261004/README.rst b/docs/refactor/receipts/runtime-paired-v15-20261004/README.rst new file mode 100644 index 0000000000..101f66283d --- /dev/null +++ b/docs/refactor/receipts/runtime-paired-v15-20261004/README.rst @@ -0,0 +1,41 @@ +Fresh paired single-worker runtime: V15 +====================================== + +Measured production source ``4f2e44701c1c5460ca7e447c7b3d05e3530367ad`` includes the request-wide configuration capture and inherited progress admission fix (#595). Main #593 is merged; installed ZMQRuntime is merged #19 at ``04d813fe6c93f74166c05847afb1eae158d3c817``. All eight actual imported dependency heads, source/input hashes and environment guards are retained in the adjacent qualification. + +Both ordinary observations and both fresh native CellProfiler observations completed for each original pipeline. All twelve pairwise scientific comparisons PASS: full measurement policy, relationship correlations, physical inventories and image comparisons. Both 3D label volumes match exactly; no plane flattening or tolerance relaxation was used. + +Descriptive means of two observations (seconds): + +======================================== ========= ========= ========= ========= =========== =========== +Pipeline Compile Execution Total Native CP Exec speedup Total speedup +======================================== ========= ========= ========= ========= =========== =========== +3D monolayer 0.852 5.217 6.364 13.860 2.657x 2.178x +Speckles 0.486 1.036 1.674 1.893 1.828x 1.131x +Beginner 0.439 3.451 4.115 14.806 4.290x 3.598x +======================================== ========= ========= ========= ========= =========== =========== + +Clocks exclude ZMQ startup, registry/kernel preparation, native imports/JVM/input loading, warmup and shutdown. OpenHCS execution includes runtime plumbing; total includes compilation and default OUTCOMES/RSS completion. Native uses the existing full invocation clock, including preparation, modules and closure. Single-worker execution is inline. + +Relative to retained V12, OpenHCS total fell from 7.057 to 6.364 s for 3D and from 4.633 to 4.115 s for Beginner. Speckles total is effectively unchanged (1.674 versus 1.674 s), while its execution mean rose from 0.982 to 1.036 s. The new fresh native 3D mean is 13.860 s rather than V12's 16.144 s, so a smaller plotted speedup does not imply slower OpenHCS. These observations do not isolate any individual patch's effect. All samples are shown; no confidence interval or full-catalog/scaling claim is made. + +Speckles remains the poorest relative-performance case. Its execution gap to 2x is approximately 0.089 s; its total gap is approximately 0.728 s. The remaining compiler, completion and IPO costs must be assessed against those gaps. Rejected historical heap/readiness costs are not current savings. The performance goal remains active. + +The three direct OpenHCS progress queue bypasses were fixed by using the existing inherited server admission. A real server/client control verifies compiler, axisless and worker progress sequences and retained terminal watermark; worker forwarding drains before terminal completion. The two ordinary sweeps provide installed integration acceptance. Earlier V14 observations failed this integration and remain rejected, with no fresh native run or accepted timing claim. + +Configuration controls: 34 PASS plus a saved seven-step Speckles request replay with one admitted capture and zero internal live-getter rereads. Authored PipelineConfig remains the step context provider; the public getter remains live and direct compile captures a fresh epoch. This is not a claim to seal arbitrary external mutation of ObjectState globals. + +The separate public aggregate/Mosaic source-position fix is not included in these timings. Its valid-declaration alias counterexample remains open under #435; four previously reproduced baseline Volume fixture failures are also unwaived. Neither removes this pipeline-scoped scientific acceptance. + +Retained immutable campaign:: + + /home/ts/.local/state/openhcs-maintenance/20261004/canonical-runtime-coherent-paired-v15-qualified + +Renderer uses the existing repository figure owner:: + + /home/ts/.local/state/openhcs-maintenance/20261004/plot_current_paired_timings_v15.py + +SHA-256 custody: + +* ``strict-science.json``: ``2f2d6d2462e8d01b8688754e7b95edb21b9d2b3f47dd3197af8100929eb8fab4``. +* ``source-freeze.json``: ``ffc4089f7fcef08af92740b2cca15b81b2541435562357f14b8a925a811e7b2c``. diff --git a/docs/refactor/receipts/runtime-paired-v15-20261004/matched_runtime.png b/docs/refactor/receipts/runtime-paired-v15-20261004/matched_runtime.png new file mode 100644 index 0000000000..0eb3a84e4c Binary files /dev/null and b/docs/refactor/receipts/runtime-paired-v15-20261004/matched_runtime.png differ diff --git a/docs/refactor/receipts/runtime-paired-v15-20261004/matched_runtime.svg b/docs/refactor/receipts/runtime-paired-v15-20261004/matched_runtime.svg new file mode 100644 index 0000000000..d866d3ed34 --- /dev/null +++ b/docs/refactor/receipts/runtime-paired-v15-20261004/matched_runtime.svg @@ -0,0 +1,1815 @@ + + + + + + + + 2026-10-04T04:05:37.163756 + image/svg+xml + + + Matplotlib v3.11.2, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/refactor/receipts/runtime-paired-v15-20261004/matched_runtime_samples.png b/docs/refactor/receipts/runtime-paired-v15-20261004/matched_runtime_samples.png new file mode 100644 index 0000000000..c8f072a5f2 Binary files /dev/null and b/docs/refactor/receipts/runtime-paired-v15-20261004/matched_runtime_samples.png differ diff --git a/docs/refactor/receipts/runtime-paired-v15-20261004/matched_runtime_samples.svg b/docs/refactor/receipts/runtime-paired-v15-20261004/matched_runtime_samples.svg new file mode 100644 index 0000000000..faaf45e065 --- /dev/null +++ b/docs/refactor/receipts/runtime-paired-v15-20261004/matched_runtime_samples.svg @@ -0,0 +1,2090 @@ + + + + + + + + 2026-10-04T04:05:37.985065 + image/svg+xml + + + Matplotlib v3.11.2, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/refactor/receipts/runtime-paired-v15-20261004/matched_speedup.png b/docs/refactor/receipts/runtime-paired-v15-20261004/matched_speedup.png new file mode 100644 index 0000000000..ffc04e99ff Binary files /dev/null and b/docs/refactor/receipts/runtime-paired-v15-20261004/matched_speedup.png differ diff --git a/docs/refactor/receipts/runtime-paired-v15-20261004/matched_speedup.svg b/docs/refactor/receipts/runtime-paired-v15-20261004/matched_speedup.svg new file mode 100644 index 0000000000..7e6465f62e --- /dev/null +++ b/docs/refactor/receipts/runtime-paired-v15-20261004/matched_speedup.svg @@ -0,0 +1,1801 @@ + + + + + + + + 2026-10-04T04:05:37.541893 + image/svg+xml + + + Matplotlib v3.11.2, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/refactor/receipts/runtime-paired-v15-20261004/metrics.csv b/docs/refactor/receipts/runtime-paired-v15-20261004/metrics.csv new file mode 100644 index 0000000000..5c5cb0f27b --- /dev/null +++ b/docs/refactor/receipts/runtime-paired-v15-20261004/metrics.csv @@ -0,0 +1,28 @@ +pipeline_name,method,assay_category,module_category,accuracy_fraction,raw_seconds,speedup,peak_memory_mb +cp_tutorial_3d_monolayer,CellProfiler,,,1.0,13.86009584995918,1.0, +cp_tutorial_3d_monolayer,OH execution,,,1.0,5.216976642608643,2.6567295196914515, +cp_tutorial_3d_monolayer,OH total,,,1.0,6.364388023037463,2.1777578299420406, +ExampleSpeckles,CellProfiler,,,1.0,1.8934401751030236,1.0, +ExampleSpeckles,OH execution,,,1.0,1.0358242988586426,1.827954969959069, +ExampleSpeckles,OH total,,,1.0,1.6744454675354064,1.130786407687527, +cp_tutorial_beginner_segmentation_final,CellProfiler,,,1.0,14.806181988911703,1.0, +cp_tutorial_beginner_segmentation_final,OH execution,,,1.0,3.451413869857788,4.289888882413797, +cp_tutorial_beginner_segmentation_final,OH total,,,1.0,4.114824359305203,3.5982537032058786, +cp_tutorial_3d_monolayer,CellProfiler run 1,,,1.0,13.959804884158075,, +cp_tutorial_3d_monolayer,CellProfiler run 2,,,1.0,13.760386815760285,, +cp_tutorial_3d_monolayer,OH execution run 1,,,1.0,5.062480926513672,, +cp_tutorial_3d_monolayer,OH execution run 2,,,1.0,5.371472358703613,, +cp_tutorial_3d_monolayer,OH total run 1,,,1.0,6.217378613073379,, +cp_tutorial_3d_monolayer,OH total run 2,,,1.0,6.511397433001548,, +ExampleSpeckles,CellProfiler run 1,,,1.0,1.9473207769915462,, +ExampleSpeckles,CellProfiler run 2,,,1.0,1.8395595732145011,, +ExampleSpeckles,OH execution run 1,,,1.0,1.007242202758789,, +ExampleSpeckles,OH execution run 2,,,1.0,1.064406394958496,, +ExampleSpeckles,OH total run 1,,,1.0,1.8021175120957196,, +ExampleSpeckles,OH total run 2,,,1.0,1.5467734229750931,, +cp_tutorial_beginner_segmentation_final,CellProfiler run 1,,,1.0,14.8254848648794,, +cp_tutorial_beginner_segmentation_final,CellProfiler run 2,,,1.0,14.786879112944007,, +cp_tutorial_beginner_segmentation_final,OH execution run 1,,,1.0,3.3552932739257812,, +cp_tutorial_beginner_segmentation_final,OH execution run 2,,,1.0,3.547534465789795,, +cp_tutorial_beginner_segmentation_final,OH total run 1,,,1.0,4.0072277639992535,, +cp_tutorial_beginner_segmentation_final,OH total run 2,,,1.0,4.222420954611152,, diff --git a/docs/refactor/receipts/runtime-paired-v15-20261004/qualification.json b/docs/refactor/receipts/runtime-paired-v15-20261004/qualification.json new file mode 100644 index 0000000000..08147461e3 --- /dev/null +++ b/docs/refactor/receipts/runtime-paired-v15-20261004/qualification.json @@ -0,0 +1,326 @@ +{ + "status": "PASS", + "source_head": "4f2e44701c1c5460ca7e447c7b3d05e3530367ad", + "origin_main": "0ce2af938ec8125c2dc5110c7a9c4f03fe5bb9d7", + "science_path": "/home/ts/.local/state/openhcs-maintenance/20261004/canonical-runtime-coherent-paired-v15-qualified/strict-science.json", + "science_sha256": "2f2d6d2462e8d01b8688754e7b95edb21b9d2b3f47dd3197af8100929eb8fab4", + "source_freeze_path": "/home/ts/.local/state/openhcs-maintenance/20261004/canonical-runtime-coherent-paired-v15-qualified/source-freeze.json", + "source_freeze_sha256": "ffc4089f7fcef08af92740b2cca15b81b2541435562357f14b8a925a811e7b2c", + "source_environment_sha256": "9171bbcd52a260697d445e29fd901bd13ad75216685d639cc0988c583804d491", + "dependency_heads": { + "external/ObjectState": "9fb5b7eeea96f3b7bb0579de30718bbcc0018823", + "external/python-introspect": "430fbbeeb6c7e0a9274d3bf9b0998a10cae5a505", + "external/arraybridge": "1e53d03d9f468322a1c085c8be29485fb139caf2", + "external/metaclass-registry": "393a7e03003cdc56df9013f932ed4f26e632d77a", + "external/zmqruntime": "04d813fe6c93f74166c05847afb1eae158d3c817", + "external/pycodify": "108a8edbf25de258168756bac22c7572f018fa90", + "external/PolyStore": "89deeef3662eabb11bc520fad9acd976698636bd", + "external/pyqt-reactive": "b64ed2eca96fcdad29ba90beb545caa669a4d3d8" + }, + "actual_import_dependency_heads": { + "external/ObjectState": "9fb5b7eeea96f3b7bb0579de30718bbcc0018823", + "external/PolyStore": "89deeef3662eabb11bc520fad9acd976698636bd", + "external/arraybridge": "1e53d03d9f468322a1c085c8be29485fb139caf2", + "external/metaclass-registry": "393a7e03003cdc56df9013f932ed4f26e632d77a", + "external/pycodify": "108a8edbf25de258168756bac22c7572f018fa90", + "external/pyqt-reactive": "b64ed2eca96fcdad29ba90beb545caa669a4d3d8", + "external/python-introspect": "430fbbeeb6c7e0a9274d3bf9b0998a10cae5a505", + "external/zmqruntime": "04d813fe6c93f74166c05847afb1eae158d3c817" + }, + "ordered_source_ref_counts": { + "cp_tutorial_3d_monolayer": 180, + "ExampleSpeckles": 2, + "cp_tutorial_beginner_segmentation_final": 10 + }, + "comparisons": [ + { + "case": "cp_tutorial_3d_monolayer", + "ordinary_repeat": 0, + "native_repeat": 0, + "measurement_differences": 0, + "image_differences": 0, + "tables": [ + 7, + 6 + ], + "physical_images": [ + 2, + 2 + ], + "logical_images": [ + 2, + 2 + ], + "known_relationship_keys": [ + 3, + 3 + ], + "ordinary_receipt_sha256": "ca2f0caba6173f63c0ee14c53a098fa0281a8faf950c4df5beaa0e1ef127fe46" + }, + { + "case": "cp_tutorial_3d_monolayer", + "ordinary_repeat": 0, + "native_repeat": 1, + "measurement_differences": 0, + "image_differences": 0, + "tables": [ + 7, + 6 + ], + "physical_images": [ + 2, + 2 + ], + "logical_images": [ + 2, + 2 + ], + "known_relationship_keys": [ + 3, + 3 + ], + "ordinary_receipt_sha256": "ca2f0caba6173f63c0ee14c53a098fa0281a8faf950c4df5beaa0e1ef127fe46" + }, + { + "case": "ExampleSpeckles", + "ordinary_repeat": 0, + "native_repeat": 0, + "measurement_differences": 0, + "image_differences": 0, + "tables": [ + 3, + 3 + ], + "physical_images": [ + 0, + 0 + ], + "logical_images": [ + 0, + 0 + ], + "known_relationship_keys": [ + 1, + 1 + ], + "ordinary_receipt_sha256": "6044f89006fec3f516b08e97d33794e2a370eec332f12fac7f6b3ad9567b348f" + }, + { + "case": "ExampleSpeckles", + "ordinary_repeat": 0, + "native_repeat": 1, + "measurement_differences": 0, + "image_differences": 0, + "tables": [ + 3, + 3 + ], + "physical_images": [ + 0, + 0 + ], + "logical_images": [ + 0, + 0 + ], + "known_relationship_keys": [ + 1, + 1 + ], + "ordinary_receipt_sha256": "6044f89006fec3f516b08e97d33794e2a370eec332f12fac7f6b3ad9567b348f" + }, + { + "case": "cp_tutorial_beginner_segmentation_final", + "ordinary_repeat": 0, + "native_repeat": 0, + "measurement_differences": 0, + "image_differences": 0, + "tables": [ + 7, + 7 + ], + "physical_images": [ + 2, + 2 + ], + "logical_images": [ + 2, + 2 + ], + "known_relationship_keys": [ + 5, + 5 + ], + "ordinary_receipt_sha256": "33c5dca4c9605c94d1b62aa5500326bab09733bb80a277276a9ef5467c9bd70b" + }, + { + "case": "cp_tutorial_beginner_segmentation_final", + "ordinary_repeat": 0, + "native_repeat": 1, + "measurement_differences": 0, + "image_differences": 0, + "tables": [ + 7, + 7 + ], + "physical_images": [ + 2, + 2 + ], + "logical_images": [ + 2, + 2 + ], + "known_relationship_keys": [ + 5, + 5 + ], + "ordinary_receipt_sha256": "33c5dca4c9605c94d1b62aa5500326bab09733bb80a277276a9ef5467c9bd70b" + }, + { + "case": "cp_tutorial_3d_monolayer", + "ordinary_repeat": 1, + "native_repeat": 0, + "measurement_differences": 0, + "image_differences": 0, + "tables": [ + 7, + 6 + ], + "physical_images": [ + 2, + 2 + ], + "logical_images": [ + 2, + 2 + ], + "known_relationship_keys": [ + 3, + 3 + ], + "ordinary_receipt_sha256": "06831733126112526ce629f2ec674d22a3307c42da9dce0d60c0107979516a16" + }, + { + "case": "cp_tutorial_3d_monolayer", + "ordinary_repeat": 1, + "native_repeat": 1, + "measurement_differences": 0, + "image_differences": 0, + "tables": [ + 7, + 6 + ], + "physical_images": [ + 2, + 2 + ], + "logical_images": [ + 2, + 2 + ], + "known_relationship_keys": [ + 3, + 3 + ], + "ordinary_receipt_sha256": "06831733126112526ce629f2ec674d22a3307c42da9dce0d60c0107979516a16" + }, + { + "case": "ExampleSpeckles", + "ordinary_repeat": 1, + "native_repeat": 0, + "measurement_differences": 0, + "image_differences": 0, + "tables": [ + 3, + 3 + ], + "physical_images": [ + 0, + 0 + ], + "logical_images": [ + 0, + 0 + ], + "known_relationship_keys": [ + 1, + 1 + ], + "ordinary_receipt_sha256": "d97997831b83c3aa7133d0f526750a73e1ced6eae14a32fa1edf7f513f6b3df1" + }, + { + "case": "ExampleSpeckles", + "ordinary_repeat": 1, + "native_repeat": 1, + "measurement_differences": 0, + "image_differences": 0, + "tables": [ + 3, + 3 + ], + "physical_images": [ + 0, + 0 + ], + "logical_images": [ + 0, + 0 + ], + "known_relationship_keys": [ + 1, + 1 + ], + "ordinary_receipt_sha256": "d97997831b83c3aa7133d0f526750a73e1ced6eae14a32fa1edf7f513f6b3df1" + }, + { + "case": "cp_tutorial_beginner_segmentation_final", + "ordinary_repeat": 1, + "native_repeat": 0, + "measurement_differences": 0, + "image_differences": 0, + "tables": [ + 7, + 7 + ], + "physical_images": [ + 2, + 2 + ], + "logical_images": [ + 2, + 2 + ], + "known_relationship_keys": [ + 5, + 5 + ], + "ordinary_receipt_sha256": "17c256bf4baf0eb2aa81436e01fb4892772e5ca0a7dc6132023cbdcd8f493c45" + }, + { + "case": "cp_tutorial_beginner_segmentation_final", + "ordinary_repeat": 1, + "native_repeat": 1, + "measurement_differences": 0, + "image_differences": 0, + "tables": [ + 7, + 7 + ], + "physical_images": [ + 2, + 2 + ], + "logical_images": [ + 2, + 2 + ], + "known_relationship_keys": [ + 5, + 5 + ], + "ordinary_receipt_sha256": "17c256bf4baf0eb2aa81436e01fb4892772e5ca0a7dc6132023cbdcd8f493c45" + } + ], + "scope": "Both ordinary observations versus both native measured observations; full strict files/values/correlation policy; descriptive two-repeat clocks, not full30 acceptance." +} diff --git a/docs/refactor/receipts/runtime-paired-v15-20261004/timing_summary.json b/docs/refactor/receipts/runtime-paired-v15-20261004/timing_summary.json new file mode 100644 index 0000000000..cd3999099c --- /dev/null +++ b/docs/refactor/receipts/runtime-paired-v15-20261004/timing_summary.json @@ -0,0 +1,507 @@ +{ + "source_head": "4f2e44701c1c5460ca7e447c7b3d05e3530367ad", + "cases": { + "cp_tutorial_3d_monolayer": { + "native_invocation_seconds": [ + 13.959804884158075, + 13.760386815760285 + ], + "native_mean_seconds": 13.86009584995918, + "native_first_module_through_post_run_seconds": [ + 13.83606267394498, + 13.64653044193983 + ], + "native_first_module_through_post_run_mean_seconds": 13.741296557942405, + "ordinary_samples": { + "compile_seconds": [ + 0.8459196090698242, + 0.8587756156921387 + ], + "execute_seconds": [ + 5.062480926513672, + 5.371472358703613 + ], + "total_seconds": [ + 6.217378613073379, + 6.511397433001548 + ] + }, + "ordinary_means": { + "compile_seconds": 0.8523476123809814, + "execute_seconds": 5.216976642608643, + "total_seconds": 6.364388023037463 + }, + "observed_ranges_seconds": { + "native_invocation_seconds": { + "minimum": 13.760386815760285, + "maximum": 13.959804884158075 + }, + "compile_seconds": { + "minimum": 0.8459196090698242, + "maximum": 0.8587756156921387 + }, + "execute_seconds": { + "minimum": 5.062480926513672, + "maximum": 5.371472358703613 + }, + "total_seconds": { + "minimum": 6.217378613073379, + "maximum": 6.511397433001548 + } + }, + "other_total_seconds_mean": 0.2950637680478394, + "execution_speedup_ratio_of_means": 2.6567295196914515, + "total_speedup_ratio_of_means": 2.1777578299420406 + }, + "ExampleSpeckles": { + "native_invocation_seconds": [ + 1.9473207769915462, + 1.8395595732145011 + ], + "native_mean_seconds": 1.8934401751030236, + "native_first_module_through_post_run_seconds": [ + 1.8632063162513077, + 1.767908887937665 + ], + "native_first_module_through_post_run_mean_seconds": 1.8155576020944864, + "ordinary_samples": { + "compile_seconds": [ + 0.6512229442596436, + 0.3212571144104004 + ], + "execute_seconds": [ + 1.007242202758789, + 1.064406394958496 + ], + "total_seconds": [ + 1.8021175120957196, + 1.5467734229750931 + ] + }, + "ordinary_means": { + "compile_seconds": 0.486240029335022, + "execute_seconds": 1.0358242988586426, + "total_seconds": 1.6744454675354064 + }, + "observed_ranges_seconds": { + "native_invocation_seconds": { + "minimum": 1.8395595732145011, + "maximum": 1.9473207769915462 + }, + "compile_seconds": { + "minimum": 0.3212571144104004, + "maximum": 0.6512229442596436 + }, + "execute_seconds": { + "minimum": 1.007242202758789, + "maximum": 1.064406394958496 + }, + "total_seconds": { + "minimum": 1.5467734229750931, + "maximum": 1.8021175120957196 + } + }, + "other_total_seconds_mean": 0.1523811393417418, + "execution_speedup_ratio_of_means": 1.827954969959069, + "total_speedup_ratio_of_means": 1.130786407687527 + }, + "cp_tutorial_beginner_segmentation_final": { + "native_invocation_seconds": [ + 14.8254848648794, + 14.786879112944007 + ], + "native_mean_seconds": 14.806181988911703, + "native_first_module_through_post_run_seconds": [ + 14.575672373641282, + 14.59319975413382 + ], + "native_first_module_through_post_run_mean_seconds": 14.584436063887551, + "ordinary_samples": { + "compile_seconds": [ + 0.4405944347381592, + 0.4372115135192871 + ], + "execute_seconds": [ + 3.3552932739257812, + 3.547534465789795 + ], + "total_seconds": [ + 4.0072277639992535, + 4.222420954611152 + ] + }, + "ordinary_means": { + "compile_seconds": 0.43890297412872314, + "execute_seconds": 3.451413869857788, + "total_seconds": 4.114824359305203 + }, + "observed_ranges_seconds": { + "native_invocation_seconds": { + "minimum": 14.786879112944007, + "maximum": 14.8254848648794 + }, + "compile_seconds": { + "minimum": 0.4372115135192871, + "maximum": 0.4405944347381592 + }, + "execute_seconds": { + "minimum": 3.3552932739257812, + "maximum": 3.547534465789795 + }, + "total_seconds": { + "minimum": 4.0072277639992535, + "maximum": 4.222420954611152 + } + }, + "other_total_seconds_mean": 0.22450751531869173, + "execution_speedup_ratio_of_means": 4.289888882413797, + "total_speedup_ratio_of_means": 3.5982537032058786 + } + }, + "clock_definitions": { + "native_invocation_seconds": "Full existing native invocation clock: pre-first-module work plus first-module-through-post-run. Process imports, JVM startup, input loading and full warmup excluded. This is the same clock used by V7 ratios.", + "native_first_module_through_post_run_seconds": "Separate diagnostic clock, excluding native pre-first-module work. Not used for the plotted speedup ratios.", + "openhcs_execute_seconds": "Ordinary pipeline execution including generic runtime plumbing; not pure callable or kernel time.", + "openhcs_total_seconds": "Ordinary compilation plus execution and default OUTCOMES/RSS completion. ZMQ server READY startup/shutdown excluded." + }, + "scope": "Three current pipelines, one selected well and one worker; two observations per method. Means and observed min/max are descriptive, not confidence intervals or per-cut causal gains. No full30 or scaling claim. All measured samples shown separately; no synthetic pairing of native and OpenHCS repetitions.", + "qualification": { + "status": "PASS", + "source_head": "4f2e44701c1c5460ca7e447c7b3d05e3530367ad", + "origin_main": "0ce2af938ec8125c2dc5110c7a9c4f03fe5bb9d7", + "science_path": "/home/ts/.local/state/openhcs-maintenance/20261004/canonical-runtime-coherent-paired-v15-qualified/strict-science.json", + "science_sha256": "2f2d6d2462e8d01b8688754e7b95edb21b9d2b3f47dd3197af8100929eb8fab4", + "source_freeze_path": "/home/ts/.local/state/openhcs-maintenance/20261004/canonical-runtime-coherent-paired-v15-qualified/source-freeze.json", + "source_freeze_sha256": "ffc4089f7fcef08af92740b2cca15b81b2541435562357f14b8a925a811e7b2c", + "source_environment_sha256": "9171bbcd52a260697d445e29fd901bd13ad75216685d639cc0988c583804d491", + "dependency_heads": { + "external/ObjectState": "9fb5b7eeea96f3b7bb0579de30718bbcc0018823", + "external/python-introspect": "430fbbeeb6c7e0a9274d3bf9b0998a10cae5a505", + "external/arraybridge": "1e53d03d9f468322a1c085c8be29485fb139caf2", + "external/metaclass-registry": "393a7e03003cdc56df9013f932ed4f26e632d77a", + "external/zmqruntime": "04d813fe6c93f74166c05847afb1eae158d3c817", + "external/pycodify": "108a8edbf25de258168756bac22c7572f018fa90", + "external/PolyStore": "89deeef3662eabb11bc520fad9acd976698636bd", + "external/pyqt-reactive": "b64ed2eca96fcdad29ba90beb545caa669a4d3d8" + }, + "actual_import_dependency_heads": { + "external/ObjectState": "9fb5b7eeea96f3b7bb0579de30718bbcc0018823", + "external/PolyStore": "89deeef3662eabb11bc520fad9acd976698636bd", + "external/arraybridge": "1e53d03d9f468322a1c085c8be29485fb139caf2", + "external/metaclass-registry": "393a7e03003cdc56df9013f932ed4f26e632d77a", + "external/pycodify": "108a8edbf25de258168756bac22c7572f018fa90", + "external/pyqt-reactive": "b64ed2eca96fcdad29ba90beb545caa669a4d3d8", + "external/python-introspect": "430fbbeeb6c7e0a9274d3bf9b0998a10cae5a505", + "external/zmqruntime": "04d813fe6c93f74166c05847afb1eae158d3c817" + }, + "ordered_source_ref_counts": { + "cp_tutorial_3d_monolayer": 180, + "ExampleSpeckles": 2, + "cp_tutorial_beginner_segmentation_final": 10 + }, + "comparisons": [ + { + "case": "cp_tutorial_3d_monolayer", + "ordinary_repeat": 0, + "native_repeat": 0, + "measurement_differences": 0, + "image_differences": 0, + "tables": [ + 7, + 6 + ], + "physical_images": [ + 2, + 2 + ], + "logical_images": [ + 2, + 2 + ], + "known_relationship_keys": [ + 3, + 3 + ], + "ordinary_receipt_sha256": "ca2f0caba6173f63c0ee14c53a098fa0281a8faf950c4df5beaa0e1ef127fe46" + }, + { + "case": "cp_tutorial_3d_monolayer", + "ordinary_repeat": 0, + "native_repeat": 1, + "measurement_differences": 0, + "image_differences": 0, + "tables": [ + 7, + 6 + ], + "physical_images": [ + 2, + 2 + ], + "logical_images": [ + 2, + 2 + ], + "known_relationship_keys": [ + 3, + 3 + ], + "ordinary_receipt_sha256": "ca2f0caba6173f63c0ee14c53a098fa0281a8faf950c4df5beaa0e1ef127fe46" + }, + { + "case": "ExampleSpeckles", + "ordinary_repeat": 0, + "native_repeat": 0, + "measurement_differences": 0, + "image_differences": 0, + "tables": [ + 3, + 3 + ], + "physical_images": [ + 0, + 0 + ], + "logical_images": [ + 0, + 0 + ], + "known_relationship_keys": [ + 1, + 1 + ], + "ordinary_receipt_sha256": "6044f89006fec3f516b08e97d33794e2a370eec332f12fac7f6b3ad9567b348f" + }, + { + "case": "ExampleSpeckles", + "ordinary_repeat": 0, + "native_repeat": 1, + "measurement_differences": 0, + "image_differences": 0, + "tables": [ + 3, + 3 + ], + "physical_images": [ + 0, + 0 + ], + "logical_images": [ + 0, + 0 + ], + "known_relationship_keys": [ + 1, + 1 + ], + "ordinary_receipt_sha256": "6044f89006fec3f516b08e97d33794e2a370eec332f12fac7f6b3ad9567b348f" + }, + { + "case": "cp_tutorial_beginner_segmentation_final", + "ordinary_repeat": 0, + "native_repeat": 0, + "measurement_differences": 0, + "image_differences": 0, + "tables": [ + 7, + 7 + ], + "physical_images": [ + 2, + 2 + ], + "logical_images": [ + 2, + 2 + ], + "known_relationship_keys": [ + 5, + 5 + ], + "ordinary_receipt_sha256": "33c5dca4c9605c94d1b62aa5500326bab09733bb80a277276a9ef5467c9bd70b" + }, + { + "case": "cp_tutorial_beginner_segmentation_final", + "ordinary_repeat": 0, + "native_repeat": 1, + "measurement_differences": 0, + "image_differences": 0, + "tables": [ + 7, + 7 + ], + "physical_images": [ + 2, + 2 + ], + "logical_images": [ + 2, + 2 + ], + "known_relationship_keys": [ + 5, + 5 + ], + "ordinary_receipt_sha256": "33c5dca4c9605c94d1b62aa5500326bab09733bb80a277276a9ef5467c9bd70b" + }, + { + "case": "cp_tutorial_3d_monolayer", + "ordinary_repeat": 1, + "native_repeat": 0, + "measurement_differences": 0, + "image_differences": 0, + "tables": [ + 7, + 6 + ], + "physical_images": [ + 2, + 2 + ], + "logical_images": [ + 2, + 2 + ], + "known_relationship_keys": [ + 3, + 3 + ], + "ordinary_receipt_sha256": "06831733126112526ce629f2ec674d22a3307c42da9dce0d60c0107979516a16" + }, + { + "case": "cp_tutorial_3d_monolayer", + "ordinary_repeat": 1, + "native_repeat": 1, + "measurement_differences": 0, + "image_differences": 0, + "tables": [ + 7, + 6 + ], + "physical_images": [ + 2, + 2 + ], + "logical_images": [ + 2, + 2 + ], + "known_relationship_keys": [ + 3, + 3 + ], + "ordinary_receipt_sha256": "06831733126112526ce629f2ec674d22a3307c42da9dce0d60c0107979516a16" + }, + { + "case": "ExampleSpeckles", + "ordinary_repeat": 1, + "native_repeat": 0, + "measurement_differences": 0, + "image_differences": 0, + "tables": [ + 3, + 3 + ], + "physical_images": [ + 0, + 0 + ], + "logical_images": [ + 0, + 0 + ], + "known_relationship_keys": [ + 1, + 1 + ], + "ordinary_receipt_sha256": "d97997831b83c3aa7133d0f526750a73e1ced6eae14a32fa1edf7f513f6b3df1" + }, + { + "case": "ExampleSpeckles", + "ordinary_repeat": 1, + "native_repeat": 1, + "measurement_differences": 0, + "image_differences": 0, + "tables": [ + 3, + 3 + ], + "physical_images": [ + 0, + 0 + ], + "logical_images": [ + 0, + 0 + ], + "known_relationship_keys": [ + 1, + 1 + ], + "ordinary_receipt_sha256": "d97997831b83c3aa7133d0f526750a73e1ced6eae14a32fa1edf7f513f6b3df1" + }, + { + "case": "cp_tutorial_beginner_segmentation_final", + "ordinary_repeat": 1, + "native_repeat": 0, + "measurement_differences": 0, + "image_differences": 0, + "tables": [ + 7, + 7 + ], + "physical_images": [ + 2, + 2 + ], + "logical_images": [ + 2, + 2 + ], + "known_relationship_keys": [ + 5, + 5 + ], + "ordinary_receipt_sha256": "17c256bf4baf0eb2aa81436e01fb4892772e5ca0a7dc6132023cbdcd8f493c45" + }, + { + "case": "cp_tutorial_beginner_segmentation_final", + "ordinary_repeat": 1, + "native_repeat": 1, + "measurement_differences": 0, + "image_differences": 0, + "tables": [ + 7, + 7 + ], + "physical_images": [ + 2, + 2 + ], + "logical_images": [ + 2, + 2 + ], + "known_relationship_keys": [ + 5, + 5 + ], + "ordinary_receipt_sha256": "17c256bf4baf0eb2aa81436e01fb4892772e5ca0a7dc6132023cbdcd8f493c45" + } + ], + "scope": "Both ordinary observations versus both native measured observations; full strict files/values/correlation policy; descriptive two-repeat clocks, not full30 acceptance." + }, + "plot_script_sha256": "0db3962d61c7b4195700e0bfe9630d6cdb0deae521015199f3501c1bec63de1d", + "figure_owner_sha256": "bb1bf777c5c5d95507b0f751310652e29ab8b3919387334871a890bfe667f3c1", + "v7_plot_script_sha256": "28f92861b2f69908e44e30ee6dd009ac839d8eb76f32326d18a6a12b87a9dd29", + "artifacts": { + "/home/ts/.local/state/openhcs-maintenance/20261004/canonical-runtime-coherent-paired-v15-qualified/figures/metrics.csv": "ab1cdcc0a92dd09312d8eec4ccba8d5d9e51fef38202ded288330f8655d2394f", + "/home/ts/.local/state/openhcs-maintenance/20261004/canonical-runtime-coherent-paired-v15-qualified/figures/qualification.json": "44c0d924cf7491362de6518f741d5fcdef742fdb244a57aec37d7908dad931d5", + "/home/ts/.local/state/openhcs-maintenance/20261004/canonical-runtime-coherent-paired-v15-qualified/figures/matched_runtime.png": "ce860d70d499b43a4793d86769bb6444792c7c76d9a3a1581cf41b873f4aa1b7", + "/home/ts/.local/state/openhcs-maintenance/20261004/canonical-runtime-coherent-paired-v15-qualified/figures/matched_runtime.svg": "3565aba996589c62d7f22f1a8b16abdfa809421573e114b668b81cfadb608440", + "/home/ts/.local/state/openhcs-maintenance/20261004/canonical-runtime-coherent-paired-v15-qualified/figures/matched_speedup.png": "39b7b682b1afbc81096a59e68f33fe53505a85cd2eba0e9c6ce454fc0c33ac03", + "/home/ts/.local/state/openhcs-maintenance/20261004/canonical-runtime-coherent-paired-v15-qualified/figures/matched_speedup.svg": "10b29c49a1cbec487c8553666455a15e4ee14a73e10f1cf2649d2f5471ef5c60", + "/home/ts/.local/state/openhcs-maintenance/20261004/canonical-runtime-coherent-paired-v15-qualified/figures/matched_runtime_samples.png": "da3addd00420cd9756efb4a9052f30383cb2db866af9c85bc5def03c279017e3", + "/home/ts/.local/state/openhcs-maintenance/20261004/canonical-runtime-coherent-paired-v15-qualified/figures/matched_runtime_samples.svg": "e657ba206a7542cdc3f8476841a05778fd241a8e862134e5bfd689c84938d504" + } +} diff --git a/docs/source/architecture/progress_runtime_projection_system.rst b/docs/source/architecture/progress_runtime_projection_system.rst index 1f3c43b3bb..c0baab81aa 100644 --- a/docs/source/architecture/progress_runtime_projection_system.rst +++ b/docs/source/architecture/progress_runtime_projection_system.rst @@ -23,7 +23,9 @@ OpenHCS-specific modules: - ``openhcs.core.progress.projection`` and ``openhcs.core.progress.runtime_tree`` own the OpenHCS execution and tree projections. -- ``openhcs.core.progress.emitters`` owns orchestrator and step event emission. +- ``openhcs.core.progress`` emits worker events through the configured progress + queue. ``openhcs.runtime.zmq_progress`` constructs execution-server events and + owns the compiler queue adapter. Consumption path: diff --git a/docs/validation/materialization_plumbing_384_20261001.rst b/docs/validation/materialization_plumbing_384_20261001.rst new file mode 100644 index 0000000000..8125d2b4b7 --- /dev/null +++ b/docs/validation/materialization_plumbing_384_20261001.rst @@ -0,0 +1,132 @@ +One materialization batch for saving, publication and observation +=============================================================== + +This candidate addresses the generic plumbing tracked in issue #384. It is not +an accepted end-to-end performance result. The separate light owner trace bounded +eight repeated renders at approximately 0.297 seconds and metadata finalization +at 0.896 seconds; removing repeated rendering alone cannot close the generic +runtime gap. This is a structural dependency of the broader runtime boundary work. + +Ownership and production flow +----------------------------- + +``MaterializationBatch`` owns one writer-group rendering and saving algorithm; +its primary path is a derived view. ``SavedMaterializationOutputs`` owns only +completed backend outputs. ``MaterializedRuntimeArtifact`` inherits that shared +backend projection and adds the original reduced artifact binding and observation +behavior. Backend-indexed mappings contain actual destination values, not behavior +handlers. Existing WriterSpec declarations continue to determine format-specific +writing. No new runtime ledger, context cache or identity memoization was added. + +``BackendSaver`` reports only payloads accepted by each backend after successful +save calls. Failed saves raise without returning successful outcomes. Artifact +finalization passes those exact outputs to the existing nominal OutputTarget +family. Transient publication targets own the outcomes until publication finishes; +they are excluded from target equality and hashing. Image directories and source +projections consume these outputs without rendering the mutable logical artifact +again. Rendered pixel content is not carried into worker observation transport. + +The already declared ``StepExecutionObservation`` now carries actual persistent +locations and declared export paths from finalization. Ordinary worker progress +consumes returned locations; worker result observations accumulate returned paths +before image resources are released. Plate-scoped execution uses the same actual +materialization handoff. Existing ``CompiledPlateExecutionExtras`` carries its +RuntimeExecutionObservation; ``CompiledPlateExecutionResults.runtime_observations`` +is a derived collection of worker and parent observations. Both ZMQ value and +outcome exports consume that collection. RuntimeExportObservation no longer +reconstructs output paths from compiled contexts and mutable logical values. + +Terminal materializations persist without external-export participation; +streaming-only specs report no persistent destinations. Measurement reducers can +produce synthetic records absent from RuntimeValueStore; outcomes remain bound to +the record actually reduced and materialized. Main-flow manifests retain their +independent inheritance and semantic-address contracts. + +Removed code and intentionally retained consumers +------------------------------------------------ + +Removed ``_materialization_output_groups`` after moving its shared algorithm to +MaterializationBatch.render. Removed the tests-only materialized and observed +materialized path helpers, the obsolete current-runtime export-path helper, the +single-call observed-materialization wrapper, and +RuntimeExportObservation.from_execution_contexts. Routing tests now intercept +batch preparation; physical/export tests pass actual outcome records explicitly. + +Historical debug reuse still has an explicit prediction surface named +``preview_reused_*``. It does not create a new-save StepExecutionObservation. +Snapshot-owned physical receipts remain OPEN for that separate debug lifecycle; +these prediction functions are not an ordinary execution fallback. Historical +viewer expectations retain their real declaration-based rendering consumer. +Analysis consolidation retains its real CSV-content derivation consumer; it is a +separate reduction, not a replacement authority for observed export paths. + +Evidence and limits +------------------- + +Original source: 10f7e7075b412ccea8959f2c4e1aa818455149fa. NRA original syntax/class +census covers 703 modules, 5157 original ClassDefs, 5145 canonical projections and +12 retained OPEN syntax rows. The bounded ownership decision and complete census +are retained in the external benchmark evidence directory. The authored lifecycle, +new return values and argument migration exceed declaration-movement DSL proof +scope; no native behavioral equivalence proof is asserted. + +The first consumer gate retained 154 passing and 33 failing tests. Routing spies +intercepted the removed production boundary; metadata fixtures omitted the actual +output handoff. Their assertions were preserved while moving those fixtures to the +new boundary. The next six-module gate passed all 197 tests. A later parent gate +passed 264 tests with three new worker-fixture failures: the fixture failed the +existing DebugExecutionContext nominal boundary. It was replaced with a genuine +ProcessingContext subclass; the production boundary was not weakened. + +The final eleven-module gate passes 267 tests in 5.12 seconds. It includes actual +backend acceptance and failed-save controls, exact output-object reuse after +logical input mutation, rejection of re-rendering during ordinary worker progress +and export, all three runtime observation modes, pickle transport after resource +release, exact combined worker/parent export paths, materialization formats, +metadata publication/reconciliation, runtime/viewer validation and ZMQ consumers. + +The original unmodified R0 guard passes for a264ee95546ab17a3ded40f81759cc6234d08817 +against main e341ac9b55cb2b6a143df9083785b296c23000df. There are no positive debt +deltas; ZMQExecutionServer god-class excess decreases by eight lines and the +artifact materialization foreign-absence probe decreases by one. This revision +includes the normal merge of main's fixture/documentation fix; production sources +are identical to the 267-test candidate. + +Combined R1 source qualification, representative ordinary unprofiled timing and +native numerical parity remain required before promotion. No benchmark ratios or +speedup claim are attached to this receipt. + +Actual array outputs and raster publication +------------------------------------------ + +The first combined native comparison retained 28 numerically equivalent cases +and two illumination metadata failures. The saved illumination NumPy arrays were +actual outputs, but their NumPy-only directory had incorrectly become eligible +for raster image inventory publication. The existing FileManager inventory +includes declared raster formats; NumPy array exports are outside that inventory. +The candidate had removed OutputTarget's inherited ``contains_images`` admission +gate while switching directory discovery to actual saved outputs. + +The correction restores that existing nominal gate. Actual NumPy saved outputs +and their observation locations remain intact; publication and completed-plate +reconciliation consume only directories with images in the existing inventory. +No second format registry, rerendering fallback or empty source projection was +introduced. + +Independent controls use a real FileManager and physical NumPy-only and mixed +TIFF/NumPy outputs. The original candidate fails the NumPy-only control with the +same empty SourceProjectionSet error; its mixed-directory control passes. Both +controls pass after restoration, verifying exact saved pixels, actual observation +paths, raster-only inventory and typed calibration. The focused red and green +receipts are ``materialization-npy-publication-red-v3-20261001.log/xml`` and +``materialization-npy-publication-green-20261001.log/xml`` in the external benchmark +evidence directory. Earlier import-order and typed-unit fixture errors are also +retained separately; they are harness failures, not the product regression. + +The expanded eleven-module consumer gate passes all 269 tests using only the +original nominal viewer route fixture from the root test configuration. Two +initial broader invocations retained 264 passes and five missing-fixture setup +errors; the corrected fixture registration preserves those same five controls. +The final receipt is ``materialization-npy-publication-consumers-v3-20261001.log/xml``. +Full native parity and fresh accepted timing remain required for the corrected +combined source; the original 28-pass/two-error receipt is not replaced. diff --git a/docs/validation/persisted_result_publication_134_20261002.rst b/docs/validation/persisted_result_publication_134_20261002.rst new file mode 100644 index 0000000000..fe8e061086 --- /dev/null +++ b/docs/validation/persisted_result_publication_134_20261002.rst @@ -0,0 +1,47 @@ +Saved-result publication through the existing output owners +========================================================== + +PR394 integrates the source proposal supplied by PR404 (issue134), against +shared runtime source4afd51415. Successfully saved result directories participate +in publication even when their files are not raster images. This changes the +shared publication contract, not an ROI-specific writer or a function case. + +Existing OutputTarget owns guarded contains_outputs and a stored_output_paths +hook. RuntimeArtifactMetadataTarget overrides that hook for all saved formats; +no additional capability class is needed for its sole existing consumer. +The original MaterializationBatch saved outcomes determine runtime destinations. +Publication cannot rerender a mutable batch or invent an outcome from unrelated +filesystem files. Exact plate-relative result-directory ancestry is retained. +Final reconciliation derives previously declared directories from the existing +OpenHCSMetadataHandler after runtime values have been released. + +AtomicMetadataWriter remains the single transaction. It constructs image +component projections only for nonempty addressed image sets. SourceProjectionSet +retains its nonempty invariant, and actual saved images without produced source +addresses still fail without changing the metadata document. Result-only +publication produces an empty image inventory and projection, not an invented +image or source address. Existing format inventory remains authoritative. + +The current-source original control reproduces four failures and one pass. +The actual two-owner implementation passes89 publication, checkpoint, metadata +and materialization-journey tests. Five source cases exercise real bundle writer +saving, simple and nested result-only directories, original public result queries, +reconciliation after release, byte-exact refusal of unaddressed images, and a +new independently declared target with cooperative publication hooks. Its test +declaration explicitly requests its own registry key and restores the complete +registry after use; the initially inherited-key test contamination is retained. +The existing NumPy export control now requires a declared result destination +with empty raster inventory, instead of incorrectly requiring no metadata file. + +The NRA owner inventory joins137 original declarations across the selected +existing owners, scans1,498 caller modules without parse failures and records +alternative owners and open binding leads. Those syntax facts are not proof of +runtime binding or an architecture-gate pass. Original-source failure, failed +initial test path, registry-contamination failure, corrected consumer gate and +inventory receipts remain in the shared benchmark-runs workspace under +pr394-roi-publication prefixes. + +This is saved-output admission correctness and establishes no performance gain. +Synthetic archive bytes do not establish native ROI geometry, scientific pixels, +source provenance reopening or complete issue134 graph acceptance. Those broader +PR404 gates remain open. No additional scientific pipeline is executed here. diff --git a/docs/validation/prepared_callable_signatures_419_20261002.rst b/docs/validation/prepared_callable_signatures_419_20261002.rst new file mode 100644 index 0000000000..e987dab3b9 --- /dev/null +++ b/docs/validation/prepared_callable_signatures_419_20261002.rst @@ -0,0 +1,54 @@ +Prepared callable signatures and raw argument admission +====================================================== + +Registered argument contracts belong in function-library warmup before server +readiness. Newly authored declarations prepare before compiler validation and +resolve once per compilation. Invocation must consume those prepared contracts. +This is a correctness/preparation dependency of the plumbing work, not a claim +that signature caching alone removes multiple seconds. + +CallableMetadata carries the resolved canonical inspect.Signature. Parameter +names, annotations, defaults and semantic controls derive from that declaration. +Preparation publishes it only after every registered preparation hook finishes. +FunctionReference and existing namespace/pickle/cloudpickle transport retain it. +The compiler reuses registered snapshots and captures fresh authored snapshots; +the old late invocation preparation is removed. + +Actual boundary inspection found that most CP raw targets differ from their +semantic signatures because injected controls are absent from the raw function. +The existing metadata owner therefore also carries a raw-runtime Signature only +when required by that distinct boundary. Identical boundaries reuse canonical; +default objects are retained by identity and never compared through value equality. +Existing invocation and batch-request owners receive the exact raw view for +filtering/defaults. Three independent signature/default/type LRUs and the obsolete +signature-parameter helper are removed. Unprepared authoring and distinct generic +wrapper queries remain live. Explicit library rewarm or supported declaration +invalidation refreshes registered snapshots; arbitrary direct annotation/default +mutation does not retroactively rewrite compiled contracts. + +Raw array admission is derived from the callable's declared nominal type, including +unions and Annotated. The adapter retains context until the actual raw boundary. +Array-only callables receive pixels; declared RuntimeArrayData consumers retain +metadata. Their truthful annotation migration changes no scientific function body, +defaults or decorators, as checked across all 19 affected CP modules by AST. + +Controls: 646 passed, 5 existing skips, 2 existing warnings. They cover preparation +ordering, rewarm/new compilation, request bindings, custom signatures/defaults, +transport, and 12-plane compiled execution with all signature/hint queries forbidden. +An additional 75 publication/real-payload controls pass, including actual compiled +ColorToGray spatial-mask/channel collapse, MedianFilter intensity scale/mask and +IdentifySecondaryObjects source coordinates/provenance. + +The final real isolated registry check prepares 267 catalog entries and 976 targets; +all 267 contracts have snapshots, with zero missing signatures and zero subsequent +owner signature/hint resolutions in contract queries/projections. Its 16.67s +cached-startup duration is diagnostic startup and excluded from pipeline clocks. +The earlier fresh-cache 91.01s startup check remains separately preserved. + +Evidence is retained under /home/ts/code/projects/openhcs-benchmark-runs: +issue419-shared-signature-closure-final-receipt-20261002.json, +issue419-actual-shared-signature-closure-readiness-20261002.json and +issue419-truthful-annotation-actual-source-consumers-20261002.json. Earlier failed +intermediates are retained. Current all-case scientific parity and ordinary +performance are separate pending gates; earlier 90c30 timings do not qualify this +new source or updated shared dependencies. diff --git a/docs/validation/shared-dense-coordinate-owner-20261002.rst b/docs/validation/shared-dense-coordinate-owner-20261002.rst new file mode 100644 index 0000000000..4d865af45f --- /dev/null +++ b/docs/validation/shared-dense-coordinate-owner-20261002.rst @@ -0,0 +1,111 @@ +Shared dense coordinate reduction +================================ + +The shared reducer is integrated into PR394 for issue #384. The isolated +qualification source was ``d5441f960fb4cafe5a1f56740cf8c52de7a7d69d``, normally +merged with qualified PR394 ``eb2f23efd`` and main ``a6c18f054``. Integrated +controls use clean ``6e69b85122d3c1a44857835ba9b3fe77e743240d``. + +``ObjectLabelStorageStrategy`` retains the genuine sparse-IJV algorithm and +owns shared sum allocation/division. The existing dense leaf specializes int32 +2D/3D arrays; ``ObjectLabelValueStorageStrategy`` delegates actual storage. +Tracking and relationships consume one core numerical primitive through their +existing ABI adapters. Their two duplicate kernels are deleted, with all five +compiled consumers migrated. No new class, registry, dispatch table or cache +was introduced. + +Before a public domain iterator can mutate pixels or raise, the dense leaf +captures coordinate moments from a borrowing strided 3D view. The existing +``DenseIntegerObjectLabelIdDomain`` bounds moment allocation by the number of +positive pixels. Empty or large sparse ID spans use the original sparse path; +a lone ID ``2**31 - 1`` therefore reaches the original domain error without +allocating a max-ID-sized table. Unsupported dtypes/ranks retain original +conversion, warnings and errors. Readonly, reversed, Fortran and zero-stride +inputs avoid flatten copies. This establishes an O(nnz) allocation bound, not +identical heap thresholds under OOM or a resolution of issue #433. + +Existing provider/callable preparation warms C/F/A writable and readonly +signatures before execution. An isolated PrimaryObjects preparation control +refuses both compilation and cache loading during subsequent admitted calls. +Controls preserve effectful Sequence iteration, NumPy allocation-phase errors, +NaNs/counts, independent result buffers and input mutation/alias semantics. +Eleven effect controls also run against the actual unchanged Git parent. + +Qualification +------------- + +* Isolated synchronized controls: 100 passed, 2 existing skips. +* Integrated controls at ``6e69b85122``: 101 passed, 2 existing skips in + 194.57 seconds; tracked source hashes remain unchanged. +* Original scoped R0: every metric delta zero; original R1: no increases, + unchanged 160-second budget. Both compare ``eb2f23efd`` to ``d5441f960``. +* Global NRA census: 5,526 original classes, 5,513 canonical declarations, + 13 explicitly OPEN syntax rows, no parse errors. +* Saved real Wound pair: exact coordinates/counts and physical allocation/ + alias gates; original median 0.160669 s, candidate 0.019144 s, local saving + 0.141524 s across paired replay. Preparation/JIT precede timing. +* Twenty-one saved Track frames and old-Git tracking/relationship numerical + ABI comparisons pass. This is not a full relationship transaction proof. + +Initial admission, readiness and high-ID negative evidence remains retained. +These local results alone do not establish ordinary pipeline performance. +Root-owned ordinary qualification is recorded separately below. Illumination +has no centroid calls. + +Evidence: ``/var/tmp/openhcs-shared-dense-coordinate-owner-closure-v2-20261002.json``; +``/var/tmp/openhcs-shared-dense-production-saved-replay-v4-20261002/receipt.json``; +``/var/tmp/openhcs-pr394-integrated-dense-coordinate-controls-20261002.log``. + +Ordinary integrated comparison +------------------------------ + +Four uninstrumented public sweeps in ABBA order compare frozen b4700288f +(shared geometry baseline) with integrated 6e69b8512 (shared coordinate owner). +Each case has one well, inline worker and thread on CPU5, default OUTCOMES +and memory observer, and a reused READY server. Server/library/kernel startup +and shutdown are excluded; compilation remains in total. No samples are removed. + +Two-sample descriptive means (seconds; not statistical significance): + +* ExampleWoundHealing: execution 3.287030339 -> 2.984141707; + compilation 0.337689161 -> 0.340739846; + total 3.866369809 -> 3.562642806. +* ExampleTrackObjects: execution 5.338271976 -> 5.052027345; + compilation 0.929434419 -> 1.252314091; + total 6.629491309 -> 6.684317434. + +Track total regresses by 0.054826125 seconds in this comparison. Its compilation +increases by 0.322879672 seconds; no causal late-JIT attribution is established. +Wound total decreases by 0.303727004 seconds. Neither result satisfies the +remaining whole-pipeline objective or replaces the generic-plumbing frontier. + +Every observation, in case/compile/execution/total seconds: + +* 0-A ExampleTrackObjects: 0.950359821, + 5.625208855, 6.914708113. +* 0-A ExampleWoundHealing: 0.343463182, + 3.276733875, 3.827193568. +* 1-B ExampleTrackObjects: 1.421878338, + 5.020748138, 6.829343345. +* 1-B ExampleWoundHealing: 0.342035055, + 3.044292212, 3.623388787. +* 2-B ExampleTrackObjects: 1.082749844, + 5.083306551, 6.539291524. +* 2-B ExampleWoundHealing: 0.339444637, + 2.923991203, 3.501896825. +* 3-A ExampleTrackObjects: 0.908509016, + 5.051335096, 6.344274506. +* 3-A ExampleWoundHealing: 0.331915140, + 3.297326803, 3.905546051. + +All eight complete authored-output inventories, strict table/image comparisons, +scientific file bytes and source/environment/native/input freezes pass. Wound +retains full native qualification through the exact qualified output reference. +Track preserves all original OH bytes and its original 77,726-pixel native RED; +this does not include the separate draft renderer repair in PR468. No parity +tolerance, exclusion or output policy changes. + +Receipt: ``/var/tmp/openhcs-pr394-shared-dense-ordinary-abba-science-20261002.json`` +SHA256 ``affb93c5955585be6963936552a1f40da051989688e7b0c58f406f398e894400``. +Commands: ``run_pr394_shared_dense_ordinary_abba_20261002.py`` and +``validate_pr394_shared_dense_ordinary_abba_science_20261002.py`` under /var/tmp. diff --git a/docs/validation/shared_runtime_plumbing_384_20261001.rst b/docs/validation/shared_runtime_plumbing_384_20261001.rst new file mode 100644 index 0000000000..ef92751224 --- /dev/null +++ b/docs/validation/shared_runtime_plumbing_384_20261001.rst @@ -0,0 +1,2178 @@ +Shared runtime plumbing qualification +==================================== + +Issue #384 covers repeated source resolution, metadata construction and artifact +rendering outside callable execution. This branch combines three production +dependencies under their existing lifecycle owners. It does not yet establish an +end-to-end speedup. + +Primary target and abstraction admission +--------------------------------------- + +The primary performance goal is shared runtime work outside callable execution: +invocation and adapter preparation, stack loading, output registration, +finalization, saving, publication and provenance. Each existing abstraction must +own a distinct invariant, behavior or useful validated view. Objects that only +forward or reconstruct facts already owned elsewhere should be removed, with +consumers deriving directly from the determining owner. Shared algorithms belong +on existing nominal ancestors; a new class is not evidence of improved ownership. +Small measured redundancies are folded into the coherent migration even when +they cannot independently close the performance gap. + +The ordinary 3D probe at clean revision 5d2fd489946e6885f161a7379e4eec1d14e307fd +records 9.860550 seconds of public server execution. Its same-thread root takes +9.757393 seconds, including 4.097127 seconds at runtime callable boundaries and +5.118847 seconds elsewhere inside steps. Final plate publication adds 0.476819 +seconds. The callable boundary includes target resolution and signature filtering; +it is not an exact naked-kernel timer. Execution is inline for this one-worker +configuration; a configured fork policy does not imply a separate worker process. + +A deeper probe on the same source records 10.275668 seconds, including 0.023519 +seconds of explicitly isolated input capture. Its nonoverlapping coarse phases +locate 0.697612 seconds in output recording, 0.478745 in image-request preparation, +0.795071 in three atomic publication transactions and another 0.143612 in durable +target reconciliation. Remaining loading and output-registration work takes +0.739507 and 0.722780 seconds respectively. Stack metadata composition takes only +0.102824 seconds across all consumers. These diagnostic clocks locate work and +must not substitute for an ordinary uninstrumented paired comparison. + +Required output work remains included: this pipeline saves 120 TIFF planes and +six result CSVs. Some work outside the callable boundary is numerical table +assembly or actual saving, so the full noncallable duration is not asserted to be +removable indirection. Nine stack-composition calls belong to loading; nineteen +belong to unstacking. Aggregate composition counts do not establish cache misses. + +Saved real-payload replays confirm that duplicated input/name resolution and +rebuilding a compiled callable contract have small individual payoffs: about +0.112 milliseconds per input pair and 4.386 milliseconds per 211 resolutions. +These are included for ownership cleanup, without attributing the larger adapter +gap to them. The direct cache payload migration removes +``RuntimeImageStackCacheValue``, which owned only a forwarded ``stack`` field; +the cache retains path/memory identity, invalidation and execution lifetime. +All 102 related lifetime/source-projection controls pass for that migration. + +Complete saved atomic publication transactions retain actual parser, labels, +saved paths, pretransaction JSON, locking and filesystem writes. Deriving +geometry from the already decoded nominal projections reduces a 60-path +transaction from median 0.13556 to 0.07601 seconds and a 120-path transaction from +0.27224 to 0.15354 seconds, with byte-identical complete JSON. The production +implementation also reproduces both baseline byte hashes, and 57 metadata, +projection and image-output controls pass, including pruning, concurrent partial +inventory updates, fresh geometry and atomic rollback. This is stage replay +evidence, not an end-to-end speedup claim; integrated qualification remains in +progress. + +The existing CellProfiler executor now resolves the compiled raw callable once +at its validated invocation boundary and passes that target through the existing +processing and slice dispatch. The existing callable-view policy accepts that +already resolved target; no additional generic invocation type or parallel +contract/callable fields are needed. Image source-name projection consumes the +already resolved payload through the existing artifact strategy family. + +The executor does not own a second interpretation of input relations or returned +artifact contexts. ``ArtifactSpecCollection`` derives exact broadcast indices +from its ordered declarations; ``RuntimeReturnedOutputMatcher`` contextualizes +the compiled canonical return ABI. ``AlignedImageStack`` binds the complete +declared output roster to its exact slice contexts in one linear traversal. The +old CP and canonical-values helpers are deleted. The existing contract, +collection and returned value determine these answers directly. + +The deeper clean-source probe at 5d1f1a781eda851b4783b68db342b76eeef9dea9 records +10.053237 seconds of public execution, including 4.465789 seconds at the callable +boundary and 4.939001 seconds elsewhere inside steps. Loading takes 0.699904 +exclusive seconds, image recording 0.519127, output identity 0.412492 and image +request preparation 0.388981. Explicit diagnostic capture costs 0.044853 seconds. +These partitions are diagnostic evidence, not accepted A/B measurements. + +All 23 produced-stack cache hits correspond to previously stored output paths. +The nine misses are original inputs; seven repeat earlier source reads and cost +0.5149 seconds inclusively. Those inputs are already in memory. Caching their +mutable arrays by path alone is rejected: storage has no mutation revision and +loaded source semantics depend on binding, aliases and plane contracts. + +The next shared route is metadata ownership, rather than a second pixel cache. +Changing spatial context, intensity or image names repeatedly constructs source +provenance and copies/fingerprints its component mapping. Source loading and CP +image recording consume this common path. The saved typed ImageMath fixture +retains actual nested mapping ownership for a cold-promotion and complete-workflow +replay. An isolated query-cache payoff does not admit this migration. CP-recorded +outputs already bypass generic postprocessing; removing that hypothetical second +contextualization would not affect the measured recorder. + +The unmodified-main light trace located about 3.44 seconds in loading, unstacking, +saving and finalization for the representative 3D pipeline. CP request and output +context construction account for another approximately 1.216 seconds. These are +diagnostic bounds, not additive nested timer totals or accepted benchmark clocks. +Repeated artifact rendering alone is bounded at about 0.297 seconds; saved plane +projection replay estimates about 0.20 seconds for that individual component. +Neither is admitted as a sufficient standalone performance route. The integrated +boundary must demonstrate a material improvement in ordinary execution. + +Production authorities +---------------------- + +``ImageMetadataProjection`` owns the common single-pass image metadata algorithm. +Source-plane and leading-axis specializations provide their declared projection +semantics through inheritance. Provenance constructors consume the actual +``SourceImageProvenance`` constructor defaults, avoiding absent-field allocation +without a second default roster. Mutable scalar payload metadata retains its +independent ownership and mutation controls. + +``SourceMetadataRecord`` owns declared/parser/rule resolution. Its declared leaf +retains live input semantics, while its resolved leaf enforces owned immutable +metadata at construction. ``RuntimeSourceResolutionSnapshot`` belongs to the +existing context-local runtime source cache and retains its determining inputs. +Only the explicit execution factories take this boundary; direct constructors and +unknown paths preserve live resolution. Derived caches are discarded on process +transport. The original adapter provenance construction remains authoritative: +deep-freezing selector records must not change repr-based image identities. + +``MaterializationBatch`` owns rendering and saving. Actual saved outputs flow into +the existing metadata target family, step observation, worker observation and +plate observation. Export paths derive from these outcomes after payload resource +release. Removed rerender helpers and the old context-derived export path API have +no remaining consumers. Historical debug reuse retains explicitly named previews; +these do not claim new successful saves. The component receipt describes the +retained CSV consolidation and independent viewer expectation consumers. + +Qualification and disposition +---------------------------- + +The integrated source passed 1,362 behavioral tests. Each of the three components +passed the original unmodified R0 guard. Final combined R0/R1 passed against main +91dc52d4040890e1b88494acba7368196f6cd1e8 at tested source +dc1a371b06079ff249c8c6432953d21e0c05917b, without increasing debt allowances or +source checks. The main synchronization passed 85 help/output/source-resolution +controls. These source ratchets are scoped guards, not a formal proof of every +dynamic binding. + +The subsequent ownership/publication follow-up normally merges main +76a2d392056f4fa6cc74bc122a552edc32f24239 at candidate +84057fbefd0ad5469c766051e19b34f42e851102, including the declaration-owned +classification and singleton image-selection repairs. All 955 controls across +26 changed-path and relevant main-owner test files pass, with two existing +watershed warnings. Original unmodified R0 and R1 pass against that main, with +no metric budgets or exclusions changed. The R1 scan uses the current NRA +checkout's virtual environment and its original 120-second deadline. Earlier +failed owner-growth/context-inspection guards and the wrong-interpreter import +failure are retained. Evidence: shared-plumbing-final-local-gates-20261001.json +and the original R0/R1 logs in the external evidence directory. + +The first complete saved-native gate exposed two illumination-correction +publication failures: actual numeric NPY saves admitted directories without any +raster images into metadata publication. The inherited raster-inventory admission +now governs directories derived from successful saves. A real FileManager NPY-only +control reproduced the failure; a mixed TIFF/NPY control preserves exact pixels, +raster inventory, alias and calibration. All 269 related controls passed. The +repaired full gate completed: all 30 cases equivalent, zero differences. The +original 28-pass/two-error gate is retained. + +Repaired ordinary ABBA evidence +------------------------------ + +Two main and two candidate observations per case were retained, without excluding +samples. Revisions are the exact dc1a371b/91dc52d4 sources above. In seconds: + +========================= ======================= ======================= +Case Mean execution Mean pipeline total +========================= ======================= ======================= +3D monolayer 10.278553 -> 9.657654 12.241441 -> 11.607624 +Imaging Flow Cytometry 15.506204 -> 15.423871 17.719883 -> 17.949389 +Advanced segmentation 8.658128 -> 8.887496 11.158074 -> 11.397346 +========================= ======================= ======================= + +3D execution improves 6.04%, while advanced execution regresses 2.65%. The default +memory observer's mean peak process-tree RSS changes by +14.65% for 3D, -3.41% for +Imaging Flow Cytometry and +10.87% for advanced segmentation. Process-tree RSS can +count shared fork pages repeatedly; these figures do not prove distinct physical +allocation. Candidate memory varies substantially between the two observations. +This is mixed evidence, not an accepted broad optimization. PR394 remains draft. + +The pre-publication-repair eight-sweep observations remain retained separately; +their larger improvement is not substituted for the repaired source's results. +External evidence: shared-runtime-plumbing-repaired-qualified-abba-summary- +20261001.json and every corresponding source/input/observation receipt in the +openhcs-benchmark-runs evidence directory. + +Existing-owner follow-up ordinary ABBA +------------------------------------- + +The synchronized follow-up compares main 76a2d392 against candidate d9c9f8fe4. +The candidate's production source is the locally qualified 84057fb revision; +subsequent changes only retain the qualification receipt. Two observations per +side use the same ordinary public path and retain every sample. In seconds: + +========================= ======================= ======================= +Case Mean execution Mean pipeline total +========================= ======================= ======================= +3D monolayer 11.173033 -> 9.979570 13.166303 -> 11.915196 +Imaging Flow Cytometry 16.847054 -> 18.891492 19.058024 -> 21.417949 +Advanced segmentation 8.802229 -> 8.616838 11.271471 -> 11.113117 +========================= ======================= ======================= + +3D execution improves 10.68% and advanced execution 2.11%, while Imaging Flow +Cytometry regresses 12.14%. Its candidate observations are 17.371243 and 20.411741 +seconds, compared with 17.554674 and 16.139433 for main. Compilation is also +inflated in the slower candidate sweep. These samples establish mixed evidence, +not a statistical significance or causal attribution; PR394 remains draft. + +All 24 ordered Imaging Flow Cytometry step occurrences align. Most of the extra +time is inside steps, distributed across the slower candidate sweep. Between-step +gaps remain about 0.017-0.023 seconds; execution outside the complete step span +does not explain the regression. Existing output comparisons and shared metadata +ownership investigation continue before promotion. Evidence: +shared-plumbing-owner-followup-qualified-abba-20261001.json and its summary, +source receipts and all per-step/progress observations. + +Across all six run pairs, Imaging Flow Cytometry's two header rows and all +1,800-by-527 measurement cells match exactly. All six 3D CSV schemas, rows and +cells match, as do all 120 TIFF arrays, shapes and dtypes. Ordinary output +inventories match. Outcome-wire differences are fresh execution UUIDs and actual +run-root path prefixes; no scientific values are present in those outcome views. +Advanced's database/properties were not numerically compared, so absence of +ordinary CSV/TIFF output does not establish its parity. Evidence: +shared-plumbing-owner-followup-abba-step-output-audit-20261001.json. + +The next normal synchronization integrates main +0d07909b07870557a04f125452dc6944db77cb6c, including PR358's startup feedback and +worker-budget repair, at candidate fdf50241aa9adc6d96bc9c530dcc9acd19692b64. +The recorded ZMQRuntime dependency 668edafcb5ee530a163377c936431ae1e8334e85 is +checked out in both trees and consumed through the shared editable environment. +All 498 preparation/startup/CP integration controls pass, with six skips and two +existing warnings; original R0/R1 pass with unchanged budgets and exclusions. +Issue355 is closed by its existing merged PR. The ABBA remains pinned to its +measured sources; no timing result is projected through this synchronization. +Evidence: shared-plumbing-main355-local-gates-20261001.json. + +Subsequent normal synchronization consumes documentation/knowledge changes in +main PR405 and PR406, through e66500e7ae3804abca1396681c50e1cef5e9a11e. These merges +do not change production source or dependencies. All 23 knowledge-transfer controls +pass on the final merged declarations, with two existing warnings. Benchmark and source-gate +observations remain pinned above. + +Independent review of the isolated metadata-owner migration found the important +distinction between ordered selection-record equality and public mapping-content +equality. It also checked duplicate stringified keys, normalization error order, +output-extension insertion order and fields-only transport. That migration remains +outside this PR until the affected consumers preserve their existing semantics +and the complete production-owner replay and source gates pass. Review evidence: +source-metadata-owner-independent-review-20261001.json. No stage replay is promoted +as an end-to-end gain. + +Fresh native qualification and next dominant route +------------------------------------------------ + +The revision-pinned matched Imaging Flow Cytometry driver completed three observed +native CP/OpenHCS repetitions and one warmup. All observed repetitions have zero +output differences under the existing numerical tolerances, exact discrete/schema +checks and strict declared output inventory. The input is one well with two native +image sets, one OpenHCS worker and one native job; the configured worker start +method is fork. Native and candidate phase boundaries are retained separately. +The driver's timing_claim explicitly remains none until first-module/first-axis +boundary equivalence is qualified. No native throughput ratio is asserted here; +the physical 3D volume/plane consumer gap also remains unfinished. + +Fresh paired diagnostic traces cover all three workloads with identical owner +hooks. Their high-frequency instrumentation perturbs costs, so these are authority +and call-count evidence, not accepted timing clocks. The 3D trace reduces +SourceImageIdentity construction from 142,412 to 78,769, but still calls +SourceMetadataRoleView.scalar_items 194,349 times and source metadata field identity +1,120,064 times. Image-processing invocation remains approximately unchanged in +these traces. Repeated metadata queries are the next potentially material generic +route; saved representative replay must establish its transferable payoff before +another production authority is admitted. Immutable query ownership must retain +live public mapping behavior, lazy validation, alias/role semantics and image +identity fingerprints. + +Source snapshots structurally retain historical projection owners, but output +publication does not normally replace these workspaces' cached metadata documents. +The observed RSS increase is therefore not attributed to snapshot generations. +Rendered outputs also remain visible through immediate publication; many arrays +already belong to runtime storage. Per-process memory and ownership diagnostics +must distinguish extra references from newly allocated buffers before changing +that boundary. + +The subsequent normal main396 merge changes documentation, knowledge resources +and five knowledge-transfer test assertions. OpenHCS production source bytes are +unchanged from the corresponding measured candidate and baseline revisions; the +existing source/benchmark evidence remains pinned to its original revisions. + +Issue and branch audit +---------------------- + +The source components are integrated in actual draft PR394, formally linked to +issue384. A branch/history audit covered 46 local worktrees and 194 remote branches; +the two subsequently created branches have PR396 (merged) and PR397 (draft). +Current branch tips were checked beyond historical PR association, including exact +source patch equivalence for squash/rebase history. No additional useful +unpublished fix branch was identified. Rejected prototypes and obsolete planning +branches are not nominated as unfinished production fixes. + +The subsequent complete audit verifies eight of 26 open issues have formal +closing PR references and exact manual ConnectedEvent entries; 18 still lack an +actual complete fixing PR. Mere cross-references and diagnosis-only drafts are +not counted. The pairs are 138/207, 213/217, 320/217, 355/358, 384/394, 386/388, +395/397 and 398/399. For the three automatically detected links whose manual +mutation was initially a no-op, the exact original PR bodies were restored after +the manual links were created. Head, base and draft state were preserved. +Audit evidence: official-development-link-final-20261001.json/.md, +manual-development-relink-exact-events-v3-20261001.json, +remaining-remote-branch-pr-audit-20261001.json and local-worktree-branch-inventory- +20261001.json in the external evidence directory. Counts describe that pinned +audit rather than future repository state. + +The earlier runtime-plumbing prototype 2253ec63b is rejected. Its paired timing +did not establish a gain and its original R0 gate failed. It is not part of this +branch or the accepted evidence. Failed controls and diagnostic observations are +retained in the external benchmark evidence directory rather than replaced with +the fastest observations. + +Pipeline clocks exclude ZMQ server startup, mandatory registry/kernel prewarming +and shutdown. Timed runs use the ordinary public OUTCOMES path and default memory +observer, without profiling injection. Candidate and baseline must have frozen +clean source revisions and the same dependencies, affinity and environment. + +Global lifetime counterfactuals: rejected routes +---------------------------------------------- + +The next ordinary diagnostics and exact saved-input replays reject several +insufficient standalone routes before further implementation. These are payoff +bounds, not candidate speedups. Their observations remain revision-pinned; they +do not supersede the mixed ordinary ABBA above. + +* The eight complete saved IFC geometry owners take 0.4745 seconds in aggregate + median replay; the actual complete spreadsheet renderer takes 1.3662 seconds. + Even eliminating both separate phases has an optimistic ceiling below two + seconds. The isolated geometry/export route is stopped. +* On main 18317499be069fbe58387137f326ac7b6ff57988, all 634 original Advanced + measurement queries take 0.6422 seconds, while complete CPA collection takes + 1.1943 seconds. Fabricated missing-cell counts alone do not admit this route: + eliminating both whole phases still cannot supply two seconds. The saved + query capture is a bounded subset, not a substitute for the complete clock. +* On that same main revision, all 32 3D stack loads and all saves take 0.9927 + and 0.9526 exclusive diagnostic seconds respectively. Eighteen loads select + an actual previously stored named producer; all eighteen allocate independent + main-flow pixel buffers. The full saved step-14 Resize input matches the + stored Monolayer pixels exactly, but differs in filename-derived extension + and per-plane source-name metadata. Direct value reuse would violate existing + buffer isolation and provenance. A narrow named-handoff migration is stopped. +* A low-overhead aggregate diagnostic on that revision measures all 40,673 + ``ImagePayloadMetadata.__post_init__`` calls at 0.8919 inclusive seconds and + all 147,354 ``SourceImageIdentity.__post_init__`` calls at 0.5544 inclusive + seconds. These totals overlap and must never be added. Constructor count + contraction alone cannot justify the multi-second target, even though counts + identify repeated work. The proposed 44.6 percent birth reduction is not a + measured speedup. The wider field-derivation lifetime remains unqualified. + +Every diagnostic uses the ordinary OUTCOMES path, one worker/thread and the +default memory observer. Hook overhead is retained; server startup, prewarming, +compilation and shutdown are outside execution. Exact original-method timing +does not establish that the whole measured duration can be removed. Controllers, +source/dependency freezes, successful outputs and failed earlier captures are +retained under ``/var/tmp`` and the external benchmark evidence directory. + +Evidence: ``measurement-lifetime-actual-input-baseline-replay-20261001/receipt.json``, +``global-plumbing-three-workload-coarse-lifetime-20261001.json``, +``runtime-value-handoff-step14-fixture-metadata-inspection-20261001.json``, and +``metadata-initialization-aggregate-decision-20261001.json``. The full query and +handoff observations reside in their corresponding ``/var/tmp`` captures. + +Main 9a04107492ad90233394cf17524d0ca8e74062bb is normally integrated, including +the merged native-module source-discovery repair in PR416 and source projection +capability repair in PR418. Earlier behavior/source/performance gates retain +their exact source pins. PR394 remains a draft formally closing issue384. + +The next bounded union-depth diagnostic on that main measures 3.6594 seconds +across selected metadata construction, provenance projection, component/literal +field lookup and merges. Its 972,354 selected calls enter 102,445 outer selected +regions; nested work is timed once and the final depth is zero. It retains hook +overhead, includes metadata inside callable wrappers and excludes physical +processing, I/O, complete writer preparation and publication ancestors. Thus +this is a plausible wider counterfactual scope, not 3.6594 recoverable seconds. +Reflection controls compare original and wrapped constructors: hints and errors +agree, including the original generated image-metadata constructor's existing +``NameError('InitVar')``. Actual provenance mapping decode succeeds through the +hooks. The next gate is an ordinary production comparison against the existing +nominal immutable-field owner, before further implementation or broad gates. +Evidence: ``metadata-lifetime-union-production-counterfactual-admission-20261001.json`` +and ``metadata-lifetime-union-reflection-pair-control-20261001.json``. + +Initial ordinary complete-field-owner counterfactual +--------------------------------------------------- + +The existing immutable field-owner migration is now included in this draft, +rather than left on an unpublished independent branch. ``SourceMetadataFields`` +owns the common algorithms; live declared fields and owned resolved/durable +fields provide their actual lifetime through inheritance. Owned builtin values +permit local derived-view reuse, indexed lookup and readonly snapshot reuse. +Raw mutable mappings retain fresh derivation. The obsolete role/identity view +types and duplicate field algorithms are removed. Fields-only transport drops +process-local derived caches. + +One initial ordinary, uninstrumented 3D pair compares main +9a04107492ad90233394cf17524d0ca8e74062bb against the complete candidate +401cd69fa718d6b19ce4dc35fb5f7c2d70f2d219: + +=================== ============ ============ +Metric Main Candidate +=================== ============ ============ +Execution 11.6153 s 8.1170 s +Compilation 2.2212 s 50.7997 s +Pipeline total 14.5439 s 59.6670 s +=================== ============ ============ + +Execution improves by 3.4984 seconds in this initial pair; total time regresses +by 45.1231 seconds. All six actual result CSVs have exact rows and all 120 TIFF +arrays have exact dtype, shape and pixels, with equal complete inventories. +This is an initial counterfactual, not accepted ABBA or all-case native parity. + +The compilation regression is not startup time: 239 Numba cache files are written +after axis compilation, over 48.2219 seconds, ending immediately before compilation +completes. The cold candidate source-path kernel cache exposes a startup regression. +Commit 2b86bfbe49f36d302dcd67c5b0a0cb4f656f1eb0 implemented registry kernel warming; +ffba8426cefcaa87b6b00ff056e4cb96855233e4 in PR358 subsequently removed that loop +and deferred readiness to selected compilation. PR420 restores the existing registry warmup lifecycle and closes issue162. +Its separate empty-cache regression gate is recorded below; the integrated +field-owner performance still requires requalification. + +The field-owner integration into this draft passes 81 scoped lifetime/ownership +controls with metaclass-registry 0.2.2. A subsequent projection correctness repair +passes 173 scoped controls in its isolated source. It restores source-plane +derivation and cross-invalid field/error ordering before leading-axis guards, +shares normalization on the existing metadata owner, and deletes premature +projection properties. That repair requires performance requalification; the +initial pair is not projected through it. Arbitrary external constructor/mapping +callback equivalence remains an OPEN obligation, not a claimed proof. + +Evidence: ``metadata-owner-ordinary-pair-output-parity-20261001.json``, +``metadata-owner-cold-compilation-regression-cause-20261001.json``, +``source-projection-order-384-correctness-patch-20261002.json``, +``/var/tmp/openhcs-metadata-owner-ordinary-pair-20261001/observations.json`` and +``/var/tmp/openhcs-integrated-metadata-owner-scoped-gates-20261002.log``. +Main 25d56ae3fb9b80acda80f3cf4e1c8667939147eb is normally merged; the shared +environment and PR submodule consume the declared published metaclass-registry +0.2.2 source 393a7e03003cdc56df9013f932ed4f26e632d77a. Earlier observations retain +their measured source/dependency pins. + +Restored registry readiness on main +---------------------------------- + +PR420 merges the startup correction to main +107498cfacf3b12d926c55f84c4b3cb7c04aa50f. That main is normally merged into +this performance branch. Existing affinity admission, cancellation ownership +and compiler guards for declarations introduced after startup are retained. + +An ordinary, uninstrumented 3D 1w_1t run at fix source +e55e2ec0bc98ad750837cd4dcfd830ad04096286 starts with a new empty Numba cache. +Compilation is 1.720214 s, execution 11.151797 s and pipeline total 13.637182 s. +All 481 cache files are written before pipeline submission; the last write is +6.001317 s before run creation and no cache files are written during compilation +or execution. Server startup, warmup and shutdown are excluded from pipeline +clocks. All six CSVs and 120 TIFF arrays exactly match retained main9a output, +including dtype, shape and matching inventories. This is a lifecycle regression +gate, not an ABBA performance comparison or current integrated-candidate timing. + +The fix passes 37 scoped tests with five single-affinity skips and both actual +two-core fork controls. Original unmodified R0 passes for openhcs, scripts and +benchmark; R1 reports no increases against main25d56ae under its unchanged +160-second budget. The failed Python3.12 ratchet launch and uninitialized +worktree R1 launch remain retained; final guards use Python3.14 and the initialized +main repository, respectively, without modifying either detector. + +Evidence: ``registry-startup-readiness-162-empty-cache-pipeline-20261002.json``, +``registry-startup-readiness-162-validation-20261001.json`` and +``registry-startup-readiness-162-original-r0-py314-20261002.log`` plus +``registry-startup-readiness-162-original-r1-initialized-root-20261002.log``. +The original 50.800-second compilation regression remains retained. Current +combined performance, IFC behavior and source guards remain draft gates. + +Complete-field ordinary ABBA and current ownership repairs +--------------------------------------------------------- + +The completed uninstrumented ABBA at main 107498cf against candidate 02609e12 +has two observations per source for each workload. Execution/total means are +11.162969/13.119510 s versus 8.295599/10.351318 s for 3D, +8.706567/11.262818 s versus 8.474416/11.132766 s for Advanced, and +16.500067/18.794964 s versus 16.920803/19.454312 s for IFC. Thus 3D saves +2.867370 s execution and 2.768192 s total, while IFC regresses 0.420735 s +execution and 0.659348 s total in these samples. No statistical significance +or noise explanation is asserted. All observations remain retained. + +Original unmodified R0/R1 rejected 02609e12. The actual metadata owner now owns +normalization and leading-axis transformation; the redundant raw projected +field dictionary, provenance normalization forwarder and foreign optional-state +handling are removed. Source and axis projection roles compose through +inheritance while preserving effect/error order and independent result ownership. +Common scalar admission is shared on SourceMetadataFields. The optional +intensity-proof projection and scale queries consume their existing authorities +instead of duplicating algorithms. Component controls include 41 scalar tests, +1,212 original-source behavior comparisons and 197 metadata/proof controls. +The collected classification projection census was also repaired to skip actually +abstract parameter declarations while still checking concrete descendants; +429 focused and 1,111 broader consumer controls passed before dependency update. +The inherited census failure was reproduced on main under the same imports. + +The subsequent ordinary ABBA measures frozen production candidate +90c30e1adfacd25a834ed48949b430099c866134 against the same main 107498cf: + +==================== ======================== ======================== +Workload Execution main/candidate Total main/candidate +==================== ======================== ======================== +3D 11.089386 / 8.172661 s 13.063124 / 10.106094 s +Advanced 8.854658 / 8.988559 s 11.408556 / 11.590607 s +IFC 17.382926 / 16.212604 s 19.628127 / 18.661190 s +==================== ======================== ======================== + +3D saves 2.916725 s execution and 2.957031 s total; compilation means are +1.214262 / 1.209572 s. Advanced regresses 0.133900 s execution and 0.182051 s +total. IFC improves 1.170322 s execution and 0.966938 s total in this batch. +These means do not erase the adverse026 IFC evidence or establish significance. +All twelve case observations succeed through ordinary OUTCOMES, default memory +observation, one well/thread and CPU5. Both sources use identical public drivers, +shared dependencies/native binaries and mandatory registry preparation before +readiness. Server startup, prewarming and shutdown are excluded. There are no +profiling hooks, captures or scientific substitutions in either ABBA. + +For each ABBA, all six output pairs pass scientific comparison. All six 3D +CSV exports and all 120 TIFF arrays match exactly, including complete scientific +inventories, dtype and shape. IFC has exact headers and all 1,800 x 527 result cells. +Advanced uses the existing CellProfiler database/export comparator at absolute +and relative 1e-6, with exact schemas, cardinalities, discrete values, identifier +relationships and categorical data. Eight scientific subject tables and all +relationships are nonempty. Unsaved final segmentation masks were not observed. +The90 comparison reads actualaf45 source against its still unchanged pre-update +dependency environment, attested before and after. Output files remain unchanged. + +At 90c30, original R1 passes with no increases under the unchanged 160-second +budget, and original R0 scripts/benchmark pass. R0 openhcs remains RED solely +because the scalar/container rejection classifier moved from virtual workspace +decoding to its actual field owner: source_metadata gains one local switch and +three arms, while virtual_workspace_metadata loses one switch and four arms. +The original per-file gate is not waived or declared passed. Across all changed +roots the global delta is zero switches and minus one arm; untouched files cancel +because these original metrics are file-local AST measurements. Existing error +and reported-class observation ordering is preserved rather than altered to +satisfy the metric. The global 702-module authority audit found no existing +replacement retaining that complete grammar/error contract. These are distinct +architecture and behavioral gates, not interchangeable claims. + +After both ABBA and all their comparisons finished, main +c32447f1c86a1878a313d1643a398e30ac20f75e was normally merged into this branch. +The shared environment now installs declared published ArrayBridge 0.3.6 at +source 1e53d03d9f468322a1c085c8be29485fb139caf2, openhcs-basicpy 1.3.1 and +JAX/jaxlib 0.9.2. Metaclass-registry 0.2.2 source 393a7e0, NumPy/SciPy/Numba +and both native extension hashes are unchanged. Pip check reports no broken +requirements and actual package imports pass. The separate native CellProfiler +4.2.8.1 environment remains unchanged. Earlier timings retain their measured +source/dependency pins; they are not projected through this new main/environment. +New combined qualification and full native parity remain required. + +A capture-free coarse diagnostic on frozen 80d92 source partitions one 9.208835 s +job into 4.164762 s inside RuntimeCallableInvocation.call and 5.044073 s outside. +The callable boundary includes decorated processing/metadata and is not a pure +image-kernel measurement. Diagnostic wrappers are not accepted performance +comparisons. Full load, unstack, save, CP image recording and image request phases +have a nonoverlapping 3.009640 s upper bound. Recovering 2 s requires eliminating +at least 66.453% of those complete phases, not just a cached recomposition or +an original-source cache miss. The existing named-value to eager-plane metadata +to MemoryVFS to whole-stack round trip is the next structural premise. Mandatory +named/mainflow pixel-copy isolation and concurrent durable publication remain +constraints. No new production route is admitted without a representative replay +showing that complete consumer closure can realize a material payoff. + +Retained evidence is in the shared benchmark-runs directory: +``owned-metadata-90c30-ordinary-abba-csv-tiff-parity-20261002.json``, +``advanced-ordinary90-six-pair-sqlite-parity-20261002.json``, +``pr394-integrated-90c30-original-source-guards-20261002.json``, +``scalar-owner-original-r0-global-delta-counterevidence-20261002.json``, +``integrated90-classification-concrete-projection-census-fix-20261002.json``, +``shared-main-dependency-update-c32447-20261002.json`` and +``pr394-90c30-whole-mainflow-value-frontier-20261002.json``. +Source freezes, complete observations and diagnostic boundaries are retained in +``/var/tmp/openhcs-owned-metadata-90c30-ordinary-abba-20261002/`` and +``/var/tmp/openhcs-owned-metadata-phase-probe-20261002/``. The original 026 +comparison and original failures remain separate pinned evidence. + + +Prepared callable owner and independent plane follow-up (2026-10-02) +------------------------------------------------------------------ + +Registry preparation now resolves canonical and actual raw signatures after all +function preparation hooks and before READY. Authored declarations resolve in +compilation. Immutable signature pairs travel on the existing CallableMetadata +through existing function-reference/worker transport. Runtime filtering, batch +defaults and canonical argument admission consume the associated prepared view; +three separate signature/default/type LRU caches and late kernel preparation are +removed. Server preparation remains outside pipeline clocks. + +The isolated owner repair ``760e9ae8613d8737411a627b6abfe6a15f4ca0b9`` moves actual +target resolution, signature state and carrier grammar onto CallableMetadata; +CallableProjection/Reader own preparation admission, RuntimeCallablePolicy owns +invocation, and Pure2DSliceBatchExecutor owns the formerly duplicated executor +selection. Distinct actual targets always receive independent raw snapshots; +only the same actual target shares its canonical snapshot. No new wrapper class +or equality comparison over arbitrary callable defaults is introduced. + +Original, unchanged R0 passes against both the prepared-callable commit and the +frozen qualification source, eliminating its new class-size, Boolean-chain and +foreign-absence debt. Original R1 passes within the unchanged 160-second budget +with 3,084 projections. These are isolated gates; the inherited scalar-owner +per-file R0 gate on the whole branch remains open. Focused owner tests pass 105 +controls; the larger 648-pass/five-skip suite initially retained two baseline-red +plane-domain controls. Their failure also reproduces on untouched ``94915``. + +The independent repair ``0b7f6f98a4b19d85d0dbb20f4db49e45cd0d90c1`` validates an +explicit object projection against its declared source axis and nonempty +acquisition cardinality directly. Independently authored runtime planes can own +an exact projection without acquisition-plane provenance. Physical source/label +cardinality and spatial-shape checks remain mandatory. Thirty-nine controls pass, +including both axes at one/two planes and wrong-axis refusal. No object-domain +semantics are inferred from source storage axes. + +The all-30 scientific qualification on frozen ``94915`` is RED: 24 cases pass; +four fail at missing payload context in Align/Crop, one loses its server to a +confirmed kernel OOM kill, and one differs in threshold entropy. Saved input +replay traces that entropy mismatch to missing Threshold source scale/dtype at +the canonical raw boundary. Truthful declarations are being corrected without +scientific-body or tolerance changes. Linux killed endpoint PID 2412356 with +13,360,004 KiB anonymous RSS; the dominant allocation/retaining owner is still +unmeasured. Issue #433 tracks that distinct execution-server acceptance gate and +is formally linked to this draft PR. Retained native clocks are not current +paired speedup evidence. + +Evidence stays in the external benchmark RUNS directory, including +``pr394-94915-all30-native-science-qualification-red-20261002.json``, +``pr394-signature-owner-760-source-inventory-20261002.json``, the original R0/R1 +receipts, and ``issue419-explicit-object-plane-cardinality-followup-20261002.json``. +Two partial cohort captures complete all 31 production steps and match all six +CSV files and 120 TIFF dtype/shape/pixel arrays exactly, but each admits only six +of ten graph snapshots. V4 identifies an unsupported native allocation owner in +the four remaining before-state graphs; those graphs remain missing. Diagnostic +capture clocks do not establish a speedup, and the additional multi-second +whole-value plumbing payoff remains unmeasured. + + +Prepared payload contract qualification (2026-10-02) +-------------------------------------------------- + +The integrated library/kernel readiness run at ``1ad3898`` prepares all 267 +functions and 976 targets before READY. It creates 265 distinct actual raw +signature snapshots and reuses the canonical snapshot for two identical actual +targets. Three rounds of prepared annotation, carrier, raw-signature, batch +default and invocation-construction queries perform zero additional live +signature/type-hint resolutions. The fresh-cache 90.381-second preparation is +server startup diagnostics, excluded from pipeline clocks. Later explicit-plane +validation and test-producer changes do not change these warming/signature owner +sources. This finite check does not claim zero reflection for arbitrary +unprepared authoring or unsupported callable mutation. + +The annotation-only follow-up ``9ae4c9426`` corrects twelve existing context +consumers, three forwarding helpers and CropRequest.image. Existing +RuntimeArrayData preserves their nominal image payload at the actual raw +boundary; NumPy-only consumers still receive NumPy arrays. Scientific bodies, +defaults, decorators and return declarations are unchanged by AST comparison. +Frozen ``7241ca99b`` passes native-science comparison for Colocalization, +Neighbors, YeastColonies and pixel classification with zero differences. +YeastPatches passes its previous Crop failure but subsequently exposes an +incorrect RGB source domain from IdentifyObjectsInGrid. + +Saved actual RGB pixels, source metadata and both 93-ID label artifacts isolate +the remaining defect: IdentifyObjectsInGrid's primary argument and its existing +request field/from_runtime argument falsely declare np.ndarray despite passing +the image to SourceImageObjectLabelBuildRequest. Their raw ABI strips the +1200-by-1600 source domain and (150, 170) crop origin, producing a (1255, 3) +domain for (835, 1255) labels. ``84e99c0dd`` changes only those declarations and +their direct RuntimeArrayData import. Scientific bodies and the refusing domain +guard are unchanged. Seventy-seven scoped controls and 127 integrated controls +pass. A fresh YeastPatches execution at that revision passes the existing native +comparator with zero differences. Its replay uses retained source-pinned native +artifacts, not newly timed native execution. The original 84-entry/38-module AST +frontier now has no remaining exact classmethod context leads; aliases, inherited +dispatch and dynamic routes remain outside that finite inventory. + +The five affected cases have passed across these two targeted sources. The full +all-30 latest-head science gate, the execution-server OOM retaining-owner gate, +the whole-branch scalar per-file architecture gate and fresh ordinary performance +qualification remain open. No current native speedup is inferred from retained +clocks or instrumented captures. Evidence includes +``issue419-actual-integrated-1ad-signature-owner-readiness-20261002.json``, +``pr394-7241-context5-science-qualification-20261002.json``, +``issue419-grid-context-fix-20261002.json`` and +``pr394-84e99-grid-science-qualification-20261002.json`` in the benchmark RUNS +directory. All original failed source-pinned runs remain retained. + +Graph ROI source-bearing writer integration (issue #134) +------------------------------------------------------- + +The receiving owner requested narrow integration from PR #404 checkpoint +``f3e566485a391a270a6d2c40dbfddf07881dcd3d``. The exact patch binds existing +ROIArchiveSourceMetadata to graph ROI content and places the same existing +ImagePayloadMetadata on Output. Graph provenance already selects its declared +source plane; no second global-plane selection is performed. Coordinate spacing +uses existing SourceVoxelSpacing. The binder, disk ZIP transport, geometry +projection and native admission retain their existing owners and guards. + +On current ``38067a4a5`` before the production patch, the receiving seven-case +fixture reproduces three source-bearing failures and four refusal controls +pass. After integration, all seven pass alongside the original graph, batch +outcome and materialization controls: 87 PASS in 2.28 seconds. The existing +geometry test obtains geometry through the original archive projection before +its unchanged coordinate and feature assertions; bound transport metadata is not +mistaken for a graph feature. An independent cooperative graph subtype and new +feature require no new writer or consumer registration. Missing, unbound, mixed +and conflicting native source declarations remain refused before transport. + +This is current-source synthetic writer/disk/archive qualification. Actual +installed public/native graph reopening remains with the receiving owner, and +no performance or biological acceptance claim follows. Original failures remain +in ``pr394-38067-graph-roi-before-20261002.log``; integrated controls are in +``pr394-graph-roi-integrated-after-20261002.log`` in RUNS. The historical PR #404 +branch and its older publication proposal are not merged as a whole. + +Opaque image domain and current 3D frontier (2026-10-02) +------------------------------------------------------ + +Frozen ``45f3a721e`` diagnoses the dominant current 3D failure: scalar output +composition adds a runtime axis to an opaque whole volume. Watershed receives +``(1, 60, 128, 128)`` and fails after 118.394 seconds inside its raw callable. +The failed job peaks at 3745.977 MiB. Installed Mahotas 1.4.19's filter-offset +formula requires a 2 GiB table for that incorrect 4D seed-label neighborhood; +the singleton changes neighborhood rank without changing image voxel count. +This is a source-backed bound, not an allocator-stack capture or attribution of +the original 13.36 GB OOM. No NumBa cache files are created during the observed +pipeline window. Cache warming does not correct an invalid scientific domain. + +``d092a03af`` repairs composition using the existing nominal alignment owners. +``AlignedImageStack`` retains its declared outer runtime axis; named +``ImageOutputBundle`` members supply their original individual domains. +``PatternGroupOutputData`` derives saved member declarations from those original +values, and ``ProducedOutputSemantics`` retains that domain across physical-leaf +projection and passthrough. This execution-local fact distinguishes an opaque +single-Z volume from an explicitly declared one-plane runtime stack after both +have otherwise similar leaf metadata. It does not replace durable source ingress. +Mixed cohorts cannot manufacture one combined domain. Cache misses, overwrites, +named selection and independent pixel/mask/metadata ownership are covered. +Producer and loader bundle composition use the same existing authority. + +The first scoped original R0 rejects ten added lines in the oversized runtime +class. ``6dd47dd7e`` moves actual input assembly onto existing +``PatternGroupData`` and shared independent copying onto +``ImagePayloadStackComposition``, removing the input loader's call into the +output factory. Both unchanged original scoped R0 and R1 then pass against +``45f3a721e``; 271 controls pass, including retained lazy device resolution for +bundle composition. The whole-branch scalar relocation gate remains separate +and is not waived. Cross-device composition equivalence remains unqualified. + +A fresh ordinary CPU5/one-inline-worker execution at frozen ``d092a03af`` gets +through the first 18 steps. The entire Watershed step completes in 0.156588 +seconds. The older figure is an instrumented raw-call failure, so these are not +paired successful timings or a native speedup ratio. The full pipeline still +fails at step 18, MaskImage: a correctly selected 2D invocation receives the +opaque secondary volume without a source-proved plane projection. The refusing +2D mask guard is correct. Failure-row zero compile/execute values are wrapper +placeholders; the public compile-event span is 1.619 seconds. Pipeline clocks +exclude mandatory registry/kernel server preparation and shutdown. + +The generic relation-aware repair belongs at ``RuntimeInputBindingRequest``. +MaskImage, Crop and CorrectIlluminationApply already declare +``InputStackBroadcastSourceRelation``. That declaration permits broadcasts but +does not prove spatial-Z ordering. Contributor provenance or equal array lengths +cannot supply the missing pixel-coordinate proof. ``SourceSpatialDomain`` is +currently XY-only; source/transform ownership is being traced before extending +its existing contract. No function-specific mask path or geometry-guard +relaxation is included. Latest-head all30/native parity and ordinary performance +remain open. + +Main ``902913616`` (merged PR #434) is integrated at ``ff9d7c79d``. The combined +14-file source suite has 810 passes and two unary GrayToColor failures. Both +failures reproduce unchanged on clean main ``902913616``; they are retained, +not converted into successful assertions or treated as axis-fix regressions. +No foreign PR implementation is duplicated. + +Three completed same-server Human jobs at ``45f3a721e`` pass their scientific +comparisons and leave zero backend image-array bytes after each job. This +rejects the proposed completed-job backend leak for that workload. Generic +worker resource release already executes for inline jobs. The older OOM's full +allocation mix remains unknown; no speculative global cleanup is added. + +Receipts remain in the external benchmark RUNS directory: +``issue433-rank4-watershed-large-allocation-source-bound-20261002.json``, +``issue433-three-complete-job-retention-counterevidence-20261002.json``, +``pr394-opaque-axis-input-owner-original-r0-openhcs-20261002.json``, +``pr394-opaque-axis-input-owner-original-r1-20261002.json`` and +``d092-mask-secondary-domain-caller-audit-20261002.json``. Frozen ordinary +outputs/source hashes are retained under +``/var/tmp/openhcs-opaque-axis-d092-ordinary-20261002``. The initial failed +guard-launch arguments and the original R0 growth finding are also retained. + +Persisted derived-role publication (issue #435) +---------------------------------------------- + +``ce1b7acfc`` repairs duplicate publication of one saved image occurrence in the +existing metadata writer. The existing output context derives the declared +source alias; anonymous main flow remains anonymous. Produced records and +successful materialization outcomes share a path index. A second projection is +omitted only when declared alias, artifact kind, producer scope, exact path, +scalar acquisition address and full persisted image metadata agree. Distinct +files with colliding identities, stale scopes, different kinds and conflicting +metadata retain their original refusal. No source-projection guard is relaxed. +The index is linear in produced records and successful outputs. + +The actual writer reproducer at baseline ``130c03a26`` saves two distinct role +images with real C2 addresses and calibration, then reproduces the duplicate +projection failure. At ``ce1b7acfc``, both roles publish once and reopen through +the existing virtual workspace; exact pixels, addresses and spacing pass. All +four independent refusal controls pass, together with 232 focused controls in +9.42 seconds. These are writer/materialization/reopening controls, not an +installed five-step acceptance or a performance benchmark. + +Unchanged original scoped R0 and R1 pass for ``130c03a26`` to ``ce1b7acfc``. +The first candidate ``6dfda9597`` failed original R0 for a long producer-match +Boolean and a foreign absence probe. Moving alias derivation to its existing +context owner and comparing exact producer tuples resolves those findings. +The whole-branch scalar gate remains separate. Independent review finds no +blocker; persisted occurrence identity does not prove stale in-memory pixels +equal the final overwritten file. Pixel parity remains a separate gate. + +The parent has supplied the original five-step source and bounded saved-path +facts in issue comment ``5948666249``. Actual produced-record and materialized +output pairs were not serialized there. Installed original-path acceptance +remains open; no biological replay or fabricated collision pair is claimed. +The separate #437 owner retains its singleton-consumption repair. + +Main ``8551a4864`` (merged #438 and #439) is integrated at ``3de415d63``. +The integrated publication, axis and new MCP compilation controls pass: +247 tests in 51.50 seconds, with two existing pytest configuration warnings. +The scoped guard receipts are retained externally as +``issue435-ce1-original-r0-retry-20261002.json`` and +``issue435-ce1-original-r1-20261002.json``; independent review is +``/var/tmp/openhcs-issue435-independent-publication-review-20261002.json``. +Original failures and failed guard launches remain retained. + +Fresh native comparison and measurement lifetime frontier (2026-10-02) +-------------------------------------------------------------------- + +Frozen ``919fee286f8003a00aafc023ad28767d9713842b`` completed two ordinary +public-driver observations on CPU5, one inline worker/thread, with default +OUTCOMES and the default memory observer. Server startup, mandatory registry +and kernel warmup, and shutdown are excluded from pipeline clocks. + +===================== =========== ============== ============== ============== +Case Compilation Server job Pipeline total Native CP run +===================== =========== ============== ============== ============== +Advanced segmentation 1.324832 s 8.078740 s 10.650795 s 34.327521 s +Imaging flow cytometry 1.941105 s 15.497744 s 18.177965 s 77.795280 s +===================== =========== ============== ============== ============== + +Native CellProfiler 4.2.8.1 uses the same physical input paths and SHA256 +values, CPU5 and one thread. Its invocation excludes interpreter/JVM startup, +pipeline load and one complete warmup, but includes image-set preparation, +modules, post_run and Measurements.close. These are single observations with +different explicit setup/publication accounting; they do not establish a +kernel ratio, statistical significance or a new patch's speedup. + +IFC's existing strict exported-science comparison passes with zero differences +and 1800 nonempty rows in each CSV. Native has 528 physical columns and OH 527: +the native redundant Number_Object_Number equals ObjectNumber for all 1800 +rows, and the existing nominal identity policy recognizes that declaration. +This is semantic measurement equality, not identical cross-tool CSV headers. +The observed native/OH ratios +are 5.019781 for server-job execution and 4.279647 for pipeline total. Unsaved +segmentation masks are outside these retained outputs. Advanced's existing +scientific database comparison also passes with zero differences, but complete +source-information acceptance remains RED: five illumination sources across +two sites have 90 NULL cells instead of native values. The original integer +gate detects 40 Frame/Series/Height/Width cells; independent inventory adds +ten Scaling and forty FileName/PathName/URL/MD5Digest cells. Issue #444 is +formally linked to PR #394. No field exclusion or tolerance change is admitted. + +A separate coarse diagnostic on the same source partitions IFC's 13.838053 s +execution into 9.373829 s inside the raw-callable boundary and 4.464224 s +outside. Advanced's 8.087572 s partitions into 3.836250 s inside and 4.251322 s +outside. The callable boundary includes decorated processing and result +assembly, not just numerical kernels. Nested inclusive spans are not added. +Exclusive recording, table assembly and export work has a combined envelope +of 2.812474 s for IFC and 2.882479 s for Advanced. Saving two seconds requires +roughly 71.11% and 69.38% reduction respectively; recording alone is insufficient. +Stack loading costs 0.126811 s / 0.106307 s. Ordinary progress events bound +between-step/axis work below 17 ms and other job-minus-axis gaps at +0.196432 s / 0.100492 s. Those routes cannot close the multi-second target. +Diagnostic clocks are not ordinary speedup evidence. + +Retained evidence lives under ``/var/tmp``: ordinary outputs and source freeze +in ``openhcs-latest-ordinary-advanced-ifc-20261002``, fresh native inputs, +reports and IFC comparison in +``openhcs-current-native-advanced-ifc-v2-919fee-20261002``, and coarse regions +in ``openhcs-current919-runtime-phase-probe-20261002``. Independent source-field +inventory is ``advanced-fresh-native-missing-illum-metadata-20261002.json``; +the dominant cost/owner receipt is +``openhcs-919-measurement-lifetime-frontier-20261002.json``. Original failed +native preparation and the exact metadata comparison failure remain retained. +Actual typed measurement-request/export capture is in progress; no production +optimization or replay acceptance follows from the cost envelope alone. + +Latest main ``3df650bf7`` (merged #442/#443) is integrated at ``436e49755``. +The incoming BioFormats calibration, MCP streaming and existing publication/ +opaque-domain controls pass: 141 tests in 16.72 seconds. The initial narrow +launch failed collection because the MCP test imports the streaming fixture +module by its short name; the corrected command includes that actual fixture +owner first. Both logs are retained in ``/var/tmp``. No source/test guard was +modified to obtain the pass. + +The actual IFC capture completed the public pipeline and exact source/dependency +freeze, but its four-snapshot admission remains RED: step22 never invokes +MeasurementsOutputRecorder.record. Only the terminal spreadsheet before/after +graphs were captured (44,935,114 and 56,109,057 bytes), with no graph or budget +rejection. The nine real recorder calls publish identification/filtering/ +expansion/relationship core tables. Texture and intensity-distribution tables +use the separate per-object recorder. Thus the proposed capture and the premise +that all outer recording cost is redundant wide-feature conversion are rejected. + +Independent export-only qualification passes both unchanged V6 loads (615 arrays +each), exact original CSV bytes, existing strict CP science, and all determining +field/source/array aliases. Thirty-five immutable metadata owners drop their +derived views by their existing declared transport policy; every populated view +matches fresh recomputation from the same fields. Original raw-heap equality +remains RED for that intentionally untransported cache state, separately from +declared-state equality. The actual exporter graph has 31 measurement tables +and two relationship records, with no label pixels; it cannot validate a dense +label-storage optimization. Local diagnostic profiling finds repeated row +identity/axis scanning and assignment; it is not end-to-end speedup evidence. +The ordinary export ceiling is 1.4077 seconds, so export alone cannot save two +seconds. Preserving the native CSV span leaves an optimistic combined outer +recording/export ceiling of 2.4189 seconds; a two-second saving requires about +82.68% collapse. No implementation is admitted by that ceiling alone. +Receipts are ``openhcs-measurement-export-declared-state-profile-20261002`` and +``openhcs-measurement-export-declared-fields-alias-control-20261002.json`` under +``/var/tmp``. The original four-snapshot and raw-heap failures remain retained. + + +Current-main integration and recording attribution (2026-10-02) +--------------------------------------------------------------- + +Main was normally merged through 3cb701770 at 6097ec4ff. Independent PR447 +merged the source-only CPA metadata repair and closed issue444. Its own +220 controls, original architecture check, public Advanced run and independent +scientific/source-identity comparison are documented in +``cpa-secondary-source-metadata-444.rst``. The larger branch still has open +acceptance gates and remains draft. + +The main58ee singleton controls exposed a real prepared-ABI integration bug: +unannotated COMPOSED functions lost their nominal carrier. d4e800a75 derives +that default from the existing consumption declaration while preserving +explicit ndarray/Any/nominal ABI precedence. 136 isolated and249 integrated +controls pass; the original scoped architecture check has zero increases. + +A fresh frozen746 Advanced run completed with compilation1.7983s, +execution9.4002s and total12.3852s, default observers and startup excluded. +Its scientific database comparison has zero differences. All90 previously +NULL calibration fields are present;70 match literally and20 native staging +PathName/URL strings are proven to identify the same source files using +same-inode, resolved-source and original native input-inventory SHA checks. +The raw path-string comparison remains separatelyRED. This is one observation, +not a performance benefit: colocalization and one primary identification step +were slower than frozen919, while database export changed1.8378 to1.7538s. + +The first nine-recorder cProfile diagnostic is scopeRED. It omitted the +existing monitoring callback thread filter and attributed background sleeps +to arbitrary numeric callers. A separate companion-thread experiment +reproduced the error and confirmed the existing worker-profiling policy +removes it after every profiler enable. No production workaround or duplicate +issue for the already-fixed profiler infrastructure was introduced. + +The corrected frozen919 diagnostic has zero foreign sleep/server/poller +events, exact original IFC CSV bytes, and zero scientific differences against +native CP for1800rows. Its disjoint recording attribution is diagnostic only: + +================================ ============ +Region Profile time +================================ ============ +Centroid calculation 0.6766s +Sparse relationship row assembly 0.4404s +Repeated axis-domain scans 0.2159s +Other table assembly 0.3644s +Ownership validation 0.000027s +Measurement storage 0.0123s +================================ ============ + +Centroid-to-IJV conversion is nested within centroid calculation and must not +be added to it. Storage/ownership are immaterial targets for these recording +calls; centroid-only cannot deliver the multi-second goal. Recording plus +nonserialization export remains an optimistic2.4189s ceiling, not a measured +counterfactual improvement. + +A real source-born3D diagnostic on isolated8dec failed mask alignment at +step18. It observed300 source births and18 completed producer groups with +no observation errors. RescaledDNA starts with60 correlated physical Z rows; +Resize preserves60planes and changes onlyXY but drops the source domain. +Resize after ImageMath repeats the loss. Source audit identifies bare ndarray +annotations on the public Resize entries despite their shared implementation +requiring metadata/masks. Direct unwrapped tests bypassed this boundary. +Issue450 is formally linked to PR394; truthful RuntimeArrayData declarations, +prepared-contract tests and a fresh production rerun are required. No source +facts are injected into legacy captures, and no3D speedup/parity claim is made. + +Retained thread-scope/science receipts: +``/var/tmp/openhcs-nine-recorders-profile-thread-scope-control-20261002.json``, +``/var/tmp/openhcs-nine-recorders-profile-thread-owned-science-20261002.json`` +and ``/var/tmp/openhcs-nine-recorders-thread-owned-disjoint-analysis-20261002.json``. +Actual failed3D proof: +``/var/tmp/openhcs-spatial-plane-sourceborn-diagnostic-v2-20261002/observations.json``. + + +Actual 3D production completion and remaining qualification (2026-10-02) +---------------------------------------------------------------------- + +The isolated physical-plane prototype at aba4bfaf3 normally incorporates this +branch through424bd2029. Its truthful Resize ABI declarations and prepared +FULL_STACK controls pass438 tests. The actual new production run completes +with no observer errors,780 source-plane births and32 producer groups. Resize +now retains the runtime stack axis and all60 correlated physical rows; +MonolayerMask and the primary input consequently use the existing declared +stack-binding path. The diagnostic controller had required the different +opaque-image fallback's hook. Its original observation gate remains RED; +zero calls to that fallback is not a production failure or evidence of lost +metadata. The actual route is separately adjudicated from retained producer +observations and the existing binding declaration. + +Independent unchanged saved-output comparison passes all6 CSVs and120 TIFFs +exactly against the specified retained ordinary reference: headers/cells and +image dtype/shape/pixels. Receipt: +``/var/tmp/openhcs-spatial-plane-aba4-independent-historical-science-20261002.json``. +Diagnostic clocks are compilation2.1216s, execution9.7020s and total12.7136s; +they exclude server startup but do not establish a new performance benefit +or a current native CP ratio. Original R1 passes within its unchanged budget; +original R0 retains the quoted-Iterable finding. Independent actual RGB-volume +controls show identical pixels/masks but incorrect XY metadata in the +prototype: (3,3) instead of the declared channel-aware (2,3). Baseline passes. +The separate 2D RGB mask failure also occurs on baseline and is not claimed +as a new regression. + +The decisive route reassessment rejects promotion of the broader physical-Z +prototype. Preserving Resize's runtime stack carrier makes the existing typed +binding sufficient here; the new opaque physical-plane binding has no actual +production consumer in this run. Synthetic controls and successful saved +science do not establish its runtime payoff. Further prototype implementation +is stopped; the next counterfactual applies only truthful carrier declarations +and existing prepared metadata/mask/stack controls to current PR394. Actual +production execution must identify any remaining necessary repair. The +original failed observer gate and the RGB counterexample remain retained; +no source facts are injected and no gate is retroactively called PASS. + +PR394 normally incorporates latest main4754fbe2b at2aa930eb2. The added Napari +integration controls pass183 cases and fail the existing offscreen window +width assertion (1260 versus0). The exact isolated assertion also fails on +clean main4754fbe2b with the same values; it remains a separately recorded +inherited gate failure, not a passing full suite. Logs: +``/var/tmp/openhcs-pr394-latest-main4754-napari-controls-20261002.log`` and +``/var/tmp/openhcs-main4754-napari-layout-isolated-20261002.log``. + + +Qualified narrow carrier repair and fresh native 3D (2026-10-02) +--------------------------------------------------------------- + +The rejected physical-plane prototype is absent from PR394. Narrow commit +b7640ad61 on isolated main-synchronized2aa930eb2 changes only five geometry +annotations; no numerical body, domain, HoleRemoval or renderer changes. +Nine prepared/FULL_STACK controls establish7 failures before and9 passes +after, preserving typed masks, runtime/opaque domains and source provenance. +The related suite passes148 tests; unchanged original R0/R1 both pass within +their original budgets. Integration fecf3114a has exactly the same production +and test Git trees as the qualified isolated source; only validation prose +differs. The fix is formally carried by PR394 for issue450. + +The actual uninstrumented default3D pipeline completes, with exact6CSV and +120TIFF saved science against the same retained reference. All180 actual +source-plane references belong to exactly3 physical TIFFs with indices0..59 +and unchanged source-file SHA values. Both fresh native CP4.2.8.1 measured +repeats pass the existing strict6table/150key/2825fact comparison, exact two +logical uint16(60,256,256) label volumes and complete physical-file coverage. +Native comparison to the prototype plus exact prototype/reference/narrow +comparisons establishes transitive narrow parity; no direct narrow/native +comparison is claimed. The original comparison-controller API failure +(tuple subtraction from frozenset) remains RED; a separate recipe supplies +the required frozenset input views without changing any scientific gate. + +Fresh current main4754fbe2b also matches the same saved reference exactly. +All clocks below use CPU5 and one thread, with startup/warmup excluded. +OpenHCS includes default OUTCOMES and memory observation; native invocation +includes prepare_run, module execution, post_run and Measurements.close, +and excludes imports/JVM/pipeline loading plus its separate warmup. + +===================== ============ ============ ============ +Observation Compilation Execution Total +===================== ============ ============ ============ +Main4754 ordinary 1.6754s 10.0712s 12.4766s +Narrowb764 ordinary 1.6190s 8.3008s 10.7417s +Native measured0 excluded 14.3544s invocation +Native measured1 excluded 14.4375s invocation +===================== ============ ============ ============ + +The observed main/candidate difference is1.7704s execution and1.7349s total +for the full PR394 plus annotation repair. It is not evidence that the five +annotations alone save that time. One ordinary observation per source does +not establish repeatability or statistical significance. Native's two-run +mean is14.39595s, giving a descriptive1.7343x candidate execution ratio and +1.3402x whole-pipeline ratio under the explicitly different clock scopes. +The target gap remains: reaching2x requires about1.10s further execution +reduction, or3.54s whole-pipeline reduction. No goal completion is claimed. + +Receipts: +``/var/tmp/openhcs-geometry-narrow-original-guards-20261002.json``, +``/var/tmp/openhcs-geometry-narrow-b764-3d-ordinary-20261002/observations.json``, +``/var/tmp/openhcs-geometry-narrow-b764-independent-science-and-inputs-20261002.json``, +``/var/tmp/openhcs-main4754-independent-historical-3d-science-20261002.json`` and +``/var/tmp/openhcs-native-3d-aba4-qualification-20261002/fresh-native-scientific-comparison-supplemental.json``. + + +Four-run 3D comparison and dominant runtime frontier (2026-10-02) +---------------------------------------------------------------- + +The subsequent A1/B1/B2/A2 ordinary comparison supersedes the single-pair +ratios above. A is frozen clean main4754fbe2b; B is frozen narrowb7640ad61, +including the full PR394 runtime change and five truthful annotations. Each +run uses CPU5, one worker/thread, the unchanged public driver, default OUTCOMES +and memory observation. Mandatory server/library/kernel startup and shutdown +remain outside the pipeline clocks. All four observations preserve exact six +CSV tables and120 TIFFs against the same retained reference, unchanged source +and dependency freezes, and all180 source-plane references to the same three +physical volumes used by fresh native CP. + +======================= ============ ============ ============ +Observation Compilation Execution Total +======================= ============ ============ ============ +Main A1 1.6754s 10.0712s 12.4766s +Candidate B1 1.6190s 8.3008s 10.7417s +Candidate B2 1.7936s 8.7713s 11.3281s +Main A2 1.6213s 10.0910s 12.4374s +Main mean 1.6484s 10.0811s 12.4570s +Candidate mean 1.7063s 8.5360s 11.0349s +======================= ============ ============ ============ + +The descriptive mean reductions are1.5451s execution and1.4221s total. +Native warm invocation mean14.39595s gives1.6865x execution and1.3046x +total ratios under the previously stated clock scopes. Two observations per +source do not establish statistical significance or annotation-only causality. +The remaining2x gap is1.3381s execution and3.8369s total, larger than the +first-pair estimate. The complete independent receipt is +``/var/tmp/openhcs-3d-b764-abba-science-clocks-20261002.json``. + +A separate source-pinned diagnostic partitions8.3448s of execution into +4.0497s inside the callable boundary and4.2951s outside it. Callable time +includes decorated metadata/control work, not only numerical kernels. The +exclusive outer terms include stack loading0.5991s, unstacking0.2126s, +saving0.3487s, output identity0.2070s across1680 calls, image recording0.2333s, +CP image requests0.2012s, SaveImages invocation preparation0.3463s, metadata +finalization0.1112s, publication0.4795s and reconciliation0.2812s. These are +diagnostic spans, not accepted speedup measurements; required copying, +validation and I/O remain within them. + +The SaveImages preparation span stores memory artifacts and contextualizes +their values; it is not TIFF encoding. Actual artifact materialization has a +separate0.0831s envelope. Saved metadata contains120 SourceArtifactProjection +entries from the two SaveImages outputs. The generic main-flow metadata/VFS +reload branch is not the observed publication route. The actual joint route +is artifact invocation/store, successful materialization metadata, source +artifact projection, serialization, locked publication and reconciliation. + +Publication/finalization/identity alone has an optimistic1.0789s ceiling and +is rejected as insufficient to close the current execution gap. The broader +cohort/recording/invocation/publication envelope is3.0201s and requires at +least44.3% collapse before accounting for mandatory work. Existing whole-stack +cache lookup/storage is already below1ms; dictionary tuning or assuming every +input is restacked cannot support the target. The next admission requires an +actual saved joint leaf replay preserving metadata mutation, source correlation, +custom normalization, error ordering and pixel/mask isolation. No new mutable +identity cache or production optimization has yet been admitted by this ceiling. + +Diagnostic science and freeze validation: +``/var/tmp/openhcs-narrow450-phase-science-and-freeze-20261002.json``. +Global authority/consumer inventory and corrected route: +``/var/tmp/openhcs-b764-publication-authority-consumer-inventory-20261002.json`` +and ``/var/tmp/openhcs-b764-coupled-publication-source-frontier-v2-20261002.json``. + +Latest mainb68029c0c is normally merged atc0d78b62e. The initial MCP/agent +integration run passes131 cases and fails both MRO variants of a new cold +feedback fixture. Clean mainb680 reproduces both failures: its reporting thread +can observe published progress before the fake compiler sets its subsequent +``emitted`` marker. This identifies a fixture synchronization race, not a +demonstrated production race. The original candidate and clean-main failures +remain retained. Baseline causal receipt: +``/var/tmp/openhcs-main-b680-cold-feedback-race-baseline-20261002.json``. +Benchmark timings above remain pinned to their actual main4754/narrowb764 +sources; the newer MCP merge is not silently included in their evidence. + +Test-only integration3317bf9c2 sets the compiler-entry marker before publishing +progress. The actual reporting callback still releases held work; the original +three-second timeout, both cooperative MROs, ContextVar restoration, terminal +ordering and original compiler-error assertions are unchanged. No production +race workaround, retry or longer timeout is introduced. The clean-main repair +passes124 cold-feedback/agent-service controls; integrated PR394 then passes +all133 controls including the narrow prepared geometry ABI tests in13.72s. +Both initial failed runs remain retained. Integrated command, CPU3: + +.. code-block:: bash + + env PYTHONDONTWRITEBYTECODE=1 \ + PYTHONPATH=/home/ts/code/projects/openhcs-shared-runtime-plumbing \ + OPENBLAS_NUM_THREADS=1 OMP_NUM_THREADS=1 MKL_NUM_THREADS=1 \ + NUMBA_NUM_THREADS=1 CUDA_VISIBLE_DEVICES='' taskset -c 3 \ + /home/ts/code/projects/openhcs/.venv/bin/python -m pytest -q \ + -p no:cacheprovider tests/unit/agent/test_cold_inspection_feedback.py \ + tests/unit/agent/test_agent_services.py \ + tests/unit/test_cellprofiler_geometry_prepared_payload_abi.py + +Pass log: +``/var/tmp/openhcs-pr394-main-b680-repaired-integration-controls-20261002.log``. + +Saved-leaf rejection and whole-worker diagnostic, 2026-10-02 +---------------------------------------------------------- + +A second source-b764 diagnostic captures the actual contextualization, +normalization scopes, identity-cache preimages, serializer inputs and five +locked publication preimages. All39 admitted snapshots retain their original +metadata, source correlations and alias relations. Exact six CSV/120 TIFF +comparison against the same-head ordinary run and retained historical reference, +all180 physical input references and source/dependency/native freezes pass. +Injected capture work is separately timed; these are not accepted pipeline clocks. +Receipt: +``/var/tmp/openhcs-narrow450-joint-leaf-v3-science-and-freeze-20261002.json``. + +An exploratory metadata projection fusion passes the11 captured valid-input +leaf comparisons but saves only4.82ms across the five actual context calls; +normalization has no measured gain. Separately, malformed self spatial-domain +metadata combined with malformed source fallback spacing changes the first +exception. The original reports the spatial-domain failure; the candidate +reports invalid spacing. This is a real correctness failure, independent of a +historical test that observes normalization phase counts. The candidate is +rejected for both inadequate payoff and error-order drift, and is not included +in this branch. Original/candidate replay receipts: +``/var/tmp/openhcs-narrow450-joint-leaf-v3-original-replay-20261002.json`` and +``/var/tmp/openhcs-narrow450-joint-leaf-v3-fusion-replay-20261002.json``. +Malformed-input witness: +``/var/tmp/repro_narrow450_fusion_domain_spacing_order_20261002.py``. + +All five original locked publication transactions and both serializer calls +replay with exact ordered JSON results and argument after-state. Original replay +transaction medians sum to0.4646s; the observed callback sum is0.3760s and +lock/read/JSON-write residual0.0872s. Replacing three final transactions with one +would remove only about0.04s of this replay's I/O baseline. Standalone batching +is rejected as insufficient. These are saved-input replay clocks, not an +end-to-end speedup; original on-disk whitespace was not captured. Receipt: +``/var/tmp/openhcs-original-publication-v3-replay-20261002/receipt.json``. + +One further actual public-driver diagnostic uses the existing thread-owned +worker profiling policy, with no source edits or diagnostic monkeypatches. +The worker records26,443,742 calls, including5,280 slice-context projections, +25,304 source-metadata merges,55,173 source identity constructions and248 NumPy +stack calls. The next investigation follows repeated whole-image/plane +derivations across loading, invocation, saving and publication. It does not +assume every cache hit copies or every saved plane has independent pixels: +the observed SaveImages named values, VFS planes and cache share pixels, while +the observed Resize output has independent buffers. Profiling increases the +execution clock substantially; profile times must not be scaled into ordinary +costs or reported as benchmark speedups. Exact six CSV/120 TIFF and frozen source, +dependency, native and physical-input comparisons pass. Receipts: +``/var/tmp/openhcs-narrow450-existing-worker-profile-20261002/observations.json`` +and +``/var/tmp/openhcs-narrow450-existing-worker-profile-science-and-freeze-20261002.json``. + +Main17c630606 is normally merged ata6abc4418. Its new lifetime controls initially +produce140 passes, two SDK failures and one teardown error in the integrated +repository suite. The generated child imports PolyStore before activating the +selected OpenHCS checkout; the intentionally failing synthetic callback also +outlives its test into autouse cleanup. Test-only789e3c304 activates OpenHCS first +and restores the callback owner in a lexical monkeypatch context. Original +failure identity, cooperative close, main-thread checks and repeated-close +assertions remain unchanged. All142 lifetime/cold-feedback/agent-service/prepared +geometry controls then pass in25.24s. This is tracked separately by issue457; +closed issue455's installed production shutdown acceptance is not reopened. +Original RED and repaired logs: +``/var/tmp/openhcs-pr394-main-17c630606-integration-controls-20261002.log`` and +``/var/tmp/openhcs-pr394-main17-lifetime-fixture-repair-controls-20261002.log``. +AST/owner receipt: +``/var/tmp/openhcs-pr394-main17-lifetime-fixture-repair-20261002.json``. + +The test-only repair ships independently in merged PR460, commitb495dbb13; +issue457 is formally linked and closed. Its exact clean-main branch passes21 +lifetime/stdio/dev-client controls through normal repository conftest collection +in13.21s. Main is normally merged back into this branch at01875a772; the merge +introduces no additional production diff. Clean-main qualification receipt: +``/var/tmp/openhcs-mcp-lifetime-fixture-457-main-qualification-20261002.json``. + +The next ownership census uses NRA's ModuleSyntaxIndex and canonical +CompactClassFamilyIndex on all703 OpenHCS production modules and the actual +63 PolyStore,12 python-introspect and6 metaclass-registry modules. All5506 +original class declarations remain represented;5493 join canonical family +declarations and13 remain unprojected OPEN. There are no parse errors. +Conditional/function-local binding, omitted numerical dependencies and native +runtime effects remain explicit proof limits. This is source discovery, not +an admitted architecture or equivalence proof. NRA revision0844525ec is pinned. +Receipt: +``/var/tmp/openhcs-b764-shared-derivation-nra-class-census-20261002.json``. + +Current-main integration and acceptance findings, 2026-10-02 +----------------------------------------------------------- + +Main cc9fcdfd4 is normally merged at 133da74ec. The affected native +presentation/MCP, agent-service, resource-lifetime and prepared-geometry suite +passes 150 cases in 17.75s. A separate current-source owner gate passes 73 +metadata-owner, live-mutation, provenance-constructor and resolution-snapshot +cases in 1.34s. These scoped gates do not erase the retained broader offscreen +window failure or qualify a new benchmark source. Logs: +``/var/tmp/openhcs-pr394-main-cc9fcdfd4-integration-controls-20261002.log`` and +``/var/tmp/openhcs-pr394-current-maincc9-source-owner-controls-20261002.log``. + +The original, unchanged whole-branch R0 is rerun against cc9fcdfd4 and +133da74ec with tool revision 3b03785f4. It exits 1. Its only positive measures +remain source_metadata's one TypeSwitch and three TypeSwitchArms; the removed +virtual_workspace_metadata classifier contributes minus one switch and minus +four arms. The ownership decision retains scalar admission on +SourceMetadataFields and durable rejection on DurableSourceMetadata: the +grammar belongs to the field owner, while canonical runtime spelling and +literal durable spelling remain substitutable policies. Reintroducing the +decoder's duplicate validator or moving the grammar to an unrelated utility +would contradict that ownership. This adjudicates the relocation's architecture; +it does not declare the per-file ratchet passed or alter its implementation, +budget, exclusions or observations. Primitive/subclass admission, reported-class +read ordering, scalar/container precedence, exact errors and mutable lifetime +remain separate behavior obligations covered by the owner controls. Raw report: +``/var/tmp/openhcs-pr394-current-maincc9-original-r0-20261002.log``. + +The metadata-only whole-query prototype is rejected immediately after saved +replay: its five captured context calls still take about 55ms, with no matched +speedup demonstrated. Valid saved leaf gates pass, but constructor/subclass, +malformed-input and live-mutation obligations remain unresolved. Neither its +callback-based query abstraction nor its manually replayed constructor effects +are promoted. A separate source trace falsifies wholesale stack-rebuild removal: +23 of 32 loads already hit the whole-stack cache and memory saves retain typed +payload references. The entire load/unstack/save/identity envelope is only +1.3674s before mandatory work, insufficient to close the 1.3381s execution gap. +The next route must span repeated source derivation across existing request, +recording, stack and publication owners. Receipts: +``/var/tmp/openhcs-whole-source-query-exploratory-REJECTED-20261002.json`` and +``/var/tmp/openhcs-b764-whole-cohort-cycle-dominant-route-review-20261002.json``. + +Issue 435's fresh public MCP synthetic acceptance is RED on frozen 133da74ec. +The original five processing steps are unchanged; only owned output paths and +the unused required DAPI binding differ. The first attempt stops before runtime +creation because native TCP lock paths do not follow XDG storage. A fresh, +separately retained attempt admits only its declared private data/control lock +paths, completes mandatory preparation and compilation, then fails the fifth +step at the unchanged duplicate source-projection guard. Its exact owned runtime +is closed through the public API and all SDK children are terminal. This is a +real workflow failure that the existing same-occurrence unit fixture did not +cover; installed acceptance remains open. No original biological replay or +performance claim follows from this synthetic check. Source/input/dependency, +native, request/reply and failure evidence: +``/var/tmp/openhcs-derived-role-435-synthetic-acceptance-v2-20261002``. + +Current main integration and publication diagnosis, 2026-10-02 +----------------------------------------------------------- + +Main 283119c42 is normally merged after the declared independent-plane NLM +implementation and its documentation land. The combined affected NLM, +cold-feedback, agent-service, prepared geometry, native presentation and MCP +resource-lifetime controls pass 168 cases in 25.84s. Log: +``/var/tmp/openhcs-pr394-main-283119c42-integration-controls-20261002.log``. +The qualified benchmark sources and clocks above remain unchanged. + +The separately retained issue 435 public diagnostic reproduces the original +failure. Four actual projections show two correctly qualified main-flow images +but both retained artifacts address the same unqualified TIFF. The final raw +artifact overwrites the capped artifact. The same-occurrence ownership comparator +is never called: destination matching fails before that comparison. The existing +duplicate guard therefore detects a physical filename collision, not a guard +that should be relaxed. Both observer hooks call their original implementation +once; no capture errors are reported. The exact owned runtime is closed through +the public API and all SDK children are terminal. Receipt: +``/var/tmp/openhcs-derived-role-435-collision-facts-v3-20261002.json``. +An isolated repair on existing materialization-purpose and filename owners is +under review; its local test results do not yet establish public acceptance. + +The owned source-field composition prototype is also rejected: the eleven +captured valid leaves and additional mutation/constructor controls agree, but +the five context, three normalization and three identity calls save only 9.24ms +warm or 5.96ms cold. No candidate pipeline qualification or PR is opened for it. +Receipt: +``/var/tmp/openhcs-owned-source-composition-exploratory-REJECTED-20261002.json``. + +SaveImages reconstructs two source stacks solely for materialization metadata, +whose downstream consumer reads provenance. Its earlier 0.346s envelope includes +four contextualization children already measured elsewhere. After separating +those children in the retained diagnostics, the residual envelope is only about +0.10--0.114s. This is rejected as a standalone performance route; it cannot be +counted as an independent 0.346s saving. The complete source-query preimage was +not captured, so resulting metadata leaves are not a source-lookup replay. +Read-only audit: +``/var/tmp/openhcs-b764-save-images-artifact-subtree-readonly-audit-20261002.json``. + +Automatic image-role repair and public execution, 2026-10-02 +---------------------------------------------------------- + +Commits 0b6c66560 and 2d756646b repair the physical issue 435 collision on +existing owners. Artifact type and materialization purpose supply the retained +role; shared filename identity supplies parser-backed names. MaterializationBatch +binds the original rendering spec onto its existing context, because a public +caller may render a spec different from the compiled plan's default. The original +output plan and source references remain intact. Explicit exports keep their +authored paths. Both scalar and projected retained images preserve physical +coordinates and complete filename suffixes. Missing parsers use the existing +required-parser error policy. Strict projection and path-conflict guards remain +unchanged. + +The initial candidate's two actual-purpose mismatch controls fail before this +binding repair. The initial scoped R0 also reports a foreign optional-plan probe; +the corrected owner eliminates that probe without changing the guard. Original +scoped R0 and R1 pass for the complete repair versus 51533665e. Both original +failures are retained. Related controls pass 171 cases; after normal main +283119c42 integration at 053c9d445, 183 affected controls pass. An attempted +unrelated Torch NLM control stops at collection because Torch is absent; that +failure remains separate and no dependency changes follow. Handoff: +``/var/tmp/openhcs-automatic-image-role-435-reviewed-handoff-20261002.json``. + +The clean frozen 053c9d445 source completes public MCP startup preparation, +compilation and all five original processing steps. The output contains exactly +the two distinct qualified role TIFFs and two matching source-projection rows. +The fourth journey then stops at its inspection assertion: the API reports +PARTIAL with the sole missing-grid warning, because the synthetic declaration +does not supply plate grid dimensions. This original whole-journey RED is +retained; it is not a pixel-comparison failure or a completed fresh-process +readback acceptance. The runtime and all SDK children are terminal. Receipt: +``/var/tmp/openhcs-derived-role-435-synthetic-acceptance-v4-20261002/journey.json``. +Supplemental public inventory, complete pixel and fresh-process checks remain +pending on these unchanged outputs. + +The reviewed source is normally integrated into PR394 at fa694eb56. Its affected +current NLM, cold-feedback, agent-service, prepared geometry, native presentation, +MCP lifetime and new role controls pass 194 cases in 20.43s. Log: +``/var/tmp/openhcs-pr394-automatic-role-435-current-integration-controls-20261002.log``. +Neither this bug repair nor its public synthetic run establishes a performance +gain. Accepted benchmark clocks remain pinned to main4754 and candidateb764. + +The global runtime reassessment finds no sufficient measured optimization route +yet. Removing 485 provenance births and 485 identity births in captured context +leaves already saved only 4.82ms and changed malformed-input ordering. The next +candidate must remove whole repeated projection/adapter transactions, rather +than another constructor or field-query leaf. The strongest remaining joint +frontier is 3.0201s with incomplete whole-lane replay coverage; counts from the +instrumented profile cannot establish its reducible fraction. Audit and smallest +missing capture recipe: +``/var/tmp/openhcs-b764-whole-lifecycle-architecture-reassessment-20261002.json``. + +Issue 435 supplemental public readback passes on the unchanged V4 output. Two +fresh SDK processes expose identical complete inventory, sample and projection +facts. Both 1024-by-1024 float32 role images pass the unchanged existing CP pixel +comparison with zero out-of-tolerance pixels: raw maximum difference is zero; +capped maximum difference is 1.1920928955078125e-7 under atol=rtol=1e-6. Both +roles retain physical C2 and calibration within the existing inspection spacing +tolerance of 1e-12. The original controller, journey, inputs, source, dependencies, +native binaries and all physical output hashes remain unchanged, and both reader +children exit zero. The original V4 journey remains RED. The supplemental +inspection check follows the existing status policy, retaining PARTIAL for the +sole undeclared-grid warning without fabricating grid metadata; spacing uses the +existing inspection tolerance rather than literal equality after TIFF formatting. +This is synthetic source qualification, not original biological or installed-root +acceptance. Supplemental receipt: +``/var/tmp/openhcs-derived-role-435-v4-readback-supplement-20261002/receipt.json`` +(SHA256 4f0f0550e50aaff297d134ee5accf2b2da01297305394a155fe79e827b844fdf). + +Current source qualification and workload priority, 2026-10-02 +------------------------------------------------------------ + +Main 142196857 (callable documentation ownership) is normally merged at +9aa3918d2. The affected declared-documentation, agent-service, cold-feedback, +automatic-image-role and plane-NLM integration controls pass 170 cases in +14.77s. Log: +``/var/tmp/openhcs-pr394-main142-documentation-role-integration-controls-20261002.log``. + +A clean frozen 9aa3918d2 ordinary public-driver observation completes one CPU5 +inline worker/thread with compilation 2.103262s, execution 7.870635s and total +10.781240s. Server/library/kernel startup and shutdown remain outside pipeline +clocks. All six CSVs, 120 TIFFs, 180 disk projection references and three source +volume hashes agree exactly with the retained qualified reference and b764 +output; source, dependencies, interpreter and native binaries remain unchanged. +Native science is transitive through that exact reference. This single current +observation does not replace the earlier repeated ABBA comparison or establish +a new optimization gain. Receipt: +``/var/tmp/openhcs-pr394-role-qualified-3d-science-20261002.json``. + +The descriptive comparison against the two retained warm native 3D observations +(mean 14.395949s) is 1.829x execution and 1.335x total. 3D is weakest among the +three qualified representatives (3D, Advanced and IFC), whose OpenHCS revisions +differ. The global weakest case remains unknown: all30 cached native clocks +include subprocess startup and the older multicore CP scaling baseline is +projected. Historical WoundHealing, TrackObjects and worm cases require current +matched warm-native qualification before ranking the whole catalog. Receipt: +``/var/tmp/openhcs-current-native-workload-priority-revalidation-20261002.json``. + +The next whole-transaction diagnostic is rejected before launch when its saved +representative identity pairs predict 2,719,141,800 bytes for three 60-request +cohorts alone, exceeding the transport's 1GiB root budget. No pipeline is run +for V4 and none of its frozen files are changed. This prediction is not an +observed complete production roster. A saved grouped-graph experiment reduces +those three representative graphs to 81,450,818 bytes while preserving actual +saved payloads; cache subsets contain no arrays. A separate V5 preparation +must capture actual ordered requests and detached pre/post cache states before +its replay or a performance candidate can be admitted. Receipts: +``/var/tmp/openhcs-whole-cohort-v4-budget-preflight-REJECTED-20261002.json`` and +``/var/tmp/openhcs-grouped-identity-budget-saved-experiment-v3-20261002/receipt.json``. + +Fresh native qualification changes the primary target +--------------------------------------------------- + +Four additional ordinary current9aa cases now have matched source inventories +and actual warm native runs. Each native case excludes one warmup and retains +both measured repetitions. OpenHCS uses one CPU5 inline worker/thread, mandatory +READY warmup before compilation, the default OUTCOMES observer and memory policy. +Server startup and shutdown are excluded. The following ratios are descriptive: +one OpenHCS observation against the mean of two native observations, not a +repeated A/B optimization claim. Native time includes preparation, modules, +post-run and measurement closure, excluding imports, JVM startup and pipeline +loading; OpenHCS total includes compilation. + +.. list-table:: Current single-worker observations, seconds + :header-rows: 1 + + * - Case + - OpenHCS execution + - OpenHCS total + - Native mean + - Execution speedup + - Total speedup + * - WoundHealing + - 3.571737 + - 4.096850 + - 3.779188 + - 1.058x + - 0.922x + * - TrackObjects + - 5.036489 + - 6.400329 + - 8.276148 + - 1.643x + - 1.293x + * - UntangleWorms + - 2.194352 + - 3.206172 + - 2.974680 + - 1.356x + - 0.928x + * - UntangleWormsBrightField + - 3.064656 + - 4.264850 + - 6.152021 + - 2.007x + - 1.443x + +All eight comparisons pass the existing measurement/schema/discrete gate and +unchanged numeric tolerances. WoundHealing and BrightField also pass complete +saved-output science. TrackObjects and UntangleWorms fail saved-image content +comparison in both repetitions; their ratios therefore have measurement-only +qualification. Physical output inventories match. All original RED receipts +remain unchanged. TrackObjects saves 21 three-panel PNGs: original-image and +outline panels agree exactly, while the tracked-object panels are gray instead +of the native colored labels and white IDs. The current callable deletes the +requested saved-image options and returns its unchanged input image. Worm +images have matching backgrounds and colors but 96 differing outline pixels +across two outputs. Sparse-overlap rendering is a candidate cause requiring +actual producer inputs, not a proved segmentation diagnosis. + +WoundHealing is weakest among seven retained representative measurement-science +scopes, replacing 3D as the primary investigation. This is not a full-catalog +ranking. WoundHealing needs about 1.682142s execution reduction and 2.207256s +total reduction to reach twice its native throughput. Its native comparison +uses exactly two selected 2304-by-1536 RGB JPGs; TrackObjects uses all 21 selected +sequence frames, and both worm cases retain their actual source bindings and +training inputs. Source, dependencies, interpreter, native binaries and all +original inputs are frozen before and after. Evidence: +``/var/tmp/openhcs-current-slowcase-priority-and-png-audit-20261002.json`` +(SHA256 c84d5c0f39bf2a246e00eb7cbb42a7457849efb6a974a6d78fee0e68c6c270ef). + +The existing worker-owned profile on current9aa WoundHealing preserves exact +ordinary CSV outputs. It attributes 0.604904s to 22 runtime stack operations, +0.551025s to 16 image normalizations, 0.288266s to two centroid queries and +0.464524s to two color reductions. These profile durations are diagnostic costs, +not measured savings. Metadata composition itself is only 0.016512s. Source +recording's 0.251105s overlaps normalization and must not be added to it. Even +eliminating stacking, normalization and centroid costs entirely gives an +optimistic 1.444195s, below the execution gap before mandatory copies. Another +small metadata leaf is rejected as a sufficient route. Receipt: +``/var/tmp/openhcs-current9aa-wound-profile-dominant-frontier-20261002.json``. + +The bounded actual-input normalization capture completes successfully: all 16 +calls are recorded, with two unchanged V6 before/after graph pairs for the +large integer arrivals. Both consume the same two-frame uint8 RGB stack, +shape (2, 1536, 2304, 3), scale 255 and float32 target. Original input pixels +and public metadata remain unchanged; source/environment/native freezes pass. +Capture clocks are not performance evidence. Independent whole-output science +and original-leaf replay remain separate gates. Receipt: +``/var/tmp/openhcs-wound-intensity-leaf-capture-v1-20261002/observations.json``. +The generic consumer investigation must preserve exact compiled artifact +selection, source projection and stack-broadcast laws; raw integer pixels cannot +be relabeled as normalized unit-interval pixels to avoid a conversion. + +The former 3D grouped-cohort V5 diagnostic remains prepared and unlaunched after +this priority change. No rejected route is promoted because its preparation is +already complete. The tracking renderer is being investigated in an independent +main142 worktree with actual 21-frame producer inputs and exact native panel +replay; no saved-image repair is included or claimed here yet. + +Library readiness repair and latest qualification, 2026-10-02 +------------------------------------------------------------ + +Main 3f955d3fb (MCP sampling) and cf5a83f89 (fixture CLI repair) are normally +merged. The MCP/prepared-geometry/automatic-role integration gate records 354 +passes and nine failures. All nine fail identically on clean main3f955 with the +same readonly native-binary bindings: eight fixture declarations omit the +required server, and one expected stream-argument mapping omits display_config. +The first clean-main attempt refused a missing native extension at collection; +that original failure is retained before the exact-bound native supplement. +These are existing fixture failures, not a passing full suite. Numerical and +dependency sources are unchanged by the fixture-CLI merge. + +The actual Illumination3 first run reached an unprepared masked polynomial +specialization. Its Numba artifacts were written inside the measured polynomial +step: 0.526s versus 0.016s when already cached. The existing callable preparation +hook now prepares masked/unmasked and readonly canonical image/mask signatures +before READY. A fresh-cache subprocess forbids all later compilation and cache +loads across 36 dtype/layout/mutability/mask combinations and verifies an +independent polynomial oracle, input isolation and geometry errors. Twenty +preparation/fitted-illumination controls pass, with two existing skips. The fix +ships independently in merged PR474, formally closing issue473; original R0 +passes all three roots and original R1 passes its unchanged 160-second budget. +Main a6c18f054 is normally merged back into this branch. Its full receipt is +``docs/validation/polynomial-library-readiness-473-20261002.rst``. + +The clean frozen integrated source54708367b has fresh ordinary CPU5 one-worker, +one-thread observations using the existing cache, default OUTCOMES observer and +default memory policy: + +.. list-table:: Fresh post-repair observations, seconds + :header-rows: 1 + + * - Case + - Compilation + - Execution + - Pipeline total + * - Illumination3 + - 0.962373 + - 0.647611 + - 1.961545 + * - WoundHealing + - 0.346341 + - 3.916717 + - 4.575604 + +Startup/library/kernel preparation and shutdown remain outside pipeline clocks. +These are single observations, with no matched repair speedup or statistical +regression claim. Wound is slower than its retained earlier single observation; +that result is preserved rather than substituting the better sample. Both +authored Illumination3 NPY images and Wound's complete two-row Image.csv agree +byte-for-byte with the qualified unchanged references. Existing complete saved +inventory and CP-tolerance comparison gates pass. Native science is transitive +through those fully qualified references. The first validator incorrectly +expected two Wound tables rather than two rows; its failure remains retained, +and the V2 supplement checks the actual authored inventory without changing any +production comparison policy. Source, dependencies, interpreter, native binaries +and all inputs remain frozen. Receipt: +``/var/tmp/openhcs-pr394-masked-prewarm-ordinary-science-v2-20261002.json`` +(SHA256 21231dffa14dbe17bf824a4258f677e7d656122036da81e0b3d8c9c8bc2f9c02). + +Additional native qualification and remaining execution frontier +--------------------------------------------------------------- + +Current9aa Vitra uses one selected joined source set containing all four physical +resources, rather than two channel-derived image sets. Its two warm native +repetitions average 3.044868s; OpenHCS is 1.615775s execution and 2.908514s total. +Complete saved science passes for 2,233 table rows and its authored image in both +native repetitions. Earlier source-set controller refusals remain retained. +Receipt: +``/var/tmp/openhcs-current-vitra-native-timing-science-v3-20261002.json``. + +Illumination3's two warm native repetitions average 0.603076s. Its authored +pipeline saves two NPY images and no CSV. Complete existing inventory and image +science pass in both repetitions. The retained first OpenHCS observation is +1.309110s execution and 2.603767s total, containing the late polynomial +specialization described above; the fresh post-repair observation is recorded +separately. Cache-state differences prevent treating these as a matched repair +speedup. The global weakest full-catalog case remains unknown. Receipt: +``/var/tmp/openhcs-current-illumination3-native-timing-science-v1-20261002.json``. + +Wound's actual worker profile partitions 3.387111s into 1.536850s of disjoint raw +processing and 1.850261s of other runtime/recording work. The 22 stack operations +include 0.4036s in 16 aggregate image stacks, 0.1481s in object variants, 0.0538s +in main-flow/cache and 0.0023s in initial loading. Ten source-record +normalizations account for 0.2436s of the 0.5510s normalization envelope. These +are profiled costs and overlap the earlier source-query attribution; none are +accepted saved seconds. + +Actual Wound ON_DEMAND QA images are not forced by terminal OUTCOMES publication. +However, raw QA planes borrow object-variant pixels and shared validity masks; +their current aggregates establish independent mutable artifact buffers. +Deferral with equivalent eager per-plane copies cannot remove those copy bytes, +and zero-copy adoption without an ownership/lifetime proof is unsound. Existing +ArrayBridge geometry validation also forces concrete arrays at payload +construction. No lazy wrapper or second mutable identity cache is promoted. +The global AST owner/lifetime audit retains a bounded actual alias-capture plan: +``/var/tmp/openhcs-current9aa-wound-copy-lifetime-reassessment-20261002.json``. + +An external shared-geometry convex prototype preserves both actual saved input +graphs exactly. The outer 256-level call's warm local median changes from +0.260906s to 0.023542s, saving 0.237364s; the nested 16-level call overlaps it +and is never added as independent work. This is useful local evidence, not a +production pipeline gain. The nominal owner audit identifies existing shared +column-envelope and Bresenham authorities and a disconnected 15-kernel legacy +component; production migration and end-to-end qualification remain separate. +The shared dense-coordinate prototype also has exact actual Wound/Track input +replays and passing scoped R0/R1 after removing duplicated admission logic. +Its pre-domain allocation behavior for very sparse large label IDs remains +under review. Neither prototype is integrated here or counted as a speedup. + +Independent tracking PR468 is synced to main and passes 19 focused tests plus +unchanged scoped R0/R1. It remains draft: native saved-image differences shrink +from 77,726 to 3,340 text pixels, but full native PNG parity is still RED. It +formally links issue467. No parity gate, tolerance, scientific output or renderer +environment is weakened, and no tracking repair is included in this branch. + +Remaining acceptance still includes installed-root issue419 IPO/Shape and +Morph/DISTANCE consumers; issue433's original 13.36GB OOM allocation owner and +repeated READY behavior; installed-root issue435; and issue450's installed +prepared-Resize consumer. The original whole-branch scalar-classifier R0 RED +remains separately retained. These draft closing references do not establish +completion. Full native scaling, all30 benchmark reruns and fresh figures remain +outstanding, and the long-running performance goal stays active. + +Shared geometry release and coordinate-owner checkpoint +------------------------------------------------------ + +Main ``5b7f3c48d89da4415de001375d0e06de881153c9`` is normally merged. +Independent PR476 ships the shared quantized hull/Bresenham geometry and +officially closes issue475. Earlier hull issues158/268 and PR161 remain +completed. The full-source PR394 ABBA comparison pins eb2 versus b470: +BrightField total4.635292249 ->3.294145465s, Untangle3.234328632 ->2.311149861s, +Illumination1.988957128 ->1.892348221s. All16 complete saved outputs pass exact +science and source/env/native/input freezes. Wound is a variance control, not +an attributed hull saving. See the committed shared-quantized-hull report for +every sample, readiness/source guards and retained native-image RED. + +The existing object-label storage family now owns the single shared dense +coordinate reducer. Tracking and relationships inherit/use its primitive; +two duplicate kernels are removed. Resource/domain-effect and C/F/A readiness +controls pass. Isolated100 and integrated101 tests pass, both with2 existing +skips; original scoped R0/R1 pass unchanged against eb2. Frozen b470 versus +6e69 ordinary ABBA Wound total3.866369809 ->3.562642806s; Track execution +5.338271976 ->5.052027345s, but total6.629491309 ->6.684317434s regresses +with higher compilation. All8 full saved outputs/freeze gates pass. The separate +shared-dense-coordinate report retains all samples, no causal late-JIT claim +and the original tracking image RED. No reduction resolves issue433's original +allocation owner or the whole-branch scalar-classifier R0 RED. + +Owner WT remains /home/ts/code/projects/openhcs-shared-runtime-plumbing. All +production edits are committed here. Agent-owned implementation branches are +integrated; no additional unpublished production files are claimed. Frozen +benchmark WTs remain unchanged. Compared with receiving checkpoint eb2, new +production edits are precisely three CP geometry/illumination modules plus +core/runtime_object_labels.py and four CP backend/preparation/tracking/ +relationships modules. These are indirect numerical/coordinate and preparation +changes beyond the receiving review's original four-file eb2/wheel delta. +Installed receiving obligations419/433/435/450, whole-branch R0, full native +image parity, full-catalog/scaling and figures remain open. A first-wave fresh +four-case ordinary/native qualification is in progress, not a completed gate. + +Library readiness and saved-reader checkpoint, 2026-10-02 +------------------------------------------------------- + +Main ``b4405ff3541add6b91004002b7d6f389f1208636`` is normally merged. +Independent PR482 closes issue477 and PR486 closes issue481. Main's singleton +invocation fix passes 401 controls and original scoped R0/R1; its actual public +translocation observation is 1.679128s execution / 3.094840s total / 1.008657s +compilation. Both saved warm native repetitions pass full database, schema, +discrete and numerical measurements, properties, exact image and physical +inventory gates. This single main-based observation is not a measured gain. +Receipt: /var/tmp/openhcs-singleton-label-main-477-saved-native-science-20261002.json +(SHA256 5c5c4c497df1ee4b115aba42650941f451fac3ae3f784cfcfe3144e0ae94d6ac). + +Issue481 prepares canonical masked float32/float64 declumping signatures through +the existing morphology backend library lifecycle. Numerical bodies are +unchanged. Eight isolated controls and original scoped R0/R1 pass; cold and +disk-cache witnesses reject subsequent compilation or cache loading. Frozen +integrated ``adef79b4ff3825b35a41ef96b60f3bc421a5ddd5`` Speckles execution is +1.915174s, total 3.212164s, compilation 0.959121s. No kernel-cache writes occur +inside execution. All three scientific CSVs match the original fully native +qualified output exactly, with complete inventory and freezes. This necessary +readiness repair does not establish a speedup. Receipt: +/var/tmp/openhcs-pr394-morphology-ready-speckles-science-20261002.json +(SHA256 29526b6c5c37bbd840c706393b9290695894bc80a2247aedc7c718cb58ee5477). + +Issue479's saved relationship reader is integrated from ``2de4e021f``. It +validates directed edge declarations, object/image domains, reverse pairs and +redundant Parent/Children fields before using scalar projections. Saved +snapshots and cache transport retain endpoint correlations; typed value-only +snapshots explicitly retain UNKNOWN evidence. Both-root scoped R0 passes, +but original R1 remains RED for an unchanged validator's relocation (+1 core, +-1 interop, zero global type-check change). This is not all-guards admission. +The merged-parent controls pass 380; root integration passes 235. + +Corrected saved Beginner replay uses the actual complete output root. Both +native repetitions have exact two-image agreement, complete physical-file +coverage and five matching correlation keys / 2,093 directed pairs. Full +measurement parity remains RED: 80 extra Costes features and 63 missing Nuclei +child-mean features. The earlier helper's incorrect results-directory root and +missing-image report are rejected, retained harness evidence. Reader receipt: +/var/tmp/openhcs-relationship-479-full-saved-replay-v2-20261002/receipt.json. + +Issue487 isolates the first loss for unwanted Costes work: existing settings +postprocessing treats legacy Run all metrics=Accurate as true and overwrites +the five authored flags. Native CellProfiler uses this aggregate setting only +for UI visibility, including when Yes; individual choices remain authoritative. +The correct existing owner is ModuleOnlySettingBinding, with the obsolete +runtime override removed. Public-importer RED and native/global AST census are +retained. Qualification is in progress. Colocalization's ordinary 2.514475s +inclusive step cost inside 6.424050s execution is an upper bound, not measured +Costes-exclusive work or a promised saving. The separate 63 missing means +still require first-loss evidence. No numerical tolerance or parity gate changes. + +Compiler profiling confirms repeated effective-configuration construction and +cold schema analysis, but its timings overlap and are diagnostic only. A +private prototype is not admitted: default-factory/callback and mutable-state +laws remain unproved. This route is deferred while the larger unauthorized +metric execution is qualified. Full scaling and fresh figures remain pending; +the long-running optimization goal remains active. + +Requested CPA workspace production qualification +------------------------------------------------ + +Issue480 is integrated at ``38d02e20a795ad6f8c6457459c380995a798d0fe``. +The existing export settings retain authored workspace requests and panels; +nominal tool/axis leaves own the irreducible external grammar and derive +columns from the existing CPA dialect. The discarded settings validator is +removed. Publication uses the same existing export bundle/materialization +path. Full physical-file admission now consumes paths actually read by the +existing CPA equivalence report, instead of a manually synchronized suffix +roster. Unmatched files and failed readers cannot claim coverage. + +Original scoped R0 across all three roots and original R1 pass against2560; +138 agent controls and 81 root integration controls pass. An actual ordinary +QualityControl public run on clean, sealed38d observes 0.652361870s execution, +2.120112958s total and 1.088341713s compilation. Startup/readiness and shutdown +are excluded. No diagnostic hooks are installed. Both immutable saved native +repetitions pass database/schema/discrete/numerical measurements, nonempty +declared two-row Image table, requested workspace meaning, every physical +output and all source/input/dependency/native/controller freezes. This is a +correctness qualification, not a paired performance gain. The original V4 +missing-workspace inventory RED is retained unchanged. + +Complete receipt: +/var/tmp/openhcs-cpa-workspace-480-integrated-saved-native-v1-20261002.json +SHA256 72e22c3859081de0494ad24440d36a54b306adbaa509d8afcb9db87d671ece5d. +Ordinary source-freeze SHA256: +317de6735208ed9c99149d81296bf40dd3c1e70823e198da69b7cb7575d47e5d. +Standalone main isolation and its independent source checks are in progress; +the integrated result does not claim a main-only benchmark. + +The actual before-fix Beginner observation on frozen4904884 is execution +6.981277943s, total9.296563831s, compilation1.451889992s. It intentionally +preserves the reproduced issue487 metric bug and missing63parentmeans; no +parity exemption or speedup is claimed. Controller/source/environment/native +and complete actual input freezes pass. Source-freeze SHA256: +dc8a40519a10b7dd13ba9809a95bd6e2070622a326afa66ee2684adbe892a28d. +Issue487's source fix passes156 controls and original scoped R0/R1, but actual +candidate pipeline science and paired ordinary timing remain outstanding. + +Metric policy, saved parity and readiness follow-up, 2026-10-02 +------------------------------------------------------------- + +Main3705c071b13c29d354417d85dccf78c765b4a580 is normally merged at05ea538a. +Independent PR488 closes480 and PR489 closes487. Their production changes +are already integrated; subsequent main synchronization changes documentation +only. PR489 passes156 controls and original scoped R0/R1. Existing metric +declarations now derive enabled output columns; disabled Costes computations +and columns are omitted without changing enabled numerical implementations. + +Frozen baseline4904884 and sealed candidate d567d4d7 each have two cached +ordinary observations. Baseline execution5.527808428/5.327760458s and total +7.723725582/7.677667536s compare with candidate execution4.583703041/ +4.648376942s and total6.814110309/6.839743058s. Means improve execution +5.427784443 to4.616039992s (0.811744451s) and total7.700696559 to6.826926684s +(0.873769875s). Startup/readiness and shutdown are excluded; one worker +executes inline, with ordinary OUTCOMES and memory observation enabled. +This is a full-branch cached comparison, not an exclusive Costes attribution, +ABBA experiment, statistical claim or fully prewarmed qualification. + +The original baseline6.981277943/9.296563831s is excluded from that comparison: +three kernel overloads were written inside its pipeline timing window. The +later runs have no cache writes, which does not prove absence of cache loads. +Existing public library preparation omits object correlation and prepares +float64 threshold/RWC arrays; canonical runtime stages require float32 arrays. +A fresh private-cache public-preparation probe refuses later compilation and +cache loading: base passes; correlation, threshold and RWC fail. Requested +argument types exactly match retained production cache signatures. This is +readiness evidence using lawful synthetic values, not actual-input science +or performance evidence. Issue491 tracks canonical-stage preparation. + +All seven common CSV domains and two images are unchanged;100 unauthorized +Costes columns disappear (80 canonical and20 derived parent columns). +Candidate repeat scientific bytes are exact. Complete saved native replay +still fails solely for63 missing parent-mean features in both repetitions, +with no Costes, image, other numeric or physical-inventory differences. All +five relationship correlation keys and2093 pairs agree. Numerical tolerances +and required outputs are unchanged; full-case native parity remains RED. + +Issue492 identifies its first loss: all16 object-intensity tables exist, and +the producer has channel groups1/2/5/3, but compilation selects only child +channel3 for the prior-measurement input. Other channels never reach runtime +scope filtering. Repair belongs to the existing artifact relation/projection +contracts and must preserve child subject and image-set correlation. It adds +required scientific work; no speedup is claimed for this correctness repair. + +The bounded joint diagnostic pipeline succeeds with exact scientific bytes, +but capture admission is RED: no batch arrays are captured, and one final +store metadata event exceeds the4MiB cap. Earlier complete selection events +establish the bounded first-loss fact. The worker profile reaches28 serial +measurement invocations and zero batch calls; the earlier assumed batch +capture route is invalidated. A narrower serial-owner capture and nominal +batch-executor transport audit are next, not a claimed admitted replay. + +Cached comparison receipt: +/var/tmp/openhcs-beginner-metric-487-ordinary-cached-comparison-v1-20261002.json +SHA25636883d131c224f20b44139b02078c6ddba8b78a2e598901651910e12a92e4c2b. +Strict saved native receipt: +/var/tmp/openhcs-beginner-metric-487-strict-native-science-v1-20261002/receipt.json. +Fresh READY probe: +/var/tmp/openhcs-colocalization-public-ready-signatures-v2-20261002/observations.json. +Parent-mean first-loss receipt: +/var/tmp/openhcs-beginner-parent-means-first-loss-v2-20261002.json +SHA256c127ff3c79d82ddad4df38bb197606a25ee44a934e1909759922fc62b560f135. +Joint diagnostic admission/science receipt: +/var/tmp/issue487-joint-v2-original-admission-and-science-20261002.json +SHA256b29d5df0cd203e40a6e7f018e59b42d91e815a21af3e623811bc6b87a00ae53e. + +Whole-branch scalar-classifier R0 and issue479 validator-relocation R1 remain +RED. Installed419/433/435/450, original native image differences, full30-case +and scaling reruns and fresh figures remain open. The optimization goal stays +active; these measured gains do not redefine or complete the target. + +Canonical READY and current generic-query frontier +------------------------------------------------- + +PR493 is merged on mainb85f1e4add6075a71f4fd4e5ba7e2512e48990e5 and +closes491. Root normally integrates it atb015526c7c491abf80ea0958a08eb8723131c152. +Canonical image/object stages replace the duplicate kernel list and threshold +arithmetic.23 focused controls and original three-root R0/R1 pass; the actual +root fresh-cache integration control passes1test/9.86s. Compilation and disk +cache loading are refused after public preparation across IMAGE/OBJECT/BOTH +and threshold/Costes option states. This establishes readiness, not a speedup. + +One source-pinned Beginner diagnostic on clean b015 completes with exactly one +existing worker profile, nonempty existing runtime events,108 actual CP +executor calls,133 declared callable calls and no diagnostic errors. Profile +and event files occupy1.19MiB. Ten prelaunch controls preserve original calls, +errors, alias/mutation, descriptor/loader and thread partition behavior. The +instrumented12.9997s execution/15.2588s total is not an ordinary benchmark or +a regression. Profiling overhead is substantial and nonuniform. + +The same-thread orchestrator region partitions exactly12.988882s. This region +omits prior source/config decode; it is not the complete server-job clock. +Disjoint instrumented exclusive costs include module-output recording4.918576s, +declared callable invocations2.300491s, stack loading1.007764s, per-object output +recording0.920284s and worker residual0.861094s. cProfile costs overlap these +regions and must not be added or scaled to ordinary clocks. + +The determining generic query path makes312 full-column queries directly from +upstream parent-mean derivation:803488 structural-missing checks and195808 +qualification calls within those queries. Whole-worker structural checks are +1187866. Qualification precedes feature/source/row/object selection. Issue496 +tracks an operation-local schema/index fold on the existing nominal owners. +Opaque callback order, errors and mutation must remain observable; explicit +NaN propagation differs from default measurement-presence qualification. No new cache, +callback-identity dispatch or per-Relate numerical optimization is admitted. + +Strict replay of this diagnostic retains exactly63 missing parent means in both +saved native repetitions, with zero other numeric, image or inventory failures. +All seven CSVs/two TIFFs are byte-identical to ordinary candidated567; full +physical inventories agree and five correlation keys/2093pairs match. Source, +outputs, inputs, native and dependencies remain unchanged through replay. +Final all-zero science assertion correctly fails: no63-feature waiver exists. +Receipt /var/tmp/openhcs-current-generic-job-profile-strict-native-science-v1-20261002/receipt.json +SHA256bbc135e6de97628ddbabe8d350381a76a8af3000b4fba28f19e1879c27a220a8. + +Saved CSV readers cannot reconstruct preexport long rows, structural padding, +explicit missing cells, ownership or query order. That route is rejected; +metadata/relationship reader-domain errors are harness counterevidence, not +science failures. A bounded post492 actual logical-column/query capture must +demonstrate material absolute payoff before production optimization. The prior +ordinary Relate span near0.8s is only a whole-operation ceiling; the corrected +four-channel frontier and transfer remain unmeasured. + +Independent client residual evidence is0.818/0.804s for cached Beginner and +0.379s for QC. Two submissions occupy0.367/0.368s and0.120s respectively; +waiting beyond server clocks occupies0.03-0.08s. Four pipeline renders and +three config renders are observed in source, but their exact elapsed and byte +equality remain unproved. Blind memoization is rejected because shallow-frozen +documents contain mutable steps. This client-only route cannot remove server +execution work or independently close the seconds-wide target gap. + +Issue492's prepared four-channel/two-site repair passes its original controls +and guards. New prerequisite495 proves complete dynamic queries previously +ignored compiled producer path/backend, allowing foreign locations or an +ambiguous retained producer after legal rebinding. Existing planned query and +location authorities own the repair and point-in-time address law. Combined +qualification and actual full native63-field acceptance remain pending. + +The shared /home filesystem temporarily blocked Git commits. Only the owned +mutable worktree's website projection was made sparse through standard Git; +all75 website files were first preserved byte-exact at +/var/tmp/openhcs-owned-runtime-website-sparse-preserved-20261002/website with +their manifest receipt. Git objects retain the same files. This freed27MiB; +canonical ROOT, source code, benchmark inputs/outputs, dependencies and shared +caches were untouched. Earlier b015 source freezes completed before this +projection change; future freezes must explicitly record the sparse website. +All remaining acceptance and full-catalog/scaling/figure obligations stay open. + +Corrected producer domain, native parity and residual measurement frontier +------------------------------------------------------------------------ + +PR497 merges on main49f2fd3639363b7cc5e716eb3ba3a7358aa85429 and formally +closes492 and495. Its independently qualified production commit iseeed09233; +final6da19179 adds tracked qualification only. Original unchanged R0/R1 pass +against normally merged main6ce527a29 with no increased finding and unchanged +R1 budget.211 related controls pass;212 integrated controls pass11.78s with +two unrelated plugin configuration warnings. Global supplemental ownership +census covers704 modules/5228 original classes with no AST errors. + +InputObjectMeasurementSourceRelation derives complete measurement-producer +consumption through the existing input projection owner. The old planner and +RelateObjects selection algorithms are removed. Ordinary input and PLATE +selection remain intact. Dynamic queries resolve the actual compiled producer +path/backend and snapshot mutable group-address maps at query birth. The +meaningful old store-pickle control passed before planned lookup but failed +after caching a mapping-proxy address. Both lookup domains now use the existing +bounded store-owned cache lifetime; obsolete flat cache fields, initialization, +invalidation and transport paths are deleted. Ordered records, empty results, +replacement revision, eviction, primary/current/observation state and aliases +are covered. Arbitrary external plan/mapping callbacks and query-target callback +counts under bounded eviction remain outside the concrete production audit. + +Root integrates production at5ed0d13978db1cda92a490614d326525ad552af7. A fresh +uninstrumented ordinary Beginner1w1t completes with execution4.650205374s, +compilation1.603918076s and total7.070084621s. Mandatory READY, registry/kernel +warmup, process startup and shutdown are excluded. Execution is inline with one +thread; no measured fork/spawn startup. Default OUTCOMES and ordinary memory +observation are retained. The tracked75-file website-only sparse projection is +explicitly inventoried; no production source/input/dependency is omitted. +Source, Python, installed dependencies, native binaries and exact image/CPPipe +hashes are fixed before and after. This single correctness observation is not +causal optimization or statistical evidence. + +The unchanged strict reader consumes all seven CSVs and two TIFFs against BOTH +retained native repetitions: ZERO numeric/measurement differences, ZERO image +differences, complete physical inventory, and five correlation keys/2093pairs +on both sides. The63 missing parent means are restored. Only MyExpt_Nuclei.csv +changes scientifically versus the previous ordinary result. Reader/source and +output hashes remain unchanged through comparison. This execution uses the +integrated394/479 reader: it qualifies the producer repair's outputs, not a +standalone main-only execution or whole394 architecture gate. +Receipt /var/tmp/openhcs-child-measurements-492-integrated-strict-native-science-v1-20261002/receipt.json +SHA25637930ee4622c5fc1e067fc853bef1ae627ebe74546c27c3cc65d9fb476343ba0. +Tracked independent qualification: +docs/validation/child-measurement-producer-selection-492-495-20261002/QUALIFICATION.rst. + +The retained native warm-process invocations are15.270141648s and14.634740414s, +mean14.952441031s. A descriptive comparison to this single corrected execution +is3.215x execution and2.115x including OpenHCS compilation/client completion; +these are different sample counts, not a causal change or statistical claim. +Native invocation includes prepare/modules/post-run/close, with import/JVM, +CPPipe load and its warmup excluded. Startup is not added to either pipeline. +Other cases and full-catalog/scaling figures are not qualified by this case. + +The next actual logical-query capture executes438 queries over seven tables, +not four times the previous312. Its processor succeeds and all nine scientific +files are byte-identical to the qualified5ed ordinary output; complete physical +inventories match. Diagnostic admission correctly fails before writing any +logical graph: unchanged V6 refuses the150000-node unique-instance inventory. +No partial graph, increased limit, saved-CSV substitution or performance claim +is admitted. The profiled/captured14.1409s execution is diagnostic overhead, +not an ordinary regression. Preserve the original failure and source freeze. +Artifact /var/tmp/openhcs-measurement-query-logical-capture-v1-20261002/observations.json. +Scientific-byte receipt: +/var/tmp/openhcs-measurement-query-logical-capture-v1-scientific-byte-comparison-20261002.json. + +A revised diagnostic representation may pack numeric answer-oracle leaves while +preserving every actual query and the complete determining input/schema/alias +graph. Node/category counts and original replay must establish admission before +any matched candidate timing or production change. Existing150000-node, +32MiB graph,4MiB ledger and512MiB free-space limits remain unchanged. Pure +callback declarations alone do not license skipping arbitrary scalar equality +or string effects; original opaque callback/error/mutation order remains a +separate production wiring gate. + +The output-recording ownership audit also rejects a misleading second frontier: +coarse recorder-exclusive4.9186s contains the query496 subtree. In cProfile, +record_module_outputs self time is0.000638s, and measurement-table construction +contains Relate augmentation4.1412s/upstream query3.3457s. Those diagnostic +times cannot be added. Independent100-call object recording is dominated by +split_scoped_rows0.5620s diagnostic. Its18735-row domain has80 colocalization, +16 concatenated and4 shape batches. Existing row owners could remove dictionary +expansion, but no credible multi-second ordinary payoff is established; the +standalone route is rejected pending a necessary shared-query dependency. +Audit /var/tmp/openhcs-b015-output-recording-ownership-audit-20261002.json +SHA256b0bf2c90f50c1da5022f6aa2a657779f0bdd9390c0adfb022a86b5db21b10779. + +Root normally merges current main after all5ed jobs complete, at899aaddce; +that merge changes documentation/evidence only relative to5ed production. +Whole394 scalar-classifier R0 and479 validator-relocation R1 remain RED. +Installed419/433/435/450, outstanding native image differences, full30/scaling +reruns and fresh figures remain open. The unlimited optimization goal is ACTIVE. + +Profiler-free exclusive ledger and plate export correction +--------------------------------------------------------- + +The source-pinned5d50a0bb46ab4ccdd17bb9924ce698893f5ed85b diagnostic completes +with BOTH cProfile/runtime profiler disabled,24 coarse nominal boundaries and +14 meaningful prelaunch controls. Source/environment/native/input and explicit +website-only sparse witnesses remain fixed before/after. It retains32,223bytes +of JSON, no profile/capture artifacts and no diagnostic errors. All nine +scientific output bytes and the complete11-file inventory are identical to the +strict-both-native-qualified5ed ordinary result. Managed metadata differences +are recorded separately. No new native execution or tolerance waiver is used. + +Public execution4.703251600s/compilation1.568818331s/total7.089778207s are +diagnostic, not a causal gain or an estimate of wrapper overhead. The execution +region4.692535908s partitions into23 nonzero owner groups:133 hooked callable +invocations1.923475937s and2.769059971s outside that boundary. The invocation +boundary includes metadata/filtering and does NOT cover all registered calls. +In particular, execute_plate_scoped_steps directly resolves/calls PLATE exports. +Actual ExportToSpreadsheet progress is0.707153320s; it lies inside the +server-exclusive0.734300637s bucket. These intervals overlap and cannot be +added or subtracted as exact disjoint method costs. Server reconstruction is +therefore not established as the dominant0.734s term. Source/config decoding +also precedes this region. Compiler-exclusive1.009028861s includes genuine +fresh compilation, not a second artifact-reuse compile. + +Current measured exclusive query cost is0.481040613s/438calls. Nonquery module +recording is0.405474477s (inclusive0.886515090s), object recording0.156714182s, +stack loading0.184871211s, CP contract execution0.212007483s, worker remainder +0.140013289s, CP module remainder0.130000117s and image request0.086237226s. +Saving/publication/unstacking individually are smaller. Recording remainder +contains actual table creation, parent means and other required processing; it +is not isolated provenance. All-query/all-module/all-object recording has an +impossible elimination ceiling1.043229273s before retaining mandatory work. + +This invalidates the single-query route as the main multi-second fix. Its +18-control compact numeric-oracle capture preparation is retained but will not +be frozen/launched/polished without a necessary broader dependency. Existing +V6 and original limits remain unchanged. The new investigation maps common +columnar table/schema derivation across queries, recorders and the actual +spreadsheet publication path, retaining opaque scalar/callback semantics. +The exporter needs its own authority/phase analysis before a payoff claim. + +Ledger /var/tmp/openhcs-current-generic-runtime-ledger-v2-20261002/observations.json. +Corrected analysis /var/tmp/openhcs-current-generic-runtime-ledger-v2-analysis-plate-corrected-20261002.json +SHA2568b74fb088fae2527563fb42d38f3dedf5ab5ed936c5de805cd394343e3d0529c. +Byte gate /var/tmp/openhcs-current-generic-runtime-ledger-v2-scientific-byte-gate-20261002.json. +Original first-classification and correction receipts are both retained. +PR394's current description is rewritten around the remaining implementation; +merged fixes are described as dependencies and closed issue clauses removed. +Open persisted-publication134 now has an explicit closing link to draft394, +alongside384/419/433/435/450/479/176/496. None is claimed complete merely linked. diff --git a/docs/validation/singleton-label-invocation-477-20261002.rst b/docs/validation/singleton-label-invocation-477-20261002.rst new file mode 100644 index 0000000000..faad1c18a4 --- /dev/null +++ b/docs/validation/singleton-label-invocation-477-20261002.rst @@ -0,0 +1,92 @@ +Singleton label projection at the final invocation boundary (#477) +================================================================= + +The ordinary translocation benchmark failed on frozen ``6e69b851`` before +producing a successful well. Its OverlayOutlines invocation paired a scalar +640-by-640 RGB image with object labels on a declared singleton runtime root. +The image had a channel axis but no image-plane projection. Treating the RGB +channels as image planes would violate the existing strict axis contract. + +The input binding request initially derived label shape with the callable's +FLEXIBLE default. The module executor resolved the final NATURAL mode later, +after binding, so its semantic controls and the bound labels could disagree. + +Existing nominal ownership +------------------------- + +``ObjectLabelInputExecutionMode.invocation_kwargs`` now owns this final +projection. MATCH_IMAGE_STACK with a NATURAL scalar image may project an +already-bound label argument only when the original runtime declaration proves +exactly one plane. It delegates to the existing ``RuntimeSliceProjection`` and +merges the resolved semantic controls once. The module executor delegates to +that owner after resolving execution mode. + +Explicit FULL_STACK label declarations and FULL_STACK execution remain intact. +Multiple or unproved runtime axes and retained image-plane projections keep +their original strict guards. The fix neither invents an image axis nor reloads +artifacts. Redundant intermediate image/default-mode locals are removed. No +new policy class, cache, per-module exception, or color-processing change is +introduced. + +Source and local validation +--------------------------- + +The final isolated source is ``ccaa4cba6a1eca818cd544438941f1c1cedb3e32``, +integrated into PR #394 by ``1763ef07eba959dbefa7643cb90c8230fdf12518``. +The initial inline implementation and its original R0 failure are retained in +history; that route added GodClass, boolean-chain and foreign-absence metrics. +The final existing-owner implementation passes unchanged original R0 metrics +and original R1 with its original 160-second budget. + +The original reproducer recorded two expected failures and five passing +controls. The repaired module-consumer gate passes 402 controls. The global +source census parsed 703 modules with no errors. All five registered +MATCH_IMAGE_STACK consumers currently declare FLEXIBLE processing contracts. +External custom MATCH consumers with a non-FLEXIBLE stack-only contract have +not been qualified; this report makes no blanket callback-equivalence claim. + +The source-qualified receipt is +``/var/tmp/issue477-policy-owner-qualified-receipt-20261002.json`` with SHA256 +``7ebcd89739bbe58cf7630c093f02b92ecf41732a196073641ec373e4d9b019ca``. + +Actual public pipeline consumer +------------------------------- + +The frozen integrated source at +``/var/tmp/openhcs-pr394-singleton-label-qualified-20261002`` remains immutable. +Its ordinary public run completed both translocation and WoundHealing with one +successful well each, a reused READY server, one inline worker and one thread +on CPU 5. All input, native-binary, environment, dependency and tracked-source +freezes pass. Server/library/kernel preparation and shutdown are outside the +pipeline clocks; compilation and OUTCOMES closure remain inside total. + +The single observations are: + +================= ============== ============== ============== +Case Compilation(s) Execution(s) Total(s) +================= ============== ============== ============== +Translocation 0.527004 1.570796 2.539227 +WoundHealing 1.296431 2.897727 4.421997 +================= ============== ============== ============== + +These are correctness observations, not matched optimization evidence. +Wound's higher compilation observation is retained and its cause is unknown. +The original failed translocation clocks remain excluded from speedup claims. +The observation receipt is +``/var/tmp/openhcs-pr394-singleton-label-ordinary-v1-20261002/observations.json``; +its source-freeze SHA256 is +``ea4969dbfe48e7a42ff039b07a32eb0d2464374362b89588682483fa33039128``. + +Wound's complete authored output inventory, table comparison and exact +scientific bytes pass against the qualified ``9aa3918d`` reference. Its +two-row Image.csv SHA256 remains +``939735fa17a067137fea2adc77d57f9ce1df24bfcb6588c49023de1cc3998677``. +The read-only scientific receipt is +``/var/tmp/openhcs-pr394-singleton-label-wound-science-20261002.json`` with SHA256 +``7a8c3cafa33e54394d9a24f7744c6a6b641e48c6f712f1baab7c632dcace0655``. + +Translocation still requires fresh warm-native execution and complete authored +table, image, discrete-value and inventory comparison before issue acceptance. +The first native-controller preparation correctly rejected an auxiliary CSV +misclassified as an image input; its failure is retained. No tolerance change, +scientific-output exclusion or issue-closure claim is made here. diff --git a/external/ObjectState b/external/ObjectState index 9c31e4b07b..9fb5b7eeea 160000 --- a/external/ObjectState +++ b/external/ObjectState @@ -1 +1 @@ -Subproject commit 9c31e4b07b5537c0ed2307c5a63034c708b86bbb +Subproject commit 9fb5b7eeea96f3b7bb0579de30718bbcc0018823 diff --git a/external/PolyStore b/external/PolyStore index 84f322e468..89deeef366 160000 --- a/external/PolyStore +++ b/external/PolyStore @@ -1 +1 @@ -Subproject commit 84f322e46871de5ed47e7fd20976ad03e533c1c4 +Subproject commit 89deeef3662eabb11bc520fad9acd976698636bd diff --git a/external/pycodify b/external/pycodify index 792b034133..108a8edbf2 160000 --- a/external/pycodify +++ b/external/pycodify @@ -1 +1 @@ -Subproject commit 792b03413331fdf107e369c924c257a2f0b16126 +Subproject commit 108a8edbf25de258168756bac22c7572f018fa90 diff --git a/external/pyqt-reactive b/external/pyqt-reactive index ad4948775a..b64ed2eca9 160000 --- a/external/pyqt-reactive +++ b/external/pyqt-reactive @@ -1 +1 @@ -Subproject commit ad4948775ab81180a354d4b793d17ee5ddff3972 +Subproject commit b64ed2eca96fcdad29ba90beb545caa669a4d3d8 diff --git a/external/python-introspect b/external/python-introspect index 6f5ac0b79d..430fbbeeb6 160000 --- a/external/python-introspect +++ b/external/python-introspect @@ -1 +1 @@ -Subproject commit 6f5ac0b79d6cef163df6a8389e72a889a91ed548 +Subproject commit 430fbbeeb6c7e0a9274d3bf9b0998a10cae5a505 diff --git a/external/zmqruntime b/external/zmqruntime index f7b80c871e..04d813fe6c 160000 --- a/external/zmqruntime +++ b/external/zmqruntime @@ -1 +1 @@ -Subproject commit f7b80c871eb4773757368bb21f108920bf461881 +Subproject commit 04d813fe6c93f74166c05847afb1eae158d3c817 diff --git a/openhcs/agent/services/execution_session_service.py b/openhcs/agent/services/execution_session_service.py index df91176dd9..d4043a1557 100644 --- a/openhcs/agent/services/execution_session_service.py +++ b/openhcs/agent/services/execution_session_service.py @@ -5,12 +5,10 @@ import logging import time from abc import ABC, abstractmethod -from collections.abc import Callable from dataclasses import dataclass, replace from enum import Enum from itertools import count from pathlib import Path -from typing import Self from zmqruntime.execution import ExecutionProgressObservation from zmqruntime.startup import EndpointStartupPhase, EndpointStartupStatus @@ -76,6 +74,7 @@ from openhcs.microscopes.exceptions import MicroscopePixelSizeUnavailableError from openhcs.runtime.zmq_config import OPENHCS_ZMQ_CONFIG, OpenHCSZMQConfig from openhcs.runtime.zmq_execution_client import ( + ZMQExecutionRequestBuilder, ExecutionSubmissionPreparationTimeoutError, OpenHCSExecutionSubmission, ZMQExecutionClient, @@ -252,18 +251,9 @@ def endpoint_handshake(self) -> PongResponse | None: return None @abstractmethod - def submit_compile( + def submit_prepared_pipeline( self, - submission: OpenHCSExecutionSubmission, - *, - timeout_ms: int = OPENHCS_ZMQ_CONFIG.execution_submission_timeout_ms, - ) -> JsonObject: - raise NotImplementedError - - @abstractmethod - def submit_pipeline( - self, - submission: OpenHCSExecutionSubmission, + request: ZMQExecutionRequestBuilder, *, timeout_ms: int = OPENHCS_ZMQ_CONFIG.execution_submission_timeout_ms, ) -> JsonObject: @@ -303,48 +293,17 @@ def disconnect(self) -> None: raise NotImplementedError -ExecutionSubmitter = Callable[ - [ExecutionClientABC, OpenHCSExecutionSubmission, int], - JsonObject, -] - - class ExecutionJobKind(Enum): - COMPILE = ( - "compile", - lambda client, submission, timeout_ms: client.submit_compile( - submission, - timeout_ms=timeout_ms, - ), - ) - EXECUTE = ( - "execute", - lambda client, submission, timeout_ms: client.submit_pipeline( - submission, - timeout_ms=timeout_ms, - ), - ) - - def __new__( - cls, - value: str, - submitter: ExecutionSubmitter, - ) -> Self: - member = object.__new__(cls) - member._value_ = value - member._submitter = submitter - return member - - def submit( - self, - client: ExecutionClientABC, - submission: OpenHCSExecutionSubmission, - *, - timeout_ms: int, - ) -> JsonObject: - """Submit through the operation owned by this job kind.""" - - return self._submitter(client, submission, timeout_ms) + COMPILE = "compile" + EXECUTE = "execute" + + def prepare_request( + self, submission: OpenHCSExecutionSubmission + ) -> ZMQExecutionRequestBuilder: + """Admit the exact wire declaration selected by this job kind.""" + return ZMQExecutionRequestBuilder.from_task( + submission.compile_request() if self is self.COMPILE else submission + ) class ExecutionClientFactoryABC(ABC): @@ -363,21 +322,13 @@ class ZMQExecutionClientAdapter(ExecutionClientABC): def endpoint_handshake(self) -> PongResponse | None: return self.client.connected_endpoint - def submit_compile( - self, - submission: OpenHCSExecutionSubmission, - *, - timeout_ms: int = OPENHCS_ZMQ_CONFIG.execution_submission_timeout_ms, - ) -> JsonObject: - return dict(self.client.submit_compile(submission, timeout_ms=timeout_ms)) - - def submit_pipeline( + def submit_prepared_pipeline( self, - submission: OpenHCSExecutionSubmission, + request: ZMQExecutionRequestBuilder, *, timeout_ms: int = OPENHCS_ZMQ_CONFIG.execution_submission_timeout_ms, ) -> JsonObject: - return dict(self.client.submit_pipeline(submission, timeout_ms=timeout_ms)) + return dict(self.client.submit_prepared_pipeline(request, timeout_ms=timeout_ms)) def get_status( self, @@ -569,7 +520,7 @@ class ExecutionJobRecord: ref: ExecutionJobRef response: JsonObject client: ExecutionClientABC | None - submission: OpenHCSExecutionSubmission | None = None + request: ZMQExecutionRequestBuilder | None = None endpoint: PongResponse | None = None def status(self, response: JsonObject | None = None) -> ExecutionJobStatus: @@ -664,7 +615,7 @@ def register( response: JsonObject, client: ExecutionClientABC | None, *, - submission: OpenHCSExecutionSubmission | None = None, + request: ZMQExecutionRequestBuilder | None = None, endpoint: PongResponse | None = None, ) -> ExecutionJobRef: job_id = f"job-{next(self._counter)}" @@ -681,7 +632,7 @@ def register( ref=ref, response=response, client=client, - submission=submission, + request=request, endpoint=endpoint, ) return ref @@ -712,7 +663,7 @@ class ExecutionJobSubmission: client: ExecutionClientABC response: JsonObject - submission: OpenHCSExecutionSubmission + request: ZMQExecutionRequestBuilder endpoint: PongResponse | None @@ -720,7 +671,7 @@ class ExecutionJobSubmission: class CompletedPipelineExecution: """The exact ordinary submission and server-owned successful result.""" - submission: OpenHCSExecutionSubmission + request: ZMQExecutionRequestBuilder record: ExecutionRecord endpoint: PongResponse | None @@ -739,10 +690,11 @@ def submit( timeout_ms: int = OPENHCS_ZMQ_CONFIG.execution_submission_timeout_ms, ) -> ExecutionJobSubmission: client = self.factory.create_client(record.session.connection) - execution_request = record.submission(compile_artifact_id, auxiliary_params) + execution_request = kind.prepare_request( + record.submission(compile_artifact_id, auxiliary_params) + ) try: - response = kind.submit( - client, + response = client.submit_prepared_pipeline( execution_request, timeout_ms=timeout_ms, ) @@ -763,7 +715,7 @@ def submit( return ExecutionJobSubmission( client=client, response=dict(response), - submission=execution_request, + request=execution_request, endpoint=endpoint, ) @@ -1184,12 +1136,12 @@ def require_completed_pipeline_execution( raise RuntimeError( f"Pipeline execution {job_id} has no successful server result." ) - if job.submission is None: + if job.request is None: raise RuntimeError( f"Pipeline execution {job_id} has no retained submission." ) return CompletedPipelineExecution( - submission=job.submission, + request=job.request, record=snapshot.execution, endpoint=job.endpoint, ) @@ -1290,7 +1242,7 @@ def _submit_job( kind, submission.response, client=submission.client, - submission=submission.submission, + request=submission.request, endpoint=submission.endpoint, ) if wait and ref.server_execution_id is not None: diff --git a/openhcs/core/aligned_image_payload.py b/openhcs/core/aligned_image_payload.py index 7c6dfae012..ab5aa3cda5 100644 --- a/openhcs/core/aligned_image_payload.py +++ b/openhcs/core/aligned_image_payload.py @@ -6,10 +6,9 @@ from collections.abc import Iterator, Sequence from dataclasses import dataclass, replace from enum import Enum -from typing import Any, ClassVar, Mapping +from typing import Any, ClassVar, Mapping, TYPE_CHECKING import numpy as np -from metaclass_registry import AutoRegisterMeta from openhcs.core.image_payload_execution_mode import ( ImagePayloadExecutionMode, @@ -24,9 +23,6 @@ detect_memory_type, stack_runtime_slices, ) -from openhcs.core.registry_strategies import ( - NominalTypeKeyedStrategyMixin, -) from openhcs.core.runtime_image_values import ( ImagePayloadMetadata, ImagePayloadSliceProjector, @@ -49,7 +45,6 @@ RuntimePlaneAxis, RuntimePlaneAxisProjector, RuntimePlaneAxisValueProjection, - RuntimeSliceProjectableValue, ) from openhcs.core.runtime_slice_alignment import RuntimeSliceAlignedValueSet from openhcs.core.source_spatial_domain import ( @@ -57,6 +52,14 @@ SourceSpatialDomainAdapter, ) +if TYPE_CHECKING: + from openhcs.core.compiled_step_plan import CompiledStepPlan + from openhcs.core.steps.function_output_manifest import ProducedOutputSemantics + from openhcs.core.source_workspace_projection import ( + VirtualWorkspaceSourceProjection, + VirtualWorkspacePathLookup, + ) + @dataclass(frozen=True, slots=True) class ImagePayloadSourceSpatialDomainAdapter(SourceSpatialDomainAdapter): @@ -209,11 +212,10 @@ def value_in_payload_domain( ) -> RuntimeArrayData: """Project this image payload into another declared payload domain.""" materialized = self.payload_in_source_domain(self.value, target.domain) - target_domain = SourceSpatialDomain( + target_domain = replace( + self.domain, origin_yx=target.payload_domain.origin_yx, source_shape_yx=target.payload_domain.source_shape_yx, - fill_value=self.domain.fill_value, - value_name=self.domain.value_name, ) metadata = replace( image_payload_metadata(materialized), @@ -343,11 +345,10 @@ def value_in_payload_domain( target: SourceSpatialDomainAdapter, ) -> ObjectLabelValue: """Project every label variant into another declared payload domain.""" - target_domain = SourceSpatialDomain( + target_domain = replace( + self.domain, origin_yx=target.payload_domain.origin_yx, source_shape_yx=target.payload_domain.source_shape_yx, - fill_value=self.domain.fill_value, - value_name=self.domain.value_name, ) variants = self.value.variant_data.project( lambda labels: target.extract_source_array( @@ -373,11 +374,9 @@ class AlignedImageStackKwargResolver: reference_payload: Any | None = None def resolve(self, value: Any) -> Any: - strategy = AlignedImageStackKwargResolutionStrategy.require_nominal_value( - value, - context="Aligned image-stack kwarg resolution", - ) - return strategy.resolve(value, self) + from openhcs.core.runtime_slice_projection import RuntimeSliceProjectionStrategy + + return RuntimeSliceProjectionStrategy.aligned_kwarg_value(value, self) def resolve_source_spatial_value(self, value: Any) -> Any: """Project a nominal value into the declared reference payload domain.""" @@ -423,6 +422,141 @@ def composition_payloads(self) -> tuple[Any, ...]: ... @abstractmethod def composition_metadata_mode(self) -> ImagePayloadMetadataCompositionMode: ... + @staticmethod + def validate_main_flow_cohort( + producer_records: Sequence[ProducedOutputSemantics] | None, + ) -> None: + """One input cohort has one declared whole-image composition domain.""" + if producer_records and len( + {record.main_flow_plane_axis for record in producer_records} + ) != 1: + raise ValueError( + "One main-flow cohort cannot combine different declared image axes." + ) + + @staticmethod + def from_loaded_images( + payloads: Sequence[RuntimeArrayData], + *, + producer_records: Sequence[ProducedOutputSemantics] | None, + execution_plan: CompiledStepPlan, + source_projection: VirtualWorkspaceSourceProjection | None, + workspace_source_lookups: Sequence[VirtualWorkspacePathLookup], + ) -> RuntimeArrayData: + """Compose a selected admissible input cohort in its declared image domain.""" + if len(payloads) == 1 and ( + image_payload_metadata(payloads[0]).persists_whole_image() + or ( + producer_records + and len(producer_records) == 1 + and producer_records[0].main_flow_plane_axis + is image_payload_metadata(payloads[0]).plane_axis + ) + ): + main_data_stack = ImagePayloadStackComposition.copy_whole_image( + payloads[0], + memory_type=execution_plan.input_memory_type, + device_id=execution_plan.device_id_for(execution_plan.input_memory_type), + ) + else: + metadata_mode = ImagePayloadMetadataCompositionMode.STACK + if producer_records: + declared_axis = producer_records[0].main_flow_plane_axis + metadata_mode = ( + ImagePayloadMetadataCompositionMode.BUNDLE + if declared_axis is None + else ImagePayloadMetadataCompositionMode.for_plane_axis( + declared_axis + ) + ) + if source_projection is not None and workspace_source_lookups: + metadata_mode = source_projection.payload_composition_mode( + workspace_source_lookups + ) + if metadata_mode is ImagePayloadMetadataCompositionMode.STACK: + main_data_stack = stack_runtime_slices( + tuple(image_payload_data(payload) for payload in payloads), + execution_plan.input_memory_type, + execution_plan.device_id_for(execution_plan.input_memory_type), + ) + main_data_stack = stack_image_payload_context( + payloads, main_data_stack, metadata_mode=metadata_mode, + ) + elif metadata_mode is ImagePayloadMetadataCompositionMode.BUNDLE: + main_data_stack = ImagePayloadBundleContext.from_payloads( + tuple(payloads), metadata_mode=metadata_mode, + ).compose() + return main_data_stack + + @staticmethod + def copy_whole_image( + value: RuntimeArrayData, + *, + memory_type: str, + device_id: int | None, + ) -> RuntimeArrayData: + """Copy pixels, mask and metadata without adding a composition axis.""" + if isinstance(value, ImagePayloadStackComposition): + return value.copy_input_cohort( + memory_type=memory_type, device_id=device_id, + ) + copied_data = stack_runtime_slices( + (image_payload_data(value),), memory_type, device_id, + )[0] + mask = image_payload_mask(value) + copied_mask = ( + None if mask is None + else stack_runtime_slices((mask,), memory_type, device_id)[0] + ) + return image_payload_metadata(value).replace_fields().payload_with( + copied_data, copied_mask, + ) + + def copy_input_cohort( + self, *, memory_type: str, device_id: int | None, + ) -> RuntimeArrayData: + """Copy the dense image domain owned by this composition.""" + return self.copy_whole_image( + self.compose(), memory_type=memory_type, device_id=device_id, + ) + + @staticmethod + def with_saved_output_context( + stack_payload: RuntimeArrayData, + payloads: Sequence[RuntimeArrayData], + metadata: Sequence[ImagePayloadMetadata], + *, + single_output_plane_axis: RuntimePlaneAxis | None, + ) -> RuntimeArrayData: + """Attach saved member context without replacing the independent buffer.""" + data = image_payload_data(stack_payload) + if ( + len(payloads) == 1 + and single_output_plane_axis is metadata[0].plane_axis + and np.shape(data) == np.shape(image_payload_data(payloads[0])) + ): + return metadata[0].replace_fields().payload_with( + data, image_payload_mask(stack_payload), + ) + if np.shape(data)[:1] != (len(payloads),): + raise ValueError( + "Output stack must match its declared output slice count: " + f"stack shape {np.shape(data)!r}, slice count {len(payloads)}." + ) + mode = ( + ImagePayloadMetadataCompositionMode.for_plane_axis( + image_payload_metadata(stack_payload).plane_axis, + ) + if isinstance(stack_payload, ImagePayloadMetadataCarrier) + else ImagePayloadMetadataCompositionMode.STACK + ) + output_metadata = ImagePayloadMetadata.compose( + tuple(payloads), mode=mode, source_metadata=tuple(metadata), + ) + return output_metadata.payload_with( + data, _stack_image_payload_mask(tuple(payloads), data), + ) + def composition_source_metadata(self) -> tuple[ImagePayloadMetadata, ...]: return tuple( self.composition_payload_metadata(image_payload_metadata(payload)) @@ -494,23 +628,6 @@ def stack_image_payloads( return ImagePayloadStackContext(image_payloads, metadata_mode).compose() -def stack_image_payload_context_from_metadata( - image_payloads: Sequence[Any], - stack: RuntimeArrayData, - metadata_by_payload: Sequence[ImagePayloadMetadata], - *, - metadata_mode: ImagePayloadMetadataCompositionMode, -) -> Any: - """Attach composed image context using already resolved payload metadata.""" - payloads = tuple(image_payloads) - metadata = ImagePayloadMetadata.compose( - payloads, - mode=metadata_mode, - source_metadata=tuple(metadata_by_payload), - ) - return metadata.payload_with(stack, _stack_image_payload_mask(payloads, stack)) - - def _stack_image_payload_mask( image_payloads: Sequence[Any], stack: RuntimeArrayData, @@ -592,149 +709,6 @@ def unstack_image_payload_context( return projector.payloads_for_slices(slices) -class AlignedImageStackKwargResolutionStrategy( - NominalTypeKeyedStrategyMixin, - ABC, - metaclass=AutoRegisterMeta, -): - """Nominal strategy for resolving one slice-aligned runtime kwarg.""" - - __registry_key__ = "value_type_label" - __skip_if_no_key__ = True - __registry__: ClassVar[ - dict[str, type["AlignedImageStackKwargResolutionStrategy"]] - ] = {} - value_type: ClassVar[type[Any] | None] = None - value_type_label: ClassVar[str | None] = None - - @abstractmethod - def resolve( - self, - value: Any, - resolver: AlignedImageStackKwargResolver, - ) -> Any: - """Return the value in the current aligned slice context.""" - - -class TupleAlignedKwargResolutionStrategy(AlignedImageStackKwargResolutionStrategy): - """Resolve tuple-valued kwargs elementwise while preserving tuple structure.""" - - value_type = tuple - - def resolve( - self, - value: Any, - resolver: AlignedImageStackKwargResolver, - ) -> Any: - return tuple(resolver.resolve(item) for item in value) - - -class ImagePayloadAlignedKwargResolutionStrategy( - AlignedImageStackKwargResolutionStrategy -): - """Resolve image payloads without discarding metadata or masks.""" - - value_type = ImagePayloadMetadataCarrier - - def resolve( - self, - value: Any, - resolver: AlignedImageStackKwargResolver, - ) -> Any: - return resolver.resolve_source_spatial_value(value) - - -class ObjectLabelAlignedKwargResolutionStrategy( - AlignedImageStackKwargResolutionStrategy -): - """Resolve object labels by runtime-slice and source-spatial contracts.""" - - value_type = ObjectLabelValue - - def resolve( - self, - value: Any, - resolver: AlignedImageStackKwargResolver, - ) -> Any: - if not isinstance(value, ObjectLabelValue): - raise TypeError( - "Object-label aligned kwarg resolution requires ObjectLabelValue." - ) - slice_count = value.runtime_slice_plane_count() - if slice_count is not None: - if slice_count != resolver.projection_axis.axis_size: - raise ValueError( - "Runtime-slice object-label cardinality must exactly match the " - f"declared projection axis: {slice_count} != " - f"{resolver.projection_axis.axis_size}." - ) - from openhcs.core.runtime_slice_projection import RuntimeSliceProjection - - projected = RuntimeSliceProjection.value_for_slice( - value, - resolver.projection_axis, - ) - else: - projected = value - return resolver.resolve_source_spatial_value(projected) - - -class RuntimeSliceAlignedValueKwargResolutionStrategy( - AlignedImageStackKwargResolutionStrategy -): - """Select non-image values that explicitly declare runtime-slice alignment.""" - - value_type = RuntimeSliceAlignedValueSet - - def resolve( - self, - value: Any, - resolver: AlignedImageStackKwargResolver, - ) -> Any: - if not isinstance(value, RuntimeSliceAlignedValueSet): - raise TypeError( - "RuntimeSliceAlignedValueKwargResolutionStrategy requires " - "RuntimeSliceAlignedValueSet." - ) - return resolver.projection_axis.aligned_value(value) - - -class RuntimeSliceProjectableAlignedKwargResolutionStrategy( - AlignedImageStackKwargResolutionStrategy -): - """Project values through their declared runtime-slice hook.""" - - value_type = RuntimeSliceProjectableValue - - def resolve( - self, - value: Any, - resolver: AlignedImageStackKwargResolver, - ) -> Any: - from openhcs.core.runtime_slice_projection import RuntimeSliceProjection - - return RuntimeSliceProjection.value_for_slice( - value, - resolver.projection_axis, - ) - - -class PassThroughAlignedKwargResolutionStrategy( - AlignedImageStackKwargResolutionStrategy, -): - """Leave non-slice-aligned kwargs in their native runtime domain.""" - - value_type = object - - def resolve( - self, - value: Any, - resolver: AlignedImageStackKwargResolver, - ) -> Any: - del resolver - return value - - @dataclass(frozen=True, slots=True) class ImagePayloadComposition: """Resolved image payload plus its execution mode.""" @@ -992,6 +966,11 @@ class AlignedImageSliceContext: projection_key: str artifact_kind: str | None = None + @property + def persisted_source_alias(self) -> str | None: + """Expose a declared artifact name, preserving anonymous main flow.""" + return self.output_key if self.artifact_kind is not None else None + @classmethod def main_flow( cls, @@ -1140,6 +1119,17 @@ def composition_payloads(self) -> tuple[Any, ...]: def composition_metadata_mode(self) -> ImagePayloadMetadataCompositionMode: return ImagePayloadMetadataCompositionMode.STACK + @property + def projected_output_composition_mode(self) -> ImagePayloadMetadataCompositionMode | None: + """Declare the outer runtime axis retained by projected output members.""" + return self.composition_metadata_mode + + def plane_axis_for_output_context( + self, context: AlignedImageSliceContext, + ) -> RuntimePlaneAxis | None: + """An explicitly aligned stack declares its outer runtime-slice domain.""" + return RuntimePlaneAxis.RUNTIME_SLICE + def composition_payload_metadata( self, metadata: ImagePayloadMetadata ) -> ImagePayloadMetadata: @@ -1185,14 +1175,112 @@ def with_slices(self, slices: Sequence[Any]) -> "AlignedImageStack": return type(self)(tuple(slices), self.slice_contexts) + def copy_input_cohort( + self, *, memory_type: str, device_id: int | None, + ) -> "AlignedImageStack": + """Retain aligned member domains while admitting independent buffers.""" + return self.with_slices( + tuple( + self.copy_whole_image( + payload, memory_type=memory_type, device_id=device_id, + ) + for payload in self.slices + ) + ) + def projected_output_slices( self, ) -> Iterator[tuple[Any, AlignedImageSliceContext | None]]: """Project each output once together with its declaration-owned context.""" contexts = self.slice_contexts or (None,) * len(self.slices) for payload, context in zip(self.slices, contexts, strict=True): - for output_slice in payload_slices_for_alignment(payload): - yield output_slice, context + if image_payload_metadata(payload).persists_whole_image(): + yield payload, context + else: + for output_slice in payload_slices_for_alignment(payload): + yield output_slice, context + + def copy_projected_output_stack( + self, + projected_outputs: Sequence[tuple[Any, AlignedImageSliceContext | None]], + *, + memory_type: str, + device_id: int | None, + ) -> RuntimeArrayData | None: + """Prepare an independent output buffer in this owner's declared domain.""" + payloads = tuple(payload for payload, _context in projected_outputs) + metadata_mode = self.projected_output_composition_mode + if metadata_mode is None: + return self.copy_whole_image( + payloads[0], memory_type=memory_type, device_id=device_id, + ) + data = tuple(image_payload_data(payload) for payload in payloads) + declared_axes = { + self.plane_axis_for_output_context(context) + for _payload, context in projected_outputs + } + if len(declared_axes) != 1 or len({tuple(np.shape(item)) for item in data}) != 1: + return None + if metadata_mode is ImagePayloadMetadataCompositionMode.BUNDLE: + return ImagePayloadBundleContext.from_payloads( + payloads, metadata_mode=metadata_mode, + ).compose() + stacked = stack_runtime_slices(data, memory_type, device_id) + return stack_image_payload_context( + payloads, stacked, metadata_mode=metadata_mode, + ) + + def output_values_for_artifact_specs( + self, + canonical_specs: tuple[ArtifactSpec, ...], + ) -> dict[ArtifactSpecRef, Any]: + """Bind one complete declared main-flow roster to exact slice contexts.""" + + if not self.slice_contexts: + raise ValueError( + "Multiple canonical output specs require exact AlignedImageStack " + "slice contexts; positional slice order is not artifact identity." + ) + + specs_by_context = { + (spec.name, spec.artifact_type.value): spec for spec in canonical_specs + } + if len(specs_by_context) != len(canonical_specs): + raise ValueError("Canonical output ABI contains duplicate named contexts.") + resolved: dict[ArtifactSpecRef, Any] = {} + for payload, context in zip( + self.slices, + self.slice_contexts, + strict=True, + ): + if context.output_kind != AlignedImageSliceContext.MAIN_FLOW_OUTPUT_KIND: + raise ValueError( + "Canonical AlignedImageStack contains a non-main-flow slice " + f"context: {context!r}." + ) + context_key = (context.output_key, context.artifact_kind) + spec = specs_by_context.get(context_key) + if spec is None: + raise ValueError( + "Canonical AlignedImageStack context is not declared by the " + f"callable ABI: {context!r}." + ) + ref = spec.ref() + if ref in resolved: + raise ValueError( + "Canonical AlignedImageStack contains duplicate context for " + f"{ref!r}." + ) + resolved[ref] = payload + missing = tuple( + spec.ref() for spec in canonical_specs if spec.ref() not in resolved + ) + if missing: + raise ValueError( + "Canonical AlignedImageStack does not carry every declared output: " + f"{missing!r}." + ) + return resolved def output_payload( self, @@ -1234,6 +1322,33 @@ def composition_payloads(self) -> tuple[Any, ...]: def composition_metadata_mode(self) -> ImagePayloadMetadataCompositionMode: return ImagePayloadMetadataCompositionMode.BUNDLE + @property + def projected_output_composition_mode(self) -> ImagePayloadMetadataCompositionMode | None: + """Flatten declared inner runtime planes, retaining other named image domains.""" + if any( + image_payload_metadata(payload).plane_axis is RuntimePlaneAxis.RUNTIME_SLICE + for payload in self.slices + ): + return ImagePayloadMetadataCompositionMode.STACK + if len(self.slices) == 1: + return None + return self.composition_metadata_mode + + def plane_axis_for_output_context( + self, context: AlignedImageSliceContext, + ) -> RuntimePlaneAxis | None: + """Resolve a named output's original inner domain before leaf projection.""" + payloads = tuple( + payload for payload, declared_context in zip(self.slices, self.slice_contexts, strict=True) + if declared_context == context + ) + if len(payloads) != 1: + raise ValueError( + "Named image output context requires exactly one original payload: " + f"{context!r}; found {len(payloads)}." + ) + return image_payload_metadata(payloads[0]).plane_axis + def composition_payload_metadata( self, metadata: ImagePayloadMetadata ) -> ImagePayloadMetadata: @@ -1278,26 +1393,6 @@ def pack_aligned_image_outputs( return AlignedImageStack(packed) -class NestedAlignedImageStackKwargResolutionStrategy( - AlignedImageStackKwargResolutionStrategy -): - """Select matching slices from kwargs that are already aligned stacks.""" - - value_type = AlignedImageStack - - def resolve( - self, - value: Any, - resolver: AlignedImageStackKwargResolver, - ) -> Any: - return resolver.resolve( - value.aligned_slice( - resolver.projection_axis.require_plane_index(), - resolver.projection_axis.axis_size, - ) - ) - - def compose_aligned_image_payload( owner_name: str, image_payloads: tuple[Any, ...], diff --git a/openhcs/core/artifacts.py b/openhcs/core/artifacts.py index 635e6f958a..7fee966e4d 100644 --- a/openhcs/core/artifacts.py +++ b/openhcs/core/artifacts.py @@ -24,6 +24,7 @@ from openhcs.core.component_set import ComponentSet if TYPE_CHECKING: + from openhcs.core.steps.function_output_identity import FunctionOutputIdentity from openhcs.core.callable_contract import FunctionStepExecutionScope from openhcs.core.function_patterns import FunctionInvocationKey from openhcs.core.artifact_key_selection import AdapterRecordedArtifactOutputPolicy @@ -31,8 +32,15 @@ RuntimeValue, ) from openhcs.core.runtime_image_values import ImagePayloadMetadata + from openhcs.core.runtime_plane_projection import ( + RuntimePlaneAxisValueProjection, + RuntimePlaneAxisProjector, + ) + from openhcs.core.runtime_tabular_values import ColumnarRows + from openhcs.core.source_image_provenance import SourceImageProvenance from openhcs.core.runtime_measurements import ( MeasurementSubject, + MeasurementTable, RuntimeMeasurementFeatureOwner, ) from openhcs.core.runtime_slice_alignment import RuntimeSliceAlignedValueSet @@ -215,6 +223,98 @@ def materialization_base_path( del source_filename, uses_source_identity_filename, image_output_dir return Path(analysis_output_dir) / descriptor_filename + @classmethod + def retained_filename_qualifier(cls, artifact_name: str) -> str | None: + """Retain families whose existing paths already own artifact identity.""" + return None + + @classmethod + def contextualize_output( + cls, + source_payload: object, + output_value: object, + output_plan: "ArtifactOutputPlan | None", + plane_projection: "RuntimePlaneAxisValueProjection | None", + ) -> object: + """Context-free kinds preserve their actual returned value.""" + return output_value + + @classmethod + def contextualize_output_from_projector( + cls, + source_payload: object, + output_value: object, + output_plan: "ArtifactOutputPlan | None", + plane_projector: "RuntimePlaneAxisProjector | None", + ) -> object: + """Keep context-free artifacts outside image-axis projection.""" + return output_value + + @staticmethod + def output_owns_source_context( + source_payload: object, + output_value: object, + output_plan: "ArtifactOutputPlan | None", + plane_projection: "RuntimePlaneAxisValueProjection | None", + ) -> bool: + return False + + @classmethod + def contextualize_projected_output( + cls, + source_payload: object, + output_value: object, + output_plan: ArtifactOutputPlan | None, + plane_projector: RuntimePlaneAxisProjector | None, + ) -> object: + """Resolve plane projection only after the artifact strategy is selected.""" + + from openhcs.core.runtime_image_values import ( + preserve_declared_image_payload_axis, + ) + from openhcs.core.runtime_plane_projection import ( + RuntimePlaneAxis, + RuntimePlaneAxisValueProjection, + ) + + plane_projection = ( + None + if plane_projector is None + else preserve_declared_image_payload_axis( + plane_projector, + output_value, + source_payload=source_payload, + ) + ) + if ( + plane_projection is None + and output_plan is not None + and output_plan.variable_components + ): + if plane_projector is None: + if not cls.output_owns_source_context( + source_payload, + output_value, + output_plan, + None, + ): + raise ValueError( + f"Artifact output {output_plan.ref()!r} preserves variable " + f"components {output_plan.variable_components!r} but the " + "runtime invocation supplies no plane projector." + ) + return output_value + plane_projection = RuntimePlaneAxisValueProjection.require_from_projector( + plane_projector, + RuntimePlaneAxis.RUNTIME_SLICE, + ) + return cls.contextualize_output( + source_payload, + output_value, + output_plan, + plane_projection, + ) + @classmethod def normalize_runtime_payload( cls, @@ -236,6 +336,11 @@ def normalize_source_payload( return data, channel_axis + @classmethod + def source_image_payload_from_runtime_value(cls, value: object) -> object | None: + """Read image context from this artifact's currently resolved payload.""" + return None + @classmethod def compose_runtime_values( cls, @@ -385,6 +490,215 @@ class ImageArtifactType(ArtifactType): participates_in_main_flow_output = True carries_source_image_context = True + @staticmethod + def output_owns_source_context( + source_payload: object, + output_value: object, + output_plan: ArtifactOutputPlan | None, + plane_projection: RuntimePlaneAxisValueProjection | None, + ) -> bool: + """Return whether an image result already carries complete source identity.""" + + from openhcs.core.aligned_image_payload import ( + AlignedImageStack, + flatten_aligned_image_payload_slices, + ) + from openhcs.core.runtime_image_values import image_payload_metadata + + if not isinstance(output_value, AlignedImageStack) and not ( + image_payload_metadata(output_value).has_complete_source_identity( + output_value, + plane_projection, + ) + ): + return False + output_surfaces = flatten_aligned_image_payload_slices(output_value) + if not all( + image_payload_metadata(output_surface).has_complete_source_identity( + output_surface + ) + for output_surface in output_surfaces + ): + return False + if output_plan is None: + return True + source_surfaces = flatten_aligned_image_payload_slices(source_payload) + return len(output_surfaces) == len(source_surfaces) and all( + image_payload_metadata( + output_surface + ).source_provenance.represented_source_identities + == image_payload_metadata( + source_surface + ).source_provenance.represented_source_identities + for source_surface, output_surface in zip( + source_surfaces, + output_surfaces, + strict=True, + ) + ) + + @classmethod + def contextualize_output( + cls, + source_payload: object, + output_value: object, + output_plan: ArtifactOutputPlan | None, + plane_projection: RuntimePlaneAxisValueProjection | None, + ) -> object: + import numpy as np + from openhcs.core.aligned_image_payload import AlignedImageStack + from openhcs.core.projected_image_output import ( + SourceProjectedImageOutput, + ImageOutputSourceContextStrategy, + ) + from openhcs.core.runtime_artifact_values import RuntimeValue + from openhcs.core.runtime_image_values import ( + image_payload_metadata, + image_payload_data, + ) + from openhcs.core.runtime_plane_projection import ( + RuntimePlaneAxis, + RuntimePlaneAxisValueProjection, + ) + from openhcs.core.runtime_slice_alignment import ( + RuntimeSliceAlignedValueSet, + RuntimeSliceAlignedValues, + ) + from openhcs.core.runtime_slice_projection import RuntimeSliceProjection + + if isinstance(output_value, SourceProjectedImageOutput): + return output_value.resolve_source_context(source_payload, plane_projection) + if isinstance(output_value, RuntimeSliceAlignedValueSet): + if ( + plane_projection is None + or plane_projection.axis is not RuntimePlaneAxis.RUNTIME_SLICE + ): + raise ValueError( + "Runtime-slice-aligned image output requires an exact runtime " + "slice projection." + ) + if plane_projection.axis_size != output_value.slice_count: + raise ValueError( + "Runtime-slice-aligned image output count must exactly match " + "the declared runtime plane axis: " + f"{output_value.slice_count} != {plane_projection.axis_size}." + ) + contextualized_slices = [] + for slice_index in range(output_value.slice_count): + item = output_value.value_for_slice(slice_index) + contextualized_slices.append( + cls.contextualize_output( + RuntimeSliceProjection.value_for_slice( + source_payload, + RuntimePlaneAxisValueProjection.from_selected_plane( + axis=plane_projection.axis, + plane_index=slice_index, + axis_size=plane_projection.axis_size, + ), + ), + item.data if isinstance(item, RuntimeValue) else item, + output_plan, + None, + ) + ) + return RuntimeSliceAlignedValues(tuple(contextualized_slices)) + source_ref = ( + None if output_plan is None else output_plan.source_context_source() + ) + if ( + output_plan is not None + and output_plan.variable_components + and plane_projection is not None + and plane_projection.plane_index is None + ): + output_metadata = image_payload_metadata(output_value) + if ( + output_metadata.plane_axis is None + and output_metadata.source_provenance.source_plane_count + == plane_projection.axis_size + and plane_projection.dense_shape_carries_axis( + np.shape(image_payload_data(output_value)) + ) + ): + output_value = output_metadata.replace_fields( + plane_axis=plane_projection.axis, + ).attach_to(output_value) + if output_plan is not None and not output_plan.variable_components: + output_metadata = image_payload_metadata(output_value) + if output_metadata.plane_axis is RuntimePlaneAxis.RUNTIME_SLICE: + output_value = RuntimeSliceProjection.value_for_singleton_slice( + output_value, + source_description=f"Image output {output_plan.ref()!r}", + ) + source_metadata = image_payload_metadata(source_payload) + if source_metadata.plane_axis is RuntimePlaneAxis.RUNTIME_SLICE: + if source_ref is None: + raise ValueError( + f"Image output {output_plan.ref()!r} consumes a runtime " + "stack without a declared source-context relation." + ) + collapsed_metadata = source_metadata.collapse_leading_plane_axis() + source_payload = collapsed_metadata.with_source_provenance( + collapsed_metadata.source_provenance.with_source_image_names( + (source_ref.name,) + ) + ).attach_source_context_to(output_value) + plane_projection = None + source_context_strategy = ImageOutputSourceContextStrategy.for_source_payload( + source_payload, + ) + if cls.output_owns_source_context( + source_payload, + output_value, + output_plan, + plane_projection, + ) and not source_context_strategy.requires_plane_contextualization( + source_payload, + output_value, + plane_projection, + ): + if isinstance(output_value, AlignedImageStack): + return output_value + output_metadata = image_payload_metadata(output_value) + source_metadata = image_payload_metadata(source_payload) + contextualized_output = output_metadata.with_source_context_from( + source_metadata + ).attach_source_context_to( + output_value, + ) + if image_payload_metadata(contextualized_output) == output_metadata: + return output_value + return contextualized_output + return source_context_strategy.contextualize( + source_payload, + output_value, + plane_projection, + ) + + @classmethod + def contextualize_output_from_projector( + cls, + source_payload: object, + output_value: object, + output_plan: "ArtifactOutputPlan | None", + plane_projector: "RuntimePlaneAxisProjector | None", + ) -> object: + return cls.contextualize_projected_output( + source_payload, + output_value, + output_plan, + plane_projector, + ) + + @classmethod + def source_image_payload_from_runtime_value(cls, value: object) -> object: + return value + + @classmethod + def retained_filename_qualifier(cls, artifact_name: str) -> str: + """Distinguish named retained images sharing one physical source plane.""" + return artifact_name + @classmethod def projected_materialization_base_path( cls, @@ -548,6 +862,41 @@ class ObjectLabelsArtifactType(ArtifactType): carries_source_image_context = True payload_description = "object_labels payload" + @classmethod + def contextualize_output( + cls, + source_payload: object, + output_value: object, + output_plan: ArtifactOutputPlan | None, + plane_projection: RuntimePlaneAxisValueProjection | None, + ) -> object: + from openhcs.core.projected_image_output import ( + ObjectLabelOutputValueContextStrategy, + ) + + return ObjectLabelOutputValueContextStrategy.for_output_value( + output_value, + ).contextualize(source_payload, output_value, plane_projection) + + @classmethod + def contextualize_output_from_projector( + cls, + source_payload: object, + output_value: object, + output_plan: "ArtifactOutputPlan | None", + plane_projector: "RuntimePlaneAxisProjector | None", + ) -> object: + return cls.contextualize_projected_output( + source_payload, + output_value, + output_plan, + plane_projector, + ) + + @classmethod + def source_image_payload_from_runtime_value(cls, value: object) -> object: + return value + @classmethod def runtime_parameter_types(cls) -> tuple[type, ...]: from openhcs.core.runtime_object_labels import ObjectLabelValue @@ -690,6 +1039,121 @@ class MeasurementsArtifactType(ArtifactType): value = "measurements" payload_shape = ArtifactPayloadShape.TABLE + @staticmethod + def _declared_subject(output_plan: ArtifactOutputPlan | None) -> MeasurementSubject: + if output_plan is None: + raise ValueError("Measurement outputs require a compiled output plan.") + return MeasurementsArtifactType.require_output_subject(output_plan) + + @staticmethod + def _validate_nominal_table( + output_value: MeasurementTable, + output_plan: ArtifactOutputPlan, + subject: MeasurementSubject, + ) -> None: + output_value.validate_artifact_name(output_plan.name) + if output_value.subject != subject: + raise ValueError( + f"Measurement output {output_plan.ref()!r} declares subject " + f"{subject!r}, but returned {output_value.subject!r}." + ) + + @staticmethod + def _contextualized_rows( + rows: ColumnarRows, + *, + subject: MeasurementSubject, + source_provenance: SourceImageProvenance, + ) -> ColumnarRows: + from openhcs.core.measurement_row_materialization import ( + MeasurementRowOwnership, + measurement_rows_with_source_provenance, + ) + from openhcs.core.runtime_tabular_values import ColumnarRows + + owned_rows = MeasurementRowOwnership( + object_name=subject.object_name, + source_image_name=subject.source_image_name, + ).annotate_rows(rows) + if not isinstance(owned_rows, ColumnarRows): + raise TypeError( + "Measurement row ownership must preserve the nominal ColumnarRows " + f"carrier, got {type(owned_rows).__name__}." + ) + return measurement_rows_with_source_provenance( + owned_rows, + source_provenance, + ) + + @classmethod + def contextualize_output( + cls, + source_payload: object, + output_value: object, + output_plan: ArtifactOutputPlan | None, + plane_projection: RuntimePlaneAxisValueProjection | None, + ) -> object: + from openhcs.core.runtime_measurements import MeasurementTable + from openhcs.core.runtime_tabular_values import ColumnarRows + from openhcs.core.runtime_image_values import image_payload_metadata + + del plane_projection + subject = cls._declared_subject(output_plan) + assert output_plan is not None + source_provenance = image_payload_metadata(source_payload).source_provenance + if isinstance(output_value, MeasurementTable): + cls._validate_nominal_table(output_value, output_plan, subject) + contextualized_provenance = ( + output_value.source_provenance.with_missing_from(source_provenance) + ) + return output_value.replace_fields( + rows=cls._contextualized_rows( + output_value.rows, + subject=subject, + source_provenance=contextualized_provenance, + ), + source_provenance=contextualized_provenance, + ) + if not isinstance(output_value, ColumnarRows): + raise TypeError( + f"Measurement output {output_plan.ref()!r} requires ColumnarRows " + f"or MeasurementTable, got {type(output_value).__name__}." + ) + return MeasurementTable( + name=output_plan.name, + rows=cls._contextualized_rows( + output_value, + subject=subject, + source_provenance=source_provenance, + ), + source_image_name=subject.source_image_name, + subject=subject, + source_provenance=source_provenance, + ) + + @classmethod + def contextualize_output_from_projector( + cls, + source_payload: object, + output_value: object, + output_plan: ArtifactOutputPlan | None, + plane_projector: RuntimePlaneAxisProjector | None, + ) -> object: + """Validate nominal identity before generic plane projection inspects it.""" + + from openhcs.core.runtime_measurements import MeasurementTable + + subject = cls._declared_subject(output_plan) + if isinstance(output_value, MeasurementTable): + assert output_plan is not None + cls._validate_nominal_table(output_value, output_plan, subject) + return cls.contextualize_projected_output( + source_payload, + output_value, + output_plan, + plane_projector, + ) + @classmethod def require_output_subject( cls, @@ -713,13 +1177,13 @@ def require_output_subject( def validate_output_declaration(cls, spec: "ArtifactSpec") -> None: """Reject incompatible row domains before payload-owner validation. - Source-qualified image rows share one image-set domain. Their recording - owner determines whether multiple subjects can occupy the output; native - and ordinary recorded tables still require one exact subject. + The payload owner determines whether distinct named subjects can occupy + the output. Native and ordinary recorded tables require one exact + subject; row-owning recorders preserve each subject's identity. """ subjects = ArtifactSpecRelation.measurement_subjects_for_output(spec) - if len({subject.row_identity_domain for subject in subjects}) > 1: + if len({(subject.scope, subject.id_field) for subject in subjects}) > 1: ArtifactSpecRelation.measurement_subject_for_output(spec) @classmethod @@ -763,12 +1227,11 @@ def compose_runtime_values( """Concatenate exact producer-group measurement tables.""" del producer_group_scope - from openhcs.core.runtime_artifact_queries import MeasurementTableUnion + from openhcs.core.runtime_measurements import MeasurementTable - return MeasurementTableUnion( - values[0].name, - tuple(value.data for value in values), - ).as_table() + return MeasurementTable.join( + values[0].name, tuple(value.data for value in values) + ) @classmethod def materialization_payload(cls, value: "RuntimeValue") -> object: @@ -968,6 +1431,50 @@ class SpatialGraphArtifactType(ArtifactType): carries_source_image_context = True payload_description = "spatial graph payload" + @classmethod + def contextualize_output( + cls, + source_payload: object, + output_value: object, + output_plan: ArtifactOutputPlan | None, + plane_projection: RuntimePlaneAxisValueProjection | None, + ) -> object: + from openhcs.core.runtime_spatial_graph import SpatialGraph + from openhcs.core.runtime_image_values import image_payload_metadata + + del plane_projection + if not isinstance(output_value, SpatialGraph): + raise TypeError( + "Spatial graph output requires SpatialGraph, got " + f"{type(output_value).__name__}." + ) + if output_plan is not None: + output_value.validate_artifact_name(output_plan.name) + source_provenance = output_value.contextualized_source_provenance( + image_payload_metadata(source_payload).source_provenance + ) + contextualized_provenance = output_value.source_provenance.with_missing_from( + source_provenance + ) + if contextualized_provenance == output_value.source_provenance: + return output_value + return replace(output_value, source_provenance=contextualized_provenance) + + @classmethod + def contextualize_output_from_projector( + cls, + source_payload: object, + output_value: object, + output_plan: "ArtifactOutputPlan | None", + plane_projector: "RuntimePlaneAxisProjector | None", + ) -> object: + return cls.contextualize_projected_output( + source_payload, + output_value, + output_plan, + plane_projector, + ) + @classmethod def runtime_parameter_types(cls) -> tuple[type, ...]: from openhcs.core.runtime_spatial_graph import SpatialGraph @@ -1054,6 +1561,23 @@ def participates_in_persistent_materialization(self) -> bool: def uses_source_identity_filename(self) -> bool: """Return whether this materialization names files by source identity.""" + @abstractmethod + def filename_qualifier(self, output_plan: ArtifactOutputPlan | None) -> str | None: + """Derive the output role required by this materialization purpose.""" + + def filename_identity_for_output( + self, + identity: FunctionOutputIdentity, + output_plan: ArtifactOutputPlan | None, + ) -> FunctionOutputIdentity: + """Apply a declared role through the shared filename identity algorithm.""" + qualifier = self.filename_qualifier(output_plan) + return ( + identity + if qualifier is None + else identity.with_filename_qualifier(qualifier) + ) + def _coerce_artifact_plan_type( plan_type: type["ArtifactPlan"], @@ -1400,6 +1924,31 @@ class InputGroupLineageSourceRelation(ArtifactGroupScopeSourceRelation): relation_key: ClassVar[str] = "input_group_lineage_source" +class InputImageSetContextSourceRelation(ArtifactSourceContextSourceRelation): + """Consume an artifact in the image-set context of a declared input image.""" + + relation_key: ClassVar[str] = "input_image_set_context_source" + + def __post_init__(self) -> None: + super().__post_init__() + if ( + self.source.plan_type is not ArtifactInputPlan + or self.source.artifact_type is not ImageArtifactType + ): + raise ValueError( + f"{type(self).__name__} requires an input image source, got " + f"{self.source!r}." + ) + + def require_target_spec(self, spec: "ArtifactSpec") -> None: + super().require_target_spec(spec) + if not spec.artifact_type.carries_source_image_context: + raise ValueError( + f"{type(self).__name__} requires a target carrying source-image " + f"context, got {spec.artifact_type.value!r}." + ) + + class InputStackBroadcastSourceRelation(ArtifactSourceContextSourceRelation): """Input artifact may broadcast across one declared source input stack.""" @@ -2153,6 +2702,37 @@ def __iter__(self): def __getitem__(self, index): return self.specs[index] + def stack_broadcast_source_indices(self) -> tuple[int | None, ...]: + """Resolve exact stack-broadcast owners from declared input relations.""" + + indices_by_ref: dict[ArtifactSpecRef, list[int]] = {} + for input_index, spec in enumerate(self.specs): + indices_by_ref.setdefault(spec.ref(), []).append(input_index) + + result: list[int | None] = [] + for input_index, spec in enumerate(self.specs): + sources = spec.stack_broadcast_sources() + if len(sources) > 1: + raise ValueError( + f"Input {spec.ref()!r} declares multiple stack-broadcast " + f"owners: {sources!r}." + ) + if not sources: + result.append(None) + continue + source_indices = tuple(indices_by_ref.get(sources[0], ())) + if len(source_indices) != 1: + raise ValueError( + f"Input {spec.ref()!r} requires exactly one active occurrence " + f"of stack-broadcast owner {sources[0]!r}, got " + f"{source_indices!r}." + ) + source_index = source_indices[0] + if source_index == input_index: + raise ValueError(f"Input {spec.ref()!r} cannot broadcast from itself.") + result.append(source_index) + return tuple(result) + def of_artifact_type( self, artifact_type: ArtifactTypeValue, @@ -3287,6 +3867,7 @@ def validate_complete_producer_projection( ArtifactSpecRelation.target_plan_type = ArtifactOutputPlan InputGroupLineageSourceRelation.target_plan_type = ArtifactInputPlan +InputImageSetContextSourceRelation.target_plan_type = ArtifactInputPlan InputStackBroadcastSourceRelation.target_plan_type = ArtifactInputPlan InputStackBroadcastSourceRelation.target_artifact_type = ImageArtifactType InputObjectMeasurementSourceRelation.target_plan_type = ArtifactInputPlan diff --git a/openhcs/core/callable_contract.py b/openhcs/core/callable_contract.py index 81bd266aa6..b2d61b24fc 100644 --- a/openhcs/core/callable_contract.py +++ b/openhcs/core/callable_contract.py @@ -14,6 +14,7 @@ from enum import Enum from functools import wraps from pathlib import Path +from threading import Lock from types import MappingProxyType from typing import ( TYPE_CHECKING, @@ -22,6 +23,7 @@ Mapping, TypeVar, cast, + get_args, get_type_hints, overload, ) @@ -33,6 +35,7 @@ coerce_enum_member, declared_enum_type, enum_member_type, + is_union_type, resolve_annotated, validate_annotation_value, ) @@ -56,6 +59,7 @@ from openhcs.core.variable_component_stack_requirement import ( VariableComponentStackRequirement, ) +from openhcs.core.process_local_cache import IdentityBoundProcessCache if TYPE_CHECKING: from openhcs.core.aligned_image_payload import ( @@ -77,7 +81,12 @@ CallableNamespace = Mapping[str, Any] _EnumT = TypeVar("_EnumT", bound=Enum) -CallableRuntimeCacheKey = int + +class CallableContractRuntimeCache(IdentityBoundProcessCache): + """Retain executable callables for their exact compiled declaration owners.""" + + registry_key = "function_invocation_callable" + resolution_lock = Lock() @dataclass(frozen=True, slots=True) @@ -341,9 +350,152 @@ class CallableMetadata: image_payload_consumption: ImagePayloadConsumption = ImagePayloadConsumption.NATURAL request_binding: "CallableRequestBinding | None" = None prepare: Callable[..., object] | None = None + canonical_signature: inspect.Signature | None = None + raw_runtime_signature: inspect.Signature | None = None primary_image_carrier_requirement: PrimaryImageCarrierRequirement | None = None primary_image_carrier_transition: PrimaryImageCarrierTransition | None = None + @staticmethod + def prepared_callable_signature(func: Callable[..., object]) -> inspect.Signature | None: + """Admit an owned snapshot only for its exact semantic callable boundary.""" + raw = getattr(func, FunctionContractAttribute.raw_processing_function, None) + if raw is not None and raw is not func: + return None + signature = getattr(func, FunctionContractAttribute.canonical_signature, None) + if signature is not None and not isinstance(signature, inspect.Signature): + raise TypeError("Prepared callable signature must be an inspect.Signature or None.") + return signature + + @classmethod + def callable_signature(cls, func: Callable[..., object]) -> inspect.Signature: + """Read the prepared exact ABI; unprepared wrapper/authoring views stay live.""" + signature = cls.prepared_callable_signature(func) + return inspect.signature(func) if signature is None else signature + + def resolve_canonical_raw_callable(self, func: Any) -> Callable[..., object]: + """Return the declaration-owned callable whose signature defines behavior.""" + + declared = self.raw_processing_function + if declared is None: + declared = func + return _resolve_declared_callable(declared) + + def resolve_raw_runtime_callable(self, func: Any) -> Callable[..., object]: + """Remove runtime wrappers without crossing a semantic request binding.""" + + canonical = self.resolve_canonical_raw_callable(func) + if self.request_binding is None: + return inspect.unwrap(canonical) + + binding_key = FunctionContractAttribute.callable_request_binding + + def is_request_boundary(candidate: Callable[..., object]) -> bool: + namespace = _callable_namespace(candidate) + if binding_key not in namespace: + return False + wrapped = namespace.get("__wrapped__") + return not callable(wrapped) or binding_key not in _callable_namespace( + wrapped + ) + + resolved = inspect.unwrap(canonical, stop=is_request_boundary) + if binding_key not in _callable_namespace(resolved): + raise RuntimeError( + f"Callable {CallableProjection.from_callable(func).name!r} declares a request binding, but " + "its canonical raw callable has no request-binding boundary." + ) + return resolved + + def resolve_signature(self, raw_callable: Callable[..., object]) -> inspect.Signature: + """Resolve the semantic ABI once after declaration preparation.""" + signature = inspect.signature(raw_callable) + annotations = ( + self.request_binding.public_annotations_dict + if self.request_binding is not None + else get_type_hints(raw_callable, include_extras=True) + ) + return signature.replace( + parameters=tuple( + parameter.replace(annotation=annotations.get(name, parameter.annotation)) + for name, parameter in signature.parameters.items() + ), + return_annotation=annotations.get("return", signature.return_annotation), + ) + + @staticmethod + def primary_input_name(parameters: Mapping[str, inspect.Parameter]) -> str | None: + for parameter in parameters.values(): + if parameter.kind in ( + inspect.Parameter.POSITIONAL_ONLY, + inspect.Parameter.POSITIONAL_OR_KEYWORD, + ): + return parameter.name + return None + + @classmethod + def _nominal_argument_types(cls, annotation: object) -> tuple[type, ...]: + annotation = resolve_annotated(annotation) + if is_union_type(annotation): + return tuple( + argument_type for member in get_args(annotation) + for argument_type in cls._nominal_argument_types(member) + ) + return ( + (annotation,) + if annotation is not Any and isinstance(annotation, type) + else () + ) + + def raw_main_flow_call_argument(self, source_payload: Any, signature: inspect.Signature) -> Any: + """Admit a declared nominal carrier at the canonical image boundary.""" + from openhcs.core.runtime_image_values import image_payload_data + + primary_name = self.primary_input_name(signature.parameters) + annotation = None if primary_name is None else signature.parameters[primary_name].annotation + if ( + annotation is inspect.Parameter.empty + and self.image_payload_consumption is ImagePayloadConsumption.COMPOSED + ): + return source_payload + return source_payload if any( + isinstance(source_payload, argument_type) + for argument_type in self._nominal_argument_types(annotation) + ) else image_payload_data(source_payload) + + def canonical_signature_for(self, func: Any) -> inspect.Signature: + """Use the prepared semantic ABI; unprepared authoring remains live.""" + if self.canonical_signature is not None: + return self.canonical_signature + return self.resolve_signature(self.resolve_canonical_raw_callable(func)) + + def raw_runtime_signature_for(self, func: Any) -> inspect.Signature: + """Own the distinct raw ABI or the shared canonical target snapshot.""" + if self.raw_runtime_signature is not None: + return self.raw_runtime_signature + if self.canonical_signature is not None: + return self.canonical_signature + return self.resolve_signature(self.resolve_raw_runtime_callable(func)) + + def with_prepared_signatures(self, canonical: Callable, runtime: Callable) -> "CallableMetadata": + """Snapshot each actual target independently after declaration preparation.""" + return dataclasses.replace( + self, canonical_signature=self.resolve_signature(canonical), + raw_runtime_signature=None if runtime is canonical else self.resolve_signature(runtime), + ) + + def with_missing_signatures(self, canonical: Callable[[], Callable], runtime: Callable[[], Callable]) -> "CallableMetadata": + """Reuse library readiness or capture the newly prepared authored targets.""" + if self.canonical_signature is not None: + return self + return self.with_prepared_signatures(canonical(), runtime()) + + def publish_signatures(self, namespace: MutableMapping[str, Any]) -> None: + """Replace the namespace pair as one library preparation epoch.""" + namespace[FunctionContractAttribute.canonical_signature] = self.canonical_signature + namespace.pop(FunctionContractAttribute.raw_runtime_signature, None) + if self.raw_runtime_signature is not None: + namespace[FunctionContractAttribute.raw_runtime_signature] = self.raw_runtime_signature + @property def artifact_output_policy(self) -> type[ArtifactOutputPolicy]: """Project recording ownership from this callable's adapter declaration.""" @@ -427,13 +579,14 @@ def from_projection( runtime_adapter = runtime_adapter_spec_from_callable(projection.func) if runtime_adapter is not None and callable(projection.func): runtime_adapter.validate_callable_signature(projection.func) + declared_artifact_inputs = _artifact_specs_from_namespace( + namespace, projection.name, FunctionContractAttribute.artifact_inputs, + ) + signature = ( + cls.callable_signature(projection.func) if callable(projection.func) else None + ) artifact_inputs = _artifact_input_specs_from_projection( - projection, - _artifact_specs_from_namespace( - namespace, - projection.name, - FunctionContractAttribute.artifact_inputs, - ), + projection, declared_artifact_inputs, signature, ) return cls( input_memory_type=reader.optional_string( @@ -450,6 +603,7 @@ def from_projection( projection, reader, artifact_inputs, + signature, ), artifact_outputs=_artifact_specs_from_namespace( namespace, @@ -471,7 +625,7 @@ def from_projection( FunctionContractAttribute.allowed_group_by, ), runtime_adapter=runtime_adapter, - runtime_context_parameter=_runtime_context_parameter(projection, reader), + runtime_context_parameter=_runtime_context_parameter(reader, signature), execution_scope=reader.optional_execution_scope( FunctionContractAttribute.execution_scope, ), @@ -506,6 +660,12 @@ def from_projection( prepare=reader.optional_callable( FunctionContractAttribute.processing_prepare ), + canonical_signature=reader.optional_signature( + FunctionContractAttribute.canonical_signature, + ), + raw_runtime_signature=reader.optional_signature( + FunctionContractAttribute.raw_runtime_signature, + ), ) def without_prepare(self) -> "CallableMetadata": @@ -525,6 +685,10 @@ def with_raw_processing_function( def as_namespace(self) -> dict[str, object]: """Project typed metadata into callable declaration keys.""" namespace: dict[str, object] = {} + if self.canonical_signature is not None: + namespace[FunctionContractAttribute.canonical_signature] = self.canonical_signature + if self.raw_runtime_signature is not None: + namespace[FunctionContractAttribute.raw_runtime_signature] = self.raw_runtime_signature if self.input_memory_type is not None: MemoryContractAttribute.INPUT.write(namespace, self.input_memory_type) if self.output_memory_type is not None: @@ -784,6 +948,16 @@ def preserves_input_main_flow(self) -> bool: return self.artifact_output_policy.preserves_input_main_flow(self) + @property + def invocation_domain_inputs(self) -> ArtifactSpecCollection: + """Derive carrier inputs through the declared adapter's nominal owner.""" + adapter = self.runtime_adapter + return ( + self.group_scope_inputs + if adapter is None + else adapter.invocation_domain_inputs(self) + ) + @property def runtime_adapter(self) -> RuntimeAdapterSpec | None: """Declared runtime adapter.""" @@ -820,10 +994,7 @@ def config_bound_parameters(self) -> tuple[inspect.Parameter, ...]: from openhcs.core.config import runtime_config_parameter - signature = inspect.signature( - self.resolve_canonical_raw_callable(), - eval_str=True, - ) + signature = self.canonical_signature return tuple( normalized for parameter in signature.parameters.values() @@ -886,7 +1057,7 @@ def declared_path_values( ) -> Mapping[str, tuple["PlatePathDeclaration", object]]: """Return authored or signature-default values for declared paths.""" - signature = inspect.signature(self.resolve_canonical_raw_callable()) + signature = self.canonical_signature values: dict[str, tuple["PlatePathDeclaration", object]] = {} for parameter_name, declaration in self.declared_path_parameters.items(): value = kwargs.get(parameter_name, signature.parameters[parameter_name].default) @@ -966,17 +1137,15 @@ def require_processing_contract(self) -> "ProcessingContract": ) return processing_contract - def raw_main_flow_call_argument(self, source_payload: Any) -> Any: + def runtime_main_flow_call_argument(self, source_payload: Any) -> Any: """Project this callable's ABI without discarding an adapter's context.""" - from arraybridge import ArrayPayload - from openhcs.core.runtime_image_values import image_payload_data - if self.runtime_adapter is not None: return source_payload - annotation = self.canonical_parameter_annotations.get(self.primary_input_parameter_name) - if isinstance(annotation, type) and issubclass(annotation, ArrayPayload): - return source_payload - return image_payload_data(source_payload) + return self.raw_main_flow_call_argument(source_payload) + + def raw_main_flow_call_argument(self, source_payload: Any) -> Any: + """Project the metadata-owned raw carrier declaration for this contract.""" + return self.metadata.raw_main_flow_call_argument(source_payload, self.canonical_signature) def main_flow_call_argument(self, source_payload: Any) -> Any: """Let the processing declaration retain context needed before raw calls.""" @@ -1044,14 +1213,8 @@ def artifact_specs(self) -> ArtifactSpecCollection: @property def primary_input_parameter_name(self) -> str | None: """FunctionStep input payload parameter declared by callable signature.""" - signature = inspect.signature(self.resolve_canonical_raw_callable()) - for parameter in signature.parameters.values(): - if parameter.kind in ( - inspect.Parameter.POSITIONAL_ONLY, - inspect.Parameter.POSITIONAL_OR_KEYWORD, - ): - return parameter.name - return None + signature = self.canonical_signature + return self.metadata.primary_input_name(signature.parameters) @property def accepts_implicit_main_flow_input(self) -> bool: @@ -1072,29 +1235,32 @@ def runtime_batch_executor( return None return self.runtime_batch_executors.get(domain) - def runtime_callable_cache_identity( - self, - ) -> CallableRuntimeCacheKey: - """Return the process-local cache identity for this callable contract.""" - if not _is_function_reference(self.func) and not callable(self.func): - raise TypeError(f"Invalid callable contract function: {self.func}") - return id(self) + def require_memory_types(self) -> tuple[str, str]: + """Admit both declared memory domains before runtime conversion.""" + if self.input_memory_type is None or self.output_memory_type is None: + raise ValueError( + f"Callable {self.function_name!r} is missing memory types." + ) + return self.input_memory_type, self.output_memory_type def resolve_runtime_callable(self) -> Callable[..., object]: """Return the executable callable for this contract.""" + cache = CallableContractRuntimeCache.process_cache() + with CallableContractRuntimeCache.resolution_lock: + cached = cache.get_bound(self) + if cached is not None: + return cached resolved = _resolve_declared_callable(self.func) runtime_adapter = self.runtime_adapter - if runtime_adapter is None: - return resolved - return runtime_adapter.executable_callable(resolved, self) + if runtime_adapter is not None: + resolved = runtime_adapter.executable_callable(resolved, self) + with CallableContractRuntimeCache.resolution_lock: + cache.put_bound(self, resolved) + return resolved def resolve_canonical_raw_callable(self) -> Callable[..., object]: - """Return the declaration-owned callable whose signature defines behavior.""" - - declared = self.raw_processing_function - if declared is None: - declared = self.func - return _resolve_declared_callable(declared) + """Return the declaration-owned semantic target.""" + return self.metadata.resolve_canonical_raw_callable(self.func) def canonical_raw_import_identity(self) -> CallableImportIdentity: """Return the complete import identity of the canonical raw callable.""" @@ -1104,41 +1270,49 @@ def canonical_raw_import_identity(self) -> CallableImportIdentity: ) def resolve_raw_runtime_callable(self) -> Callable[..., object]: - """Remove runtime wrappers without crossing a semantic request binding.""" + """Resolve the metadata-owned raw target without crossing request binding.""" + return self.metadata.resolve_raw_runtime_callable(self.func) - canonical = self.resolve_canonical_raw_callable() - if self.request_binding is None: - return inspect.unwrap(canonical) + @property + def canonical_parameter_annotations(self) -> Mapping[str, object]: + """Derive annotations from the original semantic signature owner.""" + return { + name: parameter.annotation + for name, parameter in self.canonical_parameter_declarations.items() + } - binding_key = FunctionContractAttribute.callable_request_binding + @property + def canonical_parameter_declarations(self) -> Mapping[str, inspect.Parameter]: + """Resolve signature and annotations together at their declaration owner.""" + return self.canonical_signature.parameters - def is_request_boundary(candidate: Callable[..., object]) -> bool: - namespace = _callable_namespace(candidate) - if binding_key not in namespace: - return False - wrapped = namespace.get("__wrapped__") - return not callable(wrapped) or binding_key not in _callable_namespace( - wrapped - ) + @property + def canonical_signature(self) -> inspect.Signature: + """The metadata-owned semantic signature for this contract's target.""" + return self.metadata.canonical_signature_for(self.func) - resolved = inspect.unwrap(canonical, stop=is_request_boundary) - if binding_key not in _callable_namespace(resolved): - raise RuntimeError( - f"Callable {self.function_name!r} declares a request binding, but " - "its canonical raw callable has no request-binding boundary." - ) - return resolved + def with_prepared_signature(self) -> "CallableContract": + """Freeze the prepared declaration into its existing compiled contract.""" + return dataclasses.replace(self, metadata=self.metadata.with_prepared_signatures( + self.resolve_canonical_raw_callable(), self.resolve_raw_runtime_callable(), + )) @property - def canonical_parameter_annotations(self) -> Mapping[str, object]: - """Derive annotations from the original semantic signature owner.""" + def raw_runtime_signature(self) -> inspect.Signature: + """The metadata-owned execution signature for this contract's target.""" + return self.metadata.raw_runtime_signature_for(self.func) - raw_callable = self.resolve_canonical_raw_callable() - annotations = get_type_hints(raw_callable, include_extras=True) - return { - name: annotations.get(name, parameter.annotation) - for name, parameter in inspect.signature(raw_callable).parameters.items() - } + @classmethod + def from_prepared_callable(cls, func: Callable[..., object]) -> "CallableContract": + """Construct a compiled view only after the declaration owner prepares it.""" + projection = CallableProjection.from_callable(func) + prepared = cls.from_callable(projection.prepared_callable()) + return dataclasses.replace( + prepared, func=func, function_name=projection.name, module_name=projection.module_name, + metadata=prepared.metadata.with_missing_signatures( + prepared.resolve_canonical_raw_callable, prepared.resolve_raw_runtime_callable, + ), + ) def decode_public_kwargs(self, kwargs: Mapping[str, object]) -> dict[str, object]: """Descend declared scalar enums at authoring, before source projection.""" @@ -1166,7 +1340,7 @@ def validate_public_kwargs( raise TypeError( "CallableContract.validate_public_kwargs requires a mapping." ) - signature = inspect.signature(self.resolve_canonical_raw_callable()) + signature = self.canonical_signature runtime_owned_value = object() call_kwargs = dict(kwargs) runtime_loaded_parameters = frozenset(runtime_loaded_artifact_parameter_names) @@ -1237,15 +1411,19 @@ def validate_artifact_input_parameter_bindings(self) -> None: """Validate exact artifact occurrences against the normalized callable ABI.""" from openhcs.core.pipeline.function_contracts import ( - resolved_callable_parameter, special_input_parameter_accepts_sequence, ) - raw_callable = self.resolve_canonical_raw_callable() - artifact_parameters = { - parameter_name: resolved_callable_parameter(raw_callable, parameter_name) - for parameter_name in self.artifact_input_parameter_names - } + artifact_parameters = {} + parameters = self.canonical_parameter_declarations + for parameter_name in self.artifact_input_parameter_names: + parameter = parameters.get(parameter_name) + if parameter is None: + raise ValueError( + f"Callable {self.function_name!r} does not declare parameter " + f"{parameter_name!r}." + ) + artifact_parameters[parameter_name] = parameter specs_by_parameter: dict[str, list[ArtifactSpec]] = {} for spec in self.artifact_inputs: parameter_name = spec.parameter_name @@ -1283,6 +1461,10 @@ def validate_artifact_input_parameter_bindings(self) -> None: continue if ( len(bound_specs) > 1 + and not ( + self.runtime_adapter is not None + and self.runtime_adapter.manages_artifact_inputs + ) and not special_input_parameter_accepts_sequence(parameter) and any( spec.artifact_type is not ImageArtifactType for spec in bound_specs @@ -1462,6 +1644,8 @@ def wrapper(*args: Any, **kwargs: Any) -> Any: return func(**binding.implementation_kwargs(bound.arguments)) wrapper_namespace = _mutable_callable_namespace(wrapper) + wrapper_namespace.pop(FunctionContractAttribute.canonical_signature, None) + wrapper_namespace.pop(FunctionContractAttribute.raw_runtime_signature, None) wrapper_namespace[FunctionContractAttribute.callable_request_binding] = binding wrapper_namespace["__signature__"] = public_signature return wrapper @@ -1516,6 +1700,8 @@ def attach_callable_contract_metadata( primary_image_carrier_transition: PrimaryImageCarrierTransition | None = None, ) -> None: """Attach OpenHCS callable metadata used by compiler/runtime phases.""" + _mutable_callable_namespace(func).pop(FunctionContractAttribute.canonical_signature, None) + _mutable_callable_namespace(func).pop(FunctionContractAttribute.raw_runtime_signature, None) if declared_processing_contract is not None: if ( not isinstance(declared_processing_contract, str) @@ -1692,9 +1878,10 @@ def attach_processing_prepare(func: Any, prepare: Any) -> None: f"got {type(prepare).__name__}." ) for target in CallableProjection.from_callable(func).prepare_targets(): - _mutable_callable_namespace(target)[ - FunctionContractAttribute.processing_prepare - ] = prepare + namespace = _mutable_callable_namespace(target) + namespace.pop(FunctionContractAttribute.canonical_signature, None) + namespace.pop(FunctionContractAttribute.raw_runtime_signature, None) + namespace[FunctionContractAttribute.processing_prepare] = prepare def runtime_image_execution_mode( @@ -1846,6 +2033,21 @@ def from_callable(cls, func: Any) -> "CallableProjection": ) return cls(func=func, name=name, module_name=module_name, namespace=namespace) + def prepared_callable(self) -> Any: + """Keep ready library references or prepare live authored targets before validation.""" + reader = CallableMetadataReader(self.namespace, self.name) + if reader.has_prepared_signature(): + return self.func + resolved = _resolve_declared_callable(self.func) + for target in type(self).from_callable(resolved).prepare_targets(): + prepare_processing_callable(target) + return resolved + + def warm_canonical_signature(self) -> None: + """Publish prepared target signatures only after all library hooks finish.""" + contract = CallableContract.from_callable(self.func).with_prepared_signature() + contract.metadata.publish_signatures(_mutable_callable_namespace(self.func)) + def prepare_targets(self) -> tuple[Any, ...]: """Return wrapper/raw callables that may carry preparation metadata.""" targets: list[Any] = [] @@ -1869,8 +2071,8 @@ def prepare_targets(self) -> tuple[Any, ...]: def _runtime_context_parameter( - projection: CallableProjection, reader: "CallableMetadataReader", + signature: inspect.Signature | None, ) -> str | None: field_name = FunctionContractAttribute.runtime_context_parameter declared = reader.optional_string(field_name) @@ -1878,19 +2080,8 @@ def _runtime_context_parameter( return declared from openhcs.core.context.processing_context import ProcessingContext - return _callable_signature_parameter( - projection.func, - ProcessingContext.require_parameter_name(), - ) - - -def _callable_signature_parameter(func: Any, parameter_name: str) -> str | None: - """Return a callable parameter name accepted by live signatures only.""" - if not callable(func): - return None - if parameter_name not in inspect.signature(func).parameters: - return None - return parameter_name + parameter_name = ProcessingContext.require_parameter_name() + return parameter_name if signature is not None and parameter_name in signature.parameters else None @dataclass(frozen=True, slots=True) @@ -1900,6 +2091,16 @@ class CallableMetadataReader: namespace: CallableNamespace function_name: str + def has_prepared_signature(self) -> bool: + """Validate the namespace-owned readiness declaration before phase selection.""" + return self.optional_signature(FunctionContractAttribute.canonical_signature) is not None + + def optional_signature(self, field_name: str) -> inspect.Signature | None: + value = self.namespace.get(field_name) + if value is not None and not isinstance(value, inspect.Signature): + raise TypeError(f"{self.function_name!r}.{field_name} must be an inspect.Signature or None.") + return value + def optional_string(self, field_name: str) -> str | None: """Return an optional string metadata field.""" value = self.namespace.get(field_name) @@ -2250,12 +2451,12 @@ def _artifact_input_parameter_names( def _artifact_input_specs_from_projection( projection: CallableProjection, artifact_inputs: tuple[ArtifactSpec, ...], + signature: inspect.Signature | None, ) -> tuple[ArtifactSpec, ...]: """Bind exact same-name input declarations at the metadata boundary.""" - if not callable(projection.func): + if signature is None: return artifact_inputs - signature = inspect.signature(projection.func) primary_parameter_name = next( ( parameter.name @@ -2285,6 +2486,7 @@ def _artifact_input_parameter_names_from_projection( projection: CallableProjection, reader: CallableMetadataReader, artifact_inputs: tuple[ArtifactSpec, ...], + signature: inspect.Signature | None, ) -> tuple[str, ...]: """Normalize compatibility and exact artifact parameter declarations once.""" @@ -2338,9 +2540,8 @@ def _artifact_input_parameter_names_from_projection( f"disagree: {declarations}." ) - if not callable(projection.func): + if signature is None: return first_names - signature = inspect.signature(projection.func) ordered_names = tuple(name for name in signature.parameters if name in first_set) return ( *ordered_names, diff --git a/openhcs/core/compiled_step_plan.py b/openhcs/core/compiled_step_plan.py index 0282c2d04e..e89c619ee5 100644 --- a/openhcs/core/compiled_step_plan.py +++ b/openhcs/core/compiled_step_plan.py @@ -6,9 +6,12 @@ from contextlib import AbstractContextManager, nullcontext from dataclasses import dataclass, field from pathlib import Path -from typing import TYPE_CHECKING, Any, Mapping, Sequence +from typing import TYPE_CHECKING, Any, ClassVar, Mapping, Sequence + +from polystore.streaming.identity import StreamProducerIdentity from openhcs.constants.constants import ( + Backend, GPU_MEMORY_TYPES, MemoryType, SequentialComponents, @@ -21,7 +24,11 @@ ) from openhcs.core.callable_contract import FunctionStepExecutionScope from openhcs.core.component_group_scope import ComponentGroupScope -from openhcs.core.function_patterns import CompiledFunctionPattern +from openhcs.core.function_patterns import ( + CompiledFunctionGroup, + CompiledFunctionPattern, + InvocationArtifactInputEdgePlan, +) from openhcs.core.source_bindings import ( CompiledSourceBindingPlan, CompiledSourceUniversePlan, @@ -30,6 +37,7 @@ from openhcs.core.step_dependencies import StepInputDependency if TYPE_CHECKING: + from openhcs.core.aligned_image_payload import AlignedImageSliceContext from openhcs.core.config import StreamingConfig else: StreamingConfig = Any @@ -254,6 +262,8 @@ class CompiledStepPlan: mutate fields on this dataclass rather than writing string-keyed dicts. """ + ARTIFACT_OUTPUT_KIND: ClassVar[str] = "artifact" + step_index: int step_name: str step_type: str @@ -315,6 +325,109 @@ class CompiledStepPlan: chainbreaker: bool = False error: str | None = None + def stored_primary_input_edges_for_group( + self, group: CompiledFunctionGroup, component_key: str | None, + ) -> tuple[InvocationArtifactInputEdgePlan, ...] | None: + """Admit exact producer transport only without path-based transforms.""" + if self.input_conversion is not None or self.sequential_filter_plan.enabled: + return None + edges = group.stored_primary_input_edges_for_component( + self.execution_group_scope, component_key, + ) + if edges and any( + edge.storage_plan.source_step_scope_id == self.step_scope_id + if edge.storage_plan.source_step_scope_id is not None + else edge.storage_plan.source_step_id in ( + self.step_index, self.step_scope_id, + ) + for edge in edges + ): + return None + return edges + + def requires_main_flow_checkpoint( + self, plans: Mapping[int, "CompiledStepPlan"], + ) -> bool: + """Follow this value's consumers through preserved input lifetimes.""" + if not plans or self.step_index not in plans: + return True + consumers: dict[int, list[CompiledStepPlan]] = {} + for plan in plans.values(): + predecessor = plan.main_input_dependency.predecessor_step_index() + if predecessor is not None: + consumers.setdefault(predecessor, []).append(plan) + pending = [self.step_index] + visited: set[int] = set() + while pending: + step_index = pending.pop() + if step_index in visited: + continue + visited.add(step_index) + plan = plans.get(step_index) + if plan is None: + continue + if ( + plan.write_backend != Backend.MEMORY.value + or plan.materialized_output is not None + or plan.streaming_configs + or plan.visualize + ): + return True + for consumer in consumers.get(step_index, ()): + pattern = consumer.compiled_function_pattern + if pattern is None or any( + (group := pattern.group_for_component(component_key)) is None + or consumer.stored_primary_input_edges_for_group( + group, component_key, + ) is None + for component_key in consumer.execution_group_scope.keys + ): + return True + if pattern.preserves_input_main_flow(): + pending.append(consumer.step_index) + return False + + def producer_identity( + self, + *, + output_kind: str, + output_key: str, + projection_key: str, + artifact_kind: str | None = None, + ) -> StreamProducerIdentity: + """Project this step's identity onto one declared output surface.""" + return StreamProducerIdentity.pipeline_output( + output_kind=output_kind, + output_key=output_key, + projection_key=projection_key, + step_name=self.step_name, + pipeline_position=self.pipeline_position, + step_scope_id=self.step_scope_id, + artifact_kind=artifact_kind, + ) + + def producer_identity_for_main_flow( + self, output_context: AlignedImageSliceContext + ) -> StreamProducerIdentity: + """Retain the main-flow surface's declared kind, key and projection.""" + return self.producer_identity( + output_kind=output_context.output_kind, + output_key=output_context.output_key, + projection_key=output_context.projection_key, + artifact_kind=output_context.artifact_kind, + ) + + def producer_identity_for_artifact( + self, output_plan: ArtifactOutputPlan + ) -> StreamProducerIdentity: + """Derive a named artifact producer from its original compiled plan.""" + return self.producer_identity( + output_kind=self.ARTIFACT_OUTPUT_KIND, + output_key=output_plan.name, + projection_key=output_plan.name, + artifact_kind=output_plan.artifact_type.value, + ) + @property def requires_terminal_source_projection(self) -> bool: """Require an exact source anchor when declared bindings have no predecessor.""" diff --git a/openhcs/core/component_group_scope.py b/openhcs/core/component_group_scope.py index 78b18d51af..8a424610f5 100644 --- a/openhcs/core/component_group_scope.py +++ b/openhcs/core/component_group_scope.py @@ -10,6 +10,7 @@ from openhcs.constants.constants import AllComponents from openhcs.core.component_set import ComponentSet from openhcs.core.source_metadata import ( + SourceMetadataFields, SourceMetadataMapping, SourceMetadataScalar, SourceMetadataValue, @@ -386,6 +387,39 @@ def value_text_for_component( def has_fixed_components(self) -> bool: return bool(self.fixed_component_values) + def join_execution_cohort( + self, + other: "RuntimeExecutionAxisScope", + ) -> "RuntimeExecutionAxisScope | None": + """Join complete producer coordinates within one consumer execution group. + + An absent fixed coordinate leaves that axis unconstrained. Shared + coordinates must agree before either correlated row contributes its + remaining coordinates; fields from conflicting rows are never combined. + """ + + if not isinstance(other, RuntimeExecutionAxisScope): + raise TypeError("Execution cohorts require RuntimeExecutionAxisScope values.") + if ( + self.axis_id != other.axis_id + or self.component is not other.component + or self.value_text != other.value_text + ): + return None + own_fixed = dict(self.fixed_component_values) + other_fixed = dict(other.fixed_component_values) + if any( + own_fixed[component] != other_fixed[component] + for component in own_fixed.keys() & other_fixed.keys() + ): + return None + return type(self).from_raw( + self.axis_id, + component=self.component, + value=self.value_text, + fixed_component_values=tuple((own_fixed | other_fixed).items()), + ) + @property def source_component_values(self) -> RuntimeFixedComponentValues: """Return every typed source coordinate represented by this scope.""" @@ -467,7 +501,7 @@ def for_group_coordinate( def fixed_component_metadata( self, metadata: SourceMetadataMapping | None = None, - ) -> dict[str, SourceMetadataValue]: + ) -> SourceMetadataMapping: """Merge fixed execution coordinates into source component metadata.""" from openhcs.constants.constants import get_multiprocessing_axis @@ -476,7 +510,9 @@ def fixed_component_metadata( with_source_component_metadata, ) - merged: dict[str, SourceMetadataValue] = dict(metadata or {}) + merged = SourceMetadataFields.composition_snapshot( + metadata if metadata is not None else {} + ) fixed_values = ( (get_multiprocessing_axis(), self.axis_id), *self.fixed_component_values, diff --git a/openhcs/core/components/validation.py b/openhcs/core/components/validation.py index 10b835e7fc..c2bb0c3de1 100644 --- a/openhcs/core/components/validation.py +++ b/openhcs/core/components/validation.py @@ -94,14 +94,19 @@ def validate_step( Returns: ValidationResult indicating success or failure """ + from openhcs.core.function_patterns import NormalizedFunctionPattern + try: # 1. Validate component combination self.config.validate_combination(variable_components, group_by) # 2. Validate dict pattern requirements - if isinstance(func_pattern, dict) and ( - group_by is None or group_by.value is None - ): + grouped = ( + func_pattern.is_grouped + if isinstance(func_pattern, NormalizedFunctionPattern) + else isinstance(func_pattern, dict) + ) + if grouped and (group_by is None or group_by.value is None): return ValidationResult( is_valid=False, error_message=( @@ -158,13 +163,19 @@ def validate_dict_pattern_keys( Returns: ValidationResult indicating success or failure """ + from openhcs.core.function_patterns import NormalizedFunctionPattern + try: # Use enum objects directly - orchestrator now accepts VariableComponents available_keys = orchestrator.get_component_keys(group_by) available_keys_set = set(str(key) for key in available_keys) # Check each dict key against available keys - pattern_keys = list(func_pattern.keys()) + pattern_keys = ( + func_pattern.source_group_keys + if isinstance(func_pattern, NormalizedFunctionPattern) + else tuple(func_pattern) + ) pattern_keys_set = set(str(key) for key in pattern_keys) # Try direct string match first diff --git a/openhcs/core/equivalence/object_label_measurements.py b/openhcs/core/equivalence/object_label_measurements.py index dc141546fe..ee5cea564a 100644 --- a/openhcs/core/equivalence/object_label_measurements.py +++ b/openhcs/core/equivalence/object_label_measurements.py @@ -314,7 +314,7 @@ def from_object_label_records( identifier_subjects: set[RuntimeMeasurementSubjectKey] = set() location_subjects: set[RuntimeMeasurementSubjectKey] = set() for record in records: - object_labels = cast(ObjectLabelSet, record.value.data) + object_labels = cast(ObjectLabelSet, record.data) subject = RuntimeMeasurementSubjectKey( MeasurementScope.OBJECT, object_labels.name, @@ -401,7 +401,7 @@ def from_records( counts: dict[RuntimeMeasurementSubjectKey, int] = {} named_plane_domains: list[tuple[str, tuple[tuple[int, ...], ...]]] = [] for record in records: - object_labels = cast(ObjectLabelSet, record.value.data) + object_labels = cast(ObjectLabelSet, record.data) subject = RuntimeMeasurementSubjectKey( MeasurementScope.OBJECT, object_labels.name, @@ -508,7 +508,7 @@ def facts_for_records( facts: RuntimeMeasurementFactList = [] for record in records: context = ObjectLabelMeasurementContext.from_runtime_value( - record.value, + record, self.policy, self.object_identifier_subjects, self.object_location_subjects, @@ -885,7 +885,7 @@ def object_label_measurement_values_for_name( values_by_feature: RuntimeObjectValuesByLabel = {} for record in records: - object_labels = cast(ObjectLabelSet, record.value.data) + object_labels = cast(ObjectLabelSet, record.data) if normalize_runtime_identifier(object_labels.name) != subject.name: continue for key, values in object_label_location_values_by_label( diff --git a/openhcs/core/equivalence/policy.py b/openhcs/core/equivalence/policy.py index 22f86707e1..4e39f2549a 100644 --- a/openhcs/core/equivalence/policy.py +++ b/openhcs/core/equivalence/policy.py @@ -648,6 +648,30 @@ def resolved_category_prefixes(self) -> tuple[tuple[str, ...], ...]: """Return static and provider-supplied measurement category prefixes.""" return _resolved_category_prefixes(runtime_measurement_dialect_cache_id(self)) + def projected_feature_name( + self, feature_name: str, qualifier_values: tuple[tuple[str, object], ...] + ) -> str: + """Render a producer feature using this declaration's qualifier grammar.""" + return self._projected_feature_name( + runtime_measurement_dialect_cache_id(self), feature_name, qualifier_values + ) + + @staticmethod + @lru_cache(maxsize=8192) + def _projected_feature_name( + dialect_id: int, + feature_name: str, + qualifier_values: tuple[tuple[str, object], ...], + ) -> str: + from .measurement_rows import measurement_row_qualifiers + + qualifiers = measurement_row_qualifiers( + dict(qualifier_values), + runtime_measurement_dialect_for_cache_id(dialect_id), + feature_name, + ) + return "_".join((feature_name, *qualifiers)) if qualifiers else feature_name + def spatial_grid_measurement_feature_name( self, grid_name: str, diff --git a/openhcs/core/function_contract_metadata.py b/openhcs/core/function_contract_metadata.py index b269577cb8..09713a46ce 100644 --- a/openhcs/core/function_contract_metadata.py +++ b/openhcs/core/function_contract_metadata.py @@ -16,6 +16,8 @@ class FunctionContractAttribute: "__openhcs_declared_processing_contract__" ) raw_processing_function: ClassVar[str] = "__openhcs_raw_processing_function__" + canonical_signature: ClassVar[str] = "__openhcs_canonical_signature__" + raw_runtime_signature: ClassVar[str] = "__openhcs_raw_runtime_signature__" processing_prepare: ClassVar[str] = "__openhcs_prepare__" runtime_adapter: ClassVar[str] = "__runtime_adapter__" runtime_image_execution_mode: ClassVar[str] = ( diff --git a/openhcs/core/function_patterns.py b/openhcs/core/function_patterns.py index cca3eade16..78ed0fdbd9 100644 --- a/openhcs/core/function_patterns.py +++ b/openhcs/core/function_patterns.py @@ -18,7 +18,7 @@ if TYPE_CHECKING: from openhcs.core.aligned_image_payload import AlignedImageSliceContext from openhcs.core.pipeline.compilation_session import CompilationPathResolver - from openhcs.core.steps.function_runtime import FunctionInvocationArtifactScope + from openhcs.core.steps.function_runtime import FunctionCoreExecutor from pyqt_reactive.pattern_metadata import PatternScopeToken from python_introspect import Enableable @@ -229,9 +229,24 @@ class InvocationArtifactInputEdgePlan: spec: ArtifactSpec storage_plan: ArtifactInputPlan | None = field(compare=False) projection: ArtifactInputProjectionPlan | None - consumes_main_flow: bool = False main_flow_projection: MainFlowInputProjection | None = None + @staticmethod + def source_projection( + spec: ArtifactSpec, + main_flow_artifacts: ArtifactSpecCollection, + invocation_sources: ArtifactSpecCollection, + ) -> MainFlowInputProjection | None: + """Derive the primary source role independently of its pixel producer.""" + main_flow_refs = main_flow_artifacts.ref_set() + if spec.ref() not in main_flow_refs or spec.ref() not in invocation_sources.ref_set(): + return None + return ( + MainFlowInputProjection.COMPLETE_PAYLOAD + if len(main_flow_refs) == 1 + else MainFlowInputProjection.DECLARED_SOURCE_IMAGE + ) + @classmethod def from_source_declarations( cls, @@ -245,13 +260,12 @@ def from_source_declarations( ) -> "InvocationArtifactInputEdgePlan": """Project one unstored source occurrence from its exact declarations.""" - main_flow_refs = main_flow_artifacts.ref_set() - consumes_main_flow = ( - spec.ref() in main_flow_refs and spec.ref() in invocation_sources.ref_set() + main_flow_projection = cls.source_projection( + spec, main_flow_artifacts, invocation_sources, ) edge_type = ( CompiledMetadataArtifactInputEdgePlan - if metadata_available and not (consumes_main_flow or source_binding_available) + if metadata_available and main_flow_projection is None and not source_binding_available else cls ) return edge_type( @@ -259,16 +273,7 @@ def from_source_declarations( spec=spec, storage_plan=None, projection=None, - consumes_main_flow=consumes_main_flow, - main_flow_projection=( - MainFlowInputProjection.COMPLETE_PAYLOAD - if consumes_main_flow and len(main_flow_refs) == 1 - else ( - MainFlowInputProjection.DECLARED_SOURCE_IMAGE - if consumes_main_flow - else None - ) - ), + main_flow_projection=main_flow_projection, ) def uses_runtime_storage(self) -> bool: @@ -277,11 +282,13 @@ def uses_runtime_storage(self) -> bool: def requires_callable_binding(self) -> bool: """Admit parameter-bearing sources and validate every stored argument.""" - return self.uses_runtime_storage() or self.spec.binds_callable_parameter() + return self.spec.binds_callable_parameter() or ( + self.uses_runtime_storage() and self.main_flow_projection is None + ) def resolve_unstored_payload( self, - scope: "FunctionInvocationArtifactScope", + scope: "FunctionCoreExecutor", primary_source_payload: object, ) -> object: """Resolve source input through the existing exact-origin authority.""" @@ -290,22 +297,6 @@ def resolve_unstored_payload( ) def __post_init__(self) -> None: - if type(self.consumes_main_flow) is not bool: - raise TypeError( - "Invocation artifact input edge consumes_main_flow must be bool, " - f"got {type(self.consumes_main_flow).__name__}." - ) - if self.consumes_main_flow and self.main_flow_projection is None: - object.__setattr__( - self, - "main_flow_projection", - MainFlowInputProjection.DECLARED_SOURCE_IMAGE, - ) - elif not self.consumes_main_flow and self.main_flow_projection is not None: - raise ValueError( - "Invocation artifact input edge cannot declare a main-flow " - "projection when it does not consume main flow." - ) if self.main_flow_projection is not None and not isinstance( self.main_flow_projection, MainFlowInputProjection, @@ -315,11 +306,6 @@ def __post_init__(self) -> None: "MainFlowInputProjection or None, got " f"{type(self.main_flow_projection).__name__}." ) - if self.consumes_main_flow and self.storage_plan is not None: - raise ValueError( - "Invocation artifact input edge cannot consume main flow when an " - "exact storage plan owns the input." - ) if (self.storage_plan is None) != (self.projection is None): raise ValueError( "Invocation artifact input edge storage and projection must be " @@ -342,25 +328,12 @@ class CompiledMetadataArtifactInputEdgePlan(InvocationArtifactInputEdgePlan): def resolve_unstored_payload( self, - scope: "FunctionInvocationArtifactScope", + scope: "FunctionCoreExecutor", primary_source_payload: object, ) -> object: return scope.invocation.artifact_parameter_value(self.spec) -@dataclass(frozen=True) -class FunctionInvocation: - """One enabled callable extracted from a FunctionStep pattern.""" - - contract: CallableContract - key: FunctionInvocationKey - - @property - def func(self) -> FunctionPatternCallable: - """Callable reference used by the runtime invocation.""" - return self.contract.func - - @dataclass(frozen=True, slots=True) class NormalizedFunctionItem: """Compiler-normalized callable item with stable invocation identity.""" @@ -402,6 +375,38 @@ def group_key(self) -> str: return str(self.source_group_key) + @classmethod + def from_pattern( + cls, + group_key: FunctionGroupKey, + pattern: FunctionPatternSyntax, + ) -> NormalizedFunctionGroup: + items = pattern if isinstance(pattern, list) else [pattern] + normalized_items: list[NormalizedFunctionItem] = [] + + for item in items: + func, kwargs = _split_function_item(item) + if RUNTIME_CALLABLE_KWARG_POLICY.item_is_disabled(kwargs): + continue + contract = CallableContract.from_prepared_callable(func) + position = len(normalized_items) + normalized_items.append( + NormalizedFunctionItem( + key=FunctionInvocationKey.from_contract( + contract, + group_key, + position, + ), + contract=contract, + kwargs=_freeze_runtime_kwargs(kwargs), + ) + ) + + return cls( + source_group_key=group_key, + items=tuple(normalized_items), + ) + @dataclass(frozen=True, slots=True) class NormalizedFunctionPattern: @@ -426,6 +431,44 @@ def __post_init__(self) -> None: ) source_key_by_invocation[item.key] = group.source_group_key + def __bool__(self) -> bool: + return any(group.items for group in self.groups) + + @property + def source_group_keys(self) -> tuple[FunctionGroupKey, ...]: + return tuple(group.source_group_key for group in self.groups) + + def with_artifact_input_values( + self, values_by_key: RuntimeKwargMap + ) -> "NormalizedFunctionPattern": + """Inject this axis's metadata without rebuilding captured declarations.""" + return replace( + self, + groups=tuple( + replace( + group, + items=tuple( + replace( + item, + kwargs=_freeze_runtime_kwargs( + { + **item.kwargs_dict, + **{ + spec.parameter_name: values_by_key[spec.name] + for spec in item.contract.artifact_inputs + if spec.binds_callable_parameter() + and spec.name in values_by_key + }, + } + ), + ) + for item in group.items + ), + ) + for group in self.groups + ), + ) + def iter_items(self) -> Iterator[NormalizedFunctionItem]: """Yield normalized callable items in runtime order.""" for group in self.groups: @@ -475,11 +518,6 @@ def execution_memory_type(self) -> str | None: """Declared execution memory type from the callable contract.""" return self.contract.execution_memory_type - @property - def kwargs_dict(self) -> dict: - """Return user-authored callable kwargs as a runtime dict.""" - return dict(self.kwargs) - def output_plans_for_component( self, execution_scope: ComponentGroupScope, @@ -662,6 +700,83 @@ def proves_primary_image_carrier( transition = self.contract.primary_image_carrier_transition return transition is not None and transition.proves(requirement) + @classmethod + def from_normalized_item( + cls, + item: NormalizedFunctionItem, + input_plans: Mapping[ArtifactSpecRef, ArtifactInputPlan], + output_plans: Mapping[ArtifactSpecRef, ArtifactOutputPlan], + declaration_provider: InvocationArtifactDeclarationProviderLike, + invocation_contract_provider: InvocationContractProvider, + step_context: ArtifactDeclarationStepContext, + runtime_parameter_bindings: Sequence[RuntimeParameterBinding], + path_resolver: "CompilationPathResolver | None", + ) -> "CompiledFunctionInvocation": + contract_plan = invocation_contract_provider(item, step_context) + if contract_plan is None: + invocation_kwargs = item.kwargs + else: + invocation_kwargs = contract_plan.consume_authored_kwargs( + item, + step_context, + ) + item = replace(item, contract=contract_plan.contract) + artifact_selector = declaration_provider(item, step_context) + item.contract.validate_artifact_input_parameter_bindings() + artifact_selector.validate_artifact_output_declarations() + artifact_input_plans = artifact_selector.select_plans( + ArtifactInputPlan, + input_plans, + ) + user_kwargs, compiled_runtime_bindings = _compile_runtime_parameter_bindings( + invocation_kwargs, + runtime_parameter_bindings, + ( + *item.contract.runtime_bound_parameters, + *item.contract.config_bound_parameter_names, + ), + ) + public_kwargs = dict(user_kwargs) + if path_resolver is not None: + public_kwargs = item.contract.resolve_declared_paths( + public_kwargs, + path_resolver, + ) + else: + relative_parameters = tuple( + parameter_name + for parameter_name, (_declaration, value) in ( + item.contract.declared_path_values(public_kwargs).items() + ) + if isinstance(value, (str, Path)) and not Path(value).is_absolute() + ) + if relative_parameters: + raise ValueError( + f"Callable {item.contract.function_name!r} has relative declared " + f"paths {relative_parameters!r} but compilation supplied no " + "CompilationPathResolver." + ) + runtime_loaded_input_refs = frozenset(plan.ref() for plan in artifact_input_plans) + validated_kwargs = item.contract.validate_public_kwargs( + public_kwargs, + runtime_loaded_artifact_parameter_names=( + spec.parameter_name + for spec in item.contract.artifact_inputs + if spec.parameter_name is not None + and spec.ref() in runtime_loaded_input_refs + ), + ) + return cls( + key=item.key, + contract=item.contract, + kwargs=validated_kwargs, + artifact_output_plans=artifact_selector.select_plans( + ArtifactOutputPlan, + output_plans, + ), + runtime_parameter_bindings=compiled_runtime_bindings, + ) + @dataclass(frozen=True, slots=True) class CompiledFunctionGroup: @@ -722,7 +837,7 @@ def _main_flow_input_refs( edge.spec.ref() for _invocation, edges in invocations_and_edges for edge in edges - if edge.consumes_main_flow + if edge.main_flow_projection is not None ) ) if main_flow_refs: @@ -733,6 +848,69 @@ def _main_flow_input_refs( ) return None if has_implicit_image_argument else () + def stored_primary_input_edges_for_component( + self, + execution_scope: ComponentGroupScope, + component_key: str | None, + ) -> tuple[InvocationArtifactInputEdgePlan, ...] | None: + """Select exact producer edges supplying an artifact-owned cohort. + + Artifact-owning invocations admit declared semantic primary sources. + Context-only inputs can supply a cohort when no raw primary image is + consumed. Unknown raw adapters retain source-path transport. + """ + active = tuple( + (invocation, invocation.input_edges_for_outputs(active_outputs)) + for invocation in self.invocations + if ( + active_outputs := invocation.output_plans_for_component( + execution_scope, component_key, + ) + ) is not None + ) + if not active or any( + invocation.contract.accepts_implicit_main_flow_input + and not invocation.adapter_manages_artifact_inputs + for invocation, edges in active + ): + return None + primary_edges = tuple( + edge + for invocation, edges in active + for edge in edges + if edge.main_flow_projection is not None + and edge.spec.artifact_type.carries_source_image_context + ) + if not primary_edges: + primary_edges = tuple( + edge + for invocation, edges in active + for domain_refs in (invocation.contract.invocation_domain_inputs.ref_set(),) + for edge in edges + if edge.spec.ref() + in domain_refs + and edge.spec.artifact_type.carries_source_image_context + ) + if not primary_edges or any( + edge.storage_plan is None for edge in primary_edges + ): + return None + selected: dict[ArtifactSpecRef, InvocationArtifactInputEdgePlan] = {} + for edge in primary_edges: + previous = selected.get(edge.spec.ref()) + if previous is not None and ( + edge.spec != previous.spec + or edge.storage_plan != previous.storage_plan + or edge.projection != previous.projection + or edge.main_flow_projection != previous.main_flow_projection + ): + raise ValueError( + f"Artifact-owned cohort source {edge.spec.ref()!r} has " + "conflicting compiled producer authorities." + ) + selected.setdefault(edge.spec.ref(), edge) + return tuple(selected.values()) + def resulting_main_flow_output_plans(self) -> tuple[ArtifactOutputPlan, ...]: """Return exact named output plans carried after this callable chain.""" @@ -815,6 +993,37 @@ def primary_image_carrier_proof( return CreatedPrimaryImageCarrierProof() return InheritedPrimaryImageCarrierProof() + @classmethod + def from_normalized_group( + cls, + normalized_group: NormalizedFunctionGroup, + *, + input_plans: Mapping[ArtifactSpecRef, ArtifactInputPlan], + output_plans: Mapping[ArtifactSpecRef, ArtifactOutputPlan], + declaration_provider: InvocationArtifactDeclarationProviderLike, + invocation_contract_provider: InvocationContractProvider, + step_context: ArtifactDeclarationStepContext, + runtime_parameter_bindings: Sequence[RuntimeParameterBinding], + path_resolver: "CompilationPathResolver | None", + ) -> "CompiledFunctionGroup": + """Compile an authored group through its declaration-owned invocation values.""" + return cls( + group_key=normalized_group.group_key, + invocations=tuple( + CompiledFunctionInvocation.from_normalized_item( + item=item, + input_plans=input_plans, + output_plans=output_plans, + declaration_provider=declaration_provider, + invocation_contract_provider=invocation_contract_provider, + step_context=step_context, + runtime_parameter_bindings=runtime_parameter_bindings, + path_resolver=path_resolver, + ) + for item in normalized_group.items + ), + ) + class PrimaryImageCarrierProof(ABC): """One group-owned proof result, not another carrier metadata authority.""" @@ -1025,23 +1234,22 @@ def prepare_grouped_patterns( def iter_enabled_function_invocations( pattern: FunctionPatternSyntax, -) -> Iterator[FunctionInvocation]: +) -> Iterator[NormalizedFunctionItem]: """Yield enabled callable invocations from any supported function pattern. Positions are renumbered after disabled functions are filtered out, matching the current runtime behavior for list chains and dict-pattern branches. """ - for item in normalize_function_pattern(pattern).iter_items(): - yield FunctionInvocation( - contract=item.contract, - key=item.key, - ) + yield from normalize_function_pattern(pattern).iter_items() def get_core_callable( func_pattern: FunctionPatternSyntax, ) -> FunctionPatternCallable | None: """Extract the first effective callable reference from a function pattern.""" + if isinstance(func_pattern, NormalizedFunctionPattern): + return next((item.func for item in func_pattern.iter_items()), None) + if isinstance(func_pattern, FunctionReference): return func_pattern @@ -1075,10 +1283,9 @@ def normalize_function_pattern( """Lower raw FunctionStep.func syntax into typed grouped callable items.""" if isinstance(pattern, NormalizedFunctionPattern): return pattern - normalizer = NormalizeFunctionGroupAuthority() if isinstance(pattern, dict): groups = tuple( - normalizer.normalize(group_key=group_key, pattern=value) + NormalizedFunctionGroup.from_pattern(group_key=group_key, pattern=value) for group_key, value in pattern.items() ) return NormalizedFunctionPattern( @@ -1088,7 +1295,7 @@ def normalize_function_pattern( return NormalizedFunctionPattern( groups=( - normalizer.normalize( + NormalizedFunctionGroup.from_pattern( group_key=DEFAULT_GROUP_KEY, pattern=pattern, ), @@ -1145,17 +1352,21 @@ def compile_function_pattern( ) -> CompiledFunctionPattern: """Compile raw FunctionStep.func syntax into the runtime source of truth.""" normalized = normalize_function_pattern(pattern) - compiler = CompileFunctionGroupAuthority( - input_plans=input_plans, - output_plans=output_plans, - declaration_provider=declaration_provider, - invocation_contract_provider=invocation_contract_provider, - step_context=step_context, - runtime_parameter_bindings=tuple(runtime_parameter_bindings), - path_resolver=path_resolver, - ) + runtime_parameter_bindings = tuple(runtime_parameter_bindings) return CompiledFunctionPattern( - groups=tuple(compiler.compile(group) for group in normalized.groups), + groups=tuple( + CompiledFunctionGroup.from_normalized_group( + group, + input_plans=input_plans, + output_plans=output_plans, + declaration_provider=declaration_provider, + invocation_contract_provider=invocation_contract_provider, + step_context=step_context, + runtime_parameter_bindings=runtime_parameter_bindings, + path_resolver=path_resolver, + ) + for group in normalized.groups + ), is_grouped=normalized.is_grouped, ) @@ -1164,6 +1375,8 @@ def strip_disabled_functions( pattern: FunctionPatternSyntax, ) -> FunctionPatternSyntax | None: """Remove disabled function items from any supported function-pattern shape.""" + if isinstance(pattern, NormalizedFunctionPattern): + return pattern if isinstance(pattern, tuple): _func, kwargs = _split_function_item(pattern) if RUNTIME_CALLABLE_KWARG_POLICY.item_is_disabled(kwargs): @@ -1216,6 +1429,9 @@ def inject_artifact_input_values( if not values_by_key: return pattern + if isinstance(pattern, NormalizedFunctionPattern): + return pattern.with_artifact_input_values(values_by_key) + if _is_callable_pattern_item(pattern): core_callable = get_core_callable(pattern) contract = CallableContract.from_callable(core_callable) @@ -1274,152 +1490,6 @@ def merge_replacing_existing( return self.merge(pattern) -@dataclass(frozen=True, slots=True) -class NormalizeFunctionGroupAuthority: - """Normalize one function-pattern group into callable invocation items.""" - - def normalize( - self, - group_key: FunctionGroupKey, - pattern: FunctionPatternSyntax, - ) -> NormalizedFunctionGroup: - items = pattern if isinstance(pattern, list) else [pattern] - normalized_items: list[NormalizedFunctionItem] = [] - - for item in items: - func, kwargs = _split_function_item(item) - if RUNTIME_CALLABLE_KWARG_POLICY.item_is_disabled(kwargs): - continue - contract = CallableContract.from_callable(func) - position = len(normalized_items) - normalized_items.append( - NormalizedFunctionItem( - key=FunctionInvocationKey.from_contract( - contract, - group_key, - position, - ), - contract=contract, - kwargs=_freeze_runtime_kwargs(kwargs), - ) - ) - - return NormalizedFunctionGroup( - source_group_key=group_key, - items=tuple(normalized_items), - ) - - -@dataclass(frozen=True, slots=True, kw_only=True) -class CompileFunctionGroupAuthority: - """Compile normalized function-pattern groups into invocation plans.""" - - input_plans: Mapping[ArtifactSpecRef, ArtifactInputPlan] - output_plans: Mapping[ArtifactSpecRef, ArtifactOutputPlan] - declaration_provider: InvocationArtifactDeclarationProviderLike - invocation_contract_provider: InvocationContractProvider - step_context: ArtifactDeclarationStepContext - runtime_parameter_bindings: tuple[RuntimeParameterBinding, ...] = () - path_resolver: "CompilationPathResolver | None" = None - - def compile( - self, normalized_group: NormalizedFunctionGroup - ) -> CompiledFunctionGroup: - invocations = tuple( - _compile_invocation( - item=item, - input_plans=self.input_plans, - output_plans=self.output_plans, - declaration_provider=self.declaration_provider, - invocation_contract_provider=self.invocation_contract_provider, - step_context=self.step_context, - runtime_parameter_bindings=self.runtime_parameter_bindings, - path_resolver=self.path_resolver, - ) - for item in normalized_group.items - ) - return CompiledFunctionGroup( - group_key=normalized_group.group_key, - invocations=invocations, - ) - - -def _compile_invocation( - item: NormalizedFunctionItem, - input_plans: Mapping[ArtifactSpecRef, ArtifactInputPlan], - output_plans: Mapping[ArtifactSpecRef, ArtifactOutputPlan], - declaration_provider: InvocationArtifactDeclarationProviderLike, - invocation_contract_provider: InvocationContractProvider, - step_context: ArtifactDeclarationStepContext, - runtime_parameter_bindings: Sequence[RuntimeParameterBinding], - path_resolver: "CompilationPathResolver | None", -) -> CompiledFunctionInvocation: - contract_plan = invocation_contract_provider(item, step_context) - if contract_plan is None: - invocation_kwargs = item.kwargs - else: - invocation_kwargs = contract_plan.consume_authored_kwargs( - item, - step_context, - ) - item = replace(item, contract=contract_plan.contract) - artifact_selector = declaration_provider(item, step_context) - item.contract.validate_artifact_input_parameter_bindings() - artifact_selector.validate_artifact_output_declarations() - artifact_input_plans = artifact_selector.select_plans( - ArtifactInputPlan, - input_plans, - ) - user_kwargs, compiled_runtime_bindings = _compile_runtime_parameter_bindings( - invocation_kwargs, - runtime_parameter_bindings, - ( - *item.contract.runtime_bound_parameters, - *item.contract.config_bound_parameter_names, - ), - ) - public_kwargs = dict(user_kwargs) - if path_resolver is not None: - public_kwargs = item.contract.resolve_declared_paths( - public_kwargs, - path_resolver, - ) - else: - relative_parameters = tuple( - parameter_name - for parameter_name, (_declaration, value) in ( - item.contract.declared_path_values(public_kwargs).items() - ) - if isinstance(value, (str, Path)) and not Path(value).is_absolute() - ) - if relative_parameters: - raise ValueError( - f"Callable {item.contract.function_name!r} has relative declared " - f"paths {relative_parameters!r} but compilation supplied no " - "CompilationPathResolver." - ) - runtime_loaded_input_refs = frozenset(plan.ref() for plan in artifact_input_plans) - validated_kwargs = item.contract.validate_public_kwargs( - public_kwargs, - runtime_loaded_artifact_parameter_names=( - spec.parameter_name - for spec in item.contract.artifact_inputs - if spec.parameter_name is not None - and spec.ref() in runtime_loaded_input_refs - ), - ) - return CompiledFunctionInvocation( - key=item.key, - contract=item.contract, - kwargs=validated_kwargs, - artifact_output_plans=artifact_selector.select_plans( - ArtifactOutputPlan, - output_plans, - ), - runtime_parameter_bindings=compiled_runtime_bindings, - ) - - def _compile_runtime_parameter_bindings( kwargs: RuntimeKwargItems, runtime_parameter_bindings: Sequence[RuntimeParameterBinding], diff --git a/openhcs/core/function_step_transport.py b/openhcs/core/function_step_transport.py index 2ea347cc2b..204a75a7fc 100644 --- a/openhcs/core/function_step_transport.py +++ b/openhcs/core/function_step_transport.py @@ -13,6 +13,8 @@ CompiledFunctionGroup, CompiledFunctionInvocation, CompiledFunctionPattern, + NormalizedFunctionPattern, + NormalizedFunctionItem, ) from openhcs.core.function_reference import ( FunctionReference, @@ -116,6 +118,20 @@ def normalize_step(cls, step: Any) -> Any: @classmethod def normalize_function_spec(cls, func_spec: Any) -> Any: + if isinstance(func_spec, NormalizedFunctionPattern): + return replace( + func_spec, + groups=tuple( + replace( + group, + items=tuple( + cls.normalize_compiled_invocation(item) + for item in group.items + ), + ) + for group in func_spec.groups + ), + ) if isinstance(func_spec, FunctionReference): return cls.normalize_function_reference(func_spec) if isinstance(func_spec, list): @@ -205,8 +221,8 @@ def normalize_compiled_group( @classmethod def normalize_compiled_invocation( cls, - invocation: CompiledFunctionInvocation, - ) -> CompiledFunctionInvocation: + invocation: NormalizedFunctionItem, + ) -> NormalizedFunctionItem: contract = cls.normalize_callable_contract(invocation.contract) if contract is invocation.contract: return invocation diff --git a/openhcs/core/image_file_serialization.py b/openhcs/core/image_file_serialization.py index 0b2593fa72..d330a45be6 100644 --- a/openhcs/core/image_file_serialization.py +++ b/openhcs/core/image_file_serialization.py @@ -4,13 +4,14 @@ import logging from abc import ABC, abstractmethod -from dataclasses import dataclass +from dataclasses import dataclass, replace from functools import lru_cache from pathlib import Path from typing import Any, Callable, ClassVar, Sequence import numpy as np from metaclass_registry import AutoRegisterMeta +from polystore.config import TiffConfig, TiffPhotometric, TiffPlanarConfig from openhcs.constants.constants import FileFormat from openhcs.core.registry_strategies import NominalTypeStrategyFamilyMixin @@ -251,6 +252,42 @@ def require_path(cls, path: str | Path) -> "ImageFileFormat": def prepare(self, payload: Any) -> Any: """Return a payload suitable for this file format.""" + def storage_config( + self, payload: Any, configured: TiffConfig | None + ) -> TiffConfig | None: + """Non-TIFF formats retain their existing backend writer configuration.""" + return None + + @classmethod + def storage_write_batches( + cls, + payloads: Sequence[Any], + paths: Sequence[str | Path], + configured: TiffConfig | None, + ) -> tuple[tuple[tuple[int, ...], TiffConfig | None], ...]: + """Batch compatible declared image codecs without changing output order.""" + if len(payloads) != len(paths): + raise ValueError("Image storage payload/path cardinality mismatch.") + batches = [] + for index, (payload, path) in enumerate(zip(payloads, paths, strict=True)): + config = ( + cls.require_path(path).storage_config( + payload, + ( + configured + if configured is not None and configured.applies_to_path(path) + else None + ), + ) + if cls.is_image_path(path) + else None + ) + if batches and batches[-1][1] == config: + batches[-1][0].append(index) + else: + batches.append(([index], config)) + return tuple((tuple(indices), config) for indices, config in batches) + def read(self, path: str | Path) -> np.ndarray: """Read pixels through this exact registered image-file format.""" import imageio.v3 as iio @@ -413,6 +450,50 @@ def preserves_pixel_values(self, source_dtype: Any) -> bool: def prepare(self, payload: Any) -> Any: return image_payload_data(payload) + def storage_config( + self, payload: Any, configured: TiffConfig | None + ) -> TiffConfig | None: + metadata = image_payload_metadata(payload) + if not metadata.persists_whole_image(): + return configured + data = image_payload_data(payload) + channel_axis = metadata.normalized_source_channel_axis(data) + axes = list("ZYX") + planarconfig = None + photometric = TiffPhotometric.MINISBLACK + if channel_axis is not None: + if channel_axis < 0: + channel_axis += data.ndim + if channel_axis not in (data.ndim - 1, data.ndim - 3): + raise ValueError( + "Intrinsic TIFF channels must be contiguous or planar before Y/X." + ) + axes.insert(channel_axis, "S") + planarconfig = ( + TiffPlanarConfig.CONTIG + if channel_axis == data.ndim - 1 + else TiffPlanarConfig.SEPARATE + ) + photometric = TiffPhotometric.RGB + if len(axes) != data.ndim: + raise ValueError( + "Intrinsic TIFF pixels must retain exactly their declared Z/Y/X and channel axes." + ) + return replace( + configured if configured is not None else TiffConfig(), + photometric=photometric, + axes="".join(axes), + planarconfig=planarconfig, + ) + + def write(self, path: str | Path, payload: Any) -> None: + config = self.storage_config(payload, None) + if config is None: + return super().write(path, payload) + import tifffile + + tifffile.imwrite(path, self.prepare(payload), **config.tifffile_write_kwargs()) + def requires_plane_store_decoder(self, path: Path) -> bool: import tifffile diff --git a/openhcs/core/measurement_feature_queries.py b/openhcs/core/measurement_feature_queries.py index 15acdfb0d7..a7a940e16c 100644 --- a/openhcs/core/measurement_feature_queries.py +++ b/openhcs/core/measurement_feature_queries.py @@ -3,7 +3,7 @@ from __future__ import annotations from abc import ABC, abstractmethod -from collections.abc import Callable, Mapping, Sequence +from collections.abc import Callable, Iterator, Mapping, Sequence from dataclasses import dataclass, field from types import MappingProxyType from typing import Any, ClassVar @@ -18,23 +18,18 @@ resolve_runtime_measurement_lookup_dialect, ) from openhcs.core.measurement_row_materialization import ( - MeasurementObjectLabelResolution, MeasurementRowOwnership, columnar_row_values, is_structural_missing_measurement_cell as _is_structural_missing_measurement_cell, measurement_object_label, + measurement_object_label_value, measurement_row_has_object_identity, measurement_row_object_name, measurement_row_source_image_name, measurement_rows, measurement_table_axis_values, ) -from openhcs.core.process_local_cache import ( - IdentityBoundProcessCache, - BoundedCache, - RegisteredProcessLocalBoundedCache, - identity_owner_tuples_match, -) +from openhcs.core.process_local_cache import BoundedCache from openhcs.core.registry_strategies import NominalTypeKeyedStrategyMixin from openhcs.core.runtime_identifier import normalize_runtime_identifier from openhcs.core.runtime_measurements import ( @@ -64,14 +59,6 @@ OptionalMeasurementValueIndexResult = MeasurementValueIndexResult | None MeasurementTablesByObject = Mapping[str, tuple[MeasurementTable, ...]] MeasurementValueIndexesByObject = Mapping[str, MeasurementValueIndexResult] -MeasurementObjectFeatureVectorBatchCacheValue = tuple[ - tuple[MeasurementTable, ...], - MeasurementValueIndexesByObject, -] -MeasurementObjectFeatureAxisBatchCacheValue = tuple[ - tuple[MeasurementTable, ...], - Mapping[int, MeasurementValueIndexesByObject], -] _DIAGNOSTIC_NONE = "" @@ -213,33 +200,12 @@ def value_is_present(self, value: object) -> bool: return measurement_axis_integer_value(value, self.axis) is not None -@dataclass(frozen=True, slots=True) -class MeasurementObjectFeatureVectorBatchCacheKey: - """Identity key for a batch object-feature value-index lookup.""" - - feature_name: str - dialect_identity: int - table_identities: tuple[int, ...] - - -@dataclass(frozen=True, slots=True) -class MeasurementObjectFeatureAxisBatchCacheKey: - """Identity key for a batch object-feature row-axis value-index lookup.""" - - feature_name: str - dialect_identity: int - row_axis: MeasurementRowAxisField - table_identities: tuple[int, ...] - - @dataclass(frozen=True, slots=True) class ColumnarMeasurementTableSchema: - """Cached semantic projection for nominal columnar measurement rows.""" + """Call-local semantic projection for nominal columnar measurement rows.""" columns: tuple[str, ...] normalized_columns: dict[str, str] - object_names: tuple[str, ...] - feature_names: frozenset[str] feature_name_values: Sequence[object] | None object_name_values: Sequence[object] | None source_image_name_values: Sequence[object] | None @@ -250,19 +216,13 @@ class ColumnarMeasurementTableSchema: @classmethod def from_table(cls, table: MeasurementTable) -> "ColumnarMeasurementTableSchema": rows = table.rows - cached = ColumnarMeasurementTableSchemaCache.process_cache().get_bound(rows) - if cached is not None: - return cached - columns = tuple(str(column) for column in rows.columns) normalized_columns = { column: normalize_measurement_token(column) for column in columns } - table_object_name = table.subject.object_name object_name_values = ( columnar_row_values(rows, MeasurementRowAxisField.OBJECT_NAME.value) - if table_object_name is None - and MeasurementRowAxisField.OBJECT_NAME.value in columns + if MeasurementRowAxisField.OBJECT_NAME.value in columns else None ) source_image_name_values = ( @@ -271,45 +231,93 @@ def from_table(cls, table: MeasurementTable) -> "ColumnarMeasurementTableSchema" else None ) feature_name_values = cls._feature_name_values(rows, columns) - if table_object_name is not None: - object_names = (table_object_name,) - elif object_name_values is not None: - object_names = tuple( - dict.fromkeys( - object_name - for value in object_name_values - for object_name in (str(value).strip(),) - if object_name + return cls( + columns=columns, + normalized_columns=normalized_columns, + feature_name_values=feature_name_values, + object_name_values=object_name_values, + source_image_name_values=source_image_name_values, + feature_masks_by_candidates={}, + object_masks_by_name={}, + source_masks_by_candidates={}, + ) + + def object_names(self, table: MeasurementTable) -> tuple[str, ...]: + """Derive current subjects from table ownership and admitted row columns.""" + if table.subject.object_name is not None: + return (table.subject.object_name,) + return tuple( + dict.fromkeys( + name + for value in ( + () if self.object_name_values is None else self.object_name_values ) + for name in (str(value).strip(),) + if name ) - else: - object_names = () - - return ColumnarMeasurementTableSchemaCache.process_cache().put_bound( - rows, - cls( - columns=columns, - normalized_columns=normalized_columns, - object_names=object_names, - feature_names=( - MeasurementTableObjectFeatureSemantics.feature_names_from_names( - columns, - table, - ) - if feature_name_values is None - else frozenset( - str(value) - for value in feature_name_values - if value not in (None, "") - ) - ), - feature_name_values=feature_name_values, - object_name_values=object_name_values, - source_image_name_values=source_image_name_values, - feature_masks_by_candidates={}, - object_masks_by_name={}, - source_masks_by_candidates={}, - ), + ) + + def feature_names(self, table: MeasurementTable) -> frozenset[str]: + """Derive current declared features without a parallel semantics carrier.""" + if self.feature_name_values is not None: + return frozenset( + str(value) + for value in self.feature_name_values + if value not in (None, "") + ) + excluded = set(MeasurementRowAxisField.field_names()) + if table.subject.object_id_field is not None: + excluded.add(table.subject.object_id_field) + return frozenset(name for name in self.columns if name not in excluded) + + @classmethod + def tables_for_object( + cls, + tables: tuple[MeasurementTable, ...], + object_name: str, + ) -> tuple[MeasurementTable, ...]: + return tuple( + table + for table in tables + if object_name in cls.from_table(table).object_names(table) + ) + + @classmethod + def tables_for_object_feature( + cls, + tables: tuple[MeasurementTable, ...], + object_name: str, + feature_name: str, + *, + dialect: RuntimeMeasurementLookupDialectLike = CURRENT_RUNTIME_MEASUREMENT_LOOKUP_DIALECT, + ) -> tuple[MeasurementTable, ...]: + query = MeasurementFeatureQuery(feature_name, dialect=dialect) + query_object = ( + resolve_runtime_measurement_lookup_dialect(dialect) + .feature_lookup(feature_name) + .query_object_name(object_name) + ) + schemas = tuple((table, cls.from_table(table)) for table in tables) + selected = ( + schemas + if query_object is None + else tuple( + (table, schema) + for table, schema in schemas + if query_object in schema.object_names(table) + ) + ) + if not selected and query_object is not None: + selected = tuple( + (table, schema) + for table, schema in schemas + if table.subject.object_id_field is not None + and not schema.object_names(table) + ) + return tuple( + table + for table, schema in selected + if query.table_may_carry_feature(table, schema) ) @staticmethod @@ -326,19 +334,30 @@ def feature_mask(self, candidates: tuple[str, ...]) -> Any | None: """Return a boolean row mask for row-declared feature ownership.""" if self.feature_name_values is None: return None - cached = self.feature_masks_by_candidates.get(candidates) - if cached is not None: - return cached - normalized_features = np.asarray( - [ - normalize_measurement_token(str(value)) - for value in self.feature_name_values - ], - dtype=object, + return self.feature_masks((candidates,))[candidates] + + def feature_masks( + self, candidates: Sequence[tuple[str, ...]] + ) -> Mapping[tuple[str, ...], Any]: + """Resolve multiple feature selections from one row-feature normalization.""" + missing = tuple( + candidate + for candidate in dict.fromkeys(candidates) + if candidate not in self.feature_masks_by_candidates ) - mask = np.isin(normalized_features, np.asarray(candidates, dtype=object)) - self.feature_masks_by_candidates[candidates] = mask - return mask + if missing and self.feature_name_values is not None: + normalized_features = np.asarray( + [ + normalize_measurement_token(str(value)) + for value in self.feature_name_values + ], + dtype=object, + ) + for candidate in missing: + self.feature_masks_by_candidates[candidate] = np.isin( + normalized_features, np.asarray(candidate, dtype=object) + ) + return self.feature_masks_by_candidates def object_mask(self, object_name: str) -> Any | None: """Return a boolean row mask for a row-owned object table.""" @@ -378,6 +397,255 @@ def source_mask(self, source_candidates: tuple[str, ...]) -> Any | None: self.source_masks_by_candidates[source_candidates] = mask return mask + def feature_value_indexes( + self, + table: MeasurementTable, + queries: Mapping[str, "MeasurementFeatureQuery"], + query_object_names_by_feature: Mapping[str, Mapping[str | None, str | None]], + *, + index_type: type["MeasurementFeatureValueIndex"], + row_masks: Mapping[int | None, Any | None] | None = None, + measurement_value_qualifier: Callable[[object], bool] | None = None, + ) -> Iterator[ + tuple[str, dict[int | None, dict[str | None, "MeasurementFeatureValueIndex"]]] + ]: + """Project one admitted table epoch into feature/object/axis indexes. + + Default qualification is shared per physical column. Opaque qualifiers + run for each query before reading its object identity, preserving their + observable calls and mutations. Nothing survives this call. + """ + rows = table.rows + projections = {None: None} if row_masks is None else row_masks + object_labels_by_row: dict[int, int | None] = {} + admitted_columns: dict[str, tuple[Any, Any]] = {} + columns_by_token: dict[str, list[str]] = {} + for column, token in self.normalized_columns.items(): + columns_by_token.setdefault(token, []).append(column) + self.feature_masks(tuple(query.field_candidates for query in queries.values())) + for feature_name, query in queries.items(): + if measurement_value_qualifier is not None: + admitted_columns.clear() + object_labels_by_row.clear() + query_object_names_by_result = query_object_names_by_feature[feature_name] + if not query.table_source_matches_feature(table): + yield feature_name, { + axis: { + result_name: index_type() + for result_name in query_object_names_by_result + } + for axis in projections + } + continue + if self.feature_name_values is None: + feature_columns = tuple( + dict.fromkeys( + column + for candidate in query.field_candidates + for column in columns_by_token.get(candidate, ()) + ) + ) + else: + feature_column = self.matching_feature_column(query) + feature_columns = () if feature_column is None else (feature_column,) + if not feature_columns: + yield feature_name, {axis: {} for axis in projections} + continue + raw_values = None + value_mask = None + for feature_column in feature_columns: + if feature_column not in admitted_columns: + values = np.asarray( + columnar_row_values(rows, feature_column), dtype=object + ) + mask = np.asarray( + [ + not _is_structural_missing_measurement_cell(value) + and ( + bool(measurement_value_qualifier(value)) + if measurement_value_qualifier is not None + else MeasurementScalarLiteral( + value + ).is_present_measurement_value + ) + for value in values + ], + dtype=bool, + ) + admitted_columns[feature_column] = values, mask + candidate_values, candidate_mask = admitted_columns[feature_column] + if raw_values is None: + raw_values, value_mask = candidate_values, candidate_mask + continue + selected_mask = np.logical_and( + np.logical_not(value_mask), candidate_mask + ) + # Alias precedence selects the first present value per row. + raw_values = np.where(selected_mask, candidate_values, raw_values) + value_mask = np.logical_or(value_mask, candidate_mask) + row_indices = np.flatnonzero(value_mask) + yield feature_name, self._project_feature_indexes( + table, + query, + row_indices, + raw_values[row_indices], + projections, + query_object_names_by_result, + index_type, + object_labels_by_row, + ) + + def non_absent_feature_value_indexes( + self, + table: MeasurementTable, + queries: Mapping[str, "MeasurementFeatureQuery"], + query_object_names_by_feature: Mapping[str, Mapping[str | None, str | None]], + *, + index_type: type["MeasurementFeatureValueIndex"], + row_masks: Mapping[int | None, Any | None] | None = None, + ) -> Iterator[ + tuple[str, dict[int | None, dict[str | None, "MeasurementFeatureValueIndex"]]] + ]: + """Index the literal grammar's physical cells, including present NaNs. + + This declaration-owned operation has no opaque qualification callback. + Whole columns previously admitted by a caller remain authoritative; + otherwise physical segments are captured for each current feature query. + """ + if self.feature_name_values is not None: + yield from self.feature_value_indexes( + table, + queries, + query_object_names_by_feature, + index_type=index_type, + row_masks=row_masks, + measurement_value_qualifier=lambda value: not MeasurementScalarLiteral( + value + ).is_absent, + ) + return + projections = {None: None} if row_masks is None else row_masks + columns_by_token: dict[str, list[str]] = {} + for column, token in self.normalized_columns.items(): + columns_by_token.setdefault(token, []).append(column) + for feature_name, query in queries.items(): + query_object_names = query_object_names_by_feature[feature_name] + if not query.table_source_matches_feature(table): + yield feature_name, { + axis: {name: index_type() for name in query_object_names} + for axis in projections + } + continue + feature_columns = tuple( + dict.fromkeys( + column + for candidate in query.field_candidates + for column in columns_by_token.get(candidate, ()) + ) + ) + if not feature_columns: + yield feature_name, {axis: {} for axis in projections} + continue + position_batches, value_batches = [], [] + for column in feature_columns: + for offset, segment in table.rows.column_value_segments(column): + snapshot = np.array( + segment, + copy=True, + dtype=None if isinstance(segment, np.ndarray) else object, + ) + selected = np.flatnonzero( + MeasurementScalarLiteral.non_absent_values(snapshot) + ) + position_batches.append(offset + selected) + value_batches.append(np.asarray(snapshot[selected], dtype=object)) + if position_batches: + positions, first_alias = np.unique( + np.concatenate(position_batches), return_index=True + ) + values = np.concatenate(value_batches)[first_alias] + else: + positions = np.empty(0, dtype=np.intp) + values = np.empty(0, dtype=object) + yield feature_name, self._project_feature_indexes( + table, + query, + positions, + values, + projections, + query_object_names, + index_type, + {}, + ) + + def _project_feature_indexes( + self, + table: MeasurementTable, + query: "MeasurementFeatureQuery", + row_indices: Any, + values: Any, + projections: Mapping[int | None, Any | None], + query_object_names: Mapping[str | None, str | None], + index_type: type["MeasurementFeatureValueIndex"], + object_labels_by_row: dict[int, int | None], + ) -> dict[int | None, dict[str | None, "MeasurementFeatureValueIndex"]]: + source_mask = self.source_mask(query.source_candidates) + feature_mask = self.feature_mask(query.field_candidates) + mask = np.ones(len(row_indices), dtype=bool) + if source_mask is not None: + mask &= source_mask[row_indices] + if feature_mask is not None: + mask &= feature_mask[row_indices] + row_indices, values = row_indices[mask], values[mask] + object_id_field = self.object_id_field(table.subject.object_id_field) + object_ids = ( + None + if object_id_field is None + else columnar_row_values(table.rows, object_id_field) + ) + by_axis = {} + for axis, row_mask in projections.items(): + projected_mask = ( + np.ones(len(row_indices), dtype=bool) + if row_mask is None + else row_mask[row_indices] + ) + indexes = {} + for result_name, object_name in query_object_names.items(): + object_mask = None + if object_name is not None: + if table.subject.object_name not in (None, object_name): + continue + if table.subject.object_name is None: + if self.object_name_values is None: + continue + object_mask = self.object_mask(object_name) + effective_mask = ( + projected_mask + if object_mask is None + else np.logical_and(projected_mask, object_mask[row_indices]) + ) + object_values = values[effective_mask].astype(float, copy=False) + if object_ids is None: + indexes[result_name] = index_type( + {}, [float(value) for value in object_values] + ) + continue + values_by_label = {} + for row_index, value in zip( + row_indices[effective_mask], object_values, strict=True + ): + if row_index not in object_labels_by_row: + object_labels_by_row[row_index] = measurement_object_label_value( + object_ids[row_index] + ) + object_label = object_labels_by_row[row_index] + if object_label is not None: + values_by_label[object_label] = float(value) + indexes[result_name] = index_type(values_by_label, []) + by_axis[axis] = indexes + return by_axis + def matching_feature_column(self, query: "MeasurementFeatureQuery") -> str | None: """Return the column matching a measurement feature query.""" if self.feature_name_values is not None: @@ -420,12 +688,6 @@ def object_id_field(self, declared_object_id_field: str | None) -> str | None: ) -class ColumnarMeasurementTableSchemaCache(IdentityBoundProcessCache): - """Process-local semantic cache keyed by a columnar row object identity.""" - - registry_key = "columnar_measurement_table_schema" - - @dataclass(frozen=True, slots=True) class MeasurementFeatureQuery: """Query for measurement rows carrying one semantic feature value.""" @@ -526,8 +788,8 @@ def table_summaries( """Return compact diagnostics for tables searched by this query.""" summaries: list[str] = [] for table in measurement_tables: - semantics = MeasurementTableObjectFeatureSemantics.from_table(table) - features = tuple(sorted(semantics.feature_names)) + semantics = ColumnarMeasurementTableSchema.from_table(table) + features = tuple(sorted(semantics.feature_names(table))) feature_column = None row_count = "unknown" object_match_count = "unknown" @@ -553,7 +815,7 @@ def table_summaries( summaries.append( f"{table.name}/object={_diagnostic_value(table.subject.object_name)}/" f"source={_diagnostic_value(table.source_image_name)}/" - f"rows={type(table.rows).__name__}/objects={semantics.object_names[:8]}/" + f"rows={type(table.rows).__name__}/objects={semantics.object_names(table)[:8]}/" f"feature_column={_diagnostic_value(feature_column)}/" f"row_count={row_count}/object_matches={object_match_count}/" f"axes={axis_values}/feature_count={len(features)}/features={features[:8]}" @@ -584,22 +846,22 @@ def values_for_domain( def table_may_carry_feature( self, table: MeasurementTable, - semantics: "MeasurementTableObjectFeatureSemantics | None" = None, + schema: "ColumnarMeasurementTableSchema | None" = None, ) -> bool: """Return whether table ownership and feature schema can satisfy this query.""" if not self.table_source_matches_feature(table): return False table_semantics = ( - MeasurementTableObjectFeatureSemantics.from_table(table) - if semantics is None - else semantics + ColumnarMeasurementTableSchema.from_table(table) + if schema is None + else schema ) - if not table_semantics.feature_names: + if not table_semantics.feature_names(table): return True candidates = frozenset(self.field_candidates) return any( normalize_measurement_token(feature_name) in candidates - for feature_name in table_semantics.feature_names + for feature_name in table_semantics.feature_names(table) ) def table_source_matches_feature(self, table: MeasurementTable) -> bool: @@ -669,61 +931,26 @@ def value_indexes( self, measurement_tables_by_object: MeasurementTablesByObject, ) -> MeasurementValueIndexesByObject: - """Return value indexes keyed by object name for this feature.""" + """Return current object-feature indexes from one correlated table pass.""" object_names = self.normalized_object_names - cache_object_names = self.cache_object_names(measurement_tables_by_object) - cached_indexes = self.cached_matching_value_indexes( - measurement_tables_by_object, - ) - if cached_indexes is not None: - if all(object_name in cached_indexes for object_name in object_names): - return { - object_name: cached_indexes[object_name] - for object_name in object_names - } - indexes_by_object = dict(cached_indexes) - else: - indexes_by_object = {} - missing_cache_object_names = tuple( - object_name - for object_name in cache_object_names - if object_name not in indexes_by_object - ) - lookup = resolve_runtime_measurement_lookup_dialect( self.dialect ).feature_lookup(self.feature_name) query_objects_by_requested_object = { object_name: lookup.query_object_name(object_name) - for object_name in cache_object_names - } - pending_indexes_by_object = { - object_name: MeasurementFeatureValueIndex() - for object_name in missing_cache_object_names + for object_name in object_names } - objects_by_table_id: dict[int, list[str]] = {} - tables_by_id: dict[int, MeasurementTable] = {} - for table in self.feature_measurement_tables(measurement_tables_by_object): - table_id = id(table) - tables_by_id[table_id] = table - objects_by_table_id[table_id] = list( - object_name - for object_name in self.table_cache_object_names( - table, - object_names, - ) - if object_name in missing_cache_object_names - ) - + indexes_by_object = self.empty_indexes(object_names) table_query = MeasurementFeatureQuery( self.feature_name, dialect=self.dialect, ) - for table_id, table in tables_by_id.items(): - table_object_names = tuple(dict.fromkeys(objects_by_table_id[table_id])) + for table in self.feature_measurement_tables(measurement_tables_by_object): + table_object_names = self.table_object_names(table, object_names) if not table_object_names: continue - columnar_indexes = ( + self.merge_indexes( + indexes_by_object, MeasurementFeatureValueIndex.from_columnar_table_by_object( table, table_query, @@ -731,34 +958,21 @@ def value_indexes( object_name: query_objects_by_requested_object[object_name] for object_name in table_object_names }, - ) + ), ) - for object_name, object_index in columnar_indexes.items(): - pending_indexes_by_object[object_name] = pending_indexes_by_object[ - object_name - ].merged(object_index) - - indexes_by_object.update( - { - object_name: object_index.as_query_result() - for object_name, object_index in pending_indexes_by_object.items() - if object_index.present - } - ) + resolved = { + object_name: object_index.as_query_result() + for object_name, object_index in indexes_by_object.items() + if object_index.present + } missing_object_names = tuple( - object_name - for object_name in object_names - if object_name not in indexes_by_object + object_name for object_name in object_names if object_name not in resolved ) if missing_object_names: - diagnostic_query = MeasurementFeatureQuery( - self.feature_name, - dialect=self.dialect, - ) table_summaries = tuple( f"{object_name}:" + ";".join( - diagnostic_query.table_summaries( + table_query.table_summaries( measurement_tables_by_object[object_name] ) ) @@ -768,107 +982,64 @@ def value_indexes( f"Could not resolve measurement feature {self.feature_name!r} " f"for object(s) {missing_object_names!r}; tables={table_summaries!r}." ) - resolved = { - object_name: indexes_by_object[object_name] - for object_name in cache_object_names - if object_name in indexes_by_object - } - self.cache_value_indexes(measurement_tables_by_object, resolved) - return {object_name: resolved[object_name] for object_name in object_names} + return resolved def value_indexes_by_axis( self, measurement_tables_by_object: MeasurementTablesByObject, row_axis: MeasurementRowAxisField, ) -> dict[int, MeasurementValueIndexesByObject] | None: - """Return object-keyed feature indexes grouped by one declared row axis.""" - required_axis_values = self.required_axis_values( - measurement_tables_by_object, - row_axis, - ) - if not required_axis_values: - return None - cached_axis_indexes = self.cached_matching_axis_value_indexes( - measurement_tables_by_object, - row_axis, - ) + """Return current feature indexes preserving complete object/axis rows.""" object_names = self.normalized_object_names - cache_object_names = self.cache_object_names(measurement_tables_by_object) - if cached_axis_indexes is not None: - requested = self.requested_axis_value_indexes(cached_axis_indexes) - if self.requested_axis_indexes_present( - requested, - required_axis_values=required_axis_values, - ): - return requested - cached_object_names = frozenset( - object_name - for object_name in cache_object_names - if self.axis_indexes_contain_object( - cached_axis_indexes, - object_name, - required_axis_values=required_axis_values, - ) - ) - else: - cached_axis_indexes = {} - cached_object_names = frozenset() - missing_cache_object_names = tuple( - object_name - for object_name in cache_object_names - if object_name not in cached_object_names - ) - if not missing_cache_object_names: - return self.requested_axis_value_indexes(cached_axis_indexes) - lookup = resolve_runtime_measurement_lookup_dialect( self.dialect ).feature_lookup(self.feature_name) query_objects_by_requested_object = { object_name: lookup.query_object_name(object_name) - for object_name in cache_object_names + for object_name in object_names } table_query = MeasurementFeatureQuery( self.feature_name, dialect=self.dialect, ) by_axis: dict[int, dict[str, MeasurementFeatureValueIndex]] = {} - + has_row_axis = False for table in self.feature_measurement_tables(measurement_tables_by_object): - table_object_names = tuple( - object_name - for object_name in dict.fromkeys( - self.table_cache_object_names(table, object_names) - ) - if object_name in missing_cache_object_names - ) - if not table_object_names: - continue axis_values = self.table_axis_values(table, row_axis) if not axis_values: continue - for axis_value in axis_values: - target = by_axis.setdefault( - axis_value, - self.empty_indexes(missing_cache_object_names), + has_row_axis = True + table_object_names = self.table_object_names(table, object_names) + if not table_object_names: + continue + axis_column = columnar_row_values(table.rows, row_axis.value) + _feature_name, table_indexes = next( + ColumnarMeasurementTableSchema.from_table(table).feature_value_indexes( + table, + {table_query.feature_name: table_query}, + { + table_query.feature_name: { + object_name: query_objects_by_requested_object[object_name] + for object_name in table_object_names + } + }, + index_type=MeasurementFeatureValueIndex, + row_masks={ + axis_value: MeasurementAxisValueProjection( + row_axis, axis_value + ).mask(axis_column) + for axis_value in axis_values + }, ) - self.merge_indexes( - target, - self.table_value_indexes( - table, - table_query, - table_object_names, - query_objects_by_requested_object, - projection=MeasurementAxisValueProjection( - row_axis, - axis_value, - ), - ), + ) + for axis_value, indexes in table_indexes.items(): + target = by_axis.setdefault( + axis_value, self.empty_indexes(object_names) ) - - if not by_axis: - return self.requested_axis_value_indexes(cached_axis_indexes) - resolved = { + self.merge_indexes(target, indexes) + if not has_row_axis: + return None + return { axis_value: { object_name: object_index.as_query_result() for object_name, object_index in indexes.items() @@ -876,18 +1047,6 @@ def value_indexes_by_axis( } for axis_value, indexes in by_axis.items() } - merged_resolved = { - axis_value: dict(object_indexes) - for axis_value, object_indexes in cached_axis_indexes.items() - } - for axis_value, object_indexes in resolved.items(): - merged_resolved.setdefault(axis_value, {}).update(object_indexes) - self.cache_axis_value_indexes( - measurement_tables_by_object, - row_axis, - merged_resolved, - ) - return self.requested_axis_value_indexes(merged_resolved) @staticmethod def empty_indexes( @@ -898,13 +1057,6 @@ def empty_indexes( object_name: MeasurementFeatureValueIndex() for object_name in object_names } - @staticmethod - def indexes_present( - indexes: Mapping[str, "MeasurementFeatureValueIndex"], - ) -> bool: - """Return whether any object index carries values.""" - return any(index.present for index in indexes.values()) - @staticmethod def merge_indexes( target: dict[str, "MeasurementFeatureValueIndex"], @@ -916,53 +1068,6 @@ def merge_indexes( target[object_name] = MeasurementFeatureValueIndex() target[object_name] = target[object_name].merged(object_index) - def table_value_indexes( - self, - table: MeasurementTable, - table_query: MeasurementFeatureQuery, - table_object_names: tuple[str, ...], - query_objects_by_requested_object: Mapping[str, str | None], - *, - projection: MeasurementAxisValueProjection | None = None, - ) -> dict[str, "MeasurementFeatureValueIndex"]: - """Return object indexes for one table, optionally narrowed by row axis.""" - return self.columnar_table_value_indexes( - table, - table_query, - table_object_names, - query_objects_by_requested_object, - projection=projection, - ) - - def columnar_table_value_indexes( - self, - table: MeasurementTable, - table_query: MeasurementFeatureQuery, - table_object_names: tuple[str, ...], - query_objects_by_requested_object: Mapping[str, str | None], - *, - projection: MeasurementAxisValueProjection | None = None, - ) -> dict[str, "MeasurementFeatureValueIndex"]: - """Return object indexes for one columnar table and optional axis projection.""" - rows = table.rows - row_mask = None - if projection is not None: - column_names = tuple(str(column) for column in rows.columns) - if projection.field_name in column_names: - row_mask = projection.mask( - columnar_row_values(rows, projection.field_name) - ) - columnar_indexes = MeasurementFeatureValueIndex.from_columnar_table_by_object( - table, - table_query, - { - object_name: query_objects_by_requested_object[object_name] - for object_name in table_object_names - }, - row_mask=row_mask, - ) - return columnar_indexes - @staticmethod def table_axis_values( table: MeasurementTable, @@ -978,48 +1083,23 @@ def table_axis_values( row_axis, ) - def cache_object_names( - self, - measurement_tables_by_object: MeasurementTablesByObject, - ) -> tuple[str, ...]: - """Return object domains worth indexing for this feature/table set.""" - return tuple( - dict.fromkeys( - ( - *self.normalized_object_names, - *( - object_name - for table in self.feature_measurement_tables( - measurement_tables_by_object - ) - for object_name in self.table_cache_object_names( - table, - self.normalized_object_names, - ) - ), - ) - ) - ) - - def table_cache_object_names( + def table_object_names( self, table: MeasurementTable, - fallback_object_names: tuple[str, ...], + requested_object_names: tuple[str, ...], ) -> tuple[str, ...]: - """Return result object domains represented by one table scan.""" - semantics = MeasurementTableObjectFeatureSemantics.from_table(table) - if not semantics.object_names: - return fallback_object_names + """Return requested object domains represented by this table epoch.""" + semantics = ColumnarMeasurementTableSchema.from_table(table) + if not semantics.object_names(table): + return requested_object_names feature_lookup = resolve_runtime_measurement_lookup_dialect( self.dialect ).feature_lookup(self.feature_name) - unconstrained_result_names = tuple( - object_name - for object_name in fallback_object_names - if feature_lookup.query_object_name(object_name) is None - ) return tuple( - dict.fromkeys((*semantics.object_names, *unconstrained_result_names)) + object_name + for object_name in requested_object_names + if object_name in semantics.object_names(table) + or feature_lookup.query_object_name(object_name) is None ) def unique_measurement_tables( @@ -1053,231 +1133,6 @@ def feature_measurement_tables( if query.table_may_carry_feature(table) ) - def cache_key( - self, - measurement_tables_by_object: MeasurementTablesByObject, - ) -> MeasurementObjectFeatureVectorBatchCacheKey: - """Return the process-local identity key for this feature/table batch.""" - return MeasurementObjectFeatureVectorBatchCacheKey( - feature_name=self.feature_name, - dialect_identity=id( - resolve_runtime_measurement_lookup_dialect(self.dialect) - ), - table_identities=tuple( - id(table) - for table in self.feature_measurement_tables( - measurement_tables_by_object - ) - ), - ) - - def axis_cache_key( - self, - measurement_tables_by_object: MeasurementTablesByObject, - row_axis: MeasurementRowAxisField, - ) -> MeasurementObjectFeatureAxisBatchCacheKey: - """Return the process-local identity key for this feature/table/axis batch.""" - return MeasurementObjectFeatureAxisBatchCacheKey( - feature_name=self.feature_name, - dialect_identity=id( - resolve_runtime_measurement_lookup_dialect(self.dialect) - ), - row_axis=row_axis, - table_identities=tuple( - id(table) - for table in self.feature_measurement_tables( - measurement_tables_by_object - ) - ), - ) - - def table_owners( - self, - measurement_tables_by_object: MeasurementTablesByObject, - ) -> tuple[MeasurementTable, ...]: - """Return table owners used to protect identity-keyed cache entries.""" - return self.feature_measurement_tables(measurement_tables_by_object) - - def cached_value_indexes( - self, - measurement_tables_by_object: MeasurementTablesByObject, - ) -> MeasurementValueIndexesByObject | None: - """Return cached value indexes when table identities still match.""" - cached_indexes = self.cached_matching_value_indexes( - measurement_tables_by_object, - ) - if cached_indexes is None: - return None - if not all( - object_name in cached_indexes - for object_name in self.normalized_object_names - ): - return None - return { - object_name: cached_indexes[object_name] - for object_name in self.normalized_object_names - } - - def cached_matching_value_indexes( - self, - measurement_tables_by_object: MeasurementTablesByObject, - ) -> MeasurementValueIndexesByObject | None: - """Return every cached object index for this feature/table identity.""" - cache = MeasurementObjectFeatureVectorBatchQueryCache.process_cache() - cached = cache.cached_value(self.cache_key(measurement_tables_by_object)) - if cached is None: - return None - cached_owners, cached_indexes = cached - if not identity_owner_tuples_match( - cached_owners, - self.table_owners(measurement_tables_by_object), - ): - return None - return cached_indexes - - def cached_axis_value_indexes( - self, - measurement_tables_by_object: MeasurementTablesByObject, - row_axis: MeasurementRowAxisField, - ) -> dict[int, MeasurementValueIndexesByObject] | None: - """Return cached row-axis indexes when table identities still match.""" - cached_indexes = self.cached_matching_axis_value_indexes( - measurement_tables_by_object, - row_axis, - ) - if cached_indexes is None: - return None - requested = self.requested_axis_value_indexes(cached_indexes) - if not self.requested_axis_indexes_present( - requested, - required_axis_values=self.required_axis_values( - measurement_tables_by_object, - row_axis, - ), - ): - return None - return requested - - def cached_matching_axis_value_indexes( - self, - measurement_tables_by_object: MeasurementTablesByObject, - row_axis: MeasurementRowAxisField, - ) -> Mapping[int, MeasurementValueIndexesByObject] | None: - """Return every cached row-axis index for this feature/table identity.""" - cache = MeasurementObjectFeatureAxisBatchQueryCache.process_cache() - cached = cache.cached_value( - self.axis_cache_key(measurement_tables_by_object, row_axis) - ) - if cached is None: - return None - cached_owners, cached_indexes = cached - if not identity_owner_tuples_match( - cached_owners, - self.table_owners(measurement_tables_by_object), - ): - return None - return cached_indexes - - def requested_axis_value_indexes( - self, - indexes_by_axis: Mapping[int, MeasurementValueIndexesByObject], - ) -> dict[int, MeasurementValueIndexesByObject]: - """Project cached row-axis indexes to requested object names.""" - object_names = self.normalized_object_names - return { - axis_value: { - object_name: object_indexes[object_name] - for object_name in object_names - if object_name in object_indexes - } - for axis_value, object_indexes in indexes_by_axis.items() - } - - def requested_axis_indexes_present( - self, - indexes_by_axis: Mapping[int, MeasurementValueIndexesByObject], - *, - required_axis_values: tuple[int, ...], - ) -> bool: - """Return whether cached axis indexes satisfy every requested object.""" - return all( - self.axis_indexes_contain_object( - indexes_by_axis, - object_name, - required_axis_values=required_axis_values, - ) - for object_name in self.normalized_object_names - ) - - @staticmethod - def axis_indexes_contain_object( - indexes_by_axis: Mapping[int, MeasurementValueIndexesByObject], - object_name: str, - *, - required_axis_values: tuple[int, ...], - ) -> bool: - """Return whether one object has complete cached indexes for an axis scope.""" - return bool(required_axis_values) and all( - object_name in indexes_by_axis.get(axis_value, {}) - for axis_value in required_axis_values - ) - - def required_axis_values( - self, - measurement_tables_by_object: MeasurementTablesByObject, - row_axis: MeasurementRowAxisField, - ) -> tuple[int, ...]: - """Return declared row-axis values that must be represented in the cache.""" - values: set[int] = set() - for table in self.feature_measurement_tables(measurement_tables_by_object): - values.update(self.table_axis_values(table, row_axis)) - return tuple(sorted(values)) - - def cache_value_indexes( - self, - measurement_tables_by_object: MeasurementTablesByObject, - value_indexes: MeasurementValueIndexesByObject, - ) -> None: - """Store value indexes with table-owner references for id-reuse safety.""" - MeasurementObjectFeatureVectorBatchQueryCache.process_cache().store_value( - self.cache_key(measurement_tables_by_object), - (self.table_owners(measurement_tables_by_object), value_indexes), - ) - - def cache_axis_value_indexes( - self, - measurement_tables_by_object: MeasurementTablesByObject, - row_axis: MeasurementRowAxisField, - value_indexes: Mapping[int, MeasurementValueIndexesByObject], - ) -> None: - """Store row-axis value indexes with table-owner id-reuse protection.""" - MeasurementObjectFeatureAxisBatchQueryCache.process_cache().store_value( - self.axis_cache_key(measurement_tables_by_object, row_axis), - (self.table_owners(measurement_tables_by_object), value_indexes), - ) - - -class MeasurementObjectFeatureVectorBatchQueryCache( - RegisteredProcessLocalBoundedCache[ - MeasurementObjectFeatureVectorBatchCacheKey, - MeasurementObjectFeatureVectorBatchCacheValue, - ] -): - """Process-local cache for repeated object-feature table batch indexes.""" - - max_entries = 1024 - - -class MeasurementObjectFeatureAxisBatchQueryCache( - RegisteredProcessLocalBoundedCache[ - MeasurementObjectFeatureAxisBatchCacheKey, - MeasurementObjectFeatureAxisBatchCacheValue, - ] -): - """Process-local cache for repeated object-feature row-axis table indexes.""" - - max_entries = 1024 - @dataclass(frozen=True, slots=True) class MeasurementFeatureValueIndex: @@ -1333,114 +1188,20 @@ def from_columnar_table_by_object( row_mask: Any | None = None, measurement_value_qualifier: Callable[[object], bool] | None = None, ) -> dict[str | None, "MeasurementFeatureValueIndex"] | None: - """Return feature indexes from one columnar table scan.""" - rows = table.rows - + """Return one feature through the shared table batch projection.""" if not query.table_source_matches_feature(table): - return { - result_object_name: cls() - for result_object_name in query_object_names_by_result - } - - schema = ColumnarMeasurementTableSchema.from_table(table) - if schema.feature_name_values is None: - feature_columns = matching_measurement_fields( - schema.normalized_columns, - query.field_candidates, + return {result_name: cls() for result_name in query_object_names_by_result} + _feature_name, by_axis = next( + ColumnarMeasurementTableSchema.from_table(table).feature_value_indexes( + table, + {query.feature_name: query}, + {query.feature_name: query_object_names_by_result}, + index_type=cls, + row_masks={None: row_mask}, + measurement_value_qualifier=measurement_value_qualifier, ) - else: - feature_column = schema.matching_feature_column(query) - feature_columns = () if feature_column is None else (feature_column,) - if not feature_columns: - return {} - - raw_values = np.full(rows.row_count(), None, dtype=object) - value_mask = np.zeros(rows.row_count(), dtype=bool) - for feature_column in feature_columns: - candidate_values = np.asarray( - columnar_row_values(rows, feature_column), - dtype=object, - ) - candidate_mask = np.asarray( - [ - not _is_structural_missing_measurement_cell(value) - and ( - bool(measurement_value_qualifier(value)) - if measurement_value_qualifier is not None - else MeasurementScalarLiteral( - value - ).is_present_measurement_value - ) - for value in candidate_values - ], - dtype=bool, - ) - selected_mask = np.logical_and(np.logical_not(value_mask), candidate_mask) - raw_values[selected_mask] = candidate_values[selected_mask] - value_mask = np.logical_or(value_mask, candidate_mask) - source_mask = schema.source_mask(query.source_candidates) - feature_mask = schema.feature_mask(query.field_candidates) - source_feature_mask = ( - value_mask - if source_mask is None - else np.logical_and(value_mask, source_mask) - ) - base_mask = ( - source_feature_mask - if feature_mask is None - else np.logical_and(source_feature_mask, feature_mask) ) - if row_mask is not None: - base_mask = np.logical_and(base_mask, row_mask) - object_id_field = schema.object_id_field(table.subject.object_id_field) - object_ids = ( - None - if object_id_field is None or object_id_field not in schema.columns - else np.asarray(columnar_row_values(rows, object_id_field), dtype=object) - ) - table_object_name = table.subject.object_name - indexes: dict[str | None, MeasurementFeatureValueIndex] = {} - for ( - result_object_name, - query_object_name, - ) in query_object_names_by_result.items(): - object_mask: Any | None = None - if query_object_name is not None: - if table_object_name not in (None, query_object_name): - continue - if table_object_name is None: - if schema.object_name_values is None: - continue - object_mask = schema.object_mask(query_object_name) - - effective_mask = ( - base_mask - if object_mask is None - else np.logical_and(base_mask, object_mask) - ) - object_values = raw_values[effective_mask].astype(float, copy=False) - if object_id_field is None or object_ids is None: - indexes[result_object_name] = cls( - {}, - [float(value) for value in object_values], - ) - continue - indexes[result_object_name] = cls( - { - object_label: float(value) - for raw_object_id, value in zip( - object_ids[effective_mask], - object_values, - strict=True, - ) - for object_label in ( - MeasurementObjectLabelResolution(raw_object_id).object_label, - ) - if object_label is not None - }, - [], - ) - return indexes + return by_axis[None] @classmethod def from_rows( @@ -1511,60 +1272,6 @@ def as_query_result(self) -> MeasurementValueIndexResult: return self.values_by_label, self.positional_values -class MeasurementTableObjectFeatureSemanticsCache(IdentityBoundProcessCache): - """Bounded process-local cache for immutable measurement-table semantics.""" - - registry_key = "measurement_table_object_feature_semantics" - - -@dataclass(frozen=True, slots=True) -class MeasurementTableObjectFeatureSemantics: - """Object and feature declarations carried by one measurement table.""" - - object_names: tuple[str, ...] - feature_names: frozenset[str] - - @classmethod - def from_table( - cls, table: MeasurementTable - ) -> "MeasurementTableObjectFeatureSemantics": - cache = MeasurementTableObjectFeatureSemanticsCache.process_cache() - cached = cache.get_bound(table) - if cached is not None: - return cached - return cache.put_bound(table, cls.from_table_declarations(table)) - - @classmethod - def from_table_declarations( - cls, - table: MeasurementTable, - ) -> "MeasurementTableObjectFeatureSemantics": - """Return semantics from table-level schema when rows need not be scanned.""" - object_name = table.subject.object_name - schema = ColumnarMeasurementTableSchema.from_table(table) - return cls( - object_names=( - (object_name,) if object_name is not None else schema.object_names - ), - feature_names=schema.feature_names, - ) - - @staticmethod - def feature_names_from_names( - field_names: tuple[str, ...], - table: MeasurementTable, - ) -> frozenset[str]: - """Return wide-form feature names declared by measurement field names.""" - non_feature_fields = set(MeasurementRowAxisField.field_names()) - if table.subject.object_id_field is not None: - non_feature_fields.add(table.subject.object_id_field) - return frozenset( - field_name - for field_name in field_names - if field_name not in non_feature_fields - ) - - @dataclass(frozen=True, slots=True, kw_only=True) class MeasurementTableFeatureQuery(MeasurementFeatureQuery, ABC): """Feature query bound to a concrete measurement-table collection.""" diff --git a/openhcs/core/measurement_image_alignment.py b/openhcs/core/measurement_image_alignment.py index f8264e9d8e..010db0a305 100644 --- a/openhcs/core/measurement_image_alignment.py +++ b/openhcs/core/measurement_image_alignment.py @@ -265,237 +265,8 @@ def with_source_projected_labels(self) -> "MeasurementImageLabelAlignmentRequest label_payload=payload_projection, ) - -@dataclass(frozen=True, slots=True) -class PreparedMeasurementObjectLabels: - """Single-pass object-label preparation for measurement-image execution.""" - - request: MeasurementImageLabelAlignmentRequest - source_payload: ObjectLabelValue - source_projected_payload: ObjectLabelValue - source_projected_labels: ObjectLabelMeasurementSource - aligned_source: MeasurementImageAlignmentSource - measurement_labels: ObjectLabelMeasurementSource - completion_payload: ObjectLabelValue - - @property - def aligned_image(self) -> RuntimeArrayData | AlignedImageStack: - """Return the image from the source that owns its projected semantics.""" - - return self.aligned_source.alignment_image - - @classmethod - def from_source( - cls, - source: MeasurementImageAlignmentSource, - label_payload: ObjectLabelValue, - *, - plane_projector: RuntimePlaneAxisProjector | None = None, - align_image_to_labels: bool = True, - ) -> "PreparedMeasurementObjectLabels": - """Prepare labels from one measurement-image source and payload.""" - return cls.from_request( - request=source.object_label_alignment_request( - label_payload, - plane_projector=plane_projector, - align_image_to_labels=align_image_to_labels, - ), - ) - - @classmethod - def from_request( - cls, - request: MeasurementImageLabelAlignmentRequest, - ) -> "PreparedMeasurementObjectLabels": - """Prepare image, dense labels, and completion payload in one pass.""" - if request.label_payload is None: - raise TypeError( - "Measurement object-label preparation requires label_payload." - ) - profile_enabled = RuntimeProfileLogger.enabled() - source_payload = request.label_payload - source_projection_timer = RuntimeProfileTimer.start() - source_projected_request = request.with_source_projected_labels() - source_projected_labels = source_projected_request.labels - source_projection_payload = source_projected_request.label_payload - if source_projection_payload is None: - raise TypeError( - "Measurement object-label source projection lost label_payload." - ) - if profile_enabled: - RuntimeProfileLogger.log( - logger, - "measurement_object_labels_source_projection", - source_projection_timer.elapsed(), - reference_domain=request.reference_domain.value, - source_type=type(request.image).__name__, - labels_type=type(request.labels).__name__, - source_aliases=request.source_aliases, - ) - source_context_timer = RuntimeProfileTimer.start() - source_projected_payload = cls.source_context_payload( - source_projected_request, - source_projection_payload, - source_projected_labels, - ) - if profile_enabled: - RuntimeProfileLogger.log( - logger, - "measurement_object_labels_source_context", - source_context_timer.elapsed(), - reference_domain=request.reference_domain.value, - payload_reused=source_projected_payload is source_payload, - ) - image_request = replace( - source_projected_request, - labels=source_projected_labels, - label_payload=source_projected_payload, - ) - image_align_timer = RuntimeProfileTimer.start() - if request.align_image_to_labels: - aligned_image = MeasurementImageLabelAlignmentStrategy.align(image_request) - else: - aligned_image = request.image - aligned_source = image_request.source.with_alignment_image(aligned_image) - if profile_enabled: - RuntimeProfileLogger.log( - logger, - "measurement_object_labels_image_alignment", - image_align_timer.elapsed(), - reference_domain=request.reference_domain.value, - align_image_to_labels=request.align_image_to_labels, - aligned_type=type(aligned_image).__name__, - ) - label_align_timer = RuntimeProfileTimer.start() - aligned_measurement_labels = MeasurementLabelSourceAlignmentStrategy.align( - aligned_image, - source_projected_labels, - label_payload=source_projected_payload, - ) - measurement_labels = ( - object_label_dense_array(aligned_measurement_labels) - if isinstance(aligned_measurement_labels, ObjectLabelValue) - else aligned_measurement_labels - ) - if profile_enabled: - RuntimeProfileLogger.log( - logger, - "measurement_object_labels_label_alignment", - label_align_timer.elapsed(), - reference_domain=request.reference_domain.value, - labels_reused=aligned_measurement_labels is source_projected_labels, - ) - completion_timer = RuntimeProfileTimer.start() - completion_payload = source_projected_payload.with_measurement_labels( - measurement_labels - ) - if profile_enabled: - RuntimeProfileLogger.log( - logger, - "measurement_object_labels_completion_payload", - completion_timer.elapsed(), - reference_domain=request.reference_domain.value, - payload_reused=completion_payload is source_projected_payload, - ) - return cls( - request=request, - source_payload=source_payload, - source_projected_payload=source_projected_payload, - source_projected_labels=source_projected_labels, - aligned_source=aligned_source, - measurement_labels=measurement_labels, - completion_payload=completion_payload, - ) - @staticmethod - def source_context_payload( - request: MeasurementImageLabelAlignmentRequest, - source_payload: ObjectLabelValue, - source_projected_labels: ObjectLabelMeasurementSource, - ) -> ObjectLabelValue: - """Attach measurement-image source context to projected object labels.""" - source_variants = source_payload.variant_data - if isinstance(source_projected_labels, ObjectLabelValue): - variants = source_projected_labels.variant_data - elif source_projected_labels is request.labels: - variants = source_variants - else: - variants = ObjectLabelVariantData.compatible_replacement( - source_payload, - source_projected_labels, - ) - metadata = image_payload_metadata(request.image) - payload_domain = source_payload.object_label_source_spatial_domain() - source_spatial_domain = ( - metadata.object_label_source_spatial_domain() - .with_missing_from(payload_domain) - .with_fill_value(payload_domain.fill_value) - .with_value_name(payload_domain.value_name) - ) - if ( - variants.labels is source_variants.labels - and variants.unedited_labels is source_variants.unedited_labels - and variants.small_removed_labels is source_variants.small_removed_labels - and source_spatial_domain == payload_domain - ): - return source_payload - if ( - source_projected_labels is request.labels - and source_spatial_domain == payload_domain - ): - return source_payload.with_variants( - variants, - source_spatial_domain=source_spatial_domain, - ) - if source_spatial_domain != payload_domain: - contextual_payload = source_payload.with_variants( - variants, - source_spatial_domain=source_spatial_domain, - ) - image_source_domain = measurement_image_source_spatial_adapter( - request.image - ) - if image_source_domain is None: - raise ValueError( - "Measurement source-spatial projection requires an image source domain." - ) - contextual_source_domain = SourceSpatialDomainAdapter.for_value( - contextual_payload - ) - if contextual_source_domain is None: - raise TypeError( - "Measurement source-spatial projection requires an object-label " - "source domain adapter." - ) - variants = ObjectLabelVariantData.compatible_replacement( - contextual_payload, - image_source_domain.extract_source_array( - object_label_dense_array(contextual_payload), - spatial_axes_yx=contextual_source_domain.spatial_axes_yx, - ), - ) - return source_payload.with_variants( - variants, - representation=ObjectLabelRepresentation.DENSE_LABELS, - source_spatial_domain=source_spatial_domain, - ) - - -def measurement_image_source_spatial_adapter( - image: RuntimeArrayData | AlignedImageStack, -) -> SourceSpatialDomainAdapter | None: - """Return the nominal source-domain adapter for a measurement image.""" - if isinstance(image, AlignedImageStack): - return image.first_slice_source_spatial_adapter() - return SourceSpatialDomainAdapter.for_value(image) - - -class MeasurementLabelSourceAlignmentStrategy: - """Align labels through nominal image and source-spatial contracts.""" - - @classmethod - def align( - cls, + def labels_for_image( image: RuntimeArrayData | AlignedImageStack, labels: ObjectLabelMeasurementSource | RuntimeSliceAlignedValueSet, *, @@ -540,34 +311,29 @@ def align( return labels return label_domain_adapter.value_in_payload_domain(image_domain_adapter) - @classmethod - def align_request_labels_to_image_source( - cls, - request: MeasurementImageLabelAlignmentRequest, + def labels_in_image_source( + self, ) -> ObjectLabelMeasurementSource | RuntimeSliceAlignedValueSet: - """Return request labels projected into the request image source domain.""" - request = request.with_source_projected_labels() - return cls.align( + """Project labels into this request's declared image source domain.""" + request = self.with_source_projected_labels() + return self.labels_for_image( request.image, request.labels, label_payload=request.label_payload, ) + def aligned(self) -> "MeasurementImageLabelAlignmentRequest": + """Return projected image and labels from one coupled alignment pass.""" + return self.with_source_projected_labels()._with_aligned_source() -class MeasurementImageLabelAlignmentStrategy: - """Select measurement-image alignment from existing nominal contracts.""" - - @classmethod - def align( - cls, - request: MeasurementImageLabelAlignmentRequest, - ) -> RuntimeArrayData | AlignedImageStack: - request = request.with_source_projected_labels() + def _with_aligned_source(self) -> "MeasurementImageLabelAlignmentRequest": + """Align an already projected request without repeating label projection.""" + request = self if request.reference_domain is MeasurementImageReferenceDomain.SOURCE_IMAGE: request = request.with_source_projected_image() image = request.image elif request.reference_domain is MeasurementImageReferenceDomain.OBJECT_LABELS: - image = cls.object_label_reference_image(request) + image = request.object_label_reference_image() else: raise ValueError( "Measurement image alignment has no declared reference-domain behavior " @@ -589,7 +355,7 @@ def align( source_description="Payload-scoped object-label measurement image", ) aligned_labels = ( - MeasurementLabelSourceAlignmentStrategy.align( + self.labels_for_image( image, request.labels, label_payload=label_payload, @@ -597,19 +363,20 @@ def align( if request.reference_domain is MeasurementImageReferenceDomain.SOURCE_IMAGE else request.labels ) - cls.validate_alignment( + self.validate_alignment( image, aligned_labels, label_payload=label_payload, ) - return image + return replace( + request, + source=request.source.with_alignment_image(image), + labels=aligned_labels, + ) - @classmethod - def object_label_reference_image( - cls, - request: MeasurementImageLabelAlignmentRequest, - ) -> RuntimeArrayData | AlignedImageStack: + def object_label_reference_image(self) -> RuntimeArrayData | AlignedImageStack: """Return an image selected by declared object-label-domain semantics.""" + request = self label_payload = request.label_payload if label_payload is None: raise ValueError( @@ -758,6 +525,237 @@ def validate_dense_pair( ) +@dataclass(frozen=True, slots=True) +class PreparedMeasurementObjectLabels: + """Single-pass object-label preparation for measurement-image execution.""" + + request: MeasurementImageLabelAlignmentRequest + source_payload: ObjectLabelValue + source_projected_payload: ObjectLabelValue + source_projected_labels: ObjectLabelMeasurementSource + aligned_source: MeasurementImageAlignmentSource + measurement_labels: ObjectLabelMeasurementSource + completion_payload: ObjectLabelValue + + @property + def aligned_image(self) -> RuntimeArrayData | AlignedImageStack: + """Return the image from the source that owns its projected semantics.""" + + return self.aligned_source.alignment_image + + @classmethod + def from_source( + cls, + source: MeasurementImageAlignmentSource, + label_payload: ObjectLabelValue, + *, + plane_projector: RuntimePlaneAxisProjector | None = None, + align_image_to_labels: bool = True, + ) -> "PreparedMeasurementObjectLabels": + """Prepare labels from one measurement-image source and payload.""" + return cls.from_request( + request=source.object_label_alignment_request( + label_payload, + plane_projector=plane_projector, + align_image_to_labels=align_image_to_labels, + ), + ) + + @classmethod + def from_request( + cls, + request: MeasurementImageLabelAlignmentRequest, + ) -> "PreparedMeasurementObjectLabels": + """Prepare image, dense labels, and completion payload in one pass.""" + if request.label_payload is None: + raise TypeError( + "Measurement object-label preparation requires label_payload." + ) + profile_enabled = RuntimeProfileLogger.enabled() + source_payload = request.label_payload + source_projection_timer = RuntimeProfileTimer.start() + source_projected_request = request.with_source_projected_labels() + source_projected_labels = source_projected_request.labels + source_projection_payload = source_projected_request.label_payload + if source_projection_payload is None: + raise TypeError( + "Measurement object-label source projection lost label_payload." + ) + if profile_enabled: + RuntimeProfileLogger.log( + logger, + "measurement_object_labels_source_projection", + source_projection_timer.elapsed(), + reference_domain=request.reference_domain.value, + source_type=type(request.image).__name__, + labels_type=type(request.labels).__name__, + source_aliases=request.source_aliases, + ) + source_context_timer = RuntimeProfileTimer.start() + source_projected_payload = cls.source_context_payload( + source_projected_request, + source_projection_payload, + source_projected_labels, + ) + if profile_enabled: + RuntimeProfileLogger.log( + logger, + "measurement_object_labels_source_context", + source_context_timer.elapsed(), + reference_domain=request.reference_domain.value, + payload_reused=source_projected_payload is source_payload, + ) + image_request = replace( + source_projected_request, + labels=source_projected_labels, + label_payload=source_projected_payload, + ) + image_align_timer = RuntimeProfileTimer.start() + if request.align_image_to_labels: + aligned_request = image_request._with_aligned_source() + aligned_image = aligned_request.image + aligned_source = aligned_request.source + else: + aligned_image = request.image + aligned_source = image_request.source.with_alignment_image(aligned_image) + if profile_enabled: + RuntimeProfileLogger.log( + logger, + "measurement_object_labels_image_alignment", + image_align_timer.elapsed(), + reference_domain=request.reference_domain.value, + align_image_to_labels=request.align_image_to_labels, + aligned_type=type(aligned_image).__name__, + ) + label_align_timer = RuntimeProfileTimer.start() + aligned_measurement_labels = ( + aligned_request.labels + if request.align_image_to_labels + and request.reference_domain is MeasurementImageReferenceDomain.SOURCE_IMAGE + else image_request.labels_for_image( + aligned_image, + source_projected_labels, + label_payload=source_projected_payload, + ) + ) + measurement_labels = ( + object_label_dense_array(aligned_measurement_labels) + if isinstance(aligned_measurement_labels, ObjectLabelValue) + else aligned_measurement_labels + ) + if profile_enabled: + RuntimeProfileLogger.log( + logger, + "measurement_object_labels_label_alignment", + label_align_timer.elapsed(), + reference_domain=request.reference_domain.value, + labels_reused=aligned_measurement_labels is source_projected_labels, + ) + completion_timer = RuntimeProfileTimer.start() + completion_payload = source_projected_payload.with_measurement_labels( + measurement_labels + ) + if profile_enabled: + RuntimeProfileLogger.log( + logger, + "measurement_object_labels_completion_payload", + completion_timer.elapsed(), + reference_domain=request.reference_domain.value, + payload_reused=completion_payload is source_projected_payload, + ) + return cls( + request=request, + source_payload=source_payload, + source_projected_payload=source_projected_payload, + source_projected_labels=source_projected_labels, + aligned_source=aligned_source, + measurement_labels=measurement_labels, + completion_payload=completion_payload, + ) + + @staticmethod + def source_context_payload( + request: MeasurementImageLabelAlignmentRequest, + source_payload: ObjectLabelValue, + source_projected_labels: ObjectLabelMeasurementSource, + ) -> ObjectLabelValue: + """Attach measurement-image source context to projected object labels.""" + source_variants = source_payload.variant_data + if isinstance(source_projected_labels, ObjectLabelValue): + variants = source_projected_labels.variant_data + elif source_projected_labels is request.labels: + variants = source_variants + else: + variants = ObjectLabelVariantData.compatible_replacement( + source_payload, + source_projected_labels, + ) + metadata = image_payload_metadata(request.image) + payload_domain = source_payload.object_label_source_spatial_domain() + source_spatial_domain = ( + metadata.object_label_source_spatial_domain() + .with_missing_from(payload_domain) + .with_fill_value(payload_domain.fill_value) + .with_value_name(payload_domain.value_name) + ) + if ( + variants.labels is source_variants.labels + and variants.unedited_labels is source_variants.unedited_labels + and variants.small_removed_labels is source_variants.small_removed_labels + and source_spatial_domain == payload_domain + ): + return source_payload + if ( + source_projected_labels is request.labels + and source_spatial_domain == payload_domain + ): + return source_payload.with_variants( + variants, + source_spatial_domain=source_spatial_domain, + ) + if source_spatial_domain != payload_domain: + contextual_payload = source_payload.with_variants( + variants, + source_spatial_domain=source_spatial_domain, + ) + image_source_domain = measurement_image_source_spatial_adapter( + request.image + ) + if image_source_domain is None: + raise ValueError( + "Measurement source-spatial projection requires an image source domain." + ) + contextual_source_domain = SourceSpatialDomainAdapter.for_value( + contextual_payload + ) + if contextual_source_domain is None: + raise TypeError( + "Measurement source-spatial projection requires an object-label " + "source domain adapter." + ) + variants = ObjectLabelVariantData.compatible_replacement( + contextual_payload, + image_source_domain.extract_source_array( + object_label_dense_array(contextual_payload), + spatial_axes_yx=contextual_source_domain.spatial_axes_yx, + ), + ) + return source_payload.with_variants( + variants, + representation=ObjectLabelRepresentation.DENSE_LABELS, + source_spatial_domain=source_spatial_domain, + ) + + +def measurement_image_source_spatial_adapter( + image: RuntimeArrayData | AlignedImageStack, +) -> SourceSpatialDomainAdapter | None: + """Return the nominal source-domain adapter for a measurement image.""" + if isinstance(image, AlignedImageStack): + return image.first_slice_source_spatial_adapter() + return SourceSpatialDomainAdapter.for_value(image) + + class MeasurementImageReferenceDomain(str, Enum): """Semantic image domain used as the reference for object measurement.""" diff --git a/openhcs/core/measurement_row_materialization.py b/openhcs/core/measurement_row_materialization.py index ac6c9bf6fa..79c9980a83 100644 --- a/openhcs/core/measurement_row_materialization.py +++ b/openhcs/core/measurement_row_materialization.py @@ -14,8 +14,9 @@ from dataclasses import dataclass, field, fields as dataclass_fields, is_dataclass from dataclasses import replace as dataclass_replace from functools import lru_cache +from itertools import chain from types import MappingProxyType -from typing import Any, ClassVar, TypeAlias, cast +from typing import Any, ClassVar, TYPE_CHECKING, TypeAlias, cast from metaclass_registry import AutoRegisterMeta from openhcs.constants.constants import AllComponents @@ -52,8 +53,6 @@ from openhcs.core.source_matching import source_component_metadata_value from enum import Enum -from openhcs.core.registry_strategies import EnumKeyedStrategyMixin -from openhcs.core.runtime_measurements import ObjectMeasurementValueRow @lru_cache(maxsize=32768) @@ -143,6 +142,10 @@ def measurement_table_axis_values( } +if TYPE_CHECKING: + from openhcs.core.equivalence.policy import RuntimeMeasurementDialect + + ProjectedMeasurementRows: TypeAlias = Sequence[Mapping[str, Any]] | ColumnarRows MeasurementFeatureNameProjection: TypeAlias = Callable[ [str, tuple[tuple[str, object], ...]], @@ -510,6 +513,9 @@ def __getitem__(self, column_name: str) -> Sequence[Any]: return self.overlay_columns[column_name] return self.base_columns[column_name] + def __contains__(self, column_name: object) -> bool: + return column_name in self.column_names + def __iter__(self): return iter(self.column_names) @@ -789,6 +795,122 @@ def add( columns = { str(column): rows.column_values(str(column)) for column in rows.columns } + feature_columns = wide_measurement_feature_columns( + columns, + object_id_field=object_id_field, + qualifier_field_names=qualifier_field_names, + ) + self._add_columns( + columns, + row_count, + feature_columns, + project_feature_name, + default_subject=default_subject, + default_scope=default_scope, + source_image_name=source_image_name, + object_id_field=object_id_field, + qualifier_field_names=qualifier_field_names, + missing_cell=missing_cell, + ) + + def add_declared_rows( + self, + rows: ColumnarRows, + dialect: RuntimeMeasurementDialect, + *, + default_subject: str, + default_scope: MeasurementScope = MeasurementScope.ARTIFACT, + source_image_name: str | None = None, + object_id_field: str | None = None, + qualifier_field_names: Iterable[str] = (), + missing_cell: object = MEASUREMENT_SPARSE_CELL, + ) -> None: + """Admit correlated physical batches using a declared export grammar. + + Opaque callbacks retain add()'s complete, writable column admission. + Here snapshots are call-local and no sparse union arrays are retained. + """ + names = tuple(str(column) for column in rows.columns) + batches = tuple( + ( + count, + { + name: np.array( + values, + copy=True, + dtype=None if isinstance(values, np.ndarray) else object, + ) + for name, values in columns.items() + }, + ) + for count, columns in rows.columnar_row_batches() + ) + eligible = frozenset( + name + for name, _values in wide_measurement_feature_columns( + { + name: chain.from_iterable( + columns[name] for _count, columns in batches if name in columns + ) + for name in names + }, + object_id_field=object_id_field, + qualifier_field_names=qualifier_field_names, + ) + ) + structural_names = tuple(name for name in names if name not in eligible) + for count, source_columns in batches: + if not count: + continue + columns = { + name: source_columns[name] + for name in names + if name in source_columns + and ( + name not in eligible + or any( + not is_structural_missing_measurement_cell(value) + for value in source_columns[name] + ) + ) + } + for name in structural_names: + if name not in columns: + values = np.empty(count, dtype=object) + values.fill(MEASUREMENT_SPARSE_CELL) + columns[name] = values + columns = {name: columns[name] for name in names if name in columns} + self._add_columns( + columns, + count, + tuple( + (name, values) + for name, values in columns.items() + if name in eligible + ), + dialect.projected_feature_name, + default_subject=default_subject, + default_scope=default_scope, + source_image_name=source_image_name, + object_id_field=object_id_field, + qualifier_field_names=qualifier_field_names, + missing_cell=missing_cell, + ) + + def _add_columns( + self, + columns: Mapping[str, Sequence[object]], + row_count: int, + feature_columns: tuple[tuple[str, Sequence[object]], ...], + project_feature_name: MeasurementFeatureNameProjection, + *, + default_subject: str, + default_scope: MeasurementScope, + source_image_name: str | None, + object_id_field: str | None, + qualifier_field_names: Iterable[str], + missing_cell: object, + ) -> None: feature_fields = MeasurementRowAxisField.feature_name_field_names_ordered() value_fields = MeasurementRowValueField.field_names_ordered() qualifier_fields = tuple( @@ -816,11 +938,7 @@ def add( for field_name, values in columns.items() if normalize_runtime_identifier(field_name) in identity_field_names ) - feature_columns = wide_measurement_feature_columns( - columns, - object_id_field=object_id_field, - qualifier_field_names=qualifier_fields, - ) + source_values = columns.get(MeasurementRowAxisField.SOURCE_IMAGE_NAME.value) object_name_values = columns.get(MeasurementRowAxisField.OBJECT_NAME.value) object_id_columns = tuple( @@ -1573,17 +1691,6 @@ def measurement_row_source_image_name(row: Mapping[str, object]) -> str | None: return cast(str | None, MeasurementRowSourceImageName.value_from_row(row)) -@dataclass(frozen=True, slots=True) -class MeasurementObjectLabelResolution: - """Integer object label resolved from runtime/CSV scalar encodings.""" - - value: object - - @property - def object_label(self) -> int | None: - return measurement_object_label_value(self.value) - - def measurement_object_label_value(value: object) -> int | None: """Return the integer object label represented by one scalar value.""" if value is None: @@ -1926,6 +2033,9 @@ def __getitem__(self, column_name: str) -> Sequence[object]: self._column_cache[column_name] = values return values + def __contains__(self, column_name: object) -> bool: + return column_name in self.column_names + def __iter__(self): return iter(self.column_names) @@ -1956,6 +2066,55 @@ def __post_init__(self) -> None: def __len__(self) -> int: return sum(columnar_row_count(row_batch) for row_batch in self.row_batches) + def row_count(self) -> int: + return len(self) + + def column_value_segments( + self, column: str + ) -> Iterable[tuple[int, Sequence[object]]]: + if column not in self.columns: + raise KeyError(column) + cached = self.columns._column_cache.get(column) + if cached is not None: + yield 0, cached + return + offset = 0 + for row_batch in self.row_batches: + if column in row_batch.columns: + for local_offset, values in row_batch.column_value_segments(column): + yield offset + local_offset, values + offset += row_batch.row_count() + + def bounded_column_values(self, column: str, row_stop: int) -> Sequence[object]: + cached = self.columns._column_cache.get(column) + if cached is not None: + return cached[:row_stop] + values = np.empty(min(max(0, row_stop), self.row_count()), dtype=object) + values.fill(MEASUREMENT_SPARSE_CELL) + for offset, segment in self.column_value_segments(column): + if offset >= len(values): + break + count = min(len(segment), len(values) - offset) + values[offset : offset + count] = segment[:count] + return values + + def columnar_row_batches( + self, + ) -> Iterable[tuple[int, Mapping[str, Sequence[object]]]]: + offset = 0 + for row_batch in self.row_batches: + for count, columns in row_batch.columnar_row_batches(): + yield count, { + name: ( + self.columns._column_cache[name][offset : offset + count] + if name in self.columns._column_cache + else columns[name] + ) + for name in self.columns + if name in self.columns._column_cache or name in columns + } + offset += count + @property def covers_declared_object_measurement_domain(self) -> bool: """Return whether every concatenated batch covers its declared domain.""" @@ -2159,15 +2318,16 @@ def metadata_for_row(row_index: int): f"slice_index={slice_index}, but provenance declares " f"{source_provenance.source_plane_count} runtime plane(s)." ) - return source_provenance.for_source_plane(slice_index).source_component_metadata + return source_provenance.component_metadata_for_plane(slice_index) + metadata_by_row = tuple(metadata_for_row(index) for index in range(row_count)) for component in AllComponents: values = tuple( ( MEASUREMENT_SPARSE_CELL if ( value := source_component_metadata_value( - metadata_for_row(row_index) or {}, + metadata_by_row[row_index] or {}, component, ) ) @@ -2265,76 +2425,9 @@ def source_names_for_row(row_index: int) -> tuple[str, ...]: class MeasurementTableRowLayout(str, Enum): """Nominal row layout for measurement tables.""" - EMPTY = "empty" LONG = "long" WIDE = "wide" - @classmethod - def for_row(cls, row: object) -> "MeasurementTableRowLayout": - """Classify one row from its declared measurement fields.""" - field_names = frozenset( - str(field_name) for field_name in measurement_row_mapping(row) - ) - has_feature_field = bool( - field_names & MeasurementRowAxisField.feature_name_field_names() - ) - has_value_field = bool(field_names & MeasurementRowValueField.field_names()) - if has_feature_field and not has_value_field: - raise ValueError( - "Long-form measurement rows must declare both a feature field " - f"and a value field, got fields {sorted(field_names)!r}." - ) - return cls.LONG if has_feature_field else cls.WIDE - - -class MeasurementRowLayoutProjectionStrategy( - EnumKeyedStrategyMixin[MeasurementTableRowLayout], - ABC, - metaclass=AutoRegisterMeta, -): - """Project one nominal measurement row layout into canonical long form.""" - - __enum_member_attr__ = "layout" - layout: ClassVar[MeasurementTableRowLayout | None] = None - - @abstractmethod - def long_rows(self, row: object) -> tuple[Mapping[str, object], ...]: - """Return canonical long-form rows for one source row.""" - - -class LongMeasurementRowProjectionStrategy(MeasurementRowLayoutProjectionStrategy): - """Preserve already-long rows.""" - - layout = MeasurementTableRowLayout.LONG - - def long_rows(self, row: object) -> tuple[Mapping[str, object], ...]: - return (measurement_row_mapping(row),) - - -class WideMeasurementRowProjectionStrategy(MeasurementRowLayoutProjectionStrategy): - """Explode wide feature columns into canonical long-form rows.""" - - layout = MeasurementTableRowLayout.WIDE - - def long_rows(self, row: object) -> tuple[Mapping[str, object], ...]: - row_mapping = measurement_row_mapping(row) - axis_fields = MeasurementRowAxisField.field_names() - axis_values = { - str(field_name): value - for field_name, value in row_mapping.items() - if str(field_name) in axis_fields - } - long_rows: list[Mapping[str, object]] = [] - for field_name, value in row_mapping.items(): - field_text = str(field_name) - if field_text in axis_fields: - continue - long_row = dict(axis_values) - long_row[MeasurementRowAxisField.FEATURE_NAME.value] = field_text - long_row[MeasurementRowValueField.RESULT_VALUE.value] = value - long_rows.append(long_row) - return tuple(long_rows) - def measurement_row_semantic_field_names() -> frozenset[str]: """Return fields that identify a payload as a measurement row.""" @@ -2358,18 +2451,6 @@ def carries_measurement_row_semantics(row: object) -> bool: return bool(field_names & semantic_fields) -def measurement_table_row_layout(rows: object) -> MeasurementTableRowLayout: - """Return the declared layout implied by a table row payload.""" - observed_layouts = measurement_table_row_layouts(rows) - if not observed_layouts: - return MeasurementTableRowLayout.EMPTY - if len(observed_layouts) != 1: - raise ValueError( - f"MeasurementTable rows must not mix long-form and wide-form layouts; got {sorted((layout.value for layout in observed_layouts))!r}." - ) - return next(iter(observed_layouts)) - - def measurement_table_row_layout_from_fields( fields: Iterable[FieldSpec], ) -> MeasurementTableRowLayout | None: @@ -2400,48 +2481,3 @@ def _measurement_table_row_layout_from_field_names( if has_feature_field else MeasurementTableRowLayout.WIDE ) - - -def measurement_table_row_layouts(rows: object) -> frozenset[MeasurementTableRowLayout]: - """Return every nominal row layout observed in a measurement payload.""" - if rows is None: - return frozenset() - row_sequence = rows if isinstance(rows, list | tuple) else (rows,) - if not row_sequence: - return frozenset() - if isinstance(row_sequence[0], ObjectMeasurementValueRow) and all( - (isinstance(row, ObjectMeasurementValueRow) for row in row_sequence) - ): - return frozenset((MeasurementTableRowLayout.LONG,)) - return frozenset((MeasurementTableRowLayout.for_row(row) for row in row_sequence)) - - -def normalize_measurement_table_rows( - rows: object, *, fields: Iterable[FieldSpec] = () -) -> object: - """Return homogeneous measurement rows, canonicalizing mixed tables to long form.""" - declared_layout = measurement_table_row_layout_from_fields(fields) - if declared_layout is not None: - return rows - observed_layouts = measurement_table_row_layouts(rows) - if len(observed_layouts) <= 1: - return rows - return measurement_rows_as_layout(rows, MeasurementTableRowLayout.LONG) - - -def measurement_rows_as_layout( - rows: object, layout: MeasurementTableRowLayout -) -> object: - """Project measurement rows into a declared table layout.""" - if layout is not MeasurementTableRowLayout.LONG: - raise ValueError( - f"Unsupported measurement row layout projection: {layout.value}." - ) - row_sequence = rows if isinstance(rows, list | tuple) else (rows,) - return [ - projected_row - for row in row_sequence - for projected_row in MeasurementRowLayoutProjectionStrategy.for_enum_member( - MeasurementTableRowLayout.for_row(row) - ).long_rows(row) - ] diff --git a/openhcs/core/orchestrator/analysis_consolidation.py b/openhcs/core/orchestrator/analysis_consolidation.py index dbcc0f1d68..13a4b4949a 100644 --- a/openhcs/core/orchestrator/analysis_consolidation.py +++ b/openhcs/core/orchestrator/analysis_consolidation.py @@ -3,9 +3,8 @@ from __future__ import annotations import logging -from collections.abc import Mapping +from collections.abc import Iterable, Mapping from dataclasses import dataclass -from functools import partial from pathlib import Path from typing import TYPE_CHECKING @@ -18,11 +17,6 @@ ExecutionResult, RuntimeExecutionObservation, ) -from openhcs.core.runtime_stores import StoredRuntimeValue -from openhcs.core.steps.function_artifact_materialization import ( - RuntimeArtifactMaterialization, - runtime_artifact_materializations_from_records, -) from openhcs.processing.backends.analysis.consolidate_analysis_results import ( AnalysisSummaryWriter, RuntimeAnalysisTableOutput, @@ -35,6 +29,12 @@ if TYPE_CHECKING: from polystore.filemanager import FileManager + from openhcs.core.compiled_step_plan import CompiledStepPlan + from openhcs.core.steps.function_artifact_materialization import ( + MaterializedRuntimeArtifact, + RuntimeArtifactMaterialization, + ) + from openhcs.processing.materialization.core import Output @dataclass(frozen=True, slots=True) @@ -67,55 +67,109 @@ def outputs_by_directory( return {directory: group.outputs for directory, group in self.groups.items()} @classmethod - def from_records( + def from_saved_outputs( + cls, + context: ProcessingContext, + plan: CompiledStepPlan, + saved: MaterializedRuntimeArtifact, + ) -> RuntimeAnalysisConsolidationInputs | None: + """Project the writer's actual saved CSV content without rendering again.""" + if not plan.runtime_artifact_materialization.has_persistent_target: + return None + backend = plan.runtime_artifact_materialization.require_persistent_backend() + return cls._from_table_contents( + context, plan, saved.materialization, + ( + (Path(output.path), output.require_text_content()) + for output in saved.outputs_for_backend(backend) + if analysis_file_path_is_included( + Path(output.path), + analysis_consolidation_config=context.analysis_consolidation_config, + ) + ), + ) + + @classmethod + def from_reused_outputs( cls, context: ProcessingContext, - records: tuple[StoredRuntimeValue, ...], + plan: CompiledStepPlan, + materialization: RuntimeArtifactMaterialization, + outputs: tuple[Output, ...], ) -> RuntimeAnalysisConsolidationInputs | None: - """Render only execution-owned tables while their payloads are available.""" - if not context.analysis_consolidation_config.enabled: + """Read exact historical CSV text for explicitly reused debug outputs.""" + if not plan.runtime_artifact_materialization.has_persistent_target: return None + backend = plan.runtime_artifact_materialization.require_persistent_backend() + return cls._from_table_contents( + context, plan, materialization, + ( + (Path(output.path), context.filemanager.load_text(output.path, backend)) + for output in outputs + if analysis_file_path_is_included( + Path(output.path), + analysis_consolidation_config=context.analysis_consolidation_config, + ) + ), + ) + + @classmethod + def _from_table_contents( + cls, + context: ProcessingContext, + plan: CompiledStepPlan, + materialization: RuntimeArtifactMaterialization, + contents: Iterable[tuple[Path, str]], + ) -> RuntimeAnalysisConsolidationInputs | None: + """Bind table identity and destinations from this one materialization.""" + if ( + not materialization.spec.participates_in_runtime_export_observation() + or not context.analysis_consolidation_config.enabled + ): + return None + backend = plan.runtime_artifact_materialization.require_persistent_backend() + destination = RuntimeAnalysisSummaryDestination( + backend=backend, images_dir=plan.artifact_images_dir, + ) + output_groups: dict[ + tuple[Path, RuntimeAnalysisSummaryDestination], list[RuntimeAnalysisTableOutput] + ] = {} + for output_path, content in contents: + output_groups.setdefault((output_path.parent, destination), []).append( + runtime_analysis_table_output( + materialization, + output_path=output_path, + csv_content=content, + pipeline_position=plan.pipeline_position, + ) + ) + return cls._from_groups( + output_groups, + {RuntimeAnalysisSummaryDestination(backend, str(plan.output_dir))}, + ) + + @classmethod + def combine( + cls, + inputs: Iterable[RuntimeAnalysisConsolidationInputs | None], + ) -> RuntimeAnalysisConsolidationInputs | None: + """Combine actual rendered projections without revisiting their payloads.""" output_groups: dict[ tuple[Path, RuntimeAnalysisSummaryDestination], list[RuntimeAnalysisTableOutput] ] = {} destinations: set[RuntimeAnalysisSummaryDestination] = set() seen_paths: set[tuple[str, Path]] = set() - for step_plan in context.step_plans.values(): - if (not step_plan.owns_runtime_outputs - or not step_plan.runtime_artifact_materialization.has_persistent_target): + for item in inputs: + if item is None: continue - for materialization in runtime_artifact_materializations_from_records( - step_plan, context, records, - ): - if not materialization.spec.participates_in_runtime_export_observation(): - continue - backend = step_plan.runtime_artifact_materialization.require_persistent_backend() - destination = RuntimeAnalysisSummaryDestination( - backend=backend, images_dir=step_plan.artifact_images_dir, - ) - for output in materialization.outputs( - step_plan, - context, - output_path_filter=partial( - analysis_file_path_is_included, - analysis_consolidation_config=context.analysis_consolidation_config, - ), - ): - output_path = Path(output.path) - if (backend, output_path) in seen_paths: + destinations.add(item.destination) + for directory, group in item.groups.items(): + for output in group.outputs: + identity = (group.destination.backend, output.path) + if identity in seen_paths: continue - seen_paths.add((backend, output_path)) - destinations.add(RuntimeAnalysisSummaryDestination( - backend=backend, images_dir=str(step_plan.output_dir), - )) - output_groups.setdefault((output_path.parent, destination), []).append( - runtime_analysis_table_output( - materialization, - output_path=output_path, - csv_content=output.require_text_content(), - pipeline_position=step_plan.pipeline_position, - ) - ) + seen_paths.add(identity) + output_groups.setdefault((directory, group.destination), []).append(output) return cls._from_groups(output_groups, destinations) @classmethod @@ -124,12 +178,8 @@ def from_observations( compiled_contexts: Mapping[str, ProcessingContext], observations: tuple[RuntimeExecutionObservation, ...], ) -> RuntimeAnalysisConsolidationInputs | None: - """Combine projected tables without revisiting worker artifact payloads.""" - output_groups: dict[ - tuple[Path, RuntimeAnalysisSummaryDestination], list[RuntimeAnalysisTableOutput] - ] = {} - destinations: set[RuntimeAnalysisSummaryDestination] = set() - seen_paths: set[tuple[str, Path]] = set() + """Admit execution contexts and combine their actual rendered outputs.""" + inputs = [] for observation in observations: for context_observation in observation.contexts: if context_observation.context_key not in compiled_contexts: @@ -137,18 +187,8 @@ def from_observations( "Runtime observation references unknown compiled context " f"{context_observation.context_key!r}." ) - inputs = context_observation.analysis_inputs - if inputs is None: - continue - destinations.add(inputs.destination) - for directory, group in inputs.groups.items(): - for output in group.outputs: - identity = (group.destination.backend, output.path) - if identity in seen_paths: - continue - seen_paths.add(identity) - output_groups.setdefault((directory, group.destination), []).append(output) - return cls._from_groups(output_groups, destinations) + inputs.append(context_observation.analysis_inputs) + return cls.combine(inputs) @classmethod def _from_groups( diff --git a/openhcs/core/orchestrator/compiled_plate_execution.py b/openhcs/core/orchestrator/compiled_plate_execution.py index df19654ac4..5e2cb76fcf 100644 --- a/openhcs/core/orchestrator/compiled_plate_execution.py +++ b/openhcs/core/orchestrator/compiled_plate_execution.py @@ -40,6 +40,7 @@ from openhcs.core.execution_visualizer import ExecutionVisualizerABC from openhcs.core.function_patterns import CompiledFunctionInvocation from openhcs.core.orchestrator.analysis_consolidation import ( + RuntimeAnalysisConsolidationInputs, consolidate_analysis_outputs, ) from openhcs.core.orchestrator.cancellation import ExecutionCancelledError @@ -77,7 +78,7 @@ replace_runtime_artifact_payload, ) from openhcs.core.source_bindings import CompiledSourceBindingPlan -from openhcs.core.steps.abstract import AbstractStep +from openhcs.core.steps.abstract import AbstractStep, StepExecutionObservation from openhcs.core.steps.function_outputs import ( OpenHCSMetadataWriter, RuntimeArtifactMaterializationAuthority, @@ -104,6 +105,9 @@ class CompiledPlateExecutionExtras: RESULTS_SUMMARY_KEY: ClassVar[str] = "viewer_states_by_port" viewer_states_by_port: Mapping[int, "ViewerControlResponse"] + runtime_observation: RuntimeExecutionObservation = field( + default_factory=RuntimeExecutionObservation + ) class CompiledPlateExecutionResults(dict[str, ExecutionResult]): @@ -120,6 +124,13 @@ def __init__( viewer_states_by_port=MappingProxyType({}) ) + @property + def runtime_observations(self) -> tuple[RuntimeExecutionObservation, ...]: + return ( + *tuple(result.runtime_observation for result in self.values()), + self.extras.runtime_observation, + ) + @dataclass(frozen=True, slots=True) class CompiledPlateExecutionRequest(ProgressExecutionContext): @@ -249,6 +260,7 @@ def execute_compiled_plate_request( executor_resources.clear_execution_bundle() executor_resources.release_parent_runtime_resources(execution_bundle) + plate_runtime_observation = RuntimeExecutionObservation() if all(result.is_success() for result in execution_results.values()): plate_runtime_observation = execute_plate_scoped_steps( validated.compiled_contexts, @@ -285,7 +297,8 @@ def execute_compiled_plate_request( return CompiledPlateExecutionResults( execution_results, extras=CompiledPlateExecutionExtras( - viewer_states_by_port=viewer_states_by_port + viewer_states_by_port=viewer_states_by_port, + runtime_observation=plate_runtime_observation, ), ) except ExecutionCancelledError: @@ -445,6 +458,7 @@ def execute_plate_scoped_steps( plate_step_indexes = validate_plate_scoped_contexts(compiled_contexts) total_steps = max(next(iter(compiled_contexts.values())).step_plans) + 1 records_by_axis = _runtime_record_snapshot(compiled_contexts) + observations_by_context = {key: [] for key in compiled_contexts} for step_index in plate_step_indexes: owner_context, owner_plan = _plate_output_owner( compiled_contexts, @@ -523,13 +537,24 @@ def execute_plate_scoped_steps( ) records_by_axis = _records_with_output(records_by_axis, record) - RuntimeArtifactMaterializationAuthority.materialize( + materializations = RuntimeArtifactMaterializationAuthority.materialize( owner_context, owner_plan.require_function_execution_ready(), ) OpenHCSMetadataWriter.write( owner_context, owner_plan.require_function_execution_ready(), + artifact_materializations=materializations, + ) + owner_context_key = next( + key + for key, context in compiled_contexts.items() + if context is owner_context + ) + observations_by_context[owner_context_key].append( + StepExecutionObservation.combine( + item.observation(owner_plan, owner_context) for item in materializations + ) ) _emit_execution_progress( progress_queue=progress_queue, @@ -548,7 +573,16 @@ def execute_plate_scoped_steps( context_key=context_key, context=context, records=records, + runtime_export_paths=tuple( + dict.fromkeys( + path for item in observations_by_context[context_key] + for path in item.runtime_export_paths + ) + ), runtime_observation_mode=RuntimeObservationMode.MERGE_INTO_PARENT, + analysis_inputs=RuntimeAnalysisConsolidationInputs.combine( + item.analysis_inputs for item in observations_by_context[context_key] + ), ) for context_key, context in compiled_contexts.items() if ( diff --git a/openhcs/core/orchestrator/execution_result.py b/openhcs/core/orchestrator/execution_result.py index af3bec8f40..60ddd28926 100644 --- a/openhcs/core/orchestrator/execution_result.py +++ b/openhcs/core/orchestrator/execution_result.py @@ -74,29 +74,15 @@ def from_context( context: ProcessingContext, records: tuple[StoredRuntimeValue, ...], runtime_observation_mode: "RuntimeObservationMode", + runtime_export_paths: tuple[Path, ...], + analysis_inputs: "RuntimeAnalysisConsolidationInputs | None", ) -> "RuntimeContextObservation": - """Project completed outputs before releasing worker-owned payloads.""" - from openhcs.core.orchestrator.analysis_consolidation import ( - RuntimeAnalysisConsolidationInputs, - ) - from openhcs.core.steps.function_artifact_materialization import ( - observed_runtime_export_artifact_output_paths, - ) - + """Retain requested records beside the completed output projections.""" return cls( context_key=context_key, records=runtime_observation_mode.retain_records(records, context), - runtime_export_paths=tuple( - dict.fromkeys( - path - for plan in context.step_plans.values() - if plan.owns_runtime_outputs - for path in observed_runtime_export_artifact_output_paths( - plan, context, records, - ) - ) - ), - analysis_inputs=RuntimeAnalysisConsolidationInputs.from_records(context, records), + runtime_export_paths=tuple(dict.fromkeys(runtime_export_paths)), + analysis_inputs=analysis_inputs, ) diff --git a/openhcs/core/orchestrator/orchestrator.py b/openhcs/core/orchestrator/orchestrator.py index f898fac200..ac75e8d866 100644 --- a/openhcs/core/orchestrator/orchestrator.py +++ b/openhcs/core/orchestrator/orchestrator.py @@ -98,6 +98,7 @@ def __init__( workspace_path: Optional[Union[str, Path]] = None, *, pipeline_config: Optional["PipelineConfig"] = None, + resolved_config: GlobalPipelineConfig | None = None, storage_registry: Optional[Any] = None, selected_pipeline_path: Union[str, Path, None] = None, progress_callback: Optional[Callable[[Dict[str, Any]], None]] = None, @@ -192,7 +193,9 @@ def __init__( logger.info("PipelineOrchestrator using global StorageRegistry instance.") # Override zarr backend with orchestrator's resolved config. - effective_config = self.get_effective_config() + effective_config = ( + self.get_effective_config() if resolved_config is None else resolved_config + ) zarr_backend_with_config = ZarrStorageBackend(effective_config.zarr_config) self.registry[Backend.ZARR.value] = zarr_backend_with_config logger.info( @@ -295,7 +298,9 @@ def get_or_create_visualizer(self, config, vis_config=None): self._visualizers[(backend_name,)] = vis return vis - def initialize_microscope_handler(self): + def initialize_microscope_handler( + self, resolved_config: GlobalPipelineConfig | None = None + ): """Initializes the microscope handler.""" if self.microscope_handler is not None: logger.debug("Microscope handler already initialized.") @@ -307,7 +312,11 @@ def initialize_microscope_handler(self): f"Initializing microscope handler using input directory: {self.input_dir}..." ) try: - shared_context = self.get_effective_config() + shared_context = ( + self.get_effective_config() + if resolved_config is None + else resolved_config + ) microscope_type = ( shared_context.microscope.value if shared_context.microscope != Microscope.AUTO @@ -396,7 +405,10 @@ def _rebind_created_plate_path(self, execution_plate_path: Path) -> None: self._plate_path_frozen = True def initialize( - self, workspace_path: Optional[Union[str, Path]] = None + self, + workspace_path: Optional[Union[str, Path]] = None, + *, + resolved_config: GlobalPipelineConfig | None = None, ) -> "PipelineOrchestrator": """ Initializes all required components for the orchestrator. @@ -408,7 +420,12 @@ def initialize( return self try: - self.initialize_microscope_handler() + effective_config = ( + self.get_effective_config() + if resolved_config is None + else resolved_config + ) + self.initialize_microscope_handler(effective_config) self.microscope_handler.source_selection_role().require_available_source( self.plate_path ) @@ -426,7 +443,7 @@ def initialize( # Log effective backend intent early for debugging test/UI differences try: - vfs_cfg = self.get_effective_config().vfs_config + vfs_cfg = effective_config.vfs_config logger.info( "VFS config at init: read_backend=%s intermediate_backend=%s materialization_backend=%s", vfs_cfg.read_backend, @@ -460,7 +477,7 @@ def initialize( ) # Ensure complete OpenHCS metadata exists - self._ensure_openhcs_metadata() + self._ensure_openhcs_metadata(effective_config) logger.info( "PipelineOrchestrator fully initialized with cached component keys and metadata." @@ -537,7 +554,9 @@ def adopt_compiled_execution( def is_initialized(self) -> bool: return self._initialized - def _ensure_openhcs_metadata(self) -> None: + def _ensure_openhcs_metadata( + self, resolved_config: GlobalPipelineConfig + ) -> None: """Ensure complete OpenHCS metadata exists for the plate. Uses the same context creation logic as pipeline execution to get full metadata @@ -561,7 +580,9 @@ def _ensure_openhcs_metadata(self) -> None: subdir_name = get_subdirectory_name(self.input_dir, self.plate_path) # Create context using SAME logic as create_context() to get full metadata - context = self.create_context(axis_id="metadata_init") + context = self.create_context( + axis_id="metadata_init", resolved_config=resolved_config + ) # Determine correct backend using handler's logic (virtual_workspace for ImageXpress/Opera, disk for others) backend = self.microscope_handler.get_primary_backend( @@ -607,7 +628,9 @@ def get_results_path(self) -> Path: return output_plate_root / materialization_path - def create_context(self, axis_id: str) -> ProcessingContext: + def create_context( + self, axis_id: str, *, resolved_config: GlobalPipelineConfig | None = None + ) -> ProcessingContext: """Creates a ProcessingContext for a given multiprocessing axis value.""" if not self.is_initialized(): raise RuntimeError( @@ -620,7 +643,9 @@ def create_context(self, axis_id: str) -> ProcessingContext: "Orchestrator input_dir is not set; initialize orchestrator first." ) - effective_config = self.get_effective_config() + effective_config = ( + self.get_effective_config() if resolved_config is None else resolved_config + ) context = ProcessingContext( axis_id=axis_id, filemanager=self.filemanager, @@ -694,6 +719,8 @@ def compile_pipelines( enable_visualizer_override: bool = False, is_zmq_execution: bool = False, debug_execution_policy: DebugExecutionPolicy = NoOpDebugExecutionPolicy(), + *, + resolved_config: GlobalPipelineConfig | None = None, ) -> CompiledExecutionBundle: """Compile the selected axes into one typed execution bundle.""" return PipelineCompiler.compile_pipelines( @@ -703,6 +730,7 @@ def compile_pipelines( enable_visualizer_override=enable_visualizer_override, is_zmq_execution=is_zmq_execution, debug_execution_policy=debug_execution_policy, + resolved_config=resolved_config, ) def cancel_execution(self): diff --git a/openhcs/core/orchestrator/worker_execution.py b/openhcs/core/orchestrator/worker_execution.py index c14394a31a..9257de1522 100644 --- a/openhcs/core/orchestrator/worker_execution.py +++ b/openhcs/core/orchestrator/worker_execution.py @@ -23,6 +23,9 @@ from openhcs.core.context.processing_context import ProcessingContext from openhcs.core.function_step_transport import FunctionStepTransportAuthority from openhcs.core.native_threading import configure_native_thread_count +from openhcs.core.orchestrator.analysis_consolidation import ( + RuntimeAnalysisConsolidationInputs, +) from openhcs.core.orchestrator.execution_result import ( ExecutionResult, RuntimeContextObservation, @@ -48,10 +51,14 @@ from openhcs.core.progress.runtime_artifacts import ( runtime_artifact_context_for_records, ) -from openhcs.core.runtime_stores import StoredRuntimeValue +from openhcs.core.runtime_stores import ( + StoredRuntimeValue, + RuntimeArtifactAddress, + RuntimeArtifactLocation, +) from openhcs.core.steps.abstract import AbstractStep, StepExecutionObservation from openhcs.core.steps.function_artifact_materialization import ( - observed_materialized_artifact_locations_by_address, + preview_reused_step_outputs, ) from openhcs.utils.environment import OpenHCSProcessEnvironment @@ -62,21 +69,16 @@ def _runtime_observation_progress_context( records: tuple[StoredRuntimeValue, ...], *, - plan: CompiledStepPlan, - context: ProcessingContext, + materialized_locations_by_address: Mapping[ + RuntimeArtifactAddress, tuple[RuntimeArtifactLocation, ...] + ], ) -> dict | None: """Project one RuntimeValueStore observation delta through owned payloads.""" runtime_artifacts = runtime_artifact_context_for_records(records) live_measurements = live_measurement_context_for_records( records, - materialized_locations_by_address=( - observed_materialized_artifact_locations_by_address( - plan, - context, - records, - ) - ), + materialized_locations_by_address=materialized_locations_by_address, ) if runtime_artifacts is None: return live_measurements @@ -801,16 +803,26 @@ def _execute_axis_with_sequential_combinations( pipeline_definition, frozen_context, lane_context, + context_key=context_key, cancellation=cancellation, ) observed_records = runtime_store.observed_values_after( execution_observation_cursor ) + runtime_export_paths = tuple( + path + for observation in result.runtime_observation.contexts + for path in observation.runtime_export_paths + ) observation = RuntimeContextObservation.from_context( context_key=context_key, context=frozen_context, records=observed_records, runtime_observation_mode=runtime_observation_mode, + runtime_export_paths=runtime_export_paths, + analysis_inputs=RuntimeAnalysisConsolidationInputs.combine( + item.analysis_inputs for item in result.runtime_observation.contexts + ), ) finally: # This cache is context-local even when lanes share a process. @@ -926,6 +938,8 @@ def _execute_single_axis_static( pipeline_definition: List[AbstractStep], frozen_context: ProcessingContext, lane_context: WorkerLaneExecutionContext, + *, + context_key: str, cancellation: ExecutionCancellationSignal | None = None, ) -> ExecutionResult: """Execute one frozen axis context against the compiled pipeline.""" @@ -946,6 +960,8 @@ def _execute_single_axis_static( frozen_context.bind_execution_runtime(lane_context) lane_context.install_debug_sink(frozen_context) runtime_value_store = frozen_context.runtime_value_store + runtime_export_paths = [] + analysis_inputs = [] for step_index, step in enumerate(pipeline_definition): if cancellation is not None: @@ -973,11 +989,15 @@ def _execute_single_axis_static( observed_records = runtime_value_store.observed_values_after( observation_cursor ) + reused_outputs = preview_reused_step_outputs( + step_plan, frozen_context, observed_records, + ) runtime_progress_context = _runtime_observation_progress_context( observed_records, - plan=step_plan, - context=frozen_context, + materialized_locations_by_address=reused_outputs.materialized_locations_by_address, ) + runtime_export_paths.extend(reused_outputs.runtime_export_paths) + analysis_inputs.append(reused_outputs.analysis_inputs) emit( execution_id=lane_context.execution_id, plate_id=lane_context.plate_id, @@ -1010,12 +1030,13 @@ def _execute_single_axis_static( ) observation_cursor = runtime_value_store.observation_cursor() - step.process(frozen_context, step_index) + step_observation = step.process(frozen_context, step_index) + runtime_export_paths.extend(step_observation.runtime_export_paths) + analysis_inputs.append(step_observation.analysis_inputs) observed_records = runtime_value_store.observed_values_after(observation_cursor) runtime_progress_context = _runtime_observation_progress_context( observed_records, - plan=step_plan, - context=frozen_context, + materialized_locations_by_address=step_observation.materialized_locations_by_address, ) emit( @@ -1038,7 +1059,19 @@ def _execute_single_axis_static( ): break - return ExecutionResult.success(axis_id=axis_id) + return ExecutionResult.success( + axis_id=axis_id, + runtime_observation=RuntimeExecutionObservation( + contexts=( + RuntimeContextObservation( + context_key=context_key, + records=(), + runtime_export_paths=tuple(dict.fromkeys(runtime_export_paths)), + analysis_inputs=RuntimeAnalysisConsolidationInputs.combine(analysis_inputs), + ), + ) + ), + ) def execute_worker_lane( diff --git a/openhcs/core/pipeline/compilation_session.py b/openhcs/core/pipeline/compilation_session.py index 785b2ef9f3..c86ff7e2ca 100644 --- a/openhcs/core/pipeline/compilation_session.py +++ b/openhcs/core/pipeline/compilation_session.py @@ -2,7 +2,6 @@ from __future__ import annotations -from collections.abc import Iterator from dataclasses import dataclass, fields, is_dataclass, replace from pathlib import Path from typing import TYPE_CHECKING, Any, Mapping, MutableMapping, Sequence, get_type_hints @@ -11,13 +10,14 @@ from openhcs.core.compiled_step_plan import CompiledStepPlan from openhcs.core.context.processing_context import ProcessingContext -from openhcs.core.pipeline.step_snapshot import ( - StepSnapshot, - build_step_snapshots, -) from openhcs.core.source_metadata import SourceMetadataMapping from openhcs.core.source_workspace_projection import VirtualWorkspaceSourceProjection from openhcs.core.steps.abstract import AbstractStep +from openhcs.core.steps.function_step import FunctionStep +from openhcs.core.function_patterns import ( + normalize_function_pattern, + strip_disabled_functions, +) from openhcs.core.vfs_protocol import ( FileManagerLike, PlatePathDeclaration, @@ -156,21 +156,56 @@ def resolve_declared_dataclass_paths( return replace(value, **replacements) if replacements else value +@dataclass(frozen=True, slots=True) +class ResolvedPipelineDefinition: + """Capture enabled declarations once after ObjectState/callable resolution. + + Axis sessions derive metadata kwargs and provider contracts from this view; + authored FunctionSteps keep their public function-pattern syntax. + """ + + steps: Sequence[AbstractStep] + step_state_map: Mapping[int, "ObjectState"] + + def __post_init__(self) -> None: + missing_states = [ + index for index in range(len(self.steps)) if index not in self.step_state_map + ] + if missing_states: + raise ValueError( + f"Resolved pipeline missing ObjectState entries for steps {missing_states}." + ) + object.__setattr__( + self, + "steps", + tuple( + ( + step.with_function_spec( + normalize_function_pattern( + strip_disabled_functions(step.func) or [] + ) + ) + if isinstance(step, FunctionStep) + else step + ) + for step in self.steps + ), + ) + + @dataclass(slots=True) class CompilationSession: """Compiler boundary for one ProcessingContext. The session is not a dict wrapper. It owns the invariants tying together the - resolved step list, ObjectState map, StepSnapshot tuple, context, and mutable + resolved pipeline declaration, context, and mutable compiled-plan map for one axis or sequential-combination context. """ context: ProcessingContext - steps: Sequence[AbstractStep] + pipeline: ResolvedPipelineDefinition orchestrator: "PipelineOrchestrator" global_config: "GlobalPipelineConfig" - step_state_map: Mapping[int, "ObjectState"] - snapshots: tuple[StepSnapshot, ...] plans: MutableMapping[int, CompiledStepPlan] source_workspace_projection: VirtualWorkspaceSourceProjection path_resolver: CompilationPathResolver | None = None @@ -183,11 +218,9 @@ def from_context( cls, *, context: ProcessingContext, - steps: Sequence[AbstractStep], + pipeline: ResolvedPipelineDefinition, orchestrator: "PipelineOrchestrator", global_config: "GlobalPipelineConfig", - step_state_map: Mapping[int, "ObjectState"], - snapshots: tuple[StepSnapshot, ...] | None = None, source_workspace_projection: VirtualWorkspaceSourceProjection | None = None, path_resolver: CompilationPathResolver | None = None, metadata_writer: bool = False, @@ -196,15 +229,11 @@ def from_context( ) -> "CompilationSession": if context.step_plans is None: raise ValueError("CompilationSession requires context.step_plans.") - if snapshots is None: - snapshots = build_step_snapshots(steps, step_state_map) return cls( context=context, - steps=steps, + pipeline=pipeline, orchestrator=orchestrator, global_config=global_config, - step_state_map=step_state_map, - snapshots=snapshots, plans=context.step_plans, source_workspace_projection=( VirtualWorkspaceSourceProjection.empty(context.plate_path) @@ -224,34 +253,6 @@ def from_context( def __post_init__(self) -> None: if self.plate_scope is None and self.context.plate_path is not None: self.plate_scope = CompilationPlateScope.from_context(self.context) - if len(self.steps) != len(self.snapshots): - raise ValueError( - "CompilationSession requires one StepSnapshot per step: " - f"{len(self.snapshots)} snapshots for {len(self.steps)} steps." - ) - missing_states = [ - index - for index in range(len(self.steps)) - if index not in self.step_state_map - ] - if missing_states: - raise ValueError( - f"CompilationSession missing ObjectState entries for steps " - f"{missing_states}." - ) - for expected_index, (snapshot, step) in enumerate( - zip(self.snapshots, self.steps, strict=True) - ): - if snapshot.index != expected_index: - raise ValueError( - f"StepSnapshot index mismatch: expected {expected_index}, " - f"got {snapshot.index}." - ) - if snapshot.step is not step: - raise ValueError( - f"StepSnapshot {expected_index} does not reference its resolved step." - ) - @property def axis_id(self) -> str: return self.context.axis_id @@ -273,35 +274,16 @@ def realized_source_metadata( ) return metadata or None - def step(self, index: int) -> AbstractStep: - return self.steps[index] - - def snapshot(self, index: int) -> StepSnapshot: - return self.snapshots[index] - @property def step_count(self) -> int: - return len(self.snapshots) - - def indexed_snapshots(self) -> Iterator[tuple[int, StepSnapshot]]: - return iter(enumerate(self.snapshots)) - - def reverse_snapshot_indices(self) -> range: - return range(self.step_count - 1, -1, -1) - - def step_state(self, index: int) -> "ObjectState": - try: - return self.step_state_map[index] - except KeyError as exc: - raise ValueError(f"Missing ObjectState for step {index}.") from exc + return len(self.pipeline.steps) def plan(self, index: int) -> CompiledStepPlan: try: return self.plans[index] except KeyError as exc: - snapshot = self.snapshot(index) raise ValueError( - f"Missing compiled plan for step {index} ({snapshot.step.name})." + f"Missing compiled plan for step {index} ({self.pipeline.steps[index].name})." ) from exc def main_flow_plan_ancestry( @@ -325,12 +307,3 @@ def main_flow_plan_ancestry( if source_step_index is None: return tuple(ancestry) current_index = source_step_index - - -@dataclass(frozen=True, slots=True) -class ResolvedPipelineDefinition: - """ObjectState-resolved pipeline declaration shared by all axis sessions.""" - - steps: Sequence[AbstractStep] - step_state_map: Mapping[int, "ObjectState"] - snapshots: tuple[StepSnapshot, ...] diff --git a/openhcs/core/pipeline/compiler.py b/openhcs/core/pipeline/compiler.py index 46619c1b74..8fad83ca52 100644 --- a/openhcs/core/pipeline/compiler.py +++ b/openhcs/core/pipeline/compiler.py @@ -7,7 +7,7 @@ CONFIGURATION ACCESS PATTERN: ============================ The compiler resolves ObjectState once and replaces the submitted pipeline with -the resolved steps before creating compiler snapshots: +the resolved steps retained by ResolvedPipelineDefinition: CORRECT: # Steps are registered in ObjectState with parent hierarchy: step → orchestrator → global @@ -15,8 +15,7 @@ ObjectStateRegistry.register(step_state) resolved_step = step_state.to_saved_resolved_object() - snapshot = StepSnapshot(index=0, scope_id=step_state.scope_id, step=resolved_step) - var_comps = snapshot.step.processing_config.variable_components + var_comps = resolved_step.processing_config.variable_components ✅ CORRECT (LIVE VALUES FOR UI): # For UI: use get_resolved_value() to get current values with unsaved edits @@ -34,7 +33,7 @@ WHY: - ObjectState.to_saved_resolved_object() provides the resolved compiler step -- StepSnapshot carries only compiler index, scope identity, and that resolved step +- ResolvedPipelineDefinition owns ordered resolved steps and their registered ObjectStates - get_resolved_value() provides live state with unsaved edits (for UI) - parameters.get() returns raw local value only, NO inheritance - No cross-step pollution - each step only sees its own config hierarchy @@ -113,10 +112,6 @@ PathPlannerExecutionGroups, PipelinePathPlanner, ) -from openhcs.core.pipeline.step_snapshot import ( - StepSnapshot, - build_step_snapshots, -) from openhcs.core.source_matching import SourceImageSetIdentityPolicy from openhcs.core.source_workspace_projection import ( VirtualWorkspaceSourceProjectionAuthority, @@ -203,7 +198,9 @@ class AxisCompilationRequest: is_zmq_execution: bool def context_for(self, axis_id: str) -> ProcessingContext: - context = self.orchestrator.create_context(axis_id) + context = self.orchestrator.create_context( + axis_id, resolved_config=self.global_config + ) context.source_image_set_identity_policy = ( SourceImageSetIdentityPolicy.from_pipeline_config(self.global_config) ) @@ -234,11 +231,9 @@ class PipelineCompiler: @staticmethod def initialize_step_plans_for_context( context: ProcessingContext, - steps_definition: List[AbstractStep], + pipeline: ResolvedPipelineDefinition, orchestrator, global_config: "GlobalPipelineConfig", - step_state_map: Mapping[int, "ObjectState"], - step_snapshots: tuple[StepSnapshot, ...], metadata_writer: bool = False, plate_path: Optional[Path] = None, path_resolver: CompilationPathResolver | None = None, @@ -252,13 +247,11 @@ def initialize_step_plans_for_context( Args: context: ProcessingContext to initialize step plans for - steps_definition: List of AbstractStep objects defining the pipeline + pipeline: Ordered resolved steps and their registered ObjectStates orchestrator: Orchestrator instance for well filter resolution metadata_writer: If True, this well is responsible for creating OpenHCS metadata files plate_path: Path to plate root for zarr conversion detection global_config: Resolved global compiler configuration - step_state_map: ObjectState mapping from pipeline-level resolution - step_snapshots: Snapshots of the same resolved pipeline steps Returns: The axis-scoped compilation session used by all downstream stages. @@ -268,11 +261,9 @@ def initialize_step_plans_for_context( logger.debug("Using pipeline-resolved steps for context %s", context.axis_id) session = CompilationSession.from_context( context=context, - steps=steps_definition, + pipeline=pipeline, orchestrator=orchestrator, global_config=global_config, - step_state_map=step_state_map, - snapshots=step_snapshots, source_workspace_projection=( orchestrator.source_workspace_projection().filtered_by_axis( axis_id=context.axis_id, @@ -286,10 +277,7 @@ def initialize_step_plans_for_context( PipelineCompiler._ensure_initial_step_plans(session) PipelineCompiler._configure_input_conversion_if_needed( - context, - session.steps, - orchestrator, - plate_path, + session, ) PipelineCompiler._plan_context_paths(session) PipelineCompiler._supplement_step_plans(session) @@ -311,7 +299,7 @@ def _register_object_state( scope_id: str, parent_state: Optional["ObjectState"], ) -> "ObjectState": - """Create and register an ObjectState with the compiler's snapshot policy.""" + """Create and register an ObjectState with the compiler's step policy.""" state = ObjectState( object_instance=object_instance, scope_id=scope_id, @@ -351,26 +339,26 @@ def _missing_plan_fields( def _ensure_initial_step_plans( session: CompilationSession, ) -> None: - for step_index, snapshot in enumerate(session.snapshots): + for step_index, step in enumerate(session.pipeline.steps): if step_index not in session.plans: session.plans[step_index] = CompiledStepPlan( step_index=step_index, - step_name=snapshot.step.name, - step_type=type(snapshot.step).__name__, + step_name=step.name, + step_type=type(step).__name__, axis_id=session.axis_id, ) @staticmethod def _configure_input_conversion_if_needed( - context: ProcessingContext, - steps: Sequence[AbstractStep], - orchestrator, - plate_path: Path | None, + session: CompilationSession, ) -> None: + context = session.context + steps = session.pipeline.steps + plate_path = session.plate_path if not steps or plate_path is None: return - vfs_config = orchestrator.get_effective_config().vfs_config + vfs_config = session.global_config.vfs_config if vfs_config.materialization_backend != MaterializationBackend.ZARR: return @@ -421,17 +409,17 @@ def _plan_context_paths( @staticmethod def _supplement_step_plans(session: CompilationSession) -> None: - for step_index, snapshot in enumerate(session.snapshots): + for step_index, step in enumerate(session.pipeline.steps): if step_index not in session.plans: logger.error( "Critical error: Step %s (index: %s) not found in step_plans after path planning phase.", - snapshot.step.name, + step.name, step_index, ) session.plans[step_index] = CompiledStepPlan( step_index=step_index, - step_name=snapshot.step.name, - step_type=type(snapshot.step).__name__, + step_name=step.name, + step_type=type(step).__name__, axis_id=session.axis_id, error="Missing from path planning phase by PipelinePathPlanner", create_openhcs_metadata=session.metadata_writer, @@ -439,29 +427,29 @@ def _supplement_step_plans(session: CompilationSession) -> None: continue current_plan = session.plans[step_index] - current_plan.step_scope_id = snapshot.scope_id - current_plan.step_name = snapshot.step.name - current_plan.step_type = type(snapshot.step).__name__ + current_plan.step_scope_id = session.pipeline.step_state_map[ + step_index + ].scope_id + current_plan.step_name = step.name + current_plan.step_type = type(step).__name__ current_plan.axis_id = session.axis_id current_plan.create_openhcs_metadata = session.metadata_writer - current_plan.variable_components = ( - snapshot.step.processing_config.variable_components - ) + current_plan.variable_components = step.processing_config.variable_components current_plan.group_by = PathPlannerExecutionGroups.normalized_group_by( - snapshot, + step, ) - declared_group_by = snapshot.step.processing_config.group_by + declared_group_by = step.processing_config.group_by if current_plan.group_by is not declared_group_by: logger.warning( "Step %r uses a non-routed function pattern with group_by=%s " "also present in variable_components; compiled group_by is " "GroupBy.NONE because variable_components owns the runtime " "stack axis.", - snapshot.step.name, + step.name, declared_group_by.name, ) - current_plan.input_source = snapshot.step.processing_config.input_source - current_plan.sequential_processing = snapshot.step.processing_config + current_plan.input_source = step.processing_config.input_source + current_plan.sequential_processing = step.processing_config current_plan.sequential_filter_plan = ( PipelineCompiler._compile_sequential_runtime_filter_plan(session) ) @@ -513,13 +501,13 @@ def _collect_streaming_configs( session: CompilationSession, ) -> None: streaming_config_types = tuple(StreamingConfig.__registry__.values()) - for step_index, snapshot in enumerate(session.snapshots): + for step_index, step in enumerate(session.pipeline.steps): step_plan = session.plans[step_index] for config_type in streaming_config_types: PipelineCompiler._collect_streaming_config( session, step_index, - snapshot, + step, step_plan, config_type, ) @@ -528,19 +516,19 @@ def _collect_streaming_configs( def _collect_streaming_config( session: CompilationSession, step_index: int, - snapshot: StepSnapshot, + step: AbstractStep, step_plan: CompiledStepPlan, config_type: type[StreamingConfig], ) -> None: resolved_config_type = get_base_type_for_lazy(config_type) or config_type configs = tuple( value - for value in vars(snapshot.step).values() + for value in vars(step).values() if isinstance(value, resolved_config_type) ) if not configs: return - defaults_enabled = snapshot.step.streaming_defaults.enabled + defaults_enabled = step.streaming_defaults.enabled for config_obj in configs: per_stream_enabled = config_obj.enabled enabled = True if defaults_enabled is True else per_stream_enabled @@ -604,14 +592,14 @@ def declare_zarr_stores(session: CompilationSession) -> None: all_wells = orchestrator.get_component_keys(get_multiprocessing_axis()) # Access config from merged config (pipeline + global) for proper inheritance - vfs_config = orchestrator.get_effective_config().vfs_config + vfs_config = session.global_config.vfs_config - for step_index, snapshot in enumerate(session.snapshots): + for step_index, step in enumerate(session.pipeline.steps): step_plan = session.plan(step_index) will_use_zarr = ( vfs_config.materialization_backend == MaterializationBackend.ZARR - and step_index == len(session.steps) - 1 + and step_index == len(session.pipeline.steps) - 1 ) if will_use_zarr: @@ -620,7 +608,7 @@ def declare_zarr_stores(session: CompilationSession) -> None: "needs_initialization": True, } logger.debug( - f"Step '{snapshot.step.name}' will use zarr backend for axis {context.axis_id}" + f"Step '{step.name}' will use zarr backend for axis {context.axis_id}" ) else: step_plan.zarr_config = None @@ -647,7 +635,7 @@ def plan_materialization_flags(session: CompilationSession) -> None: # CRITICAL: Pass merged config (not raw pipeline_config) for proper global config inheritance MaterializationFlagPlanner.prepare_pipeline_flags( context, - session.steps, + session.pipeline.steps, session.orchestrator.plate_path, session.global_config, # Use merged config instead of raw pipeline_config available_axis_values=session.orchestrator.get_component_keys( @@ -656,11 +644,11 @@ def plan_materialization_flags(session: CompilationSession) -> None: ) # Post-check (optional, but good for ensuring contracts are met by the planner) - for step_index, snapshot in enumerate(session.snapshots): + for step_index, step in enumerate(session.pipeline.steps): if step_index not in context.step_plans: # This should not happen if prepare_pipeline_flags guarantees plans for all steps logger.error( - f"Step {snapshot.step.name} (index: {step_index}) missing from step_plans after materialization planning." + f"Step {step.name} (index: {step_index}) missing from step_plans after materialization planning." ) continue @@ -672,7 +660,7 @@ def plan_materialization_flags(session: CompilationSession) -> None: ) if missing_keys: logger.error( - f"Materialization flag planning incomplete for step {snapshot.step.name} (index: {step_index}). " + f"Materialization flag planning incomplete for step {step.name} (index: {step_index}). " f"Missing required keys: {missing_keys}." ) PipelineCompiler._compile_runtime_artifact_materialization_plans(session) @@ -714,14 +702,14 @@ def _compile_runtime_artifact_materialization_plans( @staticmethod def validate_sequential_components_compatibility( - step_snapshots: Sequence[StepSnapshot], + steps: Sequence[AbstractStep], sequential_components: List, ) -> None: """ Validate that no step's variable_components overlap with pipeline's sequential_components. Args: - step_snapshots: ObjectState-resolved compiler snapshots + steps: ObjectState-resolved pipeline steps sequential_components: List of SequentialComponents from pipeline config Raises: @@ -732,10 +720,10 @@ def validate_sequential_components_compatibility( seq_comp_values = {sc.value for sc in sequential_components} - for snapshot in step_snapshots: - if not isinstance(snapshot.step, FunctionStep): + for step in steps: + if not isinstance(step, FunctionStep): continue - var_comps = snapshot.step.processing_config.variable_components + var_comps = step.processing_config.variable_components if not var_comps: continue var_comp_values = {vc.value for vc in var_comps} @@ -743,7 +731,7 @@ def validate_sequential_components_compatibility( if overlap: raise ValueError( - f"Step '{snapshot.step.name}' has variable_components {sorted(overlap)} that conflict with " + f"Step '{step.name}' has variable_components {sorted(overlap)} that conflict with " f"pipeline's sequential_components {sorted(seq_comp_values)}. " f"A component cannot be both sequential (pipeline-level) and variable (step-level). " f"Either remove {sorted(overlap)} from step's variable_components or from " @@ -850,17 +838,17 @@ def validate_memory_contracts(session: CompilationSession) -> None: ) FuncStepContractValidator.validate_pipeline( - steps=session.steps, + steps=session.pipeline.steps, pipeline_context=context, # Pass context so validator can access step plans for memory type overrides orchestrator=session.orchestrator, # Pass orchestrator for dict pattern key validation ) - for step_index, step in enumerate(session.steps): + for step_index, step in enumerate(session.pipeline.steps): if not isinstance(step, FunctionStep): continue if step_index not in context.step_plans: raise AssertionError( - f"Memory validation requires a compiled plan for FunctionStep {session.snapshot(step_index).step.name} (index: {step_index})." + f"Memory validation requires a compiled plan for FunctionStep {session.pipeline.steps[step_index].name} (index: {step_index})." ) step_plan = context.step_plans[step_index] compiled_pattern = step_plan.compiled_function_pattern @@ -879,7 +867,7 @@ def validate_memory_contracts(session: CompilationSession) -> None: ) # Apply memory type override: Any step with disk output must use numpy for disk writing - for step_index, step in enumerate(session.steps): + for step_index, step in enumerate(session.pipeline.steps): if isinstance(step, FunctionStep): if step_index in context.step_plans: step_plan = context.step_plans[step_index] @@ -894,7 +882,7 @@ def validate_memory_contracts(session: CompilationSession) -> None: if write_backend == "disk": logger.debug( - f"Step {session.snapshot(step_index).step.name} has disk output, overriding output_memory_type to numpy" + f"Step {session.pipeline.steps[step_index].name} has disk output, overriding output_memory_type to numpy" ) step_plan.output_memory_type = "numpy" @@ -956,7 +944,7 @@ def resolve_lazy_dataclasses(session: CompilationSession) -> None: # Configs are already resolved via ObjectState.to_object() in initialize_step_plans_for_context # No additional resolution needed - step plans already contain resolved configs logger.debug( - f"Step plans already resolved via ObjectState for {len(session.steps)} steps" + f"Step plans already resolved via ObjectState for {len(session.pipeline.steps)} steps" ) @staticmethod @@ -1023,9 +1011,9 @@ def _validate_compile_request( def _axis_values_to_process( orchestrator, axis_filter: Optional[List[str]], + effective_config: GlobalPipelineConfig, ) -> List[str]: resolved_axis_filter = axis_filter - effective_config = orchestrator.get_effective_config() well_filter_config = ( effective_config.well_filter_config if effective_config else None ) @@ -1075,25 +1063,22 @@ def _register_and_resolve_pipeline_once( plate_path_str, pipeline_definition, ) - plate_orch_state = PipelineCompiler._pipeline_config_state( - orchestrator, - compiler_scope_id, - global_config_state, - force_fresh=force_fresh, - ) - orchestrator_scope_id = f"{compiler_scope_id}::orchestrator" - orch_state = PipelineCompiler._get_or_register_object_state( - orchestrator_scope_id, - orchestrator, - plate_orch_state, - force_fresh=force_fresh, - ) - logger.debug("Registered orchestrator at scope: %s", orchestrator_scope_id) - + pipeline_config_state = ObjectStateRegistry.get_by_scope(compiler_scope_id) + if orchestrator.pipeline_config is not None: + pipeline_config_state = PipelineCompiler._get_or_register_object_state( + compiler_scope_id, + orchestrator.pipeline_config, + global_config_state, + force_fresh=force_fresh, + ) + if pipeline_config_state is None: + raise RuntimeError( + "Missing ObjectState for plate; cannot resolve pipeline config." + ) step_state_map = PipelineCompiler._register_pipeline_step_states( pipeline_definition, compiler_scope_id, - orch_state, + pipeline_config_state, force_fresh=force_fresh, ) PipelineCompiler._replace_pipeline_with_resolved_steps( @@ -1106,23 +1091,14 @@ def _register_and_resolve_pipeline_once( len(pipeline_definition), ) - step_state_map, snapshots = PipelineCompiler._filter_enabled_steps( + pipeline = PipelineCompiler._filter_enabled_steps( pipeline_definition, step_state_map, ) - pipeline_config_state = ObjectStateRegistry.get_by_scope(compiler_scope_id) - if pipeline_config_state is None: - raise RuntimeError( - "Missing ObjectState for plate; cannot resolve pipeline config." - ) return ( compiler_scope_id, pipeline_config_state, - ResolvedPipelineDefinition( - steps=pipeline_definition, - step_state_map=step_state_map, - snapshots=snapshots, - ), + pipeline, ) @staticmethod @@ -1145,30 +1121,11 @@ def _compile_global_config_state(*, force_fresh: bool) -> "ObjectState" | None: logger.debug("Registered global config at scope ''") return global_config_state - @staticmethod - def _pipeline_config_state( - orchestrator, - compiler_scope_id: str, - global_config_state: "ObjectState" | None, - *, - force_fresh: bool, - ) -> "ObjectState" | None: - plate_orch_state = ObjectStateRegistry.get_by_scope(compiler_scope_id) - if orchestrator.pipeline_config: - plate_orch_state = PipelineCompiler._get_or_register_object_state( - compiler_scope_id, - orchestrator.pipeline_config, - global_config_state, - force_fresh=force_fresh, - ) - logger.debug("Registered pipeline_config at scope '%s'", compiler_scope_id) - return plate_orch_state - @staticmethod def _register_pipeline_step_states( pipeline_definition: Sequence[AbstractStep], compiler_scope_id: str, - orch_state: "ObjectState", + pipeline_config_state: "ObjectState", *, force_fresh: bool, ) -> Dict[int, "ObjectState"]: @@ -1182,7 +1139,7 @@ def _register_pipeline_step_states( step_state_map[step_index] = PipelineCompiler._get_or_register_object_state( step_scope_id, step, - orch_state, + pipeline_config_state, force_fresh=force_fresh, ) return step_state_map @@ -1206,47 +1163,32 @@ def _replace_pipeline_with_resolved_steps( def _filter_enabled_steps( pipeline_definition: List[AbstractStep], step_state_map: Mapping[int, "ObjectState"], - ) -> tuple[Dict[int, "ObjectState"], tuple[StepSnapshot, ...]]: - snapshots = build_step_snapshots(pipeline_definition, step_state_map) + ) -> ResolvedPipelineDefinition: enabled_pairs = [ - (step, step_state_map[snapshot.index]) - for snapshot, step in zip(snapshots, pipeline_definition) + (step, step_state_map[index]) + for index, step in enumerate(pipeline_definition) if step.enabled ] pipeline_definition.clear() pipeline_definition.extend(step for step, _state in enabled_pairs) - enabled_state_map = { - new_index: state for new_index, (_step, state) in enumerate(enabled_pairs) - } - if not pipeline_definition: - return enabled_state_map, () - return ( - enabled_state_map, - build_step_snapshots(pipeline_definition, enabled_state_map), + return ResolvedPipelineDefinition( + steps=pipeline_definition, + step_state_map={ + index: state for index, (_step, state) in enumerate(enabled_pairs) + }, ) - @staticmethod - def _capture_pipeline_config( - pipeline_config_state: "ObjectState", - ) -> GlobalPipelineConfig: - pipeline_config = pipeline_config_state.to_saved_resolved_object() - if not isinstance(pipeline_config, GlobalPipelineConfig): - raise TypeError( - "Compiler pipeline ObjectState must resolve GlobalPipelineConfig; " - f"got {type(pipeline_config).__name__}." - ) - return pipeline_config - @staticmethod def _resolve_global_step_axis_filters( orchestrator, - step_snapshots: tuple[StepSnapshot, ...], - step_state_map: Mapping[int, "ObjectState"], + pipeline: ResolvedPipelineDefinition, + global_config: GlobalPipelineConfig, ) -> StepAxisFilterMap: - temp_context = orchestrator.create_context("temp") + temp_context = orchestrator.create_context( + "temp", resolved_config=global_config + ) _resolve_step_axis_filters( - step_snapshots, - step_state_map, + pipeline, temp_context, orchestrator, ) @@ -1319,11 +1261,9 @@ def build_initialize_axis_session( ) -> CompilationSession: return PipelineCompiler.initialize_step_plans_for_context( context, - list(request.pipeline.steps), + request.pipeline, request.orchestrator, request.global_config, - dict(request.pipeline.step_state_map), - request.pipeline.snapshots, metadata_writer=metadata_writer, plate_path=request.orchestrator.plate_path, path_resolver=request.path_resolver, @@ -1708,7 +1648,7 @@ def _validate_sequential_components_for_session( seq_config = session.global_config.sequential_processing_config if seq_config and seq_config.sequential_components: PipelineCompiler.validate_sequential_components_compatibility( - session.snapshots, + session.pipeline.steps, seq_config.sequential_components, ) @@ -1737,6 +1677,7 @@ def _finalize_compilation( pipeline_definition: List[AbstractStep], compiled_contexts: Mapping[str, ProcessingContext], compiler_scope_id: str, + effective_config: GlobalPipelineConfig, ) -> None: PipelineCompiler._log_path_planning_summary(compiled_contexts) PipelineCompiler._cleanup_compilation_object_states( @@ -1746,7 +1687,6 @@ def _finalize_compilation( logger.info("Stripping attributes from pipeline definition steps.") StepAttributeStripper.strip_step_attributes(pipeline_definition, {}) orchestrator._state = OrchestratorState.COMPILED - effective_config = orchestrator.get_effective_config() logger.info( f"Execution config: {effective_config.num_workers} workers configured for pipeline execution" ) @@ -1820,6 +1760,8 @@ def compile_pipelines( enable_visualizer_override: bool = False, is_zmq_execution: bool = False, debug_execution_policy: DebugExecutionPolicy = NoOpDebugExecutionPolicy(), + *, + resolved_config: GlobalPipelineConfig | None = None, ) -> CompiledExecutionBundle: """ Compile-all phase: prepares execution artifacts for each axis value. @@ -1846,9 +1788,15 @@ def compile_pipelines( PipelineCompiler._validate_compile_request(orchestrator, pipeline_definition) compiler_scope_id: str | None = None try: + effective_config = ( + orchestrator.get_effective_config() + if resolved_config is None + else resolved_config + ) axis_values_to_process = PipelineCompiler._axis_values_to_process( orchestrator, axis_filter, + effective_config, ) if not axis_values_to_process: logger.warning("No axis values found to process based on filter.") @@ -1857,7 +1805,7 @@ def compile_pipelines( runtime_contexts={}, worker_assignments={}, runtime_environment=CompiledRuntimeEnvironmentPlan.from_global_config( - orchestrator.get_effective_config(), + effective_config, compiled_contexts={}, server_mode=is_zmq_execution, ), @@ -1867,7 +1815,7 @@ def compile_pipelines( f"Starting compilation for axis values: {', '.join(axis_values_to_process)}" ) - compiler_scope_id, pipeline_config_state, pipeline_inputs = ( + compiler_scope_id, _pipeline_config_state, pipeline_inputs = ( PipelineCompiler._register_and_resolve_pipeline_once( orchestrator, pipeline_definition, @@ -1887,14 +1835,11 @@ def compile_pipelines( runtime_contexts={}, worker_assignments={}, runtime_environment=CompiledRuntimeEnvironmentPlan.from_global_config( - orchestrator.get_effective_config(), + effective_config, compiled_contexts={}, server_mode=is_zmq_execution, ), ) - effective_config = PipelineCompiler._capture_pipeline_config( - pipeline_config_state - ) path_resolver = CompilationPathResolver( plate_scope=CompilationPlateScope.from_path(orchestrator.plate_path), filemanager=orchestrator.filemanager, @@ -1918,21 +1863,15 @@ def compile_pipelines( pipeline_inputs = replace( pipeline_inputs, steps=resolved_steps, - snapshots=build_step_snapshots( - resolved_steps, - pipeline_inputs.step_state_map, - ), ) PipelineCompiler.validate_backend_compatibility( orchestrator, effective_config.vfs_config, ) - global_step_axis_filters = ( - PipelineCompiler._resolve_global_step_axis_filters( - orchestrator, - pipeline_inputs.snapshots, - pipeline_inputs.step_state_map, - ) + global_step_axis_filters = PipelineCompiler._resolve_global_step_axis_filters( + orchestrator, + pipeline_inputs, + effective_config, ) axis_request = AxisCompilationRequest( orchestrator=orchestrator, @@ -1968,6 +1907,7 @@ def compile_pipelines( pipeline_definition, compiled_contexts, compiler_scope_id, + effective_config, ) execution_bundle = CompiledExecutionBundle.from_runtime_contexts( pipeline_definition=pipeline_definition, @@ -2017,8 +1957,7 @@ def _write_compilation_debug_bundle_if_configured( def _resolve_step_axis_filters( - step_snapshots: tuple[StepSnapshot, ...], - step_state_map: Mapping[int, "ObjectState"], + pipeline: ResolvedPipelineDefinition, context, orchestrator, ): @@ -2030,8 +1969,7 @@ def _resolve_step_axis_filters( It processes ALL WellFilterConfig instances (materialization, streaming, etc.) uniformly. Args: - step_snapshots: ObjectState-resolved compiler snapshots - step_state_map: ObjectState owners retaining inherited-field provenance + pipeline: Resolved steps and ObjectState owners retaining inherited-field provenance context: Processing context for the current axis value orchestrator: Orchestrator instance with access to available axis values """ @@ -2043,10 +1981,10 @@ def _resolve_step_axis_filters( logger.warning("No available axis values found for axis filter resolution") return - for snapshot in step_snapshots: + for step_index, step in enumerate(pipeline.steps): step_filters: dict[type[WellFilterConfig], StepAxisFilterResolution] = {} - step_state = step_state_map[snapshot.index] - for field_name, config in vars(snapshot.step).items(): + step_state = pipeline.step_state_map[step_index] + for field_name, config in vars(step).items(): if not isinstance(config, WellFilterConfig) or config.well_filter is None: continue provenance = step_state.get_provenance(f"{field_name}.well_filter") @@ -2073,7 +2011,7 @@ def _resolve_step_axis_filters( ) if step_filters: - context.step_axis_filters[snapshot.index] = StepAxisFilterSet(step_filters) + context.step_axis_filters[step_index] = StepAxisFilterSet(step_filters) total_filters = sum(len(filters) for filters in context.step_axis_filters.values()) logger.debug( diff --git a/openhcs/core/pipeline/funcstep_contract_validator.py b/openhcs/core/pipeline/funcstep_contract_validator.py index 81b606c4c9..1aafedeaf8 100644 --- a/openhcs/core/pipeline/funcstep_contract_validator.py +++ b/openhcs/core/pipeline/funcstep_contract_validator.py @@ -762,7 +762,7 @@ def validate_compiled_step_plan(step_plan, orchestrator=None) -> None: if ( orchestrator is not None - and isinstance(func_pattern, dict) + and compiled_pattern.is_grouped and group_by not in (None, GroupBy.NONE) ): dict_validation_result = validator.validate_dict_pattern_keys( @@ -831,7 +831,7 @@ def validate_funcstep( ) execution_scope = FunctionStepExecutionScope.require_uniform(contracts) if execution_scope is FunctionStepExecutionScope.PLATE: - if isinstance(func_pattern, dict): + if normalized.is_grouped: raise ValueError( f"Plate-scoped FunctionStep {step_name!r} cannot use a dict pattern." ) @@ -881,7 +881,7 @@ def validate_funcstep( # Validate dict pattern keys if orchestrator is available if ( orchestrator is not None - and isinstance(func_pattern, dict) + and normalized.is_grouped and group_by not in (None, GroupBy.NONE) ): dict_validation_result = validator.validate_dict_pattern_keys( @@ -1125,59 +1125,6 @@ def _validate_required_args( missing_required_args_error(func.__name__, step_name, missing_args) ) - @staticmethod - def _validate_dict_pattern_keys( - func_pattern: dict, group_by, step_name: str, orchestrator - ) -> None: - """ - Validate that dict function pattern keys match available component keys. - - This validation ensures compile-time guarantee that dict patterns will work - at runtime by checking that all dict keys exist in the actual component data. - - Args: - func_pattern: Dict function pattern to validate - group_by: GroupBy enum specifying component type - step_name: Name of the step containing the function - orchestrator: Orchestrator for component key access - - Raises: - ValueError: If dict pattern keys don't match available component keys - """ - # Get available component keys from orchestrator - try: - available_keys = orchestrator.get_component_keys(group_by) - available_keys_set = set(str(key) for key in available_keys) - except Exception as e: - raise ValueError(f"Failed to get component keys for {group_by.value}: {e}") - - # Check each dict key against available keys - pattern_keys = list(func_pattern.keys()) - pattern_keys_set = set(str(key) for key in pattern_keys) - - # Try direct string match first - missing_keys = pattern_keys_set - available_keys_set - - if missing_keys: - # Try integer conversion for missing keys - still_missing = set() - for key in missing_keys: - try: - # Try converting pattern key to int and check if int version exists - key_as_int = int(key) - if str(key_as_int) in available_keys_set: - continue # Key exists as integer, not missing - except (ValueError, TypeError): - still_missing.add(key) - - if still_missing: - raise ValueError( - f"Function pattern keys not found in available {group_by.value} components for step '{step_name}'. " - f"Missing keys: {sorted(still_missing)}. " - f"Available keys: {sorted(available_keys)}. " - f"Function pattern keys must match component values from the plate data." - ) - @staticmethod def validate_pattern_structure( func: FunctionPatternSyntax, step_name: str diff --git a/openhcs/core/pipeline/function_contracts.py b/openhcs/core/pipeline/function_contracts.py index 182fdefa60..c7cab4da8a 100644 --- a/openhcs/core/pipeline/function_contracts.py +++ b/openhcs/core/pipeline/function_contracts.py @@ -3,7 +3,6 @@ from collections.abc import Mapping, Sequence from dataclasses import replace from enum import Enum -from functools import lru_cache import inspect from types import UnionType from typing import ( @@ -61,17 +60,27 @@ def decorator(func: F) -> F: f"{parameter_name!r}." ) namespace = vars(func) + namespace.pop(FunctionContractAttribute.canonical_signature, None) + namespace.pop(FunctionContractAttribute.raw_runtime_signature, None) namespace[FunctionContractAttribute.runtime_context_parameter] = parameter_name return func return decorator -@lru_cache(maxsize=256) def resolved_callable_type_hints(func: Callable) -> dict[str, Any]: """Return the callable's resolved type contract or propagate its error.""" - return get_type_hints(func) + signature = CallableMetadata.prepared_callable_signature(func) + if signature is None: + return get_type_hints(func) + from typing import _strip_annotations + + return { + **{name: _strip_annotations(parameter.annotation) for name, parameter in signature.parameters.items() + if parameter.annotation is not inspect.Parameter.empty}, + **({} if signature.return_annotation is inspect.Signature.empty else {"return": _strip_annotations(signature.return_annotation)}), + } def annotation_accepts_runtime_type(annotation: object, value_type: type[Any]) -> bool: @@ -125,7 +134,7 @@ def resolved_callable_parameter( ) -> inspect.Parameter: """Return one callable parameter with its runtime type hint resolved.""" - signature = inspect.signature(func) + signature = CallableMetadata.callable_signature(func) parameter = signature.parameters.get(parameter_name) if parameter is None: raise ValueError( @@ -153,7 +162,6 @@ def preserves_full_stack(self, *, image_stack_required: bool) -> bool: self is self.MATCH_IMAGE_STACK and image_stack_required ) - def invocation_kwargs( self, kwargs: Mapping[str, Any], @@ -482,7 +490,7 @@ def special_input_parameters_from_callable( """Return special-input parameters in their canonical signature order.""" declared_names = special_input_names_from_callable(func) - signature = inspect.signature(func) + signature = CallableMetadata.callable_signature(func) missing = tuple(name for name in declared_names if name not in signature.parameters) if missing: raise ValueError( diff --git a/openhcs/core/pipeline/path_planner.py b/openhcs/core/pipeline/path_planner.py index 3a1f469928..85bd258ae3 100644 --- a/openhcs/core/pipeline/path_planner.py +++ b/openhcs/core/pipeline/path_planner.py @@ -35,6 +35,7 @@ FunctionPatternSyntax, InvocationArtifactInputEdgePlan, InvocationArtifactInputProjectionKey, + MainFlowInputProjection, RuntimeParameterBinding, compile_function_pattern, inject_artifact_input_values, @@ -70,9 +71,6 @@ CompilationPlateScope, CompilationSession, ) -from openhcs.core.pipeline.step_snapshot import ( - StepSnapshot, -) from openhcs.core.source_bindings import ( CompiledSourceBindingPlan, CompiledSourceUniversePlan, @@ -84,6 +82,7 @@ StepInputDependency, StepInputDependencyKind, ) +from openhcs.core.steps.abstract import AbstractStep from openhcs.core.steps.function_step import FunctionStep logger = logging.getLogger(__name__) @@ -214,11 +213,11 @@ def scope_for_group_by( def output_after( self, - snapshot: StepSnapshot, + step: AbstractStep, execution_scope: PathPlannerGroupScope, compiled_pattern: CompiledFunctionPattern | None, ) -> "PathPlannerComponentScopes": - if not isinstance(snapshot.step, FunctionStep): + if not isinstance(step, FunctionStep): return self if compiled_pattern is None: raise TypeError( @@ -229,15 +228,13 @@ def output_after( return self scopes = dict(self.scopes) - variable_components = tuple( - snapshot.step.processing_config.variable_components or () - ) + variable_components = tuple(step.processing_config.variable_components or ()) for component in variable_components: scopes.pop(component, None) if compiled_pattern.collapses_input_plane_axis(): scopes[component] = PathPlannerGroupScope.ungrouped() - group_by = PathPlannerExecutionGroups.normalized_group_by(snapshot) + group_by = PathPlannerExecutionGroups.normalized_group_by(step) group_by_component = self.component_from_group_by(group_by) if ( group_by_component is not None @@ -295,24 +292,24 @@ def context_producer_scope( def get_execution_groups( self, - snapshot: StepSnapshot, + step: AbstractStep, input_component_scopes: PathPlannerComponentScopes | None = None, *, source_bindings: StepSourceBindingsConfig | None = None, contracts: Sequence[CallableContract] = (), ) -> PathPlannerGroupScope: """Determine which component groups this step will execute for.""" - if not isinstance(snapshot.step, FunctionStep): + if not isinstance(step, FunctionStep): return PathPlannerGroupScope.ungrouped() - func_pattern = snapshot.step.func - group_by = self.normalized_group_by(snapshot) - if isinstance(func_pattern, dict): + func_pattern = normalize_function_pattern(step.func) + group_by = self.normalized_group_by(step) + if func_pattern.is_grouped: scope = PathPlannerGroupScope.from_raw( - func_pattern.keys(), + func_pattern.source_group_keys, component=self.execution_component_for_dict_pattern( group_by, - snapshot.step.name, + step.name, ), ) logger.debug("Dict function pattern groups: %s", scope.keys) @@ -328,46 +325,42 @@ def get_execution_groups( ) if artifact_owned: source_bindings = ( - self.planner.source_bindings_for_snapshot(snapshot) - if source_bindings is None - else source_bindings + step.source_bindings if source_bindings is None else source_bindings ).for_artifact_refs( - spec.ref() - for contract in contracts - for spec in contract.group_scope_inputs + spec.ref() for contract in contracts for spec in contract.group_scope_inputs ) scope = component_scopes.scope_for_group_by( group_by, ) if scope is None: source_scope = self.source_binding_scope_for_group_by( - snapshot, + step, group_by, source_bindings=source_bindings, ) scope = ( - self.dynamic_execution_scope_for_group_by(snapshot, group_by) + self.dynamic_execution_scope_for_group_by(step, group_by) if source_scope.is_ungrouped else source_scope ) if artifact_owned: scope = self.artifact_owned_execution_scope( - snapshot, + step, contracts, consumer_scope=scope, ) logger.debug( "Artifact-managed FunctionStep groups for %s: %s", - snapshot.step.name, + step.name, scope.keys, ) return scope - logger.debug("FunctionStep groups for %s: %s", snapshot.step.name, scope.keys) + logger.debug("FunctionStep groups for %s: %s", step.name, scope.keys) return scope def artifact_owned_execution_scope( self, - snapshot: StepSnapshot, + step: AbstractStep, contracts: Sequence[CallableContract], *, consumer_scope: PathPlannerGroupScope, @@ -381,13 +374,13 @@ def artifact_owned_execution_scope( ) if not owner_specs: raise ValueError( - f"Artifact-owned FunctionStep {snapshot.step.name!r} declares no " + f"Artifact-owned FunctionStep {step.name!r} declares no " "artifact group-scope owner." ) available_artifacts = self.planner.artifact_context.available_artifacts - contract_source_bindings = self.planner.source_bindings_for_snapshot(snapshot) - group_by = self.normalized_group_by(snapshot) + contract_source_bindings = step.source_bindings + group_by = self.normalized_group_by(step) group_component = PathPlannerComponentScopes.component_from_group_by(group_by) normalized_group_component = ( None @@ -420,8 +413,7 @@ def artifact_owned_execution_scope( continue has_source_lineage = ( - contract_source_bindings.binding_for_artifact_ref(spec.ref()) - is not None + contract_source_bindings.binding_for_artifact_ref(spec.ref()) is not None or available_artifacts.by_name_and_artifact_type( spec.name, spec.artifact_type, @@ -435,7 +427,7 @@ def artifact_owned_execution_scope( continue if group_by is not GroupBy.NONE: raise ValueError( - f"Artifact-owned FunctionStep {snapshot.step.name!r} cannot " + f"Artifact-owned FunctionStep {step.name!r} cannot " f"resolve group scope for {spec.ref()!r}." ) scopes.append(PathPlannerGroupScope.ungrouped()) @@ -463,7 +455,7 @@ def artifact_owned_execution_scope( ) if source_scope.is_ungrouped and group_by is not GroupBy.NONE: raise ValueError( - f"Artifact-owned FunctionStep {snapshot.step.name!r} cannot " + f"Artifact-owned FunctionStep {step.name!r} cannot " f"resolve group scope for {spec.ref()!r}." ) scopes.append(source_scope) @@ -472,7 +464,7 @@ def artifact_owned_execution_scope( return consumer_scope consumer_variable_components = ComponentSet.from_enum_values( - snapshot.step.processing_config.variable_components or () + step.processing_config.variable_components or () ) projected_scopes = tuple( scope.output_lineage_scope( @@ -484,26 +476,23 @@ def artifact_owned_execution_scope( execution_scope = PathPlannerGroupScope.union_compatible(projected_scopes) if execution_scope is None: raise ValueError( - f"Artifact-owned FunctionStep {snapshot.step.name!r} has " + f"Artifact-owned FunctionStep {step.name!r} has " f"incompatible declared owner scopes {projected_scopes!r}." ) return execution_scope def dynamic_execution_scope_for_group_by( self, - snapshot: StepSnapshot, + step: AbstractStep, group_by: GroupBy | None, ) -> PathPlannerGroupScope: """Return a typed runtime-discovered scope for a concrete group axis.""" - group_by_component = PathPlannerComponentScopes.component_from_group_by( - group_by - ) + group_by_component = PathPlannerComponentScopes.component_from_group_by(group_by) if group_by_component is None: return PathPlannerGroupScope.ungrouped() source_keys = ( tuple(self.planner.orchestrator.get_component_keys(group_by_component)) - if snapshot.step.processing_config.input_source - is InputSource.PIPELINE_START + if step.processing_config.input_source is InputSource.PIPELINE_START else () ) if source_keys: @@ -517,20 +506,18 @@ def dynamic_execution_scope_for_group_by( def source_binding_scope_for_group_by( self, - snapshot: StepSnapshot, + step: AbstractStep, group_by: GroupBy | None, *, source_bindings: StepSourceBindingsConfig | None = None, ) -> PathPlannerGroupScope: """Derive execution groups declared by source-binding component identity.""" - group_by_component = PathPlannerComponentScopes.component_from_group_by( - group_by - ) + group_by_component = PathPlannerComponentScopes.component_from_group_by(group_by) if group_by_component is None: return PathPlannerGroupScope.ungrouped() if source_bindings is None: - source_bindings = self.planner.source_bindings_for_snapshot(snapshot) + source_bindings = step.source_bindings if not source_bindings.binding_declarations: return PathPlannerGroupScope.ungrouped() component = ComponentSet.coerce_component(group_by_component) @@ -558,17 +545,17 @@ def execution_component_for_dict_pattern( return AllComponents.from_value(group_by.value) @staticmethod - def normalized_group_by(snapshot: StepSnapshot) -> GroupBy: + def normalized_group_by(step: AbstractStep) -> GroupBy: """Use the same group_by normalization as compiled execution plans.""" from openhcs.core.pipeline.funcstep_contract_validator import ( FuncStepContractValidator, ) return FuncStepContractValidator.normalized_group_by( - snapshot.step.processing_config.group_by, - snapshot.step.processing_config.variable_components, - snapshot.step.name, - normalize_function_pattern(snapshot.step.func), + step.processing_config.group_by, + step.processing_config.variable_components, + step.name, + normalize_function_pattern(step.func), ) @@ -609,7 +596,8 @@ class PathPlannerArtifactStage(PathPlannerMetadataArtifactInjection): def prepare_step_declarations( self, - snapshot: StepSnapshot, + step: AbstractStep, + step_index: int, ) -> tuple[ ArtifactGraph, FunctionPatternSyntax | None, @@ -617,7 +605,7 @@ def prepare_step_declarations( tuple[CallableContract, ...], ]: """Normalize a step's function pattern and collect artifact declarations.""" - if not isinstance(snapshot.step, FunctionStep): + if not isinstance(step, FunctionStep): return ( ArtifactGraph.empty(), None, @@ -625,19 +613,22 @@ def prepare_step_declarations( (), ) - func_pattern = strip_disabled_functions(snapshot.step.func) - source_bindings = self.planner.source_bindings_for_snapshot(snapshot) + func_pattern = normalize_function_pattern( + strip_disabled_functions(step.func) or [] + ) + source_bindings = step.source_bindings declaration_context = self.artifact_declaration_context( - snapshot, + step, + step_index, source_bindings=source_bindings, ) contracts = resolve_function_pattern_contracts( - self.declaration_pattern(func_pattern), + func_pattern, self.planner.invocation_contract_provider, declaration_context, ) declarations = extract_artifact_declarations( - self.declaration_pattern(func_pattern), + func_pattern, declaration_provider=self.planner.declaration_provider, invocation_contract_provider=self.planner.invocation_contract_provider, step_context=declaration_context, @@ -652,25 +643,22 @@ def prepare_step_declarations( def source_bindings_for_contracts( self, - snapshot: StepSnapshot, + step: AbstractStep, contracts: Iterable[CallableContract], main_input_dependency: StepInputDependency, ) -> StepSourceBindingsConfig: """Project bindings to implicit main flow and exact public source inputs.""" contracts = tuple(contracts) - source_bindings = self.planner.source_bindings_for_snapshot(snapshot) + source_bindings = step.source_bindings available_artifacts = self.planner.artifact_context.available_artifacts implicit_main_flow_specs = ( tuple( - binding.input_spec() - for binding in source_bindings.primary_plane_bindings + binding.input_spec() for binding in source_bindings.primary_plane_bindings ) if ( main_input_dependency.kind is StepInputDependencyKind.PIPELINE_START - and any( - contract.accepts_implicit_main_flow_input for contract in contracts - ) + and any(contract.accepts_implicit_main_flow_input for contract in contracts) ) else () ) @@ -683,8 +671,7 @@ def source_bindings_for_contracts( for contract in contracts for spec in contract.artifact_inputs if ( - source_bindings.binding_for_artifact_ref(spec.ref()) - is not None + source_bindings.binding_for_artifact_ref(spec.ref()) is not None or available_artifacts.by_name_and_artifact_type( spec.name, spec.artifact_type, @@ -736,7 +723,7 @@ def source_binding_component_domains( def compile_source_plans( self, - snapshot: StepSnapshot, + step: AbstractStep, source_bindings: StepSourceBindingsConfig, ) -> tuple[CompiledSourceBindingPlan, CompiledSourceUniversePlan]: """Freeze invocation-scoped source declarations into runtime plans.""" @@ -746,34 +733,13 @@ def compile_source_plans( else: binding_plan = CompiledSourceBindingPlan.from_config( source_bindings, - realized_source_metadata=( - self.planner.session.realized_source_metadata - ), + realized_source_metadata=(self.planner.session.realized_source_metadata), ) return ( binding_plan, CompiledSourceUniversePlan.from_source_binding_plan(binding_plan), ) - @staticmethod - def declaration_pattern( - func_pattern: FunctionPatternSyntax | None, - ) -> FunctionPatternSyntax: - """Return the declaration-time pattern, with disabled-only steps empty.""" - if func_pattern is None: - return [] - return func_pattern - - @classmethod - def stripped_declaration_pattern( - cls, - func_pattern: FunctionPatternSyntax | None, - ) -> FunctionPatternSyntax: - """Return declaration pattern after disabled functions are removed.""" - if func_pattern is None: - return [] - return cls.declaration_pattern(strip_disabled_functions(func_pattern)) - def namespace_grouped_outputs_for_runtime_consumers( self, func_pattern: FunctionPatternSyntax | None, @@ -783,9 +749,9 @@ def namespace_grouped_outputs_for_runtime_consumers( """Namespace grouped outputs by the step execution groups.""" output_refs = tuple(declarations.outputs) if ( - isinstance(func_pattern, dict) + not output_refs or group_scope.is_ungrouped - or not output_refs + or normalize_function_pattern(func_pattern).is_grouped ): return declarations @@ -795,7 +761,7 @@ def namespace_grouped_outputs_for_runtime_consumers( def compile_plan_maps( self, - snapshot: StepSnapshot, + step: AbstractStep, step_index: int, declarations: ArtifactGraph, group_scope: PathPlannerGroupScope, @@ -803,14 +769,14 @@ def compile_plan_maps( source_bindings: StepSourceBindingsConfig = EMPTY_SOURCE_BINDINGS, ) -> ArtifactPlanMaps: """Compile artifact declarations into runtime I/O maps.""" - step_name = snapshot.step.name - group_by = PathPlannerExecutionGroups.normalized_group_by(snapshot) + step_name = step.name + group_by = PathPlannerExecutionGroups.normalized_group_by(step) source_binding_plan, source_universe_plan = self.compile_source_plans( - snapshot, + step, source_bindings, ) consumer_variable_components = ComponentSet.from_enum_values( - snapshot.step.processing_config.variable_components or () + step.processing_config.variable_components or () ) artifact_inputs = self.process_artifact_inputs( declarations, @@ -1158,7 +1124,8 @@ def relation_source_scopes_by_ref( def build_step_compiled_function_pattern( self, - snapshot: StepSnapshot, + step: AbstractStep, + step_index: int, is_function_step: bool, func_pattern: FunctionPatternSyntax | None, artifact_inputs: Mapping[ArtifactSpecRef, ArtifactInputPlan], @@ -1173,7 +1140,7 @@ def build_step_compiled_function_pattern( if not is_function_step or not func_pattern: return None - step_context = self.artifact_declaration_context(snapshot) + step_context = self.artifact_declaration_context(step, step_index) contracts = resolve_function_pattern_contracts( func_pattern, self.planner.invocation_contract_provider, @@ -1185,11 +1152,11 @@ def build_step_compiled_function_pattern( prior = config_parameters.setdefault(parameter.name, parameter) if prior.annotation is not parameter.annotation: raise TypeError( - f"FunctionStep {snapshot.step.name!r} callable pattern " + f"FunctionStep {step.name!r} callable pattern " f"declares incompatible config parameter {parameter.name!r}: " f"{prior.annotation!r} and {parameter.annotation!r}." ) - step_values = vars(snapshot.step) + step_values = vars(step) pipeline_values = vars(self.planner.session.global_config) runtime_parameter_bindings: list[RuntimeParameterBinding] = [] for parameter_name, parameter in config_parameters.items(): @@ -1203,7 +1170,7 @@ def build_step_compiled_function_pattern( ) if not isinstance(provider, parameter_type): raise TypeError( - f"FunctionStep {snapshot.step.name!r} config parameter " + f"FunctionStep {step.name!r} config parameter " f"{parameter_name!r} requires {parameter_type.__name__}, got " f"{type(provider).__name__}." ) @@ -1233,7 +1200,7 @@ def build_step_compiled_function_pattern( relation_source_scopes=relation_source_scopes, execution_group_scope=execution_group_scope, consumer_variable_components=ComponentSet.from_enum_values( - snapshot.step.processing_config.variable_components or () + step.processing_config.variable_components or () ), source_bindings=step_context.source_bindings, available_artifacts=available_artifacts, @@ -1259,14 +1226,10 @@ def compile_invocation_input_edges( ) -> CompiledFunctionPattern: """Compile exact invocation-to-input projections from nominal contracts.""" - main_flow_refs = main_flow_artifacts.ref_set() groups: list[CompiledFunctionGroup] = [] for group in compiled_pattern.groups: invocations: list[CompiledFunctionInvocation] = [] for invocation in group.invocations: - relation_owned_main_flow_refs = main_flow_refs.intersection( - invocation.contract.output_group_scope_sources - ) if compiled_pattern.is_grouped: if execution_group_scope.is_ungrouped: raise ValueError( @@ -1298,17 +1261,24 @@ def compile_invocation_input_edges( len(invocation.contract.artifact_inputs), ) selected_plans_by_ref = {plan.ref(): plan for plan in selected_plans} + adapter = invocation.contract.runtime_adapter + owns_artifact_inputs = ( + adapter is not None and adapter.manages_artifact_inputs + ) + raw_main_flow_refs = ( + main_flow_artifacts.ref_set() + .intersection(invocation.contract.output_group_scope_sources) + if not owns_artifact_inputs + else frozenset() + ) edges: list[InvocationArtifactInputEdgePlan] = [] for input_edge_key, input_spec in zip( input_edge_keys, invocation.contract.artifact_inputs, strict=True, ): - # A declared lineage source already travels in the primary - # payload; its producer storage is not a second ABI argument. storage_plan = ( - None - if input_spec.ref() in relation_owned_main_flow_refs + None if input_spec.ref() in raw_main_flow_refs else selected_plans_by_ref.get(input_spec.ref()) ) if storage_plan is None: @@ -1334,7 +1304,11 @@ def compile_invocation_input_edges( consumer_variable_components=consumer_variable_components, source_bindings=source_bindings, available_artifacts=available_artifacts, - consumes_main_flow=False, + main_flow_projection=InvocationArtifactInputEdgePlan.source_projection( + input_spec, + main_flow_artifacts, + invocation.contract.group_scope_inputs, + ) if owns_artifact_inputs else None, ) ) invocations.append(invocation.with_artifact_input_edges(tuple(edges))) @@ -1356,7 +1330,7 @@ def invocation_input_edge( consumer_variable_components: ComponentSet, source_bindings: StepSourceBindingsConfig, available_artifacts: ArtifactSpecCollection, - consumes_main_flow: bool, + main_flow_projection: MainFlowInputProjection | None, ) -> InvocationArtifactInputEdgePlan: """Compile one exact relation-owned invocation input edge.""" @@ -1381,7 +1355,7 @@ def invocation_input_edge( spec=input_spec, storage_plan=storage_plan, projection=projection, - consumes_main_flow=consumes_main_flow, + main_flow_projection=main_flow_projection, ) relation_scopes = tuple( @@ -1439,7 +1413,7 @@ def invocation_input_edge( spec=input_spec, storage_plan=storage_plan, projection=projection, - consumes_main_flow=consumes_main_flow, + main_flow_projection=main_flow_projection, ) @staticmethod @@ -1528,23 +1502,24 @@ def exact_component_scopes( def artifact_declaration_context( self, - snapshot: StepSnapshot, + step: AbstractStep, + step_index: int, *, source_bindings: StepSourceBindingsConfig | None = None, ) -> ArtifactDeclarationStepContext: """Return compile-time context for invocation artifact providers.""" if source_bindings is None: - source_bindings = self.planner.source_bindings_for_snapshot(snapshot) + source_bindings = step.source_bindings return replace( self.planner.artifact_context, - step_name=snapshot.step.name, - step_index=snapshot.index, + step_name=step.name, + step_index=step_index, ).with_source_binding_scope( source_bindings=source_bindings, - group_by=PathPlannerExecutionGroups.normalized_group_by(snapshot), - input_source=snapshot.step.processing_config.input_source, + group_by=PathPlannerExecutionGroups.normalized_group_by(step), + input_source=step.processing_config.input_source, source_groups=self.planner.execution_groups.dynamic_execution_scope_for_group_by( - snapshot, PathPlannerExecutionGroups.normalized_group_by(snapshot) + step, PathPlannerExecutionGroups.normalized_group_by(step) ).keys, ) @@ -2010,23 +1985,22 @@ class PathPlannerMaterializationStage: def materialized_output_dir_for_step( self, - snapshot: StepSnapshot, + step: AbstractStep, + step_index: int, ) -> Optional[Path]: """Resolve optional per-step materialization output directory.""" - materialization_config = snapshot.step.step_materialization_config + materialization_config = step.step_materialization_config if not materialization_config or not materialization_config.enabled: return None step_axis_filters = self.planner.ctx.step_axis_filters.get( - snapshot.index, + step_index, StepAxisFilterSet.empty(), ) - if not step_axis_filters.allows( - materialization_config, self.planner.ctx.axis_id - ): + if not step_axis_filters.allows(materialization_config, self.planner.ctx.axis_id): logger.debug( "Skipping materialization for step %s, axis %s (filtered out)", - snapshot.step.name, + step.name, self.planner.ctx.axis_id, ) return None @@ -2056,7 +2030,7 @@ def input_conversion_plan_for_step( def apply_materialization_plan( self, - snapshot: StepSnapshot, + step: AbstractStep, step_index: int, materialized_output_dir: Optional[Path], ) -> None: @@ -2064,7 +2038,7 @@ def apply_materialization_plan( if not materialized_output_dir: return - materialization_config = snapshot.step.step_materialization_config + materialization_config = step.step_materialization_config materialized_plate_root = self.planner.paths.build_output_plate_root( self.planner.plate_path, materialization_config, @@ -2102,7 +2076,7 @@ class PathPlannerValidationStage: def validate(self) -> None: """Validate connectivity and materialization paths.""" for i in range(1, self.planner.session.step_count): - curr = self.planner.session.snapshot(i) + curr = self.planner.session.pipeline.steps[i] dependency = self.planner.plans[i].main_input_dependency if dependency.kind in ( StepInputDependencyKind.NO_MAIN_FLOW, @@ -2110,13 +2084,11 @@ def validate(self) -> None: ): continue if dependency.kind is not StepInputDependencyKind.STEP_OUTPUT: - raise ValueError( - f"Step {curr.step.name} has unresolved main input dependency." - ) + raise ValueError(f"Step {curr.name} has unresolved main input dependency.") source_step_index = dependency.source_step_index if source_step_index is None: raise ValueError( - f"Step {curr.step.name} main input dependency is missing source_step_index." + f"Step {curr.name} main input dependency is missing source_step_index." ) curr_in = self.planner.plans[i].input_dir source_out = self.planner.plans[source_step_index].output_dir @@ -2127,10 +2099,10 @@ def validate(self) -> None: for inp in self.planner.plans[i].artifact_inputs.values() ) if not has_artifact_bridge: - producer_name = self.planner.session.snapshot( + producer_name = self.planner.session.pipeline.steps[ source_step_index - ).step.name - raise ValueError(f"Disconnect: {producer_name} -> {curr.step.name}") + ].name + raise ValueError(f"Disconnect: {producer_name} -> {curr.name}") self.validate_materialization_paths() @@ -2140,39 +2112,36 @@ def validate_materialization_paths(self) -> None: mat_steps = [ ( - snapshot, + step, self.planner.plans[i].pipeline_position or i, - self.planner.paths.build_output_path( - snapshot.step.step_materialization_config - ), + self.planner.paths.build_output_path(step.step_materialization_config), ) - for i, snapshot in self.planner.session.indexed_snapshots() - if snapshot.step.step_materialization_config - and snapshot.step.step_materialization_config.enabled + for i, step in enumerate(self.planner.session.pipeline.steps) + if step.step_materialization_config and step.step_materialization_config.enabled ] path_groups = defaultdict(list) - for snapshot, pos, path in mat_steps: + for step, pos, path in mat_steps: if path == global_path: - self.resolve_and_update_paths(snapshot, pos, path, "main flow") + self.resolve_and_update_paths(step, pos, path, "main flow") else: - path_groups[str(path)].append((snapshot, pos, path)) + path_groups[str(path)].append((step, pos, path)) for path_key, step_list in path_groups.items(): if len(step_list) > 1: - for snapshot, pos, path in step_list: - self.resolve_and_update_paths(snapshot, pos, path, f"pos {pos}") + for step, pos, path in step_list: + self.resolve_and_update_paths(step, pos, path, f"pos {pos}") def resolve_and_update_paths( self, - snapshot: StepSnapshot, + step: AbstractStep, position: int, original_path: Path, conflict_type: str, ) -> None: """Resolve path conflict by updating the compiled plan only.""" del original_path, conflict_type - materialization_config = snapshot.step.step_materialization_config + materialization_config = step.step_materialization_config original_sub_dir = materialization_config.sub_dir new_sub_dir = f"{original_sub_dir}_step{position}" @@ -2337,14 +2306,12 @@ def prime_future_artifact_inputs(self) -> None: set() for _ in range(self.planner.session.step_count) ] - for i in self.planner.session.reverse_snapshot_indices(): + for i in range(self.planner.session.step_count - 1, -1, -1): self.planner.future_artifact_inputs[i] = set(future_inputs) - snapshot = self.planner.session.snapshot(i) - if isinstance(snapshot.step, FunctionStep): - pattern = self.planner.artifacts.stripped_declaration_pattern( - snapshot.step.func - ) + step = self.planner.session.pipeline.steps[i] + if isinstance(step, FunctionStep): + pattern = step.func declarations = extract_artifact_declarations( pattern, declaration_provider=self.planner.declaration_provider, @@ -2352,7 +2319,7 @@ def prime_future_artifact_inputs(self) -> None: self.planner.invocation_contract_provider ), step_context=self.planner.artifacts.artifact_declaration_context( - snapshot + step, i ), ) step_inputs = { @@ -2367,27 +2334,30 @@ def prime_future_artifact_inputs(self) -> None: future_inputs.update(step_inputs) - def plan_step(self, snapshot: StepSnapshot, step_index: int) -> None: + def plan_step(self, step: AbstractStep, step_index: int) -> None: """Plan one step's directories, artifacts, and executable pattern.""" - self.planner.plans[step_index].step_scope_id = snapshot.scope_id - self.planner.artifact_context = ( - self.planner.artifacts.artifact_declaration_context(snapshot) + self.planner.plans[step_index].step_scope_id = ( + self.planner.session.pipeline.step_state_map[step_index].scope_id + ) + self.planner.artifact_context = self.planner.artifacts.artifact_declaration_context( + step, step_index ) declarations, func_pattern, execution_scope, contracts = ( self.planner.artifacts.prepare_step_declarations( - snapshot, + step, + step_index, ) ) - resolved_source_bindings = self.planner.source_bindings_for_snapshot(snapshot) + resolved_source_bindings = step.source_bindings main_input_dependency = self.main_input_dependency( - snapshot, + step, step_index, declarations=declarations, execution_scope=execution_scope, source_bindings=resolved_source_bindings, ) contract_source_bindings = self.planner.artifacts.source_bindings_for_contracts( - snapshot, + step, contracts, main_input_dependency, ) @@ -2405,7 +2375,7 @@ def plan_step(self, snapshot: StepSnapshot, step_index: int) -> None: PathPlannerGroupScope.ungrouped() if execution_scope is FunctionStepExecutionScope.PLATE else self.planner.execution_groups.get_execution_groups( - snapshot, + step, input_component_scopes, source_bindings=execution_source_bindings, contracts=contracts, @@ -2419,7 +2389,7 @@ def plan_step(self, snapshot: StepSnapshot, step_index: int) -> None: ) ) artifact_maps = self.planner.artifacts.compile_plan_maps( - snapshot, + step, step_index, declarations, group_scope, @@ -2427,7 +2397,7 @@ def plan_step(self, snapshot: StepSnapshot, step_index: int) -> None: contract_source_bindings, ) - if isinstance(snapshot.step, FunctionStep): + if isinstance(step, FunctionStep): func_pattern = self.planner.artifacts.inject_metadata( func_pattern, declarations.inputs, @@ -2435,8 +2405,9 @@ def plan_step(self, snapshot: StepSnapshot, step_index: int) -> None: self.planner.plans[step_index].func = func_pattern compiled_pattern = self.planner.artifacts.build_step_compiled_function_pattern( - snapshot, - isinstance(snapshot.step, FunctionStep), + step, + step_index, + isinstance(step, FunctionStep), func_pattern, artifact_maps.inputs, artifact_maps.outputs, @@ -2451,7 +2422,7 @@ def plan_step(self, snapshot: StepSnapshot, step_index: int) -> None: ) ) self.update_core_step_plan( - snapshot, + step, step_index, main_input_dependency, input_dir, @@ -2460,9 +2431,9 @@ def plan_step(self, snapshot: StepSnapshot, step_index: int) -> None: compiled_pattern, ) self.planner.materialization.apply_materialization_plan( - snapshot, + step, step_index, - self.planner.materialization.materialized_output_dir_for_step(snapshot), + self.planner.materialization.materialized_output_dir_for_step(step, step_index), ) self.planner.materialization.apply_input_conversion_plan( step_index, @@ -2473,7 +2444,7 @@ def plan_step(self, snapshot: StepSnapshot, step_index: int) -> None: ) self.planner.main_flow_component_scopes[step_index] = ( input_component_scopes.output_after( - snapshot, + step, artifact_maps.group_scope, compiled_pattern, ) @@ -2496,7 +2467,7 @@ def input_component_scopes( def update_core_step_plan( self, - snapshot: StepSnapshot, + step: AbstractStep, step_index: int, main_input_dependency: StepInputDependency, input_dir: Path, @@ -2511,15 +2482,14 @@ def update_core_step_plan( is_per_step_materialization=False, ) step_plan = self.planner.plans[step_index] - step_plan.step_scope_id = snapshot.scope_id step_plan.input_dir = input_dir step_plan.output_dir = output_dir step_plan.output_plate_root = str(main_plate_root) step_plan.sub_dir = self.planner.cfg.sub_dir step_plan.analysis_results_dir = str(self.planner.paths.results_path()) step_plan.pipeline_position = step_index - step_plan.input_source = self.input_source(snapshot) - step_plan.group_by = PathPlannerExecutionGroups.normalized_group_by(snapshot) + step_plan.input_source = self.input_source(step) + step_plan.group_by = PathPlannerExecutionGroups.normalized_group_by(step) step_plan.main_input_dependency = main_input_dependency step_plan.artifact_inputs = artifact_maps.inputs step_plan.artifact_outputs = artifact_maps.outputs @@ -2530,7 +2500,7 @@ def update_core_step_plan( def main_input_dependency( self, - snapshot: StepSnapshot, + step: AbstractStep, step_index: int, *, declarations: ArtifactGraph = ArtifactGraph(), @@ -2539,22 +2509,18 @@ def main_input_dependency( ) -> StepInputDependency: """Resolve the explicit main-input edge for one step.""" existing_plan = self.planner.plans.get(step_index) - if ( - existing_plan is not None - and existing_plan.main_input_dependency.is_resolved - ): + if existing_plan is not None and existing_plan.main_input_dependency.is_resolved: return existing_plan.main_input_dependency if ( - isinstance(snapshot.step, FunctionStep) + isinstance(step, FunctionStep) and execution_scope is FunctionStepExecutionScope.PLATE ): return StepInputDependency.no_main_flow() if ( step_index == 0 - or snapshot.step.processing_config.input_source - == InputSource.PIPELINE_START + or step.processing_config.input_source == InputSource.PIPELINE_START ): return StepInputDependency.pipeline_start() @@ -2601,7 +2567,7 @@ def main_input_dependency( raise MissingArtifactInputError( step_id=step_index, artifact_key=producer_ref.name, - step_name=snapshot.step.name, + step_name=step.name, ) if len(candidate_indices) > 1: raise ValueError( @@ -2613,14 +2579,14 @@ def main_input_dependency( producer_step_indices = tuple(dict.fromkeys(producer_step_indices)) if len(producer_step_indices) > 1: raise ValueError( - f"Step {snapshot.step.name!r} declares main-flow inputs from multiple " + f"Step {step.name!r} declares main-flow inputs from multiple " f"producer steps {producer_step_indices!r}: {main_input_specs!r}." ) if producer_step_indices: producer_index = producer_step_indices[0] if not isinstance(producer_index, int): raise TypeError( - f"Main-flow artifact producer for step {snapshot.step.name!r} has " + f"Main-flow artifact producer for step {step.name!r} has " f"non-integer step identity {producer_index!r}." ) producer_scope_id = self.planner.plans[producer_index].step_scope_id @@ -2637,10 +2603,7 @@ def main_input_dependency( producer_index = step_index - 1 producer_plan = self.planner.plans[producer_index] compiled_pattern = producer_plan.compiled_function_pattern - if ( - compiled_pattern is not None - and compiled_pattern.preserves_input_main_flow() - ): + if compiled_pattern is not None and compiled_pattern.preserves_input_main_flow(): if not producer_plan.main_input_dependency.is_resolved: raise RuntimeError( f"Main-flow-preserving step {producer_index} has no resolved " @@ -2648,7 +2611,7 @@ def main_input_dependency( ) return producer_plan.main_input_dependency - producer_scope_id = self.planner.session.snapshot(producer_index).scope_id + producer_scope_id = self.planner.plans[producer_index].step_scope_id return StepInputDependency.step_output( source_step_index=producer_index, source_step_scope_id=producer_scope_id, @@ -2692,9 +2655,9 @@ def step_io_dirs( return input_dir, output_dir @staticmethod - def input_source(snapshot: StepSnapshot) -> str: + def input_source(step: AbstractStep) -> str: """Get input source string.""" - if snapshot.step.processing_config.input_source == InputSource.PIPELINE_START: + if step.processing_config.input_source == InputSource.PIPELINE_START: return "PIPELINE_START" return "PREVIOUS_STEP" @@ -2741,18 +2704,11 @@ def __init__( self.plate_scope = CompilationPlateScope.from_context(self.ctx) self.plate_path = self.plate_scope.path - def source_bindings_for_snapshot( - self, - snapshot: StepSnapshot, - ) -> StepSourceBindingsConfig: - """Return the ObjectState-resolved source declarations from the snapshot.""" - return snapshot.step.source_bindings - def plan(self) -> dict[int, CompiledStepPlan]: """Plan all paths with zero duplication.""" self.steps.prime_future_artifact_inputs() - for i, snapshot in self.session.indexed_snapshots(): - self.steps.plan_step(snapshot, i) + for i, step in enumerate(self.session.pipeline.steps): + self.steps.plan_step(step, i) self.validation.validate() diff --git a/openhcs/core/pipeline/step_snapshot.py b/openhcs/core/pipeline/step_snapshot.py deleted file mode 100644 index 621373625d..0000000000 --- a/openhcs/core/pipeline/step_snapshot.py +++ /dev/null @@ -1,44 +0,0 @@ -"""Compiler identity for already-resolved pipeline steps.""" - -from __future__ import annotations - -from dataclasses import dataclass -from typing import TYPE_CHECKING, Mapping, Sequence - -from openhcs.core.steps.abstract import AbstractStep - -if TYPE_CHECKING: - from objectstate import ObjectState - - -@dataclass(frozen=True, slots=True) -class StepSnapshot: - """Bind compiler identity to one already-resolved pipeline step. - - The normal compiler path has already converted ObjectState to a resolved step - object before this snapshot is built. ObjectState contributes only its scope - identity; all step semantics remain owned by the resolved step. - """ - - index: int - scope_id: str - step: AbstractStep - - -def build_step_snapshots( - steps: Sequence[AbstractStep], - step_state_map: Mapping[int, "ObjectState"], -) -> tuple[StepSnapshot, ...]: - """Build compiler snapshots for already-resolved steps.""" - snapshots: list[StepSnapshot] = [] - for index, step in enumerate(steps): - try: - step_state = step_state_map[index] - except KeyError as exc: - raise ValueError( - f"Missing ObjectState for resolved step {index} ({step.name})." - ) from exc - snapshots.append( - StepSnapshot(index=index, scope_id=step_state.scope_id, step=step) - ) - return tuple(snapshots) diff --git a/openhcs/core/progress/__init__.py b/openhcs/core/progress/__init__.py index fda37b2df9..5cf0260176 100644 --- a/openhcs/core/progress/__init__.py +++ b/openhcs/core/progress/__init__.py @@ -8,7 +8,6 @@ - ProgressPhase, ProgressStatus: Type-safe enums - emit(): Emit progress (convenience wrapper) - registry(): Get per-process registry - - ProgressEmitter: Emitter base class - ProgressRegistry: Registry singleton Usage Examples: @@ -35,13 +34,6 @@ def on_progress(execution_id, event): print(f"{event.phase.value}: {event.percent}%") registry().add_listener(on_progress) - - Testing (mock emitter): - from openhcs.core.progress import NoopEmitter, ProgressEvent - - emitter = NoopEmitter() - event = ProgressEvent(...) - emitter.emit(event) """ # Public API - Types @@ -70,15 +62,6 @@ def on_progress(execution_id, event): # Public API - Registry from .registry import registry -# Public API - Emitters -from .emitters import ( - ProgressEmitter, - NoopEmitter, - CallbackEmitter, - ZMQProgressEmitter, - LoggingEmitter, -) - # Public API - Exceptions from .exceptions import ( ProgressError, diff --git a/openhcs/core/progress/emitters.py b/openhcs/core/progress/emitters.py deleted file mode 100644 index 66ecfdef4c..0000000000 --- a/openhcs/core/progress/emitters.py +++ /dev/null @@ -1,167 +0,0 @@ -"""Progress emitter interface and implementations.""" - -import logging -from abc import ABC, abstractmethod -from typing import Callable -import json - -from .types import ProgressEvent - -logger = logging.getLogger(__name__) - - -# ============================================================================= -# ProgressEmitter Interface (ABC) -# ============================================================================= - - -class ProgressEmitter(ABC): - """Abstract base class for progress emitters. - - Follows OpenHCS pattern: explicit ABC with single abstract method. - Emitter implementations decide WHERE progress goes (callback, ZMQ, noop). - - Design: - - ABC enforces implementation (no duck typing) - - Single abstract method (minimal surface area) - - Subclasses handle transport details - """ - - @abstractmethod - def emit(self, event: ProgressEvent) -> None: - """Emit a progress event. - - Args: - event: ProgressEvent to emit - - Raises: - ProgressError: If emission fails - """ - pass - - -# ============================================================================= -# NoopEmitter - For Testing/Disabled Progress -# ============================================================================= - - -class NoopEmitter(ProgressEmitter): - """No-op emitter for testing or disabled progress tracking. - - Does nothing on emit() - useful for: - - Unit tests (no side effects) - - Production runs with progress disabled - - Dry-run modes - """ - - def emit(self, event: ProgressEvent) -> None: - """Do nothing (intentionally no-op).""" - pass - - -# ============================================================================= -# CallbackEmitter - For In-Process Use -# ============================================================================= - - -class CallbackEmitter(ProgressEmitter): - """Callback-based emitter for in-process use. - - Useful when: - - No ZMQ required (same process) - - Direct UI updates needed - - Testing with mock callbacks - """ - - def __init__(self, callback: Callable[[ProgressEvent], None]): - """Initialize with callback. - - Args: - callback: Function to call on each emit - """ - self.callback = callback - - def emit(self, event: ProgressEvent) -> None: - """Call callback with event. - - Wraps in try/except to prevent progress failures from - crashing the pipeline (fail-safe). - """ - try: - self.callback(event) - except Exception as e: - logger.exception(f"Progress callback failed: {e}") - # Don't re-raise - progress failure shouldn't stop pipeline - - -# ============================================================================= -# ZMQProgressEmitter - For Cross-Process Communication -# ============================================================================= - - -class ZMQProgressEmitter(ProgressEmitter): - """ZMQ-based emitter for cross-process communication. - - Serializes ProgressEvent to JSON and sends via ZMQ socket. - Used for worker processes to communicate progress to main process. - """ - - def __init__(self, socket): - """Initialize with ZMQ socket. - - Args: - socket: ZMQ socket (REQ/REP pair) or None - """ - self.socket = socket - - def emit(self, event: ProgressEvent) -> None: - """Emit event via ZMQ socket. - - Serializes to JSON dict for ZMQ transport. - Handles closed socket gracefully (no crash). - - Args: - event: ProgressEvent to emit - """ - if self.socket is None: - logger.debug(f"Progress emit (no socket): {event}") - return - - try: - # Serialize to dict (enums → strings for JSON) - message = event.to_dict() - json_str = json.dumps(message) - self.socket.send_string(json_str) - except Exception as e: - logger.exception(f"ZMQ emit failed: {e}") - # Don't re-raise - progress failure shouldn't stop pipeline - - -# ============================================================================= -# LoggingEmitter - For Debugging -# ============================================================================= - - -class LoggingEmitter(ProgressEmitter): - """Logging emitter for debugging. - - Logs every progress event at INFO level. - Useful for development and troubleshooting. - """ - - def __init__(self, prefix: str = "PROGRESS"): - """Initialize with log prefix. - - Args: - prefix: Prefix for log messages (e.g., "PROGRESS") - """ - self.prefix = prefix - - def emit(self, event: ProgressEvent) -> None: - """Log event at INFO level.""" - logger.info( - f"[{self.prefix}] {event.execution_id} | " - f"{event.phase.value} | {event.status.value} | " - f"{event.step_name} | {event.axis_id} | " - f"{event.percent:.1f}% ({event.completed}/{event.total})" - ) diff --git a/openhcs/core/progress/live_measurements.py b/openhcs/core/progress/live_measurements.py index 45c1f0eacb..0bf8eae861 100644 --- a/openhcs/core/progress/live_measurements.py +++ b/openhcs/core/progress/live_measurements.py @@ -75,7 +75,7 @@ def from_record( if record.key.artifact_type is not MeasurementsArtifactType: return None - table = cast(MeasurementTable, record.value.data) + table = cast(MeasurementTable, record.data) row_preview = _measurement_row_preview( table.rows, row_limit, @@ -271,7 +271,9 @@ def _columnar_row_preview( column_limit: int, ) -> LiveMeasurementRowPreview: columns = tuple(str(column) for column in rows.columns)[:column_limit] - column_values = tuple((column, rows.column_values(column)) for column in columns) + column_values = tuple( + (column, rows.bounded_column_values(column, row_limit)) for column in columns + ) row_count = rows.row_count() return LiveMeasurementRowPreview( rows=tuple( diff --git a/openhcs/core/projected_image_output.py b/openhcs/core/projected_image_output.py index ac05300b6b..0bbbbf3bce 100644 --- a/openhcs/core/projected_image_output.py +++ b/openhcs/core/projected_image_output.py @@ -1,14 +1,43 @@ """Image results that explicitly project their invocation's source identity.""" +from __future__ import annotations + from abc import ABC, abstractmethod from dataclasses import dataclass, replace +import numpy as np +from metaclass_registry import AutoRegisterMeta + +from openhcs.core.aligned_image_payload import ( + AlignedImageStack, + stack_image_payload_context, +) +from openhcs.core.registry_strategies import NominalTypeKeyedStrategyMixin from openhcs.core.runtime_array_values import ( DataBackedRuntimeArrayPayload, RuntimeArrayData, ) -from openhcs.core.runtime_image_values import image_payload_metadata -from openhcs.core.runtime_plane_projection import RuntimePlaneAxisValueProjection +from openhcs.core.runtime_image_values import ( + ImagePayloadMetadataCarrier, + ImagePayloadMetadataCompositionMode, + image_payload_data, + image_payload_metadata, + image_payload_slice_context, +) +from openhcs.core.runtime_object_labels import ( + ObjectLabelValue, + object_label_dense_array, +) +from openhcs.core.runtime_object_label_building import SourceImageObjectLabelBuildRequest +from openhcs.core.runtime_plane_projection import ( + RuntimePlaneAxis, + RuntimePlaneAxisValueProjection, +) +from openhcs.core.runtime_slice_alignment import ( + RuntimeSliceAlignedValueSet, + RuntimeSliceAlignedValues, +) +from openhcs.core.runtime_slice_projection import RuntimeSliceProjection class SourceProjectedImageOutput(DataBackedRuntimeArrayPayload, ABC): @@ -82,3 +111,396 @@ def with_data(self, data: RuntimeArrayData) -> "SelectedPlaneImageOutput": def selected_source_plane_indices(self) -> tuple[int, ...]: """Provide this declaration's exact source-selection proof.""" return self.source_indices + + +class ImageOutputSourceContextStrategy( + NominalTypeKeyedStrategyMixin, + ABC, + metaclass=AutoRegisterMeta, +): + """Registered image-output contextualization by semantic source payload type.""" + + __registry_key__ = "value_type_label" + __skip_if_no_key__ = True + + @classmethod + def for_source_payload( + cls, + source_payload: RuntimeArrayData, + ) -> "ImageOutputSourceContextStrategy": + strategy = cls.for_nominal_value(source_payload) + if strategy is None: + return DefaultImageOutputSourceContextStrategy() + return strategy + + def requires_plane_contextualization( + self, + source_payload: RuntimeArrayData, + output_value: RuntimeArrayData, + plane_projection: RuntimePlaneAxisValueProjection | None, + ) -> bool: + """Return whether this source type must bind an undeclared output axis.""" + + del source_payload, output_value, plane_projection + return False + + @abstractmethod + def contextualize( + self, + source_payload: RuntimeArrayData, + output_value: RuntimeArrayData, + plane_projection: RuntimePlaneAxisValueProjection | None, + ) -> RuntimeArrayData: + """Return image output with source semantics attached.""" + + +class DefaultImageOutputSourceContextStrategy(ImageOutputSourceContextStrategy): + """Attach scalar source-image context to a derived image output.""" + + def contextualize( + self, + source_payload: RuntimeArrayData, + output_value: RuntimeArrayData, + plane_projection: RuntimePlaneAxisValueProjection | None, + ) -> RuntimeArrayData: + if isinstance(output_value, AlignedImageStack): + return output_value + return image_payload_metadata(source_payload).derive_payload( + source_payload, + output_value, + plane_projection=plane_projection, + ) + + +class AlignedImageStackOutputSourceContextStrategy(ImageOutputSourceContextStrategy): + """Preserve aligned multi-source image payloads as their own source context.""" + + value_type = AlignedImageStack + + def contextualize( + self, + source_payload: RuntimeArrayData, + output_value: RuntimeArrayData, + plane_projection: RuntimePlaneAxisValueProjection | None, + ) -> RuntimeArrayData: + del source_payload, plane_projection + return output_value + + +class RuntimeSliceAlignedImageOutputSourceContextStrategy( + ImageOutputSourceContextStrategy +): + """Attach per-runtime-slice source context to derived image outputs.""" + + value_type = RuntimeSliceAlignedValueSet + + def contextualize( + self, + source_payload: RuntimeArrayData, + output_value: RuntimeArrayData, + plane_projection: RuntimePlaneAxisValueProjection | None, + ) -> RuntimeArrayData: + source_values = source_payload + if not isinstance(source_values, RuntimeSliceAlignedValueSet): + raise TypeError( + "Runtime-slice-aligned image output strategy requires " + f"RuntimeSliceAlignedValueSet, got {type(source_values).__name__}." + ) + output_data = image_payload_data(output_value) + if plane_projection is None: + if source_values.slice_count != 1: + raise ValueError( + "Runtime-slice-aligned image output has multiple source values " + "but no declared runtime plane projection." + ) + source_value = source_values.value_for_aligned_slice(0, 1) + return image_payload_metadata(source_value).derive_payload( + source_value, + output_value, + ) + output_slices = self.output_slices( + output_value, + output_data, + source_values, + plane_projection, + ) + contextualized_slices = [] + for slice_index, output_slice in enumerate(output_slices): + source_value = source_values.value_for_aligned_slice( + slice_index, + len(output_slices), + ) + contextualized_slices.append( + image_payload_metadata(source_value).derive_payload( + source_value, + output_slice, + ) + ) + return stack_image_payload_context( + tuple(contextualized_slices), + output_data, + metadata_mode=ImagePayloadMetadataCompositionMode.STACK, + ) + + @staticmethod + def output_slices( + output_value: RuntimeArrayData, + output_data: RuntimeArrayData, + source_values: RuntimeSliceAlignedValueSet, + plane_projection: RuntimePlaneAxisValueProjection, + ) -> tuple[RuntimeArrayData, ...]: + output_array = np.asarray(output_data) + projection = plane_projection + if projection.axis_size != source_values.slice_count: + raise ValueError( + "Runtime-slice image output projection must exactly match its " + f"aligned source count: {projection.axis_size} != " + f"{source_values.slice_count}." + ) + projection.validate_shape( + output_array.shape, + value_name="Runtime-slice-aligned image output", + ) + return tuple( + image_payload_slice_context( + output_value, + output_array[slice_index], + slice_index, + plane_axis=projection.axis, + ) + for slice_index in range(projection.axis_size) + ) + + +class ObjectLabelImageOutputSourceContextStrategy(ImageOutputSourceContextStrategy): + """Project an image rendered from labels onto the invocation plane axis.""" + + value_type = ObjectLabelValue + + def requires_plane_contextualization( + self, + source_payload: RuntimeArrayData, + output_value: RuntimeArrayData, + plane_projection: RuntimePlaneAxisValueProjection | None, + ) -> bool: + """Require projection for a volume label payload, including depth one.""" + + del output_value + if not isinstance(source_payload, ObjectLabelValue): + raise TypeError( + "Object-label image output context requires ObjectLabelValue, got " + f"{type(source_payload).__name__}." + ) + return ( + plane_projection is not None + and plane_projection.plane_index is None + and image_payload_metadata(source_payload).plane_axis is None + and not image_payload_metadata(source_payload).persists_whole_image() + and np.ndim(object_label_dense_array(source_payload)) >= 3 + ) + + def contextualize( + self, + source_payload: RuntimeArrayData, + output_value: RuntimeArrayData, + plane_projection: RuntimePlaneAxisValueProjection | None, + ) -> RuntimeArrayData: + if not isinstance(source_payload, ObjectLabelValue): + raise TypeError( + "Object-label image output context requires ObjectLabelValue, got " + f"{type(source_payload).__name__}." + ) + source_metadata = image_payload_metadata(source_payload) + if source_metadata.persists_whole_image(): + return source_metadata.derive_payload( + source_payload, + output_value, + plane_projection=None, + ) + if plane_projection is None or plane_projection.plane_index is not None: + return source_metadata.derive_payload( + source_payload, + output_value, + plane_projection=plane_projection, + ) + plane_count = source_metadata.source_provenance.source_plane_count + if plane_count != plane_projection.axis_size: + raise ValueError( + "Object-label image output source-plane provenance must match the " + "declared runtime plane axis: " + f"{plane_count} != {plane_projection.axis_size}." + ) + plane_projection.validate_shape( + np.shape(image_payload_data(output_value)), + value_name="Object-label image output payload", + ) + output_metadata = image_payload_metadata(output_value) + contextualized_output = output_metadata.replace_fields( + plane_axis=plane_projection.axis, + ).attach_to(output_value) + return source_metadata.derive_payload( + source_payload, + contextualized_output, + plane_projection=plane_projection, + ) + + +class ObjectLabelOutputValueContextStrategy( + NominalTypeKeyedStrategyMixin, + ABC, + metaclass=AutoRegisterMeta, +): + """Registered object-label output contextualization by nominal value type.""" + + __registry_key__ = "value_type_label" + __skip_if_no_key__ = True + + @classmethod + def for_output_value( + cls, + output_value: RuntimeArrayData | ObjectLabelValue | RuntimeSliceAlignedValueSet, + ) -> "ObjectLabelOutputValueContextStrategy": + return cls.require_nominal_value( + output_value, + context="Object-label function output", + ) + + @abstractmethod + def contextualize( + self, + source_payload: RuntimeArrayData, + output_value: RuntimeArrayData | ObjectLabelValue | RuntimeSliceAlignedValueSet, + plane_projection: RuntimePlaneAxisValueProjection | None, + ) -> RuntimeArrayData | ObjectLabelValue | RuntimeSliceAlignedValueSet: + """Return the output with source-image context attached when possible.""" + + +class RuntimeSliceAlignedObjectLabelOutputValueContextStrategy( + ObjectLabelOutputValueContextStrategy +): + """Contextualize each runtime-slice-aligned object-label output slice.""" + + value_type = RuntimeSliceAlignedValueSet + + def contextualize( + self, + source_payload: RuntimeArrayData, + output_value: RuntimeArrayData | ObjectLabelValue | RuntimeSliceAlignedValueSet, + plane_projection: RuntimePlaneAxisValueProjection | None, + ) -> RuntimeArrayData | ObjectLabelValue | RuntimeSliceAlignedValueSet: + aligned_values = output_value + if not isinstance(aligned_values, RuntimeSliceAlignedValueSet): + raise TypeError( + "Runtime-slice-aligned object-label output strategy requires " + f"RuntimeSliceAlignedValueSet, got {type(aligned_values).__name__}." + ) + if plane_projection is None: + raise ValueError( + "Runtime-slice-aligned object-label output requires a declared " + "runtime plane projection." + ) + if plane_projection.axis is not RuntimePlaneAxis.RUNTIME_SLICE: + raise ValueError( + "Runtime-slice-aligned object-label output requires the " + f"runtime-slice axis, got {plane_projection.axis.value!r}." + ) + if plane_projection.axis_size != aligned_values.slice_count: + raise ValueError( + "Runtime-slice-aligned object-label output count must exactly " + "match the declared runtime plane axis: " + f"{aligned_values.slice_count} != {plane_projection.axis_size}." + ) + return RuntimeSliceAlignedValues( + tuple( + ObjectLabelOutputValueContextStrategy.for_output_value( + aligned_values.value_for_slice(slice_index) + ).contextualize( + RuntimeSliceProjection.value_for_slice( + source_payload, + RuntimePlaneAxisValueProjection.from_selected_plane( + axis=plane_projection.axis, + plane_index=slice_index, + axis_size=plane_projection.axis_size, + ), + ), + aligned_values.value_for_slice(slice_index), + None, + ) + for slice_index in range(aligned_values.slice_count) + ) + ) + + +class ContextualObjectLabelOutputValueContextStrategy( + ObjectLabelOutputValueContextStrategy +): + """Preserve object-label domain while filling missing source-image context.""" + + value_type = ObjectLabelValue + + def contextualize( + self, + source_payload: RuntimeArrayData, + output_value: RuntimeArrayData | ObjectLabelValue | RuntimeSliceAlignedValueSet, + plane_projection: RuntimePlaneAxisValueProjection | None, + ) -> ObjectLabelValue: + del plane_projection + if not isinstance(output_value, ObjectLabelValue): + raise TypeError( + "Contextual object-label output strategy requires " + f"ObjectLabelValue, got {type(output_value).__name__}." + ) + return output_value.with_source_image_context(source_payload) + + +class DenseArrayObjectLabelOutputValueContextStrategy( + ObjectLabelOutputValueContextStrategy +): + """Build declared object labels through the existing source-domain owner.""" + + def contextualize( + self, + source_payload: RuntimeArrayData, + output_value: RuntimeArrayData | ObjectLabelValue | RuntimeSliceAlignedValueSet, + plane_projection: RuntimePlaneAxisValueProjection | None, + ) -> ObjectLabelValue: + return SourceImageObjectLabelBuildRequest( + image=source_payload, + labels=self.label_array(output_value), + plane_projection=plane_projection, + ).payload() + + @abstractmethod + def label_array( + self, + output_value: RuntimeArrayData | ObjectLabelValue | RuntimeSliceAlignedValueSet, + ) -> object: + """Project the dense label data owned by this nominal value case.""" + + +class NumpyArrayObjectLabelOutputValueContextStrategy( + DenseArrayObjectLabelOutputValueContextStrategy +): + """Build object-label context for declared NumPy array outputs.""" + + value_type = np.ndarray + + def label_array( + self, + output_value: RuntimeArrayData | ObjectLabelValue | RuntimeSliceAlignedValueSet, + ) -> object: + return output_value + + +class ImagePayloadObjectLabelOutputValueContextStrategy( + DenseArrayObjectLabelOutputValueContextStrategy +): + """Consume a declared label array with its preserved runtime plane carrier.""" + + value_type = ImagePayloadMetadataCarrier + + def label_array( + self, + output_value: RuntimeArrayData | ObjectLabelValue | RuntimeSliceAlignedValueSet, + ) -> object: + return image_payload_data(output_value) diff --git a/openhcs/core/registry_strategies.py b/openhcs/core/registry_strategies.py index c2776e5b8e..3558578685 100644 --- a/openhcs/core/registry_strategies.py +++ b/openhcs/core/registry_strategies.py @@ -3,7 +3,7 @@ from __future__ import annotations from abc import ABC, abstractmethod -from collections.abc import Mapping, MutableMapping +from collections.abc import Iterable, Mapping, MutableMapping from dataclasses import dataclass, field from enum import Enum from functools import lru_cache @@ -185,10 +185,32 @@ def strategy_types_for_nominal_type( value_type: type[object], ) -> tuple[type[_TypeStrategyT], ...]: """Return registered strategy classes ordered by type MRO specificity.""" + return cls.order_nominal_strategy_members( + value_type, cls.nominal_strategy_members(), + ) + + @classmethod + def nominal_strategy_members( + cls: type[_TypeStrategyT], + ) -> Iterable[ + tuple[type[_TypeStrategyT], type[object] | tuple[type[object], ...] | None] + ]: + """Derive nominal members from the existing registered declarations.""" + for strategy_type in cls.registered_strategy_types(): + yield strategy_type, strategy_type.value_type + + @classmethod + def order_nominal_strategy_members( + cls: type[_TypeStrategyT], + value_type: type[object], + members: Iterable[ + tuple[type[_TypeStrategyT], type[object] | tuple[type[object], ...] | None] + ], + ) -> tuple[type[_TypeStrategyT], ...]: + """Order derived operation members using the family's existing MRO law.""" value_mro = value_type.mro() matches: list[tuple[int, type[_TypeStrategyT]]] = [] - for strategy_type in cls.registered_strategy_types(): - member = strategy_type.value_type + for strategy_type, member in members: if _is_nominal_type_member(member) and issubclass(value_type, member): distance = cls.nominal_type_distance(value_mro, member) matches.append((distance, strategy_type)) diff --git a/openhcs/core/runtime_adapters.py b/openhcs/core/runtime_adapters.py index 50a3df0fdc..8cc4b817c5 100644 --- a/openhcs/core/runtime_adapters.py +++ b/openhcs/core/runtime_adapters.py @@ -38,17 +38,14 @@ from openhcs.core.source_bindings import ( CompiledSourceBindingPlan, NamedSourceBinding, - SourceBindingRuntimeContext, ) from openhcs.core.source_binding_selection import ( SourceBindingMatchedImageSet, - SourcePatternResolutionContext, ) from openhcs.core.source_image_provenance import ( SourceImageIdentity, SourceImageProvenance, ) -from openhcs.core.source_image_semantics import apply_source_binding_payload from openhcs.core.source_load_plan import SourceLoadPlan from openhcs.core.runtime_plane_projection import ( RuntimePlaneAxis, @@ -63,7 +60,6 @@ if TYPE_CHECKING: from openhcs.core.callable_contract import CallableContract from openhcs.core.context.processing_context import ProcessingContext - from openhcs.core.steps.function_runtime import FunctionRuntimeScope from openhcs.core.runtime_stores import RuntimeArtifactInput @@ -94,9 +90,6 @@ class RuntimeAdapterRequest: default_factory=dict ) source_binding_plan: CompiledSourceBindingPlan = CompiledSourceBindingPlan.empty() - source_binding_context: SourceBindingRuntimeContext = field( - default_factory=SourceBindingRuntimeContext.empty - ) group_key: str | None = None axis_scope: RuntimeExecutionAxisScope plane_projection: RuntimePlaneProjection = field( @@ -229,8 +222,8 @@ def require_artifact_input_edge( first = matches[0] if any( edge.spec != first.spec - or (edge.storage_plan, edge.projection, edge.consumes_main_flow) - != (first.storage_plan, first.projection, first.consumes_main_flow) + or (edge.storage_plan, edge.projection, edge.main_flow_projection) + != (first.storage_plan, first.projection, first.main_flow_projection) for edge in matches[1:] ): raise ValueError( @@ -284,10 +277,12 @@ def source_artifact_payload(self, ref: ArtifactSpecRef) -> object: projection, axis_id=self.axis_scope.axis_id, ) - source_context = SourcePatternResolutionContext.from_projection( - parser=self.context.microscope_handler.parser, - projection=projection, - metadata_rules=self.source_binding_plan.metadata_rules, + source_context = ( + self.context.runtime_source_binding_context_cache.source_pattern_context( + parser=self.context.microscope_handler.parser, + projection=projection, + metadata_rules=self.source_binding_plan.metadata_rules, + ) ) matched_set = SourceBindingMatchedImageSet.from_plan( bindings=self.source_binding_plan.binding_declarations, @@ -339,9 +334,8 @@ def source_artifact_payload(self, ref: ArtifactSpecRef) -> object: ) projected = projection.project_payload(lookup, payload) projected_payloads.append( - apply_source_binding_payload( + binding.apply_loaded_payload( projected, - binding, ImagePayloadSourceMetadataContext( SourceImageIdentity( member, @@ -353,91 +347,23 @@ def source_artifact_payload(self, ref: ArtifactSpecRef) -> object: ), ) ) - return stack_image_payloads( - projected_payloads, - metadata_mode=ImagePayloadMetadataCompositionMode.for_plane_axis( - RuntimePlaneAxis.RUNTIME_SLICE - ), - ) - - @classmethod - def from_source_context( - cls, - *, - context: "ProcessingContext", - source_payload: object | None, - artifact_inputs: Mapping[ - "InvocationArtifactInputProjectionKey", - "InvocationArtifactInputEdgePlan", - ], - artifact_outputs: Mapping[ArtifactSpecRef, ArtifactOutputPlan], - source_binding_plan: CompiledSourceBindingPlan, - source_binding_context: SourceBindingRuntimeContext, - group_key: str | None = None, - axis_scope: RuntimeExecutionAxisScope | None = None, - plane_projection: RuntimePlaneProjection | None = None, - variable_components: tuple[VariableComponents, ...] | None = None, - source_load_plan: SourceLoadPlan | None = None, - callable_contract: "CallableContract | None" = None, - ) -> "RuntimeAdapterRequest": - """Project a source-binding runtime context into an adapter request.""" - return cls( - context=context, - callable_contract=callable_contract, - source_payload=source_payload, - artifact_inputs=artifact_inputs, - artifact_outputs=artifact_outputs, - source_binding_plan=source_binding_plan, - source_binding_context=source_binding_context, - group_key=group_key, - axis_scope=( - axis_scope - if axis_scope is not None - else RuntimeExecutionAxisScope.from_context(context) - ), - plane_projection=( - plane_projection - if plane_projection is not None - else RuntimePlaneProjection.stack() - ), - variable_components=( - tuple(variable_components) if variable_components is not None else () - ), - source_load_plan=( - source_load_plan if source_load_plan is not None else SourceLoadPlan() - ), + payload = ( + projected_payloads[0] + if len(projected_payloads) == 1 + and image_payload_metadata(projected_payloads[0]).persists_whole_image() + else stack_image_payloads( + projected_payloads, + metadata_mode=ImagePayloadMetadataCompositionMode.for_plane_axis( + RuntimePlaneAxis.RUNTIME_SLICE + ), + ) ) - - @classmethod - def from_runtime_scope( - cls, - *, - runtime_scope: "FunctionRuntimeScope", - artifact_inputs: Mapping[ - "InvocationArtifactInputProjectionKey", - "InvocationArtifactInputEdgePlan", - ], - artifact_outputs: Mapping[ArtifactSpecRef, ArtifactOutputPlan], - group_key: str | None, - plane_projection: RuntimePlaneProjection, - source_payload: object, - callable_contract: "CallableContract | None" = None, - ) -> "RuntimeAdapterRequest": - """Project an invocation runtime scope into an adapter request.""" - return cls.from_source_context( - context=runtime_scope.context, - callable_contract=callable_contract, - source_payload=source_payload, - artifact_inputs=artifact_inputs, - artifact_outputs=artifact_outputs, - source_binding_plan=runtime_scope.source_binding_plan, - source_binding_context=runtime_scope.source_binding_context, - group_key=group_key, - axis_scope=runtime_scope.axis_scope, - plane_projection=plane_projection, - variable_components=tuple(runtime_scope.execution_plan.variable_components), - source_load_plan=runtime_scope.execution_plan.source_load_plan, + metadata = image_payload_metadata(payload) + domain = self.source_binding_plan.source_spatial_domain.admit_source_cohort( + metadata.source_spatial_domain, + depth=len(members), ) + return metadata.replace_fields(source_spatial_domain=domain).attach_to(payload) RuntimeAdapterFactory = Callable[[RuntimeAdapterRequest], object] @@ -454,9 +380,19 @@ class RuntimeAdapterSpec: parameter_name: str factory: RuntimeAdapterFactory manages_artifact_inputs: bool = False - artifact_output_policy: type[ArtifactOutputPolicy] = NativeReturnArtifactOutputPolicy + artifact_output_policy: type[ArtifactOutputPolicy] = ( + NativeReturnArtifactOutputPolicy + ) runtime_callable_factory: RuntimeCallableFactory | None = None + def invocation_domain_inputs( + self, contract: "CallableContract", + ) -> ArtifactSpecCollection: + """Use declared context inputs when the callable has no raw image ABI.""" + if contract.accepts_implicit_main_flow_input: + return ArtifactSpecCollection(()) + return contract.group_scope_inputs + def __post_init__(self) -> None: if not self.parameter_name: raise ValueError("RuntimeAdapterSpec.parameter_name cannot be empty.") @@ -509,7 +445,9 @@ def runtime_adapter( factory: RuntimeAdapterFactory, *, manages_artifact_inputs: bool = False, - artifact_output_policy: type[ArtifactOutputPolicy] = NativeReturnArtifactOutputPolicy, + artifact_output_policy: type[ + ArtifactOutputPolicy + ] = NativeReturnArtifactOutputPolicy, runtime_callable_factory: RuntimeCallableFactory | None = None, ) -> Callable[[_F], _F]: """Declare that a callable needs an invocation-scoped runtime adapter.""" diff --git a/openhcs/core/runtime_artifact_queries.py b/openhcs/core/runtime_artifact_queries.py index 260fd32914..d48a3a1993 100644 --- a/openhcs/core/runtime_artifact_queries.py +++ b/openhcs/core/runtime_artifact_queries.py @@ -16,33 +16,22 @@ SpatialGridArtifactType, ) from openhcs.core.measurement_row_materialization import ( - ConcatenatedColumnarRows, MeasurementColumnarRowsView, - MeasurementRowOwnership, - MeasurementRowsAxisProjection, columnar_row_values, measurement_row_object_name, measurement_rows, measurement_table_axis_values, ) from openhcs.core.measurement_feature_queries import ( - ColumnarMeasurementTableSchema, IndexedObjectMeasurementLabelPlaneBinding, MeasurementAxisValueProjection, MeasurementFeatureValueIndex, MeasurementObjectFeatureVectorBatchQuery, MeasurementTableFeatureQuery, + ColumnarMeasurementTableSchema, MeasurementValueIndexResult, ) -from openhcs.core.measurement_lookup_dialect import ( - resolve_runtime_measurement_lookup_dialect, -) -from openhcs.core.process_local_cache import ( - BoundedCache, - RegisteredProcessLocalBoundedCache, - identity_owner_tuples_match, - named_identity_owner_tuples_match, -) +from openhcs.core.process_local_cache import BoundedCache from openhcs.core.runtime_measurements import ( MeasurementRowAxisField, MeasurementSubject, @@ -64,10 +53,6 @@ from openhcs.core.runtime_measurements import ( MeasurementTable, ) -from openhcs.core.runtime_image_values import ( - ImagePayloadMetadata, - ImagePayloadMetadataCompositionMode, -) from openhcs.core.runtime_object_labels import ( ObjectLabelValue, ) @@ -91,245 +76,6 @@ class RuntimeMeasurementTablesQueryCache( """Store-owned measurement tables for one axis and component group.""" -MeasurementLabelSliceFeatureBatchCacheValue = tuple[ - tuple[MeasurementTable, ...], - tuple[tuple[str, object], ...], - Mapping[str, tuple[Any, ...]], -] - - -@dataclass(frozen=True, slots=True) -class MeasurementLabelSliceFeatureBatchCacheKey: - """Identity key for label-plane feature projections.""" - - feature_name: str - object_names: tuple[str, ...] - dialect_identity: int - row_axis: MeasurementRowAxisField - table_identities: tuple[int, ...] - label_identities: tuple[tuple[str, int], ...] - row_axis_values: tuple[tuple[str, tuple[int, ...]], ...] - - -class MeasurementLabelSliceFeatureBatchQueryCache( - RegisteredProcessLocalBoundedCache[ - MeasurementLabelSliceFeatureBatchCacheKey, - MeasurementLabelSliceFeatureBatchCacheValue, - ] -): - """Process-local cache for repeated label-plane feature projections.""" - - max_entries = 1024 - - -@dataclass(frozen=True, slots=True) -class MeasurementTableUnion: - """Lossless row-owned view over same-artifact measurement subject tables.""" - - name: str - tables: tuple[MeasurementTable, ...] - - def __post_init__(self) -> None: - if not self.name: - raise ValueError("MeasurementTableUnion.name cannot be empty.") - if not self.tables: - raise ValueError("MeasurementTableUnion.tables cannot be empty.") - - def as_table(self) -> MeasurementTable: - if len(self.tables) == 1: - return self.tables[0] - subjects = tuple(dict.fromkeys(table.subject for table in self.tables)) - if len(subjects) != 1: - raise ValueError( - "Measurement table unions require one exact nominal subject; " - f"got {subjects!r}." - ) - owners = tuple( - dict.fromkeys(table.measurement_feature_owner for table in self.tables) - ) - if len(owners) != 1: - raise ValueError( - "Measurement table unions require one exact nominal measurement " - f"feature owner; got {owners!r}." - ) - source_names = tuple( - dict.fromkeys(table.source_image_name for table in self.tables) - ) - if len(source_names) != 1: - raise ValueError( - "Measurement table unions require one exact source-image owner; " - f"got {source_names!r}." - ) - return MeasurementTable( - name=self.name, - rows=self.rows(), - source_image_name=source_names[0], - subject=subjects[0], - measurement_feature_owner=owners[0], - source_provenance=self.source_metadata().source_provenance, - ) - - def as_artifact_table(self) -> MeasurementTable: - """Re-own mixed subject rows as one artifact-level export table.""" - - return MeasurementTable( - name=self.name, - rows=ConcatenatedColumnarRows( - tuple( - cast( - ColumnarRows, - MeasurementRowOwnership( - object_name=table.subject.object_name, - source_image_name=( - table.source_image_name - or table.subject.source_image_name - ), - ).annotate_rows(table.rows), - ) - for table in self.tables - ) - ), - subject=MeasurementSubject(MeasurementScope.ARTIFACT, self.name), - source_provenance=self.source_metadata().source_provenance, - ) - - def rows(self) -> ColumnarRows: - return ConcatenatedColumnarRows(tuple(table.rows for table in self.tables)) - - def source_metadata(self) -> ImagePayloadMetadata: - """Compose table provenance on its declared runtime-slice axis.""" - - if len(self.tables) == 1: - return ImagePayloadMetadata( - source_provenance=self.tables[0].source_provenance, - ) - - slice_axis = MeasurementRowAxisField.SLICE_INDEX - axis_domain = self.row_axis_domain(slice_axis) - if axis_domain is None: - return ImagePayloadMetadata.compose( - tuple( - ImagePayloadMetadata( - source_provenance=table.source_provenance, - ).payload_with((0,)) - for table in self.tables - ), - mode=ImagePayloadMetadataCompositionMode.STACK, - ) - - table_domains = tuple( - MeasurementRowsAxisProjection.from_rows(table.rows).present_axis_values( - slice_axis.value - ) - for table in self.tables - ) - declared_plane_counts = tuple( - table.source_provenance.source_plane_count - for table in self.tables - if table.source_provenance.source_plane_count > 0 - ) - distinct_plane_counts = tuple(dict.fromkeys(declared_plane_counts)) - if len(distinct_plane_counts) > 1: - raise ValueError( - f"Measurement table union {self.name!r} cannot align declared " - f"source-plane counts {distinct_plane_counts!r}." - ) - axis_size = ( - distinct_plane_counts[0] if distinct_plane_counts else max(axis_domain) + 1 - ) - if max(axis_domain) >= axis_size: - raise ValueError( - f"Measurement table union {self.name!r} declares " - f"{slice_axis.value}={max(axis_domain)} beyond its source-plane " - f"axis of size {axis_size}." - ) - - for table, domain in zip(self.tables, table_domains, strict=True): - provenance = table.source_provenance - if ( - provenance.source_plane_count == 0 - and provenance.has_values - and len(domain) > 1 - ): - raise ValueError( - f"Measurement table {table.name!r} carries scalar source " - f"provenance for multiple {slice_axis.value} values {domain!r}." - ) - - plane_metadata: list[ImagePayloadMetadata] = [] - for plane_index in range(axis_size): - plane_provenance = tuple( - ( - table.source_provenance.for_source_plane(plane_index) - if table.source_provenance.source_plane_count > 0 - else table.source_provenance - ) - for table, domain in zip(self.tables, table_domains, strict=True) - if table.source_provenance.source_plane_count > 0 - or domain == (plane_index,) - ) - source_metadata = tuple( - ImagePayloadMetadata(source_provenance=provenance) - for provenance in plane_provenance - ) - if not source_metadata: - raise ValueError( - f"Measurement table union {self.name!r} has no declared " - f"source provenance for {slice_axis.value}={plane_index}." - ) - if len(source_metadata) == 1: - plane_metadata.append(source_metadata[0]) - else: - plane_metadata.append( - ImagePayloadMetadata.compose( - tuple( - metadata.payload_with((0,)) for metadata in source_metadata - ), - mode=ImagePayloadMetadataCompositionMode.BUNDLE, - ).without_leading_plane_axis() - ) - - return ImagePayloadMetadata.compose( - tuple(metadata.payload_with((0,)) for metadata in plane_metadata), - mode=ImagePayloadMetadataCompositionMode.STACK, - ) - - def row_axis_domain( - self, - axis: MeasurementRowAxisField, - ) -> tuple[int, ...] | None: - """Return one exact row-axis domain, or ``None`` for an axisless union.""" - - projections = tuple( - MeasurementRowsAxisProjection.from_rows(table.rows) for table in self.tables - ) - declarations = tuple( - projection.declares_axis_field(axis) - or any(field.name == axis.value for field in table.rows.fields) - for table, projection in zip(self.tables, projections, strict=True) - ) - if not any(declarations): - return None - domains = tuple( - projection.present_axis_values(axis.value) for projection in projections - ) - if not any(domains): - return None - for table, projection, domain in zip( - self.tables, - projections, - domains, - strict=True, - ): - if projection.has_rows and not domain: - raise ValueError( - f"Measurement table union {self.name!r} mixes declared and " - f"axisless {axis.value!r} row domains; table {table.name!r} " - "declares no concrete axis value." - ) - return tuple(sorted({value for domain in domains for value in domain})) - - @dataclass(frozen=True, slots=True) class RuntimeArtifactQueryContext: """Execution-scope view over a RuntimeValueStore.""" @@ -383,7 +129,7 @@ def resolve( def runtime_record_locations(records: Sequence[StoredRuntimeValue]) -> tuple[str, ...]: """Return compact runtime-record identities without formatting payload data.""" return tuple( - f"{record.key.scope.value_text or ''}@{record.backend}:{record.path}" + f"{record.key.scope.value_text or ''}@{record.location.backend}:{record.location.path}" for record in records ) @@ -402,10 +148,9 @@ def matches(self, table: MeasurementTable) -> bool: if table.subject.scope is MeasurementScope.OBJECT: return table.subject.name == self.object_name if isinstance(table.rows, ColumnarRows): - return ( - self.object_name - in ColumnarMeasurementTableSchema.from_table(table).object_names - ) + return self.object_name in ColumnarMeasurementTableSchema.from_table( + table + ).object_names(table) if not _measurement_table_may_declare_object_name(table): return False return any( @@ -443,7 +188,7 @@ def runtime_measurement_tables( if cached is not None: return cached tables = tuple( - cast(MeasurementTable, record.value.data) + cast(MeasurementTable, record.data) for record in context.find(artifact_type=MeasurementsArtifactType) ) return store_cache.store_value(cache_key, tables) @@ -482,7 +227,7 @@ def runtime_relationship( artifact_type=RelationshipsArtifactType, purpose="relationship artifact", ) - return cast(ObjectRelationship, record.value.data) + return cast(ObjectRelationship, record.data) def runtime_spatial_grid( @@ -495,7 +240,7 @@ def runtime_spatial_grid( artifact_type=SpatialGridArtifactType, purpose="spatial grid artifact", ) - return cast(SpatialGrid, record.value.data) + return cast(SpatialGrid, record.data) def _measurement_table_may_declare_object_name(table: MeasurementTable) -> bool: @@ -874,10 +619,6 @@ def object_names(self) -> tuple[str, ...]: def values_by_object(self) -> Mapping[str, tuple[Any, ...]]: """Return label-plane-aligned vectors keyed by object name.""" - cached = self.cached_values_by_object() - if cached is not None: - return cached - label_planes_by_object = { object_name: self.object_feature_query(object_name).label_planes(labels) for object_name, labels in self.labels_by_object.items() @@ -952,13 +693,8 @@ def values_by_object(self) -> Mapping[str, tuple[Any, ...]]: strict=True, ) ) - return self.cache_values_by_object( - MappingProxyType( - { - object_name: values_by_object[object_name] - for object_name in object_names - } - ) + return MappingProxyType( + {object_name: values_by_object[object_name] for object_name in object_names} ) def object_feature_query( @@ -974,73 +710,6 @@ def object_feature_query( plane_projector=self.plane_projector, ) - def cache_key(self) -> MeasurementLabelSliceFeatureBatchCacheKey: - """Return the identity key for this label-plane feature projection.""" - object_names = self.object_names - return MeasurementLabelSliceFeatureBatchCacheKey( - feature_name=self.feature_name, - object_names=object_names, - dialect_identity=id( - resolve_runtime_measurement_lookup_dialect(self.dialect) - ), - row_axis=self.row_axis, - table_identities=tuple(id(table) for table in self.measurement_tables), - label_identities=tuple( - (object_name, id(self.labels_by_object[object_name])) - for object_name in object_names - ), - row_axis_values=tuple( - ( - object_name, - self.object_feature_query(object_name) - .select_axis(self.labels_by_object[object_name]) - .row_axis_values, - ) - for object_name in object_names - ), - ) - - def table_owners(self) -> tuple[MeasurementTable, ...]: - """Return table owners used to protect identity-keyed cache entries.""" - return self.measurement_tables - - def label_owners(self) -> tuple[tuple[str, object], ...]: - """Return label owners used to protect identity-keyed cache entries.""" - return tuple( - (object_name, self.labels_by_object[object_name]) - for object_name in self.object_names - ) - - def cached_values_by_object(self) -> Mapping[str, tuple[Any, ...]] | None: - """Return cached label-plane feature projections when owners still match.""" - cached = ( - MeasurementLabelSliceFeatureBatchQueryCache.process_cache().cached_value( - self.cache_key() - ) - ) - if cached is None: - return None - cached_tables, cached_labels, cached_values = cached - if not identity_owner_tuples_match(cached_tables, self.table_owners()): - return None - if not named_identity_owner_tuples_match(cached_labels, self.label_owners()): - return None - return cached_values - - def cache_values_by_object( - self, - values_by_object: Mapping[str, tuple[Any, ...]], - ) -> Mapping[str, tuple[Any, ...]]: - """Store label-plane feature projections with identity-owner protection.""" - return MeasurementLabelSliceFeatureBatchQueryCache.process_cache().store_value( - self.cache_key(), - ( - self.table_owners(), - self.label_owners(), - values_by_object, - ), - )[2] - def _merge_measurement_value_index( target: MeasurementValueIndexResult, diff --git a/openhcs/core/runtime_artifact_values.py b/openhcs/core/runtime_artifact_values.py index deb4343b71..05e9e9395a 100644 --- a/openhcs/core/runtime_artifact_values.py +++ b/openhcs/core/runtime_artifact_values.py @@ -4,7 +4,7 @@ from collections.abc import Sequence from dataclasses import dataclass, replace -from typing import TYPE_CHECKING, Any, Self +from typing import TYPE_CHECKING, Any from openhcs.core.artifacts import ArtifactOutputPlan, ArtifactSpec, ArtifactType from openhcs.core.component_group_scope import ( @@ -14,6 +14,9 @@ if TYPE_CHECKING: from openhcs.core.runtime_image_values import ImagePayloadMetadata + from openhcs.core.runtime_plane_projection import ( + RuntimePlaneAxisProjector, + ) @dataclass(frozen=True, slots=True) @@ -48,16 +51,15 @@ class RuntimeValue: data: Any materialization_source_metadata: "ImagePayloadMetadata | None" = None - @classmethod + @staticmethod def from_output_plan( - cls, output_plan: ArtifactOutputPlan, data: Any, *, execution_scope: RuntimeExecutionAxisScope, materialization_source_metadata: "ImagePayloadMetadata | None" = None, - ) -> Self: - """Construct one exact runtime value from already-normalized data.""" + ) -> "RuntimeValue": + """Construct a transient value from already-normalized data and identity.""" if not isinstance(execution_scope, RuntimeExecutionAxisScope): raise TypeError( @@ -68,24 +70,23 @@ def from_output_plan( output_plan.group_component if group_key is not None else None, group_key, ) - return cls.from_spec( + return RuntimeValue.from_spec( output_plan, data, execution_scope=artifact_scope, materialization_source_metadata=materialization_source_metadata, ) - @classmethod + @staticmethod def from_spec( - cls, spec: ArtifactSpec, data: Any, *, execution_scope: RuntimeExecutionAxisScope, materialization_source_metadata: "ImagePayloadMetadata | None" = None, - ) -> Self: - """Derive transient or stored runtime identity from one declared artifact.""" - return cls( + ) -> "RuntimeValue": + """Derive transient runtime identity without declaring a stored location.""" + return RuntimeValue( key=ArtifactKey( name=spec.name, artifact_type=spec.artifact_type, @@ -151,9 +152,8 @@ def compose( producer_group_scope=producer_group_scope, ) - @classmethod + @staticmethod def normalize( - cls, output_plan: ArtifactOutputPlan, value: Any, *, @@ -162,16 +162,39 @@ def normalize( ) -> "RuntimeValue": """Normalize a raw artifact return exactly once through its compiled plan.""" - return cls.normalize_for_execution_scope( + return RuntimeValue.normalize_for_execution_scope( output_plan, value, execution_scope=RuntimeExecutionAxisScope(axis_id=str(axis_id)), materialization_source_metadata=materialization_source_metadata, ) - @classmethod + @staticmethod + def normalize_output_from_projector( + output_plan: ArtifactOutputPlan, + value: Any, + *, + source_payload: object, + plane_projector: "RuntimePlaneAxisProjector | None", + execution_scope: RuntimeExecutionAxisScope, + materialization_source_metadata: "ImagePayloadMetadata | None" = None, + ) -> "RuntimeValue": + """Admit current source context and raw output at one generic boundary.""" + contextualized = output_plan.artifact_type.contextualize_output_from_projector( + source_payload, + value, + output_plan, + plane_projector, + ) + return RuntimeValue.normalize_for_execution_scope( + output_plan, + contextualized, + execution_scope=execution_scope, + materialization_source_metadata=materialization_source_metadata, + ) + + @staticmethod def normalize_for_execution_scope( - cls, output_plan: ArtifactOutputPlan, value: Any, *, @@ -209,7 +232,7 @@ def normalize_for_execution_scope( axis_id=execution_scope.axis_id, ) - runtime_value = cls.from_output_plan( + runtime_value = RuntimeValue.from_output_plan( output_plan, normalized, execution_scope=execution_scope, @@ -259,5 +282,9 @@ def validated_for_output_plan( self.artifact_type.validate_runtime_payload(output_plan.name, self.data) semantic_id = self.artifact_type.runtime_semantic_id(self.data) if semantic_id != self.key.semantic_id: - return replace(self, key=replace(self.key, semantic_id=semantic_id)) + return RuntimeValue( + key=replace(self.key, semantic_id=semantic_id), + data=self.data, + materialization_source_metadata=self.materialization_source_metadata, + ) return self diff --git a/openhcs/core/runtime_batch_contracts.py b/openhcs/core/runtime_batch_contracts.py index 6e380102f8..7997a363e7 100644 --- a/openhcs/core/runtime_batch_contracts.py +++ b/openhcs/core/runtime_batch_contracts.py @@ -6,14 +6,13 @@ from collections.abc import Callable, Hashable, Mapping from dataclasses import dataclass, replace from enum import Enum -from functools import lru_cache import inspect from types import MappingProxyType from typing import ClassVar, Generic, TypeVar from metaclass_registry import AutoRegisterMeta -from openhcs.core.callable_contract import KeywordRuntimeParameter +from openhcs.core.callable_contract import CallableMetadata, KeywordRuntimeParameter from openhcs.core.function_reference import FunctionReference from openhcs.core.aligned_image_payload import ( AlignedImageStack, @@ -49,11 +48,12 @@ class RuntimePlaneAxisValueProjectionParameter(KeywordRuntimeParameter): parameter_default = None -@lru_cache(maxsize=1024) -def runtime_callable_defaults(func: Callable[..., object]) -> Mapping[str, object]: +def runtime_callable_defaults( + func: Callable[..., object], *, signature: inspect.Signature | None = None, +) -> Mapping[str, object]: """Return callable defaults visible to runtime batch executors.""" try: - callable_signature = inspect.signature(func) + callable_signature = CallableMetadata.callable_signature(func) if signature is None else signature except (TypeError, ValueError) as exc: raise TypeError( f"Runtime batch function {func!r} must expose an inspectable signature." @@ -191,6 +191,7 @@ class RuntimePure2DSliceBatchRequest( ], RuntimeSliceResultT, ] + signature: inspect.Signature | None = None def __post_init__(self) -> None: object.__setattr__( @@ -198,7 +199,7 @@ def __post_init__(self) -> None: "kwargs", MappingProxyType( { - **runtime_callable_defaults(self.func), + **runtime_callable_defaults(self.func, signature=self.signature), **dict(self.kwargs), } ), @@ -292,6 +293,14 @@ def executors(self) -> Mapping[RuntimeBatchExecutionDomain, Callable]: class Pure2DSliceBatchExecutor(RuntimeBatchExecutor): """Base contract for equivalent pure-2D slice batch execution.""" + @classmethod + def from_executors( + cls, executors: Mapping[RuntimeBatchExecutionDomain, Callable] | None, + ) -> Callable: + """Honor a declared pure-2D executor before the nominal serial default.""" + declared = None if executors is None else executors.get(RuntimeBatchExecutionDomain.PURE_2D_SLICES) + return declared if callable(declared) else cls.default_executor() + @classmethod def default_executor(cls) -> "Pure2DSliceBatchExecutor": """Return the single-thread default pure-2D batch executor.""" diff --git a/openhcs/core/runtime_equivalence.py b/openhcs/core/runtime_equivalence.py index 4fbbbe3d2f..bb1bf87b4b 100644 --- a/openhcs/core/runtime_equivalence.py +++ b/openhcs/core/runtime_equivalence.py @@ -639,8 +639,8 @@ def accept_measurement_table( ) -> None: self.measurement_tables.append( RuntimeScopedMeasurementTable( - cast(MeasurementTable, record.value.data), - record_identity=record.path, + cast(MeasurementTable, record.data), + record_identity=record.location.path, execution_scope=record.key.scope, ) ) @@ -654,7 +654,7 @@ def accept_relationship_record( record: StoredRuntimeValue, ) -> None: """Record a relationship artifact observed on this axis.""" - relationship = cast(ObjectRelationship, record.value.data) + relationship = cast(ObjectRelationship, record.data) relationship_identity = RuntimeObjectRelationshipIdentity.from_relationship( relationship ) @@ -879,7 +879,7 @@ def measurement_fact_counter_for_projected_key( def record_spatial_grid(self, record: StoredRuntimeValue) -> None: record_measurement_facts( self.measurement_fact_counts, - spatial_grid_measurement_facts(record.value, self.policy), + spatial_grid_measurement_facts(record, self.policy), required_keys=self.required_measurement_keys, ) @@ -3220,7 +3220,7 @@ def _measurement_source_names_from_artifact_execution( for record in records: if record.key.artifact_type is not MeasurementsArtifactType: continue - table = cast(MeasurementTable, record.value.data) + table = cast(MeasurementTable, record.data) if table.source_image_name is not None: source_names.update(_source_name_aliases(table.source_image_name)) for row in iter_measurement_rows((table,)): diff --git a/openhcs/core/runtime_execution_validation.py b/openhcs/core/runtime_execution_validation.py index 8f1c90d4a1..ac0408d267 100644 --- a/openhcs/core/runtime_execution_validation.py +++ b/openhcs/core/runtime_execution_validation.py @@ -3,7 +3,7 @@ from __future__ import annotations from collections import Counter -from collections.abc import Iterable, Mapping +from collections.abc import Iterable, Mapping, Sequence from dataclasses import dataclass from pathlib import Path from types import MappingProxyType @@ -12,6 +12,7 @@ from openhcs.core.artifacts import ArtifactSpec, ArtifactType from openhcs.core.context.processing_context import ProcessingContext +from openhcs.core.orchestrator.execution_result import RuntimeExecutionObservation from openhcs.core.runtime_exports import ( RuntimeExportExpectation, RuntimeExportObservation, @@ -25,10 +26,6 @@ source_component_metadata_items, ) from openhcs.core.source_spatial_domain import SourceSpatialDomain -from openhcs.core.steps.function_output_manifest import ( - FunctionStepOutputProducerIdentityAuthority, - FunctionStepOutputProducerIdentityRequest, -) from openhcs.processing.materialization import Output RuntimeArtifactViewerComponentIdentity = tuple[tuple[str, str], ...] @@ -235,12 +232,13 @@ def runtime_artifact_viewer_expectations( if not plan.streaming_configs or not plan.owns_runtime_outputs: continue from openhcs.core.steps.function_artifact_materialization import ( - observed_runtime_artifact_materializations, + runtime_artifact_materializations_from_records, ) - for materialization in observed_runtime_artifact_materializations( + for materialization in runtime_artifact_materializations_from_records( plan, context, + context.runtime_value_store.observed_values, ): output_plan = materialization.output_plan if plan.compiled_function_pattern.publishes_output_to_main_flow( @@ -251,12 +249,7 @@ def runtime_artifact_viewer_expectations( viewer_outputs = materialization.viewer_outputs(plan, context) if not viewer_outputs: continue - producer = FunctionStepOutputProducerIdentityAuthority.build( - FunctionStepOutputProducerIdentityRequest.from_artifact( - plan, - output_plan, - ) - ) + producer = plan.producer_identity_for_artifact(output_plan) payloads = expected_by_producer.setdefault(producer, []) payloads.extend( _runtime_artifact_viewer_output_payloads( @@ -319,6 +312,8 @@ class RuntimeArtifactExecutionObservation: def from_contexts( cls, execution_contexts: Mapping[str, ProcessingContext], + *, + runtime_observations: Sequence[RuntimeExecutionObservation], ) -> "RuntimeArtifactExecutionObservation": identity_policies = frozenset( context.source_image_set_identity_policy @@ -331,8 +326,8 @@ def from_contexts( ) return cls( records_by_axis=runtime_records_by_axis(execution_contexts), - exports=RuntimeExportObservation.from_execution_contexts( - execution_contexts + exports=RuntimeExportObservation.from_runtime_observations( + runtime_observations ), source_image_set_identity_policy=next( iter(identity_policies), diff --git a/openhcs/core/runtime_exports.py b/openhcs/core/runtime_exports.py index 1cc9d50317..8712395dfd 100644 --- a/openhcs/core/runtime_exports.py +++ b/openhcs/core/runtime_exports.py @@ -28,7 +28,6 @@ from openhcs.processing.materialization.core import materialization_is_empty if TYPE_CHECKING: - from openhcs.core.context.processing_context import ProcessingContext from openhcs.core.orchestrator.execution_result import RuntimeExecutionObservation @@ -113,26 +112,6 @@ class RuntimeExportObservation: table_row_counts_by_path: Mapping[Path, int] output_files: tuple[Path, ...] = () - @classmethod - def from_execution_contexts( - cls, - execution_contexts: Mapping[str, ProcessingContext], - ) -> RuntimeExportObservation: - """Read contract-owned export paths without retaining runtime values.""" - from openhcs.core.steps.function_artifact_materialization import ( - runtime_export_artifact_output_paths, - ) - - return cls.from_output_paths( - tuple( - path - for context in execution_contexts.values() - for plan in context.step_plans.values() - if plan.owns_runtime_outputs - for path in runtime_export_artifact_output_paths(plan, context) - ) - ) - @classmethod def from_runtime_observations( cls, @@ -410,7 +389,7 @@ def _file_bundle_failures( ) -> tuple[str, ...]: failures: list[str] = [] for record in _runtime_records_for_specs(output_specs, runtime_records_by_axis): - payload = record.value.materialization_payload() + payload = record.materialization_payload() if type(payload) is not dict: failures.append( f"materialized file-bundle artifact {record.key.name!r} has " @@ -462,7 +441,7 @@ def _table_schema_field_failures( if record.key.artifact_type is not MeasurementsArtifactType: return () expected_fields = tuple( - field.name for field in cast(MeasurementTable, record.value.data).rows.fields + field.name for field in cast(MeasurementTable, record.data).rows.fields ) if not expected_fields: return () @@ -488,7 +467,7 @@ def _table_row_count_failures( table_outputs: tuple[Path, ...], row_counts_by_path: Mapping[Path, int], ) -> tuple[str, ...]: - if materialization_is_empty(record.value.materialization_payload()): + if materialization_is_empty(record.materialization_payload()): return () return tuple( f"table output {path} has no data rows" diff --git a/openhcs/core/runtime_image_loading.py b/openhcs/core/runtime_image_loading.py index a29901c1c2..aac6f04af4 100644 --- a/openhcs/core/runtime_image_loading.py +++ b/openhcs/core/runtime_image_loading.py @@ -17,6 +17,7 @@ ImagePayloadMetadataCarrier, image_payload_data, image_payload_metadata, + image_payload_mask, ) from openhcs.core.runtime_plane_projection import RuntimePlaneAxis from openhcs.core.source_image_provenance import ( @@ -51,6 +52,13 @@ def source_path(self) -> str: raise ValueError("ImagePayloadSourceMetadataContext requires source path.") return self.source_identity.path + def payload(self, image: Any) -> ImagePayloadMetadataCarrier: + """Keep loader metadata, deriving source facts only for bare pixels.""" + metadata = image_payload_metadata(image) + if not metadata.has_values: + metadata = self.metadata(image) + return metadata.payload_with(image_payload_data(image), image_payload_mask(image)) + def metadata( self, image: Any, @@ -130,9 +138,14 @@ def metadata( image_shape_yx=source_spatial_shape_yx, ) ) - return metadata.with_source_context_from( + metadata = metadata.with_source_context_from( existing_metadata ).with_missing_intensity_from(existing_metadata) + if source_binding is not None: + # A declared absent channel axis must not be refilled from the + # previous carrier while merging missing source context. + metadata.source_channel_axis = source_channel_axis + return metadata @staticmethod def source_channel_axis( diff --git a/openhcs/core/runtime_image_values.py b/openhcs/core/runtime_image_values.py index f43374ff3d..a351979f8e 100644 --- a/openhcs/core/runtime_image_values.py +++ b/openhcs/core/runtime_image_values.py @@ -10,7 +10,6 @@ from dataclasses import dataclass, field, fields from enum import Enum from pathlib import Path -from types import MappingProxyType from typing import Any, TypeVar import numpy as np @@ -36,18 +35,13 @@ RuntimePlaneAxisValueProjection, ) from openhcs.core.source_image_provenance import ( - RuntimeSourceImageProvenancePlane, SourceComponentMetadata, - SourceImageIdentity, SourceImageProvenance, SourceImageProvenanceFields, - SourceImageProvenancePlanes, SourcePlaneIndexedProvenanceExpansion, - common_source_component_metadata, ) from openhcs.core.source_metadata import ( SourceMetadataScalar, - SourceMetadataValue, SourceVoxelSpacing, SourceVoxelSpacingFields, ) @@ -193,6 +187,10 @@ def from_mapping(cls, values: Mapping[str, object]) -> "ImagePayloadMetadata": decoded["source_provenance"] = SourceImageProvenance.from_mapping( decoded["source_provenance"] ) + if "source_spatial_domain" in decoded: + decoded["source_spatial_domain"] = SourceSpatialDomain.from_mapping( + decoded["source_spatial_domain"] + ) return dataclass_from_mapping(cls, decoded) def retained_plane_component_values( @@ -251,15 +249,28 @@ def for_array_payload( ) def __post_init__(self, *source_provenance_values: object) -> None: - self.absorb_explicit_source_provenance( - SourceImageProvenance.from_init_values(source_provenance_values) - ) + self.absorb_explicit_source_provenance(source_provenance_values) + self.normalize_metadata_fields() + + def normalize_metadata_fields(self) -> None: + """Normalize this metadata's typed fields in their constructor effect order.""" self.source_voxel_spacing = self.source_voxel_spacing.with_missing_from( SourceVoxelSpacing.from_source_metadata(self.source_component_metadata) ) self.normalize_source_provenance_fields() self.normalize_source_spatial_domain_fields() self.normalize_source_voxel_spacing_fields() + self.validate_source_channel_axis() + if self.plane_axis is not None: + self.plane_axis = RuntimePlaneAxis(self.plane_axis) + + def require_leading_plane_axis(self, message: str) -> None: + """Require axis presence before later ordered projection validation.""" + if self.plane_axis is None: + raise ValueError(message) + + def validate_source_channel_axis(self) -> None: + """Validate the authored channel declaration before transforming axes.""" if self.source_channel_axis is not None and ( not isinstance(self.source_channel_axis, int) or isinstance(self.source_channel_axis, bool) @@ -267,10 +278,6 @@ def __post_init__(self, *source_provenance_values: object) -> None: raise TypeError( "ImagePayloadMetadata.source_channel_axis must be int or None." ) - if self.plane_axis is not None: - self.plane_axis = RuntimePlaneAxis( - self.plane_axis, - ) @property def has_values(self) -> bool: @@ -429,19 +436,36 @@ def _derived_metadata( f"{metadata.plane_axis.value!r} axis after the invocation " "selected one plane." ) + # Admit current source fields before deriving the output. This private + # snapshot owns its stripped axes; no intermediate image is published. source_context = source_metadata.replace_fields(plane_axis=None) if isinstance(data, ImagePayloadMetadataCarrier): - source_context = source_context.replace_fields(source_channel_axis=None) - metadata = output_metadata.with_source_context_from(source_context) + source_context.source_channel_axis = None + # Admit current output calibration and geometry before replacing stale + # source identity. These fields belong to the returned pixel domain. + metadata = output_metadata.with_source_spatial_context_from(source_context) if source_metadata.source_provenance.has_values: - metadata = metadata.with_source_provenance( + # The source owns derived-image provenance. Do not merge every + # output plane into a value that this source identity supersedes. + source_provenance = ( source_metadata.source_provenance.with_derived_source_image_names( output_metadata.source_image_names or source_metadata.source_image_names ) ) - return metadata.with_missing_intensity_from(source_metadata).replace_fields( + else: + source_provenance = metadata.source_provenance.with_missing_from( + source_context.source_provenance + ) + return metadata.replace_fields( + source_provenance=source_provenance, + source_channel_axis=( + metadata.source_channel_axis + if metadata.source_channel_axis is not None + else source_context.source_channel_axis + ), plane_axis=declared_output_axis, + **metadata._missing_intensity_fields(source_metadata), ) def project_channel_payload( @@ -598,18 +622,24 @@ def without_source_channel_axis(self) -> "ImagePayloadMetadata": """Return metadata after an operation collapses the source channel axis.""" return self.replace_fields(source_channel_axis=None) + def persists_whole_image(self) -> bool: + """Keep intrinsic pixels whole, excluding a distinct image-binding axis.""" + return ( + self.source_spatial_domain.persists_whole_image() + and self.plane_axis is not RuntimePlaneAxis.SOURCE_BINDING + ) + def for_leading_source_plane(self, plane_index: int) -> "ImagePayloadMetadata": """Project metadata after explicitly removing its leading plane axis.""" - if self.plane_axis is None: - raise ValueError( - "Leading source-plane projection requires a declared plane axis." - ) - return self.for_source_plane(plane_index).without_leading_plane_axis() + return LeadingSourcePlaneMetadataProjection(self, plane_index).project() - def without_leading_plane_axis(self) -> "ImagePayloadMetadata": - """Return metadata after an explicitly declared leading axis is removed.""" - if self.plane_axis is None: - raise ValueError("Image metadata has no leading plane axis to remove.") + def without_leading_plane_axis( + self, *, projection: "ImageMetadataProjection | None" = None + ) -> "ImagePayloadMetadata": + """Remove an axis through the projection's declared result ownership.""" + self.require_leading_plane_axis( + "Image metadata has no leading plane axis to remove." + ) source_channel_axis = self.source_channel_axis if source_channel_axis == 0: raise ValueError( @@ -618,19 +648,22 @@ def without_leading_plane_axis(self) -> "ImagePayloadMetadata": ) if source_channel_axis is not None and source_channel_axis > 0: source_channel_axis -= 1 - return self.with_source_provenance( - self.source_provenance.with_runtime_planes_as_contributors() - ).replace_fields( - plane_axis=None, - source_channel_axis=source_channel_axis, - source_plane_intensity_scales=(), - source_plane_dtypes=(), - unit_interval_intensity=( - None - if self.unit_interval_intensity is None - else self.unit_interval_intensity.without_source_planes() - ), - ) + if projection is None: + projection = LeadingPlaneAxisMetadataProjection(self) + projected = projection.project_source_provenance( + self, self.source_provenance.with_runtime_planes_as_contributors() + ) + if self.plane_axis is RuntimePlaneAxis.RUNTIME_SLICE: + projected.source_spatial_domain = ( + projected.source_spatial_domain.for_intrinsic_plane() + ) + projected.plane_axis = None + projected.source_channel_axis = source_channel_axis + projected.source_plane_intensity_scales = () + projected.source_plane_dtypes = () + projected.unit_interval_intensity = self.project_intensity_proof(None) + projected.normalize_metadata_fields() + return projected def collapse_leading_plane_axis(self) -> "ImagePayloadMetadata": """Return scalar metadata after reducing every plane of the leading axis.""" @@ -666,22 +699,27 @@ def source_image_paths(self) -> tuple[str, ...]: def intensity_scale_for_source_plane(self, plane_index: int) -> float | None: """Return the best available intensity scale for one source plane.""" - if 0 <= plane_index < len(self.source_plane_intensity_scales): - plane_scale = self.source_plane_intensity_scales[plane_index] - if plane_scale is not None: - return plane_scale - return self.intensity_scale + plane_scale = _tuple_value(self.source_plane_intensity_scales, plane_index) + return self.intensity_scale if plane_scale is None else plane_scale def unit_interval_intensity_scale_for_source_plane( self, plane_index: int, ) -> int | None: """Return the scale proving current pixels are exact integer/scale values.""" - if 0 <= plane_index < len(self.source_plane_unit_interval_intensity_scales): - plane_scale = self.source_plane_unit_interval_intensity_scales[plane_index] - if plane_scale is not None: - return int(plane_scale) - return self.unit_interval_intensity_scale + if self.unit_interval_intensity is None: + return None + return self.unit_interval_intensity.scale_for_source_plane(plane_index) + + def project_intensity_proof( + self, plane_index: int | None + ) -> ImageUnitIntervalIntensityMetadata | None: + """Select a plane's proof, or retain only the proof for the whole image.""" + if self.unit_interval_intensity is None: + return None + if plane_index is None: + return self.unit_interval_intensity.without_source_planes() + return self.unit_interval_intensity.for_source_plane(plane_index) @property def source_plane_metadata_count(self) -> int: @@ -694,7 +732,7 @@ def source_plane_metadata_count(self) -> int: len(self.source_plane_unit_interval_intensity_scales), ) - def source_plane_metadata_records(self) -> tuple["ImagePayloadMetadata", ...]: + def source_metadata_by_payload(self) -> tuple["ImagePayloadMetadata", ...]: """Return one scalar metadata record per represented source plane.""" if ( self.source_plane_metadata_count == 1 @@ -737,20 +775,7 @@ def payload_with(self, data: Any, mask: Any | None = None) -> Any: def for_source_plane(self, plane_index: int) -> "ImagePayloadMetadata": """Return metadata for one source plane sliced from a stacked payload.""" - source_provenance = self.source_provenance.for_source_plane(plane_index) - return self.replace_fields( - intensity_scale=self.intensity_scale_for_source_plane(plane_index), - source_dtype=_tuple_value(self.source_plane_dtypes, plane_index) - or self.source_dtype, - source_provenance=source_provenance, - unit_interval_intensity=( - None - if self.unit_interval_intensity is None - else self.unit_interval_intensity.for_source_plane(plane_index) - ), - source_plane_intensity_scales=(), - source_plane_dtypes=(), - ) + return SourcePlaneImageMetadataProjection(self, plane_index).project() def for_source_planes( self, @@ -946,38 +971,60 @@ def object_label_source_spatial_domain(self) -> SourceSpatialDomain: OBJECT_LABEL_SOURCE_SPATIAL_VALUE_NAME, ) - def with_source_spatial_context_from( + def _source_spatial_context_fields( self, source: "ImagePayloadMetadata", - ) -> "ImagePayloadMetadata": - """Fill missing source-image geometry without changing provenance.""" + ) -> dict[str, Any]: spatial_domain = self.source_spatial_domain.with_missing_from( source.source_spatial_domain ) - return self.replace_fields( - source_spatial_domain=spatial_domain, - source_voxel_spacing=self.source_voxel_spacing.with_missing_from( + return { + "source_spatial_domain": spatial_domain, + "source_voxel_spacing": self.source_voxel_spacing.with_missing_from( source.source_voxel_spacing ), - physical_border_edges_yx=( + "physical_border_edges_yx": ( self.physical_border_edges_yx if self.physical_border_edges_yx is not None else source.physical_border_edges_yx ), - mask_defines_border=( + "mask_defines_border": ( self.mask_defines_border if self.mask_defines_border is not None else source.mask_defines_border ), - ) + } + + def with_source_spatial_context_from( + self, + source: "ImagePayloadMetadata", + ) -> "ImagePayloadMetadata": + """Fill missing source-image geometry without changing provenance.""" + return self.replace_fields(**self._source_spatial_context_fields(source)) def with_source_context_from( self, source: "ImagePayloadMetadata", ) -> "ImagePayloadMetadata": """Fill missing source-image identity and spatial context from a source.""" + fallback_provenance = source.source_provenance + # Scalar context cannot collapse coordinates that vary across this + # payload's represented source planes, including runtime stacks. + varying = self.source_provenance.varying_plane_component_values( + tuple(AllComponents) + ) + if varying: + fallback_provenance = fallback_provenance.with_source_component_metadata( + { + key: value + for key, value in ( + fallback_provenance.source_component_metadata or {} + ).items() + if key not in varying + } + ) source_provenance = self.source_provenance.with_missing_from( - source.source_provenance + fallback_provenance ) source_channel_axis = self.source_channel_axis if source_channel_axis is None: @@ -990,41 +1037,48 @@ def with_source_context_from( "Cannot combine image metadata with conflicting plane axes: " f"{plane_axis.value!r} != {source.plane_axis.value!r}." ) - return self.with_source_spatial_context_from(source).replace_fields( + return self.replace_fields( source_provenance=source_provenance, + **self._source_spatial_context_fields(source), source_channel_axis=source_channel_axis, plane_axis=plane_axis, ) - def with_missing_intensity_from( + def _missing_intensity_fields( self, source: "ImagePayloadMetadata", - ) -> "ImagePayloadMetadata": - """Fill missing pixel-type and intensity metadata from a source payload.""" - return self.replace_fields( - intensity_scale=( + ) -> dict[str, Any]: + return { + "intensity_scale": ( self.intensity_scale if self.intensity_scale is not None else source.intensity_scale ), - source_dtype=( + "source_dtype": ( self.source_dtype if self.source_dtype is not None else source.source_dtype ), - unit_interval_intensity=( + "unit_interval_intensity": ( self.unit_interval_intensity if self.unit_interval_intensity is not None else source.unit_interval_intensity ), - source_plane_intensity_scales=( + "source_plane_intensity_scales": ( self.source_plane_intensity_scales or source.source_plane_intensity_scales ), - source_plane_dtypes=( + "source_plane_dtypes": ( self.source_plane_dtypes or source.source_plane_dtypes ), - ) + } + + def with_missing_intensity_from( + self, + source: "ImagePayloadMetadata", + ) -> "ImagePayloadMetadata": + """Fill missing pixel-type and intensity metadata from a source payload.""" + return self.replace_fields(**self._missing_intensity_fields(source)) def with_source_provenance( self, @@ -1398,6 +1452,96 @@ def with_image_payload_data( return resolved_metadata.payload_with(data, resolved_mask) +@dataclass(frozen=True, slots=True) +class ImageMetadataProjection(ABC): + """Construct one metadata result from nominal source and axis transformations.""" + + metadata: ImagePayloadMetadata + + def project(self) -> ImagePayloadMetadata: + return self.project_axis_metadata(self.project_source_metadata()) + + @abstractmethod + def project_source_metadata(self) -> ImagePayloadMetadata: + """Select source metadata with this projection's declared ownership.""" + + def project_axis_metadata( + self, metadata: ImagePayloadMetadata + ) -> ImagePayloadMetadata: + """Retain declared axes unless a nominal axis capability transforms them.""" + return metadata + + @abstractmethod + def project_source_provenance( + self, metadata: ImagePayloadMetadata, provenance: SourceImageProvenance + ) -> ImagePayloadMetadata: + """Apply provenance using the result ownership established by source selection.""" + + +@dataclass(frozen=True, slots=True) +class SourcePlaneImageMetadataProjection(ImageMetadataProjection): + """Select scalar source-image facts without removing an array axis.""" + + plane_index: int + + def project_source_metadata(self) -> ImagePayloadMetadata: + provenance = self.metadata.source_provenance.for_source_plane(self.plane_index) + return self.metadata.replace_fields( + intensity_scale=self.metadata.intensity_scale_for_source_plane( + self.plane_index + ), + source_dtype=_tuple_value( + self.metadata.source_plane_dtypes, self.plane_index + ) + or self.metadata.source_dtype, + source_provenance=provenance, + unit_interval_intensity=self.metadata.project_intensity_proof( + self.plane_index + ), + source_plane_intensity_scales=(), + source_plane_dtypes=(), + ) + + def project_source_provenance( + self, metadata: ImagePayloadMetadata, provenance: SourceImageProvenance + ) -> ImagePayloadMetadata: + """Normalize the independently owned result created by source selection.""" + metadata.source_provenance = provenance + metadata.normalize_metadata_fields() + return metadata + + +class LeadingPlaneAxisMetadataProjection(ImageMetadataProjection): + """Remove a declared leading axis while preserving its source contributors.""" + + def project_source_metadata(self) -> ImagePayloadMetadata: + return self.metadata + + def project_axis_metadata( + self, metadata: ImagePayloadMetadata + ) -> ImagePayloadMetadata: + return metadata.without_leading_plane_axis(projection=self) + + def project_source_provenance( + self, metadata: ImagePayloadMetadata, provenance: SourceImageProvenance + ) -> ImagePayloadMetadata: + """Create the standalone result after its axis guards and source derivation.""" + return metadata.replace_fields(source_provenance=provenance) + + +class LeadingSourcePlaneMetadataProjection( + SourcePlaneImageMetadataProjection, + LeadingPlaneAxisMetadataProjection, +): + """Remove the leading axis of independently owned selected-source metadata.""" + + def project_source_metadata(self) -> ImagePayloadMetadata: + self.metadata.require_leading_plane_axis( + "Leading source-plane projection requires a declared plane axis." + ) + return super().project_source_metadata() + + @dataclass(frozen=True, slots=True) class ImagePayloadSliceProjector: """Project payload context from a parent image into one child image slice.""" @@ -1632,9 +1776,24 @@ def compose(self) -> ImagePayloadMetadata: self.source_plane_metadata_for_payload(metadata) for metadata in metadata_by_payload ) - source_plane_metadata_records = source_metadata_by_payload - composed_source_provenance_planes = self.composed_source_provenance_planes( - source_plane_metadata_records + compose_provenance = ( + SourceImageProvenance.stack + if self.mode is ImagePayloadMetadataCompositionMode.STACK + else SourceImageProvenance.bundle + ) + source_provenance = compose_provenance( + tuple( + metadata.source_provenance for metadata in source_metadata_by_payload + ), + scalar_sources=tuple( + metadata.source_provenance for metadata in metadata_by_payload + ), + preserve_single_topology=( + len(source_metadata_by_payload) == 1 + and self.mode.preserves_plane_topology( + source_metadata_by_payload[0].plane_axis + ) + ), ) common_source_voxel_spacing = self.common_metadata_value( metadata.source_voxel_spacing @@ -1643,42 +1802,19 @@ def compose(self) -> ImagePayloadMetadata: ) if common_source_voxel_spacing is None: common_source_voxel_spacing = SourceVoxelSpacing() - source_component_metadata_by_payload = tuple( - ( - metadata - if metadata.source_component_metadata is not None - else source_metadata - ) - for metadata, source_metadata in zip( - metadata_by_payload, - source_metadata_by_payload, - strict=True, - ) - ) return self.metadata_type( - source_path=self.common_metadata_value( - metadata.source_path for metadata in source_metadata_by_payload - ), - source_component_metadata=self.common_source_component_metadata( - source_component_metadata_by_payload - ), + source_provenance=source_provenance, source_plane_intensity_scales=tuple( - metadata.intensity_scale for metadata in source_plane_metadata_records + metadata.intensity_scale for metadata in source_metadata_by_payload ), source_plane_dtypes=tuple( - metadata.source_dtype for metadata in source_plane_metadata_records + metadata.source_dtype for metadata in source_metadata_by_payload ), - source_image_provenance_planes=composed_source_provenance_planes, unit_interval_intensity=self.composed_unit_interval_intensity( - source_plane_metadata_records + source_metadata_by_payload ), - source_spatial_domain=SourceSpatialDomain( - origin_yx=self.common_metadata_value( - metadata.spatial_origin_yx for metadata in metadata_by_payload - ), - source_shape_yx=self.common_metadata_value( - metadata.source_spatial_shape_yx for metadata in metadata_by_payload - ), + source_spatial_domain=SourceSpatialDomain.common_from_domains( + metadata.source_spatial_domain for metadata in metadata_by_payload ), source_voxel_spacing=common_source_voxel_spacing, physical_border_edges_yx=self.common_metadata_value( @@ -1687,33 +1823,10 @@ def compose(self) -> ImagePayloadMetadata: mask_defines_border=self.common_metadata_value( metadata.mask_defines_border for metadata in metadata_by_payload ), - source_image_names=( - composed_source_provenance_planes.runtime_source_image_names - ), source_channel_axis=self.composed_source_channel_axis(metadata_by_payload), plane_axis=self.mode.plane_axis, ) - def composed_source_provenance_planes( - self, - metadata_records: tuple[ImagePayloadMetadata, ...], - ) -> SourceImageProvenancePlanes: - """Compose projectable planes without replacing compatible topology.""" - - if len(metadata_records) == 1: - metadata = metadata_records[0] - provenance_planes = metadata.source_image_provenance_planes - if provenance_planes.count > 1 and self.mode.preserves_plane_topology( - metadata.plane_axis - ): - return provenance_planes - return SourceImageProvenancePlanes( - tuple( - self.runtime_source_provenance_plane(metadata) - for metadata in metadata_records - ) - ) - @staticmethod def composed_unit_interval_intensity( metadata_records: Sequence[ImagePayloadMetadata], @@ -1731,70 +1844,6 @@ def composed_unit_interval_intensity( ) ) - @staticmethod - def runtime_source_provenance_plane( - metadata: ImagePayloadMetadata, - ) -> RuntimeSourceImageProvenancePlane: - """Return one projectable plane with nested non-projectable contributors.""" - source_image_names = metadata.source_image_names - contributors = metadata.source_image_provenance_planes.as_contributors( - source_image_names - ).planes - if len(source_image_names) > 1: - raise ValueError( - "Composed image payload provenance permits at most one " - f"source alias per scalar plane, got {source_image_names!r}." - ) - source_image_name = source_image_names[0] if source_image_names else None - return RuntimeSourceImageProvenancePlane( - SourceImageIdentity( - metadata.source_path, - metadata.source_component_metadata, - ), - contributors, - source_image_name, - ) - - def common_source_component_metadata( - self, - values: Iterable[ImagePayloadMetadata], - ) -> SourceComponentMetadata | None: - """Return source metadata shared by the composed payload.""" - metadata_values = tuple(values) - metadata_by_plane = tuple( - dict(metadata.source_component_metadata) - for metadata in metadata_values - if metadata.source_component_metadata is not None - ) - if self.mode is ImagePayloadMetadataCompositionMode.BUNDLE: - field_names = set().union( - *(metadata.keys() for metadata in metadata_by_plane) - ) - common_metadata: dict[str, SourceMetadataValue] = {} - for field_name in field_names: - values_for_field = tuple( - metadata[field_name] - for metadata in metadata_by_plane - if field_name in metadata - ) - if values_for_field and all( - value == values_for_field[0] for value in values_for_field - ): - common_metadata[field_name] = values_for_field[0] - else: - common_metadata = dict( - common_source_component_metadata( - tuple( - metadata.source_component_metadata - for metadata in metadata_values - ) - ) - or {} - ) - if not common_metadata: - return None - return MappingProxyType(common_metadata) - @staticmethod def common_metadata_value( values: Iterable[MetadataValueT | None], diff --git a/openhcs/core/runtime_measurements.py b/openhcs/core/runtime_measurements.py index b0c613097d..55eb4bbb5d 100644 --- a/openhcs/core/runtime_measurements.py +++ b/openhcs/core/runtime_measurements.py @@ -75,9 +75,7 @@ def iter_row_mappings(self) -> Iterable[Mapping[str, object]]: return self.rows.iter_row_mappings() def __post_init__(self, *source_provenance_values: object) -> None: - self.absorb_explicit_source_provenance( - SourceImageProvenance.from_init_values(source_provenance_values) - ) + self.absorb_explicit_source_provenance(source_provenance_values) self.normalize_source_provenance_fields() self.validate_artifact_name() if self.source_image_name == "": @@ -138,6 +136,219 @@ def runtime_semantic_id(self) -> str: ) ) + @classmethod + def join(cls, name: str, tables: tuple[MeasurementTable, ...]) -> MeasurementTable: + """Concatenate tables with one exact subject, feature owner and image owner.""" + cls._require_join(name, tables) + if len(tables) == 1: + return tables[0] + subjects = tuple(dict.fromkeys(table.subject for table in tables)) + if len(subjects) != 1: + raise ValueError( + "Measurement table unions require one exact nominal subject; " + f"got {subjects!r}." + ) + owners = tuple( + dict.fromkeys(table.measurement_feature_owner for table in tables) + ) + if len(owners) != 1: + raise ValueError( + "Measurement table unions require one exact nominal measurement " + f"feature owner; got {owners!r}." + ) + source_names = tuple(dict.fromkeys(table.source_image_name for table in tables)) + if len(source_names) != 1: + raise ValueError( + "Measurement table unions require one exact source-image owner; " + f"got {source_names!r}." + ) + from openhcs.core.measurement_row_materialization import ( + ConcatenatedColumnarRows, + ) + + return cls( + name=name, + rows=ConcatenatedColumnarRows(tuple(table.rows for table in tables)), + source_image_name=source_names[0], + subject=subjects[0], + measurement_feature_owner=owners[0], + source_provenance=cls.joined_source_provenance(name, tables), + ) + + @classmethod + def join_artifact( + cls, name: str, tables: tuple[MeasurementTable, ...] + ) -> MeasurementTable: + """Re-own mixed subject rows as one lossless artifact-level export table.""" + cls._require_join(name, tables) + from openhcs.core.measurement_row_materialization import ( + ConcatenatedColumnarRows, + MeasurementRowOwnership, + ) + + return cls( + name=name, + rows=ConcatenatedColumnarRows( + tuple( + MeasurementRowOwnership( + object_name=table.subject.object_name, + source_image_name=( + table.source_image_name or table.subject.source_image_name + ), + ).annotate_rows(table.rows) + for table in tables + ) + ), + subject=MeasurementSubject(MeasurementScope.ARTIFACT, name), + source_provenance=cls.joined_source_provenance(name, tables), + ) + + @staticmethod + def _require_join(name: str, tables: tuple[MeasurementTable, ...]) -> None: + if not name: + raise ValueError("MeasurementTable join name cannot be empty.") + if not tables: + raise ValueError("MeasurementTable join tables cannot be empty.") + + @classmethod + def joined_source_provenance( + cls, name: str, tables: tuple[MeasurementTable, ...] + ) -> SourceImageProvenance: + """Compose exact table provenance on its declared runtime-slice axis.""" + cls._require_join(name, tables) + if len(tables) == 1: + return tables[0].source_provenance + slice_axis = MeasurementRowAxisField.SLICE_INDEX + table_domains = cls._row_axis_domains(name, tables, slice_axis) + if table_domains is None: + sources = tuple(table.source_provenance for table in tables) + if not any(source.has_values for source in sources): + return SourceImageProvenance() + return SourceImageProvenance.stack( + tuple( + ( + source.for_source_plane(0) + if source.source_plane_count == 1 + else source + ) + for source in sources + ), + scalar_sources=sources, + ) + axis_domain = tuple( + sorted({value for domain in table_domains for value in domain}) + ) + declared_plane_counts = tuple( + table.source_provenance.source_plane_count + for table in tables + if table.source_provenance.source_plane_count > 0 + ) + distinct_plane_counts = tuple(dict.fromkeys(declared_plane_counts)) + if len(distinct_plane_counts) > 1: + raise ValueError( + f"Measurement table union {name!r} cannot align declared " + f"source-plane counts {distinct_plane_counts!r}." + ) + axis_size = ( + distinct_plane_counts[0] if distinct_plane_counts else max(axis_domain) + 1 + ) + if max(axis_domain) >= axis_size: + raise ValueError( + f"Measurement table union {name!r} declares " + f"{slice_axis.value}={max(axis_domain)} beyond its source-plane " + f"axis of size {axis_size}." + ) + for table, domain in zip(tables, table_domains, strict=True): + provenance = table.source_provenance + if ( + provenance.source_plane_count == 0 + and provenance.has_values + and len(domain) > 1 + ): + raise ValueError( + f"Measurement table {table.name!r} carries scalar source " + f"provenance for multiple {slice_axis.value} values {domain!r}." + ) + planes: list[SourceImageProvenance] = [] + for plane_index in range(axis_size): + sources = tuple( + ( + table.source_provenance.for_source_plane(plane_index) + if table.source_provenance.source_plane_count > 0 + else table.source_provenance + ) + for table, domain in zip(tables, table_domains, strict=True) + if table.source_provenance.source_plane_count > 0 + or domain == (plane_index,) + ) + if not sources: + raise ValueError( + f"Measurement table union {name!r} has no declared " + f"source provenance for {slice_axis.value}={plane_index}." + ) + planes.append( + sources[0] + if len(sources) == 1 + else ( + SourceImageProvenance.bundle( + sources + ).with_runtime_planes_as_contributors() + if any(source.has_values for source in sources) + else SourceImageProvenance() + ) + ) + return ( + SourceImageProvenance.stack(tuple(planes)) + if any(plane.has_values for plane in planes) + else SourceImageProvenance() + ) + + @classmethod + def shared_row_axis_domain( + cls, + name: str, + tables: tuple[MeasurementTable, ...], + axis: MeasurementRowAxisField, + ) -> tuple[int, ...] | None: + """Return the exact joined row-axis domain, or None for axisless rows.""" + cls._require_join(name, tables) + domains = cls._row_axis_domains(name, tables, axis) + if domains is None: + return None + return tuple(sorted({value for domain in domains for value in domain})) + + @staticmethod + def _row_axis_domains( + name: str, tables: tuple[MeasurementTable, ...], axis: MeasurementRowAxisField + ) -> tuple[tuple[int, ...], ...] | None: + from openhcs.core.measurement_row_materialization import ( + MeasurementRowsAxisProjection, + ) + + projections = tuple( + MeasurementRowsAxisProjection.from_rows(table.rows) for table in tables + ) + declarations = tuple( + projection.declares_axis_field(axis) + or any(field.name == axis.value for field in table.rows.fields) + for table, projection in zip(tables, projections, strict=True) + ) + if not any(declarations): + return None + domains = tuple( + projection.present_axis_values(axis.value) for projection in projections + ) + if not any(domains): + return None + for table, projection, domain in zip(tables, projections, domains, strict=True): + if projection.has_rows and not domain: + raise ValueError( + f"Measurement table union {name!r} mixes declared and " + f"axisless {axis.value!r} row domains; table {table.name!r} " + "declares no concrete axis value." + ) + return domains + @dataclass(frozen=True, slots=True) class ObjectLabelMeasurementValues: @@ -1135,6 +1346,14 @@ def token(self) -> str | None: return stripped or None return None + @classmethod + def non_absent_values(cls, values: Sequence[object]) -> np.ndarray: + """Classify physical cells while retaining explicit nonfinite values.""" + if isinstance(values, np.ndarray) and values.dtype.kind in "iuf": + return np.ones(values.shape, dtype=bool) + array = np.asarray(values, dtype=object) + return np.asarray([not cls(value).is_absent for value in array], dtype=bool) + @property def is_absent(self) -> bool: return self.token is None diff --git a/openhcs/core/runtime_object_label_building.py b/openhcs/core/runtime_object_label_building.py index cac8c54e0a..e47b3b06a2 100644 --- a/openhcs/core/runtime_object_label_building.py +++ b/openhcs/core/runtime_object_label_building.py @@ -142,18 +142,9 @@ def plane_semantics(self) -> RuntimePlaneAxisValueProjection | None: ) return None metadata = self.metadata - declared_projection = RuntimePlaneAxisValueProjection.from_source_declaration( + projection.validate_source_declaration( metadata.plane_axis, metadata.source_provenance, ) - if declared_projection is not None: - if ( - projection.axis is not declared_projection.axis - or projection.axis_size != declared_projection.axis_size - ): - raise ValueError( - "Object-label plane projection conflicts with the source-image " - "axis declaration." - ) label_array = np.asarray(self.labels) projection.validate_shape( label_array.shape, diff --git a/openhcs/core/runtime_object_labels.py b/openhcs/core/runtime_object_labels.py index 69e07dbd46..396e677ae6 100644 --- a/openhcs/core/runtime_object_labels.py +++ b/openhcs/core/runtime_object_labels.py @@ -6,6 +6,7 @@ from collections.abc import ( Callable, Hashable, + Iterable, MutableMapping, Sequence, ) @@ -14,6 +15,7 @@ import numpy as np from metaclass_registry import AutoRegisterMeta +from numba import njit from openhcs.core import ( runtime_array_values, @@ -28,6 +30,7 @@ NominalTypeStrategyFamilyMixin, ) from openhcs.core.runtime_object_label_domains import ( + DenseIntegerObjectLabelIdDomain, ObjectLabelDomain, ObjectLabelDomainDeclaration, ObjectLabelDomainMetadata, @@ -928,9 +931,7 @@ class ObjectLabelPayload(ObjectLabelValue): def __post_init__(self, *source_provenance_values: object) -> None: self.validate_object_label_variants() - self.absorb_explicit_source_provenance( - SourceImageProvenance.from_init_values(source_provenance_values) - ) + self.absorb_explicit_source_provenance(source_provenance_values) self.normalize_object_label_metadata("ObjectLabelPayload") @@ -994,9 +995,7 @@ def from_payload( def __post_init__(self, *source_provenance_values: object) -> None: self.validate_object_label_variants() - self.absorb_explicit_source_provenance( - SourceImageProvenance.from_init_values(source_provenance_values) - ) + self.absorb_explicit_source_provenance(source_provenance_values) self.validate_artifact_name() if self.source_image_name == "": raise ValueError("ObjectLabelSet.source_image_name cannot be empty.") @@ -1115,14 +1114,30 @@ def axis_centers( if sparse_labels.has_slice_index else (sparse_labels.y_column, sparse_labels.x_column) ) + return self.coordinate_centers( + counts, + ( + np.bincount( + object_ids, + weights=array[:, coordinate_column], + minlength=max_label + 1, + ) + for coordinate_column in coordinate_columns + ), + maximum_label=max_label, + ) + + @staticmethod + def coordinate_centers( + counts: np.ndarray, + coordinate_sums: Iterable[np.ndarray], + *, + maximum_label: int, + ) -> tuple[tuple[np.ndarray, ...], np.ndarray]: + """Allocate and divide each coordinate sum in its declared ID domain.""" axis_centers: list[np.ndarray] = [] - for coordinate_column in coordinate_columns: - sums = np.bincount( - object_ids, - weights=array[:, coordinate_column], - minlength=max_label + 1, - ) - centers = np.full(max_label + 1, np.nan, dtype=np.float64) + for sums in coordinate_sums: + centers = np.full(maximum_label + 1, np.nan, dtype=np.float64) np.divide(sums, counts, out=centers, where=counts > 0) axis_centers.append(centers) return tuple(axis_centers), counts @@ -1202,6 +1217,62 @@ def dense_data( def sparse_ijv_rows(self, labels: object) -> SparseIJVLabelRows: return SparseIJVLabelRows.from_dense_stack(cast(np.ndarray, labels)) + @classmethod + def prepare_coordinates(cls) -> None: + """Prepare C/F/strided signatures with both input mutability policies.""" + plane = np.array([[0, 1], [1, 0]], dtype=np.int32) + volume = np.stack((plane, plane)) + for labels in (volume, np.asfortranarray(volume), volume.copy()[..., ::-1]): + for writeable in (True, False): + labels.flags.writeable = writeable + _dense_label_coordinate_moments_numba(labels, 1) + for labels in (plane, np.asfortranarray(plane), plane.copy()[:, ::-1]): + for writeable in (True, False): + labels.flags.writeable = writeable + dense_label_centers_2d_numba(labels, 1) + + def axis_centers( + self, labels: object, *, domain: Sequence[int] + ) -> tuple[tuple[np.ndarray, ...], np.ndarray]: + array = np.asarray(labels) + if ( + array.dtype != np.dtype(np.int32) + or array.ndim not in (2, 3) + or any(size > np.iinfo(np.int32).max for size in array.shape) + ): + return super().axis_centers(labels, domain=domain) + coordinate_planes = array[None, ...] if array.ndim == 2 else array + positive_parts = tuple(plane[plane > 0] for plane in coordinate_planes) + coordinate_domain = DenseIntegerObjectLabelIdDomain.from_array( + np.concatenate(positive_parts or (np.empty(0, dtype=np.int32),)) + ) + del positive_parts + if coordinate_domain is None: + return super().axis_centers(labels, domain=domain) + coordinate_columns = tuple(range(3 - array.ndim, 3)) + sums, pixel_counts = _dense_label_coordinate_moments_numba( + coordinate_planes, coordinate_domain.max_label, + ) + del coordinate_domain + # Like sparse conversion, the moments snapshot precedes domain callbacks. + object_ids = np.flatnonzero(pixel_counts) + max_domain_label = max(domain, default=0) + maximum_label = max(int(object_ids.max(initial=0)), max_domain_label) + counts = np.bincount(object_ids, minlength=maximum_label + 1) + counts[object_ids] = pixel_counts[object_ids] + return self.coordinate_centers( + counts, + ( + np.bincount( + object_ids, + weights=sums[object_ids, coordinate_column], + minlength=maximum_label + 1, + ) + for coordinate_column in coordinate_columns + ), + maximum_label=maximum_label, + ) + def stack_planes( self, labels: Sequence[object], @@ -1403,6 +1474,14 @@ def sparse_ijv_rows(self, labels: object) -> SparseIJVLabelRows: label_data ) + def axis_centers( + self, labels: object, *, domain: Sequence[int] + ) -> tuple[tuple[np.ndarray, ...], np.ndarray]: + label_data = self.label_data(labels) + return ObjectLabelStorageStrategy.for_value(label_data).axis_centers( + label_data, domain=domain + ) + def stack_planes( self, labels: Sequence[object], @@ -1555,6 +1634,46 @@ def object_label_axis_centers( ) +@njit(cache=True) +def _dense_label_coordinate_moments_numba( + labels: np.ndarray, + maximum_label: int, +) -> tuple[np.ndarray, np.ndarray]: + """Reduce dense positive labels once in their declared row-major geometry.""" + sums = np.zeros((maximum_label + 1, 3), dtype=np.float64) + counts = np.zeros(maximum_label + 1, dtype=np.int64) + plane_count, height, width = labels.shape + for plane in range(plane_count): + for y in range(height): + for x in range(width): + label_id = int(labels[plane, y, x]) + if label_id > 0 and label_id <= maximum_label: + sums[label_id, 0] += plane + sums[label_id, 1] += y + sums[label_id, 2] += x + counts[label_id] += 1 + return sums, counts + + +@njit(cache=True) +def dense_label_centers_2d_numba( + labels: np.ndarray, label_count: int +) -> np.ndarray: + """Validate compiled two-dimensional geometry and return its y/x centers.""" + height, width = labels.shape + sums, counts = _dense_label_coordinate_moments_numba( + labels[None, :height, :width], label_count + ) + centers = np.empty((label_count + 1, 2), dtype=np.float64) + for label_id in range(label_count + 1): + for axis in range(2): + centers[label_id, axis] = ( + np.nan if counts[label_id] == 0 + else sums[label_id, axis + 1] / counts[label_id] + ) + return centers + + def object_label_storage_is_sparse_ijv(payload: object) -> bool: """Return whether the nominal storage authority owns sparse-IJV rows.""" authority = ObjectLabelStorageStrategy.for_value(payload) diff --git a/openhcs/core/runtime_output_matching.py b/openhcs/core/runtime_output_matching.py index 44cc127d39..7e6dd98b49 100644 --- a/openhcs/core/runtime_output_matching.py +++ b/openhcs/core/runtime_output_matching.py @@ -9,6 +9,7 @@ from openhcs.core.aligned_image_payload import ( AlignedImageSliceContext, AlignedImageStack, + pack_aligned_image_outputs, ) from openhcs.core.artifacts import ( ArtifactOutputPlan, @@ -16,6 +17,12 @@ ArtifactSpecRef, ) from openhcs.core.callable_contract import CallableContract +from openhcs.core.runtime_image_values import image_payload_metadata +from openhcs.core.runtime_plane_projection import RuntimePlaneAxisValueProjection +from openhcs.core.runtime_slice_projection import ( + RuntimeSliceProjection, + RuntimeSliceProjectionDeclarationError, +) class RuntimeOutputBundle(ABC): @@ -61,6 +68,75 @@ def canonical_output(self) -> Any: return split_runtime_output(self.returned_output)[0] + def contextualize_canonical_output( + self, + *, + plane_projection: RuntimePlaneAxisValueProjection | None = None, + ) -> Any: + """Attach the compiled canonical ABI to one exact returned image axis.""" + + canonical_specs = self.callable_contract.canonical_return_output_specs.specs + if len(canonical_specs) <= 1: + return self.returned_output + canonical_output, trailing_outputs = split_runtime_output(self.returned_output) + if isinstance(canonical_output, AlignedImageStack): + if canonical_output.slice_contexts: + return self.returned_output + output_values = canonical_output.slices + else: + projection = plane_projection + function_name = self.callable_contract.function_name + if projection is None: + raise RuntimeSliceProjectionDeclarationError( + f"{function_name} declares {len(canonical_specs)} canonical " + "outputs but returned a non-aligned payload without a " + "compiled plane projection." + ) + if projection.plane_index is not None: + raise RuntimeSliceProjectionDeclarationError( + f"{function_name} declares {len(canonical_specs)} canonical " + "outputs after the compiled plane projection already selected " + f"plane {projection.plane_index}." + ) + if projection.axis_size != len(canonical_specs): + raise ValueError( + f"{function_name} declares {len(canonical_specs)} canonical " + "outputs but its compiled plane projection declares " + f"{projection.axis_size} value(s)." + ) + output_axis = image_payload_metadata(canonical_output).plane_axis + if output_axis is not projection.axis: + raise RuntimeSliceProjectionDeclarationError( + f"{function_name} declares {len(canonical_specs)} canonical " + "outputs but its returned payload does not declare the " + f"compiled {projection.axis.value!r} plane axis; got " + f"{output_axis!r}." + ) + output_values = tuple( + RuntimeSliceProjection.value_for_slice( + canonical_output, + projection.selected_plane(output_index), + ) + for output_index in range(projection.axis_size) + ) + if len(output_values) != len(canonical_specs): + raise ValueError( + f"{self.callable_contract.function_name} returned {len(output_values)} " + "canonical output value(s) for " + f"{len(canonical_specs)} compiled output spec(s)." + ) + contextualized_output = pack_aligned_image_outputs( + output_values, + slice_contexts=AlignedImageSliceContext.main_flow_for_artifact_specs( + canonical_specs + ), + ) + return ( + (contextualized_output, *trailing_outputs) + if trailing_outputs + else contextualized_output + ) + def resolve(self) -> dict[ArtifactSpecRef, Any]: """Resolve every output in the callable ABI.""" @@ -85,12 +161,18 @@ def resolve(self) -> dict[ArtifactSpecRef, Any]: strict=True, ) } - resolved.update( - self._canonical_values( - self.callable_contract.canonical_return_output_specs.specs, - canonical_output, + canonical_specs = self.callable_contract.canonical_return_output_specs.specs + if len(canonical_specs) == 1: + resolved[canonical_specs[0].ref()] = canonical_output + elif canonical_specs: + if not isinstance(canonical_output, AlignedImageStack): + raise TypeError( + "Multiple canonical output specs require an AlignedImageStack with " + "one exact named slice context per output." + ) + resolved.update( + canonical_output.output_values_for_artifact_specs(canonical_specs) ) - ) return resolved def resolve_plan_values( @@ -129,70 +211,6 @@ def resolve_plan_values( matched_outputs.append((plan, spec, returned_values[ref])) return returned_values, tuple(matched_outputs) - @classmethod - def _canonical_values( - cls, - canonical_specs: tuple[ArtifactSpec, ...], - canonical_output: Any, - ) -> dict[ArtifactSpecRef, Any]: - """Resolve named outputs represented by the one canonical return slot.""" - - if not canonical_specs: - return {} - if len(canonical_specs) == 1: - spec = canonical_specs[0] - return {spec.ref(): canonical_output} - if not isinstance(canonical_output, AlignedImageStack): - raise TypeError( - "Multiple canonical output specs require an AlignedImageStack with " - "one exact named slice context per output." - ) - if not canonical_output.slice_contexts: - raise ValueError( - "Multiple canonical output specs require exact AlignedImageStack " - "slice contexts; positional slice order is not artifact identity." - ) - - specs_by_context = { - (spec.name, spec.artifact_type.value): spec for spec in canonical_specs - } - if len(specs_by_context) != len(canonical_specs): - raise ValueError("Canonical output ABI contains duplicate named contexts.") - resolved: dict[ArtifactSpecRef, Any] = {} - for payload, context in zip( - canonical_output.slices, - canonical_output.slice_contexts, - strict=True, - ): - if context.output_kind != AlignedImageSliceContext.MAIN_FLOW_OUTPUT_KIND: - raise ValueError( - "Canonical AlignedImageStack contains a non-main-flow slice " - f"context: {context!r}." - ) - context_key = (context.output_key, context.artifact_kind) - spec = specs_by_context.get(context_key) - if spec is None: - raise ValueError( - "Canonical AlignedImageStack context is not declared by the " - f"callable ABI: {context!r}." - ) - ref = spec.ref() - if ref in resolved: - raise ValueError( - "Canonical AlignedImageStack contains duplicate context for " - f"{ref!r}." - ) - resolved[ref] = payload - missing = tuple( - spec.ref() for spec in canonical_specs if spec.ref() not in resolved - ) - if missing: - raise ValueError( - "Canonical AlignedImageStack does not carry every declared output: " - f"{missing!r}." - ) - return resolved - @staticmethod def _specs_by_ref( specs: tuple[ArtifactSpec, ...], diff --git a/openhcs/core/runtime_plane_projection.py b/openhcs/core/runtime_plane_projection.py index fe1bf18bc0..9f7affad17 100644 --- a/openhcs/core/runtime_plane_projection.py +++ b/openhcs/core/runtime_plane_projection.py @@ -297,6 +297,21 @@ def from_projector( axis_size=axis_size, ) + def validate_source_declaration( + self, axis: RuntimePlaneAxis | None, source: "SourceImageProvenance", + ) -> None: + """Check an explicit projection against retained acquisition declarations.""" + if axis is None: + return + declared_count = source.source_plane_count + if self.axis is not axis or ( + declared_count > 0 and self.axis_size != declared_count + ): + raise ValueError( + "Object-label plane projection conflicts with the source-image " + "axis declaration." + ) + @classmethod def require_from_projector( cls, diff --git a/openhcs/core/runtime_relationships.py b/openhcs/core/runtime_relationships.py index 5330ec6cf1..dfadd0035c 100644 --- a/openhcs/core/runtime_relationships.py +++ b/openhcs/core/runtime_relationships.py @@ -358,9 +358,7 @@ def from_payload( def __post_init__(self, *source_provenance_values: object) -> None: self.validate_artifact_name() - self.absorb_explicit_source_provenance( - SourceImageProvenance.from_init_values(source_provenance_values) - ) + self.absorb_explicit_source_provenance(source_provenance_values) self.normalize_source_provenance_fields() if not isinstance(self.declaration, ObjectRelationshipDeclaration): raise TypeError( diff --git a/openhcs/core/runtime_slice_projection.py b/openhcs/core/runtime_slice_projection.py index 283b9a9e84..5cfc599d49 100644 --- a/openhcs/core/runtime_slice_projection.py +++ b/openhcs/core/runtime_slice_projection.py @@ -6,7 +6,8 @@ from collections.abc import Iterable, Mapping, Sequence from dataclasses import dataclass, field from enum import Enum -from typing import ClassVar, TypeAlias, cast, overload +from functools import lru_cache +from typing import Any, ClassVar, TypeAlias, cast, overload import numpy as np import numpy.typing as npt @@ -14,7 +15,11 @@ from metaclass_registry import AutoRegisterMeta from openhcs.constants.constants import VariableComponents -from openhcs.core.aligned_image_payload import AlignedImageStack, ImageOutputBundle +from openhcs.core.aligned_image_payload import ( + AlignedImageStack, + AlignedImageStackKwargResolver, + ImageOutputBundle, +) from openhcs.core.measurement_row_materialization import MeasurementRowsAxisProjection from openhcs.core.registry_strategies import ( EnumKeyedStrategyMixin, @@ -23,11 +28,11 @@ from openhcs.core.runtime_array_values import RuntimeArrayData, is_array_payload from openhcs.core.runtime_artifact_queries import ( MeasurementTableAxisProjection, - MeasurementTableUnion, ) from openhcs.core.runtime_image_values import ( ImageMetadataPayload, ImagePayloadMetadata, + ImagePayloadMetadataCarrier, MaskedImagePayload, image_payload_data, image_payload_geometry, @@ -405,6 +410,54 @@ def strategy_for_value( f"{type(value).__name__}." ) + @classmethod + def aligned_kwarg_member(cls) -> type | tuple[type, ...] | None: + """Derive aligned participation from this class's operation implementation.""" + return ( + None + if cls.resolve_aligned_kwarg + is RuntimeSliceProjectionStrategy.resolve_aligned_kwarg + else cls.value_type + ) + + @classmethod + def aligned_strategy_members( + cls, + ) -> Iterable[ + tuple[type[RuntimeSliceProjectionStrategy], type | tuple[type, ...] | None] + ]: + """Project aligned operation ownership from the single nominal family.""" + for strategy_type in cls.registered_strategy_types(): + yield strategy_type, strategy_type.aligned_kwarg_member() + + @classmethod + def aligned_kwarg_value( + cls, value: Any, resolver: AlignedImageStackKwargResolver, + ) -> Any: + """Apply aligned semantics without declaring unknown values projectable.""" + strategies = cls.strategy_types_for_aligned_kwarg_type(type(value)) + if not strategies: + return value + return strategies[0]().resolve_aligned_kwarg(value, resolver) + + @classmethod + @lru_cache(maxsize=None) + def strategy_types_for_aligned_kwarg_type( + cls, + value_type: type, + ) -> tuple[type[RuntimeSliceProjectionStrategy], ...]: + """Cache the aligned view under the same nominal registry mutation contract.""" + return cls.order_nominal_strategy_members( + value_type, cls.aligned_strategy_members(), + ) + + def resolve_aligned_kwarg( + self, value: Any, resolver: AlignedImageStackKwargResolver, + ) -> Any: + """Preserve families with no declared aligned-argument operation.""" + del resolver + return value + def value_for_slice( self, value: RuntimeProjectionData, @@ -466,6 +519,21 @@ class ImagePayloadRuntimeSliceProjectionStrategy(RuntimeSliceProjectionStrategy) value_type = (ImageMetadataPayload, MaskedImagePayload) + @classmethod + def aligned_kwarg_member(cls) -> type | tuple[type, ...] | None: + return ( + ImagePayloadMetadataCarrier + if cls.value_type is ImagePayloadRuntimeSliceProjectionStrategy.value_type + else cls.value_type + ) + + def resolve_aligned_kwarg( + self, + value: Any, + resolver: AlignedImageStackKwargResolver, + ) -> Any: + return resolver.resolve_source_spatial_value(value) + def slice_count_for_value( self, value: RuntimeProjectionData, @@ -510,6 +578,18 @@ class AlignedImageStackRuntimeSliceProjectionStrategy(RuntimeSliceProjectionStra value_type = AlignedImageStack + def resolve_aligned_kwarg( + self, + value: Any, + resolver: AlignedImageStackKwargResolver, + ) -> Any: + return resolver.resolve( + value.aligned_slice( + resolver.projection_axis.require_plane_index(), + resolver.projection_axis.axis_size, + ) + ) + def full_stack_value(self, value: RuntimeProjectionData) -> RuntimeProjectionData: return cast(AlignedImageStack, value).compose() @@ -644,6 +724,21 @@ class RuntimeSliceAlignedValueProjectionStrategy( value_type = RuntimeSliceAlignedValueSet + def resolve_aligned_kwarg( + self, + value: Any, + resolver: AlignedImageStackKwargResolver, + ) -> Any: + if not isinstance(value, RuntimeSliceAlignedValueSet): + raise TypeError( + "Aligned kwarg resolution requires " + "RuntimeSliceAlignedValueSet." + ) + return value.value_for_aligned_slice( + resolver.projection_axis.require_plane_index(), + resolver.projection_axis.axis_size, + ) + def value_for_slice( self, value: RuntimeProjectionData, @@ -705,8 +800,8 @@ def slice_count_for_value( @staticmethod def row_axis_domain(table: MeasurementTable) -> tuple[int, ...] | None: - return MeasurementTableUnion(table.name, (table,)).row_axis_domain( - MeasurementRowAxisField.SLICE_INDEX + return MeasurementTable.shared_row_axis_domain( + table.name, (table,), MeasurementRowAxisField.SLICE_INDEX ) @@ -734,6 +829,16 @@ class RuntimeSliceProjectableValueProjectionStrategy( value_type = RuntimeSliceProjectableValue + def resolve_aligned_kwarg( + self, + value: Any, + resolver: AlignedImageStackKwargResolver, + ) -> Any: + return RuntimeSliceProjection.value_for_slice( + value, + resolver.projection_axis, + ) + def value_for_slice( self, value: RuntimeProjectionData, @@ -798,6 +903,31 @@ class ObjectLabelValueRuntimeSliceProjectionStrategy( value_type = ObjectLabelValue + def resolve_aligned_kwarg( + self, + value: Any, + resolver: AlignedImageStackKwargResolver, + ) -> Any: + if not isinstance(value, ObjectLabelValue): + raise TypeError( + "Object-label aligned kwarg resolution requires ObjectLabelValue." + ) + slice_count = value.runtime_slice_plane_count() + if slice_count is not None: + if slice_count != resolver.projection_axis.axis_size: + raise ValueError( + "Runtime-slice object-label cardinality must exactly match the " + f"declared projection axis: {slice_count} != " + f"{resolver.projection_axis.axis_size}." + ) + projected = RuntimeSliceProjection.value_for_slice( + value, + resolver.projection_axis, + ) + else: + projected = value + return resolver.resolve_source_spatial_value(projected) + def slice_count_for_value( self, value: RuntimeProjectionData, @@ -855,6 +985,21 @@ class SequenceRuntimeSliceProjectionStrategy(RuntimeSliceProjectionStrategy): value_type = (tuple, list) + @classmethod + def aligned_kwarg_member(cls) -> type | tuple[type, ...] | None: + return ( + tuple + if cls.value_type is SequenceRuntimeSliceProjectionStrategy.value_type + else cls.value_type + ) + + def resolve_aligned_kwarg( + self, + value: Any, + resolver: AlignedImageStackKwargResolver, + ) -> Any: + return tuple(resolver.resolve(item) for item in value) + def value_for_slice( self, value: RuntimeProjectionData, diff --git a/openhcs/core/runtime_source_binding_cache.py b/openhcs/core/runtime_source_binding_cache.py index 7e2ffb242d..9e6a311a47 100644 --- a/openhcs/core/runtime_source_binding_cache.py +++ b/openhcs/core/runtime_source_binding_cache.py @@ -3,17 +3,86 @@ from __future__ import annotations from collections.abc import Mapping -from dataclasses import dataclass, field -from typing import Any, TYPE_CHECKING +from dataclasses import dataclass, field, replace +from types import MappingProxyType +from typing import Any, Hashable, TYPE_CHECKING from openhcs.core.source_bindings import ( - SourceBindingRuntimeContext, SourceBindingRuntimeMetadataNormalizer, + MetadataExtractionRule, +) +from openhcs.core.source_metadata import ( + ResolvedSourceMetadataRecord, + SourceMetadataMapping, ) -from openhcs.core.source_metadata import SourceMetadataMapping if TYPE_CHECKING: - from openhcs.core.source_binding_selection import SourceUniverseRuntimeState + from openhcs.core.source_binding_selection import ( + SourcePatternResolutionContext, + SourceUniverseRuntimeState, + ) + from openhcs.core.source_workspace_projection import ( + VirtualWorkspaceSourceProjection, + ) + from openhcs.microscopes.microscope_interfaces import FilenameParser + + +@dataclass(frozen=True, slots=True) +class RuntimeSourceResolutionSnapshot: + """A derived resolution view retaining its exact projection and parser owners.""" + + projection: "VirtualWorkspaceSourceProjection" + context: "SourcePatternResolutionContext" + + @classmethod + def from_projection( + cls, + *, + parser: "FilenameParser", + projection: "VirtualWorkspaceSourceProjection", + metadata_rules: tuple[MetadataExtractionRule, ...], + ) -> "RuntimeSourceResolutionSnapshot": + """Resolve declared positions into one independently owned runtime view.""" + from openhcs.core.source_binding_selection import ( + DeclaredSourceMetadataRecord, + SourcePatternResolutionContext, + ) + + context = SourcePatternResolutionContext.from_projection( + parser=parser, + projection=projection, + metadata_rules=metadata_rules, + ) + normalized_metadata = SourceBindingRuntimeMetadataNormalizer( + projection.source_metadata_by_path + ).normalized() + context = replace( + context, + source_metadata_by_path=MappingProxyType( + { + path: DeclaredSourceMetadataRecord.from_mapping(metadata) + for path, metadata in normalized_metadata.items() + } + ), + source_projections_by_virtual_path=MappingProxyType( + dict(context.source_projections_by_virtual_path) + ), + ) + paths = dict.fromkeys( + ( + *context.source_metadata_by_path, + *context.source_paths_by_virtual_path, + *context.source_paths_by_virtual_path.values(), + ) + ) + records = {} + for path in paths: + metadata = context.metadata_for_path(path) + records[path] = ResolvedSourceMetadataRecord.from_mapping( + {} if metadata is None else metadata + ) + context = replace(context, source_metadata_by_path=MappingProxyType(records)) + return cls(projection=projection, context=context) @dataclass(slots=True) @@ -24,14 +93,38 @@ class RuntimeSourceBindingContextCache: int, Mapping[str, SourceMetadataMapping], ] = field(default_factory=dict) - runtime_context_by_request_identity: dict[ - tuple[int, tuple[str, ...], object, int | None], - SourceBindingRuntimeContext, - ] = field(default_factory=dict) runtime_universe_state_by_request_identity: dict[ tuple[int, tuple[str, ...], object, int | None], "SourceUniverseRuntimeState", ] = field(default_factory=dict) + source_resolution_snapshots: dict[ + tuple[int, int, tuple[Hashable, ...], tuple[MetadataExtractionRule, ...]], + RuntimeSourceResolutionSnapshot, + ] = field(default_factory=dict) + + def source_pattern_context( + self, + *, + parser: "FilenameParser", + projection: "VirtualWorkspaceSourceProjection", + metadata_rules: tuple[MetadataExtractionRule, ...], + ) -> "SourcePatternResolutionContext": + """Own one normalized runtime snapshot for exact source declarations.""" + key = (id(projection), id(parser), parser.semantic_identity(), metadata_rules) + cached = self.source_resolution_snapshots.get(key) + if cached is not None: + return cached.context + snapshot = RuntimeSourceResolutionSnapshot.from_projection( + parser=parser, + projection=projection, + metadata_rules=metadata_rules, + ) + self.source_resolution_snapshots[key] = snapshot + return snapshot.context + + def __reduce__(self) -> tuple[type[RuntimeSourceBindingContextCache], tuple[()]]: + """Transport reconstructs all derived caches from declaration defaults.""" + return type(self), () def normalized_source_metadata( self, @@ -47,24 +140,6 @@ def normalized_source_metadata( self.source_metadata_by_mapping_identity[cache_key] = cached return cached - def runtime_context( - self, - *, - plan: Any, - matching_files: tuple[str, ...], - source_backend: object, - source_projection: object | None, - ) -> SourceBindingRuntimeContext | None: - """Return a cached runtime context for one immutable request identity.""" - return self.runtime_context_by_request_identity.get( - self.runtime_context_key( - plan=plan, - matching_files=matching_files, - source_backend=source_backend, - source_projection=source_projection, - ) - ) - def runtime_universe_state( self, *, @@ -75,7 +150,7 @@ def runtime_universe_state( ) -> "SourceUniverseRuntimeState | None": """Return cached source-universe state for one request identity.""" return self.runtime_universe_state_by_request_identity.get( - self.runtime_context_key( + self.runtime_universe_state_key( plan=plan, matching_files=matching_files, source_backend=source_backend, @@ -94,7 +169,7 @@ def store_runtime_universe_state( ) -> "SourceUniverseRuntimeState": """Cache source-universe state for one request identity.""" self.runtime_universe_state_by_request_identity[ - self.runtime_context_key( + self.runtime_universe_state_key( plan=plan, matching_files=matching_files, source_backend=source_backend, @@ -103,35 +178,15 @@ def store_runtime_universe_state( ] = runtime_state return runtime_state - def store_runtime_context( - self, - runtime_context: SourceBindingRuntimeContext, - *, - plan: Any, - matching_files: tuple[str, ...], - source_backend: object, - source_projection: object | None, - ) -> SourceBindingRuntimeContext: - """Cache a runtime context for one immutable request identity.""" - self.runtime_context_by_request_identity[ - self.runtime_context_key( - plan=plan, - matching_files=matching_files, - source_backend=source_backend, - source_projection=source_projection, - ) - ] = runtime_context - return runtime_context - @staticmethod - def runtime_context_key( + def runtime_universe_state_key( *, plan: Any, matching_files: tuple[str, ...], source_backend: object, source_projection: object | None, ) -> tuple[int, tuple[str, ...], object, int | None]: - """Return the process-local identity for one source runtime context.""" + """Return the process-local identity for one source-universe request.""" return ( id(plan), tuple(matching_files), diff --git a/openhcs/core/runtime_spatial_graph.py b/openhcs/core/runtime_spatial_graph.py index f12cc3abaf..db26f65412 100644 --- a/openhcs/core/runtime_spatial_graph.py +++ b/openhcs/core/runtime_spatial_graph.py @@ -201,9 +201,7 @@ class SpatialGraph(SourceImageProvenanceFields, NamedArtifactPayload): source_plane_index: int | None = None def __post_init__(self, *source_provenance_values: object) -> None: - self.absorb_explicit_source_provenance( - SourceImageProvenance.from_init_values(source_provenance_values) - ) + self.absorb_explicit_source_provenance(source_provenance_values) self.normalize_source_provenance_fields() self.validate_artifact_name() nodes = tuple(self.nodes) diff --git a/openhcs/core/runtime_stack_cache.py b/openhcs/core/runtime_stack_cache.py index 4b92cb0020..6c2248777b 100644 --- a/openhcs/core/runtime_stack_cache.py +++ b/openhcs/core/runtime_stack_cache.py @@ -27,18 +27,11 @@ def from_paths( return cls(tuple(str(path) for path in paths), str(memory_type)) -@dataclass(frozen=True, slots=True) -class RuntimeImageStackCacheValue: - """Cached payload for an ordered runtime-slice path set.""" - - stack: RuntimeArrayData - - @dataclass(slots=True) class RuntimeImageStackCache: """Processing-context-local cache for adjacent step stack reuse.""" - stacks: dict[RuntimeImageStackCacheKey, RuntimeImageStackCacheValue] = field( + stacks: dict[RuntimeImageStackCacheKey, RuntimeArrayData] = field( default_factory=dict ) @@ -47,7 +40,7 @@ def get( paths: tuple[str, ...], *, memory_type: str, - ) -> RuntimeImageStackCacheValue | None: + ) -> RuntimeArrayData | None: """Return a cached stack for the exact ordered path and memory contract.""" return self.stacks.get( RuntimeImageStackCacheKey.from_paths(paths, memory_type=memory_type) @@ -63,7 +56,7 @@ def store( """Store a stack produced for a just-saved ordered path set.""" self.stacks[ RuntimeImageStackCacheKey.from_paths(paths, memory_type=memory_type) - ] = RuntimeImageStackCacheValue(stack=stack) + ] = stack def discard_paths(self, paths: tuple[str, ...]) -> None: """Discard cached stacks that include any of the supplied paths.""" diff --git a/openhcs/core/runtime_stores.py b/openhcs/core/runtime_stores.py index 93aa3ce0e9..afdd0b1a28 100644 --- a/openhcs/core/runtime_stores.py +++ b/openhcs/core/runtime_stores.py @@ -4,7 +4,7 @@ from collections import OrderedDict from collections.abc import Mapping, Sequence -from dataclasses import dataclass, field as dataclass_field, replace +from dataclasses import dataclass, field as dataclass_field import inspect from pathlib import Path from types import MappingProxyType @@ -44,6 +44,7 @@ SourceAxisMetadataScope, SourceImageSetIdentityCompatibility, SourceImageSetIdentityPolicy, + semantic_source_metadata_value, ) from openhcs.core.source_bindings import CompiledSourceBindingPlan from openhcs.serialization.json import to_jsonable @@ -241,25 +242,12 @@ def matches(self, record: "StoredRuntimeValue") -> bool: return True -@dataclass(frozen=True, slots=True) -class StoredRuntimeValue: +@dataclass(frozen=True, slots=True, kw_only=True) +class StoredRuntimeValue(RuntimeValue): """A validated runtime value with its persistence boundary.""" - value: RuntimeValue location: RuntimeArtifactLocation - @property - def key(self) -> ArtifactKey: - return self.value.key - - @property - def path(self) -> str: - return self.location.path - - @property - def backend(self) -> str: - return self.location.backend - @dataclass(frozen=True, slots=True) class RuntimeArtifactInput: @@ -304,19 +292,7 @@ def records( if producer_scope.is_ungrouped: return self._records(store, producer_scope, None) selection_scope = projection.producer_selection_scope - if projection.selects_declared_complete_producer( - self.edge_plan.spec, storage_plan - ): - return self.all_records(store) - if storage_plan.composes_producer_groups( - ComponentSet.coerce(projection.consumer_variable_components) - ): - return self.all_records(store) - if ( - selection_scope == producer_scope - and not selection_scope.is_dynamic - and len(selection_scope.keys) > 1 - ): + if self.selects_complete_producer(): return self.all_records(store) runtime_key = self.axis_scope.value_text_for_component( @@ -327,6 +303,136 @@ def records( ) return self._records(store, producer_scope, selected_key) + def selects_complete_producer(self) -> bool: + """Derive whole-producer selection from this exact compiled projection.""" + + storage_plan = self.edge_plan.storage_plan + projection = self.edge_plan.projection + producer_scope = storage_plan.producer_group_scope() + selection_scope = projection.producer_selection_scope + return ( + projection.selects_declared_complete_producer(self.edge_plan.spec, storage_plan) + or storage_plan.composes_producer_groups( + ComponentSet.coerce(projection.consumer_variable_components) + ) + or ( + selection_scope == producer_scope + and not selection_scope.is_dynamic + and len(selection_scope.keys) > 1 + ) + ) + + def candidate_execution_scopes( + self, + store: "RuntimeValueStore", + execution_scope: ComponentGroupScope, + *, + variable_components: ComponentSet, + ) -> dict[RuntimeExecutionAxisScope, str]: + """Discover correlated consumer coordinates from exact producer records. + + Discovery retains addresses for diagnostics; admission through records() + subsequently validates and resolves the current producer value. + """ + + storage_plan = self.edge_plan.storage_plan + producer_scope = storage_plan.producer_group_scope() + projection = self.edge_plan.projection + selection_scope = projection.producer_selection_scope + selects_complete_producer = self.selects_complete_producer() + projected_components = projection.projected_variable_components(storage_plan) + identity_policy = self._source_context_identity_policy() + candidates = tuple( + record + for group_key in ((None,) if producer_scope.is_dynamic else producer_scope.keys) + for record in store.find_matching( + RuntimeArtifactQuery.from_input_plan( + storage_plan, + axis_id=self.axis_scope.axis_id, + backend=self.backend, + group_key=group_key, + ) + ) + ) + scopes = {} + for record in candidates: + record_scope = record.key.scope + if record_scope.component is not producer_scope.component: + continue + if not selects_complete_producer and not selection_scope.contains_runtime_key( + record_scope.value_text + ): + continue + record_coordinates = dict(record_scope.source_component_values) + if selects_complete_producer: + record_coordinates.pop(producer_scope.component, None) + if projected_components: + provenance = image_payload_metadata(record.data).source_provenance + plane_metadata = provenance.source_image_provenance_planes.runtime_component_metadata + metadata_rows = plane_metadata or ( + (provenance.source_component_metadata,) + if provenance.source_component_metadata is not None else () + ) + else: + metadata_rows = (None,) + for metadata in metadata_rows: + if metadata is None and projected_components: + continue + coordinates = dict(record_coordinates) + for component in projected_components: + component_scope = projection.component_scope(component) + if component_scope.is_dynamic: + component_value = semantic_source_metadata_value( + metadata, component.value, + ) + if component_value is None: + break + component_value = str(component_value) + else: + component_value = component_scope.select_runtime_key(None) + if not SourceAxisMetadataScope.constraint_matches_metadata( + metadata, component.value, component_value, + ): + break + existing_value = coordinates.get(component) + if existing_value is not None and not SourceAxisMetadataScope.constraint_matches_metadata( + metadata, component.value, existing_value, + ): + break + coordinates.setdefault(component, component_value) + else: + runtime_value = coordinates.get(execution_scope.component) + if execution_scope.is_dynamic and runtime_value is None: + continue + component_keys = execution_scope.runtime_keys((runtime_value,)) + for component_key in component_keys: + if ( + not selects_complete_producer + and selection_scope.is_dynamic + and selection_scope.component is execution_scope.component + and record_scope.value_text != component_key + ): + continue + fixed_group_value = coordinates.get(execution_scope.component) + if fixed_group_value is not None and fixed_group_value != component_key: + continue + fixed_values = tuple( + (component, value) + for component, value in coordinates.items() + if component is not execution_scope.component + and not component.is_multiprocessing_axis() + and component not in variable_components + and identity_policy.is_identity_component(component) + ) + scope = RuntimeExecutionAxisScope.from_raw( + self.axis_scope.axis_id, + component=execution_scope.component, + value=component_key, + fixed_component_values=fixed_values, + ) + scopes.setdefault(scope, record.location.path) + return scopes + def all_records( self, store: "RuntimeValueStore", @@ -385,7 +491,7 @@ def composed_value( """Compose exact records after projecting the runtime-axis coordinate.""" return RuntimeValue.compose( - tuple(self._axis_value(record.value) for record in records), + tuple(self._axis_value(record) for record in records), self._producer_group_composition_scope(), ) @@ -395,7 +501,7 @@ def projected_values( ) -> tuple[RuntimeValue, ...]: """Return exact producer values projected into this consumer scope.""" - return tuple(self._axis_value(record.value) for record in self.records(store)) + return tuple(self._axis_value(record) for record in self.records(store)) def resolve_value(self, store: "RuntimeValueStore") -> Any: """Resolve this compiled input to its invocation value.""" @@ -488,8 +594,8 @@ def _axis_value(self, value: RuntimeValue) -> RuntimeValue: f"{metadata_scope.component_values!r} selects multiple producer " f"runtime slices {matching_indices!r}." ) - return replace( - value, + return RuntimeValue( + key=value.key, data=RuntimeSliceProjection.value_for_slice( payload, RuntimePlaneAxisValueProjection.from_selected_plane( @@ -498,6 +604,7 @@ def _axis_value(self, value: RuntimeValue) -> RuntimeValue: axis_size=slice_count, ), ), + materialization_source_metadata=value.materialization_source_metadata, ) def _consumer_component_value(self, component: AllComponents) -> str: @@ -584,17 +691,13 @@ def _matches_execution_scope( context_components = ComponentSet.collect( (component for component, _value in self.axis_scope.fixed_component_values), (component for component, _value in record_scope.fixed_component_values), - ).excluding(projected_components) - # Only a declared source-context relation supplies plane membership. - # Unrelated visible bindings must not relax an exact artifact input. - context_sources = self.edge_plan.spec.source_context_sources() - identity_policy = ( - SourceImageSetIdentityPolicy.from_source_bindings( - self.source_binding_plan.for_artifact_refs(context_sources) + ).excluding( + ComponentSet.collect( + projected_components, + (self.edge_plan.storage_plan.producer_group_scope().component,), ) - if context_sources - else SourceImageSetIdentityPolicy() ) + identity_policy = self._source_context_identity_policy() context_components = ( context_components .intersection(record_scope.source_components) @@ -615,6 +718,16 @@ def _matches_execution_scope( ), ).matches() + def _source_context_identity_policy(self) -> SourceImageSetIdentityPolicy: + """Derive plane membership only from this edge's context declarations.""" + + context_sources = self.edge_plan.spec.source_context_sources() + if not context_sources: + return SourceImageSetIdentityPolicy() + return SourceImageSetIdentityPolicy.from_source_bindings( + self.source_binding_plan.for_artifact_refs(context_sources) + ) + @dataclass(frozen=True, slots=True) class RuntimeArtifactBatch(RuntimeParameterDeclarationABC): @@ -760,7 +873,7 @@ def from_record(cls, record: StoredRuntimeValue) -> "RuntimeArtifactAddress": return cls( key=record.key, location=record.location, - value_type=type(record.value.data).__qualname__, + value_type=type(record.data).__qualname__, ) @classmethod @@ -901,7 +1014,9 @@ def record( ) -> StoredRuntimeValue: """Record a validated value and its persistence location.""" record = StoredRuntimeValue( - value=value, + key=value.key, + data=value.data, + materialization_source_metadata=value.materialization_source_metadata, location=RuntimeArtifactLocation(path=path, backend=backend), ) existing = self._current_record(value.key) @@ -927,7 +1042,9 @@ def replace( keeping record() strict for accidental duplicate writes. """ record = StoredRuntimeValue( - value=value, + key=value.key, + data=value.data, + materialization_source_metadata=value.materialization_source_metadata, location=RuntimeArtifactLocation(path=path, backend=backend), ) self._records_by_location[(value.key, record.location)] = record diff --git a/openhcs/core/runtime_tabular_values.py b/openhcs/core/runtime_tabular_values.py index 354207da60..e96d747655 100644 --- a/openhcs/core/runtime_tabular_values.py +++ b/openhcs/core/runtime_tabular_values.py @@ -13,8 +13,6 @@ from types import UnionType from typing import Annotated, Any, Union, get_args, get_origin, get_type_hints -from openhcs.core.process_local_cache import RegisteredProcessLocalBoundedCache - class ColumnarRows(ABC): """Nominal ABC for schema-bearing table payloads exposing named columns.""" @@ -85,6 +83,24 @@ def column_values(self, column: str) -> Sequence[object]: return columns[column] return self[column] + def column_value_segments( + self, column: str + ) -> Iterable[tuple[int, Sequence[object]]]: + """Read the current physical segments of one column in row order.""" + yield 0, self.column_values(column) + + def bounded_column_values(self, column: str, row_stop: int) -> Sequence[object]: + """Read a prefix without requiring whole-column admission.""" + return self.column_values(column)[:row_stop] + + def columnar_row_batches( + self, + ) -> Iterable[tuple[int, Mapping[str, Sequence[object]]]]: + """Read correlated column batches at the current payload epoch.""" + yield self.row_count(), { + str(column): self.column_values(str(column)) for column in self.columns + } + def row_count(self) -> int: """Return the number of rows represented by this columnar payload.""" columns = self.columns @@ -262,31 +278,10 @@ def measurement_row_mapping(row: object) -> Mapping[str, object]: if isinstance(row, Mapping): return row if is_dataclass(row): - return MeasurementRowMappingCache.process_cache().mapping(row) + return asdict(row) raise TypeError(f"Unsupported measurement row type {type(row).__name__}.") -@dataclass(slots=True) -class MeasurementRowMappingCache( - RegisteredProcessLocalBoundedCache[int, tuple[object, Mapping[str, object]]] -): - """Bounded process-local cache for immutable dataclass measurement rows.""" - - max_entries: int = 262144 - - def mapping(self, row: object) -> Mapping[str, object]: - row_id = id(row) - cached = self.cached_value(row_id) - if cached is not None: - cached_row, row_mapping = cached - if cached_row is row: - return row_mapping - del self.entries[row_id] - row_mapping = asdict(row) - self.store_value(row_id, (row, row_mapping)) - return row_mapping - - class MeasurementObjectRowIdentity(str, Enum): """How object-scoped measurement rows identify their measured object.""" diff --git a/openhcs/core/source_binding_selection.py b/openhcs/core/source_binding_selection.py index 90c686c60a..0ad194721e 100644 --- a/openhcs/core/source_binding_selection.py +++ b/openhcs/core/source_binding_selection.py @@ -3,7 +3,6 @@ from __future__ import annotations from abc import ABC, abstractmethod -from collections.abc import Iterator from dataclasses import dataclass, field, replace from enum import Enum from functools import lru_cache @@ -14,10 +13,7 @@ from metaclass_registry import AutoRegisterMeta from openhcs.constants.constants import Backend -from openhcs.core.registry_strategies import ( - EnumKeyedStrategyMixin, - MostDerivedContextStrategyMixin, -) +from openhcs.core.registry_strategies import EnumKeyedStrategyMixin from openhcs.core.path_pattern_matching import PathPatternTemplateMatcher from openhcs.core.source_bindings import ( CompiledSourceBindingPlan, @@ -25,7 +21,6 @@ NamedSourceBinding, SourceBindingMatchMethod, SourceBindingMatchPlan, - SourceBindingRuntimeContext, SourceSetRole, ) from openhcs.core.source_image_provenance import ( @@ -33,8 +28,9 @@ SourceImageProvenance, ) from openhcs.core.source_metadata import ( + SourceMetadataFields, SourceMetadataMapping, - SourceMetadataRoleView, + SourceMetadataRecord, SourceMetadataValue, ) from openhcs.core.source_matching import ( @@ -59,9 +55,12 @@ from openhcs.core.source_projection import SourceProjection from openhcs.core.source_workspace_projection import VirtualWorkspaceSourceProjection from openhcs.core.steps.function_io import get_all_image_paths +from openhcs.core.runtime_array_values import RuntimeArrayData +from openhcs.core.runtime_image_loading import ImagePayloadSourceMetadataContext from openhcs.core.compiled_step_plan import CompiledStepPlan if TYPE_CHECKING: + from polystore.filemanager import FileManager from openhcs.core.context.processing_context import ProcessingContext from openhcs.microscopes.microscope_interfaces import FilenameParser @@ -77,27 +76,48 @@ def _cached_source_candidate_pattern_keys(pattern_path: str) -> tuple[str, ...]: return tuple(dict.fromkeys((pattern_path, path.as_posix(), path.name))) -@dataclass(frozen=True, slots=True) -class SourceMetadataRecord(Mapping[str, SourceMetadataValue]): - """Normalized source metadata carried across source-binding selection.""" - - fields: tuple[tuple[str, SourceMetadataValue], ...] +@dataclass(frozen=True, slots=True, eq=False) +class DeclaredSourceMetadataRecord(SourceMetadataRecord): + """Live declared metadata that still requires path-specific fallbacks.""" @classmethod - def from_mapping(cls, metadata: SourceMetadataMapping) -> "SourceMetadataRecord": + def from_mapping( + cls, metadata: SourceMetadataMapping + ) -> "DeclaredSourceMetadataRecord": return cls(tuple((str(key), value) for key, value in metadata.items())) - def __getitem__(self, key: str) -> SourceMetadataValue: - for field_key, value in self.fields: - if field_key == key: - return value - raise KeyError(key) - - def __iter__(self) -> Iterator[str]: - return (key for key, _value in self.fields) - - def __len__(self) -> int: - return len(self.fields) + def resolve( + self, + path: str, + parser: "FilenameParser", + metadata_rules: tuple[MetadataExtractionRule, ...], + ) -> "SourceMetadataRecord | None": + """Fill parser and extraction-rule fields absent from declarations.""" + metadata: dict[str, SourceMetadataValue] = {} + merge_source_metadata(metadata, self, path=path) + parsed_metadata = parser.parse_filename(path) + if parsed_metadata is not None: + merge_source_metadata( + metadata, + { + key: value + for key, value in parsed_metadata.wire_mapping().items() + if key not in metadata + }, + path=path, + ) + rule_metadata = metadata_from_rules(path, metadata_rules) + if rule_metadata: + merge_source_metadata( + metadata, + { + key: value + for key, value in rule_metadata.items() + if key not in metadata + }, + path=path, + ) + return self.from_mapping(metadata) if metadata else None @dataclass(frozen=True, slots=True) @@ -176,7 +196,7 @@ def from_sources( str(path): ( metadata if isinstance(metadata, SourceMetadataRecord) - else SourceMetadataRecord.from_mapping(metadata) + else DeclaredSourceMetadataRecord.from_mapping(metadata) ) for path, metadata in source_metadata_by_path.items() } @@ -187,23 +207,6 @@ def from_sources( metadata_rules=metadata_rules, ) - @classmethod - def from_runtime_context( - cls, - *, - parser: "FilenameParser", - runtime_context: SourceBindingRuntimeContext, - metadata_rules: tuple[MetadataExtractionRule, ...] = (), - ) -> "SourcePatternResolutionContext": - """Build the generic selector context from compiled runtime source state.""" - - return cls.from_sources( - parser=parser, - source_paths_by_virtual_path=runtime_context.step_input_source_paths, - source_metadata_by_path=runtime_context.source_metadata_by_path, - metadata_rules=metadata_rules, - ) - @classmethod def from_projection( cls, @@ -244,9 +247,9 @@ def candidate_filter_paths(self, pattern: SourceCandidatePath) -> tuple[str, ... dict.fromkeys( source_filter_path for metadata in self.metadata_for_paths(resolution.metadata_paths()) - for source_filter_path in SourceMetadataRoleView( + for source_filter_path in SourceMetadataFields.source_filter_paths( metadata - ).source_filter_paths() + ) ) ) if source_filter_paths: @@ -262,17 +265,24 @@ def _candidate_path_resolution( (key for key in keys if key in self.source_paths_by_virtual_path), None, ) - virtual_matches = ( - (exact_virtual_path,) - if exact_virtual_path is not None - else tuple( + if exact_virtual_path is not None: + projection = self.source_projections_by_virtual_path.get(exact_virtual_path) + virtual_matches = ( + tuple( + path + for path, declared in self.source_projections_by_virtual_path.items() + if declared is projection + ) + if projection is not None else (exact_virtual_path,) + ) + else: + virtual_matches = tuple( dict.fromkeys( virtual_path for key in keys for virtual_path in self._matching_virtual_paths(key) ) ) - ) mapped = tuple( self.source_paths_by_virtual_path[key] for key in (*keys, *virtual_matches) @@ -337,18 +347,29 @@ def declared_positions_for_candidates( """Project exact physical spellings onto their declared workspace positions. Workspace positions are not physical-file identities: several positions - may address different planes in one store. Keep every declared position, - and replace only a physical address explicitly mapped to those positions. - No basename, filesystem resolution or metadata inference participates. + may address different planes in one store. Lookup spellings backed by + the same nominal projection are aliases of one position. Mapping-only + declarations and distinct projections retain their separate positions. + No basename, filesystem resolution or physical-ref equality participates. """ + projection_positions: dict[int, SourceCandidatePath] = {} + for position, projection in self.source_projections_by_virtual_path.items(): + projection_positions.setdefault(id(projection), position) positions: list[SourceCandidatePath] = [] for candidate, virtual_paths in zip( candidates, self.virtual_paths_for_sources(candidates), strict=True ): - if candidate in self.source_paths_by_virtual_path: - positions.append(candidate) - else: - positions.extend(virtual_paths or (candidate,)) + declared_positions = ( + (candidate,) + if candidate in self.source_paths_by_virtual_path + else virtual_paths or (candidate,) + ) + for position in declared_positions: + projection = self.source_projections_by_virtual_path.get(position) + positions.append( + projection_positions[id(projection)] + if projection is not None else position + ) return tuple(dict.fromkeys(positions)) def runtime_paths_for_candidate( @@ -404,35 +425,10 @@ def metadata_for_paths( ) def metadata_for_path(self, path: str) -> SourceMetadataRecord | None: - metadata: dict[str, SourceMetadataValue] = {} - declared_metadata = self.source_metadata_by_path.get(path) - if declared_metadata is not None: - merge_source_metadata(metadata, declared_metadata, path=path) - parsed_metadata = self.parser.parse_filename(path) - if parsed_metadata is not None: - merge_source_metadata( - metadata, - { - key: value - for key, value in parsed_metadata.wire_mapping().items() - if key not in metadata - }, - path=path, - ) - rule_metadata = metadata_from_rules(path, self.metadata_rules) - if rule_metadata: - merge_source_metadata( - metadata, - { - key: value - for key, value in rule_metadata.items() - if key not in metadata - }, - path=path, - ) - if metadata: - return SourceMetadataRecord.from_mapping(metadata) - return None + record = self.source_metadata_by_path.get(path) + if record is None: + record = DeclaredSourceMetadataRecord(()) + return record.resolve(path, self.parser, self.metadata_rules) def merged_metadata_for_paths( self, @@ -445,7 +441,7 @@ def merged_metadata_for_paths( if path_metadata is not None: merge_source_metadata(metadata, path_metadata, path=path) if metadata: - return SourceMetadataRecord.from_mapping(metadata) + return DeclaredSourceMetadataRecord.from_mapping(metadata) return None def source_metadata_by_paths( @@ -1369,11 +1365,11 @@ def _source_image_set_identity( metadata = ( metadata_candidates.values[0] if metadata_candidates.values - else SourceMetadataRecord(()) + else DeclaredSourceMetadataRecord(()) ) return SourceImageSetIdentity.from_metadata( metadata, - fallback_source_path=candidate, + fallback_source_path=self.source_path_for(candidate), policy=self.identity_policy, ) @@ -1537,13 +1533,54 @@ class SourceFileUniverse: files: tuple[str, ...] backend: Backend + def load_images( + self, + filemanager: "FileManager", + *, + zarr_config: Mapping[str, object] | None = None, + ) -> list[RuntimeArrayData]: + """Load this exact source cohort, retaining its execution-local memory copy.""" + if self.backend is Backend.MEMORY: + return filemanager.load_batch(list(self.files), self.backend.value) + missing = tuple(dict.fromkeys( + path for path in self.files + if not filemanager.exists(path, Backend.MEMORY.value) + )) + loaded_by_path = {} + if missing: + pixels = filemanager.load_batch( + list(missing), self.backend.value, + **({"zarr_config": zarr_config} if self.backend is Backend.ZARR else {}), + ) + loaded_by_path.update( + (path, ImagePayloadSourceMetadataContext( + SourceImageIdentity(path), + read_backend=self.backend.value, + filemanager=filemanager, + ).payload(image)) + for path, image in zip(missing, pixels, strict=True) + ) + for parent in dict.fromkeys(str(Path(path).parent) for path in missing): + filemanager.ensure_directory(parent, Backend.MEMORY.value) + filemanager.save_batch( + list(loaded_by_path.values()), list(loaded_by_path), Backend.MEMORY.value, + ) + retained = tuple(dict.fromkeys( + path for path in self.files if path not in loaded_by_path + )) + if retained: + loaded_by_path.update(zip( + retained, + filemanager.load_batch(list(retained), Backend.MEMORY.value), + strict=True, + )) + return [loaded_by_path[path] for path in self.files] + @dataclass(frozen=True, slots=True) class SourceUniverseRuntimeState: """Resolved source universes assembled from the registered request family.""" - step_input_universe: SourceFileUniverse | None = None - pipeline_start_universe: SourceFileUniverse | None = None load_universe: SourceFileUniverse | None = None step_input_source_paths: Mapping[str, str] = field( default_factory=lambda: MappingProxyType({}) @@ -1551,7 +1588,6 @@ class SourceUniverseRuntimeState: source_metadata_by_path: Mapping[str, SourceMetadataMapping] = field( default_factory=lambda: MappingProxyType({}) ) - pipeline_source_candidate_files: tuple[str, ...] = () def with_source_metadata( self, @@ -1570,50 +1606,11 @@ def with_source_metadata( merged.update(source_metadata_by_path) return replace(self, source_metadata_by_path=MappingProxyType(merged)) - def require_step_input_universe(self) -> SourceFileUniverse: - if self.step_input_universe is None: - raise RuntimeError( - "Source universe runtime state has no step-input universe." - ) - return self.step_input_universe - - def require_pipeline_start_universe(self) -> SourceFileUniverse: - if self.pipeline_start_universe is None: - raise RuntimeError( - "Source universe runtime state has no pipeline-start universe." - ) - return self.pipeline_start_universe - def require_load_universe(self) -> SourceFileUniverse: if self.load_universe is None: raise RuntimeError("Source universe runtime state has no load universe.") return self.load_universe - def runtime_context( - self, - request: "SourceBindingRuntimeContextRequest", - source_metadata_by_path: Mapping[str, SourceMetadataMapping], - ) -> SourceBindingRuntimeContext: - """Build the runtime context from source-universe contributions.""" - step_input_universe = self.require_step_input_universe() - pipeline_source_universe = self.require_pipeline_start_universe() - return SourceBindingRuntimeContext( - step_input_files=step_input_universe.files, - current_step_input_files=request.current_step_input_files( - step_input_universe - ), - current_image_files=request.matching_files, - step_input_dir=str(request.plan.input_dir), - step_input_source_backend=request.plan.read_backend, - step_input_storage_backend=Backend.MEMORY.value, - step_input_source_paths=self.step_input_source_paths, - source_metadata_by_path=source_metadata_by_path, - source_metadata_is_normalized=True, - pipeline_input_files=pipeline_source_universe.files, - pipeline_source_candidate_files=self.pipeline_source_candidate_files, - pipeline_input_backend=pipeline_source_universe.backend.value, - ) - @dataclass(frozen=True, slots=True) class SourceUniverseRequest(metaclass=AutoRegisterMeta): @@ -1629,6 +1626,54 @@ class SourceUniverseRequest(metaclass=AutoRegisterMeta): source_backend: Backend source_projection: VirtualWorkspaceSourceProjection | None + @classmethod + def from_context( + cls, + *, + context: "ProcessingContext", + plan: "CompiledStepPlan", + matching_files: Sequence[str], + source_projection: VirtualWorkspaceSourceProjection | None, + ) -> "SourceUniverseRequest": + if not isinstance(plan, CompiledStepPlan): + raise TypeError( + "SourceUniverseRequest requires CompiledStepPlan, got " + f"{type(plan).__name__}." + ) + plan.require_function_execution_ready() + source_backend = Backend( + context.microscope_handler.get_primary_backend( + context.input_dir, + context.filemanager, + ) + ) + return cls( + context=context, + plan=plan, + matching_files=tuple(matching_files), + source_backend=source_backend, + source_projection=source_projection, + ) + + def runtime_universe_state(self) -> SourceUniverseRuntimeState: + """Return cached source-universe state for this request.""" + cache = self.context.runtime_source_binding_context_cache + cached = cache.runtime_universe_state( + plan=self.plan, + matching_files=self.matching_files, + source_backend=self.source_backend, + source_projection=self.source_projection, + ) + if cached is not None: + return cached + return cache.store_runtime_universe_state( + SourceUniverseRequest.runtime_state(self), + plan=self.plan, + matching_files=self.matching_files, + source_backend=self.source_backend, + source_projection=self.source_projection, + ) + @classmethod def registered_request_types(cls) -> tuple[type["SourceUniverseRequest"], ...]: """Return registered concrete runtime plan request classes.""" @@ -1639,11 +1684,11 @@ def registered_request_types(cls) -> tuple[type["SourceUniverseRequest"], ...]: return tuple(request_types) @classmethod - def from_runtime_context( + def from_request( cls, - request: "SourceBindingRuntimeContextRequest", + request: "SourceUniverseRequest", ) -> "SourceUniverseRequest": - """Build this registered request type from the runtime context request.""" + """Build a registered source-universe role from its parent request.""" return cls( context=request.context, plan=request.plan, @@ -1655,16 +1700,29 @@ def from_runtime_context( @classmethod def runtime_state( cls, - request: "SourceBindingRuntimeContextRequest", + request: "SourceUniverseRequest", ) -> SourceUniverseRuntimeState: """Resolve every registered source-universe request into runtime state.""" state = SourceUniverseRuntimeState() for request_type in cls.registered_request_types(): - universe_request = request_type.from_runtime_context(request) - universe = SourceUniverseStrategy.universe(universe_request) + universe_request = request_type.from_request(request) + universe = universe_request.source_universe() state = universe_request.contribute_runtime_state(state, universe) return state + def source_universe(self) -> SourceFileUniverse: + """Resolve current-axis files through their declared source backend.""" + return SourceFileUniverse( + files=( + self.require_source_projection().pipeline_start_files( + axis_id=self.plan.axis_id, + ) + if self.uses_virtual_workspace_projection + else self.axis_files() + ), + backend=self.source_backend, + ) + def contribute_runtime_state( self, state: SourceUniverseRuntimeState, @@ -1708,7 +1766,7 @@ def source_metadata_by_path(self) -> Mapping[str, SourceMetadataMapping]: def source_context(self) -> SourcePatternResolutionContext: metadata_rules = self.plan.source_binding_plan.metadata_rules if self.source_projection is not None: - return SourcePatternResolutionContext.from_projection( + return self.context.runtime_source_binding_context_cache.source_pattern_context( parser=self.context.microscope_handler.parser, projection=self.source_projection, metadata_rules=metadata_rules, @@ -1756,6 +1814,12 @@ class StepInputSourceUniverseRequest(SourceUniverseRequest): universe_request_kind = "step_input" + def source_universe(self) -> SourceFileUniverse: + """Expand source selectors; otherwise retain the selected pattern files.""" + if not self.requires_step_input_selector_resolution: + return SourceFileUniverse(self.matching_files, self.source_backend) + return SourceUniverseRequest.source_universe(self) + def contribute_runtime_state( self, state: SourceUniverseRuntimeState, @@ -1763,7 +1827,6 @@ def contribute_runtime_state( ) -> SourceUniverseRuntimeState: state = replace( state, - step_input_universe=universe, load_universe=state.load_universe or universe, step_input_source_paths=self.step_input_source_paths, ) @@ -1776,6 +1839,25 @@ class PipelineStartSourceUniverseRequest(SourceUniverseRequest): universe_request_kind = "pipeline_start" + def source_universe(self) -> SourceFileUniverse: + """Resolve the declared original-source scope independently of step input.""" + if not self.requires_full_pipeline_source_universe: + return SourceUniverseRequest.source_universe(self) + if self.source_projection is not None: + return SourceFileUniverse( + self.source_projection.pipeline_start_files(), self.source_backend, + ) + backend = self.physical_full_universe_backend() + return SourceFileUniverse( + files=tuple( + str(path) + for path in self.context.filemanager.list_files( + str(self.context.input_dir), backend.value, recursive=True, + ) + ), + backend=backend, + ) + def contribute_runtime_state( self, state: SourceUniverseRuntimeState, @@ -1784,8 +1866,6 @@ def contribute_runtime_state( load_universe = self.load_universe() state = replace( state, - pipeline_start_universe=universe, - pipeline_source_candidate_files=universe.files, load_universe=( state.load_universe if load_universe is None else load_universe ), @@ -1850,308 +1930,3 @@ class VirtualWorkspacePipelineStartListingBackendPolicy( """Virtual-workspace pipeline-start fan-out lists disk files.""" source_backend = Backend.VIRTUAL_WORKSPACE - - -class SourceUniverseStrategy( - MostDerivedContextStrategyMixin[SourceUniverseRequest], - ABC, -): - """Registered source-universe selection for source-binding runtime scopes.""" - - __registry_key__ = "strategy_key" - __skip_if_no_key__ = True - - strategy_key: ClassVar[str | None] = None - - @classmethod - def universe(cls, request: SourceUniverseRequest) -> SourceFileUniverse: - strategy = cls.for_context( - request, - error_subject="Source universe", - ) - if strategy is None: - raise ValueError("Source universe requires a strategy.") - return strategy.source_universe(request) - - @abstractmethod - def source_universe(self, request: SourceUniverseRequest) -> SourceFileUniverse: - """Return source files and backend for pipeline-start bindings.""" - - -class StepInputSourceUniverseStrategy(SourceUniverseStrategy, ABC): - """Source-universe strategy branch for current step input.""" - - def matches(self, request: SourceUniverseRequest) -> bool: - return isinstance( - request, - StepInputSourceUniverseRequest, - ) and self.matches_step_input(request) - - @abstractmethod - def matches_step_input(self, request: StepInputSourceUniverseRequest) -> bool: - """Return whether this strategy owns one step-input request.""" - - -class PipelineStartSourceUniverseStrategy(SourceUniverseStrategy, ABC): - """Source-universe strategy branch for original pipeline input.""" - - def matches(self, request: SourceUniverseRequest) -> bool: - return isinstance( - request, - PipelineStartSourceUniverseRequest, - ) and self.matches_pipeline_start(request) - - @abstractmethod - def matches_pipeline_start( - self, - request: PipelineStartSourceUniverseRequest, - ) -> bool: - """Return whether this strategy owns one pipeline-start request.""" - - -class AxisFilesSourceUniverseStrategy(SourceUniverseStrategy): - """Source-universe strategy that uses current-axis files from the source backend.""" - - def source_universe(self, request: SourceUniverseRequest) -> SourceFileUniverse: - return SourceFileUniverse( - files=request.axis_files(), - backend=request.source_backend, - ) - - -class StepInputAxisFilesSourceUniverseStrategy( - AxisFilesSourceUniverseStrategy, - StepInputSourceUniverseStrategy, - ABC, -): - """Axis-file universe strategy branch for current step input.""" - - -class PipelineStartAxisFilesSourceUniverseStrategy( - AxisFilesSourceUniverseStrategy, - PipelineStartSourceUniverseStrategy, - ABC, -): - """Axis-file universe strategy branch for original pipeline input.""" - - -class CurrentPatternStepInputSourceUniverseStrategy(StepInputSourceUniverseStrategy): - """Use the already-loaded pattern files when selectors do not need fan-out.""" - - strategy_key = "step_input_current_pattern" - - def matches_step_input(self, request: StepInputSourceUniverseRequest) -> bool: - return not request.requires_step_input_selector_resolution - - def source_universe(self, request: SourceUniverseRequest) -> SourceFileUniverse: - return SourceFileUniverse( - files=request.matching_files, - backend=request.source_backend, - ) - - -class VirtualWorkspaceStepInputSourceUniverseStrategy(StepInputSourceUniverseStrategy): - """Use source-schema virtual files when selector resolution must span sources.""" - - strategy_key = "step_input_virtual_workspace_source_projection" - - def matches_step_input(self, request: StepInputSourceUniverseRequest) -> bool: - return ( - request.requires_step_input_selector_resolution - and request.uses_virtual_workspace_projection - ) - - def source_universe(self, request: SourceUniverseRequest) -> SourceFileUniverse: - return SourceFileUniverse( - files=request.require_source_projection().pipeline_start_files( - axis_id=request.plan.axis_id - ), - backend=request.source_backend, - ) - - -class PhysicalAxisStepInputSourceUniverseStrategy( - StepInputAxisFilesSourceUniverseStrategy, -): - """Use physical axis files when source selectors need fan-out outside VWS.""" - - strategy_key = "step_input_physical_axis" - - def matches_step_input(self, request: StepInputSourceUniverseRequest) -> bool: - return ( - request.requires_step_input_selector_resolution - and not request.uses_virtual_workspace_projection - ) - - -class AxisScopedPipelineStartSourceUniverseStrategy( - PipelineStartAxisFilesSourceUniverseStrategy, -): - """Use the current axis source files when full pipeline fan-out is unnecessary.""" - - strategy_key = "axis_scoped" - - def matches_pipeline_start( - self, - request: PipelineStartSourceUniverseRequest, - ) -> bool: - return not request.requires_full_pipeline_source_universe - - def source_universe(self, request: SourceUniverseRequest) -> SourceFileUniverse: - if request.uses_virtual_workspace_projection: - return SourceFileUniverse( - files=request.require_source_projection().pipeline_start_files( - axis_id=request.plan.axis_id - ), - backend=request.source_backend, - ) - return SourceFileUniverse( - files=request.axis_files(), - backend=request.source_backend, - ) - - -class VirtualWorkspacePipelineStartSourceUniverseStrategy( - PipelineStartSourceUniverseStrategy, -): - """Use declared virtual-workspace source paths for pipeline-start fan-out.""" - - strategy_key = "virtual_workspace_source_projection" - - def matches_pipeline_start( - self, - request: PipelineStartSourceUniverseRequest, - ) -> bool: - return ( - request.requires_full_pipeline_source_universe - and request.source_projection is not None - ) - - def source_universe(self, request: SourceUniverseRequest) -> SourceFileUniverse: - projection = request.require_source_projection() - return SourceFileUniverse( - files=projection.pipeline_start_files(), - backend=request.source_backend, - ) - - -class PhysicalPipelineStartSourceUniverseStrategy(PipelineStartSourceUniverseStrategy): - """Use a file listing backend for full pipeline fan-out outside VWS.""" - - strategy_key = "physical_full_universe" - - def matches_pipeline_start( - self, - request: PipelineStartSourceUniverseRequest, - ) -> bool: - return ( - request.requires_full_pipeline_source_universe - and request.source_projection is None - ) - - def source_universe(self, request: SourceUniverseRequest) -> SourceFileUniverse: - universe_backend = request.physical_full_universe_backend() - return SourceFileUniverse( - files=tuple( - str(path) - for path in request.context.filemanager.list_files( - str(request.context.input_dir), - universe_backend.value, - recursive=True, - ) - ), - backend=universe_backend, - ) - - -@dataclass(frozen=True, slots=True) -class SourceBindingRuntimeContextRequest: - """Build the source-binding runtime context from one resolved source universe.""" - - context: "ProcessingContext" - plan: "CompiledStepPlan" - matching_files: tuple[str, ...] - source_backend: Backend - source_projection: VirtualWorkspaceSourceProjection | None - - def __post_init__(self) -> None: - if not isinstance(self.plan, CompiledStepPlan): - raise TypeError( - "SourceBindingRuntimeContextRequest requires CompiledStepPlan, got " - f"{type(self.plan).__name__}." - ) - self.plan.require_function_execution_ready() - - @classmethod - def from_context( - cls, - *, - context: "ProcessingContext", - plan: "CompiledStepPlan", - matching_files: Sequence[str], - source_projection: VirtualWorkspaceSourceProjection | None, - ) -> "SourceBindingRuntimeContextRequest": - source_backend = Backend( - context.microscope_handler.get_primary_backend( - context.input_dir, - context.filemanager, - ) - ) - return cls( - context=context, - plan=plan, - matching_files=tuple(matching_files), - source_backend=source_backend, - source_projection=source_projection, - ) - - def runtime_context(self) -> SourceBindingRuntimeContext: - cache = self.context.runtime_source_binding_context_cache - cached = cache.runtime_context( - plan=self.plan, - matching_files=self.matching_files, - source_backend=self.source_backend, - source_projection=self.source_projection, - ) - if cached is not None: - return cached - universe_state = self.runtime_universe_state() - source_metadata_by_path = cache.normalized_source_metadata( - universe_state.source_metadata_by_path - ) - return cache.store_runtime_context( - universe_state.runtime_context( - self, - source_metadata_by_path, - ), - plan=self.plan, - matching_files=self.matching_files, - source_backend=self.source_backend, - source_projection=self.source_projection, - ) - - def runtime_universe_state(self) -> SourceUniverseRuntimeState: - """Return cached source-universe state for this request.""" - cache = self.context.runtime_source_binding_context_cache - cached = cache.runtime_universe_state( - plan=self.plan, - matching_files=self.matching_files, - source_backend=self.source_backend, - source_projection=self.source_projection, - ) - if cached is not None: - return cached - return cache.store_runtime_universe_state( - SourceUniverseRequest.runtime_state(self), - plan=self.plan, - matching_files=self.matching_files, - source_backend=self.source_backend, - source_projection=self.source_projection, - ) - - def current_step_input_files( - self, - step_input_universe: SourceFileUniverse, - ) -> tuple[str, ...]: - del step_input_universe - return self.matching_files diff --git a/openhcs/core/source_binding_workspace.py b/openhcs/core/source_binding_workspace.py index 02230380d8..3567219876 100644 --- a/openhcs/core/source_binding_workspace.py +++ b/openhcs/core/source_binding_workspace.py @@ -45,7 +45,7 @@ OriginalSourceMetadata, SourceFilterPathMetadata, SourceMetadataMapping, - SourceMetadataRoleView, + SourceMetadataFields, SourceMetadataScalar, SourceVoxelSpacing, SourceComponentProjectionStrategy, @@ -1373,7 +1373,7 @@ def _shared_candidate_metadata( value_sets_by_key: dict[str, set[object]] = {} counts_by_key: dict[str, int] = {} for candidate in candidates: - for key, value in SourceMetadataRoleView(candidate.metadata).scalar_items(): + for key, value in SourceMetadataFields.scalar_items(candidate.metadata): value_sets_by_key.setdefault(key, set()).add(value) counts_by_key[key] = counts_by_key.get(key, 0) + 1 candidate_count = len(candidates) diff --git a/openhcs/core/source_bindings.py b/openhcs/core/source_bindings.py index 7f2bf54e30..1cf4eae158 100644 --- a/openhcs/core/source_bindings.py +++ b/openhcs/core/source_bindings.py @@ -10,7 +10,7 @@ import urllib.request from abc import ABC, abstractmethod from collections.abc import Hashable, Iterable, Mapping, Sequence -from dataclasses import InitVar, dataclass, field, replace +from dataclasses import dataclass, field, replace from dataclasses import fields as dataclass_fields from enum import Enum from functools import lru_cache @@ -37,47 +37,29 @@ from openhcs.core.components.validation import convert_enum_by_value from openhcs.core.runtime_tabular_values import FieldSpec from openhcs.core.source_metadata import ( - SourceMetadataIdentityItems, - SourceMetadataIdentityProjection, + SourceMetadataFields, + ResolvedSourceMetadataRecord, SourceMetadataMapping, - SourceMetadataRoleView, SourceMetadataScalar, SourceMetadataValue, SourceVoxelSpacing, source_metadata_dict, source_metadata_scalar, ) -from openhcs.core.source_path_identity import source_path_identity_key from openhcs.core.xdg_paths import get_openhcs_cache_dir +from openhcs.core.source_spatial_domain import SourceSpatialDomain if TYPE_CHECKING: from openhcs.core.component_group_scope import RuntimeExecutionAxisScope + from openhcs.core.runtime_array_values import RuntimeArrayData + from openhcs.core.runtime_image_loading import ImagePayloadSourceMetadataContext + from openhcs.core.runtime_image_values import ImagePayloadMetadata -SourceMetadataIdentity = tuple[tuple[str, SourceMetadataIdentityItems], ...] SOURCE_ALIAS_PART_SEPARATOR = "__" SOURCE_BINDING_ALIAS_METADATA_FIELD = "source_alias" SourceBindingValue = TypeVar("SourceBindingValue") -@dataclass(frozen=True, slots=True) -class SourceBindingRuntimeContextProcessIdentity: - """Hash-stable semantic identity for process-local source caches.""" - - source_order_identity: tuple[Hashable, ...] - source_metadata_identity: SourceMetadataIdentity - _hash: int = field(init=False, repr=False, compare=False) - - def __post_init__(self) -> None: - object.__setattr__( - self, - "_hash", - hash((self.source_order_identity, self.source_metadata_identity)), - ) - - def __hash__(self) -> int: - return self._hash - - class SourceBindingPlanMeta(EnableableMeta, AutoRegisterMeta): """Auto-register source-binding plans while preserving Enableable semantics.""" @@ -1038,6 +1020,92 @@ def input_spec(self) -> ArtifactSpec: required=self.required, ) + def apply_loaded_payload( + self, + payload: RuntimeArrayData, + source_context: ImagePayloadSourceMetadataContext | None, + ) -> RuntimeArrayData: + """Apply this declaration to one freshly loaded source payload.""" + import numpy as np + + from openhcs.core.runtime_image_values import ( + ImagePayloadMetadata, + ImageUnitIntervalIntensityMetadata, + image_payload_data, + image_payload_mask, + image_payload_metadata, + ) + + if source_context is None: + existing = image_payload_metadata(payload) + metadata = ( + existing + if existing.has_values + else ImagePayloadMetadata.for_array_payload(payload) + ) + else: + # The physical context needs the declared channel axis before it + # admits source geometry. It resolves this binding's axis once. + metadata = source_context.metadata(payload, source_binding=self) + metadata = metadata.replace_fields( + source_provenance=metadata.source_provenance.with_source_image_names( + (self.alias,) + ) + ) + if source_context is None: + metadata = metadata.replace_fields( + source_channel_axis=self.source_channel_axis_for_shape( + np.shape(image_payload_data(payload)), + observed_axis=metadata.source_channel_axis, + ), + ) + metadata.normalized_source_channel_axis(payload) + + data, source_channel_axis = self.artifact_kind.normalize_source_payload( + image_payload_data(payload), + metadata.source_channel_axis, + ) + if self.load_as_monochrome and source_channel_axis is not None: + data = self._monochrome_source_data(data, source_channel_axis, metadata) + source_channel_axis = None + metadata = metadata.replace_fields( + unit_interval_intensity=ImageUnitIntervalIntensityMetadata(), + intensity_scale=ImagePayloadMetadata.for_array(data).intensity_scale, + ) + if self.load_as_mask: + data = np.asarray(data, dtype=bool) + + metadata = metadata.replace_fields(source_channel_axis=source_channel_axis) + return metadata.payload_with(data, image_payload_mask(payload)) + + @staticmethod + def _monochrome_source_data( + data: RuntimeArrayData, + channel_axis: int, + metadata: ImagePayloadMetadata, + ) -> RuntimeArrayData: + """Convert declared RGB channels using the source intensity domain.""" + import numpy as np + + from openhcs.core.runtime_image_values import ( + image_payload_data, + normalize_image_payload_intensity, + ) + + normalized = normalize_image_payload_intensity( + metadata.payload_with(data), + dtype=np.float32, + ) + rgb = np.moveaxis( + np.asarray(image_payload_data(normalized)), channel_axis, -1 + )[..., :3] + if np.all(rgb == rgb[..., :1]): + return np.ascontiguousarray(rgb[..., 0]) + + from skimage.color import rgb2gray + + return rgb2gray(rgb) + def component_values( self, component: AllComponents, @@ -1164,6 +1232,7 @@ class SourceBindingDeclarationsMixin: bindings: tuple[NamedSourceBinding, ...] | None source_stack_components: tuple[AllComponents, ...] + source_spatial_domain: SourceSpatialDomain @property def binding_declarations(self) -> tuple[NamedSourceBinding, ...]: @@ -1723,6 +1792,11 @@ class SourceBindingsConfig(SourceBindingDeclarationsMixin, _SourceBindingPlanBas source_stack_components: tuple[AllComponents, ...] = () """Ordered plate components that form one logical source image stack.""" + source_spatial_domain: SourceSpatialDomain = field( + default_factory=SourceSpatialDomain + ) + """Declared intrinsic image dimensions, independent of stack transport.""" + grouping_metadata_fields: tuple[str, ...] = () """Metadata field names used to partition matched sources into execution groups.""" @@ -2000,7 +2074,7 @@ def metadata_fields_for_realized_source_metadata( declared_names = frozenset(field.name for field in declared_fields) values_by_name: dict[str, list[SourceMetadataScalar]] = {} for metadata in realized_source_metadata: - for field_name, value in SourceMetadataRoleView(metadata).original_items(): + for field_name, value in SourceMetadataFields.original_items(metadata): if ( field_name not in declared_names and field_name not in excluded_names @@ -2140,6 +2214,9 @@ class CompiledSourceBindingPlan(SourceBindingDeclarationsMixin, _SourceBindingPl registry_key: ClassVar[str] = "compiled" bindings: tuple[NamedSourceBinding, ...] = () source_stack_components: tuple[AllComponents, ...] = () + source_spatial_domain: SourceSpatialDomain = field( + default_factory=SourceSpatialDomain + ) @classmethod def empty(cls) -> CompiledSourceBindingPlan: @@ -2165,6 +2242,7 @@ def from_config( realized_source_metadata ), source_stack_components=config.source_stack_components, + source_spatial_domain=config.source_spatial_domain, ) def __post_init__(self) -> None: @@ -2227,6 +2305,7 @@ def __reduce__( SourceBindingMatchPlan | None, tuple[FieldSpec, ...], tuple[AllComponents, ...], + SourceSpatialDomain, ], ]: """Serialize source-binding plan state for multiprocessing.""" @@ -2238,6 +2317,7 @@ def __reduce__( self.match_plan, self.metadata_fields, self.source_stack_components, + self.source_spatial_domain, ), ) @@ -2259,6 +2339,7 @@ def _from_pickled_state( match_plan: SourceBindingMatchPlan | None, metadata_fields: tuple[FieldSpec, ...], source_stack_components: tuple[AllComponents, ...], + source_spatial_domain: SourceSpatialDomain, ) -> CompiledSourceBindingPlan: return cls( bindings=bindings, @@ -2266,6 +2347,7 @@ def _from_pickled_state( match_plan=match_plan, metadata_fields=metadata_fields, source_stack_components=source_stack_components, + source_spatial_domain=source_spatial_domain, ) @@ -2360,380 +2442,13 @@ class SourceBindingRuntimeMetadataNormalizer: def normalized(self) -> Mapping[str, SourceMetadataMapping]: return MappingProxyType( { - str(path): MappingProxyType( - { - str(key): self.normalized_value(value) - for key, value in source_metadata_dict(metadata).items() - } + str(path): ResolvedSourceMetadataRecord.normalized_mapping( + source_metadata_dict(metadata) ) for path, metadata in self.source_metadata_by_path.items() } ) - @classmethod - def normalized_value(cls, value: SourceMetadataValue) -> SourceMetadataValue: - if isinstance(value, Mapping): - return MappingProxyType( - { - str(key): cls.normalized_scalar(nested_value) - for key, nested_value in value.items() - } - ) - return cls.normalized_scalar(value) - - @staticmethod - def normalized_scalar(value: SourceMetadataScalar) -> SourceMetadataScalar: - return source_metadata_scalar(value) - - -@dataclass(frozen=True) -class SourceBindingRuntimeContext: - """Execution-local file universe for selector-bearing source bindings.""" - - step_input_files: tuple[str, ...] = () - current_step_input_files: tuple[str, ...] = () - current_image_files: tuple[str, ...] = () - step_input_dir: str | None = None - step_input_source_backend: str | None = None - step_input_storage_backend: str | None = None - step_input_source_paths: Mapping[str, str] = field( - default_factory=lambda: MappingProxyType({}) - ) - source_metadata_by_path: Mapping[str, SourceMetadataMapping] = field( - default_factory=lambda: MappingProxyType({}) - ) - pipeline_input_files: tuple[str, ...] = () - pipeline_source_candidate_files: tuple[str, ...] = () - pipeline_input_backend: str | None = None - source_metadata_is_normalized: InitVar[bool] = False - _source_metadata_identity: SourceMetadataIdentity | None = field( - default=None, - init=False, - repr=False, - compare=False, - ) - _pipeline_input_files_identity: tuple[str, ...] | None = field( - default=None, - init=False, - repr=False, - compare=False, - ) - _source_order_identity: tuple[Hashable, ...] | None = field( - default=None, - init=False, - repr=False, - compare=False, - ) - _process_semantic_identity: SourceBindingRuntimeContextProcessIdentity | None = ( - field( - default=None, - init=False, - repr=False, - compare=False, - ) - ) - _virtual_source_paths_by_identity: Mapping[str, tuple[str, ...]] | None = field( - default=None, - init=False, - repr=False, - compare=False, - ) - _source_metadata_by_runtime_lookup_key: ( - Mapping[ - str, - SourceMetadataMapping, - ] - | None - ) = field( - default=None, - init=False, - repr=False, - compare=False, - ) - - @classmethod - def empty(cls) -> SourceBindingRuntimeContext: - return cls() - - def __post_init__( - self, - source_metadata_is_normalized: bool, - ) -> None: - object.__setattr__(self, "step_input_files", tuple(self.step_input_files)) - object.__setattr__( - self, - "current_step_input_files", - tuple(self.current_step_input_files or self.step_input_files), - ) - object.__setattr__( - self, - "current_image_files", - tuple(self.current_image_files or self.current_step_input_files), - ) - if self.step_input_dir is not None: - object.__setattr__(self, "step_input_dir", str(self.step_input_dir)) - if self.step_input_source_backend is not None: - object.__setattr__( - self, - "step_input_source_backend", - str(self.step_input_source_backend), - ) - if self.step_input_storage_backend is not None: - object.__setattr__( - self, - "step_input_storage_backend", - str(self.step_input_storage_backend), - ) - step_input_source_paths = self.step_input_source_paths - if not isinstance(step_input_source_paths, MappingProxyType): - step_input_source_paths = MappingProxyType( - { - str(path): str(source) - for path, source in step_input_source_paths.items() - } - ) - object.__setattr__(self, "step_input_source_paths", step_input_source_paths) - - if source_metadata_is_normalized: - if not isinstance(self.source_metadata_by_path, MappingProxyType): - raise TypeError( - "Normalized SourceBindingRuntimeContext metadata must be " - "MappingProxyType." - ) - else: - object.__setattr__( - self, - "source_metadata_by_path", - SourceBindingRuntimeMetadataNormalizer( - self.source_metadata_by_path - ).normalized(), - ) - object.__setattr__( - self, - "pipeline_input_files", - tuple(self.pipeline_input_files), - ) - object.__setattr__( - self, - "pipeline_source_candidate_files", - tuple( - self.pipeline_source_candidate_files - or self.pipeline_input_files - or self.step_input_files - ), - ) - if self.pipeline_input_backend is not None: - object.__setattr__( - self, - "pipeline_input_backend", - str(self.pipeline_input_backend), - ) - - @property - def source_metadata_identity( - self, - ) -> SourceMetadataIdentity: - """Stable identity for the complete source-metadata universe.""" - - cached = self._source_metadata_identity - if cached is None: - cached = tuple( - (path, SourceMetadataIdentityProjection(metadata).items()) - for path, metadata in sorted(self.source_metadata_by_path.items()) - ) - object.__setattr__(self, "_source_metadata_identity", cached) - return cached - - @property - def process_semantic_identity(self) -> SourceBindingRuntimeContextProcessIdentity: - """Return the source context identity used by process-local caches.""" - cached = self._process_semantic_identity - if cached is None: - cached = SourceBindingRuntimeContextProcessIdentity( - source_order_identity=self.source_order_identity, - source_metadata_identity=self.source_metadata_identity, - ) - object.__setattr__(self, "_process_semantic_identity", cached) - return cached - - @property - def source_metadata_by_runtime_lookup_key( - self, - ) -> Mapping[str, SourceMetadataMapping]: - """Return source metadata indexed by every runtime path spelling.""" - cached = self._source_metadata_by_runtime_lookup_key - if cached is None: - indexed: dict[str, SourceMetadataMapping] = {} - for path, metadata in self.source_metadata_by_path.items(): - for key in _source_runtime_path_lookup_keys( - str(path), - self.step_input_dir, - ): - indexed.setdefault(key, metadata) - indexed.setdefault(_source_runtime_native_path(str(path)), metadata) - cached = MappingProxyType(indexed) - object.__setattr__( - self, - "_source_metadata_by_runtime_lookup_key", - cached, - ) - return cached - - def source_metadata_for_runtime_path( - self, - path: str, - ) -> SourceMetadataMapping | None: - """Return source metadata for one runtime path spelling, if known.""" - lookup = self.source_metadata_by_runtime_lookup_key - for key in _source_runtime_path_lookup_keys(str(path), self.step_input_dir): - metadata = lookup.get(key) - if metadata is not None: - return metadata - return lookup.get(_source_runtime_native_path(str(path))) - - @property - def pipeline_input_files_identity(self) -> tuple[str, ...]: - """Return sorted pipeline input files for source-order cache identities.""" - cached = self._pipeline_input_files_identity - if cached is None: - cached = tuple(sorted(self.pipeline_input_files)) - object.__setattr__(self, "_pipeline_input_files_identity", cached) - return cached - - @property - def source_order_identity(self) -> tuple[Hashable, ...]: - """Return source-order mapping identity shared by runtime source caches.""" - cached = self._source_order_identity - if cached is None: - cached = ( - self.step_input_dir, - tuple(sorted(self.pipeline_source_candidate_files)), - tuple(sorted(self.step_input_source_paths.items())), - tuple(sorted(self.virtual_source_paths_by_identity.items())), - ) - object.__setattr__(self, "_source_order_identity", cached) - return cached - - @property - def virtual_source_paths_by_identity(self) -> Mapping[str, tuple[str, ...]]: - """Return virtual source paths grouped by normalized physical identity.""" - - cached = self._virtual_source_paths_by_identity - if cached is None: - grouped: dict[str, list[str]] = {} - for virtual_path, source_path in self.step_input_source_paths.items(): - for identity in self.source_path_identities(source_path): - paths = grouped.get(identity) - if paths is None: - grouped[identity] = [virtual_path] - continue - paths.append(virtual_path) - cached = MappingProxyType( - { - identity: tuple(dict.fromkeys(paths)) - for identity, paths in grouped.items() - } - ) - object.__setattr__(self, "_virtual_source_paths_by_identity", cached) - return cached - - @staticmethod - @lru_cache(maxsize=8192) - def source_path_identities(source_path: str) -> tuple[str, ...]: - """Return path identities for stored and resolved source-path spellings.""" - path = Path(source_path) - return tuple( - dict.fromkeys( - ( - source_path_identity_key(source_path), - source_path_identity_key(str(path.resolve(strict=False))), - ) - ) - ) - - def path_spellings(self, paths: Sequence[str]) -> tuple[str, ...]: - """Return virtual and physical spellings represented by selected paths.""" - - selected: list[str] = [] - for path in paths: - selected.append(str(path)) - mapped = self.step_input_source_paths.get(str(path)) - if mapped is not None: - selected.append(mapped) - for identity in self.source_path_identities(str(path)): - selected.extend(self.virtual_source_paths_by_identity.get(identity, ())) - return tuple(dict.fromkeys(selected)) - - def metadata_identity_for_paths( - self, - paths: tuple[str, ...], - ) -> SourceMetadataIdentity: - """Return the stable metadata identity for a selected source subset.""" - - identity: list[tuple[str, SourceMetadataIdentityItems]] = [] - for path in paths: - if path in self.source_metadata_by_path: - metadata = SourceMetadataIdentityProjection( - self.source_metadata_by_path[path] - ).items() - else: - metadata = () - identity.append((path, metadata)) - return tuple(identity) - - def source_candidate_file_universes(self) -> tuple[tuple[str, ...], ...]: - """Return distinct non-empty file universes that may be source-parsed.""" - return tuple( - dict.fromkeys( - files - for files in ( - self.step_input_files, - self.current_step_input_files, - self.pipeline_source_candidate_files, - ) - if files - ) - ) - - def __reduce__( - self, - ) -> tuple[ - object, - tuple[ - tuple[str, ...], - tuple[str, ...], - tuple[str, ...], - str | None, - str | None, - str | None, - dict[str, str], - dict[str, dict[str, SourceMetadataValue]], - tuple[str, ...], - tuple[str, ...], - str | None, - ], - ]: - """Serialize mappingproxy-backed provenance as a plain dict.""" - return ( - self.__class__, - ( - self.step_input_files, - self.current_step_input_files, - self.current_image_files, - self.step_input_dir, - self.step_input_source_backend, - self.step_input_storage_backend, - dict(self.step_input_source_paths), - { - path: source_metadata_dict(metadata) - for path, metadata in self.source_metadata_by_path.items() - }, - self.pipeline_input_files, - self.pipeline_source_candidate_files, - self.pipeline_input_backend, - ), - ) - EMPTY_SOURCE_BINDINGS = StepSourceBindingsConfig() diff --git a/openhcs/core/source_image_provenance.py b/openhcs/core/source_image_provenance.py index 71ff6ef174..b23f9afe55 100644 --- a/openhcs/core/source_image_provenance.py +++ b/openhcs/core/source_image_provenance.py @@ -20,6 +20,8 @@ from openhcs.core.source_metadata import ( SOURCE_PLANE_COUNT_FIELD, SOURCE_PLANE_INDEX_FIELD, + OwnedSourceMetadataFields, + SourceMetadataFields, SourceMetadataMapping, SourceMetadataScalar, SourceMetadataValue, @@ -69,20 +71,12 @@ def normalize_source_path(source_path: str | None) -> str | None: return str(source_path) -def _normalize_component_metadata( - metadata: SourceComponentMetadata | None, -) -> SourceComponentMetadata | None: - if metadata is None: - return None - return MappingProxyType(dict(metadata)) - - def _component_metadata_identity( metadata: SourceComponentMetadata | None, ) -> tuple[tuple[str, str], ...] | None: if metadata is None: return None - return tuple(sorted((str(key), repr(value)) for key, value in metadata.items())) + return SourceMetadataFields.provenance_identity_items(metadata) def _tuple_value(values: tuple[Any, ...], index: int) -> Any | None: @@ -101,7 +95,10 @@ class SourceImageIdentity: def __post_init__(self) -> None: self.path = normalize_source_path(self.path) - self.component_metadata = _normalize_component_metadata(self.component_metadata) + if self.component_metadata is not None: + self.component_metadata = SourceMetadataFields.readonly_snapshot( + self.component_metadata + ) self._identity = ( self.path, _component_metadata_identity(self.component_metadata), @@ -137,6 +134,22 @@ def with_missing_from( component_metadata=self.component_metadata_with_missing_from(fallback), ) + def image_set_identities( + self, + policy: SourceImageSetIdentityPolicy, + ) -> frozenset[SourceImageSetIdentity]: + """Project this scalar source address into its declared image-set domain.""" + identity = SourceImageSetIdentity.from_metadata( + self.component_metadata or {}, + fallback_source_path=self.path or "", + policy=policy, + ) + return ( + frozenset() + if identity.components == (("source_path", ""),) + else frozenset((identity,)) + ) + def component_metadata_with_missing_from( self, fallback: "SourceImageIdentity", @@ -147,21 +160,10 @@ def component_metadata_with_missing_from( if fallback.component_metadata is None: return self.component_metadata - merged = dict(self.component_metadata) - for component in AllComponents: - if source_component_metadata_value(merged, component) is not None: - continue - fallback_value = source_component_metadata_raw_value( - fallback.component_metadata, - component, - ) - if fallback_value is not None: - merged[component.value] = fallback_value - if self.filename_extension is None: - extension = fallback.filename_extension - if extension is not None: - merged["extension"] = extension - return MappingProxyType(merged) + merged = SourceMetadataFields.with_missing_from( + self.component_metadata, fallback.component_metadata + ) + return SourceMetadataFields.readonly_snapshot(merged) def with_parsed_path_components( self, @@ -716,6 +718,142 @@ def __init__( self.source_image_names, ) + def as_runtime_plane(self) -> RuntimeSourceImageProvenancePlane: + """Compose one scalar source, retaining its non-projectable contributors.""" + names = self.source_image_names + contributors = self.source_image_provenance_planes.as_contributors(names).planes + if len(names) > 1: + raise ValueError( + "Composed image payload provenance permits at most one " + f"source alias per scalar plane, got {names!r}." + ) + return RuntimeSourceImageProvenancePlane( + SourceImageIdentity(self.source_path, self.source_component_metadata), + contributors, + names[0] if names else None, + ) + + @classmethod + def stack( + cls, + sources: Sequence["SourceImageProvenance"], + *, + scalar_sources: Sequence["SourceImageProvenance"] | None = None, + preserve_single_topology: bool = True, + ) -> Self: + """Compose ordered runtime sources with their common scalar coordinates.""" + return cls._compose( + tuple(sources), + scalar_sources, + preserve_single_topology=preserve_single_topology, + bundle=False, + ) + + @classmethod + def bundle( + cls, + sources: Sequence["SourceImageProvenance"], + *, + scalar_sources: Sequence["SourceImageProvenance"] | None = None, + preserve_single_topology: bool = False, + ) -> Self: + """Compose same-slice sources, retaining nonconflicting partial coordinates.""" + return cls._compose( + tuple(sources), + scalar_sources, + preserve_single_topology=preserve_single_topology, + bundle=True, + ) + + @staticmethod + def bundle_component_metadata( + sources: Sequence["SourceImageProvenance"], + *, + scalar_sources: Sequence["SourceImageProvenance"] | None = None, + ) -> SourceComponentMetadata | None: + metadata = tuple( + SourceMetadataFields.composition_snapshot(fields) + for fields in SourceImageProvenance._composition_component_metadata( + sources, scalar_sources + ) + if fields is not None + ) + common: dict[str, SourceMetadataValue] = {} + for name in set().union(*(fields.keys() for fields in metadata)): + values = tuple(fields[name] for fields in metadata if name in fields) + if values and all(value == values[0] for value in values): + common[name] = values[0] + if not common: + return None + owner = ( + metadata[0] + if metadata + and all( + isinstance(fields, OwnedSourceMetadataFields) for fields in metadata + ) + else {} + ) + derived = SourceMetadataFields.derived_mapping(owner, common) + return ( + derived + if isinstance(derived, OwnedSourceMetadataFields) + else MappingProxyType(derived) + ) + + @staticmethod + def _composition_component_metadata( + sources: Sequence["SourceImageProvenance"], + scalar_sources: Sequence["SourceImageProvenance"] | None, + ) -> tuple[SourceComponentMetadata | None, ...]: + """Retain authored scalar coordinates before inheriting selected plane facts.""" + if scalar_sources is None: + scalar_sources = sources + return tuple( + ( + scalar.source_component_metadata + if scalar.source_component_metadata is not None + else selected.source_component_metadata + ) + for scalar, selected in zip(scalar_sources, sources, strict=True) + ) + + @classmethod + def _compose( + cls, + sources: tuple["SourceImageProvenance", ...], + scalar_sources: Sequence["SourceImageProvenance"] | None, + *, + preserve_single_topology: bool, + bundle: bool, + ) -> Self: + if not sources: + raise ValueError("Source provenance composition cannot be empty.") + planes = ( + sources[0].source_image_provenance_planes + if preserve_single_topology + and len(sources) == 1 + and sources[0].source_plane_count > 1 + else SourceImageProvenancePlanes( + tuple(source.as_runtime_plane() for source in sources) + ) + ) + component_metadata = ( + cls.bundle_component_metadata(sources, scalar_sources=scalar_sources) + if bundle + else common_source_component_metadata( + cls._composition_component_metadata(sources, scalar_sources) + ) + ) + present_paths = tuple( + source.source_path for source in sources if source.source_path is not None + ) + return cls( + source_path=common_source_path(present_paths), + source_component_metadata=component_metadata, + source_image_provenance_planes=planes, + source_image_names=planes.runtime_source_image_names, + ) + @classmethod def from_init_values( cls, @@ -834,14 +972,7 @@ def image_set_identities( policy: SourceImageSetIdentityPolicy, ) -> frozenset[SourceImageSetIdentity]: """Return the image-set identity represented by scalar provenance.""" - identity = SourceImageSetIdentity.from_metadata( - self.source_component_metadata or {}, - fallback_source_path=self.source_path or "", - policy=policy, - ) - if identity.components == (("source_path", ""),): - return frozenset() - return frozenset((identity,)) + return self.source_identity.image_set_identities(policy) def image_set_axis( self, @@ -859,10 +990,24 @@ def image_set_plane_identities( ) -> tuple[frozenset[SourceImageSetIdentity], ...]: """Return one image-set identity entry for every runtime source plane.""" return tuple( - self.for_source_plane(index).image_set_identities(policy) + self.source_image_provenance_planes.plane( + index + ).source_identity.with_missing_from( + self.source_identity + ).image_set_identities(policy) for index in range(self.source_plane_count) ) + def component_metadata_for_plane( + self, plane_index: int + ) -> SourceComponentMetadata | None: + """Read current plane coordinates with their scalar source fallback.""" + if not self.source_plane_count: + return self.source_component_metadata + return self.source_image_provenance_planes.plane( + plane_index + ).source_identity.component_metadata_with_missing_from(self.source_identity) + def for_source_plane(self, plane_index: int) -> "SourceImageProvenance": if self.source_plane_count == 0: return type(self)( @@ -986,16 +1131,20 @@ def varying_plane_component_values( components: Sequence[AllComponents], ) -> dict[str, tuple[SourceMetadataScalar, ...]]: """Return exact component values that vary across declared source planes.""" - if self.source_plane_count <= 1: + if not components or self.source_plane_count <= 1: return {} + metadata_by_plane = tuple( + self.component_metadata_for_plane(index) or {} + for index in range(self.source_plane_count) + ) values_by_component: dict[str, tuple[SourceMetadataScalar, ...]] = {} for component in components: values = tuple( source_component_metadata_raw_value( - self.for_source_plane(plane_index).source_component_metadata or {}, + metadata, component, ) - for plane_index in range(self.source_plane_count) + for metadata in metadata_by_plane ) if any(value is None for value in values): continue @@ -1009,24 +1158,24 @@ def require_common_component_values( ) -> tuple[tuple[AllComponents, str], ...]: """Return fixed component values shared by every represented source plane.""" + if not components: + return () + metadata_by_plane = ( + tuple( + self.component_metadata_for_plane(index) or {} + for index in range(self.source_plane_count) + ) + if self.source_plane_count + else (self.source_component_metadata or {},) + ) values: list[tuple[AllComponents, str]] = [] for component in components: - metadata_values = ( - tuple( - source_component_metadata_value( - self.for_source_plane(plane_index).source_component_metadata - or {}, - component, - ) - for plane_index in range(self.source_plane_count) - ) - if self.source_plane_count - else ( - source_component_metadata_value( - self.source_component_metadata or {}, - component, - ), + metadata_values = tuple( + source_component_metadata_value( + metadata, + component, ) + for metadata in metadata_by_plane ) if any(value is None for value in metadata_values): raise ValueError( @@ -1505,18 +1654,15 @@ def component_metadata_for_plane( self, plane_index: int, ) -> SourceComponentMetadata: - metadata = { - **dict(self.scalar_metadata), - SOURCE_PLANE_INDEX_FIELD: str(plane_index), - SOURCE_PLANE_COUNT_FIELD: str(self.source_plane_count), - } - return MappingProxyType( - with_source_component_metadata( - metadata, - AllComponents.Z_INDEX, - self.z_index_for_plane(plane_index), - ) + metadata = SourceMetadataFields.with_fields( + SourceMetadataFields.composition_snapshot(self.scalar_metadata), + { + SOURCE_PLANE_INDEX_FIELD: str(plane_index), + SOURCE_PLANE_COUNT_FIELD: str(self.source_plane_count), + }, + components=((AllComponents.Z_INDEX, self.z_index_for_plane(plane_index)),), ) + return SourceMetadataFields.readonly_snapshot(metadata) def z_index_for_plane(self, plane_index: int) -> int: scalar_z_index = source_component_metadata_value( @@ -1585,7 +1731,9 @@ def common_source_component_metadata( } if not common_metadata: return None - return MappingProxyType(common_metadata) + return SourceMetadataFields.readonly_snapshot( + SourceMetadataFields.derived_mapping(consensus, common_metadata) + ) def source_component_metadata_consensus( @@ -1594,7 +1742,9 @@ def source_component_metadata_consensus( """Return every metadata field, nulling values that differ between planes.""" metadata_values = tuple( - dict(metadata) for metadata in metadata_by_plane if metadata is not None + SourceMetadataFields.composition_snapshot(metadata) + for metadata in metadata_by_plane + if metadata is not None ) if len(metadata_values) != len(metadata_by_plane): return None @@ -1618,7 +1768,17 @@ def source_component_metadata_consensus( and all(value == present_values[0] for value in present_values) else None ) - return MappingProxyType(consensus) + owner = ( + metadata_values[0] + if all( + isinstance(metadata, OwnedSourceMetadataFields) + for metadata in metadata_values + ) + else {} + ) + return SourceMetadataFields.readonly_snapshot( + SourceMetadataFields.derived_mapping(owner, consensus) + ) def common_source_path(paths: Sequence[str | None]) -> str | None: @@ -1775,8 +1935,17 @@ class SourceImageProvenanceFields: def absorb_explicit_source_provenance( self, - explicit: SourceImageProvenance, + values: SourceProvenanceInitValues, ) -> None: + """Decode authored aliases once, leaving absent constructor facts absent.""" + if all( + value is default + for value, default in zip( + values, SourceImageProvenance.__init__.__defaults__, strict=True + ) + ): + return + explicit = SourceImageProvenance.from_init_values(values) if not explicit.has_values: return self.source_provenance = explicit.with_missing_from(self.source_provenance) diff --git a/openhcs/core/source_image_semantics.py b/openhcs/core/source_image_semantics.py deleted file mode 100644 index b12f30692f..0000000000 --- a/openhcs/core/source_image_semantics.py +++ /dev/null @@ -1,107 +0,0 @@ -"""Generic source payload transforms declared by source bindings.""" - -from __future__ import annotations - -from dataclasses import replace -import numpy as np -from openhcs.core.runtime_image_values import ( - ImageMetadataPayload, - ImagePayloadMetadata, - MaskedImagePayload, - image_payload_data, - image_payload_mask, - image_payload_metadata, - normalize_image_payload_intensity, -) -from openhcs.core.runtime_image_loading import ImagePayloadSourceMetadataContext -from openhcs.core.runtime_array_values import RuntimeArrayData -from openhcs.core.source_bindings import NamedSourceBinding - - -def _rgb_to_monochrome(data: np.ndarray) -> np.ndarray: - rgb = np.asarray(data)[..., :3] - if np.all(rgb == rgb[..., :1]): - return np.ascontiguousarray(rgb[..., 0]) - - from skimage.color import rgb2gray - - return rgb2gray(rgb) - - -def _monochrome_source_data( - data: RuntimeArrayData, - channel_axis: int | None, - metadata: ImagePayloadMetadata, -) -> RuntimeArrayData: - if channel_axis is None: - return data - normalized = normalize_image_payload_intensity( - metadata.payload_with(data), - dtype=np.float32, - ) - channel_last = np.moveaxis( - np.asarray(image_payload_data(normalized)), - channel_axis, - -1, - ) - return _rgb_to_monochrome(channel_last) - - -def _loaded_source_payload_metadata( - payload: RuntimeArrayData, - binding: NamedSourceBinding, - source_context: ImagePayloadSourceMetadataContext | None, -) -> ImagePayloadMetadata: - existing = image_payload_metadata(payload) - if source_context is None: - metadata = ( - existing - if existing.has_values - else ImagePayloadMetadata.for_array_payload(payload) - ) - else: - metadata = source_context.metadata(payload, source_binding=binding) - metadata = metadata.replace_fields( - source_provenance=metadata.source_provenance.with_source_image_names( - (binding.alias,) - ) - ) - source_channel_axis = binding.source_channel_axis_for_shape( - np.shape(image_payload_data(payload)), - observed_axis=metadata.source_channel_axis, - ) - metadata = replace(metadata, source_channel_axis=source_channel_axis) - metadata.normalized_source_channel_axis(payload) - return metadata - - -def apply_source_binding_payload( - payload: RuntimeArrayData, - binding: NamedSourceBinding, - source_context: ImagePayloadSourceMetadataContext | None, -) -> RuntimeArrayData: - """Apply one resolved source binding to a loaded runtime payload.""" - metadata = _loaded_source_payload_metadata(payload, binding, source_context) - data = image_payload_data(payload) - source_channel_axis = metadata.source_channel_axis - data, source_channel_axis = binding.artifact_kind.normalize_source_payload( - data, - source_channel_axis, - ) - if binding.load_as_monochrome and source_channel_axis is not None: - data = _monochrome_source_data(data, source_channel_axis, metadata) - source_channel_axis = None - metadata = replace( - metadata.without_unit_interval_intensity_scale(), - intensity_scale=ImagePayloadMetadata.for_array(data).intensity_scale, - ) - if binding.load_as_mask: - data = np.asarray(data, dtype=bool) - - mask = image_payload_mask(payload) - metadata = replace(metadata, source_channel_axis=source_channel_axis) - if mask is not None: - return MaskedImagePayload(data, mask, metadata) - if metadata.has_values: - return ImageMetadataPayload(data, metadata) - return data diff --git a/openhcs/core/source_matching.py b/openhcs/core/source_matching.py index 3c9d1e0d86..66108ec9fe 100644 --- a/openhcs/core/source_matching.py +++ b/openhcs/core/source_matching.py @@ -30,12 +30,13 @@ OriginalSourceMetadata, SourceFilterPathMetadata, SourceMetadataMapping, - SourceMetadataRoleView, + SourceMetadataFields, SourceMetadataScalar, SourceMetadataValue, SourceComponentProjectionStrategy, path_metadata_values_equivalent, source_metadata_field_identity, + source_metadata_component, source_metadata_dict, source_metadata_scalar, ) @@ -709,7 +710,7 @@ def overlay_source_metadata( for component, value in projected_components.items(): overlaid = with_source_component_metadata(overlaid, component, value) - for field, value in SourceMetadataRoleView(additions).scalar_items(): + for field, value in SourceMetadataFields.scalar_items(additions): if value is None: continue component = source_metadata_component(field) @@ -770,7 +771,7 @@ def source_metadata_value( key: str, ) -> SourceMetadataScalar: """Return one source-literal metadata value by its exact declared key.""" - return _source_metadata_lookup_projection(metadata).value(key) + return SourceMetadataFields.literal_value(metadata, key) def source_component_metadata_value( @@ -819,7 +820,7 @@ def semantic_source_metadata_value( field_identity = source_metadata_field_identity(field_name) semantic_values = tuple( value - for field, value in SourceMetadataRoleView(metadata).scalar_items() + for field, value in SourceMetadataFields.scalar_items(metadata) if value is not None and source_metadata_field_identity(str(field)) == field_identity ) @@ -846,14 +847,14 @@ def source_component_metadata_values( component: AllComponents, ) -> tuple[str, ...]: """Return all metadata values that semantically describe a component.""" - return _source_metadata_lookup_projection(metadata).component_values(component) + return SourceMetadataFields.component_values(metadata, component) def with_source_component_metadata( metadata: SourceMetadataMapping, component: AllComponents, value: SourceMetadataScalar, -) -> dict[str, SourceMetadataValue]: +) -> SourceMetadataMapping: """Return metadata with one canonical component value. Source schemas can carry CellProfiler spellings such as ``Well`` and OpenHCS @@ -861,15 +862,7 @@ def with_source_component_metadata( every semantic spelling so later normalized lookups cannot observe both the old and new component values. """ - return { - **{ - key: field_value - for key, field_value in metadata.items() - if key == ORIGINAL_SOURCE_METADATA_FIELD - or source_metadata_component(str(key)) is not component - }, - component.value: str(value), - } + return SourceMetadataFields.with_component(metadata, component, value) def source_metadata_values_equal( @@ -969,62 +962,10 @@ def constraint_matches_metadata( return any( metadata_value is not None and source_metadata_values_equal(str(metadata_value), value) - for metadata_value in SourceMetadataRoleView(metadata).scalar_values() + for metadata_value in SourceMetadataFields.scalar_values(metadata) ) -@lru_cache(maxsize=256) -def source_metadata_component(field: str) -> AllComponents | None: - """Return the nominal component owner of a metadata field.""" - - return SourceComponentProjectionStrategy.component_for_metadata_field(field) - - -@dataclass(frozen=True, slots=True) -class SourceMetadataLookupProjection: - """Lookup projection over the current contents of one source metadata mapping.""" - - scalar_items: tuple[tuple[str, SourceMetadataScalar], ...] - original_items: tuple[tuple[str, SourceMetadataScalar], ...] - - def value(self, key: str) -> SourceMetadataScalar: - """Return a source-literal metadata value by exact key.""" - for candidate_key, value in self.original_items: - if str(candidate_key) == key and value is not None: - return value - for candidate_key, value in self.scalar_items: - if str(candidate_key) == key and value is not None: - return value - return None - - def component_values(self, component: AllComponents) -> tuple[str, ...]: - """Return all metadata values that semantically describe a component.""" - values: list[str] = [] - for field, field_value in self.scalar_items: - field_text = str(field) - if field_text == component.value and field_value is not None: - values.append(str(field_value)) - for field, field_value in self.scalar_items: - field_text = str(field) - if ( - field_text != component.value - and source_metadata_component(field_text) is component - ) and field_value is not None: - values.append(str(field_value)) - return tuple(dict.fromkeys(values)) - - -def _source_metadata_lookup_projection( - metadata: SourceMetadataMapping, -) -> SourceMetadataLookupProjection: - """Derive a lookup projection from the current nominal metadata role view.""" - role_view = SourceMetadataRoleView(metadata) - return SourceMetadataLookupProjection( - scalar_items=role_view.scalar_items(), - original_items=role_view.original_items(), - ) - - def _require_filter_value(clause: SourceFilterClause) -> str: if clause.value is None: raise ValueError( diff --git a/openhcs/core/source_metadata.py b/openhcs/core/source_metadata.py index 9df21e92ba..bd48c004d3 100644 --- a/openhcs/core/source_metadata.py +++ b/openhcs/core/source_metadata.py @@ -3,13 +3,14 @@ from __future__ import annotations from abc import ABC, abstractmethod -from collections.abc import Callable, Iterable, Mapping +from collections.abc import Callable, Iterable, Iterator, Mapping, Sequence from dataclasses import dataclass, field from enum import Enum from functools import lru_cache from math import isfinite from pathlib import Path -from typing import ClassVar, TypeAlias +from types import MappingProxyType +from typing import ClassVar, NoReturn, Self, TYPE_CHECKING, TypeAlias, TypeVar from metaclass_registry import AutoRegisterMeta from zmqruntime.viewer_protocol import ViewerWireField @@ -17,6 +18,11 @@ from openhcs.constants.constants import AllComponents from openhcs.core.registry_strategies import EnumKeyedStrategyMixin +if TYPE_CHECKING: + from openhcs.core.source_bindings import MetadataExtractionRule + from openhcs.microscopes.microscope_interfaces import FilenameParser + + ORIGINAL_SOURCE_METADATA_FIELD = "OpenHCSOriginalSourceMetadata" SOURCE_FILTER_PATHS_METADATA_FIELD = "OpenHCSSourceFilterPaths" SOURCE_PLANE_INDEX_FIELD = "source_plane_index" @@ -24,7 +30,8 @@ SOURCE_VOXEL_SPACING_FIELD = "OpenHCSSourceVoxelSpacingZYX" SOURCE_VOXEL_SPACING_UNIT_FIELD = "OpenHCSSourceVoxelSpacingUnit" -SourceMetadataScalar: TypeAlias = str | int | float | bool | None +SourceMetadataNonNullScalar: TypeAlias = str | int | float | bool +SourceMetadataScalar: TypeAlias = SourceMetadataNonNullScalar | None SourceMetadataValue: TypeAlias = ( SourceMetadataScalar | Mapping[str, SourceMetadataScalar] ) @@ -38,6 +45,511 @@ ] +_MetadataViewT = TypeVar("_MetadataViewT") + + +@dataclass(frozen=True, slots=True, eq=False) +class SourceMetadataFields(Mapping[str, SourceMetadataValue]): + """Common field projection algorithms with nominal lifetime-selected views.""" + + fields: tuple[tuple[str, SourceMetadataValue], ...] + + @staticmethod + def canonical_component_value( + component: AllComponents | None, + value: SourceMetadataScalar, + ) -> str | int: + """Canonicalize numeric variable coordinates while retaining labels.""" + if component is None or not component.is_variable_axis(): + return str(value) + value_text = str(value) + return int(value_text) if value_text.isdecimal() else value_text + + @classmethod + def from_mapping(cls, metadata: SourceMetadataMapping) -> Self: + return cls(tuple(metadata.items())) + + @classmethod + def normalized_value(cls, value: SourceMetadataValue) -> SourceMetadataValue: + if isinstance(value, Mapping): + return MappingProxyType( + { + str(key): cls.normalized_scalar(nested_value) + for key, nested_value in value.items() + } + ) + return cls.normalized_scalar(value) + + @classmethod + def normalized_mapping( + cls, metadata: SourceMetadataMapping + ) -> SourceMetadataMapping: + return MappingProxyType( + {str(key): cls.normalized_value(value) for key, value in metadata.items()} + ) + + @classmethod + def normalized_scalar(cls, value: SourceMetadataScalar) -> SourceMetadataScalar: + """Admit the shared scalar grammar before applying the owner's policy.""" + if value is None: + return None + if isinstance(value, SourceMetadataNonNullScalar): + return cls._normalize_admitted_scalar(value) + return cls._reject_scalar(value) + + @staticmethod + def _normalize_admitted_scalar( + value: SourceMetadataNonNullScalar, + ) -> SourceMetadataNonNullScalar: + if isinstance(value, str): + return canonical_path_metadata_value(value) + return value + + @staticmethod + def _reject_scalar(value: object) -> NoReturn: + raise TypeError( + "Source metadata scalar values must be str, int, float, bool, or None, " + f"got {type(value).__name__}." + ) + + def __getitem__(self, key: str) -> SourceMetadataValue: + for field_key, value in self.fields: + if field_key == key: + return value + raise KeyError(key) + + def __iter__(self) -> Iterator[str]: + return (key for key, _value in self.fields) + + def __len__(self) -> int: + return len(self.fields) + + @abstractmethod + def __eq__(self, other: object) -> bool: + """Compare through the declared record or mapping namespace.""" + + def _derived_view( + self, key: str | AllComponents, derive: Callable[[], _MetadataViewT] + ) -> _MetadataViewT: + return derive() + + @staticmethod + def _view( + metadata: SourceMetadataMapping, + key: str | AllComponents, + derive: Callable[[], _MetadataViewT], + ) -> _MetadataViewT: + if isinstance(metadata, SourceMetadataFields): + return metadata._derived_view(key, derive) + return derive() + + @classmethod + def scalar_items( + cls, metadata: SourceMetadataMapping + ) -> tuple[tuple[str, SourceMetadataScalar], ...]: + """Read current raw fields or the immutable owner's scalar projection.""" + return cls._view( + metadata, + "scalar_items", + lambda: tuple( + (str(key), value) + for key, value in metadata.items() + if key != ORIGINAL_SOURCE_METADATA_FIELD + and not isinstance(value, Mapping) + ), + ) + + @classmethod + def scalar_values( + cls, metadata: SourceMetadataMapping + ) -> tuple[SourceMetadataScalar, ...]: + return tuple(value for _key, value in cls.scalar_items(metadata)) + + @classmethod + def original_items( + cls, metadata: SourceMetadataMapping + ) -> tuple[tuple[str, SourceMetadataScalar], ...]: + def project() -> tuple[tuple[str, SourceMetadataScalar], ...]: + original_metadata = metadata.get(ORIGINAL_SOURCE_METADATA_FIELD) + if original_metadata is None: + return () + return OriginalSourceMetadata.from_reserved_value( + original_metadata, path=ORIGINAL_SOURCE_METADATA_FIELD + ).fields + + return cls._view(metadata, "original_items", project) + + @classmethod + def source_filter_paths(cls, metadata: SourceMetadataMapping) -> tuple[str, ...]: + def project() -> tuple[str, ...]: + paths = metadata.get(SOURCE_FILTER_PATHS_METADATA_FIELD) + if paths is None: + return () + return SourceFilterPathMetadata.from_reserved_value( + paths, path=SOURCE_FILTER_PATHS_METADATA_FIELD + ).paths + + return cls._view(metadata, "source_filter_paths", project) + + @classmethod + def identity_items( + cls, metadata: SourceMetadataMapping + ) -> SourceMetadataIdentityItems: + def project() -> SourceMetadataIdentityItems: + return tuple( + sorted( + ( + str(key), + ( + tuple(sorted((str(k), v) for k, v in value.items())) + if isinstance(value, Mapping) + else value + ), + ) + for key, value in metadata.items() + ) + ) + + return cls._view(metadata, "identity_items", project) + + @classmethod + def provenance_identity_items( + cls, metadata: SourceMetadataMapping + ) -> tuple[tuple[str, str], ...]: + """Derive stable provenance identity from the owner's canonical field view.""" + return cls._view( + metadata, + "provenance_identity_items", + lambda: tuple((key, repr(value)) for key, value in cls.identity_items(metadata)), + ) + + @classmethod + def literal_value( + cls, metadata: SourceMetadataMapping, key: str + ) -> SourceMetadataScalar: + # Preserve the existing lookup's role-validation order even when the + # requested literal could be read without the original metadata role. + scalars = cls.scalar_items(metadata) + original = cls.original_items(metadata) + for fields in (original, scalars): + for candidate_key, value in fields: + if str(candidate_key) == key and value is not None: + return value + return None + + @classmethod + def component_value( + cls, metadata: SourceMetadataMapping, component: AllComponents + ) -> str | None: + return cls._view( + metadata, + component, + lambda: SourceComponentProjectionStrategy.for_enum_member( + component + ).metadata_value(metadata), + ) + + @classmethod + def component_values( + cls, metadata: SourceMetadataMapping, component: AllComponents + ) -> tuple[str, ...]: + scalars = cls.scalar_items(metadata) + cls.original_items(metadata) + values = [ + str(value) + for field, value in scalars + if str(field) == component.value and value is not None + ] + values.extend( + str(value) + for field, value in scalars + if str(field) != component.value + and source_metadata_component(str(field)) is component + and value is not None + ) + return tuple(dict.fromkeys(values)) + + @staticmethod + def readonly_snapshot(metadata: SourceMetadataMapping) -> SourceMetadataMapping: + """Preserve the old mapping snapshot while retaining an owned record's lifetime.""" + if isinstance(metadata, SourceMetadataFields): + return metadata._readonly_snapshot() + return MappingProxyType(dict(metadata)) + + def _readonly_snapshot(self) -> SourceMetadataMapping: + return MappingProxyType(dict(self)) + + @staticmethod + def composition_snapshot(metadata: SourceMetadataMapping) -> SourceMetadataMapping: + """Capture one composition's raw fields; owned records already hold that snapshot.""" + if isinstance(metadata, SourceMetadataFields): + return metadata._composition_snapshot() + return dict(metadata) + + def _composition_snapshot(self) -> SourceMetadataMapping: + return dict(self) + + @staticmethod + def derived_mapping( + metadata: SourceMetadataMapping, + fields: dict[str, SourceMetadataValue] | None, + ) -> SourceMetadataMapping: + """Keep owned lifetime on derived fields; raw callers receive a fresh dict.""" + if isinstance(metadata, SourceMetadataFields): + return metadata._derive_fields(fields) + return dict(metadata) if fields is None else fields + + def _derive_fields( + self, fields: dict[str, SourceMetadataValue] | None + ) -> SourceMetadataMapping: + return dict(self) if fields is None else fields + + @classmethod + def with_fields( + cls, + metadata: SourceMetadataMapping, + updates: SourceMetadataMapping, + *, + without: Iterable[str] = (), + components: Iterable[tuple[AllComponents, SourceMetadataScalar]] = (), + after_components: SourceMetadataMapping | None = None, + ) -> SourceMetadataMapping: + excluded = frozenset(without) + fields = {key: value for key, value in metadata.items() if key not in excluded} + fields.update(updates) + for component, value in components: + fields = { + key: field_value + for key, field_value in fields.items() + if key == ORIGINAL_SOURCE_METADATA_FIELD + or source_metadata_component(str(key)) is not component + } + fields[component.value] = str(value) + if after_components is not None: + fields.update(after_components) + return cls.derived_mapping(metadata, fields) + + @classmethod + def with_component( + cls, + metadata: SourceMetadataMapping, + component: AllComponents, + value: SourceMetadataScalar, + ) -> SourceMetadataMapping: + return cls.with_fields(metadata, {}, components=((component, value),)) + + @classmethod + def with_missing_from( + cls, metadata: SourceMetadataMapping, fallback: SourceMetadataMapping + ) -> SourceMetadataMapping: + merged: dict[str, SourceMetadataValue] | None = None + current = metadata + for component in AllComponents: + if cls.component_value(current, component) is not None: + continue + value = cls.component_value(fallback, component) + if value is not None: + if merged is None: + merged = dict(metadata) + merged[component.value] = value + current = merged + if cls.literal_value(metadata, "extension") is None: + extension = cls.literal_value(fallback, "extension") + if extension is not None: + if merged is None: + merged = dict(metadata) + merged["extension"] = str(extension) + if merged is None: + return cls.derived_mapping(metadata, None) + return cls.derived_mapping(metadata, merged) + + +@dataclass(frozen=True, slots=True, eq=False) +class SourceMetadataRecord(SourceMetadataFields): + """Ordered source metadata carried through declared selector resolution.""" + + @abstractmethod + def resolve( + self, + path: str, + parser: "FilenameParser", + metadata_rules: tuple["MetadataExtractionRule", ...], + ) -> "SourceMetadataRecord | None": + """Resolve fields through their declared metadata lifetime.""" + + def __eq__(self, other: object) -> bool: + if not isinstance(other, SourceMetadataRecord): + return NotImplemented + return self.fields == other.fields + + def __hash__(self) -> int: + return hash((self.fields,)) + + +@dataclass(frozen=True, slots=True, eq=False) +class OwnedSourceMetadataFields(SourceMetadataFields): + """Deep field ownership, indexed lookup, bounded views and local transport lifetime.""" + + _field_index: Mapping[str, SourceMetadataValue] = field( + init=False, repr=False, compare=False + ) + _views: dict[str | AllComponents, object] = field( + default_factory=dict, init=False, repr=False, compare=False + ) + _cacheable: bool = field(init=False, repr=False, compare=False) + + def __post_init__(self) -> None: + fields = tuple( + (str(key), self.normalized_value(value)) for key, value in self.fields + ) + object.__setattr__(self, "fields", self._normalized_fields(fields)) + self._initialize_derived_views() + + @staticmethod + def _normalized_fields( + fields: tuple[tuple[str, SourceMetadataValue], ...], + ) -> tuple[tuple[str, SourceMetadataValue], ...]: + return fields + + def _initialize_derived_views(self) -> None: + object.__setattr__(self, "_views", {}) + index: dict[str, SourceMetadataValue] = {} + for key, value in self.fields: + index.setdefault(key, value) + object.__setattr__(self, "_field_index", MappingProxyType(index)) + object.__setattr__( + self, + "_cacheable", + all( + ( + all( + type(v) in (str, int, float, bool, type(None)) + for v in value.values() + ) + if isinstance(value, Mapping) + else type(value) in (str, int, float, bool, type(None)) + ) + for _key, value in self.fields + ), + ) + + def __reduce__(self): + fields = tuple( + (key, dict(value) if isinstance(value, Mapping) else value) + for key, value in self.fields + ) + return (type(self)._from_serialized_fields, (fields,)) + + @classmethod + def _from_serialized_fields( + cls, fields: tuple[tuple[str, SourceMetadataValue], ...] + ) -> Self: + """Restore stored spelling and ownership without serializing derived views.""" + record = cls.__new__(cls) + object.__setattr__( + record, + "fields", + tuple( + ( + key, + ( + MappingProxyType(dict(value)) + if isinstance(value, Mapping) + else value + ), + ) + for key, value in fields + ), + ) + record._initialize_derived_views() + return record + + def __getitem__(self, key: str) -> SourceMetadataValue: + return self._field_index[key] + + @property + def metadata_contents(self) -> SourceMetadataMapping: + """Read-only mapping contents, separate from ordered record equality.""" + return self._field_index + + def _derived_view( + self, key: str | AllComponents, derive: Callable[[], _MetadataViewT] + ) -> _MetadataViewT: + if not self._cacheable: + return derive() + if key not in self._views: + self._views[key] = derive() + return self._views[key] + + def _readonly_snapshot(self) -> SourceMetadataMapping: + return self + + def _composition_snapshot(self) -> SourceMetadataMapping: + return self + + def _derive_fields( + self, fields: dict[str, SourceMetadataValue] | None + ) -> SourceMetadataMapping: + return self if fields is None else DurableSourceMetadata.from_mapping(fields) + + +@dataclass(frozen=True, slots=True, eq=False) +class ResolvedSourceMetadataRecord(OwnedSourceMetadataFields, SourceMetadataRecord): + """Owned runtime fields with the existing ordered selector record contract.""" + + def _readonly_snapshot(self) -> SourceMetadataMapping: + return self._derived_view( + "readonly_snapshot", + lambda: DurableSourceMetadata.from_mapping(self._field_index), + ) + + def resolve( + self, + path: str, + parser: "FilenameParser", + metadata_rules: tuple["MetadataExtractionRule", ...], + ) -> SourceMetadataRecord | None: + return self if self.fields else None + + +@dataclass(frozen=True, slots=True, eq=False) +class DurableSourceMetadata(OwnedSourceMetadataFields): + """Owned literal metadata from durable storage and image field derivation.""" + + @staticmethod + def _normalized_fields( + fields: tuple[tuple[str, SourceMetadataValue], ...], + ) -> tuple[tuple[str, SourceMetadataValue], ...]: + return tuple(dict(fields).items()) + + def __eq__(self, other: object) -> bool: + if isinstance(other, SourceMetadataRecord): + return NotImplemented + return Mapping.__eq__(self, other) + + __hash__ = None + + @staticmethod + def _normalize_admitted_scalar( + value: SourceMetadataNonNullScalar, + ) -> SourceMetadataNonNullScalar: + return value + + @staticmethod + def _reject_scalar(value: object) -> NoReturn: + if isinstance(value, Mapping) or ( + isinstance(value, Sequence) and not isinstance(value, str) + ): + raise RuntimeError( + "virtual_workspace source metadata supports scalar values and " + "one-level scalar mappings only." + ) + raise RuntimeError( + "virtual_workspace source metadata scalar values must be strings, " + "numbers, booleans, or null." + ) + + def source_metadata_dict( metadata: SourceMetadataMapping, ) -> dict[str, SourceMetadataValue]: @@ -69,16 +581,7 @@ def source_metadata_dict( def source_metadata_scalar(value: SourceMetadataScalar) -> SourceMetadataScalar: """Return the canonical scalar representation stored in source metadata.""" - if value is None: - return None - if not isinstance(value, (str, int, float, bool)): - raise TypeError( - "Source metadata scalar values must be str, int, float, bool, or None, " - f"got {type(value).__name__}." - ) - if isinstance(value, str): - return canonical_path_metadata_value(value) - return value + return SourceMetadataFields.normalized_scalar(value) def canonical_path_metadata_value(value: str) -> str: @@ -321,6 +824,13 @@ def __post_init__(self) -> None: if not isinstance(self.unit, SourceVoxelSpacingUnit): raise TypeError("SourceVoxelSpacing.unit must be SourceVoxelSpacingUnit.") + @classmethod + def coerce( + cls, value: "SourceVoxelSpacing | Sequence[float]" + ) -> "SourceVoxelSpacing": + """Retain nominal spacing or validate authored coordinate values.""" + return value if isinstance(value, cls) else cls(tuple(value)) + @property def has_values(self) -> bool: return bool(self.values_zyx) @@ -507,72 +1017,7 @@ class SourceVoxelSpacingFields: ) def normalize_source_voxel_spacing_fields(self) -> None: - if not isinstance(self.source_voxel_spacing, SourceVoxelSpacing): - self.source_voxel_spacing = SourceVoxelSpacing( - tuple(self.source_voxel_spacing) - ) - - -@dataclass(frozen=True, slots=True) -class SourceMetadataRoleView: - """Role-aware metadata view for literal selectors versus component axes.""" - - metadata: SourceMetadataMapping - - def scalar_items(self) -> tuple[tuple[str, SourceMetadataScalar], ...]: - items: list[tuple[str, SourceMetadataScalar]] = [] - for key, value in self.metadata.items(): - if key == ORIGINAL_SOURCE_METADATA_FIELD or isinstance(value, Mapping): - continue - items.append((str(key), value)) - return tuple(items) - - def scalar_values(self) -> tuple[SourceMetadataScalar, ...]: - return tuple(value for _key, value in self.scalar_items()) - - def original_items(self) -> tuple[tuple[str, SourceMetadataScalar], ...]: - original_metadata = self.metadata.get(ORIGINAL_SOURCE_METADATA_FIELD) - if original_metadata is None: - return () - return OriginalSourceMetadata.from_reserved_value( - original_metadata, - path=ORIGINAL_SOURCE_METADATA_FIELD, - ).fields - - def source_filter_paths(self) -> tuple[str, ...]: - source_filter_paths = self.metadata.get(SOURCE_FILTER_PATHS_METADATA_FIELD) - if source_filter_paths is None: - return () - return SourceFilterPathMetadata.from_reserved_value( - source_filter_paths, - path=SOURCE_FILTER_PATHS_METADATA_FIELD, - ).paths - - -@dataclass(frozen=True, slots=True) -class SourceMetadataIdentityProjection: - """Stable hash projection for source metadata records.""" - - metadata: SourceMetadataMapping - - def items(self) -> SourceMetadataIdentityItems: - projected: list[tuple[str, SourceMetadataIdentityValue]] = [] - for key, value in self.metadata.items(): - if isinstance(value, Mapping): - projected.append( - ( - str(key), - tuple( - sorted( - (str(nested_key), nested_value) - for nested_key, nested_value in value.items() - ) - ), - ) - ) - continue - projected.append((str(key), value)) - return tuple(sorted(projected)) + self.source_voxel_spacing = SourceVoxelSpacing.coerce(self.source_voxel_spacing) @lru_cache(maxsize=4096) @@ -589,6 +1034,12 @@ def source_metadata_field_identity(field: str) -> str: ) +@lru_cache(maxsize=256) +def source_metadata_component(field: str) -> AllComponents | None: + """Return the nominal component owner of a metadata field.""" + return SourceComponentProjectionStrategy.component_for_metadata_field(field) + + class SourceComponentProjectionStrategy( EnumKeyedStrategyMixin[AllComponents], ABC, @@ -615,7 +1066,7 @@ def metadata_component( component: AllComponents, metadata: SourceMetadataMapping, ) -> str | None: - return cls.for_enum_member(component).metadata_value(metadata) + return SourceMetadataFields.component_value(metadata, component) @classmethod def component_for_metadata_field( @@ -649,7 +1100,7 @@ def _metadata_group_value( metadata: SourceMetadataMapping, group: tuple[str, ...], ) -> str | None: - scalar_items = SourceMetadataRoleView(metadata).scalar_items() + scalar_items = SourceMetadataFields.scalar_items(metadata) for alias in group: alias_identity = source_metadata_field_identity(alias) for field_name, value in scalar_items: diff --git a/openhcs/core/source_plane_alignment.py b/openhcs/core/source_plane_alignment.py index d3c197b581..49c9dd673e 100644 --- a/openhcs/core/source_plane_alignment.py +++ b/openhcs/core/source_plane_alignment.py @@ -2,126 +2,16 @@ from __future__ import annotations -from collections import OrderedDict -from collections.abc import Sequence from dataclasses import dataclass -from typing import Any, ClassVar +from typing import ClassVar -from openhcs.core.runtime_image_values import ( - ImagePayloadMetadata, - image_payload_metadata, -) -from openhcs.core.source_image_provenance import SourceImageProvenanceIdentity from openhcs.core.source_matching import ( SourceImageSetIdentity, SourceImageSetIdentityCompatibility, SourceImageSetIdentityPairPredicate, - SourceImageSetIdentityPolicy, ) SourcePlaneIdentitySequence = tuple[frozenset[SourceImageSetIdentity], ...] -SourcePayloadPlaneIdentitySequenceCacheValue = SourcePlaneIdentitySequence -_source_payload_plane_identity_sequence_cache_size = 65536 - - -@dataclass(frozen=True, slots=True) -class SourcePayloadPlaneIdentitySequenceCacheKey: - """Stable identity key for cached per-plane source identity projection.""" - - source_provenance_identity: SourceImageProvenanceIdentity - policy: SourceImageSetIdentityPolicy - - -_source_payload_plane_identity_sequence_cache: OrderedDict[ - SourcePayloadPlaneIdentitySequenceCacheKey, - SourcePayloadPlaneIdentitySequenceCacheValue, -] = OrderedDict() - - -def _cached_source_payload_plane_identity_sequence( - key: SourcePayloadPlaneIdentitySequenceCacheKey, -) -> SourcePayloadPlaneIdentitySequenceCacheValue | None: - try: - value = _source_payload_plane_identity_sequence_cache[key] - except KeyError: - return None - _source_payload_plane_identity_sequence_cache.move_to_end(key) - return value - - -def _store_source_payload_plane_identity_sequence( - key: SourcePayloadPlaneIdentitySequenceCacheKey, - value: SourcePayloadPlaneIdentitySequenceCacheValue, -) -> SourcePayloadPlaneIdentitySequenceCacheValue: - _source_payload_plane_identity_sequence_cache[key] = value - _source_payload_plane_identity_sequence_cache.move_to_end(key) - if ( - len(_source_payload_plane_identity_sequence_cache) - > _source_payload_plane_identity_sequence_cache_size - ): - _source_payload_plane_identity_sequence_cache.popitem(last=False) - return value - - -@dataclass(frozen=True, slots=True) -class SourcePayloadPlaneIdentity: - """Source image-set identities represented by one runtime payload plane.""" - - metadata: ImagePayloadMetadata - policy: SourceImageSetIdentityPolicy - - @classmethod - def from_payload( - cls, - payload: Any, - policy: SourceImageSetIdentityPolicy, - ) -> "SourcePayloadPlaneIdentity": - return cls(image_payload_metadata(payload), policy) - - def identities(self) -> frozenset[SourceImageSetIdentity]: - return self.metadata.source_provenance.image_set_identities(self.policy) - - -@dataclass(frozen=True, slots=True) -class SourcePayloadPlaneIdentitySequence: - """Per-plane source identities for stack-like or already-sliced payloads.""" - - payload: Any - policy: SourceImageSetIdentityPolicy - - def identities(self) -> SourcePlaneIdentitySequence: - metadata = image_payload_metadata(self.payload) - cache_key = SourcePayloadPlaneIdentitySequenceCacheKey( - metadata.source_provenance.equality_identity, - self.policy, - ) - cached = _cached_source_payload_plane_identity_sequence(cache_key) - if cached is not None: - return cached - return _store_source_payload_plane_identity_sequence( - cache_key, - metadata.source_provenance.image_set_plane_identities(self.policy), - ) - - def runtime_axis_identities(self) -> SourcePlaneIdentitySequence: - """Return the image-set identity axis carried by this payload.""" - metadata = image_payload_metadata(self.payload) - return metadata.source_provenance.image_set_axis(self.policy) - - @property - def has_identity(self) -> bool: - return any(self.identities()) - - @classmethod - def from_payloads( - cls, - payloads: Sequence[Any], - policy: SourceImageSetIdentityPolicy, - ) -> SourcePlaneIdentitySequence: - return tuple( - SourcePayloadPlaneIdentity.from_payload(payload, policy).identities() - for payload in payloads - ) @dataclass(frozen=True, slots=True) diff --git a/openhcs/core/source_projection.py b/openhcs/core/source_projection.py index c90097091e..1349e94927 100644 --- a/openhcs/core/source_projection.py +++ b/openhcs/core/source_projection.py @@ -35,9 +35,9 @@ ) from openhcs.core.source_metadata import ( SourceComponentProjectionStrategy, - SourceMetadataIdentityProjection, + SourceMetadataFields, + ResolvedSourceMetadataRecord, SourceMetadataMapping, - SourceMetadataRoleView, SourceMetadataValue, source_metadata_dict, source_metadata_scalar, @@ -449,7 +449,7 @@ def identity_key(self) -> tuple[object, ...]: self.declared_address, self.dataset_identity, self.store_identity, - SourceMetadataIdentityProjection(self.metadata).items(), + SourceMetadataFields.identity_items(self.metadata), ) @@ -632,6 +632,12 @@ class SourceProjection: image_metadata: ClassVar[ImagePayloadMetadata | None] = None execution_scope: ClassVar[RuntimeExecutionAxisScope | None] = None + def artifact_result_directory( + self, virtual_path: str, backend: str + ) -> Path | None: + """Return a declared artifact destination, if this role owns one.""" + return None + @property def identity_key(self) -> tuple[object, ...]: """Return the projection identity enforced within one source set.""" @@ -802,6 +808,14 @@ class SourceArtifactProjection(SourceProjection): image_metadata: ImagePayloadMetadata | None = None execution_scope: RuntimeExecutionAxisScope | None = None + def artifact_result_directory( + self, virtual_path: str, backend: str + ) -> Path | None: + """Use the persisted virtual path, not the source pixel reference address.""" + if self.ref.backend != backend: + return None + return Path(virtual_path).parent + def __post_init__(self) -> None: normalized_alias = str(self.source_alias).strip() if not normalized_alias: @@ -821,6 +835,8 @@ def scalar_address_for_image_metadata( ) -> OpenHCSPlaneAddress | None: """Return a plane address only when the whole artifact is scalar.""" + if metadata.persists_whole_image(): + return None return OpenHCSPlaneAddress.from_complete_source_metadata( metadata.source_component_metadata ) @@ -1165,25 +1181,44 @@ def component_metadata( } return metadata + @classmethod def projection_fields( - self, + cls, projection_paths: tuple[tuple[SourceProjection, str], ...], ) -> dict[str, Any]: """Serialize the coherent path-keyed projection fields as one unit.""" return { - self.WORKSPACE_MAPPING_FIELD: { + **cls.workspace_fields(projection_paths), + cls.SOURCE_PROJECTION_FIELD: cls.projection_records(projection_paths), + } + + @classmethod + def projection_records( + cls, + projection_paths: tuple[tuple[SourceProjection, str], ...], + ) -> list[dict[str, Any]]: + """Encode producer records independently of normalized workspace views.""" + return [ + cls._source_projection_payload(projection, path) + for projection, path in projection_paths + ] + + @classmethod + def workspace_fields( + cls, + projection_paths: tuple[tuple[SourceProjection, str], ...], + ) -> dict[str, Any]: + """Derive normalized workspace views without encoding image records.""" + return { + cls.WORKSPACE_MAPPING_FIELD: { path: projection.ref.to_workspace_mapping() for projection, path in projection_paths }, - self.SOURCE_METADATA_FIELD: { - path: self._source_metadata(projection) + cls.SOURCE_METADATA_FIELD: { + path: cls._source_metadata(projection) for projection, path in projection_paths }, - self.SOURCE_PROJECTION_FIELD: [ - self._source_projection_payload(projection, path) - for projection, path in projection_paths - ], } def projection_paths( @@ -1284,14 +1319,15 @@ def _available_backends( projection.ref.backend: True for projection in projection_set.projections } + @classmethod def _source_metadata( - self, + cls, projection: SourceProjection, ) -> dict[str, SourceMetadataValue]: metadata = source_metadata_dict(projection.source_metadata) source_component_fields = { field: value - for field, value in SourceMetadataRoleView(metadata).scalar_items() + for field, value in SourceMetadataFields.scalar_items(metadata) if ( (component := source_metadata_component(field)) is not None and field != component.value @@ -1303,7 +1339,7 @@ def _source_metadata( source_component_fields, path=projection.ref.backend_address, ) - original_metadata = dict(SourceMetadataRoleView(metadata).original_items()) + original_metadata = dict(SourceMetadataFields.original_items(metadata)) for component, value in projection.source_component_values(): canonical_value = metadata.get(component.value) conflicts_with_address = ( @@ -1335,8 +1371,9 @@ def _source_metadata( projection.extend_source_metadata(metadata) return metadata + @classmethod def _source_projection_payload( - self, + cls, projection: SourceProjection, path: str, ) -> dict[str, Any]: @@ -1375,21 +1412,6 @@ def _padded(value: str, width: int) -> str: return f"{int(value):0{width}d}" if value.isdecimal() else value -def _normalized_source_metadata_value( - value: SourceMetadataValue, -) -> SourceMetadataValue: - """Freeze one source-metadata value without erasing its nominal shape.""" - - if isinstance(value, Mapping): - return MappingProxyType( - { - str(key): source_metadata_scalar(nested_value) - for key, nested_value in value.items() - } - ) - return source_metadata_scalar(value) - - def _normalize_projection(projection: SourceProjection) -> None: """Normalize fields shared by every nominal source projection.""" @@ -1410,12 +1432,7 @@ def _normalize_projection(projection: SourceProjection) -> None: object.__setattr__( projection, "source_metadata", - MappingProxyType( - { - str(key): _normalized_source_metadata_value(value) - for key, value in projection.source_metadata.items() - } - ), + ResolvedSourceMetadataRecord.normalized_mapping(projection.source_metadata), ) object.__setattr__( projection, diff --git a/openhcs/core/source_spatial_domain.py b/openhcs/core/source_spatial_domain.py index c61d8b41aa..8723c6a4ee 100644 --- a/openhcs/core/source_spatial_domain.py +++ b/openhcs/core/source_spatial_domain.py @@ -4,7 +4,7 @@ from abc import ABC, abstractmethod from collections.abc import Callable, Iterable, Mapping, Sequence -from dataclasses import dataclass, field +from dataclasses import dataclass, field, fields, replace from typing import Any, ClassVar, Generic, Self, TypeVar from metaclass_registry import AutoRegisterMeta, RegistryFamily, RegistryKeyAttribute @@ -18,6 +18,7 @@ ) from openhcs.core.registry_strategies import NominalTypeKeyedStrategyMixin +from openhcs.serialization.json import to_jsonable SourceSpatialAliasValueT = TypeVar("SourceSpatialAliasValueT") @@ -61,7 +62,7 @@ def as_tuple(self) -> tuple[int, int]: @dataclass(frozen=True, slots=True) -class SourceSpatialDomain: +class SourceSpatialDomain(metaclass=AutoRegisterMeta): """Dense XY placement contract for a source-image coordinate domain.""" origin_yx: tuple[int, int] | None = None @@ -69,6 +70,54 @@ class SourceSpatialDomain: fill_value: Any = 0 value_name: str = "Dense array" + __registry_family__ = RegistryFamily("spatial_rank") + spatial_rank: ClassVar[int] = 2 + + @classmethod + def from_mapping(cls, values: Mapping[str, Any]) -> "SourceSpatialDomain": + """Decode the declared spatial owner, retaining its intrinsic dimensions.""" + payload = dict(values) + dimensions = payload.pop("spatial_dimensions", 2) + owner = cls.__registry__.get(dimensions) + if owner is None: + raise ValueError(f"Unsupported source spatial dimensions {dimensions!r}.") + return owner(**payload).normalized() + + def to_mapping(self) -> dict[str, Any]: + """Serialize placement fields with the nominal spatial declaration.""" + return { + **{ + item.name: to_jsonable(getattr(self, item.name)) + for item in fields(self) + }, + "spatial_dimensions": self.spatial_rank, + } + + def for_intrinsic_plane(self) -> "SourceSpatialDomain": + """An ordinary source plane retains its XY placement owner.""" + return self + + def admit_source_cohort( + self, + domain: "SourceSpatialDomain", + *, + depth: int, + ) -> "SourceSpatialDomain": + """Ordinary source stacks retain their existing spatial domain.""" + return domain + + def intrinsic_plane_count( + self, + shape: Sequence[int], + fallback: int, + ) -> int: + """Return the execution plane count independently of storage layout.""" + return fallback + + def persists_whole_image(self) -> bool: + """An ordinary XY domain does not consume a runtime-slice axis.""" + return False + @property def has_values(self) -> bool: """Return whether this domain carries source-image placement metadata.""" @@ -104,7 +153,9 @@ def to_viewer_wire_mapping(self) -> dict[str, ViewerWireValue]: def with_missing_from(self, fallback: "SourceSpatialDomain") -> Self: """Fill missing spatial placement values from another source domain.""" - return type(self)( + owner = fallback if fallback.spatial_rank > self.spatial_rank else self + return replace( + owner, origin_yx=( self.origin_yx if self.origin_yx is not None else fallback.origin_yx ), @@ -147,7 +198,7 @@ def with_native_image_context( try: candidate.require_image_window(image_shape_yx) except ValueError: - return native_domain + return native_domain.with_missing_from(self) return candidate @classmethod @@ -163,6 +214,18 @@ def common_from_domains( domains_tuple = tuple(domains) if not domains_tuple: return cls(fill_value=fill_value, value_name=value_name) + owner = type(domains_tuple[0]) + if ( + cls is SourceSpatialDomain + and owner is not cls + and all(type(domain) is owner for domain in domains_tuple) + ): + return owner.common_from_domains( + domains_tuple, + expand_varying_domains=expand_varying_domains, + fill_value=fill_value, + value_name=value_name, + ) source_shape = CommonRuntimeValue.from_values( domain.source_shape_yx for domain in domains_tuple @@ -201,42 +264,22 @@ def domains_have_varying_complete_placement( def with_origin_yx(self, origin_yx: tuple[int, int] | None) -> Self: """Return this domain with a replacement source-image origin.""" - return type(self)( - origin_yx=origin_yx, - source_shape_yx=self.source_shape_yx, - fill_value=self.fill_value, - value_name=self.value_name, - ) + return replace(self, origin_yx=origin_yx) def with_source_shape_yx( self, source_shape_yx: tuple[int, int] | None, ) -> Self: """Return this domain with a replacement full source-image shape.""" - return type(self)( - origin_yx=self.origin_yx, - source_shape_yx=source_shape_yx, - fill_value=self.fill_value, - value_name=self.value_name, - ) + return replace(self, source_shape_yx=source_shape_yx) def with_value_name(self, value_name: str) -> Self: """Return this domain with a consumer-specific value label.""" - return type(self)( - origin_yx=self.origin_yx, - source_shape_yx=self.source_shape_yx, - fill_value=self.fill_value, - value_name=value_name, - ) + return replace(self, value_name=value_name) def with_fill_value(self, fill_value: Any) -> Self: """Return this domain with a replacement dense materialization fill.""" - return type(self)( - origin_yx=self.origin_yx, - source_shape_yx=self.source_shape_yx, - fill_value=fill_value, - value_name=self.value_name, - ) + return replace(self, fill_value=fill_value) def normalized(self) -> Self: """Return this domain with canonical tuple metadata values.""" @@ -253,11 +296,10 @@ def normalized(self) -> Self: "source_spatial_shape_yx", ) ) - return type(self)( + return replace( + self, origin_yx=origin_yx, source_shape_yx=source_shape_yx, - fill_value=self.fill_value, - value_name=self.value_name, ) def physical_border_edges_for_shape( @@ -292,14 +334,13 @@ def with_spatial_crop( source_shape = ( self.source_shape_yx if self.source_shape_yx is not None else input_shape ) - return type(self)( + return replace( + self, origin_yx=( int(parent_origin[0]) + int(offset_yx[0]), int(parent_origin[1]) + int(offset_yx[1]), ), source_shape_yx=source_shape, - fill_value=self.fill_value, - value_name=self.value_name, ) def with_spatial_resize( @@ -309,11 +350,10 @@ def with_spatial_resize( """Return the local coordinate domain established by a spatial resize.""" output_shape = self._shape_yx(output_shape_yx, "output_shape_yx") - return type(self)( + return replace( + self, origin_yx=(0, 0), source_shape_yx=output_shape, - fill_value=self.fill_value, - value_name=self.value_name, ) def as_materialized_source_domain( @@ -326,11 +366,10 @@ def as_materialized_source_domain( raise ValueError( f"{self.value_name} source-domain materialization requires shape." ) - return type(self)( + return replace( + self, origin_yx=(0, 0), source_shape_yx=source_shape, - fill_value=self.fill_value, - value_name=self.value_name, ) @staticmethod @@ -354,6 +393,91 @@ def materialize( ) +@dataclass(frozen=True, slots=True) +class VolumeSourceSpatialDomain(SourceSpatialDomain): + """Intrinsic Z/Y/X image placement, independent of runtime slice transport.""" + + spatial_rank: ClassVar[int] = 3 + source_depth: int | None = None + origin_z: int | None = 0 + + @property + def has_values(self) -> bool: + """The intrinsic Z dimension remains semantic without XY placement.""" + return True + + def normalized(self) -> Self: + domain = super(VolumeSourceSpatialDomain, self).normalized() + if domain.source_depth is not None and domain.source_depth <= 0: + raise ValueError("Intrinsic source volume depth must be positive.") + if domain.origin_z is not None and domain.origin_z < 0: + raise ValueError("Intrinsic source volume origin must be nonnegative.") + return domain + + def admit_source_cohort( + self, + domain: SourceSpatialDomain, + *, + depth: int, + ) -> "VolumeSourceSpatialDomain": + if domain.spatial_rank >= self.spatial_rank: + return domain + return replace( + self, + origin_yx=domain.origin_yx, + source_shape_yx=domain.source_shape_yx, + fill_value=domain.fill_value, + value_name=domain.value_name, + source_depth=depth, + ).normalized() + + def intrinsic_plane_count(self, shape: Sequence[int], fallback: int) -> int: + if len(shape) < 3 or shape[0] <= 0: + raise ValueError("An intrinsic volume must retain its Z pixel axis.") + return int(shape[0]) + + def persists_whole_image(self) -> bool: + return True + + def for_intrinsic_plane(self) -> SourceSpatialDomain: + """Explicit Z selection consumes the intrinsic volume dimension.""" + return SourceSpatialDomain( + origin_yx=self.origin_yx, + source_shape_yx=self.source_shape_yx, + fill_value=self.fill_value, + value_name=self.value_name, + ) + + def require_image_window(self, image_shape_yx: Sequence[int]) -> None: + # Source depth describes original placement, independently of current + # resampled pixels. XY placement retains its existing crop validation. + shape = tuple(image_shape_yx) + super(VolumeSourceSpatialDomain, self).require_image_window(shape[-2:]) + + @classmethod + def common_from_domains( + cls, + domains: Iterable[SourceSpatialDomain], + **kwargs: Any, + ) -> "VolumeSourceSpatialDomain": + values = tuple(domains) + domain = super(VolumeSourceSpatialDomain, cls).common_from_domains( + values, **kwargs + ) + return replace( + domain, + source_depth=CommonRuntimeValue.from_values( + value.source_depth for value in values + ).single, + origin_z=CommonRuntimeValue.from_values( + value.origin_z for value in values + ).single, + ) + + +to_jsonable.register(SourceSpatialDomain, SourceSpatialDomain.to_mapping) + + @dataclass(frozen=True, slots=True) class SourceSpatialDomainAlias(Generic[SourceSpatialAliasValueT]): """Descriptor for scalar aliases backed by a source-spatial domain.""" @@ -540,10 +664,14 @@ def common_source_domain( source_shape = cls.common_source_shape_yx(adapters) if source_shape is None: return None - return SourceSpatialDomain( - source_shape_yx=source_shape, - fill_value=fill_value, - value_name=value_name, + return ( + SourceSpatialDomain.common_from_domains( + (adapter.domain for adapter in adapters), + fill_value=fill_value, + value_name=value_name, + ) + .with_origin_yx(None) + .with_source_shape_yx(source_shape) ) @classmethod diff --git a/openhcs/core/source_workspace_projection.py b/openhcs/core/source_workspace_projection.py index 8bb9f20108..677f214007 100644 --- a/openhcs/core/source_workspace_projection.py +++ b/openhcs/core/source_workspace_projection.py @@ -24,7 +24,10 @@ NamedSourceBinding, SourceProjectionRole, ) -from openhcs.core.source_metadata import SourceMetadataMapping +from openhcs.core.source_metadata import ( + SourceMetadataFields, + SourceMetadataMapping, +) from openhcs.core.source_matching import ( source_component_metadata_values, source_metadata_value, @@ -553,12 +556,8 @@ def apply(self, payload: RuntimeArrayData) -> RuntimeArrayData: """Apply declared component metadata and source aliases to one payload.""" source_metadata = self.source_metadata if source_metadata is not None: - source_metadata = MappingProxyType( - { - field: value - for field, value in source_metadata.items() - if field != SOURCE_BINDING_ALIAS_METADATA_FIELD - } + source_metadata = SourceMetadataFields.with_fields( + source_metadata, {}, without=(SOURCE_BINDING_ALIAS_METADATA_FIELD,) ) current_metadata = image_payload_metadata(payload) metadata = self.metadata(current_metadata) @@ -780,11 +779,9 @@ class VirtualWorkspaceSourceProjectionBuilder: def ingest_subdirectory(self, subdirectory: OpenHCSSubdirectoryPayload) -> None: workspace_mapping = VirtualWorkspaceMapping.from_subdirectory(subdirectory) self.ingest_workspace_mapping(workspace_mapping) - self.ingest_source_projections( - VirtualWorkspaceSourceProjectionEntries.from_subdirectory(subdirectory) - ) - self.ingest_source_metadata( - VirtualWorkspaceSourceMetadataEntries.from_subdirectory(subdirectory), + self.ingest_admitted_subdirectory( + subdirectory, + VirtualWorkspaceSourceProjectionEntries.from_subdirectory(subdirectory), ) def ingest_workspace_mapping( @@ -806,10 +803,27 @@ def record_workspace_source_path( self.workspace_source_refs[virtual_path] = source_ref self.workspace_source_refs[loadable_path] = source_ref + def ingest_admitted_subdirectory( + self, + subdirectory: OpenHCSSubdirectoryPayload, + source_projections: VirtualWorkspaceSourceProjectionEntries, + ) -> None: + """Ingest admitted projections, then their correlated source fields. + + Workspace mappings must already be ingested. Raw readers admit each + projection after its mapping; reconciliation admits the whole document's + projection records before any workspace fields. Both share this tail. + """ + self.ingest_source_projections(source_projections) + self.ingest_source_metadata( + VirtualWorkspaceSourceMetadataEntries.from_subdirectory(subdirectory) + ) + def ingest_source_projections( self, source_projections: VirtualWorkspaceSourceProjectionEntries, ) -> None: + """Ingest a projection-only source authority after its workspace mapping.""" for virtual_path, projection in source_projections.entries.items(): mapped_ref = self.workspace_source_refs.get(virtual_path) if mapped_ref is None: @@ -839,7 +853,7 @@ def record_source_metadata( virtual_path: str, metadata_fields: SourceMetadataMapping, ) -> None: - normalized_metadata = MappingProxyType(dict(metadata_fields)) + normalized_metadata = SourceMetadataFields.readonly_snapshot(metadata_fields) self.source_metadata_by_path[virtual_path] = normalized_metadata self.source_metadata_by_path[str(self.plate_path / virtual_path)] = ( normalized_metadata diff --git a/openhcs/core/steps/abstract.py b/openhcs/core/steps/abstract.py index e82003ec93..197a5687b4 100644 --- a/openhcs/core/steps/abstract.py +++ b/openhcs/core/steps/abstract.py @@ -8,10 +8,11 @@ import abc import inspect +from pathlib import Path from collections.abc import Mapping -from dataclasses import dataclass, is_dataclass +from dataclasses import dataclass, field, is_dataclass from types import MappingProxyType -from typing import TYPE_CHECKING, get_type_hints +from typing import TYPE_CHECKING, Iterable, get_type_hints from objectstate import get_base_type_for_lazy, semantic_values_equal @@ -38,21 +39,53 @@ # ProcessingContext is used in type hints if TYPE_CHECKING: from openhcs.core.context.processing_context import ProcessingContext + from openhcs.core.orchestrator.analysis_consolidation import ( + RuntimeAnalysisConsolidationInputs, + ) @dataclass(frozen=True, slots=True) class StepExecutionObservation: - """Execution facts emitted by one step's authoritative side effects.""" + """Saved outputs and explicitly reused historical outputs from one step.""" materialized_locations_by_address: Mapping[ RuntimeArtifactAddress, tuple[RuntimeArtifactLocation, ...], ] + runtime_export_paths: tuple[Path, ...] = field(default_factory=tuple) + analysis_inputs: "RuntimeAnalysisConsolidationInputs | None" = None + @classmethod def empty(cls) -> "StepExecutionObservation": return cls(MappingProxyType({})) + @classmethod + def combine( + cls, observations: Iterable["StepExecutionObservation"] + ) -> "StepExecutionObservation": + from openhcs.core.orchestrator.analysis_consolidation import ( + RuntimeAnalysisConsolidationInputs, + ) + + locations = {} + paths = [] + analysis_inputs = [] + for observation in observations: + for ( + address, + values, + ) in observation.materialized_locations_by_address.items(): + locations[address] = tuple( + dict.fromkeys((*locations.get(address, ()), *values)) + ) + paths.extend(observation.runtime_export_paths) + analysis_inputs.append(observation.analysis_inputs) + return cls( + MappingProxyType(locations), tuple(dict.fromkeys(paths)), + RuntimeAnalysisConsolidationInputs.combine(analysis_inputs), + ) + # def get_step_id(step: 'AbstractStep') -> str: # """ diff --git a/openhcs/core/steps/function_artifact_materialization.py b/openhcs/core/steps/function_artifact_materialization.py index 7d4a0da320..5352cade3c 100644 --- a/openhcs/core/steps/function_artifact_materialization.py +++ b/openhcs/core/steps/function_artifact_materialization.py @@ -6,6 +6,7 @@ from collections.abc import Callable, Mapping from dataclasses import dataclass from pathlib import Path +from types import MappingProxyType from typing import TYPE_CHECKING, ClassVar, cast import numpy as np @@ -26,7 +27,6 @@ from openhcs.core.component_group_scope import RuntimeExecutionAxisScope from openhcs.core.component_set import ComponentSet from openhcs.core.registry_strategies import MostDerivedContextStrategyMixin -from openhcs.core.runtime_artifact_queries import MeasurementTableUnion from openhcs.core.runtime_artifact_values import RuntimeValue from openhcs.core.runtime_image_values import ( ImagePayloadMetadata, @@ -47,20 +47,17 @@ SourceImageProvenanceFields, ) from openhcs.core.source_matching import ( + source_component_metadata_items, with_source_component_metadata, ) +from openhcs.core.source_metadata import SourceMetadataFields from openhcs.core.source_projection import OpenHCSPlaneAddress +from openhcs.core.steps.abstract import StepExecutionObservation from openhcs.core.steps.function_output_identity import ( FunctionOutputIdentity, - FunctionOutputIdentityAuthority, FunctionOutputParserContext, - FunctionOutputPathAuthority, IncompleteFunctionOutputFilenameIdentityError, ) -from openhcs.core.steps.function_output_manifest import ( - FunctionStepOutputProducerIdentityAuthority, - FunctionStepOutputProducerIdentityRequest, -) from openhcs.core.steps.stream_component_semantics import ( StreamComponentMessageExtraAuthority, StreamSourceComponentMetadataItems, @@ -71,9 +68,11 @@ MaterializationSpec, MaterializationValue, Output, + SavedMaterializationOutputs, RawBackendKwargs, ViewerStreamBackendCallKwargs, materialization_outputs, + prepare_materialization, ) if TYPE_CHECKING: @@ -142,7 +141,7 @@ def records_for_group( record_locations = tuple( ( record.key.semantic_id, - record.path, + record.location.path, ) for record in records ) @@ -177,7 +176,7 @@ def records_for_output( list[StoredRuntimeValue], ] = {} for record in records: - payload = output_plan.materialization_payload(record.value) + payload = output_plan.materialization_payload(record) metadata = image_payload_metadata(payload) address = OpenHCSPlaneAddress.from_complete_source_metadata( metadata.source_component_metadata @@ -231,9 +230,9 @@ def _record_for_scalar_address( ) owner_record = owner_records[0] - owner_payload = output_plan.materialization_payload(owner_record.value) + owner_payload = output_plan.materialization_payload(owner_record) for record in records: - payload = output_plan.materialization_payload(record.value) + payload = output_plan.materialization_payload(record) if not cls._payloads_are_equivalent(owner_payload, payload): raise ValueError( "Conflicting scalar image materialization payloads for source " @@ -273,8 +272,8 @@ def records_for_group( if len(records) <= 1: return records group_plan = output_plan.for_group(group_key) - tables = tuple(cast(MeasurementTable, record.value.data) for record in records) - table = MeasurementTableUnion(output_plan.name, tables).as_artifact_table() + tables = tuple(cast(MeasurementTable, record.data) for record in records) + table = MeasurementTable.join_artifact(output_plan.name, tables) value = RuntimeValue.normalize_for_execution_scope( group_plan, table, @@ -282,7 +281,9 @@ def records_for_group( ) return ( StoredRuntimeValue( - value=value, + key=value.key, + data=value.data, + materialization_source_metadata=value.materialization_source_metadata, location=RuntimeArtifactLocation( path=group_plan.path, backend=Backend.MEMORY.value, @@ -639,7 +640,7 @@ def build( "Artifact record descriptor requires a materialization spec." ) if record.key.artifact_type.uses_aggregate_materialization_identity( - record.value.data + record.data ): metadata = cls.record_payload_metadata(record) aggregate_provenance = ( @@ -690,6 +691,33 @@ def build( source_filename=record_source.filename, ) + if record is not None: + metadata = ( + output_plan.materialization_metadata(record) + if output_plan is not None + else cls.record_payload_metadata(record) + ) + source_identity = ( + None + if metadata is None + else metadata.source_provenance.scalar_source_identity + ) + if source_identity is not None and not source_identity.addressable: + source_identity = None + if artifact_path is not None and ( + dict_key is not None + or cls.source_identity_for_path(context, artifact_path) is not None + ): + return ArtifactAnalysisOutputDescriptor( + filename=f"{Path(artifact_path).stem}.roi.zip", + source_identity=source_identity, + ) + return cls.aggregate_descriptor( + output_key, + plan, + scope=record.key.scope, + source_identity=source_identity, + ) if artifact_path is not None: source_identity = cls.source_identity_for_path( context, @@ -733,20 +761,46 @@ def record_payload_metadata( ) -> ImagePayloadMetadata | None: if record is None: return None - if isinstance(record.value.data, SourceImageProvenanceFields): + if isinstance(record.data, SourceImageProvenanceFields): return ImagePayloadMetadata( - source_provenance=record.value.data.source_provenance, + source_provenance=record.data.source_provenance, ) - return image_payload_metadata(record.value.data) + return image_payload_metadata(record.data) @classmethod def record_metadata_with_runtime_scope( cls, record: StoredRuntimeValue, metadata: ImagePayloadMetadata, + parser_context: FunctionOutputParserContext, ) -> ImagePayloadMetadata: - """Attach the artifact key's complete typed execution identity.""" + """Admit scalar source coordinates before attaching execution identity.""" + provenance = metadata.source_provenance + if ( + not provenance.source_image_provenance_planes.has_values + and not metadata.persists_whole_image() + ): + source_identity = provenance.scalar_source_identity.with_parsed_path_components( + parser_context.parser + ) + if source_identity.component_metadata is not None: + component_metadata = SourceMetadataFields.with_fields( + source_identity.component_metadata, + {}, + components=( + ( + component, + SourceMetadataFields.canonical_component_value(component, value), + ) + for component, value in source_component_metadata_items( + source_identity.component_metadata + ) + ), + ) + metadata = metadata.with_source_provenance( + provenance.with_source_component_metadata(component_metadata) + ) scope = record.key.scope if scope.has_fixed_components: component_metadata = scope.fixed_component_metadata( @@ -754,7 +808,7 @@ def record_metadata_with_runtime_scope( ) elif scope.component is not None: component_metadata = with_source_component_metadata( - dict(metadata.source_component_metadata or {}), + metadata.source_component_metadata or {}, scope.component, scope.require_value_text(), ) @@ -789,17 +843,21 @@ def record_source_descriptor( and output_plan.materialization_source() != output_plan.source_context_source() ): - metadata = output_plan.materialization_metadata(record.value) + metadata = output_plan.materialization_metadata(record) + parser_context = FunctionOutputParserContext.from_processing_context(context) metadata = cls.record_metadata_with_runtime_scope( record, metadata, + parser_context, ) - parser_context = FunctionOutputParserContext.from_processing_context(context) + source_identity = metadata.source_provenance.scalar_source_identity + if not source_identity.addressable: + source_identity = None use_filename_identity = materialization_spec.uses_filename_source_identity( - record.value.data + record.data ) if use_filename_identity or exact_fixed_scope: - identity = FunctionOutputIdentityAuthority.filename_identity_from_metadata( + identity = FunctionOutputIdentity.from_filename_metadata( parser_context.parser, metadata, ) @@ -810,19 +868,19 @@ def record_source_descriptor( "its declared source metadata has no addressable identity." ) else: - identity = FunctionOutputIdentityAuthority.identity_from_metadata( + identity = FunctionOutputIdentity.from_metadata( parser_context.parser, metadata, - fallback_identity_path=record.path, + fallback_identity_path=record.location.path, variable_components=plan.variable_components, ) if identity is not None: + identity = materialization_spec.filename_identity_for_output( + identity, output_plan, + ) try: filename = Path( - FunctionOutputPathAuthority.filename_for_identity( - parser_context.parser, - identity, - ) + identity.filename(parser_context.parser) ).name except IncompleteFunctionOutputFilenameIdentityError as exc: if cls.missing_component_is_aggregated( @@ -845,54 +903,16 @@ def record_source_descriptor( else: return ArtifactRecordSourceDescriptor( filename=filename, - source_identity=cls.record_source_identity_from_metadata( - metadata, - identity, - ), + source_identity=source_identity, ) source_path = metadata.source_provenance.scalar_source_identity.path if source_path is None: return None return ArtifactRecordSourceDescriptor( filename=Path(source_path).name, - source_identity=cls.record_source_identity_from_metadata( - metadata, - identity, - ), + source_identity=source_identity, ) - @classmethod - def record_source_identity_from_metadata( - cls, - metadata: ImagePayloadMetadata, - identity: FunctionOutputIdentity | None, - ) -> SourceImageIdentity | None: - """Return scalar source identity with parser-resolved component metadata.""" - source_identity = metadata.source_provenance.scalar_source_identity - if identity is not None: - if metadata.source_component_metadata is None: - component_metadata = {} - else: - component_metadata = dict(metadata.source_component_metadata) - identity_metadata = identity.filename_component_metadata() - for key, value in identity_metadata.items(): - component = AllComponents.from_value(str(key)) - if component is None: - component_metadata[str(key)] = value - continue - component_metadata = with_source_component_metadata( - component_metadata, - component, - value, - ) - source_identity = SourceImageIdentity( - path=source_identity.path, - component_metadata=component_metadata, - ) - if source_identity.addressable: - return source_identity - return None - @classmethod def materialization_base_path( cls, @@ -918,12 +938,26 @@ def source_identity_for_path( path: str | Path, ) -> SourceImageIdentity | None: """Return microscope source identity for a source path when available.""" - component_metadata = FunctionOutputParserContext.from_processing_context( - context - ).parse_path_metadata(path) - if component_metadata is None: + parser = FunctionOutputParserContext.from_processing_context(context).parser + parsed = parser.parse_filename(Path(path).name) + if parsed is None: return None - return SourceImageIdentity(component_metadata=component_metadata) + component_metadata = parsed.wire_mapping() + return SourceImageIdentity( + component_metadata=SourceMetadataFields.with_fields( + component_metadata, + {}, + components=( + ( + component, + SourceMetadataFields.canonical_component_value(component, value), + ) + for component, value in source_component_metadata_items( + component_metadata + ) + ), + ) + ) def actual_materialization_records( @@ -952,7 +986,7 @@ def actual_materialization_records( axis_id=plan.axis_id, ) if record.key.scope.value_text is not None - and record.backend == Backend.MEMORY.value + and record.location.backend == Backend.MEMORY.value and store.get(record.key).location == record.location ) if dynamic_records: @@ -1005,7 +1039,7 @@ def actual_materialization_records( group_key=group_key, match_group=True, ) - if record.backend == Backend.MEMORY.value + if record.location.backend == Backend.MEMORY.value and store.get(record.key).location == record.location ) if not records: @@ -1030,8 +1064,8 @@ def actual_materialization_records( candidate_locations = tuple( ( candidate.key.scope.value_text, - candidate.backend, - candidate.path, + candidate.location.backend, + candidate.location.path, ) for candidate in candidates ) @@ -1039,7 +1073,7 @@ def actual_materialization_records( candidate for candidate in candidates if candidate.key.scope.value_text is None - and candidate.backend == Backend.MEMORY.value + and candidate.location.backend == Backend.MEMORY.value and store.get(candidate.key).location == candidate.location ) if identity_records: @@ -1090,7 +1124,7 @@ def from_record( f"Artifact output {output_plan.name!r} declares unsupported " f"materialization {type(spec).__name__}." ) - data = output_plan.materialization_payload(record.value) + data = output_plan.materialization_payload(record) emits_projected_planes = spec.emits_variable_component_planes(data) if ( output_plan.materialization_uses_source_identity_filename() @@ -1107,7 +1141,10 @@ def from_record( output_plan=output_plan, ) filename_source_identity = ( - None if record_source is None else record_source.source_identity + None if record_source is None + else AnalysisOutputDescriptorAuthority.source_identity_for_path( + context, record_source.filename, + ) ) aggregate_descriptor = ( AnalysisOutputDescriptorAuthority.aggregate_descriptor( @@ -1129,7 +1166,7 @@ def from_record( plan, context, record.key.scope.value_text, - artifact_path=record.path, + artifact_path=record.location.path, record=record, materialization_spec=spec, output_plan=output_plan, @@ -1140,7 +1177,13 @@ def from_record( output_plan=output_plan, ) source_identity = output_descriptor.source_identity - filename_source_identity = output_descriptor.source_identity + filename_source_identity = ( + output_descriptor.source_identity + if output_descriptor.source_filename is None + else AnalysisOutputDescriptorAuthority.source_identity_for_path( + context, output_descriptor.source_filename, + ) + ) return cls( output_plan=output_plan, spec=spec, @@ -1173,6 +1216,37 @@ def outputs( output_path_filter=output_path_filter, ) + def reused_observation( + self, plan: CompiledStepPlan, context: "ProcessingContext", + ) -> StepExecutionObservation: + """Report historical debug destinations and read their retained CSV text.""" + from openhcs.core.orchestrator.analysis_consolidation import ( + RuntimeAnalysisConsolidationInputs, + ) + + target = plan.runtime_artifact_materialization + if not target.has_persistent_target: + return StepExecutionObservation.empty() + backend = target.require_persistent_backend() + outputs = self.outputs(plan, context) + locations = ( + {RuntimeArtifactAddress.from_record(self.record): tuple( + RuntimeArtifactLocation(path=output.path, backend=backend) + for output in outputs + )} + if self.spec.participates_in_persistent_materialization() + else {} + ) + paths = ( + tuple(Path(output.path) for output in outputs) + if self.spec.participates_in_runtime_export_observation() + else () + ) + return StepExecutionObservation( + MappingProxyType(locations), paths, + RuntimeAnalysisConsolidationInputs.from_reused_outputs(context, plan, self, outputs), + ) + def viewer_outputs( self, plan: CompiledStepPlan, @@ -1221,18 +1295,6 @@ def runtime_artifact_materializations( return tuple(materializations) -def observed_runtime_artifact_materializations( - plan: CompiledStepPlan, - context: "ProcessingContext", -) -> tuple[RuntimeArtifactMaterialization, ...]: - """Derive historical materializations from the runtime observation ledger.""" - return runtime_artifact_materializations_from_records( - plan, - context, - context.runtime_value_store.observed_values, - ) - - def runtime_artifact_materializations_from_records( plan: CompiledStepPlan, context: "ProcessingContext", @@ -1271,106 +1333,21 @@ def runtime_artifact_materializations_from_records( return tuple(materializations) -def materialized_artifact_output_paths( - plan: CompiledStepPlan, - context: "ProcessingContext", -) -> tuple[Path, ...]: - """Re-derive exact persistent output paths from runtime materializations.""" - - if not plan.runtime_artifact_materialization.has_persistent_target: - return () - return tuple( - Path(output.path) - for materialization in runtime_artifact_materializations(plan, context) - if materialization.spec.participates_in_persistent_materialization() - for output in materialization.outputs(plan, context) - ) - - -def runtime_export_artifact_output_paths( - plan: CompiledStepPlan, - context: "ProcessingContext", -) -> tuple[Path, ...]: - """Derive exact pipeline-declared export paths from runtime materializations.""" - - if not plan.runtime_artifact_materialization.has_persistent_target: - return () - return tuple( - Path(output.path) - for materialization in runtime_artifact_materializations(plan, context) - if materialization.spec.participates_in_runtime_export_observation() - for output in materialization.outputs(plan, context) - ) - - -def observed_materialized_artifact_output_paths( +def preview_reused_step_outputs( plan: CompiledStepPlan, context: "ProcessingContext", records: tuple[StoredRuntimeValue, ...], -) -> tuple[Path, ...]: - """Derive exact persistent outputs from one execution-owned observation.""" - - return tuple( - Path(location.path) - for locations in observed_materialized_artifact_locations_by_address( - plan, - context, - records, - ).values() - for location in locations - ) - - -def observed_runtime_export_artifact_output_paths( - plan: CompiledStepPlan, - context: "ProcessingContext", - records: tuple[StoredRuntimeValue, ...], -) -> tuple[Path, ...]: - """Derive exact pipeline-declared exports from worker-observed records.""" +) -> StepExecutionObservation: + """Project explicitly reused historical outputs once, independently of new saves.""" if not plan.runtime_artifact_materialization.has_persistent_target: - return () - return tuple( - Path(output.path) - for materialization in runtime_artifact_materializations_from_records( - plan, - context, - records, - ) - if materialization.spec.participates_in_runtime_export_observation() - for output in materialization.outputs(plan, context) + return StepExecutionObservation.empty() + return StepExecutionObservation.combine( + item.reused_observation(plan, context) + for item in runtime_artifact_materializations_from_records(plan, context, records) ) -def observed_materialized_artifact_locations_by_address( - plan: CompiledStepPlan, - context: "ProcessingContext", - records: tuple[StoredRuntimeValue, ...], -) -> Mapping[RuntimeArtifactAddress, tuple[RuntimeArtifactLocation, ...]]: - """Project exact persistent destinations for observed runtime artifacts.""" - - if not plan.runtime_artifact_materialization.has_persistent_target: - return {} - backend = plan.runtime_artifact_materialization.require_persistent_backend() - locations_by_address: dict[ - RuntimeArtifactAddress, - tuple[RuntimeArtifactLocation, ...], - ] = {} - for materialization in runtime_artifact_materializations_from_records( - plan, - context, - records, - ): - if not materialization.spec.participates_in_persistent_materialization(): - continue - address = RuntimeArtifactAddress.from_record(materialization.record) - locations_by_address[address] = tuple( - RuntimeArtifactLocation(path=output.path, backend=backend) - for output in materialization.outputs(plan, context) - ) - return locations_by_address - - def planned_materialization_preview( *, context: "ProcessingContext", @@ -1432,22 +1409,57 @@ def _planned_materialization_path( ) +@dataclass(frozen=True, slots=True) +class MaterializedRuntimeArtifact(SavedMaterializationOutputs): + """Actual writer outputs saved for one reduced runtime artifact.""" + + materialization: RuntimeArtifactMaterialization + + def observation( + self, plan: CompiledStepPlan, context: "ProcessingContext", + ) -> StepExecutionObservation: + target = plan.runtime_artifact_materialization + if not target.has_persistent_target: + return StepExecutionObservation.empty() + backend = target.require_persistent_backend() + outputs = self.outputs_for_backend(backend) + if not outputs: + return StepExecutionObservation.empty() + address = RuntimeArtifactAddress.from_record(self.materialization.record) + locations = tuple( + RuntimeArtifactLocation(path=output.path, backend=backend) + for output in outputs + ) + paths = ( + tuple(Path(output.path) for output in outputs) + if self.materialization.spec.participates_in_runtime_export_observation() + else () + ) + from openhcs.core.orchestrator.analysis_consolidation import ( + RuntimeAnalysisConsolidationInputs, + ) + + return StepExecutionObservation( + MappingProxyType({address: locations}), paths, + RuntimeAnalysisConsolidationInputs.from_saved_outputs(context, plan, self), + ) + + def materialize_artifact_outputs( filemanager: "FileManager", plan: CompiledStepPlan, target_plan: ArtifactMaterializationTargetPlan, context: "ProcessingContext", -) -> None: - """Materialize planned artifact outputs to persistent and streaming backends.""" - from openhcs.processing.materialization import materialize - +) -> tuple[MaterializedRuntimeArtifact, ...]: + """Save each exact artifact batch once and return its successful outputs.""" + saved_materializations = [] images_dir = plan.artifact_images_dir for materialization in runtime_artifact_materializations(plan, context): backend_plan = target_plan.backend_plan(plan, context, materialization) record = materialization.record data = materialization.data - filemanager.ensure_directory(Path(record.path).parent, record.backend) + filemanager.ensure_directory(Path(record.location.path).parent, record.location.backend) stream_output_paths = materialization.spec.candidate_paths( str(materialization.base_path) ) @@ -1458,7 +1470,7 @@ def materialize_artifact_outputs( ) if not backends: continue - materialize( + batch = prepare_materialization( materialization.spec, data, str(materialization.base_path), @@ -1467,14 +1479,13 @@ def materialize_artifact_outputs( backend_plan.backend_kwargs( materialization_spec=materialization.spec, data=data, - fallback_source_identity=materialization.source_identity, + fallback_source_identity=( + materialization.filename_source_identity + if materialization.spec.uses_filename_source_identity(data) + else materialization.source_identity + ), producer_identity=( - FunctionStepOutputProducerIdentityAuthority.build( - FunctionStepOutputProducerIdentityRequest.from_artifact( - plan, - materialization.output_plan, - ) - ) + plan.producer_identity_for_artifact(materialization.output_plan) ), context=context, filemanager=filemanager, @@ -1488,3 +1499,12 @@ def materialize_artifact_outputs( pipeline_position=plan.pipeline_position, output_plan=materialization.output_plan, ) + saved_materializations.append( + MaterializedRuntimeArtifact( + outputs_by_backend=MappingProxyType( + dict(batch.save().outputs_by_backend) + ), + materialization=materialization, + ) + ) + return tuple(saved_materializations) diff --git a/openhcs/core/steps/function_execution.py b/openhcs/core/steps/function_execution.py index 1b075b9d82..ae9b13d3dd 100644 --- a/openhcs/core/steps/function_execution.py +++ b/openhcs/core/steps/function_execution.py @@ -6,24 +6,30 @@ import os import time import traceback -from collections.abc import Callable, Iterator, Mapping, Sequence +from collections.abc import Callable, Mapping, Sequence from dataclasses import dataclass from itertools import zip_longest from typing import TYPE_CHECKING -import psutil - from openhcs.constants import MULTIPROCESSING_AXIS from openhcs.constants.constants import ( LOADABLE_IMAGE_EXTENSIONS, Backend, ) +from openhcs.core.component_set import ComponentSet +from openhcs.core.component_group_scope import ( + ComponentGroupScope, + RuntimeExecutionAxisScope, +) +from openhcs.core.runtime_stores import RuntimeArtifactInput from openhcs.core.callable_contract import ImagePayloadConsumption from openhcs.core.compiled_step_plan import CompiledStepPlan from openhcs.core.context.processing_context import ProcessingContext from openhcs.core.function_patterns import ( CompiledFunctionGroup, FunctionGroupKey, + GroupedPatternMap, + InvocationArtifactInputEdgePlan, RuntimeInvocationDomain, ) from openhcs.core.progress import ProgressPhase, ProgressStatus, emit @@ -36,11 +42,9 @@ from openhcs.core.source_bindings import CompiledSourceBindingPlan from openhcs.core.source_workspace_projection import ( VirtualWorkspaceSourceProjectionAuthority, - VirtualWorkspaceSourceProjectionCache, ) from openhcs.core.step_dependencies import StepInputDependencyKind from openhcs.core.steps.function_io import ( - bulk_preload_step_images, generate_materialized_paths, get_all_image_paths, save_materialized_data, @@ -48,12 +52,12 @@ ) from openhcs.core.steps.function_output_manifest import ( NoStepOutputManifestMatch, - StepOutputManifestStore, step_output_manifest, ) from openhcs.core.steps.abstract import StepExecutionObservation from openhcs.core.steps.function_outputs import finalize_function_step_outputs from openhcs.core.steps.function_runtime import ( + ArtifactPatternGroupExecutionRequest, PatternGroupExecutionRequest, _process_single_pattern_group, ) @@ -159,50 +163,6 @@ def record_function_step_runtime_profile( ).emit() -@dataclass(frozen=True, slots=True) -class PatternGroups: - """Execution anchors grouped by compiled function-pattern component.""" - - groups: Mapping[FunctionGroupKey, tuple[SourceCandidatePath, ...]] - - @classmethod - def from_prepared( - cls, - grouped_patterns: Mapping[FunctionGroupKey, Sequence[SourceCandidatePath]], - ) -> PatternGroups: - return cls( - { - group_key: tuple(str(pattern) for pattern in pattern_list) - for group_key, pattern_list in grouped_patterns.items() - } - ) - - def items( - self, - ) -> Iterator[tuple[FunctionGroupKey, tuple[SourceCandidatePath, ...]]]: - return iter(self.groups.items()) - - def values(self) -> Iterator[tuple[SourceCandidatePath, ...]]: - return iter(self.groups.values()) - - def __len__(self) -> int: - return len(self.groups) - - def total_count(self) -> int: - return sum(len(pattern_list) for pattern_list in self.groups.values()) - - def map_groups( - self, - selector: AnchorPatternSelector, - ) -> PatternGroups: - return PatternGroups.from_prepared( - { - group_key: selector(group_key, pattern_list) - for group_key, pattern_list in self.groups.items() - } - ) - - def _single_execution_group_patterns( patterns: DiscoveredPatternCollection, ) -> Sequence[SourceCandidatePath]: @@ -214,85 +174,133 @@ def _single_execution_group_patterns( ) -@dataclass(frozen=True, slots=True) -class StepAnchorPatternFilter: - """Apply source, producer, and artifact-domain filtering to anchor groups.""" +def _filter_patterns_by_component( + patterns: DiscoveredPatternCollection, + component: str, + target_value: str, + parser: FilenameParser, +) -> DiscoveredPatternCollection: + """Filter pattern strings by a fixed parsed component value.""" - plan: CompiledStepPlan - parser: FilenameParser - output_manifest: StepOutputManifestStore - source_workspace_authority: VirtualWorkspaceSourceProjectionAuthority - source_workspace_projection_cache: VirtualWorkspaceSourceProjectionCache + def filter_pattern_list( + pattern_list: Sequence[SourceCandidatePath], + ) -> list[SourceCandidatePath]: + filtered: list[SourceCandidatePath] = [] + component_declaration = parser.component_for_name(component) + for pattern in pattern_list: + metadata = parser.parse_filename(str(pattern)) + if metadata and str(metadata.value_for(component_declaration)) == str( + target_value + ): + filtered.append(pattern) + return filtered - @classmethod - def from_context( - cls, - context: ProcessingContext, - plan: CompiledStepPlan, - ) -> StepAnchorPatternFilter: - return cls( - plan=plan, - parser=context.microscope_handler.parser, - output_manifest=step_output_manifest(context), - source_workspace_authority=( - VirtualWorkspaceSourceProjectionAuthority.from_context( - context, - cache=context.runtime_source_workspace_projection_cache, + if isinstance(patterns, dict): + filtered_by_group = {} + for group_key, pattern_list in patterns.items(): + filtered_list = filter_pattern_list(pattern_list) + if filtered_list: + filtered_by_group[group_key] = filtered_list + return filtered_by_group + + return filter_pattern_list(patterns) + + +class FunctionStepExecutor: + """Run one compiled FunctionStep plan for one multiprocessing axis.""" + + def __init__(self, context: ProcessingContext, step_index: int) -> None: + self.context = context + compiled_plan = context.step_plans[step_index] + if not isinstance(compiled_plan, CompiledStepPlan): + raise TypeError( + f"FunctionStep {step_index} requires CompiledStepPlan, got " + f"{type(compiled_plan).__name__}." + ) + self.plan = compiled_plan.require_function_execution_ready() + + def _execution_requests( + self, + grouped_patterns: GroupedPatternMap, + ) -> tuple[PatternGroupExecutionRequest, ...]: + """Admit source anchors to their complete compiled execution coordinates.""" + + plan = self.plan + requests = [] + for component_index, (component_value, patterns) in enumerate( + grouped_patterns.items() + ): + compiled_group = plan.compiled_function_pattern.group_for_component( + component_value + ) + if compiled_group is None: + raise ValueError( + f"No compiled function group for component {component_value!r}." ) - ), - source_workspace_projection_cache=( - context.runtime_source_workspace_projection_cache - ), - ) + requests.extend( + PatternGroupExecutionRequest( + context=self.context, + execution_plan=plan, + pattern_group_info=pattern, + compiled_group=compiled_group, + component_value=component_value, + component_index=component_index, + component_count=len(grouped_patterns), + ) + for pattern in patterns + ) + return tuple(requests) - def filtered(self, grouped_patterns: PatternGroups) -> PatternGroups: + def _filter_anchor_patterns( + self, grouped_patterns: GroupedPatternMap + ) -> GroupedPatternMap: grouped_patterns = self.source_bound_anchor_patterns(grouped_patterns) grouped_patterns = self.producer_anchor_patterns(grouped_patterns) grouped_patterns = self.execution_group_anchor_patterns(grouped_patterns) - grouped_patterns = PatternGroups.from_prepared( - self.plan.compiled_function_pattern.prepare_grouped_patterns( - grouped_patterns.groups, - default_component=self.plan.execution_group_value, - ) + grouped_patterns = self.plan.compiled_function_pattern.prepare_grouped_patterns( + grouped_patterns, + default_component=self.plan.execution_group_value, ) return self.artifact_driven_anchor_patterns(grouped_patterns) def execution_group_anchor_patterns( self, - grouped_patterns: PatternGroups, - ) -> PatternGroups: + grouped_patterns: GroupedPatternMap, + ) -> GroupedPatternMap: """Map validated lifecycle anchors onto compiler-owned execution groups.""" pattern = self.plan.compiled_function_pattern source_owns_groups = ( pattern.runtime_domain is RuntimeInvocationDomain.SOURCE_ANCHORED ) - if not grouped_patterns.groups: + if not grouped_patterns: return grouped_patterns if source_owns_groups: - producer_groups = self.output_manifest.producer_patterns_by_execution_group( + producer_groups = step_output_manifest( + self.context + ).producer_patterns_by_execution_group( self.plan, tuple( pattern for patterns in grouped_patterns.values() for pattern in patterns ), - self.parser, + self.context.microscope_handler.parser, ) if producer_groups is not None: - return PatternGroups.from_prepared(producer_groups) - execution_scope = self.plan.execution_group_scope - return PatternGroups.from_prepared( - { - group_key: pattern_list - for group_key, pattern_list in grouped_patterns.items() - if execution_scope.contains_runtime_key(group_key) + return { + key: tuple(patterns) for key, patterns in producer_groups.items() } - ) + execution_scope = self.plan.execution_group_scope + return { + group_key: pattern_list + for group_key, pattern_list in grouped_patterns.items() + if execution_scope.contains_runtime_key(group_key) + } execution_group_keys = self.plan.execution_group_scope.runtime_keys( - grouped_patterns.groups + grouped_patterns ) canonical_anchors = next( ( @@ -302,17 +310,15 @@ def execution_group_anchor_patterns( ), (), ) - return PatternGroups.from_prepared( - { - group_key: grouped_patterns.groups.get(group_key) or canonical_anchors - for group_key in execution_group_keys - } - ) + return { + group_key: grouped_patterns.get(group_key) or canonical_anchors + for group_key in execution_group_keys + } def source_bound_anchor_patterns( self, - grouped_patterns: PatternGroups, - ) -> PatternGroups: + grouped_patterns: GroupedPatternMap, + ) -> GroupedPatternMap: """Restrict source-bound step anchors to compatible declared sources.""" if not self.plan.main_input_dependency.uses_pipeline_start_anchors(): @@ -379,8 +385,9 @@ def source_bound_anchor_patterns( selected_pattern = next(selected_patterns, exhausted) retained_by_group: dict[ FunctionGroupKey, + GroupedPatternMap, list[SourceCandidatePath], - ] = {component_value: [] for component_value in grouped_patterns.groups} + ] = {component_value: [] for component_value in grouped_patterns} for component_value, pattern in candidate_occurrences: if selected_pattern is exhausted: break @@ -447,15 +454,15 @@ def select_compatible( def default_source_bound_anchor_patterns( self, - grouped_patterns: PatternGroups, + grouped_patterns: GroupedPatternMap, *, policy: SourceBoundAnchorPatternPolicy, source_context: SourcePatternResolutionContext, - ) -> PatternGroups: + ) -> GroupedPatternMap: """Project raw source anchors onto compiler-owned semantic groups.""" execution_scope = self.plan.execution_group_scope - target_keys = execution_scope.runtime_keys(grouped_patterns.groups) + target_keys = execution_scope.runtime_keys(grouped_patterns) all_candidates = tuple( pattern for pattern_list in grouped_patterns.values() @@ -463,6 +470,7 @@ def default_source_bound_anchor_patterns( ) selected_groups: dict[ FunctionGroupKey, + GroupedPatternMap, Sequence[SourceCandidatePath], ] = {} for target_key in target_keys: @@ -470,7 +478,7 @@ def default_source_bound_anchor_patterns( self.plan.compiled_function_pattern.default_group, component_value=target_key, ) - local_candidates = grouped_patterns.groups.get(target_key) + local_candidates = grouped_patterns.get(target_key) requires_cross_group_resolution = ( execution_scope.component is not None and target_key is not None @@ -488,16 +496,18 @@ def default_source_bound_anchor_patterns( selected_groups[target_key] = ( () if bindings is None - else policy.select( - candidates, - bindings=bindings.binding_declarations, - source_context=source_context, + else tuple( + policy.select( + candidates, + bindings=bindings.binding_declarations, + source_context=source_context, + ) ) ) - filtered = PatternGroups.from_prepared(selected_groups) - before_count = grouped_patterns.total_count() - after_count = filtered.total_count() + filtered = selected_groups + before_count = sum(map(len, grouped_patterns.values())) + after_count = sum(map(len, filtered.values())) if before_count != after_count: record_function_step_runtime_profile( self.plan, @@ -540,8 +550,8 @@ def source_anchor_bindings( def producer_anchor_patterns( self, - grouped_patterns: PatternGroups, - ) -> PatternGroups: + grouped_patterns: GroupedPatternMap, + ) -> GroupedPatternMap: """Restrict previous-step anchors to the declared producer's files.""" def select_producer_paths( @@ -549,10 +559,10 @@ def select_producer_paths( pattern_list: tuple[SourceCandidatePath, ...], ) -> Sequence[SourceCandidatePath]: try: - return self.output_manifest.filter_to_producer_paths( + return step_output_manifest(self.context).filter_to_producer_paths( self.plan, tuple(pattern_list), - self.parser, + self.context.microscope_handler.parser, ) except NoStepOutputManifestMatch: return () @@ -565,8 +575,8 @@ def select_producer_paths( def artifact_driven_anchor_patterns( self, - grouped_patterns: PatternGroups, - ) -> PatternGroups: + grouped_patterns: GroupedPatternMap, + ) -> GroupedPatternMap: """Select the lifecycle anchors required by each compiled runtime domain.""" def select_lifecycle_anchors( @@ -589,12 +599,15 @@ def select_lifecycle_anchors( def apply( self, label: str, - grouped_patterns: PatternGroups, + grouped_patterns: GroupedPatternMap, selector: AnchorPatternSelector, - ) -> PatternGroups: - filtered = grouped_patterns.map_groups(selector) - before_count = grouped_patterns.total_count() - after_count = filtered.total_count() + ) -> GroupedPatternMap: + filtered = { + key: tuple(selector(key, patterns)) + for key, patterns in grouped_patterns.items() + } + before_count = sum(map(len, grouped_patterns.values())) + after_count = sum(map(len, filtered.values())) if before_count != after_count: record_function_step_runtime_profile( self.plan, @@ -610,62 +623,19 @@ def apply( def source_pattern_context(self) -> SourcePatternResolutionContext: """Return source-path context used to filter source-bound anchors.""" - projection = self.source_workspace_authority.projection_or_empty() - return SourcePatternResolutionContext.from_projection( - parser=self.parser, - projection=self.source_workspace_projection_cache.filtered_by_axis( + projection = VirtualWorkspaceSourceProjectionAuthority.from_context( + self.context, + cache=self.context.runtime_source_workspace_projection_cache, + ).projection_or_empty() + return self.context.runtime_source_binding_context_cache.source_pattern_context( + parser=self.context.microscope_handler.parser, + projection=self.context.runtime_source_workspace_projection_cache.filtered_by_axis( projection, axis_id=self.plan.axis_id, ), metadata_rules=self.plan.source_binding_plan.metadata_rules, ) - -def _filter_patterns_by_component( - patterns: DiscoveredPatternCollection, - component: str, - target_value: str, - parser: FilenameParser, -) -> DiscoveredPatternCollection: - """Filter pattern strings by a fixed parsed component value.""" - - def filter_pattern_list( - pattern_list: Sequence[SourceCandidatePath], - ) -> list[SourceCandidatePath]: - filtered: list[SourceCandidatePath] = [] - component_declaration = parser.component_for_name(component) - for pattern in pattern_list: - metadata = parser.parse_filename(str(pattern)) - if metadata and str(metadata.value_for(component_declaration)) == str( - target_value - ): - filtered.append(pattern) - return filtered - - if isinstance(patterns, dict): - filtered_by_group = {} - for group_key, pattern_list in patterns.items(): - filtered_list = filter_pattern_list(pattern_list) - if filtered_list: - filtered_by_group[group_key] = filtered_list - return filtered_by_group - - return filter_pattern_list(patterns) - - -class FunctionStepExecutor: - """Run one compiled FunctionStep plan for one multiprocessing axis.""" - - def __init__(self, context: ProcessingContext, step_index: int) -> None: - self.context = context - compiled_plan = context.step_plans[step_index] - if not isinstance(compiled_plan, CompiledStepPlan): - raise TypeError( - f"FunctionStep {step_index} requires CompiledStepPlan, got " - f"{type(compiled_plan).__name__}." - ) - self.plan = compiled_plan.require_function_execution_ready() - def record_runtime_profile( self, label: str, @@ -709,6 +679,110 @@ def execute( ) raise + def artifact_execution_requests( + self, + ) -> tuple[ArtifactPatternGroupExecutionRequest, ...] | None: + """Discover complete correlated cohorts from their compiled producers.""" + + context = self.context + plan = self.plan + pattern = plan.compiled_function_pattern + scope = plan.execution_group_scope + + def candidate_scopes( + edge: InvocationArtifactInputEdgePlan, + execution_scope: ComponentGroupScope, + ) -> dict[RuntimeExecutionAxisScope, str]: + return RuntimeArtifactInput( + edge_plan=edge, + axis_scope=RuntimeExecutionAxisScope.from_raw( + plan.axis_id, component=None, value=None, + ), + backend=Backend.MEMORY.value, + source_binding_plan=plan.source_binding_plan, + ).candidate_execution_scopes( + context.runtime_value_store, + execution_scope, + variable_components=ComponentSet.coerce(plan.variable_components), + ) + + if scope.is_dynamic: + discovered_keys = [] + for group in pattern.groups: + for invocation in group.invocations: + group_refs = invocation.contract.group_scope_inputs.ref_set() + for edge in invocation.artifact_input_edges: + if edge.storage_plan is None or not ( + edge.main_flow_projection is not None + or edge.spec.ref() in group_refs + ): + continue + discovered_keys.extend( + candidate.value_text + for candidate in candidate_scopes(edge, scope) + ) + if not any(key is not None for key in discovered_keys): + return None + component_keys = scope.runtime_keys(discovered_keys) + else: + component_keys = scope.runtime_keys(()) + + selected_groups = [] + for component_key in component_keys: + group = pattern.group_for_component(component_key) + if group is None: + raise ValueError( + f"No compiled function group for component {component_key!r}." + ) + edges = plan.stored_primary_input_edges_for_group(group, component_key) + if edges is None: + return None + selected_groups.append((component_key, group, edges)) + + requests = [] + for component_index, (component_key, group, edges) in enumerate(selected_groups): + cohorts = None + for edge in edges: + edge_cohorts = candidate_scopes( + edge, + ComponentGroupScope.from_raw((component_key,), component=scope.component), + ) + if not edge_cohorts: + raise ValueError( + f"Step {plan.step_index} ({plan.step_name}) has no exact " + f"producer cohort for {edge.spec.ref()!r} on axis {plan.axis_id}." + ) + cohorts = ( + edge_cohorts + if cohorts is None + else { + joined: anchor + for coordinates, anchor in cohorts.items() + for candidate in edge_cohorts + if (joined := coordinates.join_execution_cohort(candidate)) + is not None + } + ) + if not cohorts: + raise ValueError( + f"Step {plan.step_index} ({plan.step_name}) producer inputs " + "do not share a complete execution cohort." + ) + requests.extend( + ArtifactPatternGroupExecutionRequest( + context=context, + execution_plan=plan, + pattern_group_info=anchor, + compiled_group=group, + component_value=component_key, + fixed_component_values=coordinates.fixed_component_values, + component_index=component_index, + component_count=len(selected_groups), + ) + for coordinates, anchor in cohorts.items() + ) + return tuple(requests) + def run(self) -> StepExecutionObservation: plan = self.plan step_started_at = time.perf_counter() @@ -720,37 +794,41 @@ def run(self) -> StepExecutionObservation: ) phase_started_at = time.perf_counter() - patterns_by_axis = self._detect_patterns() + execution_requests = self.artifact_execution_requests() + patterns_by_axis = ( + self._detect_patterns() if execution_requests is None else None + ) self.record_runtime_profile( "step_detect_patterns", time.perf_counter() - phase_started_at, ) - self._log_discovered_patterns(patterns_by_axis) + if patterns_by_axis is not None: + self._log_discovered_patterns(patterns_by_axis) phase_started_at = time.perf_counter() self._convert_input_if_needed() self.record_runtime_profile( "step_convert_input", time.perf_counter() - phase_started_at, ) - self._require_patterns(patterns_by_axis) - self._apply_sequential_filter(patterns_by_axis) - - phase_started_at = time.perf_counter() - grouped_patterns = self._prepare_groups(patterns_by_axis) - self.record_runtime_profile( - "step_prepare_groups", - time.perf_counter() - phase_started_at, - ) - phase_started_at = time.perf_counter() - self._preload_inputs_if_needed(grouped_patterns) - self.record_runtime_profile( - "step_preload_inputs", - time.perf_counter() - phase_started_at, - ) - total_groups = grouped_patterns.total_count() + if patterns_by_axis is not None: + self._require_patterns(patterns_by_axis) + self._apply_sequential_filter(patterns_by_axis) + phase_started_at = time.perf_counter() + grouped_patterns = self._prepare_groups(patterns_by_axis) + execution_requests = self._execution_requests(grouped_patterns) + self.record_runtime_profile( + "step_prepare_groups", + time.perf_counter() - phase_started_at, + ) + if not execution_requests: + raise ValueError( + f"No execution cohorts found for step {plan.step_index} " + f"({plan.step_name}) on axis {plan.axis_id}." + ) + total_groups = len(execution_requests) execution_started_at = time.perf_counter() self._execute_pattern_groups( - grouped_patterns, + execution_requests, total_groups, ) execution_elapsed = time.perf_counter() - execution_started_at @@ -994,7 +1072,7 @@ def _apply_sequential_filter( def _prepare_groups( self, patterns_by_axis: Mapping[str, DiscoveredPatternCollection], - ) -> PatternGroups: + ) -> GroupedPatternMap: plan = self.plan axis_patterns = patterns_by_axis[plan.axis_id] execution_group_value = plan.execution_group_value @@ -1011,108 +1089,36 @@ def _prepare_groups( ): axis_patterns = _single_execution_group_patterns(axis_patterns) - pattern_filter = StepAnchorPatternFilter.from_context( - context=self.context, - plan=self.plan, - ) - grouped_patterns = PatternGroups.from_prepared( + discovered_groups = ( axis_patterns if isinstance(axis_patterns, Mapping) else {execution_group_value: axis_patterns} ) - grouped_patterns = pattern_filter.filtered(grouped_patterns) - if grouped_patterns.total_count() == 0: + grouped_patterns = { + key: tuple(str(pattern) for pattern in patterns) + for key, patterns in discovered_groups.items() + } + grouped_patterns = self._filter_anchor_patterns(grouped_patterns) + if sum(map(len, grouped_patterns.values())) == 0: raise ValueError( f"No pattern groups found for step {plan.step_index} " f"({plan.step_name}) in well {plan.axis_id}" ) return grouped_patterns - def _preload_inputs_if_needed( - self, - grouped_patterns: PatternGroups, - ) -> None: - plan = self.plan - if plan.read_backend == Backend.MEMORY.value: - return - - process = psutil.Process(os.getpid()) - mem_before_mb = process.memory_info().rss / 1024 / 1024 - logger.debug("Memory before preload: %.1f MB RSS", mem_before_mb) - - if plan.sequential_filter_plan.enabled: - patterns_to_preload = [ - pattern - for pattern_list in grouped_patterns.values() - for pattern in pattern_list - ] - logger.info( - "Sequential mode: preloading %s filtered patterns", - len(patterns_to_preload), - ) - bulk_preload_step_images( - plan.input_dir, - plan.axis_id, - plan.read_backend, - self.context.filemanager, - self.context.microscope_handler, - plan.zarr_config, - patterns_to_preload=patterns_to_preload, - variable_components=plan.variable_component_values, - ) - else: - bulk_preload_step_images( - plan.input_dir, - plan.axis_id, - plan.read_backend, - self.context.filemanager, - self.context.microscope_handler, - plan.zarr_config, - ) - - mem_after_mb = process.memory_info().rss / 1024 / 1024 - logger.debug( - "Memory after preload: %.1f MB RSS (+%.1f MB)", - mem_after_mb, - mem_after_mb - mem_before_mb, - ) - def _execute_pattern_groups( self, - grouped_patterns: PatternGroups, + execution_requests: Sequence[PatternGroupExecutionRequest], total_groups: int, ) -> None: - completed_groups = 0 - for component_index, (component_value, current_pattern_list) in enumerate( - grouped_patterns.items() - ): - compiled_group = self.plan.compiled_function_pattern.group_for_component( - component_value + for completed_groups, request in enumerate(execution_requests, start=1): + _process_single_pattern_group(request) + self._emit_pattern_progress( + completed_groups, + total_groups, + request.component_value, + request.pattern_group_info, ) - if compiled_group is None: - raise ValueError( - f"No compiled function group for component {component_value!r}." - ) - - for pattern_item in current_pattern_list: - _process_single_pattern_group( - PatternGroupExecutionRequest( - context=self.context, - execution_plan=self.plan, - pattern_group_info=pattern_item, - compiled_group=compiled_group, - component_value=component_value, - component_index=component_index, - component_count=len(grouped_patterns), - ) - ) - completed_groups += 1 - self._emit_pattern_progress( - completed_groups, - total_groups, - component_value, - pattern_item, - ) def _emit_pattern_progress( self, diff --git a/openhcs/core/steps/function_io.py b/openhcs/core/steps/function_io.py index d2e5e5e38b..caa50aaba6 100644 --- a/openhcs/core/steps/function_io.py +++ b/openhcs/core/steps/function_io.py @@ -7,10 +7,9 @@ from abc import ABC from dataclasses import dataclass, replace from pathlib import Path, PurePosixPath -from typing import TYPE_CHECKING, Callable, ClassVar, Mapping, Sequence, TypeAlias +from typing import TYPE_CHECKING, ClassVar, Mapping, Sequence, TypeAlias from metaclass_registry import AutoRegisterMeta -from polystore.config import tiff_write_batches from polystore.zarr_batch import ZarrBatchAxis, ZarrBatchAxisRole, ZarrBatchLayout from openhcs.constants.constants import ( @@ -19,16 +18,15 @@ Backend, ) from openhcs.core.components.parser_metaprogramming import FilenameParseResult -from openhcs.core.image_file_serialization import prepare_disk_image_payloads +from openhcs.core.image_file_serialization import ( + ImageFileFormat, + prepare_disk_image_payloads, +) from openhcs.core.registry_strategies import EnumKeyedStrategyMixin from openhcs.core.runtime_array_values import RuntimeArrayData -from openhcs.core.runtime_image_loading import ImagePayloadSourceMetadataContext from openhcs.core.runtime_image_values import ( image_payload_data, - image_payload_mask, - image_payload_metadata, ) -from openhcs.core.source_image_provenance import SourceImageIdentity from openhcs.core.steps.function_output_identity import FunctionOutputIdentity if TYPE_CHECKING: @@ -63,79 +61,6 @@ def prepare_storage_image_payloads( return [image_payload_data(payload) for payload in payloads] -@dataclass(frozen=True, slots=True) -class StepPreloadFileSet: - """Execution-scoped source files that must be available in memory backend.""" - - paths: tuple[str, ...] - - @classmethod - def from_paths(cls, paths: Sequence[str | Path]) -> "StepPreloadFileSet": - """Return a deterministic file set while preserving first-seen order.""" - return cls(tuple(dict.fromkeys(str(path) for path in paths))) - - def missing_memory_paths( - self, - filemanager: FileManager, - ) -> tuple[str, ...]: - """Return source paths not already copied into the execution memory backend.""" - return tuple( - path - for path in self.paths - if not filemanager.exists(path, Backend.MEMORY.value) - ) - - def load_missing_payloads( - self, - *, - filemanager: FileManager, - read_backend: str, - zarr_config: ZarrBackendConfig | None, - ) -> tuple[tuple[str, ...], list[RuntimeArrayData]]: - """Load missing source payloads and wrap them with source metadata.""" - missing_paths = self.missing_memory_paths(filemanager) - if not missing_paths: - return (), [] - if read_backend == Backend.ZARR.value: - raw_images = filemanager.load_batch( - list(missing_paths), - read_backend, - zarr_config=zarr_config, - ) - else: - raw_images = filemanager.load_batch(list(missing_paths), read_backend) - return missing_paths, [ - _preloaded_image_payload( - image, - source_path=file_path, - read_backend=read_backend, - filemanager=filemanager, - ) - for image, file_path in zip(raw_images, missing_paths, strict=True) - ] - - -def _preloaded_image_payload( - image: RuntimeArrayData, - *, - source_path: str, - read_backend: str, - filemanager: FileManager, -) -> RuntimeArrayData: - """Preserve loader-owned metadata or derive it through the source backend.""" - metadata = image_payload_metadata(image) - if not metadata.has_values: - metadata = ImagePayloadSourceMetadataContext( - SourceImageIdentity(source_path), - read_backend=read_backend, - filemanager=filemanager, - ).metadata(image) - return metadata.payload_with( - image_payload_data(image), - image_payload_mask(image), - ) - - def generate_materialized_paths( memory_paths: Sequence[str], step_output_dir: Path, @@ -384,7 +309,11 @@ def save_materialized_data( tiff_config = ( context.tiff_config if materialized_backend == Backend.DISK.value else None ) - for indices, batch_config in tiff_write_batches(materialized_paths, tiff_config): + for indices, batch_config in ImageFileFormat.storage_write_batches( + memory_data, + materialized_paths, + tiff_config, + ): filemanager.save_batch( [payloads[index] for index in indices], [materialized_paths[index] for index in indices], @@ -441,96 +370,6 @@ def get_all_image_paths( return full_file_paths -def create_image_path_getter( - axis_id: str, - filemanager: FileManager, - microscope_handler: MicroscopeHandler, -) -> Callable[[str | Path, str], list[str]]: - """Create a path getter bound to one multiprocessing axis value.""" - - def get_paths_for_axis(input_dir: str | Path, backend: str) -> list[str]: - return get_all_image_paths( - input_dir=input_dir, - axis_id=axis_id, - backend=backend, - filemanager=filemanager, - microscope_handler=microscope_handler, - ) - - return get_paths_for_axis - - -def bulk_preload_step_images( - step_input_dir: Path, - axis_id: str, - read_backend: str, - filemanager: FileManager, - microscope_handler: MicroscopeHandler, - zarr_config: ZarrBackendConfig | None = None, - patterns_to_preload: Sequence[str] | None = None, - variable_components: Sequence[str] | None = None, -) -> None: - """Preload this step's images from the source backend into the memory backend.""" - if patterns_to_preload is not None: - all_files = ( - file_path - for pattern in patterns_to_preload - for file_path in microscope_handler.path_list_from_pattern( - str(step_input_dir), - pattern, - filemanager, - read_backend, - variable_components, - ) - ) - full_file_paths = ( - ( - str(step_input_dir / file_path) - if not Path(file_path).is_absolute() - else str(file_path) - ) - for file_path in all_files - ) - else: - get_paths_for_axis = create_image_path_getter( - axis_id, filemanager, microscope_handler - ) - full_file_paths = get_paths_for_axis(step_input_dir, read_backend) - - preload_file_set = StepPreloadFileSet.from_paths(full_file_paths) - - if not preload_file_set.paths: - raise RuntimeError( - f"Bulk preload found no files for axis {axis_id} in {step_input_dir} " - f"with backend {read_backend}." - ) - - filemanager.ensure_directory(str(step_input_dir), Backend.MEMORY.value) - for parent in dict.fromkeys( - str(Path(path).parent) for path in preload_file_set.paths - ): - filemanager.ensure_directory(parent, Backend.MEMORY.value) - missing_paths, raw_images = preload_file_set.load_missing_payloads( - filemanager=filemanager, - read_backend=read_backend, - zarr_config=zarr_config, - ) - if not missing_paths: - logger.debug( - "Bulk preload reused %s memory-backed files for axis %s", - len(preload_file_set.paths), - axis_id, - ) - return - logger.debug( - "Bulk preload loading %s/%s files for axis %s", - len(missing_paths), - len(preload_file_set.paths), - axis_id, - ) - filemanager.save_batch(list(raw_images), list(missing_paths), Backend.MEMORY.value) - - def update_metadata_for_zarr_conversion( plate_root: Path, original_subdir: str, diff --git a/openhcs/core/steps/function_output_identity.py b/openhcs/core/steps/function_output_identity.py index f83da45f2f..ab483dc80a 100644 --- a/openhcs/core/steps/function_output_identity.py +++ b/openhcs/core/steps/function_output_identity.py @@ -5,7 +5,7 @@ from dataclasses import dataclass, field, replace from pathlib import Path import re -from typing import TYPE_CHECKING, Mapping, Sequence, TypeAlias +from typing import TYPE_CHECKING, ClassVar, Mapping, Sequence, TypeAlias from openhcs.core.source_path_identity import source_path_identity from openhcs.constants.constants import AllComponents, VariableComponents @@ -23,9 +23,9 @@ SourceImageIdentity, SourceImageProvenanceIdentity, ) +from openhcs.core.source_metadata import SourceMetadataFields from openhcs.core.source_matching import ( source_component_metadata_items, - with_source_component_metadata, ) from openhcs.core.source_projection import OpenHCSPlaneAddress from openhcs.microscopes.microscope_interfaces import FilenameParser @@ -144,13 +144,15 @@ def component_metadata( source_metadata: SourceComponentMetadata | None = None, ) -> SourceComponentMetadata: """Return parser-compatible component metadata for this output identity.""" - metadata = dict(source_metadata or {}) - metadata.update(self.component_values) - for component, value in source_component_metadata_items(self.component_values): - metadata = with_source_component_metadata(metadata, component, value) - if self.extension is not None: - metadata["extension"] = self.extension - return metadata + metadata = source_metadata if source_metadata is not None else {} + return SourceMetadataFields.with_fields( + SourceMetadataFields.composition_snapshot(metadata), + self.component_values, + components=source_component_metadata_items(self.component_values), + after_components=( + {"extension": self.extension} if self.extension is not None else None + ), + ) def filename_component_metadata(self) -> SourceComponentMetadata: """Return parser-compatible metadata used to construct the output filename.""" @@ -161,159 +163,82 @@ def filename_component_metadata(self) -> SourceComponentMetadata: def with_filename_qualifier(self, qualifier: str) -> "FunctionOutputIdentity": """Return this identity qualified by a declared output surface name.""" - return replace(self, filename_qualifier=FilenameQualifier.from_value(qualifier)) + return replace( + self, filename_qualifier=self._normalize_filename_qualifier(qualifier), + ) def without_filename_qualifier(self) -> "FunctionOutputIdentity": """Return this identity without its output-surface filename qualifier.""" return replace(self, filename_qualifier=None) - -class FilenameQualifier: - """Normalize declared output surface names for filename disambiguation.""" - - _unsafe_pattern = re.compile(r"[^A-Za-z0-9_.-]+") + _unsafe_qualifier_pattern: ClassVar[re.Pattern[str]] = re.compile(r"[^A-Za-z0-9_.-]+") @classmethod - def from_value(cls, value: str) -> str: - qualifier = cls._unsafe_pattern.sub("_", str(value).strip()) + def _normalize_filename_qualifier(cls, value: str) -> str: + qualifier = cls._unsafe_qualifier_pattern.sub("_", str(value).strip()) qualifier = qualifier.strip("_.-") if not qualifier: raise ValueError("Filename qualifier cannot be empty.") return qualifier - -@dataclass(frozen=True, slots=True) -class FunctionOutputParserContext: - """Parser-facing microscope context for FunctionStep output finalization.""" - - parser: FilenameParser - microscope_type: str - - @classmethod - def from_processing_context( - cls, - context: "ProcessingContext", - ) -> "FunctionOutputParserContext": - handler = context.microscope_handler - return cls( - parser=handler.parser, - microscope_type=handler.microscope_type, - ) - - @property - def parser_name(self) -> str: - return self.parser.__class__.__name__ - - def parse_path_metadata(self, path: str | Path) -> SourceComponentMetadata | None: - parsed = self.parser.parse_filename(source_path_identity(str(path)).name) - return None if parsed is None else parsed.wire_mapping() - - -class FunctionOutputPathAuthority: - """Construct output filenames from semantic identity through the parser.""" - - @classmethod - def output_path(cls, request: FunctionOutputPathRequest) -> Path: - return cls.output_path_for_identity( - request, - FunctionOutputIdentityAuthority.identity(request), + def path_for_request(self, request: FunctionOutputPathRequest) -> Path: + """Construct this identity's path in the request's output directory.""" + return Path(request.output_dir) / self.cached_filename( + request.parser, request.identity_cache, ) @classmethod - def output_filename(cls, request: FunctionOutputPathRequest) -> str: - return cls.output_filename_for_identity( - request, - FunctionOutputIdentityAuthority.identity(request), - ) + def path_from_request(cls, request: FunctionOutputPathRequest) -> Path: + """Resolve one runtime slice identity and construct its output path.""" + return cls.from_request(request).path_for_request(request) - @classmethod - def output_path_for_identity( - cls, - request: FunctionOutputPathRequest, - identity: FunctionOutputIdentity, - ) -> Path: - return Path(request.output_dir) / cls.output_filename_for_identity( - request, - identity, - ) - - @classmethod - def output_filename_for_identity( - cls, - request: FunctionOutputPathRequest, - identity: FunctionOutputIdentity, - ) -> str: - return cls.cached_filename_for_identity( - request.parser, - identity, - request.identity_cache, - ) - - @classmethod - def cached_filename_for_identity( - cls, + def cached_filename( + self, parser: FilenameParser, - identity: FunctionOutputIdentity, identity_cache: FunctionOutputIdentityCache, ) -> str: - cache_key = cls._filename_cache_key(parser, identity) + cache_key = self._filename_cache_key(parser) cached = identity_cache.filenames_by_identity.get(cache_key) if cached is not None: return cached - filename = cls.filename_for_identity(parser, identity) + filename = self.filename(parser) identity_cache.filenames_by_identity[cache_key] = filename return filename - @classmethod - def filename_for_identity( - cls, - parser: FilenameParser, - identity: FunctionOutputIdentity, - ) -> str: - component_values = dict(identity.filename_values) - extension = identity.extension + def filename(self, parser: FilenameParser) -> str: + """Construct this value's storage filename through the external parser.""" + component_values = dict(self.filename_values) + extension = self.extension try: - bound = parser.bind_component_values( - component_values, - extension=extension, - ) + bound = parser.bind_component_values(component_values, extension=extension) filename = parser.construct_filename(bound) - return cls._qualified_filename( - filename, identity.filename_qualifier, extension=bound.extension + return self._qualified_filename( + filename, self.filename_qualifier, extension=bound.extension, ) except MissingFilenameComponentError as exc: raise IncompleteFunctionOutputFilenameIdentityError( exc.component_name, - cls._construction_error_message( - identity, - component_values, - extension, - ), + self._construction_error_message(component_values, extension), ) from exc except Exception as exc: raise ValueError( - cls._construction_error_message( - identity, - component_values, - extension, - ) + self._construction_error_message(component_values, extension), ) from exc - @staticmethod def _construction_error_message( - identity: FunctionOutputIdentity, + self, component_values: FunctionOutputComponentValues, extension: str | None, ) -> str: return ( "Cannot construct FunctionStep output filename from " - f"{identity.source} identity. Components={component_values!r}, " + f"{self.source} identity. Components={component_values!r}, " f"extension={extension!r}." ) @staticmethod def _qualified_filename( - filename: str, qualifier: str | None, *, extension: str + filename: str, qualifier: str | None, *, extension: str, ) -> str: if qualifier is None: return filename @@ -321,43 +246,34 @@ def _qualified_filename( raise ValueError("Constructed filename does not retain its declared extension.") return f"{filename[:-len(extension)]}_{qualifier}{extension}" - @staticmethod - def _filename_cache_key( - parser: FilenameParser, - identity: FunctionOutputIdentity, - ) -> FunctionOutputFilenameCacheKey: - component_values = identity.filename_values + def _filename_cache_key(self, parser: FilenameParser) -> FunctionOutputFilenameCacheKey: return FunctionOutputFilenameCacheKey( parser_id=id(parser), component_values=tuple( - sorted((str(key), value) for key, value in component_values.items()) + sorted((str(key), value) for key, value in self.filename_values.items()) ), - extension=identity.extension, - filename_qualifier=identity.filename_qualifier, + extension=self.extension, + filename_qualifier=self.filename_qualifier, ) - -class FunctionOutputExtensionAuthority: - """Resolve filename extensions from source metadata or paths.""" - @classmethod - def first(cls, *extensions: str | None) -> str | None: + def _first_extension(cls, *extensions: str | None) -> str | None: for extension in extensions: if extension is not None: return extension return None @classmethod - def from_metadata( + def _extension_from_metadata( cls, metadata: SourceComponentMetadata | None, ) -> str | None: - return cls.from_raw( + return cls._extension_from_raw( SourceImageIdentity(component_metadata=metadata).filename_extension ) @classmethod - def from_path( + def _extension_from_path( cls, path: str | None, *, @@ -366,17 +282,17 @@ def from_path( ) -> str | None: if path is None: return None - identity = FunctionOutputIdentityAuthority._parsed_path_identity_with_cache( + identity = cls._parsed_path_identity_with_cache( parser, path, source="source extension", identity_cache=identity_cache ) if identity is not None: return identity.extension # Physical source paths need not have a canonical plane address. Their # terminal file suffix is not a chain of dotted source identity tokens. - return cls.from_raw(Path(path).suffix) + return cls._extension_from_raw(Path(path).suffix) @classmethod - def from_source( + def _extension_from_source( cls, metadata: SourceComponentMetadata | None, path: str | None, @@ -385,13 +301,13 @@ def from_source( identity_cache: FunctionOutputIdentityCache, ) -> str | None: """Honor retained extension declarations before external path decoding.""" - extension = cls.from_metadata(metadata) + extension = cls._extension_from_metadata(metadata) if extension is not None: return extension - return cls.from_path(path, parser=parser, identity_cache=identity_cache) + return cls._extension_from_path(path, parser=parser, identity_cache=identity_cache) @staticmethod - def from_raw(raw_extension: ParsedFilenameValue) -> str | None: + def _extension_from_raw(raw_extension: ParsedFilenameValue) -> str | None: if raw_extension is None: return None extension = str(raw_extension) @@ -399,49 +315,31 @@ def from_raw(raw_extension: ParsedFilenameValue) -> str | None: return None return extension - -class FunctionOutputComponentIdentityAuthority: - """Normalize parser/source component values for output identity.""" - @classmethod - def from_source_metadata( + def _component_values_from_source_metadata( cls, metadata: SourceComponentMetadata | None, ) -> dict[str, FunctionOutputComponentValue]: if metadata is None: return {} return { - component.value: cls.coerce_component_value(component, value) + component.value: SourceMetadataFields.canonical_component_value(component, value) for component, value in source_component_metadata_items(metadata) } @classmethod - def from_parsed( + def component_values_from_parsed( cls, parsed: FilenameParseResult, ) -> dict[str, FunctionOutputComponentValue]: return { - str(component.value): cls.coerce_component_value(component, value) + str(component.value): SourceMetadataFields.canonical_component_value(component, value) for component, value in parsed.declared_values() if value is not None } - @staticmethod - def coerce_component_value( - component: AllComponents | None, - value: ParsedFilenameValue, - ) -> FunctionOutputComponentValue: - if component is None or not component.is_variable_axis(): - return str(value) - value_text = str(value) - return int(value_text) if value_text.isdecimal() else value_text - - -class FunctionOutputIdentityAuthority: - """Resolve the single source of output identity for a runtime slice.""" - @classmethod - def identity(cls, request: FunctionOutputPathRequest) -> FunctionOutputIdentity: + def from_request(cls, request: FunctionOutputPathRequest) -> FunctionOutputIdentity: metadata = image_payload_metadata(request.output_payload) payload_identity = cls._identity_from_metadata_with_cache( request.parser, @@ -462,7 +360,7 @@ def identity(cls, request: FunctionOutputPathRequest) -> FunctionOutputIdentity: return cls._input_aligned_identity(request) @classmethod - def identity_from_metadata( + def from_metadata( cls, parser: FilenameParser, metadata: ImagePayloadMetadata, @@ -482,7 +380,7 @@ def identity_from_metadata( ) @classmethod - def identity_from_metadata_with_cache( + def from_metadata_with_cache( cls, parser: FilenameParser, metadata: ImagePayloadMetadata, @@ -583,7 +481,7 @@ def _identity_from_metadata_uncached( identity = cls._identity_from_metadata( metadata.source_component_metadata, - extension=FunctionOutputExtensionAuthority.from_source( + extension=cls._extension_from_source( metadata.source_component_metadata, metadata.source_path, parser=parser, identity_cache=identity_cache, ), @@ -591,7 +489,7 @@ def _identity_from_metadata_uncached( ) if identity is not None: if source_plane_count == 0 and len(represented_source_identities) > 1: - filename_identity = cls.filename_identity_from_metadata( + filename_identity = cls.from_filename_metadata( parser, metadata, fallback_identity_path=fallback_identity_path, @@ -608,7 +506,7 @@ def _identity_from_metadata_uncached( return replace( identity, component_values=semantic_component_values, - extension=FunctionOutputExtensionAuthority.first( + extension=cls._first_extension( identity.extension, filename_identity.extension, ), @@ -638,7 +536,7 @@ def _identity_from_metadata_uncached( source_identity = represented_source_identities[0] identity = cls._identity_from_metadata( source_identity.component_metadata, - extension=FunctionOutputExtensionAuthority.from_source( + extension=cls._extension_from_source( source_identity.component_metadata, source_identity.path, parser=parser, identity_cache=identity_cache, ), @@ -678,7 +576,7 @@ def _identity_from_metadata_uncached( return None @classmethod - def filename_identity_from_metadata( + def from_filename_metadata( cls, parser: FilenameParser, metadata: ImagePayloadMetadata, @@ -697,7 +595,7 @@ def filename_identity_from_metadata( ) identity = cls._identity_from_metadata( metadata.source_component_metadata, - extension=FunctionOutputExtensionAuthority.from_source( + extension=cls._extension_from_source( metadata.source_component_metadata, metadata.source_path, parser=parser, identity_cache=identity_cache, ), @@ -781,7 +679,7 @@ def _complete_identity_from_paths( component_values.update(identity.component_values) return FunctionOutputIdentity( component_values=component_values, - extension=FunctionOutputExtensionAuthority.first( + extension=cls._first_extension( identity.extension, parsed_identity.extension, ), @@ -821,7 +719,7 @@ def _parsed_path_identity( if parsed is None: return None return FunctionOutputIdentity( - component_values=FunctionOutputComponentIdentityAuthority.from_parsed( + component_values=cls.component_values_from_parsed( parsed ), extension=parsed.extension, @@ -897,7 +795,7 @@ def _source_stack_source_identity( ) -> FunctionOutputIdentity: identity = cls._identity_from_metadata( source_identity.component_metadata, - extension=FunctionOutputExtensionAuthority.from_source( + extension=cls._extension_from_source( source_identity.component_metadata, source_identity.path, parser=parser, identity_cache=identity_cache, ), @@ -985,8 +883,9 @@ def _source_stack_semantic_component_keys( extra_keys = tuple(sorted(keys - frozenset(ordered_keys))) return (*ordered_keys, *extra_keys) - @staticmethod + @classmethod def _source_stack_extension( + cls, plane_identities: tuple[FunctionOutputIdentity, ...], identity_component_values: frozenset[str], *, @@ -994,7 +893,7 @@ def _source_stack_extension( parser: FilenameParser, identity_cache: FunctionOutputIdentityCache, ) -> str | None: - fallback_extension = FunctionOutputExtensionAuthority.from_path( + fallback_extension = cls._extension_from_path( fallback_identity_path, parser=parser, identity_cache=identity_cache ) if fallback_extension is not None: @@ -1091,7 +990,7 @@ def _input_aligned_payload_identity( return replace( identity, component_values=component_values, - extension=FunctionOutputExtensionAuthority.first( + extension=cls._first_extension( identity.extension, parsed_identity.extension, ), @@ -1103,7 +1002,7 @@ def _input_aligned_payload_identity( return replace( identity, component_values=component_values, - extension=FunctionOutputExtensionAuthority.first( + extension=cls._first_extension( identity.extension, parsed_identity.extension, ), @@ -1119,7 +1018,7 @@ def _identity_from_metadata( source: str, ) -> FunctionOutputIdentity | None: component_values = ( - FunctionOutputComponentIdentityAuthority.from_source_metadata(metadata) + cls._component_values_from_source_metadata(metadata) ) if not component_values: return None @@ -1128,3 +1027,30 @@ def _identity_from_metadata( extension=extension, source=source, ) + + +@dataclass(frozen=True, slots=True) +class FunctionOutputParserContext: + """Parser-facing microscope context for FunctionStep output finalization.""" + + parser: FilenameParser + microscope_type: str + + @classmethod + def from_processing_context( + cls, + context: "ProcessingContext", + ) -> "FunctionOutputParserContext": + handler = context.microscope_handler + return cls( + parser=handler.parser, + microscope_type=handler.microscope_type, + ) + + @property + def parser_name(self) -> str: + return self.parser.__class__.__name__ + + def parse_path_metadata(self, path: str | Path) -> SourceComponentMetadata | None: + parsed = self.parser.parse_filename(source_path_identity(str(path)).name) + return None if parsed is None else parsed.wire_mapping() diff --git a/openhcs/core/steps/function_output_manifest.py b/openhcs/core/steps/function_output_manifest.py index ea93bbff1e..9ceb44b9c2 100644 --- a/openhcs/core/steps/function_output_manifest.py +++ b/openhcs/core/steps/function_output_manifest.py @@ -2,9 +2,9 @@ from __future__ import annotations -from dataclasses import dataclass, field +from dataclasses import dataclass, field, replace from pathlib import Path -from typing import ClassVar, Iterator, Sequence +from typing import Iterator, Sequence from weakref import WeakKeyDictionary from polystore.streaming.identity import StreamProducerIdentity @@ -23,15 +23,17 @@ ImagePayloadMetadata, image_payload_metadata, ) +from openhcs.core.runtime_plane_projection import RuntimePlaneAxis +from openhcs.core.source_metadata import SourceMetadataValue from openhcs.core.step_dependencies import StepInputDependencyKind from openhcs.core.steps.function_output_identity import ( - FunctionOutputComponentIdentityAuthority, FunctionOutputIdentity, - FunctionOutputPathAuthority, ) from openhcs.microscopes.microscope_interfaces import FilenameParser from openhcs.core.compiled_step_plan import CompiledStepPlan +from openhcs.core.component_group_scope import RuntimeExecutionAxisScope +from openhcs.constants import AllComponents @dataclass(frozen=True, slots=True) @@ -46,65 +48,6 @@ class NoStepOutputManifestMatch(RuntimeError): """Raised when a stale directory pattern is not in producer lineage.""" -@dataclass(frozen=True, slots=True) -class FunctionStepOutputProducerIdentityRequest: - """Declared producer identity facts for a FunctionStep output surface.""" - - ARTIFACT_OUTPUT_KIND: ClassVar[str] = "artifact" - - plan: CompiledStepPlan - output_kind: str - output_key: str - projection_key: str - artifact_kind: str | None = None - - @classmethod - def from_main_flow( - cls, - plan: CompiledStepPlan, - output_context: AlignedImageSliceContext, - ) -> "FunctionStepOutputProducerIdentityRequest": - return cls( - plan=plan, - output_kind=output_context.output_kind, - output_key=output_context.output_key, - projection_key=output_context.projection_key, - artifact_kind=output_context.artifact_kind, - ) - - @classmethod - def from_artifact( - cls, - plan: CompiledStepPlan, - output_plan: ArtifactOutputPlan, - ) -> "FunctionStepOutputProducerIdentityRequest": - return cls( - plan=plan, - output_kind=cls.ARTIFACT_OUTPUT_KIND, - output_key=output_plan.name, - projection_key=output_plan.name, - artifact_kind=output_plan.artifact_type.value, - ) - - -class FunctionStepOutputProducerIdentityAuthority: - """Build stable producer identities for all FunctionStep output surfaces.""" - - @staticmethod - def build( - request: FunctionStepOutputProducerIdentityRequest, - ) -> StreamProducerIdentity: - return StreamProducerIdentity.pipeline_output( - output_kind=request.output_kind, - output_key=request.output_key, - projection_key=request.projection_key, - step_name=request.plan.step_name, - pipeline_position=request.plan.pipeline_position, - step_scope_id=request.plan.step_scope_id, - artifact_kind=request.artifact_kind, - ) - - @dataclass(frozen=True, slots=True) class ProducedOutputSemantics(FunctionOutputIdentity): """Semantic record for one output file produced by a FunctionStep.""" @@ -113,6 +56,29 @@ class ProducedOutputSemantics(FunctionOutputIdentity): output_path: str relative_output_path: str image_metadata: ImagePayloadMetadata | None = None + main_flow_plane_axis: RuntimePlaneAxis | None = RuntimePlaneAxis.RUNTIME_SLICE + + def path_tokens(self, parser: FilenameParser) -> frozenset[str]: + """Expose this occurrence's exact storage and unqualified address aliases.""" + tokens = { + token + for value in (self.relative_output_path, self.output_path) + for token in ( + source_path_identity(value).as_posix(), + source_path_identity(value).name, + ) + } + if self.filename_qualifier is not None: + tokens.add(self.without_filename_qualifier().filename(parser)) + return frozenset(tokens) + + def passed_through(self, plan: CompiledStepPlan) -> "ProducedOutputSemantics": + """Retain the image domain and physical identity under the next producer.""" + return replace( + self, + producer_identity=plan.producer_identity_for_main_flow(self.output_context), + relative_output_path=source_path_identity(self.output_path).name, + ) def contextualize_image_payload( self, @@ -130,6 +96,62 @@ def path_under(self, output_dir: str | Path) -> str: return str(Path(output_dir) / self.relative_output_path) + def memory_path(self, plan: CompiledStepPlan) -> str: + """Resolve this original saved occurrence in its step's memory namespace.""" + path = Path(self.output_path) + return str(path) if path.is_absolute() else self.path_under(plan.output_dir) + + def source_metadata_for_projection( + self, metadata: ImagePayloadMetadata, destination: str + ) -> dict[str, SourceMetadataValue]: + """Combine this occurrence's coordinates with current persisted image facts.""" + source_metadata = dict( + self.component_metadata(metadata.source_component_metadata) + ) + metadata.source_voxel_spacing.merge_into(source_metadata, path=destination) + return source_metadata + + def execution_scope(self, plan: CompiledStepPlan) -> RuntimeExecutionAxisScope: + """Retain the exact producer coordinates of a whole intrinsic image.""" + group_component = plan.execution_group_scope.component + group_value = ( + None + if group_component is None + else self.component_values.get(group_component.value) + ) + return RuntimeExecutionAxisScope.from_raw( + plan.axis_id, + component=group_component if group_value is not None else None, + value=group_value, + fixed_component_values=tuple( + (component, str(value)) + for component in AllComponents + if not component.is_multiprocessing_axis() + and component is not group_component + and (value := self.component_values.get(component.value)) is not None + ), + ) + + def owns_persisted_artifact( + self, + output_plan: ArtifactOutputPlan, + output_path: str, + output_dir: str | Path, + ) -> bool: + """Identify the same declared producer and exact saved occurrence.""" + identity = self.producer_identity + return ( + self.output_context.persisted_source_alias, + identity.artifact_kind, + identity.step_scope_id, + Path(self.path_under(output_dir)), + ) == ( + output_plan.name, + output_plan.artifact_type.value, + output_plan.producer_step_scope_id, + Path(output_path), + ) + @property def output_context(self) -> AlignedImageSliceContext: """Return the declared main-flow context for this produced output.""" @@ -175,17 +197,13 @@ def from_output( output_identity: FunctionOutputIdentity, output_context: AlignedImageSliceContext | None = None, image_metadata: ImagePayloadMetadata | None = None, + main_flow_plane_axis: RuntimePlaneAxis | None = RuntimePlaneAxis.RUNTIME_SLICE, ) -> "ProducedOutputSemantics": output_path_text = str(output_path) if output_context is None: output_context = AlignedImageSliceContext.anonymous_main_flow() return cls( - producer_identity=FunctionStepOutputProducerIdentityAuthority.build( - FunctionStepOutputProducerIdentityRequest.from_main_flow( - plan, - output_context, - ) - ), + producer_identity=plan.producer_identity_for_main_flow(output_context), component_values=output_identity.component_values, extension=output_identity.extension, source=output_identity.source, @@ -197,6 +215,7 @@ def from_output( Path(plan.output_dir), ), image_metadata=image_metadata, + main_flow_plane_axis=main_flow_plane_axis, ) @classmethod @@ -216,7 +235,7 @@ def from_existing_main_flow_path( extension = parsed.extension if parsed is not None else path.suffix or None identity = FunctionOutputIdentity( component_values=( - FunctionOutputComponentIdentityAuthority.from_parsed(parsed) + FunctionOutputIdentity.component_values_from_parsed(parsed) if parsed is not None else {} ), @@ -224,12 +243,7 @@ def from_existing_main_flow_path( source="existing main-flow path", ) return cls( - producer_identity=FunctionStepOutputProducerIdentityAuthority.build( - FunctionStepOutputProducerIdentityRequest.from_main_flow( - plan, - output_context, - ) - ), + producer_identity=plan.producer_identity_for_main_flow(output_context), component_values=identity.component_values, extension=identity.extension, source=identity.source, @@ -252,10 +266,6 @@ class StepOutputManifestStore: tuple[int, int], tuple[ProducedOutputSemantics, ...] | None, ] = field(default_factory=dict) - producer_paths_by_pattern: dict[ - tuple[int, int, str, int], - tuple[str, ...], - ] = field(default_factory=dict) filtered_paths_by_plan: dict[ tuple[int, int, tuple[str, ...], int], tuple[str, ...], @@ -315,7 +325,6 @@ def record_outputs( def _invalidate_record_selection_caches(self) -> None: self.records_revision += 1 self.selected_records_by_plan.clear() - self.producer_paths_by_pattern.clear() self.filtered_paths_by_plan.clear() def producer_records_for( @@ -369,18 +378,14 @@ def producer_patterns_by_execution_group( key = plan.execution_group_scope.normalize_key(value) if plan.execution_group_scope.contains_runtime_key(key): records_by_group.setdefault(key, []).append(record) - selectors = tuple( - (pattern, ProducedPathPatternSelector.from_pattern(pattern)) - for pattern in dict.fromkeys(patterns) - ) - return { - key: tuple( - pattern - for pattern, selector in selectors - if selector.matches(ProducedPathSet.from_records(group_records, parser)) + patterns = tuple(dict.fromkeys(patterns)) + groups = {} + for key, group_records in records_by_group.items(): + index = ProducedPathRecordIndex.from_records(group_records, parser) + groups[key] = tuple( + pattern for pattern in patterns if index.contains(pattern) ) - for key, group_records in records_by_group.items() - } + return groups def produced_records_for( self, @@ -399,6 +404,15 @@ def produced_paths_for( record.relative_output_path for record in self.produced_records_for(plan) ) + def image_records_for( + self, plan: CompiledStepPlan + ) -> tuple[ProducedOutputSemantics, ...]: + """Select image occurrences directly from this step's current producer cohort.""" + return tuple( + record for record in self.produced_records_for(plan) + if record.is_image_payload + ) + def producer_output_contexts_for_paths( self, plan: CompiledStepPlan, @@ -407,23 +421,33 @@ def producer_output_contexts_for_paths( ) -> tuple[AlignedImageSliceContext, ...]: """Return producer output contexts aligned to concrete input paths.""" - producer_records = self._selected_unique_producer_records_for(plan) - if producer_records is None: + records = self.producer_output_records_for_paths(plan, paths, parser) + if records is None: return tuple( AlignedImageSliceContext.anonymous_main_flow() for _path in paths ) + return tuple(record.output_context for record in records) - path_index = ProducedPathRecordIndex.from_records(producer_records, parser) - contexts: list[AlignedImageSliceContext] = [] - for path in paths: - matching_records = path_index.matching_records(path) - if len(matching_records) != 1: - raise NoStepOutputManifestMatch( - "Expected one producer output context for input path " - f"{path!r}, found {len(matching_records)}." - ) - contexts.append(matching_records[0].output_context) - return tuple(contexts) + def producer_output_records_for_paths( + self, + plan: CompiledStepPlan, + paths: Sequence[str], + parser: FilenameParser, + ) -> tuple[ProducedOutputSemantics, ...] | None: + """Resolve exact producer declarations in the requested physical path order.""" + + index = self.producer_record_index_for(plan, parser) + return None if index is None else index.records_for_paths(paths) + + def producer_record_index_for( + self, plan: CompiledStepPlan, parser: FilenameParser, + ) -> ProducedPathRecordIndex | None: + """Admit one current producer cohort with its correlated address aliases.""" + records = self._selected_unique_producer_records_for(plan) + return ( + None if records is None + else ProducedPathRecordIndex.from_records(records, parser) + ) def filter_to_producer_paths( self, @@ -441,11 +465,10 @@ def filter_to_producer_paths( if cached is not None: return list(cached) - producer_records = self._selected_unique_producer_records_for(plan) - if producer_records is None: + index = self.producer_record_index_for(plan, parser) + if index is None: return list(paths) - allowed = ProducedPathSet.from_records(producer_records, parser) - selected = [path for path in paths if allowed.contains(path)] + selected = [path for path in paths if index.contains(path)] if selected: self.filtered_paths_by_plan[cache_key] = tuple(selected) return selected @@ -454,30 +477,6 @@ def filter_to_producer_paths( self.filtered_paths_by_plan[cache_key] = () return [] - def producer_paths_matching_pattern( - self, - plan: CompiledStepPlan, - pattern: str, - parser: FilenameParser, - ) -> list[str]: - """Return requested producer paths addressed by a detected pattern.""" - cache_key = (self.records_revision, id(plan), str(pattern), id(parser)) - cached = self.producer_paths_by_pattern.get(cache_key) - if cached is not None: - return list(cached) - - producer_records = self._selected_unique_producer_records_for(plan) - if producer_records is None: - return [] - selector = ProducedPathPatternSelector.from_pattern(pattern) - selected = tuple( - record.output_path - for record in producer_records - if selector.matches(ProducedPathSet.from_records((record,), parser)) - ) - self.producer_paths_by_pattern[cache_key] = selected - return list(selected) - def _selected_unique_producer_records_for( self, plan: CompiledStepPlan, @@ -501,6 +500,12 @@ def _unique_output_path_records( ) -> tuple[ProducedOutputSemantics, ...]: records_by_path: dict[str, ProducedOutputSemantics] = {} for record in records: + existing = records_by_path.get(record.output_path) + if existing is not None and existing.main_flow_plane_axis is not record.main_flow_plane_axis: + raise ValueError( + "One produced output path cannot declare conflicting main-flow image axes: " + f"{record.output_path!r}." + ) records_by_path.setdefault(record.output_path, record) return tuple(records_by_path.values()) @@ -556,7 +561,7 @@ def _requested_producer_outputs( for invocation in plan.compiled_function_pattern.iter_invocations() for edge in invocation.artifact_input_edges if ( - edge.consumes_main_flow + edge.main_flow_projection is not None or ( edge.spec.parameter_name is None and edge.spec.ref() @@ -575,13 +580,6 @@ def records_for_key( return () return self.records_by_key[key] - @staticmethod - def allowed_path_tokens( - records: Sequence[ProducedOutputSemantics], - parser: FilenameParser, - ) -> set[str]: - return ProducedPathSet.from_records(records, parser).tokens - @staticmethod def key_for_producer( plan: CompiledStepPlan, @@ -611,38 +609,8 @@ def step_output_manifest(context: ProcessingContext) -> StepOutputManifestStore: @dataclass(frozen=True, slots=True) -class ProducedPathSet: - """Path membership authority for concrete and template producer anchors.""" - - tokens: frozenset[str] - - @classmethod - def from_records( - cls, - records: Sequence[ProducedOutputSemantics], - parser: FilenameParser, - ) -> "ProducedPathSet": - tokens: set[str] = set() - for record in records: - for value in (record.relative_output_path, record.output_path): - tokens.add(source_path_identity(value).as_posix()) - tokens.add(source_path_identity(value).name) - if record.filename_qualifier is not None: - tokens.add( - FunctionOutputPathAuthority.filename_for_identity( - parser, - record.without_filename_qualifier(), - ) - ) - return cls(frozenset(tokens)) - - def contains(self, path: str) -> bool: - return ProducedPathPatternSelector.from_pattern(path).matches(self) - - -@dataclass(frozen=True, slots=True) -class ProducedPathRecordIndex(ProducedPathSet): - """Batch lookup of original producer records through their owned path tokens.""" +class ProducedPathRecordIndex: + """Correlated producer occurrences and their concrete/template address aliases.""" records: tuple[ProducedOutputSemantics, ...] record_indices_by_token: dict[str, tuple[int, ...]] @@ -652,52 +620,59 @@ def from_records( cls, records: Sequence[ProducedOutputSemantics], parser: FilenameParser, - ) -> "ProducedPathRecordIndex": + ) -> ProducedPathRecordIndex: indices_by_token: dict[str, list[int]] = {} for index, record in enumerate(records): - for token in ProducedPathSet.from_records((record,), parser).tokens: + for token in record.path_tokens(parser): indices_by_token.setdefault(token, []).append(index) return cls( - tokens=frozenset(indices_by_token), records=tuple(records), record_indices_by_token={ token: tuple(indices) for token, indices in indices_by_token.items() }, ) + def matching_tokens(self, path: str) -> Iterator[str]: + """Resolve exact and template address aliases through the existing matcher.""" + path = source_path_identity(path).as_posix() + tokens = self.record_indices_by_token + matcher = PathPatternTemplateMatcher.from_pattern(path) + if path in tokens: + yield path + if matcher is not None: + for token in tokens: + if token != path and matcher.matches(token): + yield token + + def contains(self, path: str) -> bool: + return next(self.matching_tokens(path), None) is not None + def matching_records(self, path: str) -> tuple[ProducedOutputSemantics, ...]: - selector = ProducedPathPatternSelector.from_pattern(path) - indices = sorted( - { - index - for token in selector.matching_tokens(self) - for index in self.record_indices_by_token[token] - } - ) + indices = sorted({ + index + for token in self.matching_tokens(path) + for index in self.record_indices_by_token[token] + }) return tuple(self.records[index] for index in indices) + def record_for_path(self, path: str) -> ProducedOutputSemantics: + """Require one original occurrence for one admitted physical address.""" + records = self.matching_records(path) + if len(records) != 1: + raise NoStepOutputManifestMatch( + "Expected one producer output context for input path " + f"{path!r}, found {len(records)}." + ) + return records[0] -@dataclass(frozen=True, slots=True) -class ProducedPathPatternSelector: - """Prepared matcher for concrete and template producer path membership.""" - - path: str - matcher: PathPatternTemplateMatcher | None + def records_for_paths( + self, paths: Sequence[str], + ) -> tuple[ProducedOutputSemantics, ...]: + return tuple(self.record_for_path(path) for path in paths) - @classmethod - def from_pattern(cls, path: str) -> "ProducedPathPatternSelector": - path_text = source_path_identity(path).as_posix() - return cls(path_text, PathPatternTemplateMatcher.from_pattern(path_text)) - - def matches(self, path_set: ProducedPathSet) -> bool: - return next(self.matching_tokens(path_set), None) is not None - - def matching_tokens(self, path_set: ProducedPathSet) -> Iterator[str]: - """Yield exact and template aliases through one matching policy.""" - tokens = path_set.tokens - if self.path in tokens: - yield self.path - if self.matcher is not None: - for token in tokens: - if token != self.path and self.matcher.matches(token): - yield token + def validate_input_records( + self, records: Sequence[ProducedOutputSemantics], + ) -> None: + """Validate address cardinality while retaining the already-selected cohort.""" + for record in records: + self.record_for_path(record.output_path) diff --git a/openhcs/core/steps/function_outputs.py b/openhcs/core/steps/function_outputs.py index 919d4acaa5..82eb17a7e6 100644 --- a/openhcs/core/steps/function_outputs.py +++ b/openhcs/core/steps/function_outputs.py @@ -5,10 +5,11 @@ import logging import time from abc import ABC, abstractmethod -from collections.abc import Callable, Mapping -from dataclasses import dataclass, replace +from collections.abc import Callable, Mapping, Sequence +from dataclasses import dataclass, field, replace from pathlib import Path -from typing import ClassVar +from types import MappingProxyType +from typing import ClassVar, TypeVar import numpy as np from metaclass_registry import ( @@ -52,14 +53,15 @@ OpenHCSPlaneAddress, SourceArtifactProjection, SourcePlaneProjection, + SourceProjection, SourceProjectionMetadataSerializer, - SourceProjectionSet, ) +from openhcs.core.steps.abstract import StepExecutionObservation from openhcs.core.steps.function_artifact_materialization import ( + MaterializedRuntimeArtifact, PersistentArtifactMaterializationTargetPlan, StreamingOnlyArtifactMaterializationTargetPlan, materialize_artifact_outputs, - runtime_artifact_materializations, ) from openhcs.core.steps.function_io import ( prepare_storage_image_payloads, @@ -67,9 +69,8 @@ zarr_output_batch_layout, ) from openhcs.core.steps.function_output_identity import ( - FunctionOutputIdentityAuthority, + FunctionOutputIdentity, FunctionOutputParserContext, - FunctionOutputPathAuthority, ) from openhcs.core.steps.function_output_manifest import ( ProducedOutputSemantics, @@ -83,7 +84,6 @@ from openhcs.core.virtual_workspace_metadata import ( METADATA_CONFIG, AtomicMetadataWriter, - OpenHCSMetadataSubdirectories, VirtualWorkspaceSourceProjectionEntries, ) from openhcs.microscopes.microscope_interfaces import FilenameParser @@ -108,79 +108,64 @@ def stream_payload_summary(payload: StreamPayload) -> str: return f"{summary} min={data.min()} max={data.max()}" -class ProducedMemoryPathsAuthority: - """Resolve absolute memory paths produced by the current step execution.""" - - @classmethod - def paths( - cls, - context: ProcessingContext, - plan: CompiledStepPlan, - ) -> list[str]: - return [ - cls.memory_path(record, plan) - for record in step_output_manifest(context).produced_records_for(plan) - if record.is_image_payload - ] - - @staticmethod - def memory_path( - record: ProducedOutputSemantics, - plan: CompiledStepPlan, - ) -> str: - path = Path(record.output_path) - if path.is_absolute(): - return str(path) - return str(plan.output_dir / record.relative_output_path) - - def finalize_function_step_outputs( context: ProcessingContext, plan: CompiledStepPlan, -) -> None: - """Persist images, streams, metadata, and non-image artifacts for one step.""" +) -> StepExecutionObservation: + """Save and publish one step's actual outputs before releasing their payloads.""" if not RuntimeProfileLogger.enabled(): MemoryOutputWriter.write_if_needed(context, plan) MaterializedImageOutputWriter.write_if_needed(context, plan) StreamOutputsAuthority.stream_outputs(context, plan) - RuntimeArtifactMaterializationAuthority.materialize(context, plan) - OpenHCSMetadataWriter.write(context, plan) - return - - _profile_finalization_phase( - "finalize_memory_outputs", - lambda: MemoryOutputWriter.write_if_needed(context, plan), - plan, - ) - _profile_finalization_phase( - "finalize_materialized_images", - lambda: MaterializedImageOutputWriter.write_if_needed(context, plan), - plan, - ) - _profile_finalization_phase( - "finalize_stream_outputs", - lambda: StreamOutputsAuthority.stream_outputs(context, plan), - plan, - ) - _profile_finalization_phase( - "finalize_runtime_artifacts", - lambda: RuntimeArtifactMaterializationAuthority.materialize(context, plan), - plan, - ) - _profile_finalization_phase( - "finalize_openhcs_metadata", - lambda: OpenHCSMetadataWriter.write(context, plan), - plan, + materializations = RuntimeArtifactMaterializationAuthority.materialize( + context, plan + ) + OpenHCSMetadataWriter.write( + context, plan, artifact_materializations=materializations + ) + else: + _profile_finalization_phase( + "finalize_memory_outputs", + lambda: MemoryOutputWriter.write_if_needed(context, plan), + plan, + ) + _profile_finalization_phase( + "finalize_materialized_images", + lambda: MaterializedImageOutputWriter.write_if_needed(context, plan), + plan, + ) + _profile_finalization_phase( + "finalize_stream_outputs", + lambda: StreamOutputsAuthority.stream_outputs(context, plan), + plan, + ) + materializations = _profile_finalization_phase( + "finalize_runtime_artifacts", + lambda: RuntimeArtifactMaterializationAuthority.materialize(context, plan), + plan, + ) + _profile_finalization_phase( + "finalize_openhcs_metadata", + lambda: OpenHCSMetadataWriter.write( + context, plan, artifact_materializations=materializations + ), + plan, + ) + return StepExecutionObservation.combine( + item.observation(plan, context) for item in materializations ) +_FinalizationResult = TypeVar("_FinalizationResult") + + def _profile_finalization_phase( label: str, - operation: Callable[[], None], + operation: Callable[[], _FinalizationResult], plan: CompiledStepPlan, -) -> None: +) -> _FinalizationResult: started_at = time.perf_counter() - operation() + result = operation() RuntimeProfileLogger.log( logger, label, @@ -189,6 +174,7 @@ def _profile_finalization_phase( step_name=plan.step_name, axis_id=plan.axis_id, ) + return result class MemoryOutputWriter: @@ -203,39 +189,48 @@ def write_if_needed( if plan.write_backend == Backend.MEMORY.value: return - produced_outputs = tuple( - record - for record in step_output_manifest(context).produced_records_for(plan) - if record.is_image_payload - ) + produced_outputs = step_output_manifest(context).image_records_for(plan) if not produced_outputs: return - memory_paths = [ - ProducedMemoryPathsAuthority.memory_path(record, plan) - for record in produced_outputs - ] + memory_paths = [record.memory_path(plan) for record in produced_outputs] memory_data = context.filemanager.load_batch( memory_paths, Backend.MEMORY.value, ) + output_paths = [ + record.path_under(plan.output_dir) + for record in produced_outputs + ] parser_context = FunctionOutputParserContext.from_processing_context(context) row, col = parser_context.parser.extract_component_coordinates(plan.axis_id) context.filemanager.ensure_directory( plan.output_dir, plan.write_backend, ) - context.filemanager.save_batch( - cls.payloads(memory_data, memory_paths, plan), - memory_paths, - plan.write_backend, - chunk_name=plan.axis_id, - zarr_config=plan.zarr_config, - batch_layout=zarr_output_batch_layout(produced_outputs), - row=row, - col=col, - parser_name=parser_context.parser_name, - microscope_type=parser_context.microscope_type, + payloads = cls.payloads(memory_data, output_paths, plan) + batches = ( + ImageFileFormat.storage_write_batches( + memory_data, output_paths, context.tiff_config + ) + if plan.write_backend == Backend.DISK.value + else ((tuple(range(len(output_paths))), None),) ) + for indices, config in batches: + context.filemanager.save_batch( + [payloads[index] for index in indices], + [output_paths[index] for index in indices], + plan.write_backend, + chunk_name=plan.axis_id, + zarr_config=plan.zarr_config, + batch_layout=zarr_output_batch_layout( + tuple(produced_outputs[index] for index in indices) + ), + row=row, + col=col, + parser_name=parser_context.parser_name, + microscope_type=parser_context.microscope_type, + **({"tiff_config": config} if config is not None else {}), + ) @staticmethod def payloads( @@ -262,13 +257,9 @@ def write_if_needed( if materialized_output is None: return - produced_outputs = tuple( - record - for record in step_output_manifest(context).produced_records_for(plan) - if record.is_image_payload - ) + produced_outputs = step_output_manifest(context).image_records_for(plan) memory_paths = [ - ProducedMemoryPathsAuthority.memory_path(record, plan) + record.memory_path(plan) for record in produced_outputs ] if not produced_outputs: @@ -303,91 +294,6 @@ def write_if_needed( ) -@dataclass(frozen=True, slots=True) -class StreamOutputProjectionRequest: - """Nominal source of truth for projecting produced outputs into viewer streams.""" - - parser: FilenameParser - payloads: tuple[StreamPayload, ...] - paths: tuple[str, ...] - produced_outputs: tuple[ProducedOutputSemantics, ...] - - @classmethod - def from_sequences( - cls, - *, - parser: FilenameParser, - payloads: list[StreamPayload], - paths: list[str], - produced_outputs: tuple[ProducedOutputSemantics, ...], - ) -> StreamOutputProjectionRequest: - return cls( - parser=parser, - payloads=tuple(payloads), - paths=tuple(paths), - produced_outputs=produced_outputs, - ) - - def __post_init__(self) -> None: - if len(self.payloads) != len(self.paths): - raise ValueError( - "Streaming payload/path cardinality mismatch: " - f"{len(self.payloads)} payloads for {len(self.paths)} paths." - ) - if len(self.payloads) != len(self.produced_outputs): - raise ValueError( - "Streaming payload/output-record cardinality mismatch: " - f"{len(self.payloads)} payloads for " - f"{len(self.produced_outputs)} output records." - ) - if not self.produced_outputs: - raise ValueError("Streaming requires at least one produced output record.") - - def require_single_projection(self) -> tuple[str, ...]: - projection = self.produced_outputs[0].producer_identity.route_parts() - for produced_output in self.produced_outputs[1:]: - if produced_output.producer_identity.route_parts() != projection: - raise ValueError( - "A viewer stream batch cannot mix producer projections." - ) - return projection - - def runtime_projection_request( - self, - payload: StreamPayload, - path: str, - produced_output: ProducedOutputSemantics, - ) -> RuntimeProjectionSourceIdentityRequest: - return RuntimeProjectionSourceIdentityRequest( - value=produced_output.contextualize_image_payload(payload), - source_description=path, - ) - - def for_projection( - self, - projection: tuple[str, ...], - ) -> StreamOutputProjectionRequest: - payloads: list[StreamPayload] = [] - paths: list[str] = [] - produced_outputs: list[ProducedOutputSemantics] = [] - for payload, path, produced_output in zip( - self.payloads, - self.paths, - self.produced_outputs, - strict=True, - ): - if produced_output.producer_identity.route_parts() == projection: - payloads.append(payload) - paths.append(path) - produced_outputs.append(produced_output) - return StreamOutputProjectionRequest.from_sequences( - parser=self.parser, - payloads=payloads, - paths=paths, - produced_outputs=tuple(produced_outputs), - ) - - @dataclass(frozen=True, slots=True) class StreamOutputItem: """One projected image payload and its stream-visible output path.""" @@ -416,23 +322,55 @@ class StreamOutputBatch: items: tuple[StreamOutputItem, ...] producer: ViewerStreamProducer + @staticmethod + def _validate_inputs( + payloads: Sequence[StreamPayload], + paths: Sequence[str], + produced_outputs: tuple[ProducedOutputSemantics, ...], + ) -> None: + if len(payloads) != len(paths): + raise ValueError( + "Streaming payload/path cardinality mismatch: " + f"{len(payloads)} payloads for {len(paths)} paths." + ) + if len(payloads) != len(produced_outputs): + raise ValueError( + "Streaming payload/output-record cardinality mismatch: " + f"{len(payloads)} payloads for " + f"{len(produced_outputs)} output records." + ) + if not produced_outputs: + raise ValueError("Streaming requires at least one produced output record.") + @classmethod def from_projection( cls, - request: StreamOutputProjectionRequest, + *, + parser: FilenameParser, + payloads: Sequence[StreamPayload], + paths: Sequence[str], + produced_outputs: tuple[ProducedOutputSemantics, ...], ) -> StreamOutputBatch: - request.require_single_projection() + payloads = tuple(payloads) + paths = tuple(paths) + cls._validate_inputs(payloads, paths, produced_outputs) + projection = produced_outputs[0].producer_identity.route_parts() + for produced_output in produced_outputs[1:]: + if produced_output.producer_identity.route_parts() != projection: + raise ValueError( + "A viewer stream batch cannot mix producer projections." + ) items: list[StreamOutputItem] = [] for payload, path, produced_output in zip( - request.payloads, - request.paths, - request.produced_outputs, - strict=True, + payloads, paths, produced_outputs, strict=True, ): projected_items = tuple( cls.project_item( - request.runtime_projection_request(payload, path, produced_output) + RuntimeProjectionSourceIdentityRequest( + value=produced_output.contextualize_image_payload(payload), + source_description=path, + ) ) ) for projected_item in projected_items: @@ -440,7 +378,7 @@ def from_projection( projected_item, produced_path=path, produced_output=produced_output, - parser=request.parser, + parser=parser, projected_item_count=len(projected_items), ) source_metadata = projected_item.require_source_component_metadata() @@ -468,18 +406,33 @@ def from_projection( @classmethod def from_projection_groups( cls, - request: StreamOutputProjectionRequest, + *, + parser: FilenameParser, + payloads: Sequence[StreamPayload], + paths: Sequence[str], + produced_outputs: tuple[ProducedOutputSemantics, ...], ) -> tuple[StreamOutputBatch, ...]: - projections = tuple( - dict.fromkeys( - produced_output.producer_identity.route_parts() - for produced_output in request.produced_outputs + payloads = tuple(payloads) + paths = tuple(paths) + cls._validate_inputs(payloads, paths, produced_outputs) + projections: dict[ + tuple[str, ...], list[tuple[StreamPayload, str, ProducedOutputSemantics]] + ] = {} + for payload, path, produced_output in zip( + payloads, paths, produced_outputs, strict=True, + ): + projection = produced_output.producer_identity.route_parts() + projections.setdefault(projection, []).append( + (payload, path, produced_output) ) - ) - return tuple( - cls.from_projection(request.for_projection(projection)) - for projection in projections + cls.from_projection( + parser=parser, + payloads=tuple(payload for payload, _path, _record in members), + paths=tuple(path for _payload, path, _record in members), + produced_outputs=tuple(record for _payload, _path, record in members), + ) + for members in projections.values() ) @property @@ -554,7 +507,7 @@ def stream_path_for_projected_item( """Return the stream-visible path for one projected payload item.""" if projected_item_count <= 1: return produced_path - identity = FunctionOutputIdentityAuthority.identity_from_metadata( + identity = FunctionOutputIdentity.from_metadata( parser, projected_item.metadata, fallback_identity_path=produced_path, @@ -565,10 +518,7 @@ def stream_path_for_projected_item( identity = identity.with_filename_qualifier( produced_output.filename_qualifier ) - filename = FunctionOutputPathAuthority.filename_for_identity( - parser, - identity, - ) + filename = identity.filename(parser) return str(Path(produced_path).parent / filename) @@ -594,13 +544,9 @@ def stream_outputs( context.axis_id, ) continue - produced_outputs = tuple( - record - for record in step_output_manifest(context).produced_records_for(plan) - if record.is_image_payload - ) + produced_outputs = step_output_manifest(context).image_records_for(plan) memory_paths = [ - ProducedMemoryPathsAuthority.memory_path(record, plan) + record.memory_path(plan) for record in produced_outputs ] if not memory_paths: @@ -624,12 +570,10 @@ def stream_outputs( ) ) stream_batches = StreamOutputBatch.from_projection_groups( - StreamOutputProjectionRequest.from_sequences( - parser=context.microscope_handler.parser, - payloads=streaming_payloads, - paths=list(streaming_paths), - produced_outputs=produced_outputs, - ) + parser=context.microscope_handler.parser, + payloads=streaming_payloads, + paths=streaming_paths, + produced_outputs=produced_outputs, ) stream_batches = tuple( stream_batch @@ -691,6 +635,9 @@ class OutputTarget(ABC, metaclass=AutoRegisterMeta): plate_root: str sub_dir: str results_dir: str | None + artifact_materializations: tuple[MaterializedRuntimeArtifact, ...] = field( + default=(), compare=False, hash=False, repr=False + ) @classmethod @abstractmethod @@ -719,17 +666,25 @@ def from_execution( @classmethod def for_execution( - cls, context: ProcessingContext, plan: CompiledStepPlan + cls, + context: ProcessingContext, + plan: CompiledStepPlan, + *, + artifact_materializations: tuple[MaterializedRuntimeArtifact, ...] = (), ) -> tuple[OpenHCSMetadataWriter.OutputTarget, ...]: return tuple( target for declaration in cls.__registry__.values() if (owner := declaration.from_execution(context, plan)) is not None - for target in owner.production_targets(context, plan) + for target in replace( + owner, artifact_materializations=artifact_materializations + ).production_targets(context, plan) ) def production_targets( - self, context: ProcessingContext, plan: CompiledStepPlan + self, + context: ProcessingContext, + plan: CompiledStepPlan, ) -> tuple[OpenHCSMetadataWriter.OutputTarget, ...]: """Project this declaration's exact storage destinations for the step.""" return (self,) @@ -747,27 +702,36 @@ def produced_records( return () def runtime_artifact_projection_paths( - self, context: ProcessingContext, plan: CompiledStepPlan + self, + context: ProcessingContext, + plan: CompiledStepPlan, + *, + produced_projections: Mapping[ + Path, tuple[ProducedOutputSemantics, SourceProjection] + ] = MappingProxyType({}), ) -> tuple[tuple[SourceArtifactProjection, str], ...]: """Publish artifacts persisted in this declared storage target.""" materialization = plan.runtime_artifact_materialization if materialization.persists_to_backend(self.backend): - return self.project_runtime_artifacts(context, plan) + return self.project_runtime_artifacts( + context, plan, produced_projections=produced_projections + ) return () - def contains_images(self, context: ProcessingContext) -> bool: - """Return whether the completed target contains image outputs.""" + def stored_output_paths(self, context: ProcessingContext) -> tuple[str, ...]: + """Return this declaration's outputs eligible for publication.""" + return tuple( + context.filemanager.list_image_files(self.output_dir, self.backend) + ) + + def contains_outputs(self, context: ProcessingContext) -> bool: + """Return whether this declared destination has publishable outputs.""" if context.filemanager is None: raise ValueError("OpenHCS metadata requires a file manager.") if not context.filemanager.is_dir(self.output_dir, self.backend): return False - return bool( - context.filemanager.list_image_files( - self.output_dir, - self.backend, - ) - ) + return bool(self.stored_output_paths(context)) def write( self, @@ -783,7 +747,7 @@ def write( raise ValueError( "Produced metadata requires declared component labels." ) - structured_metadata = self.produced_projection_metadata( + projection_entries = self.produced_projection_entries( context, produced_plan ) parser_context = FunctionOutputParserContext.from_processing_context( @@ -798,7 +762,7 @@ def write( AtomicMetadataWriter().publish_source_projection_metadata( METADATA_CONFIG.metadata_path(self.plate_root), self.sub_dir, - structured_metadata, + projection_entries, serializer=SourceProjectionMetadataSerializer(parser_context.parser), saved_image_paths=saved_image_paths, microscope_handler_name=parser_context.microscope_type, @@ -806,21 +770,26 @@ def write( component_labels=context.metadata_cache, backend=self.backend, is_main=self.is_main, - results_dir=(Path(self.results_dir).name if self.results_dir else None), + results_dir=( + str(Path(self.results_dir).relative_to(self.plate_root)) + if self.results_dir is not None else None + ), ) - def produced_projection_metadata( + def produced_projection_entries( self, context: ProcessingContext, plan: CompiledStepPlan | None, - ) -> Mapping[str, object] | None: + ) -> VirtualWorkspaceSourceProjectionEntries | None: """Project the current saved plan while its typed memory outputs remain.""" if plan is None: return None # Plate reconciliation must not reload cleaned step memory. if context.filemanager is None: raise ValueError("OpenHCS metadata requires a file manager.") target = type(self).from_plan(plan) - if target is None or self not in target.production_targets(context, plan): + if target is None or self not in replace( + target, artifact_materializations=self.artifact_materializations + ).production_targets(context, plan): raise ValueError( "Produced metadata plan does not own this output target." ) @@ -828,7 +797,7 @@ def produced_projection_metadata( payloads = ( context.filemanager.load_batch( [ - ProducedMemoryPathsAuthority.memory_path(record, plan) + record.memory_path(plan) for record in records ], Backend.MEMORY.value, @@ -837,10 +806,8 @@ def produced_projection_metadata( else () ) projection_paths = [] + produced_projections = {} declared_addresses: set[OpenHCSPlaneAddress] = set() - parser_context = FunctionOutputParserContext.from_processing_context( - context - ) for record, payload in zip(records, payloads, strict=True): destination = record.path_under(self.output_dir) virtual_path = str(Path(destination).relative_to(self.plate_root)) @@ -849,13 +816,32 @@ def produced_projection_metadata( destination=destination, payload=payload, ) - source_metadata = dict( - record.component_metadata(metadata.source_component_metadata) + source_metadata = record.source_metadata_for_projection( + metadata, destination ) - metadata.source_voxel_spacing.merge_into( - source_metadata, path=destination + address = ( + None if metadata.persists_whole_image() + else OpenHCSPlaneAddress.from_complete_source_metadata(source_metadata) ) - address = record.filename_address + if address is None: + projection_paths.append( + ( + SourceArtifactProjection( + address=None, + ref=SourcePixelRef(self.backend, virtual_path), + source_alias=record.producer_identity.output_key, + artifact_kind=ImageArtifactType, + source_metadata=source_metadata, + image_metadata=metadata, + execution_scope=record.execution_scope(plan), + ), + virtual_path, + ) + ) + produced_projections[Path(destination)] = ( + record, projection_paths[-1][0] + ) + continue if address not in declared_addresses: declared_addresses.add(address) projection_paths.append( @@ -863,12 +849,16 @@ def produced_projection_metadata( SourcePlaneProjection( address=address, ref=SourcePixelRef(self.backend, virtual_path), + source_alias=record.output_context.persisted_source_alias, source_metadata=source_metadata, image_metadata=metadata, ), virtual_path, ) ) + produced_projections[Path(destination)] = ( + record, projection_paths[-1][0] + ) continue projection_paths.append( ( @@ -883,43 +873,35 @@ def produced_projection_metadata( virtual_path, ) ) + produced_projections[Path(destination)] = ( + record, projection_paths[-1][0] + ) projection_paths.extend( - self.runtime_artifact_projection_paths(context, plan) + self.runtime_artifact_projection_paths( + context, plan, produced_projections=produced_projections + ) ) if not projection_paths: return None - projection_set = SourceProjectionSet( - tuple(projection for projection, _path in projection_paths) - ) - return SourceProjectionMetadataSerializer( - parser_context.parser - ).metadata_dict( - projection_set, - microscope_handler_name=parser_context.microscope_type, - source_filename_parser_name=parser_context.parser_name, - grid_dimensions=[], - pixel_size=1.0, - projection_paths=tuple(projection_paths), + return VirtualWorkspaceSourceProjectionEntries.from_projection_paths( + projection_paths ) def project_runtime_artifacts( self, context: ProcessingContext, plan: CompiledStepPlan, + *, + produced_projections: Mapping[ + Path, tuple[ProducedOutputSemantics, SourceProjection] + ] = MappingProxyType({}), ) -> tuple[tuple[SourceArtifactProjection, str], ...]: """Project persisted image artifacts into the target source authority.""" projection_paths = [] - for materialization in runtime_artifact_materializations(plan, context): - if ( - not materialization.spec.participates_in_persistent_materialization() - ): - continue - for output in materialization.outputs( - plan, - context, - output_path_filter=ImageFileFormat.is_image_path, - ): + for saved_artifact in self.artifact_materializations: + materialization = saved_artifact.materialization + for output in saved_artifact.outputs_for_backend(self.backend): if not ImageFileFormat.is_image_path(output.path) or Path( output.path ).parent != Path(self.output_dir): @@ -942,6 +924,26 @@ def project_runtime_artifacts( metadata ) ) + produced = produced_projections.get(Path(destination)) + if produced is not None: + record, projection = produced + if record.owns_persisted_artifact( + materialization.output_plan, destination, self.output_dir + ): + if ( + projection.address != address + or projection.image_metadata != metadata + or ( + address is None + and projection.execution_scope + != materialization.record.key.scope + ) + ): + raise ValueError( + "Conflicting metadata for persisted image " + f"occurrence {destination!r}." + ) + continue source_metadata = metadata.source_component_metadata or {} persisted_source_metadata = dict(source_metadata) metadata.source_voxel_spacing.merge_into( @@ -1005,16 +1007,20 @@ def write( cls, context: ProcessingContext, plan: CompiledStepPlan, + *, + artifact_materializations: tuple[MaterializedRuntimeArtifact, ...] = (), ) -> None: - for target in cls.OutputTarget.for_execution(context, plan): + for target in cls.OutputTarget.for_execution( + context, plan, artifact_materializations=artifact_materializations + ): if not plan.create_openhcs_metadata: - structured_metadata = target.produced_projection_metadata(context, plan) - if structured_metadata is None: + projection_entries = target.produced_projection_entries(context, plan) + if projection_entries is None: continue AtomicMetadataWriter().merge_source_projection_metadata( METADATA_CONFIG.metadata_path(target.plate_root), target.sub_dir, - structured_metadata, + projection_entries, ) else: target.write(context, produced_plan=plan) @@ -1038,7 +1044,7 @@ def finalize_completed_plate( for owner, context in target_contexts.items(): for target in owner.reconciliation_targets(context): - if target.contains_images(context): + if target.contains_outputs(context): target.write(context) @@ -1048,11 +1054,7 @@ class ProducedImageMetadataCapability: def produced_records( self, context: ProcessingContext, plan: CompiledStepPlan ) -> tuple[ProducedOutputSemantics, ...]: - return tuple( - record - for record in step_output_manifest(context).produced_records_for(plan) - if record.is_image_payload - ) + return step_output_manifest(context).image_records_for(plan) class PrimaryImageMetadataTarget( @@ -1066,7 +1068,7 @@ class PrimaryImageMetadataTarget( def from_execution( cls, context: ProcessingContext, plan: CompiledStepPlan ) -> PrimaryImageMetadataTarget | None: - if not ProducedMemoryPathsAuthority.paths(context, plan): + if not step_output_manifest(context).image_records_for(plan): return None return cls.from_plan(plan) @@ -1121,53 +1123,55 @@ def from_plan( class RuntimeArtifactMetadataTarget(OpenHCSMetadataWriter.OutputTarget): - """Image artifacts persist independently of main-flow image/checkpoint storage.""" + """Saved artifacts own result destinations independently of image storage.""" + + def stored_output_paths(self, context: ProcessingContext) -> tuple[str, ...]: + """Include every saved format in this declared result destination.""" + return tuple(context.filemanager.list_files(self.output_dir, self.backend)) def production_targets( - self, context: ProcessingContext, plan: CompiledStepPlan + self, + context: ProcessingContext, + plan: CompiledStepPlan, ) -> tuple[RuntimeArtifactMetadataTarget, ...]: """Derive directories from the same writer outputs used to save artifacts.""" directories = dict.fromkeys( Path(output.path).parent - for materialization in runtime_artifact_materializations(plan, context) - if materialization.spec.participates_in_persistent_materialization() - for output in materialization.outputs( - plan, context, output_path_filter=ImageFileFormat.is_image_path - ) - if ImageFileFormat.is_image_path(output.path) + for materialization in self.artifact_materializations + for output in materialization.outputs_for_backend(self.backend) ) return tuple( target for directory in directories for target in (self.for_directory(directory),) - if target.contains_images(context) + if target.contains_outputs(context) ) def reconciliation_targets( self, context: ProcessingContext ) -> tuple[RuntimeArtifactMetadataTarget, ...]: """Use durable typed projections, without reloading cleaned artifact values.""" - subdirectories = OpenHCSMetadataSubdirectories.from_path( - METADATA_CONFIG.metadata_path(self.plate_root) - ) - directories = tuple( - Path(self.plate_root) / Path(path).parent - for _name, subdirectory in subdirectories.items() - for path, projection in VirtualWorkspaceSourceProjectionEntries.from_subdirectory( - subdirectory - ).entries.items() - if isinstance(projection, SourceArtifactProjection) - and projection.ref.backend == self.backend - ) + from openhcs.microscopes.openhcs import OpenHCSMetadataHandler + + directories = OpenHCSMetadataHandler( + context.filemanager + ).reconciliation_directories(self.plate_root, self.backend) return tuple( self.for_directory(directory) - for directory in dict.fromkeys((self.output_dir, *directories)) + for directory in dict.fromkeys( + ( + self.output_dir, + *directories, + ) + ) ) def for_directory(self, directory: Path) -> RuntimeArtifactMetadataTarget: """Retain the compiled plate/backend while projecting one declared directory.""" sub_dir = directory.relative_to(self.plate_root) - return replace(self, output_dir=directory, sub_dir=str(sub_dir)) + return replace( + self, output_dir=directory, sub_dir=str(sub_dir), results_dir=str(directory) + ) @classmethod def from_plan(cls, plan: CompiledStepPlan) -> RuntimeArtifactMetadataTarget | None: @@ -1181,7 +1185,7 @@ def from_plan(cls, plan: CompiledStepPlan) -> RuntimeArtifactMetadataTarget | No backend=materialization.require_persistent_backend(), plate_root=plate_root, sub_dir=str(output_dir.relative_to(plate_root)), - results_dir=None, + results_dir=str(output_dir), ) @@ -1193,27 +1197,28 @@ def materialize( cls, context: ProcessingContext, plan: CompiledStepPlan, - ) -> None: + ) -> tuple[MaterializedRuntimeArtifact, ...]: if not plan.artifact_outputs: - return + return () materialization_plan = plan.runtime_artifact_materialization has_persistent_target = materialization_plan.has_persistent_target has_streaming_target = bool(plan.streaming_configs) if not has_persistent_target and not has_streaming_target: logger.info("Skipping runtime artifact materialization and streaming") - return + return () logger.info( "Starting materialization for %s artifact outputs", len(plan.artifact_outputs), ) - materialize_artifact_outputs( + materializations = materialize_artifact_outputs( context.filemanager, plan, cls.target_plan(materialization_plan), context, ) logger.info("Completed artifact materialization") + return materializations @staticmethod def target_plan( diff --git a/openhcs/core/steps/function_runtime.py b/openhcs/core/steps/function_runtime.py index 7a48a68df8..15446adc40 100644 --- a/openhcs/core/steps/function_runtime.py +++ b/openhcs/core/steps/function_runtime.py @@ -4,46 +4,34 @@ execution. FunctionStep remains responsible for step-level orchestration. """ -from abc import ABC, abstractmethod from functools import singledispatch import logging import os import time -from collections.abc import Sequence as SequenceABC -from dataclasses import dataclass, field, replace -from threading import Lock +from dataclasses import dataclass, replace from pathlib import Path from types import MappingProxyType from typing import ( Callable, - ClassVar, Generic, - Iterator, Mapping, Sequence, TypeVar, cast, ) -from metaclass_registry import AutoRegisterMeta import numpy as np -from openhcs.constants.constants import AllComponents, Backend, VariableComponents +from openhcs.constants.constants import AllComponents, Backend from openhcs.core.artifacts import ( ArtifactInputPlan, ArtifactOutputPlan, NoMainFlowOutput, - ArtifactType, - ArtifactTypeStrategyMatchMixin, ImageArtifactType, - MeasurementsArtifactType, - ObjectLabelsArtifactType, - SpatialGraphArtifactType, ArtifactSpecRef, ) from openhcs.core.callable_contract import ( - CallableRuntimeCacheKey, - prepare_processing_callable, + ImagePayloadConsumption, ) from openhcs.core.component_group_scope import ( ComponentGroupScope, @@ -51,7 +39,6 @@ RuntimeFixedComponentValues, ) from openhcs.core.component_set import ComponentSet -from openhcs.core.projected_image_output import SourceProjectedImageOutput from openhcs.core.context.processing_context import ProcessingContext from openhcs.core.debug import ( DebugCursor, @@ -74,24 +61,14 @@ from openhcs.core.aligned_image_payload import ( AlignedImageStack, AlignedImageSliceContext, - ImagePayloadBundleContext, + ImagePayloadStackComposition, ImageOutputBundle, - flatten_aligned_image_payload_slices, - stack_image_payload_context, - stack_image_payload_context_from_metadata, unstack_image_payload_context, ) from openhcs.core.memory import ( - MemoryType, convert_memory, - stack_runtime_slices, unstack_runtime_slices, ) -from openhcs.core.measurement_row_materialization import ( - MeasurementRowOwnership, - measurement_rows_with_source_provenance, -) -from openhcs.core.process_local_cache import IdentityBoundProcessCache from openhcs.core.runtime_stores import ( RuntimeArtifactInput, RuntimeArtifactLocation, @@ -109,12 +86,11 @@ RuntimeSliceAlignedValues, ) from openhcs.core.runtime_slice_projection import ( + RuntimeSliceProjection, RuntimeSliceProjectionDeclarationError, ) -from openhcs.core.source_image_semantics import apply_source_binding_payload from openhcs.core.source_image_provenance import ( SourceImageIdentity, - SourceImageProvenance, ) from openhcs.core.source_workspace_projection import ( VirtualWorkspacePathLookup, @@ -125,7 +101,8 @@ from openhcs.core.source_binding_selection import ( SourceBindingCandidateMatcher, SourceBindingMatchedImageSet, - SourceBindingRuntimeContextRequest, + SourceFileUniverse, + SourceUniverseRequest, SourcePatternResolutionContext, ) from openhcs.core.source_matching import ( @@ -136,44 +113,30 @@ from openhcs.core.source_bindings import ( CompiledSourceBindingPlan, SOURCE_BINDING_ALIAS_METADATA_FIELD, - SourceBindingRuntimeContext, SourceProjectionRole, ) from openhcs.core.runtime_image_values import ( ImagePayloadMetadata, ImagePayloadMetadataCarrier, - ImagePayloadMetadataCompositionMode, image_payload_data, image_payload_mask, image_payload_metadata, - image_payload_slice_context, - preserve_declared_image_payload_axis, with_image_payload_data, ) from openhcs.core.runtime_image_loading import ImagePayloadSourceMetadataContext from openhcs.core.runtime_array_values import RuntimeArrayData -from openhcs.core.runtime_measurements import MeasurementSubject, MeasurementTable +from openhcs.core.runtime_measurements import MeasurementTable from openhcs.core.runtime_spatial_graph import SpatialGraph from openhcs.core.runtime_object_labels import ( ObjectLabelSet, ObjectLabelValue, - object_label_dense_array, -) -from openhcs.core.runtime_object_label_building import ( - SourceImageObjectLabelBuildRequest, ) from openhcs.core.runtime_tabular_values import ColumnarRows -from openhcs.core.registry_strategies import ( - MostDerivedContextStrategyMixin, - NominalTypeKeyedStrategyMixin, -) from openhcs.core.runtime_plane_projection import ( RuntimePlaneAxis, RuntimePlaneAxisProjector, - RuntimePlaneAxisValueProjection, RuntimePlaneProjection, ) -from openhcs.core.runtime_slice_projection import RuntimeSliceProjection from openhcs.core.step_dependencies import StepInputDependencyKind from openhcs.core.steps.function_output_manifest import ( NoStepOutputManifestMatch, @@ -182,8 +145,6 @@ ) from openhcs.core.steps.function_output_identity import ( FunctionOutputIdentity, - FunctionOutputIdentityAuthority, - FunctionOutputPathAuthority, FunctionOutputPathRequest, ) from openhcs.core.compiled_step_plan import CompiledStepPlan @@ -224,55 +185,6 @@ EMPTY_ARTIFACT_PLANS: ArtifactOutputPlans = MappingProxyType({}) -class FunctionInvocationCallableCache(IdentityBoundProcessCache): - """Bound resolved callables to their exact compiled contract owners.""" - - registry_key = "function_invocation_callable" - - -class FunctionInvocationCallableResolver: - """Process-local resolver for compiled invocation callables. - - The compiler stores picklable ``FunctionReference`` objects in compiled - invocations. Runtime execution needs actual callables. Resolving them during - compiler preparation lets fork workers inherit the resolved callable cache, - while spawn workers still resolve lazily in their own process. - """ - - _lock = Lock() - - @classmethod - def prepare(cls, invocation: CompiledFunctionInvocation) -> None: - """Resolve and cache one invocation callable before timed execution.""" - cls.resolve(invocation) - prepare_processing_callable( - invocation.contract.resolve_canonical_raw_callable() - ) - - @classmethod - def resolve(cls, invocation: CompiledFunctionInvocation) -> Callable: - """Return the callable for a compiled invocation.""" - cache = FunctionInvocationCallableCache.process_cache() - with cls._lock: - cached = cache.get_bound(invocation.contract) - if cached is not None: - return cached - - resolved = invocation.contract.resolve_runtime_callable() - - with cls._lock: - cache.put_bound(invocation.contract, resolved) - return resolved - - @classmethod - def cache_key( - cls, - invocation: CompiledFunctionInvocation, - ) -> CallableRuntimeCacheKey: - """Return process-local callable cache key for one compiled invocation.""" - return invocation.contract.runtime_callable_cache_identity() - - class RuntimeProfileSink: """Runtime-profile output authority backed by explicit environment settings.""" @@ -306,458 +218,6 @@ def record( handle.write(f"RUNTIME_PROFILE {label} {seconds:.6f}s {field_text}\n") -class FunctionOutputContextStrategy( - ArtifactTypeStrategyMatchMixin, - MostDerivedContextStrategyMixin[type[ArtifactType]], - ABC, -): - """Registered normalization for function outputs before chaining or storage.""" - - artifact_type: ClassVar[type[ArtifactType] | None] = None - - @classmethod - def for_output_plan( - cls, - output_plan: ArtifactOutputPlan | None, - ) -> "FunctionOutputContextStrategy": - output_kind = ( - ImageArtifactType if output_plan is None else output_plan.artifact_type - ) - return cast( - FunctionOutputContextStrategy, - cls.for_context(output_kind), - ) - - @abstractmethod - def contextualize( - self, - source_payload: RuntimePayload, - output_value: RuntimePayload, - output_plan: ArtifactOutputPlan | None, - plane_projection: RuntimePlaneAxisValueProjection | None, - ) -> FunctionOutputContextualizedValue: - """Return output with source context preserved where semantics allow it.""" - - def contextualize_from_projector( - self, - source_payload: RuntimePayload, - output_value: RuntimePayload, - output_plan: ArtifactOutputPlan | None, - plane_projector: RuntimePlaneAxisProjector | None, - ) -> FunctionOutputContextualizedValue: - """Resolve plane projection only after the artifact strategy is selected.""" - - plane_projection = ( - None - if plane_projector is None - else preserve_declared_image_payload_axis( - plane_projector, - output_value, - source_payload=source_payload, - ) - ) - if ( - plane_projection is None - and output_plan is not None - and output_plan.variable_components - ): - if plane_projector is None: - if not self.output_owns_source_context( - source_payload, - output_value, - output_plan, - None, - ): - raise ValueError( - f"Artifact output {output_plan.ref()!r} preserves variable " - f"components {output_plan.variable_components!r} but the " - "runtime invocation supplies no plane projector." - ) - return output_value - plane_projection = RuntimePlaneAxisValueProjection.require_from_projector( - plane_projector, - RuntimePlaneAxis.RUNTIME_SLICE, - ) - return self.contextualize( - source_payload, - output_value, - output_plan, - plane_projection, - ) - - @staticmethod - def output_owns_source_context( - source_payload: RuntimePayload, - output_value: RuntimePayload, - output_plan: ArtifactOutputPlan | None, - plane_projection: RuntimePlaneAxisValueProjection | None, - ) -> bool: - """Return whether this artifact value already owns complete context.""" - - del source_payload, output_value, output_plan, plane_projection - return False - - -class UnchangedFunctionOutputContextStrategy(FunctionOutputContextStrategy): - """Leave context-free artifact families outside image-axis projection.""" - - artifact_type = ArtifactType - - def contextualize_from_projector( - self, - source_payload: RuntimePayload, - output_value: RuntimePayload, - output_plan: ArtifactOutputPlan | None, - plane_projector: RuntimePlaneAxisProjector | None, - ) -> FunctionOutputContextualizedValue: - """Keep declared side-channel values outside image-axis projection.""" - - del source_payload, output_plan, plane_projector - return output_value - - def contextualize( - self, - source_payload: RuntimePayload, - output_value: RuntimePayload, - output_plan: ArtifactOutputPlan | None, - plane_projection: RuntimePlaneAxisValueProjection | None, - ) -> FunctionOutputContextualizedValue: - del source_payload, output_plan, plane_projection - return output_value - - -class ProjectedFunctionOutputContextStrategy( - UnchangedFunctionOutputContextStrategy, -): - """Restore source-plane projection for contextual artifact families.""" - - @abstractmethod - def contextualize( - self, - source_payload: RuntimePayload, - output_value: RuntimePayload, - output_plan: ArtifactOutputPlan | None, - plane_projection: RuntimePlaneAxisValueProjection | None, - ) -> FunctionOutputContextualizedValue: - """Contextualize one projected artifact family.""" - - def contextualize_from_projector( - self, - source_payload: RuntimePayload, - output_value: RuntimePayload, - output_plan: ArtifactOutputPlan | None, - plane_projector: RuntimePlaneAxisProjector | None, - ) -> FunctionOutputContextualizedValue: - return FunctionOutputContextStrategy.contextualize_from_projector( - self, - source_payload, - output_value, - output_plan, - plane_projector, - ) - - -class ImageFunctionOutputContextStrategy(ProjectedFunctionOutputContextStrategy): - """Preserve source-image metadata for image outputs derived from the main input.""" - - artifact_type = ImageArtifactType - - @staticmethod - def output_owns_source_context( - source_payload: RuntimePayload, - output_value: RuntimePayload, - output_plan: ArtifactOutputPlan | None, - plane_projection: RuntimePlaneAxisValueProjection | None, - ) -> bool: - """Return whether an image result already carries complete source identity.""" - - if not isinstance(output_value, AlignedImageStack) and not ( - image_payload_metadata(output_value).has_complete_source_identity( - output_value, - plane_projection, - ) - ): - return False - output_surfaces = flatten_aligned_image_payload_slices(output_value) - if not all( - image_payload_metadata(output_surface).has_complete_source_identity( - output_surface - ) - for output_surface in output_surfaces - ): - return False - if output_plan is None: - return True - source_surfaces = flatten_aligned_image_payload_slices(source_payload) - return len(output_surfaces) == len(source_surfaces) and all( - image_payload_metadata( - output_surface - ).source_provenance.represented_source_identities - == image_payload_metadata( - source_surface - ).source_provenance.represented_source_identities - for source_surface, output_surface in zip( - source_surfaces, - output_surfaces, - strict=True, - ) - ) - - def contextualize( - self, - source_payload: RuntimePayload, - output_value: RuntimePayload, - output_plan: ArtifactOutputPlan | None, - plane_projection: RuntimePlaneAxisValueProjection | None, - ) -> FunctionOutputContextualizedValue: - if isinstance(output_value, SourceProjectedImageOutput): - return output_value.resolve_source_context(source_payload, plane_projection) - if isinstance(output_value, RuntimeSliceAlignedValueSet): - if ( - plane_projection is None - or plane_projection.axis is not RuntimePlaneAxis.RUNTIME_SLICE - ): - raise ValueError( - "Runtime-slice-aligned image output requires an exact runtime " - "slice projection." - ) - if plane_projection.axis_size != output_value.slice_count: - raise ValueError( - "Runtime-slice-aligned image output count must exactly match " - "the declared runtime plane axis: " - f"{output_value.slice_count} != {plane_projection.axis_size}." - ) - contextualized_slices = [] - for slice_index in range(output_value.slice_count): - item = output_value.value_for_slice(slice_index) - contextualized_slices.append( - self.contextualize( - RuntimeSliceProjection.value_for_slice( - source_payload, - RuntimePlaneAxisValueProjection.from_selected_plane( - axis=plane_projection.axis, - plane_index=slice_index, - axis_size=plane_projection.axis_size, - ), - ), - item.data if isinstance(item, RuntimeValue) else item, - output_plan, - None, - ) - ) - return RuntimeSliceAlignedValues(tuple(contextualized_slices)) - source_ref = ( - None if output_plan is None else output_plan.source_context_source() - ) - if ( - output_plan is not None - and output_plan.variable_components - and plane_projection is not None - and plane_projection.plane_index is None - ): - output_metadata = image_payload_metadata(output_value) - if ( - output_metadata.plane_axis is None - and output_metadata.source_provenance.source_plane_count - == plane_projection.axis_size - and plane_projection.dense_shape_carries_axis( - np.shape(image_payload_data(output_value)) - ) - ): - output_value = output_metadata.replace_fields( - plane_axis=plane_projection.axis, - ).attach_to(output_value) - if output_plan is not None and not output_plan.variable_components: - output_metadata = image_payload_metadata(output_value) - if output_metadata.plane_axis is RuntimePlaneAxis.RUNTIME_SLICE: - output_value = RuntimeSliceProjection.value_for_singleton_slice( - output_value, - source_description=f"Image output {output_plan.ref()!r}", - ) - source_metadata = image_payload_metadata(source_payload) - if source_metadata.plane_axis is RuntimePlaneAxis.RUNTIME_SLICE: - if source_ref is None: - raise ValueError( - f"Image output {output_plan.ref()!r} consumes a runtime " - "stack without a declared source-context relation." - ) - collapsed_metadata = source_metadata.collapse_leading_plane_axis() - source_payload = collapsed_metadata.with_source_provenance( - collapsed_metadata.source_provenance.with_source_image_names( - (source_ref.name,) - ) - ).attach_source_context_to(output_value) - plane_projection = None - source_context_strategy = ImageOutputSourceContextStrategy.for_source_payload( - source_payload, - ) - if self.output_owns_source_context( - source_payload, - output_value, - output_plan, - plane_projection, - ) and not source_context_strategy.requires_plane_contextualization( - source_payload, - output_value, - plane_projection, - ): - if isinstance(output_value, AlignedImageStack): - return output_value - output_metadata = image_payload_metadata(output_value) - source_metadata = image_payload_metadata(source_payload) - contextualized_output = output_metadata.with_source_context_from( - source_metadata - ).attach_source_context_to( - output_value, - ) - if image_payload_metadata(contextualized_output) == output_metadata: - return output_value - return contextualized_output - return source_context_strategy.contextualize( - source_payload, - output_value, - plane_projection, - ) - - -class MeasurementsFunctionOutputContextStrategy(ProjectedFunctionOutputContextStrategy): - """Own schema-bearing rows as one compiled measurement table.""" - - artifact_type = MeasurementsArtifactType - - @staticmethod - def _declared_subject(output_plan: ArtifactOutputPlan | None) -> MeasurementSubject: - if output_plan is None: - raise ValueError("Measurement outputs require a compiled output plan.") - return MeasurementsArtifactType.require_output_subject(output_plan) - - @staticmethod - def _validate_nominal_table( - output_value: MeasurementTable, - output_plan: ArtifactOutputPlan, - subject: MeasurementSubject, - ) -> None: - output_value.validate_artifact_name(output_plan.name) - if output_value.subject != subject: - raise ValueError( - f"Measurement output {output_plan.ref()!r} declares subject " - f"{subject!r}, but returned {output_value.subject!r}." - ) - - @staticmethod - def _contextualized_rows( - rows: ColumnarRows, - *, - subject: MeasurementSubject, - source_provenance: SourceImageProvenance, - ) -> ColumnarRows: - owned_rows = MeasurementRowOwnership( - object_name=subject.object_name, - source_image_name=subject.source_image_name, - ).annotate_rows(rows) - if not isinstance(owned_rows, ColumnarRows): - raise TypeError( - "Measurement row ownership must preserve the nominal ColumnarRows " - f"carrier, got {type(owned_rows).__name__}." - ) - return measurement_rows_with_source_provenance( - owned_rows, - source_provenance, - ) - - def contextualize_from_projector( - self, - source_payload: RuntimePayload, - output_value: RuntimePayload, - output_plan: ArtifactOutputPlan | None, - plane_projector: RuntimePlaneAxisProjector | None, - ) -> FunctionOutputContextualizedValue: - """Validate nominal identity before generic plane projection inspects it.""" - - subject = self._declared_subject(output_plan) - if isinstance(output_value, MeasurementTable): - assert output_plan is not None - self._validate_nominal_table(output_value, output_plan, subject) - return super().contextualize_from_projector( - source_payload, - output_value, - output_plan, - plane_projector, - ) - - def contextualize( - self, - source_payload: RuntimePayload, - output_value: RuntimePayload, - output_plan: ArtifactOutputPlan | None, - plane_projection: RuntimePlaneAxisValueProjection | None, - ) -> FunctionOutputContextualizedValue: - del plane_projection - subject = self._declared_subject(output_plan) - assert output_plan is not None - source_provenance = image_payload_metadata(source_payload).source_provenance - if isinstance(output_value, MeasurementTable): - self._validate_nominal_table(output_value, output_plan, subject) - contextualized_provenance = ( - output_value.source_provenance.with_missing_from(source_provenance) - ) - return output_value.replace_fields( - rows=self._contextualized_rows( - output_value.rows, - subject=subject, - source_provenance=contextualized_provenance, - ), - source_provenance=contextualized_provenance, - ) - if not isinstance(output_value, ColumnarRows): - raise TypeError( - f"Measurement output {output_plan.ref()!r} requires ColumnarRows " - f"or MeasurementTable, got {type(output_value).__name__}." - ) - return MeasurementTable( - name=output_plan.name, - rows=self._contextualized_rows( - output_value, - subject=subject, - source_provenance=source_provenance, - ), - source_image_name=subject.source_image_name, - subject=subject, - source_provenance=source_provenance, - ) - - -class SpatialGraphFunctionOutputContextStrategy(ProjectedFunctionOutputContextStrategy): - """Preserve invocation source identity on spatial graph outputs.""" - - artifact_type = SpatialGraphArtifactType - - def contextualize( - self, - source_payload: RuntimePayload, - output_value: RuntimePayload, - output_plan: ArtifactOutputPlan | None, - plane_projection: RuntimePlaneAxisValueProjection | None, - ) -> FunctionOutputContextualizedValue: - del plane_projection - if not isinstance(output_value, SpatialGraph): - raise TypeError( - "Spatial graph output requires SpatialGraph, got " - f"{type(output_value).__name__}." - ) - if output_plan is not None: - output_value.validate_artifact_name(output_plan.name) - source_provenance = output_value.contextualized_source_provenance( - image_payload_metadata(source_payload).source_provenance - ) - contextualized_provenance = output_value.source_provenance.with_missing_from( - source_provenance - ) - if contextualized_provenance == output_value.source_provenance: - return output_value - return replace(output_value, source_provenance=contextualized_provenance) - - @singledispatch def project_declared_source_identity( source_payload: RuntimePayload, @@ -805,412 +265,6 @@ def project_object_label_declared_source_identity( return source_payload -class ImageOutputSourceContextStrategy( - NominalTypeKeyedStrategyMixin, - ABC, - metaclass=AutoRegisterMeta, -): - """Registered image-output contextualization by semantic source payload type.""" - - __registry_key__ = "value_type_label" - __skip_if_no_key__ = True - - @classmethod - def for_source_payload( - cls, - source_payload: RuntimePayload, - ) -> "ImageOutputSourceContextStrategy": - strategy = cls.for_nominal_value(source_payload) - if strategy is None: - return DefaultImageOutputSourceContextStrategy() - return strategy - - def requires_plane_contextualization( - self, - source_payload: RuntimePayload, - output_value: RuntimePayload, - plane_projection: RuntimePlaneAxisValueProjection | None, - ) -> bool: - """Return whether this source type must bind an undeclared output axis.""" - - del source_payload, output_value, plane_projection - return False - - @abstractmethod - def contextualize( - self, - source_payload: RuntimePayload, - output_value: RuntimePayload, - plane_projection: RuntimePlaneAxisValueProjection | None, - ) -> RuntimePayload: - """Return image output with source semantics attached.""" - - -class DefaultImageOutputSourceContextStrategy(ImageOutputSourceContextStrategy): - """Attach scalar source-image context to a derived image output.""" - - def contextualize( - self, - source_payload: RuntimePayload, - output_value: RuntimePayload, - plane_projection: RuntimePlaneAxisValueProjection | None, - ) -> RuntimePayload: - if isinstance(output_value, AlignedImageStack): - return output_value - return image_payload_metadata(source_payload).derive_payload( - source_payload, - output_value, - plane_projection=plane_projection, - ) - - -class AlignedImageStackOutputSourceContextStrategy(ImageOutputSourceContextStrategy): - """Preserve aligned multi-source image payloads as their own source context.""" - - value_type = AlignedImageStack - - def contextualize( - self, - source_payload: RuntimePayload, - output_value: RuntimePayload, - plane_projection: RuntimePlaneAxisValueProjection | None, - ) -> RuntimePayload: - del source_payload, plane_projection - return output_value - - -class RuntimeSliceAlignedImageOutputSourceContextStrategy( - ImageOutputSourceContextStrategy -): - """Attach per-runtime-slice source context to derived image outputs.""" - - value_type = RuntimeSliceAlignedValueSet - - def contextualize( - self, - source_payload: RuntimePayload, - output_value: RuntimePayload, - plane_projection: RuntimePlaneAxisValueProjection | None, - ) -> RuntimePayload: - source_values = source_payload - if not isinstance(source_values, RuntimeSliceAlignedValueSet): - raise TypeError( - "Runtime-slice-aligned image output strategy requires " - f"RuntimeSliceAlignedValueSet, got {type(source_values).__name__}." - ) - return RuntimeSliceAlignedImageOutputContext( - source_values=source_values, - output_value=output_value, - plane_projection=plane_projection, - ).payload() - - -class ObjectLabelImageOutputSourceContextStrategy(ImageOutputSourceContextStrategy): - """Project an image rendered from labels onto the invocation plane axis.""" - - value_type = ObjectLabelValue - - def requires_plane_contextualization( - self, - source_payload: RuntimePayload, - output_value: RuntimePayload, - plane_projection: RuntimePlaneAxisValueProjection | None, - ) -> bool: - """Require projection for a volume label payload, including depth one.""" - - del output_value - if not isinstance(source_payload, ObjectLabelValue): - raise TypeError( - "Object-label image output context requires ObjectLabelValue, got " - f"{type(source_payload).__name__}." - ) - return ( - plane_projection is not None - and plane_projection.plane_index is None - and image_payload_metadata(source_payload).plane_axis is None - and np.ndim(object_label_dense_array(source_payload)) >= 3 - ) - - def contextualize( - self, - source_payload: RuntimePayload, - output_value: RuntimePayload, - plane_projection: RuntimePlaneAxisValueProjection | None, - ) -> RuntimePayload: - if not isinstance(source_payload, ObjectLabelValue): - raise TypeError( - "Object-label image output context requires ObjectLabelValue, got " - f"{type(source_payload).__name__}." - ) - source_metadata = image_payload_metadata(source_payload) - if plane_projection is None or plane_projection.plane_index is not None: - return source_metadata.derive_payload( - source_payload, - output_value, - plane_projection=plane_projection, - ) - plane_count = source_metadata.source_provenance.source_plane_count - if plane_count != plane_projection.axis_size: - raise ValueError( - "Object-label image output source-plane provenance must match the " - "declared runtime plane axis: " - f"{plane_count} != {plane_projection.axis_size}." - ) - plane_projection.validate_shape( - np.shape(image_payload_data(output_value)), - value_name="Object-label image output payload", - ) - output_metadata = image_payload_metadata(output_value) - contextualized_output = output_metadata.replace_fields( - plane_axis=plane_projection.axis, - ).attach_to(output_value) - return source_metadata.derive_payload( - source_payload, - contextualized_output, - plane_projection=plane_projection, - ) - - -@dataclass(frozen=True, slots=True) -class RuntimeSliceAlignedImageOutputContext: - """Compose stack metadata for image output derived from aligned source values.""" - - source_values: RuntimeSliceAlignedValueSet - output_value: RuntimePayload - plane_projection: RuntimePlaneAxisValueProjection | None - - def payload(self) -> RuntimePayload: - output_data = image_payload_data(self.output_value) - if self.plane_projection is None: - if self.source_values.slice_count != 1: - raise ValueError( - "Runtime-slice-aligned image output has multiple source values " - "but no declared runtime plane projection." - ) - source_value = self.source_values.value_for_aligned_slice(0, 1) - return image_payload_metadata(source_value).derive_payload( - source_value, - self.output_value, - ) - output_slices = self.output_slices(output_data) - contextualized_slices = [] - for slice_index, output_slice in enumerate(output_slices): - source_value = self.source_values.value_for_aligned_slice( - slice_index, - len(output_slices), - ) - contextualized_slices.append( - image_payload_metadata(source_value).derive_payload( - source_value, - output_slice, - ) - ) - return stack_image_payload_context( - tuple(contextualized_slices), - output_data, - metadata_mode=ImagePayloadMetadataCompositionMode.STACK, - ) - - def output_slices( - self, - output_data: RuntimeArrayData, - ) -> tuple[RuntimeArrayData, ...]: - output_array = np.asarray(output_data) - projection = self.plane_projection - if projection is None: - raise RuntimeError( - "Runtime-slice output splitting requires a plane projection." - ) - if projection.axis_size != self.source_values.slice_count: - raise ValueError( - "Runtime-slice image output projection must exactly match its " - f"aligned source count: {projection.axis_size} != " - f"{self.source_values.slice_count}." - ) - projection.validate_shape( - output_array.shape, - value_name="Runtime-slice-aligned image output", - ) - return tuple( - image_payload_slice_context( - self.output_value, - output_array[slice_index], - slice_index, - plane_axis=projection.axis, - ) - for slice_index in range(projection.axis_size) - ) - - -class ObjectLabelsFunctionOutputContextStrategy(ProjectedFunctionOutputContextStrategy): - """Preserve source-image metadata for object-label outputs.""" - - artifact_type = ObjectLabelsArtifactType - - def contextualize( - self, - source_payload: RuntimePayload, - output_value: RuntimePayload, - output_plan: ArtifactOutputPlan | None, - plane_projection: RuntimePlaneAxisValueProjection | None, - ) -> FunctionOutputContextualizedValue: - return ObjectLabelOutputValueContextStrategy.for_output_value( - output_value, - ).contextualize(source_payload, output_value, plane_projection) - - -class ObjectLabelOutputValueContextStrategy( - NominalTypeKeyedStrategyMixin, - ABC, - metaclass=AutoRegisterMeta, -): - """Registered object-label output contextualization by nominal value type.""" - - __registry_key__ = "value_type_label" - __skip_if_no_key__ = True - - @classmethod - def for_output_value( - cls, - output_value: ObjectLabelContextualizableOutput, - ) -> "ObjectLabelOutputValueContextStrategy": - return cls.require_nominal_value( - output_value, - context="Object-label function output", - ) - - @abstractmethod - def contextualize( - self, - source_payload: RuntimePayload, - output_value: ObjectLabelContextualizableOutput, - plane_projection: RuntimePlaneAxisValueProjection | None, - ) -> FunctionOutputContextualizedValue: - """Return the output with source-image context attached when possible.""" - - -class RuntimeSliceAlignedObjectLabelOutputValueContextStrategy( - ObjectLabelOutputValueContextStrategy -): - """Contextualize each runtime-slice-aligned object-label output slice.""" - - value_type = RuntimeSliceAlignedValueSet - - def contextualize( - self, - source_payload: RuntimePayload, - output_value: ObjectLabelContextualizableOutput, - plane_projection: RuntimePlaneAxisValueProjection | None, - ) -> FunctionOutputContextualizedValue: - aligned_values = output_value - if not isinstance(aligned_values, RuntimeSliceAlignedValueSet): - raise TypeError( - "Runtime-slice-aligned object-label output strategy requires " - f"RuntimeSliceAlignedValueSet, got {type(aligned_values).__name__}." - ) - if plane_projection is None: - raise ValueError( - "Runtime-slice-aligned object-label output requires a declared " - "runtime plane projection." - ) - if plane_projection.axis is not RuntimePlaneAxis.RUNTIME_SLICE: - raise ValueError( - "Runtime-slice-aligned object-label output requires the " - f"runtime-slice axis, got {plane_projection.axis.value!r}." - ) - if plane_projection.axis_size != aligned_values.slice_count: - raise ValueError( - "Runtime-slice-aligned object-label output count must exactly " - "match the declared runtime plane axis: " - f"{aligned_values.slice_count} != {plane_projection.axis_size}." - ) - return RuntimeSliceAlignedValues( - tuple( - ObjectLabelOutputValueContextStrategy.for_output_value( - aligned_values.value_for_slice(slice_index) - ).contextualize( - RuntimeSliceProjection.value_for_slice( - source_payload, - RuntimePlaneAxisValueProjection.from_selected_plane( - axis=plane_projection.axis, - plane_index=slice_index, - axis_size=plane_projection.axis_size, - ), - ), - aligned_values.value_for_slice(slice_index), - None, - ) - for slice_index in range(aligned_values.slice_count) - ) - ) - - -class ContextualObjectLabelOutputValueContextStrategy( - ObjectLabelOutputValueContextStrategy -): - """Preserve object-label domain while filling missing source-image context.""" - - value_type = ObjectLabelValue - - def contextualize( - self, - source_payload: RuntimePayload, - output_value: ObjectLabelContextualizableOutput, - plane_projection: RuntimePlaneAxisValueProjection | None, - ) -> ObjectLabelValue: - del plane_projection - if not isinstance(output_value, ObjectLabelValue): - raise TypeError( - "Contextual object-label output strategy requires " - f"ObjectLabelValue, got {type(output_value).__name__}." - ) - return output_value.with_source_image_context(source_payload) - - -class DenseArrayObjectLabelOutputValueContextStrategy( - ObjectLabelOutputValueContextStrategy -): - """Build declared object labels through the existing source-domain owner.""" - - def contextualize( - self, - source_payload: RuntimePayload, - output_value: ObjectLabelContextualizableOutput, - plane_projection: RuntimePlaneAxisValueProjection | None, - ) -> ObjectLabelValue: - return SourceImageObjectLabelBuildRequest( - image=source_payload, - labels=self.label_array(output_value), - plane_projection=plane_projection, - ).payload() - - @abstractmethod - def label_array(self, output_value: ObjectLabelContextualizableOutput) -> object: - """Project the dense label data owned by this nominal value case.""" - - -class NumpyArrayObjectLabelOutputValueContextStrategy( - DenseArrayObjectLabelOutputValueContextStrategy -): - """Build object-label context for declared NumPy array outputs.""" - - value_type = np.ndarray - - def label_array(self, output_value: ObjectLabelContextualizableOutput) -> object: - return output_value - - -class ImagePayloadObjectLabelOutputValueContextStrategy( - DenseArrayObjectLabelOutputValueContextStrategy -): - """Consume a declared label array with its preserved runtime plane carrier.""" - - value_type = ImagePayloadMetadataCarrier - - def label_array(self, output_value: ObjectLabelContextualizableOutput) -> object: - return image_payload_data(output_value) - - @dataclass(frozen=True) class ComponentArtifactPlans(Generic[ArtifactInputPlanKeyT, ArtifactInputPlanT]): """Artifact plans selected for one grouped component execution.""" @@ -1243,6 +297,8 @@ def select_for_invocation( *, execution_scope: ComponentGroupScope, component_key: str | None, + declared_source_bindings: CompiledSourceBindingPlan = CompiledSourceBindingPlan(), + active_source_bindings: CompiledSourceBindingPlan = CompiledSourceBindingPlan(), ) -> "ComponentArtifactPlans[InvocationArtifactInputProjectionKey, InvocationArtifactInputEdgePlan] | None": active_outputs = invocation.output_plans_for_component( execution_scope, @@ -1250,38 +306,32 @@ def select_for_invocation( ) if active_outputs is None: return None + inputs = {} + for edge_key, edge in invocation.select_inputs( + self.inputs, active_output_plans=active_outputs, + ).items(): + if ( + edge.main_flow_projection is not None + and declared_source_bindings.declares_artifact_ref(edge.spec.ref()) + and not active_source_bindings.declares_artifact_ref(edge.spec.ref()) + ): + if not invocation.adapter_manages_artifact_inputs: + continue + if edge.storage_plan is not None: + raise ValueError( + f"Stored primary input {edge.spec.ref()!r} is not represented " + "by this main-flow payload; its producer cannot substitute " + "for the current payload epoch." + ) + edge = replace(edge, main_flow_projection=None) + inputs[edge_key] = edge return ComponentArtifactPlans( - inputs=invocation.select_inputs( - self.inputs, active_output_plans=active_outputs, - ), + inputs=inputs, outputs=invocation.select_outputs( self.outputs, compiled_output_plans=active_outputs, ), ) - def select_source_bound_inputs( - self: "ComponentArtifactPlans[InvocationArtifactInputProjectionKey, InvocationArtifactInputEdgePlan]", - *, - declared_source_bindings: CompiledSourceBindingPlan, - active_source_bindings: CompiledSourceBindingPlan, - ) -> "ComponentArtifactPlans[InvocationArtifactInputProjectionKey, InvocationArtifactInputEdgePlan]": - """Keep only source-bound main-flow occurrences active on this component.""" - - return replace( - self, - inputs={ - edge_key: edge - for edge_key, edge in self.inputs.items() - if not ( - edge.consumes_main_flow - and declared_source_bindings.declares_artifact_ref(edge.spec.ref()) - and not active_source_bindings.declares_artifact_ref( - edge.spec.ref() - ) - ) - }, - ) - @classmethod def _select_output_plans_for_component( cls, @@ -1415,38 +465,45 @@ def axis_scope(self) -> RuntimeExecutionAxisScope: @dataclass(frozen=True, slots=True, kw_only=True) -class FunctionRuntimeScope(PatternGroupExecutionScope): - """Generic runtime scope shared by chain, invocation, adapter, and debug code.""" +class PatternGroupExecutionRequest(PatternGroupExecutionScope): + """All runtime data needed to process one pattern group.""" - artifacts: ComponentArtifactPlans[ArtifactSpecRef, ArtifactInputPlan] - source_binding_context: SourceBindingRuntimeContext - runtime_plane_index: int - runtime_plane_count: int + pattern_group_info: JsonValue + component_index: int + component_count: int - @classmethod - def from_pattern_group( - cls, - request: "PatternGroupExecutionRequest", - loaded: "PatternGroupData", - ) -> "FunctionRuntimeScope": - artifacts = ComponentArtifactPlans.from_step_component( - request.execution_plan, - request.component_key, - ) - logger.debug( - "Selected artifact outputs for component %s: %s", - request.component_key, - artifacts.outputs, + def load_input_stack( + self, runtime: "PatternGroupRuntime", + ) -> tuple[list[str], RuntimeArrayData]: + """Admit the filename-selected source cohort.""" + return runtime._load_input_stack() + + def loaded_plane_count( + self, + matching_files: Sequence[str], + payload: RuntimeArrayData, + ) -> int: + """The source path roster declares the initial runtime plane count.""" + return image_payload_metadata( + payload + ).source_spatial_domain.intrinsic_plane_count( + np.shape(image_payload_data(payload)), + len(matching_files), ) + + def loaded_fixed_component_values( + self, payload: RuntimeArrayData, + ) -> RuntimeFixedComponentValues: + """Capture the source-selected cohort's common fixed coordinates.""" source_provenance = image_payload_metadata( - loaded.main_data_stack + payload ).source_provenance.with_common_scalar_identity_from_planes() common_source_metadata = source_provenance.source_component_metadata or {} variable_components = ComponentSet.coerce( - request.execution_plan.variable_components or () + self.execution_plan.variable_components or () ) execution_group_component = ( - request.execution_plan.execution_group_scope.component + self.execution_plan.execution_group_scope.component ) fixed_components = tuple( component @@ -1460,18 +517,127 @@ def from_pattern_group( ) is not None ) + return source_provenance.require_common_component_values(fixed_components) + + def passthrough_producer_records( + self, matching_files: Sequence[str], + ) -> tuple[ProducedOutputSemantics, ...] | None: + """Resolve the physical source paths selected by this request.""" + return step_output_manifest(self.context).producer_output_records_for_paths( + self.execution_plan, + matching_files, + self.context.microscope_handler.parser, + ) + + +@dataclass(frozen=True, slots=True, kw_only=True) +class ArtifactPatternGroupExecutionRequest(PatternGroupExecutionRequest): + """Admit exact canonical producer values into an independent cohort.""" + + def load_input_stack( + self, runtime: "PatternGroupRuntime", + ) -> tuple[list[str], RuntimeArrayData]: + edges = self.execution_plan.stored_primary_input_edges_for_group( + self.compiled_group, self.component_key, + ) + if not edges: + raise ValueError("Artifact cohort requires complete stored primary inputs.") + payloads = [] + matching_files = [] + for edge in edges: + artifact_input = RuntimeArtifactInput( + edge_plan=edge, + axis_scope=self.axis_scope, + backend=Backend.MEMORY.value, + source_binding_plan=self.source_binding_plan, + ) + records = artifact_input.records(self.context.runtime_value_store) + source_payload = edge.spec.artifact_type.source_image_payload_from_runtime_value( + artifact_input.composed_value(records), + ) + if source_payload is None: + raise ValueError( + f"Artifact cohort source {edge.spec.ref()!r} has no image context." + ) + payloads.append( + ImagePayloadStackComposition.copy_whole_image( + source_payload, + memory_type=self.execution_plan.input_memory_type, + device_id=self.execution_plan.device_id_for( + self.execution_plan.input_memory_type, + ), + ) + ) + matching_files.extend(record.location.path for record in records) + main_data_stack = ImagePayloadConsumption.NATURAL.compose_image_payload( + self.execution_plan.step_name, tuple(payloads), + ).payload + return matching_files, main_data_stack + + def loaded_plane_count( + self, matching_files: Sequence[str], payload: RuntimeArrayData, + ) -> int: + """Canonical payloads declare their runtime axis independently of paths.""" + count = RuntimeSliceProjection.slice_count_from_values((payload,)) + return 1 if count is None else count + + def loaded_fixed_component_values( + self, payload: RuntimeArrayData, + ) -> RuntimeFixedComponentValues: + """Retain exact producer coordinates admitted by typed discovery.""" + return self.fixed_component_values + + def passthrough_producer_records( + self, matching_files: Sequence[str], + ) -> tuple[ProducedOutputSemantics, ...]: + """Preserve input transport independently of artifact context admission.""" + records = step_output_manifest(self.context).producer_records_for( + self.execution_plan, + ) + if records is None: + raise ValueError("Artifact input passthrough requires producer lineage.") + return records + + +@dataclass(frozen=True, slots=True, kw_only=True) +class PatternGroupData(PatternGroupExecutionScope): + """Complete loaded cohort and its original execution coordinates.""" + + artifacts: ComponentArtifactPlans[ArtifactSpecRef, ArtifactInputPlan] + runtime_plane_index: int + runtime_plane_count: int + matching_files: list[str] + main_data_stack: RuntimeArrayData + + @classmethod + def from_loaded_group( + cls, + request: "PatternGroupExecutionRequest", + matching_files: list[str], + main_data_stack: RuntimeArrayData, + ) -> "PatternGroupData": + artifacts = ComponentArtifactPlans.from_step_component( + request.execution_plan, + request.component_key, + ) + logger.debug( + "Selected artifact outputs for component %s: %s", + request.component_key, + artifacts.outputs, + ) return cls( + matching_files=matching_files, + main_data_stack=main_data_stack, context=request.context, execution_plan=request.execution_plan, compiled_group=request.compiled_group, artifacts=artifacts, - source_binding_context=loaded.source_binding_context, runtime_plane_index=request.component_index, - runtime_plane_count=len(loaded.matching_files), - component_value=request.component_value, - fixed_component_values=source_provenance.require_common_component_values( - fixed_components + runtime_plane_count=request.loaded_plane_count( + matching_files, main_data_stack, ), + component_value=request.component_value, + fixed_component_values=request.loaded_fixed_component_values(main_data_stack), ) def require_invocations(self) -> None: @@ -1481,105 +647,6 @@ def require_invocations(self) -> None: f"Compiled function group {self.compiled_group.group_key} has no invocations." ) - def execute_chain( - self, initial_data_stack: RuntimeArrayData - ) -> RuntimeArrayData | NoMainFlowOutput: - self.require_invocations() - current_stack: RuntimeArrayData | NoMainFlowOutput = initial_data_stack - current_memory_type = self.execution_plan.input_memory_type - debug_sink = debug_event_sink_from_context(self.context) - declared_source_bindings = self.execution_plan.source_binding_plan - active_main_flow_bindings = self.active_main_flow_source_binding_plan( - initial_data_stack - ) - for invocation in self.compiled_group.invocations: - group_key = invocation.key.runtime_group_key(self.component_value) - artifacts = self.artifacts.select_for_invocation( - invocation, - execution_scope=self.execution_plan.execution_group_scope, - component_key=self.component_key, - ) - if artifacts is None: - continue - artifacts = artifacts.select_source_bound_inputs( - declared_source_bindings=declared_source_bindings, - active_source_bindings=active_main_flow_bindings, - ) - executor = FunctionCoreExecutor( - main_data_arg=current_stack, - source_memory_type=current_memory_type, - runtime_scope=self, - invocation=invocation, - artifacts=artifacts, - group_key=group_key, - plane_projection=RuntimePlaneProjection.stack(self.runtime_plane_count), - ) - captures_debug = debug_sink.captures_invocation_events() - if captures_debug and debug_sink.should_skip_invocation( - executor.debug_cursor() - ): - continue - - invocation_started_at = time.perf_counter() - try: - current_stack = executor.execute( - debug_sink=debug_sink if captures_debug else None, - ) - except Exception as exc: - if captures_debug: - debug_sink.record( - executor.debug_event( - DebugEventType.EXCEPTION, - exception=exc, - ) - ) - raise - invocation_seconds = time.perf_counter() - invocation_started_at - if captures_debug: - after_event = executor.debug_event( - DebugEventType.AFTER_INVOCATION, - timing_seconds=invocation_seconds, - ) - debug_sink.record(after_event) - if debug_sink.should_stop_after_invocation(after_event): - break - RuntimeProfileSink.record( - "invocation_total", - invocation_seconds, - function=invocation.key.function_name, - group=invocation.key.group_key, - position=invocation.key.position, - ) - if isinstance(current_stack, NoMainFlowOutput): - return current_stack - current_memory_type = executor.memory_types().output_type - if self.compiled_group.preserves_input_main_flow() and all( - invocation.contract.artifact_output_policy.records_outputs - for invocation in self.compiled_group.invocations - ): - return NoMainFlowOutput() - return current_stack - - -@dataclass(frozen=True, slots=True, kw_only=True) -class PatternGroupExecutionRequest(PatternGroupExecutionScope): - """All runtime data needed to process one pattern group.""" - - pattern_group_info: JsonValue - component_index: int - component_count: int - - -@dataclass(frozen=True, kw_only=True) -class PatternGroupData: - """Loaded image data for one pattern group.""" - - matching_files: list[str] - main_data_stack: RuntimeArrayData - source_binding_context: SourceBindingRuntimeContext = field( - default_factory=SourceBindingRuntimeContext.empty - ) - @dataclass(frozen=True, slots=True) class OutputPathBatchEntry: @@ -1646,17 +713,11 @@ def _save_artifact_value( """Validate and save one planned artifact value to the memory VFS.""" resolved_output_plan = output_plan.for_invocation_group(group_key) vfs_path = resolved_output_plan.path - contextualized_value = FunctionOutputContextStrategy.for_output_plan( - resolved_output_plan - ).contextualize_from_projector( - source_payload, - value, + runtime_value = RuntimeValue.normalize_output_from_projector( resolved_output_plan, - plane_projector, - ) - runtime_value = RuntimeValue.normalize_for_execution_scope( - resolved_output_plan, - contextualized_value, + value, + source_payload=source_payload, + plane_projector=plane_projector, execution_scope=execution_scope, materialization_source_metadata=materialization_source_metadata, ) @@ -1679,24 +740,10 @@ def _save_artifact_value( return runtime_value.data -def _load_artifact_input_values( - runtime_scope: FunctionRuntimeScope, - input_plan: InvocationArtifactInputEdgePlan, -) -> tuple[RuntimeValue, ...]: - """Project producer-owned runtime records into one consumer invocation.""" - context = runtime_scope.context - return RuntimeArtifactInput( - edge_plan=input_plan, - axis_scope=runtime_scope.axis_scope, - backend=Backend.MEMORY.value, - source_binding_plan=runtime_scope.source_binding_plan, - ).projected_values(context.runtime_value_store) - - def prepare_compiled_function_group(group: CompiledFunctionGroup) -> None: """Run optional preparation hooks for each callable in a compiled group.""" for invocation in group.invocations: - FunctionInvocationCallableResolver.prepare(invocation) + invocation.contract.resolve_runtime_callable() def prepare_compiled_context_callables( @@ -1745,10 +792,10 @@ def prepare_compiled_context_callables( @dataclass(frozen=True, slots=True) -class FunctionInvocationArtifactScope: - """Own exact invocation artifact sources and their callable argument binding.""" +class FunctionCoreExecutor: + """Execute one scoped callable invocation and route declared artifact I/O.""" - runtime_scope: FunctionRuntimeScope + group_data: PatternGroupData invocation: CompiledFunctionInvocation artifacts: ComponentArtifactPlans[ InvocationArtifactInputProjectionKey, @@ -1756,6 +803,8 @@ class FunctionInvocationArtifactScope: ] group_key: str | None plane_projection: RuntimePlaneProjection + main_data_arg: RuntimeArrayData + source_memory_type: str @property def selected_artifact_input_edges( @@ -1769,8 +818,8 @@ def runtime_adapter_request( self, source_payload: RuntimePayload, ) -> RuntimeAdapterRequest: - return RuntimeAdapterRequest.from_runtime_scope( - runtime_scope=self.runtime_scope, + return RuntimeAdapterRequest( + context=self.group_data.context, callable_contract=self.invocation.contract, artifact_inputs={ edge.key: edge for edge in self.selected_artifact_input_edges @@ -1779,6 +828,12 @@ def runtime_adapter_request( group_key=self.group_key, plane_projection=self.plane_projection, source_payload=source_payload, + source_binding_plan=self.group_data.source_binding_plan, + axis_scope=self.group_data.axis_scope, + variable_components=tuple( + self.group_data.execution_plan.variable_components + ), + source_load_plan=self.group_data.execution_plan.source_load_plan, ) @property @@ -1800,12 +855,12 @@ def declared_source_payload( ) stored_payload = loaded_artifact_payloads.get(source_ref) source_binding = ( - self.runtime_scope.source_binding_plan.binding_for_artifact_ref(source_ref) + self.group_data.source_binding_plan.binding_for_artifact_ref(source_ref) ) main_flow_edges = tuple( edge for edge in self.selected_artifact_input_edges - if edge.spec.ref() == source_ref and edge.consumes_main_flow + if edge.spec.ref() == source_ref and edge.main_flow_projection is not None ) uses_main_flow = bool( stored_payload is None and source_binding is None and main_flow_edges @@ -1873,11 +928,12 @@ def load_artifact_inputs( projected_values = ( self.load_artifact_input(input_plan.spec.name, input_plan) if input_plan.uses_runtime_storage() + and input_plan.main_flow_projection is None else ( RuntimeValue.from_spec( input_plan.spec, input_plan.resolve_unstored_payload(self, source_payload), - execution_scope=self.runtime_scope.axis_scope, + execution_scope=self.group_data.axis_scope, ), ) ) @@ -1911,10 +967,12 @@ def load_artifact_input( ) load_started_at = time.perf_counter() try: - loaded_values = _load_artifact_input_values( - self.runtime_scope, - edge_plan, - ) + loaded_values = RuntimeArtifactInput( + edge_plan=edge_plan, + axis_scope=self.group_data.axis_scope, + backend=Backend.MEMORY.value, + source_binding_plan=self.group_data.source_binding_plan, + ).projected_values(self.group_data.context.runtime_value_store) except Exception as exc: logger.error( f"Failed to load artifact input '{arg_name}' from " @@ -1922,37 +980,21 @@ def load_artifact_input( exc_info=True, ) raise - RuntimeProfileSink.record( - "artifact_input_load", - time.perf_counter() - load_started_at, - function=self.function_name, - artifact=arg_name, - artifact_type=storage_plan.artifact_type.value, - ) - return loaded_values - - -@dataclass(frozen=True, slots=True) -class FunctionCoreExecutor(FunctionInvocationArtifactScope): - """Execute one scoped callable invocation and route declared artifact I/O.""" - - runtime_scope: FunctionRuntimeScope - invocation: CompiledFunctionInvocation - artifacts: ComponentArtifactPlans[ - InvocationArtifactInputProjectionKey, - InvocationArtifactInputEdgePlan, - ] - group_key: str | None - plane_projection: RuntimePlaneProjection - main_data_arg: RuntimeArrayData - source_memory_type: str + RuntimeProfileSink.record( + "artifact_input_load", + time.perf_counter() - load_started_at, + function=self.function_name, + artifact=arg_name, + artifact_type=storage_plan.artifact_type.value, + ) + return loaded_values def debug_cursor(self) -> DebugCursor: return DebugCursor.from_invocation( - step_index=self.runtime_scope.execution_plan.step_index, - step_scope_id=self.runtime_scope.execution_plan.step_scope_id, + step_index=self.group_data.execution_plan.step_index, + step_scope_id=self.group_data.execution_plan.step_scope_id, invocation=self.invocation, - pattern_group_identity=str(self.runtime_scope.runtime_plane_index), + pattern_group_identity=str(self.group_data.runtime_plane_index), ) def debug_artifacts( @@ -1978,9 +1020,9 @@ def debug_event( return DebugEvent.for_invocation( event_type=event_type, cursor=self.debug_cursor(), - step_name=self.runtime_scope.execution_plan.step_name, + step_name=self.group_data.execution_plan.step_name, callable_name=self.invocation.key.function_name, - axis_id=self.runtime_scope.execution_plan.axis_id, + axis_id=self.group_data.execution_plan.axis_id, input_artifacts=self.debug_artifacts( { edge.storage_plan.ref(): edge.storage_plan @@ -1997,7 +1039,7 @@ def debug_event( @property def func_callable(self) -> Callable: - return FunctionInvocationCallableResolver.resolve(self.invocation) + return self.invocation.contract.resolve_runtime_callable() @property def base_kwargs(self) -> RuntimeCallableKwargs: @@ -2018,15 +1060,17 @@ def execute( *, debug_sink: DebugEventSink | None = None, ) -> RuntimePayload | NoMainFlowOutput: - memory_types = self.memory_types() - source_payload = MainFlowMemoryConversion( - payload=self.main_data_arg, + input_memory_type, _ = self.invocation.contract.require_memory_types() + target_device_id = self.group_data.execution_plan.device_id_for( + input_memory_type + ) + converted_data = convert_memory( + data=image_payload_data(self.main_data_arg), source_type=self.source_memory_type, - target_type=memory_types.input_type, - target_device_id=self.runtime_scope.execution_plan.device_id_for( - memory_types.input_type - ), - ).converted_payload() + target_type=input_memory_type, + gpu_id=target_device_id, + ) + source_payload = with_image_payload_data(self.main_data_arg, converted_data) main_data_arg = self.main_flow_call_argument(source_payload) final_kwargs = dict(self.base_kwargs) self.bind_compiled_runtime_parameters(final_kwargs) @@ -2045,26 +1089,11 @@ def execute( loaded_artifact_payloads=loaded_artifact_payloads, debug_sink=debug_sink, ) - main_output = self.save_artifact_outputs( + return self.save_artifact_outputs( raw_output, source_payload, loaded_artifact_payloads=loaded_artifact_payloads, ) - if isinstance(main_output, NoMainFlowOutput): - return main_output - if self.invocation.adapter_records_artifact_outputs: - return main_output - output_source_payload = self.main_flow_output_source_payload( - self.execution_group_source_payload(source_payload) - ) - return FunctionOutputContextStrategy.for_output_plan( - None - ).contextualize_from_projector( - output_source_payload, - main_output, - None, - self.plane_projection, - ) def main_flow_call_argument( self, source_payload: RuntimePayload @@ -2073,19 +1102,16 @@ def main_flow_call_argument( return self.invocation.contract.main_flow_call_argument(source_payload) - def memory_types(self) -> "FunctionChainInvocationMemoryTypes": - return FunctionChainInvocationMemoryTypes.from_invocation(self.invocation) - def execution_group_source_payload( self, source_payload: RuntimePayload, ) -> RuntimePayload: """Return source payload metadata carrying the current grouped identity.""" - component = self.runtime_scope.execution_plan.execution_group_scope.component + component = self.group_data.execution_plan.execution_group_scope.component if component is None or self.group_key is None: return source_payload metadata = image_payload_metadata(source_payload) - component_metadata = dict(metadata.source_component_metadata or {}) + component_metadata = metadata.source_component_metadata or {} component_metadata = with_source_component_metadata( component_metadata, component, @@ -2101,7 +1127,7 @@ def bind_runtime_owned_parameters( ) -> None: context_parameter_name = self.invocation.contract.runtime_context_parameter if context_parameter_name is not None: - final_kwargs[context_parameter_name] = self.runtime_scope.context + final_kwargs[context_parameter_name] = self.group_data.context def bind_compiled_runtime_parameters( self, @@ -2170,7 +1196,7 @@ def invoke( ) call_started_at = time.perf_counter() try: - with self.runtime_scope.execution_plan.memory_device_scope( + with self.group_data.execution_plan.memory_device_scope( contract.execution_memory_type ): raw_output = func_callable( @@ -2193,7 +1219,7 @@ def invoke( ) raise type(exc)( f"{exc} Invocation boundary: step_index={cursor.step_index}; " - f"step_name={self.runtime_scope.execution_plan.step_name!r}; " + f"step_name={self.group_data.execution_plan.step_name!r}; " f"function_invocation_key={self.invocation.key!r}; " f"module={contract.module_name!r}; " f"callable={contract.function_name!r}; " @@ -2221,6 +1247,7 @@ def save_artifact_outputs( *, loaded_artifact_payloads: Mapping[ArtifactSpecRef, RuntimePayload], ) -> RuntimePayload | NoMainFlowOutput: + """Save declared outputs and qualify unsaved canonical returns afterward.""" if self.invocation.adapter_records_artifact_outputs: return self.save_module_recorded_output(raw_output) output_plans = tuple(self.artifacts.outputs.values()) @@ -2231,51 +1258,64 @@ def save_artifact_outputs( "Tuple returns require declared special-output slots; multiple " "main-flow images must be packed as AlignedImageStack." ) - return raw_output - - output_matcher = RuntimeReturnedOutputMatcher( - callable_contract=self.invocation.contract, - returned_output=raw_output, - ) - _returned_values, matched_outputs = output_matcher.resolve_plan_values( - output_plans - ) - saved_values = { - output_plan.ref(): self.save_artifact_output( - output_plan.name, - output_plan, - output_value, - source_payload, - loaded_artifact_payloads=loaded_artifact_payloads, + main_output = raw_output + else: + output_matcher = RuntimeReturnedOutputMatcher( + callable_contract=self.invocation.contract, + returned_output=raw_output, ) - for output_plan, _output_spec, output_value in matched_outputs - } - canonical_refs = frozenset( - spec.ref() - for spec in self.invocation.contract.canonical_return_output_specs - ) - main_outputs = tuple( - (output_plan, output_spec, saved_values[output_plan.ref()]) - for output_plan, output_spec, _output_value in matched_outputs - if output_plan.ref() in canonical_refs - ) - if main_outputs: - output_values = tuple( - output_value - for _output_plan, _output_spec, output_value in main_outputs - ) - if len(output_values) == 1: - return output_values[0] - return ImageOutputBundle( - output_values, - AlignedImageSliceContext.main_flow_for_output_plans( - tuple( - output_plan - for output_plan, _output_spec, _output_value in main_outputs - ) - ), + _returned_values, matched_outputs = output_matcher.resolve_plan_values( + output_plans ) - return output_matcher.canonical_output + saved_values = { + output_plan.ref(): self.save_artifact_output( + output_plan.name, + output_plan, + output_value, + source_payload, + loaded_artifact_payloads=loaded_artifact_payloads, + ) + for output_plan, _output_spec, output_value in matched_outputs + } + canonical_refs = frozenset( + spec.ref() + for spec in self.invocation.contract.canonical_return_output_specs + ) + main_outputs = tuple( + (output_plan, output_spec, saved_values[output_plan.ref()]) + for output_plan, output_spec, _output_value in matched_outputs + if output_plan.ref() in canonical_refs + ) + if main_outputs: + # These values already own their declared source transformation. + # Reapplying the input context would restore consumed planes. + output_values = tuple( + output_value + for _output_plan, _output_spec, output_value in main_outputs + ) + if len(output_values) == 1: + return output_values[0] + return ImageOutputBundle( + output_values, + AlignedImageSliceContext.main_flow_for_output_plans( + tuple( + output_plan + for output_plan, _output_spec, _output_value in main_outputs + ) + ), + ) + main_output = output_matcher.canonical_output + if isinstance(main_output, NoMainFlowOutput): + return main_output + output_source_payload = self.main_flow_output_source_payload( + self.execution_group_source_payload(source_payload) + ) + return ImageArtifactType.contextualize_output_from_projector( + output_source_payload, + main_output, + None, + self.plane_projection, + ) def save_module_recorded_output( self, @@ -2329,11 +1369,11 @@ def save_artifact_output( materialization_source_payload ) saved_value = _save_artifact_value( - self.runtime_scope.context, + self.group_data.context, output_plan, value, output_source_payload, - execution_scope=self.runtime_scope.axis_scope, + execution_scope=self.group_data.axis_scope, group_key=self.group_key, materialization_source_metadata=materialization_source_metadata, plane_projector=self.plane_projection, @@ -2364,130 +1404,6 @@ def artifact_output_source_payload( ) -@dataclass(frozen=True, slots=True) -class FunctionChainInvocationMemoryTypes: - """Validated memory types for one compiled invocation.""" - - input_type: str - output_type: str - - @classmethod - def from_invocation( - cls, - invocation: CompiledFunctionInvocation, - ) -> "FunctionChainInvocationMemoryTypes": - if ( - invocation.input_memory_type is None - or invocation.output_memory_type is None - ): - raise ValueError( - f"Compiled invocation {invocation.key} is missing memory types." - ) - return cls(invocation.input_memory_type, invocation.output_memory_type) - - -@dataclass(frozen=True, slots=True) -class VariableComponentNames: - """Microscope parser variable-component names for pattern lookup.""" - - components: Sequence[VariableComponents] - - @property - def value(self) -> list[str] | None: - if not self.components: - return None - return [component.value for component in self.components] - - -@dataclass(frozen=True, slots=True) -class MainFlowMemoryConversion: - """Main-flow image memory conversion preserving payload context.""" - - payload: RuntimeArrayData - source_type: str - target_type: str - target_device_id: int | None - - def converted_payload(self) -> RuntimeArrayData: - data = image_payload_data(self.payload) - converted = convert_memory( - data=data, - source_type=self.source_type, - target_type=self.target_type, - gpu_id=self.target_device_id, - ) - return with_image_payload_data(self.payload, converted) - - -@dataclass(slots=True) -class PatternGroupOutputData: - """Unstacked output slices plus declared per-slice output semantics.""" - - slices: list[RuntimeArrayData] - slice_contexts: tuple[AlignedImageSliceContext, ...] = () - stack_payload: RuntimeArrayData | None = None - - def __post_init__(self) -> None: - if not self.slice_contexts: - self.slice_contexts = tuple( - AlignedImageSliceContext.anonymous_main_flow() for _slice in self.slices - ) - if len(self.slice_contexts) != len(self.slices): - raise ValueError( - "PatternGroupOutputData.slice_contexts must match slices; " - f"got {len(self.slice_contexts)} context(s) for {len(self.slices)} slice(s)." - ) - - @classmethod - def from_aligned_stack( - cls, - value: AlignedImageStack, - *, - memory_type: MemoryType, - device_id: int | None, - ) -> "PatternGroupOutputData": - """Materialize correlated output slices through the alignment owner.""" - projected_outputs = tuple(value.projected_output_slices()) - payloads = [payload for payload, _context in projected_outputs] - data = tuple(image_payload_data(payload) for payload in payloads) - stack_payload = None - if len({tuple(np.shape(item)) for item in data}) == 1: - stacked = stack_runtime_slices(data, memory_type, device_id) - stack_payload = stack_image_payload_context( - payloads, - stacked, - metadata_mode=ImagePayloadMetadataCompositionMode.STACK, - ) - return cls( - slices=payloads, - slice_contexts=( - tuple(context for _payload, context in projected_outputs) - if value.slice_contexts - else () - ), - stack_payload=stack_payload, - ) - - def __iter__(self) -> Iterator[RuntimeArrayData]: - return iter(self.slices) - - def __len__(self) -> int: - return len(self.slices) - - def __getitem__(self, index: int) -> RuntimeArrayData: - return self.slices[index] - - def __eq__(self, other: object) -> bool: - if isinstance(other, PatternGroupOutputData): - return ( - self.slices == other.slices - and self.slice_contexts == other.slice_contexts - ) - if isinstance(other, SequenceABC): - return self.slices == list(other) - return NotImplemented - - class PatternGroupRuntime: """Staged runtime for one pattern group.""" @@ -2542,7 +1458,9 @@ def run(self) -> None: try: load_started_at = time.perf_counter() - loaded = self._load_input_stack() + matching_files, main_data_stack = ( + self.request.load_input_stack(self) + ) except NoStepOutputManifestMatch: logger.debug( "Skipping stale pattern group %s for step %s (%s); no files " @@ -2561,7 +1479,10 @@ def run(self) -> None: pattern=self.pattern_repr, ) execute_started_at = time.perf_counter() - processed_stack = self._execute_pattern(loaded) + loaded = PatternGroupData.from_loaded_group( + self.request, matching_files, main_data_stack, + ) + processed_stack = self.execute_chain(loaded) RuntimeProfileSink.record( "pattern_execute_chain", time.perf_counter() - execute_started_at, @@ -2585,37 +1506,20 @@ def run(self) -> None: plan.step_name, ) return - unstack_started_at = time.perf_counter() - output_data = self._validate_and_unstack(processed_stack, loaded) - RuntimeProfileSink.record( - "pattern_validate_unstack", - time.perf_counter() - unstack_started_at, - step=plan.step_index, - step_name=plan.step_name, - pattern=self.pattern_repr, - ) - save_started_at = time.perf_counter() - output_records = self._save_outputs(output_data, loaded.matching_files) + if not plan.requires_main_flow_checkpoint(self.request.context.step_plans): + return + output_records = self._save_outputs(processed_stack, loaded.matching_files) output_paths = [record.output_path for record in output_records] - RuntimeProfileSink.record( - "pattern_save_outputs", - time.perf_counter() - save_started_at, - step=plan.step_index, - step_name=plan.step_name, - pattern=self.pattern_repr, - ) cleanup_started_at = time.perf_counter() self._cleanup_collapsed_domains( - output_data.slices, + output_records, loaded.matching_files, output_paths, ) step_output_manifest(self.request.context).record_outputs( plan, output_records, - collapsed_input_domain=( - len(output_data.slices) < len(loaded.matching_files) - ), + collapsed_input_domain=(len(output_records) < len(loaded.matching_files)), ) RuntimeProfileSink.record( "pattern_cleanup", @@ -2647,22 +1551,23 @@ def _record_main_flow_passthrough(self, matching_files: Sequence[str]) -> None: if not matching_files: return plan = self.request.execution_plan + if not plan.requires_main_flow_checkpoint(self.request.context.step_plans): + return parser = self.request.context.microscope_handler.parser - output_contexts = self._producer_output_contexts(matching_files) - records = tuple( - ProducedOutputSemantics.from_existing_main_flow_path( - plan, - self._input_memory_path(plan.input_dir, matching_file), - parser, - output_context=output_context, - ) - for matching_file, output_context in zip( - matching_files, - output_contexts, - strict=True, + manifest = step_output_manifest(self.request.context) + producer_records = self.request.passthrough_producer_records(matching_files) + if producer_records is None: + records = tuple( + ProducedOutputSemantics.from_existing_main_flow_path( + plan, + self._input_memory_path(plan.input_dir, matching_file), + parser, + ) + for matching_file in matching_files ) - ) - step_output_manifest(self.request.context).record_outputs(plan, records) + else: + records = tuple(record.passed_through(plan) for record in producer_records) + manifest.record_outputs(plan, records) def _producer_output_contexts( self, @@ -2678,7 +1583,9 @@ def _producer_output_contexts( self.request.context.microscope_handler.parser, ) - def _load_input_stack(self) -> PatternGroupData: + def _load_input_stack( + self, + ) -> tuple[list[str], RuntimeArrayData]: context = self.request.context plan = self.request.execution_plan request = self.request @@ -2686,10 +1593,16 @@ def _load_input_stack(self) -> PatternGroupData: raise RuntimeError("MicroscopeHandler not available in context.") output_manifest = step_output_manifest(context) - producer_matching_files = output_manifest.producer_paths_matching_pattern( - plan, - str(request.pattern_group_info), - context.microscope_handler.parser, + producer_index = output_manifest.producer_record_index_for( + plan, context.microscope_handler.parser, + ) + producer_records = ( + None if producer_index is None + else producer_index.matching_records(str(request.pattern_group_info)) + ) + producer_matching_files = ( + () if producer_records is None + else tuple(record.output_path for record in producer_records) ) matching_files = list(producer_matching_files) source_projection = ( @@ -2700,14 +1613,20 @@ def _load_input_stack(self) -> PatternGroupData: str(plan.input_dir), request.pattern_group_info, context.filemanager, - Backend.MEMORY.value, - VariableComponentNames(plan.variable_components).value, + plan.read_backend, + ( + [component.value for component in plan.variable_components] + if plan.variable_components + else None + ), ) - matching_files = output_manifest.filter_to_producer_paths( - plan, - matching_files, - context.microscope_handler.parser, - ) + if producer_index is not None and not producer_matching_files: + selected_paths = [ + path for path in matching_files if producer_index.contains(path) + ] + if matching_files and not selected_paths: + raise NoStepOutputManifestMatch + matching_files = selected_paths if not matching_files: raise ValueError( @@ -2756,12 +1675,15 @@ def _load_input_stack(self) -> PatternGroupData: if source_projection is not None else () ) - source_binding_context = SourceBindingRuntimeContextRequest.from_context( - context=self.request.context, - plan=self.request.execution_plan, - matching_files=matching_files, - source_projection=source_projection, - ).runtime_context() + if producer_index is not None: + producer_records = tuple(sorted( + producer_records, key=lambda record: record.output_path, + )) + if matching_files != [record.output_path for record in producer_records]: + producer_records = producer_index.records_for_paths(matching_files) + else: + producer_index.validate_input_records(producer_records) + ImagePayloadStackComposition.validate_main_flow_cohort(producer_records) cached_stack = context.runtime_image_stack_cache.get( tuple(full_file_paths), memory_type=plan.input_memory_type, @@ -2776,16 +1698,17 @@ def _load_input_stack(self) -> PatternGroupData: memory_type=plan.input_memory_type, ) if cached_stack is None: - raw_slices = context.filemanager.load_batch( - full_file_paths, - Backend.MEMORY.value, - ) + raw_slices = SourceFileUniverse( + tuple(full_file_paths), + Backend.MEMORY + if plan.main_input_dependency.kind is StepInputDependencyKind.STEP_OUTPUT + else Backend(plan.read_backend), + ).load_images(context.filemanager, zarr_config=plan.zarr_config) if source_projection is not None or not producer_matching_files: raw_slices = self._apply_source_image_loading_semantics( raw_slices, workspace_path_lookups, workspace_source_lookups, - source_binding_context, source_projection, ) @@ -2798,38 +1721,26 @@ def _load_input_stack(self) -> PatternGroupData: f"Check file integrity and format compatibility." ) - metadata_mode = ImagePayloadMetadataCompositionMode.STACK - if source_projection is not None and workspace_source_lookups: - metadata_mode = source_projection.payload_composition_mode( - workspace_source_lookups - ) - if metadata_mode is ImagePayloadMetadataCompositionMode.STACK: - raw_slice_data = tuple( - image_payload_data(slice_data) for slice_data in raw_slices - ) - main_data_stack = stack_runtime_slices( - raw_slice_data, - plan.input_memory_type, - plan.device_id_for(plan.input_memory_type), - ) - main_data_stack = stack_image_payload_context( - raw_slices, - main_data_stack, - metadata_mode=metadata_mode, + main_data_stack = ImagePayloadStackComposition.from_loaded_images( + raw_slices, + producer_records=producer_records, + execution_plan=plan, + source_projection=source_projection, + workspace_source_lookups=workspace_source_lookups, + ) + if not producer_records: + metadata = image_payload_metadata(main_data_stack) + domain = request.source_binding_plan.source_spatial_domain.admit_source_cohort( + metadata.source_spatial_domain, + depth=len(matching_files), ) - elif metadata_mode is ImagePayloadMetadataCompositionMode.BUNDLE: - main_data_stack = ImagePayloadBundleContext.from_payloads( - tuple(raw_slices), - metadata_mode=metadata_mode, - ).compose() + main_data_stack = metadata.replace_fields( + source_spatial_domain=domain, + ).attach_to(main_data_stack) else: - main_data_stack = cached_stack.stack + main_data_stack = cached_stack - return PatternGroupData( - matching_files=matching_files, - main_data_stack=main_data_stack, - source_binding_context=source_binding_context, - ) + return matching_files, main_data_stack def _workspace_source_binding_lookups( self, @@ -2940,7 +1851,7 @@ def _source_binding_load_universe(self) -> tuple[str, ...]: source_projection = ( self.source_workspace_projection_authority().projection_if_available() ) - request = SourceBindingRuntimeContextRequest.from_context( + request = SourceUniverseRequest.from_context( context=self.request.context, plan=self.request.execution_plan, matching_files=(), @@ -2950,7 +1861,7 @@ def _source_binding_load_universe(self) -> tuple[str, ...]: def _source_binding_candidate_context(self) -> SourcePatternResolutionContext: projection = self.source_workspace_projection_authority().projection_or_empty() - return SourcePatternResolutionContext.from_projection( + return self.request.context.runtime_source_binding_context_cache.source_pattern_context( parser=self.request.context.microscope_handler.parser, projection=self.source_workspace_projection_cache().filtered_by_axis( projection, @@ -2964,7 +1875,6 @@ def _apply_source_image_loading_semantics( raw_slices: Sequence[RuntimeArrayData], workspace_path_lookups: Sequence[VirtualWorkspacePathLookup], workspace_source_lookups: Sequence[VirtualWorkspacePathLookup], - source_binding_context: SourceBindingRuntimeContext, source_projection: VirtualWorkspaceSourceProjection | None, ) -> list[RuntimeArrayData]: if source_projection is not None: @@ -2990,10 +1900,22 @@ def _apply_source_image_loading_semantics( ) ] + universe_state = SourceUniverseRequest.from_context( + context=self.request.context, + plan=self.request.execution_plan, + matching_files=tuple( + lookup.virtual_path for lookup in workspace_path_lookups + ), + source_projection=None, + ).runtime_universe_state() + cache = self.request.context.runtime_source_binding_context_cache + source_metadata = cache.normalized_source_metadata( + universe_state.source_metadata_by_path + ) source_context = SourcePatternResolutionContext.from_sources( parser=self.request.context.microscope_handler.parser, - source_paths_by_virtual_path=source_binding_context.step_input_source_paths, - source_metadata_by_path=source_binding_context.source_metadata_by_path, + source_paths_by_virtual_path=universe_state.step_input_source_paths, + source_metadata_by_path=source_metadata, metadata_rules=self.request.source_binding_plan.metadata_rules, ) return [ @@ -3006,7 +1928,7 @@ def _apply_source_image_loading_semantics( ) ), source_path=source_context.source_path_for(lookup.full_virtual_path), - read_backend=source_binding_context.step_input_source_backend, + read_backend=self.request.execution_plan.read_backend, ) for payload, lookup in zip( raw_slices, @@ -3102,59 +2024,114 @@ def _apply_source_binding_payload( f"Source-bound payload {source_path!r} declares unknown alias " f"{alias!r}." ) - return apply_source_binding_payload(payload, binding, source_context) + return binding.apply_loaded_payload(payload, source_context) - def _execute_pattern( - self, - loaded: PatternGroupData, + @staticmethod + def execute_chain( + group_data: PatternGroupData ) -> RuntimeArrayData | NoMainFlowOutput: - request = self.request - runtime_scope = FunctionRuntimeScope.from_pattern_group(request, loaded) - return runtime_scope.execute_chain(loaded.main_data_stack) + group_data.require_invocations() + current_stack: RuntimeArrayData | NoMainFlowOutput = group_data.main_data_stack + current_memory_type = group_data.execution_plan.input_memory_type + debug_sink = debug_event_sink_from_context(group_data.context) + declared_source_bindings = group_data.execution_plan.source_binding_plan + for invocation in group_data.compiled_group.invocations: + group_key = invocation.key.runtime_group_key(group_data.component_value) + artifacts = group_data.artifacts.select_for_invocation( + invocation, + execution_scope=group_data.execution_plan.execution_group_scope, + component_key=group_data.component_key, + declared_source_bindings=declared_source_bindings, + active_source_bindings=group_data.active_main_flow_source_binding_plan( + current_stack + ), + ) + if artifacts is None: + continue + executor = FunctionCoreExecutor( + main_data_arg=current_stack, + source_memory_type=current_memory_type, + group_data=group_data, + invocation=invocation, + artifacts=artifacts, + group_key=group_key, + plane_projection=RuntimePlaneProjection.stack( + group_data.runtime_plane_count + ), + ) + captures_debug = debug_sink.captures_invocation_events() + if captures_debug and debug_sink.should_skip_invocation( + executor.debug_cursor() + ): + continue + + invocation_started_at = time.perf_counter() + try: + current_stack = executor.execute( + debug_sink=debug_sink if captures_debug else None, + ) + except Exception as exc: + if captures_debug: + debug_sink.record( + executor.debug_event( + DebugEventType.EXCEPTION, + exception=exc, + ) + ) + raise + invocation_seconds = time.perf_counter() - invocation_started_at + if captures_debug: + after_event = executor.debug_event( + DebugEventType.AFTER_INVOCATION, + timing_seconds=invocation_seconds, + ) + debug_sink.record(after_event) + if debug_sink.should_stop_after_invocation(after_event): + break + RuntimeProfileSink.record( + "invocation_total", + invocation_seconds, + function=invocation.key.function_name, + group=invocation.key.group_key, + position=invocation.key.position, + ) + if isinstance(current_stack, NoMainFlowOutput): + return current_stack + current_memory_type = executor.invocation.contract.output_memory_type + if group_data.compiled_group.preserves_input_main_flow() and all( + invocation.contract.artifact_output_policy.records_outputs + for invocation in group_data.compiled_group.invocations + ): + return NoMainFlowOutput() + return current_stack - def _validate_and_unstack( + def _project_output_slices( self, processed_stack: RuntimeArrayData, - loaded: PatternGroupData, - ) -> PatternGroupOutputData: - if ( - isinstance(processed_stack, ImagePayloadMetadataCarrier) - and processed_stack.metadata.plane_axis is None + matching_files: Sequence[str], + ) -> tuple[tuple[RuntimeArrayData, AlignedImageSliceContext | None], ...]: + """Project the original output through its nominal image topology.""" + if isinstance(processed_stack, ImagePayloadMetadataCarrier) and ( + processed_stack.metadata.plane_axis is None + or processed_stack.metadata.persists_whole_image() ): output_context = self._unwrapped_main_flow_output_context() - scalar_data = image_payload_data(processed_stack) - stacked_data = stack_runtime_slices( - (scalar_data,), - self.request.execution_plan.output_memory_type, - self.request.execution_plan.device_id_for( - self.request.execution_plan.output_memory_type - ), + contexts = ( + (output_context,) + if output_context is not None + else ( + self._producer_output_contexts(matching_files) + if len(matching_files) == 1 + else () + ) ) - return PatternGroupOutputData( - slices=(processed_stack,), - slice_contexts=( - (output_context,) - if output_context is not None - else ( - self._producer_output_contexts(loaded.matching_files) - if len(loaded.matching_files) == 1 - else () - ) - ), - stack_payload=stack_image_payload_context( - (processed_stack,), - stacked_data, - metadata_mode=ImagePayloadMetadataCompositionMode.STACK, - ), + context = ( + contexts[0] if contexts + else AlignedImageSliceContext.anonymous_main_flow() ) + return ((processed_stack, context),) if isinstance(processed_stack, AlignedImageStack): - return PatternGroupOutputData.from_aligned_stack( - processed_stack, - memory_type=self.request.execution_plan.output_memory_type, - device_id=self.request.execution_plan.device_id_for( - self.request.execution_plan.output_memory_type - ), - ) + return tuple(processed_stack.projected_output_slices()) output_context = self._unwrapped_main_flow_output_context() output_projection = RuntimeSliceProjection.preserved_context_for_value( processed_stack @@ -3187,7 +2164,7 @@ def _validate_and_unstack( self.request.execution_plan.device_id_for( self.request.execution_plan.output_memory_type ), - expected_count=len(loaded.matching_files), + expected_count=len(matching_files), ) ) RuntimeProfileSink.record( @@ -3228,13 +2205,14 @@ def _validate_and_unstack( if output_context is not None else () ) - if not slice_contexts and len(output_payloads) == len(loaded.matching_files): - slice_contexts = self._producer_output_contexts(loaded.matching_files) - return PatternGroupOutputData( - slices=output_payloads, - slice_contexts=slice_contexts, - stack_payload=processed_stack, - ) + if not slice_contexts and len(output_payloads) == len(matching_files): + slice_contexts = self._producer_output_contexts(matching_files) + if not slice_contexts: + slice_contexts = tuple( + AlignedImageSliceContext.anonymous_main_flow() + for _payload in output_payloads + ) + return tuple(zip(output_payloads, slice_contexts, strict=True)) def _unwrapped_main_flow_output_context( self, @@ -3248,11 +2226,54 @@ def _unwrapped_main_flow_output_context( def _save_outputs( self, - output_data: PatternGroupOutputData, + processed_stack: RuntimeArrayData, matching_files: list[str], ) -> list[ProducedOutputSemantics]: context = self.request.context - output_slices = output_data.slices + unstack_started_at = time.perf_counter() + projected_outputs = self._project_output_slices(processed_stack, matching_files) + plan = self.request.execution_plan + explicit_output_surfaces = isinstance(processed_stack, AlignedImageStack) + if explicit_output_surfaces: + stack_payload = processed_stack.copy_projected_output_stack( + projected_outputs, + memory_type=plan.output_memory_type, + device_id=plan.device_id_for(plan.output_memory_type), + ) + elif isinstance(processed_stack, ImagePayloadMetadataCarrier) and ( + processed_stack.metadata.plane_axis is None + or processed_stack.metadata.persists_whole_image() + ): + stack_payload = ImagePayloadStackComposition.copy_whole_image( + processed_stack, + memory_type=plan.output_memory_type, + device_id=plan.device_id_for(plan.output_memory_type), + ) + else: + stack_payload = processed_stack + RuntimeProfileSink.record( + "pattern_validate_unstack", + time.perf_counter() - unstack_started_at, + step=plan.step_index, + step_name=plan.step_name, + pattern=self.pattern_repr, + ) + output_contexts = tuple( + context if context is not None else AlignedImageSliceContext.anonymous_main_flow() + for _payload, context in projected_outputs + ) + save_started_at = time.perf_counter() + + def plane_axis_for_output( + context: AlignedImageSliceContext, + ) -> RuntimePlaneAxis | None: + if isinstance(processed_stack, AlignedImageStack): + return processed_stack.plane_axis_for_output_context(context) + if isinstance(processed_stack, ImagePayloadMetadataCarrier): + return image_payload_metadata(processed_stack).plane_axis + return RuntimePlaneAxis.RUNTIME_SLICE + + output_slices = tuple(payload for payload, _context in projected_outputs) num_outputs = len(output_slices) num_inputs = len(matching_files) @@ -3296,7 +2317,7 @@ def _save_outputs( identity_cache=context.runtime_function_output_identity_cache, ) try: - output_identity = FunctionOutputIdentityAuthority.identity( + output_identity = FunctionOutputIdentity.from_request( output_path_request ) except ValueError as exc: @@ -3307,15 +2328,19 @@ def _save_outputs( f"{i} does not carry payload component identity." ) from exc raise - output_context = output_data.slice_contexts[i] - if not output_context.is_anonymous_main_flow: + output_context = output_contexts[i] + # Only explicit aligned output surfaces own filename qualifiers. + # An unwrapped canonical artifact still owns its typed source + # context, while its ordinary main-flow checkpoint keeps the + # source filename independently of named artifact materialization. + if ( + explicit_output_surfaces + and not output_context.is_anonymous_main_flow + ): output_identity = output_identity.with_filename_qualifier( output_context.output_key ) - output_path = FunctionOutputPathAuthority.output_path_for_identity( - output_path_request, - output_identity, - ) + output_path = output_identity.path_for_request(output_path_request) output_path_text = str(output_path) output_path_entries.append( OutputPathBatchEntry( @@ -3341,6 +2366,7 @@ def _save_outputs( output_identity, output_context=output_context, image_metadata=output_metadata, + main_flow_plane_axis=plane_axis_for_output(output_context), ) if output_directory_exists and context.filemanager.exists( @@ -3378,23 +2404,15 @@ def _save_outputs( output_paths_batch, Backend.MEMORY.value, ) - stack_payload_data = ( - image_payload_data(output_data.stack_payload) - if output_data.stack_payload is not None - else None - ) - if output_data.stack_payload is not None: - if np.shape(stack_payload_data)[:1] != (len(output_payloads),): - raise ValueError( - "PatternGroupOutputData.stack_payload must match its declared " - f"output slice count: stack shape {np.shape(stack_payload_data)!r}, " - f"slice count {len(output_payloads)}." - ) - stack_payload = stack_image_payload_context_from_metadata( + if stack_payload is not None: + stack_payload = ImagePayloadStackComposition.with_saved_output_context( + stack_payload, output_payloads, - stack_payload_data, output_payload_metadata, - metadata_mode=ImagePayloadMetadataCompositionMode.STACK, + single_output_plane_axis=( + plane_axis_for_output(output_contexts[0]) + if len(output_payloads) == 1 else None + ), ) context.runtime_image_stack_cache.store( tuple(output_paths_batch), @@ -3409,16 +2427,23 @@ def _save_outputs( paths=len(output_paths_batch), memory_type=self.request.execution_plan.output_memory_type, ) + RuntimeProfileSink.record( + "pattern_save_outputs", + time.perf_counter() - save_started_at, + step=plan.step_index, + step_name=plan.step_name, + pattern=self.pattern_repr, + ) return output_records def _cleanup_collapsed_domains( self, - output_slices: list[RuntimeArrayData], + output_records: Sequence[ProducedOutputSemantics], matching_files: list[str], output_paths: Sequence[str], ) -> None: context = self.request.context - num_outputs = len(output_slices) + num_outputs = len(output_records) num_inputs = len(matching_files) if num_outputs >= num_inputs: diff --git a/openhcs/core/virtual_workspace_metadata.py b/openhcs/core/virtual_workspace_metadata.py index 6ef9709f73..65cd0d90d1 100644 --- a/openhcs/core/virtual_workspace_metadata.py +++ b/openhcs/core/virtual_workspace_metadata.py @@ -5,7 +5,7 @@ import json import logging import os -from collections.abc import Mapping, Sequence +from collections.abc import Iterable, Mapping, Sequence from dataclasses import dataclass, field from pathlib import Path from types import MappingProxyType @@ -21,9 +21,9 @@ from openhcs.core.runtime_image_values import ImagePayloadMetadata from openhcs.core.source_bindings import SourceProjectionRole from openhcs.core.source_metadata import ( + DurableSourceMetadata, SourceMetadataMapping, SourceMetadataScalar, - SourceMetadataValue, SourceVoxelSpacing, ) from openhcs.core.source_projection import ( @@ -97,7 +97,12 @@ def update(data: dict[str, Any] | None) -> dict[str, Any]: } else: subdirectory[key] = value - self._update_projection_geometry(subdirectory) + self._update_projection_geometry( + subdirectory, + VirtualWorkspaceSourceProjectionEntries.from_subdirectory( + subdirectory + ).entries.values(), + ) return data self._execute_update( @@ -129,7 +134,7 @@ def merge_source_projection_metadata( self, metadata_path: str | Path, subdirectory_name: str, - projection_metadata: Mapping[str, Any] | None = None, + projection_entries: VirtualWorkspaceSourceProjectionEntries, ) -> None: """Merge exact produced paths under one lock, preserving other wells.""" @@ -138,41 +143,20 @@ def update(data): subdirectory = data[METADATA_CONFIG.SUBDIRECTORIES_KEY].setdefault( subdirectory_name, {} ) - self._merge_source_projection_fields(subdirectory, projection_metadata) - self._update_projection_geometry(subdirectory) + entries = projection_entries.merge_into_subdirectory(subdirectory) + self._update_projection_geometry( + subdirectory, + entries.entries.values(), + ) return data self._execute_update(metadata_path, update) - @staticmethod - def _merge_source_projection_fields( - subdirectory: dict[str, Any], - projection_metadata: Mapping[str, Any] | None, - ) -> None: - """Merge the one durable projection store; shared by both transactions.""" - for key in (FIELDS.WORKSPACE_MAPPING, FIELDS.SOURCE_METADATA): - subdirectory[key] = { - **subdirectory.get(key, {}), - **({} if projection_metadata is None else projection_metadata[key]), - } - entries = { - record["virtual_path"]: record - for record in subdirectory.get(FIELDS.SOURCE_PROJECTION, []) - } - if projection_metadata is not None: - entries.update( - { - record["virtual_path"]: record - for record in projection_metadata[FIELDS.SOURCE_PROJECTION] - } - ) - subdirectory[FIELDS.SOURCE_PROJECTION] = list(entries.values()) - def publish_source_projection_metadata( self, metadata_path: str | Path, subdirectory_name: str, - projection_metadata: Mapping[str, Any] | None, + projection_entries: VirtualWorkspaceSourceProjectionEntries | None, *, serializer: SourceProjectionMetadataSerializer, saved_image_paths: Sequence[str], @@ -190,76 +174,72 @@ def publish_source_projection_metadata( inventing coordinates from filenames or the input label cache. """ saved_paths = tuple(saved_image_paths) - saved_set = frozenset(saved_paths) def update(data): data = self._ensure_subdirectories_structure(data) subdirectory = data[METADATA_CONFIG.SUBDIRECTORIES_KEY].setdefault( subdirectory_name, {} ) - self._merge_source_projection_fields(subdirectory, projection_metadata) - entries = VirtualWorkspaceSourceProjectionEntries.from_subdirectory( - subdirectory + entries = ( + VirtualWorkspaceSourceProjectionEntries(MappingProxyType({})) + if projection_entries is None else projection_entries + ).publish_into_subdirectory( + subdirectory, + saved_image_paths=saved_paths, + reconcile_directory=( + subdirectory_name if projection_entries is None else None + ), ).entries - missing = saved_set.difference(entries) - if missing and projection_metadata is None: - raise MetadataWriteError( - f"Saved images lack typed produced addresses: {sorted(missing)!r}." - ) # Concurrent axes may persist their pixels before publishing their # own producer records. A step publishes known saved addresses only; # completed-plate reconciliation requires the entire saved inventory. published_paths = tuple(path for path in saved_paths if path in entries) - # Only final reconciliation can prune deleted images: a step's file - # snapshot may precede another axis's concurrent publication. - retained_paths = tuple( - (projection, path) - for path, projection in entries.items() - if ( - projection_metadata is not None - or path in saved_set - or Path(path).parent != Path(subdirectory_name) + if published_paths: + projections = SourceProjectionSet( + tuple(entries[path] for path in published_paths) + ) + subdirectory.update( + serializer.component_metadata(projections, labels=component_labels) ) - ) - subdirectory.update(serializer.projection_fields(retained_paths)) - projections = SourceProjectionSet( - tuple(entries[path] for path in published_paths) - ) - subdirectory.update( - serializer.component_metadata(projections, labels=component_labels) - ) subdirectory[FIELDS.IMAGE_FILES] = list(published_paths) subdirectory[FIELDS.MICROSCOPE_HANDLER_NAME] = microscope_handler_name - subdirectory[FIELDS.SOURCE_FILENAME_PARSER_NAME] = source_filename_parser_name + subdirectory[FIELDS.SOURCE_FILENAME_PARSER_NAME] = ( + source_filename_parser_name + ) subdirectory[FIELDS.AVAILABLE_BACKENDS] = { - **subdirectory.get(FIELDS.AVAILABLE_BACKENDS, {}), backend: True + **subdirectory.get(FIELDS.AVAILABLE_BACKENDS, {}), + backend: True, } if is_main: subdirectory[serializer.MAIN_FIELD] = True if results_dir is not None: subdirectory[serializer.RESULTS_DIR_FIELD] = results_dir - self._update_projection_geometry(subdirectory) + self._update_projection_geometry( + subdirectory, + entries.values(), + ) return data self._execute_update(metadata_path, update) @staticmethod - def _update_projection_geometry(subdirectory: dict[str, Any]) -> None: - entries = VirtualWorkspaceSourceProjectionEntries.from_subdirectory( - subdirectory - ).entries - if not entries: - return + def _update_projection_geometry( + subdirectory: dict[str, Any], + source_projections: Iterable[SourceProjection], + ) -> None: + """Derive geometry from the transaction's current nominal projections.""" unique_projections: dict[tuple[object, ...], SourceProjection] = {} - for projection in entries.values(): + for projection in source_projections: unique_projections.setdefault(projection.identity_key, projection) + if not unique_projections: + return projections = SourceProjectionSet(tuple(unique_projections.values())) subdirectory[FIELDS.GRID_DIMENSIONS] = ( SourceTileLayout.metadata_grid_dimensions(projections) ) subdirectory[FIELDS.PIXEL_SIZE] = SourceVoxelSpacing.metadata_pixel_size( SourceVoxelSpacing.from_source_metadata(projection.source_metadata) - for projection in projections.plane_projections + for projection in projections.execution_anchor_projections ) def _execute_update( @@ -436,6 +416,157 @@ class VirtualWorkspaceSourceProjectionEntries: entries: Mapping[str, SourceProjection] + @property + def projection_paths(self) -> tuple[tuple[SourceProjection, str], ...]: + """Expose serialization order directly from the admitted path owner.""" + return tuple((projection, path) for path, projection in self.entries.items()) + + @classmethod + def from_projection_paths( + cls, + projection_paths: Sequence[tuple[SourceProjection, str]], + ) -> "VirtualWorkspaceSourceProjectionEntries": + """Admit a producer's typed updates in persisted path order.""" + SourceProjectionSet( + tuple(projection for projection, _path in projection_paths) + ) + return cls( + MappingProxyType( + {path: projection for projection, path in projection_paths} + ) + ) + + @staticmethod + def _records_by_path( + subdirectory: OpenHCSSubdirectoryPayload, + ) -> dict[str, JsonValue]: + for key in (FIELDS.WORKSPACE_MAPPING, FIELDS.SOURCE_METADATA): + if not isinstance(subdirectory.get(key, {}), Mapping): + raise TypeError(f"virtual_workspace {key} must be a mapping.") + # Transactions have always replaced duplicate paths before admitting + # records. In particular, a new producer can repair an invalid old record. + return { + record["virtual_path"]: record + for record in subdirectory.get(FIELDS.SOURCE_PROJECTION, []) + } + + def merged_with_subdirectory( + self, + subdirectory: OpenHCSSubdirectoryPayload, + ) -> "VirtualWorkspaceSourceProjectionEntries": + """Admit current durable records, retaining the actual typed replacements.""" + records = self._records_by_path(subdirectory) + return self._admit_retained_records(records) + + def _admit_retained_records( + self, + records: Mapping[str, JsonValue], + ) -> "VirtualWorkspaceSourceProjectionEntries": + entries: dict[str, SourceProjection] = {} + for path, record in records.items(): + virtual_path, projection = ( + (path, self.entries[path]) + if path in self.entries else self._projection_record(record) + ) + if virtual_path in entries: + raise RuntimeError( + "virtual_workspace source_projection contains duplicate path " + f"{virtual_path!r}." + ) + entries[virtual_path] = projection + for path, projection in self.entries.items(): + if path not in records: + if path in entries: + raise RuntimeError( + "virtual_workspace source_projection contains duplicate path " + f"{path!r}." + ) + entries[path] = projection + return type(self)(MappingProxyType(entries)) + + def merge_into_subdirectory( + self, + subdirectory: dict[str, Any], + ) -> "VirtualWorkspaceSourceProjectionEntries": + """Merge producer fields without normalizing opaque retained wire fields.""" + records = self._records_by_path(subdirectory) + admitted = self._admit_retained_records(records) + fields = SourceProjectionMetadataSerializer.projection_fields( + self.projection_paths + ) + for key in (FIELDS.WORKSPACE_MAPPING, FIELDS.SOURCE_METADATA): + subdirectory[key] = {**subdirectory.get(key, {}), **fields[key]} + records.update( + (record["virtual_path"], record) + for record in fields[FIELDS.SOURCE_PROJECTION] + ) + subdirectory[FIELDS.SOURCE_PROJECTION] = list(records.values()) + return admitted + + def publish_into_subdirectory( + self, + subdirectory: dict[str, Any], + *, + saved_image_paths: Sequence[str], + reconcile_directory: str | None, + ) -> "VirtualWorkspaceSourceProjectionEntries": + """Publish current path views while retaining admitted durable records. + + Step snapshots cannot prune another axis's publication. Only completed + directory reconciliation requires complete inventory and removes deleted + paths. Retained records keep their original wire annotations; the two + workspace maps are independently derived normalized views. + """ + records = self._records_by_path(subdirectory) + admitted = self._admit_retained_records(records) + saved_set = frozenset(saved_image_paths) + missing = saved_set.difference(admitted.entries) + if missing and reconcile_directory is not None: + raise MetadataWriteError( + f"Saved images lack typed produced addresses: {sorted(missing)!r}." + ) + retained = type(self)( + MappingProxyType( + { + path: projection + for path, projection in admitted.entries.items() + if ( + reconcile_directory is None + or path in saved_set + or Path(path).parent != Path(reconcile_directory) + ) + } + ) + ) + workspace_fields = SourceProjectionMetadataSerializer.workspace_fields( + retained.projection_paths + ) + retained_records = {} + for path, record in records.items(): + if path in self.entries: + continue # Replacements can repair an invalid durable record. + canonical_path = self._required_text(record, "virtual_path") + if canonical_path in retained.entries: + retained_records[canonical_path] = ( + record if path == canonical_path + else {**record, "virtual_path": canonical_path} + ) + retained_records.update( + (record["virtual_path"], record) + for record in SourceProjectionMetadataSerializer.projection_records( + tuple( + (projection, path) + for path, projection in self.entries.items() + if path in retained.entries + ) + ) + ) + subdirectory.update(workspace_fields) + subdirectory[FIELDS.SOURCE_PROJECTION] = [ + retained_records[path] for path in retained.entries + ] + return retained + @classmethod def from_subdirectory( cls, @@ -674,51 +805,7 @@ def normalize_metadata_fields(metadata_fields: JsonValue) -> SourceMetadataMappi raise RuntimeError( "virtual_workspace source metadata values must be mappings." ) - return MappingProxyType( - { - str( - key - ): VirtualWorkspaceSourceMetadataEntries.normalize_metadata_value(value) - for key, value in metadata_fields.items() - } - ) - - @staticmethod - def normalize_metadata_value(value: JsonValue) -> SourceMetadataValue: - if isinstance(value, Mapping): - return MappingProxyType( - { - str( - nested_key - ): VirtualWorkspaceSourceMetadataEntries.require_scalar_metadata_value( - nested_value - ) - for nested_key, nested_value in value.items() - } - ) - return VirtualWorkspaceSourceMetadataEntries.require_scalar_metadata_value( - value - ) - - @staticmethod - def require_scalar_metadata_value(value: JsonValue) -> SourceMetadataScalar: - # Scalar fast path first: metadata values are overwhelmingly scalars, - # and the container ABC isinstance checks below are comparatively - # expensive per field. - if value is None or isinstance(value, (str, int, float, bool)): - return value - if isinstance(value, Mapping) or ( - isinstance(value, Sequence) and not isinstance(value, str) - ): - raise RuntimeError( - "virtual_workspace source metadata supports scalar values and " - "one-level scalar mappings only." - ) - raise RuntimeError( - "virtual_workspace source metadata scalar values must be strings, " - "numbers, booleans, or null." - ) - return value + return DurableSourceMetadata.from_mapping(metadata_fields) def metadata_for(self, virtual_path: str) -> SourceMetadataMapping: metadata = self.entries.get(virtual_path) diff --git a/openhcs/interop/cellprofiler/analyst_export.py b/openhcs/interop/cellprofiler/analyst_export.py index 171e971eb4..6d6a7d846d 100644 --- a/openhcs/interop/cellprofiler/analyst_export.py +++ b/openhcs/interop/cellprofiler/analyst_export.py @@ -69,7 +69,7 @@ SourceImageProvenance, ) from openhcs.core.source_bindings import CompiledSourceBindingPlan -from openhcs.core.source_metadata import SourceMetadataRoleView, SourceMetadataScalar +from openhcs.core.source_metadata import SourceMetadataFields, SourceMetadataScalar from openhcs.core.source_workspace_projection import ( VirtualWorkspacePathLookup, VirtualWorkspaceSourceProjectionAuthority, @@ -85,7 +85,6 @@ from .image_set_numbering import CellProfilerImageSetNumbering from .measurement_dialect import ( CELLPROFILER_MEASUREMENT_DIALECT, - cellprofiler_projected_measurement_feature_name, ) from .module_declarations import CellProfilerModule from .source_metadata import CellProfilerSourceMetadataField @@ -677,9 +676,9 @@ def measurement_rows_by_subject( accumulator = WideMeasurementRowAccumulator( CELLPROFILER_MEASUREMENT_DIALECT.row_identity_contract ) - accumulator.add( + accumulator.add_declared_rows( projected_rows, - cellprofiler_projected_measurement_feature_name, + CELLPROFILER_MEASUREMENT_DIALECT, default_subject=default_subject, default_scope=table.subject.scope, source_image_name=table.source_image_name, @@ -817,7 +816,7 @@ def _project_measurement_field( dtype=None if value_field is None else value_field.dtype, required=False, ) - feature_name = cellprofiler_projected_measurement_feature_name( + feature_name = CELLPROFILER_MEASUREMENT_DIALECT.projected_feature_name( field_name, (), ) @@ -955,7 +954,7 @@ def collect_image_provenance( ] = source_path.as_uri() if component_metadata is not None: metadata_items.update( - SourceMetadataRoleView(component_metadata).original_items() + SourceMetadataFields.original_items(component_metadata) ) image_number = self.image_set_numbering.for_source_slice( scope=scope, @@ -991,7 +990,7 @@ def collect_recorded_image_provenance( record for record in records if record.key.name == channel.alias ) for record in channel_records: - provenance = image_payload_metadata(record.value.data).source_provenance + provenance = image_payload_metadata(record.data).source_provenance self.collect_image_provenance( provenance, scope=record.key.scope, @@ -1285,7 +1284,7 @@ def build( ), ) all_measurement_tables = tuple( - cast(MeasurementTable, record.value.data) + cast(MeasurementTable, record.data) for records in measurement_records.values() for record in records ) @@ -1398,7 +1397,7 @@ def _collect_measurements( ], ) -> tuple[tuple[FieldSpec, ...], tuple[FieldSpec, ...]]: for record in records: - table = cast(MeasurementTable, record.value.data) + table = cast(MeasurementTable, record.data) image_columns, experiment_columns = self._collect_measurement_table( table=table, scope=record.key.scope, @@ -1558,7 +1557,7 @@ def _collect_relationships( ], ) -> None: for record in records: - relationship = cast(ObjectRelationship, record.value.data) + relationship = cast(ObjectRelationship, record.data) relationship_declaration = relationship.declaration declaration = ( relationship_declaration.relationship_type, @@ -1591,7 +1590,7 @@ def _collect_measurement_provenance( ) -> None: channel_aliases = frozenset(channel.alias for channel in image_channels) for record in records: - table = cast(MeasurementTable, record.value.data) + table = cast(MeasurementTable, record.data) provenance = table.source_provenance for source_image_name in provenance.represented_source_image_names: if source_image_name not in channel_aliases: @@ -1646,7 +1645,7 @@ def _collect_image_thumbnails( for record in records: if record.key.name != image_name: continue - payload = record.value.data + payload = record.data provenance = image_payload_metadata(payload).source_provenance image_numbers = row_projection.image_numbers_for_provenance( provenance, diff --git a/openhcs/interop/cellprofiler/compile_time_contracts.py b/openhcs/interop/cellprofiler/compile_time_contracts.py index f1f52a4912..10a76e3515 100644 --- a/openhcs/interop/cellprofiler/compile_time_contracts.py +++ b/openhcs/interop/cellprofiler/compile_time_contracts.py @@ -147,29 +147,25 @@ def provider_for_session( ] = {} forward_context = ArtifactDeclarationStepContext.empty() next_module_num = 1 - for snapshot in session.snapshots: - if ( - not snapshot.step.enabled - or not isinstance(snapshot.step, FunctionStep) - or snapshot.step.func is None - ): + for step_index, step in enumerate(session.pipeline.steps): + if not step.enabled or not isinstance(step, FunctionStep) or step.func is None: continue - source_bindings = snapshot.step.source_bindings + source_bindings = step.source_bindings effective_source_bindings = source_bindings.for_input_source( - snapshot.step.processing_config.input_source + step.processing_config.input_source ) forward_context = replace( forward_context, - step_name=snapshot.step.name, - step_index=snapshot.index, + step_name=step.name, + step_index=step_index, ).with_source_binding_scope( source_bindings=effective_source_bindings, - group_by=snapshot.step.processing_config.group_by, - input_source=snapshot.step.processing_config.input_source, + group_by=step.processing_config.group_by, + input_source=step.processing_config.input_source, ) step_context = forward_context - normalized_pattern = normalize_function_pattern(snapshot.step.func) + normalized_pattern = normalize_function_pattern(step.func) first_step_module_num = next_module_num step_invocations = [] group_contexts: list[ArtifactDeclarationStepContext] = [] @@ -210,7 +206,7 @@ def provider_for_session( ( ArtifactSpec.input( unnamed_main_flow_artifact_name( - snapshot.index, + step_index, invocation.key, ), ImageArtifactType, @@ -255,7 +251,7 @@ def provider_for_session( except (TypeError, ValueError) as exc: raise type(exc)( "CellProfiler contract compilation failed for step " - f"{snapshot.index} ({snapshot.step.name!r}), invocation " + f"{step_index} ({step.name!r}), invocation " f"{invocation.key!r}, module {module_type.__name__}: {exc}" ) from exc compiled_contract = replace( @@ -272,11 +268,11 @@ def provider_for_session( ), ), ) - key = (snapshot.index, invocation.key) + key = (step_index, invocation.key) if key in plans: raise ValueError( f"Duplicate CellProfiler invocation contract for step " - f"{snapshot.index} ({snapshot.step.name!r}), invocation " + f"{step_index} ({step.name!r}), invocation " f"{invocation.key!r}, module {module_type.__name__}: " f"{key!r}." ) diff --git a/openhcs/interop/cellprofiler/measurement_dialect.py b/openhcs/interop/cellprofiler/measurement_dialect.py index 74c75ade8d..bdf6d497d2 100644 --- a/openhcs/interop/cellprofiler/measurement_dialect.py +++ b/openhcs/interop/cellprofiler/measurement_dialect.py @@ -11,7 +11,6 @@ RuntimeEquivalencePolicy, RuntimeMeasurementDialect, RuntimeMeasurementSourceNameEncoding, - measurement_row_qualifiers, ) from openhcs.core.measurement_lookup_dialect import ( RuntimeMeasurementFeatureLookup, @@ -212,23 +211,6 @@ def cellprofiler_lookup_dialect_for_measurement_owner( ) -@lru_cache(maxsize=8192) -def cellprofiler_projected_measurement_feature_name( - feature_name: str, - qualifier_values: tuple[tuple[str, object], ...], -) -> str: - """Append declared descriptor axes to an exact producer feature name.""" - - qualifiers = measurement_row_qualifiers( - dict(qualifier_values), - CELLPROFILER_MEASUREMENT_DIALECT, - feature_name, - ) - if not qualifiers: - return feature_name - return "_".join((feature_name, *qualifiers)) - - def cellprofiler_runtime_equivalence_policy( **overrides: object, ) -> RuntimeEquivalencePolicy: diff --git a/openhcs/interop/cellprofiler/module_artifact_contracts.py b/openhcs/interop/cellprofiler/module_artifact_contracts.py index 6b7e254050..14ccb568b1 100644 --- a/openhcs/interop/cellprofiler/module_artifact_contracts.py +++ b/openhcs/interop/cellprofiler/module_artifact_contracts.py @@ -28,7 +28,6 @@ normalize_cellprofiler_setting_name, ) from openhcs.interop.cellprofiler.setting_names import ( - setting_name_matches, setting_names, setting_values, ) @@ -123,39 +122,6 @@ def artifact_names_for_binding( for name in split_symbol_names(value) ) - @classmethod - def split_invocation_blocks_for_binding( - cls, - modules: tuple["ModuleBlock", ...], - binding: SettingToKeywordBinding, - ) -> tuple["ModuleBlock", ...]: - """Split repeated artifact selections into exact scalar invocations.""" - - split_blocks: list[ModuleBlock] = [] - for module in modules: - names = cls.artifact_names_for_binding(module, binding) - if len(names) <= 1: - split_blocks.append(module) - continue - retained_records = tuple( - record - for record in module.iter_settings() - if not setting_name_matches(record.name, binding.setting_name) - ) - split_blocks.extend( - replace( - module, - setting_records=[ - *retained_records, - *binding.records_from_kwargs( - {binding.require_parameter_name(): name} - ), - ], - ) - for name in names - ) - return tuple(split_blocks) - @classmethod def main_flow_output_specs( cls, @@ -1067,7 +1033,9 @@ def artifact_output_relations( del module, binding, name, step_context, output_position primary_images = cls.primary_image_inputs( - cls.require_callable(invocation_key.function_name), + CallableContract.from_prepared_callable( + cls.require_callable(invocation_key.function_name) + ), artifact_inputs.specs, ) lineage_inputs = ArtifactSpecCollection( @@ -1192,7 +1160,7 @@ def callable_contract( group_key=invocation_key.group_key, ) func = cls.require_callable(invocation_key.function_name) - callable_contract = CallableContract.from_callable(func) + callable_contract = CallableContract.from_prepared_callable(func) inputs = cls.artifact_contract_inputs( module, invocation_key=invocation_key, @@ -1205,7 +1173,7 @@ def callable_contract( artifact_inputs=ArtifactSpecCollection(inputs), ) remaining_inputs = list(inputs) - primary_image_inputs = cls.primary_image_inputs(func, inputs) + primary_image_inputs = cls.primary_image_inputs(callable_contract, inputs) for primary_image_input in primary_image_inputs: remaining_inputs.remove(primary_image_input) artifact_inputs = ArtifactSpecCollection( diff --git a/openhcs/interop/cellprofiler/module_artifact_declarations.py b/openhcs/interop/cellprofiler/module_artifact_declarations.py index f7534336f8..143e485998 100644 --- a/openhcs/interop/cellprofiler/module_artifact_declarations.py +++ b/openhcs/interop/cellprofiler/module_artifact_declarations.py @@ -12,6 +12,7 @@ ClassVar, ) +from openhcs.constants.input_source import InputSource from openhcs.core.artifacts import ( ArtifactInputPlan, ArtifactOutputPlan, @@ -23,6 +24,7 @@ ImageArtifactType, ImageMeasurementSubjectRelation, InputGroupLineageSourceRelation, + InputImageSetContextSourceRelation, MeasurementsArtifactType, ObjectLabelsArtifactType, ObjectLineageArtifactType, @@ -64,6 +66,7 @@ from openhcs.core.function_patterns import ( FunctionInvocationKey, + NormalizedFunctionItem, ) from openhcs.core.runtime_image_values import ImagePayloadMetadata from openhcs.core.runtime_tabular_values import ColumnarRows @@ -726,7 +729,9 @@ def measurement_output_relations( for artifact_input in artifact_inputs.specs ) invocation_domain_inputs = cls.invocation_domain_inputs( - cls.require_callable(invocation_key.function_name), + CallableContract.from_prepared_callable( + cls.require_callable(invocation_key.function_name) + ), artifact_inputs.specs, ) return ( @@ -1188,6 +1193,58 @@ class ImageMeasurementInputModule( image_measurement_binding, ) + @classmethod + def finalize_artifact_contract_inputs( + cls, + module: "ModuleBlock", + *, + invocation_key: "FunctionInvocationKey", + step_context: "ArtifactDeclarationStepContext", + artifact_inputs: ArtifactSpecCollection, + ) -> tuple[ArtifactSpec, ...]: + """Bind measured object sets to exactly the selected input image contexts.""" + inputs = ArtifactSpecCollection( + super().finalize_artifact_contract_inputs( + module, + invocation_key=invocation_key, + step_context=step_context, + artifact_inputs=artifact_inputs, + ) + ) + image_contexts = tuple( + InputImageSetContextSourceRelation(spec.ref()) + for spec in inputs.of_artifact_type(ImageArtifactType) + ) + return tuple( + replace(spec, relations=(*spec.relations, *image_contexts)) + if spec.artifact_type is ObjectLabelsArtifactType and image_contexts + else spec + for spec in inputs + ) + + @classmethod + def input_source_for_contract( + cls, + callable_contract: CallableContract, + *, + step_context: "ArtifactDeclarationStepContext", + ) -> InputSource: + """Keep original measurement images alongside produced image subjects.""" + produced_refs = frozenset( + producer.spec.ref().for_plan_type(ArtifactInputPlan) + for producer in step_context.available_artifact_producers + ) + if any( + spec.ref() not in produced_refs + and step_context.source_bindings.binding_for_artifact_ref(spec.ref()) is not None + for spec in callable_contract.artifact_inputs.of_artifact_type(ImageArtifactType) + ): + return InputSource.PIPELINE_START + return super().input_source_for_contract( + callable_contract, + step_context=step_context, + ) + @classmethod def measurement_output_relations( cls, @@ -1218,29 +1275,6 @@ def measurement_output_relations( *image_subjects, ) - @classmethod - def invocation_module_blocks( - cls, - module: "ModuleBlock", - ) -> tuple["ModuleBlock", ...]: - """Expose each natural measurement image as one public invocation.""" - - blocks = super().invocation_module_blocks(module) - if ( - CallableContract.from_callable( - cls.require_callable() - ).image_payload_consumption - is ImagePayloadConsumption.COMPOSED - ): - return blocks - (binding,) = cls.declared_artifact_bindings( - plan_type=ArtifactInputPlan, artifact_type=ImageArtifactType - ) - return cls.split_invocation_blocks_for_binding( - blocks, - binding, - ) - @classmethod def executes_per_image_measurements( cls, @@ -1312,15 +1346,43 @@ class ObjectMeasurementInputModule( ) @classmethod - def invocation_module_blocks( + def finalize_module_blocks_for_invocation( cls, - module: "ModuleBlock", + blocks: tuple["ModuleBlock", ...], + *, + invocation: "NormalizedFunctionItem", + step_context: "ArtifactDeclarationStepContext", ) -> tuple["ModuleBlock", ...]: - """Expose each measured object set as one scalar-label invocation.""" + """Require selection intent before reconstructing multiple object subjects.""" - return cls.split_invocation_blocks_for_binding( - super().invocation_module_blocks(module), - cls.object_measurement_binding, + blocks = super().finalize_module_blocks_for_invocation( + blocks, invocation=invocation, step_context=step_context, + ) + binding = cls.object_measurement_binding + selector = binding.require_parameter_name() + if selector not in invocation.kwargs_dict: + for block in blocks: + subjects = cls.artifact_names_for_binding(block, binding) + if len(subjects) > 1: + return () + return blocks + + @classmethod + def processing_group_scope_inputs( + cls, + callable_contract: CallableContract, + ) -> tuple[ArtifactSpec, ...]: + """Keep all declared measurement subjects in one logical module batch.""" + source_refs = frozenset( + spec.ref() for spec in ( + *super().processing_group_scope_inputs(callable_contract), + *callable_contract.group_scope_inputs, + ) + ) + return tuple( + spec + for spec in callable_contract.artifact_inputs + if spec.ref() in source_refs ) diff --git a/openhcs/interop/cellprofiler/module_callable_abi.py b/openhcs/interop/cellprofiler/module_callable_abi.py index 78a23086ea..4f7bbe6d63 100644 --- a/openhcs/interop/cellprofiler/module_callable_abi.py +++ b/openhcs/interop/cellprofiler/module_callable_abi.py @@ -166,15 +166,12 @@ def source_context( @classmethod def primary_image_inputs( cls, - func: "Callable[..., RuntimeFunctionOutput]", + contract: CallableContract, declared_inputs: tuple[ArtifactSpec, ...], ) -> tuple[ArtifactSpec, ...]: """Return non-special image inputs that drive invocation slices.""" - if ( - CallableContract.from_callable(func).execution_scope - is FunctionStepExecutionScope.PLATE - ): + if contract.execution_scope is FunctionStepExecutionScope.PLATE: return () image_inputs = ArtifactSpecCollection(declared_inputs).of_artifact_type( ImageArtifactType @@ -188,19 +185,19 @@ def primary_image_inputs( @classmethod def invocation_domain_inputs( cls, - func: "Callable[..., RuntimeFunctionOutput]", + contract: CallableContract, declared_inputs: tuple[ArtifactSpec, ...], ) -> tuple[ArtifactSpec, ...]: """Return the inputs whose component scope owns one invocation.""" - primary_images = cls.primary_image_inputs(func, declared_inputs) + primary_images = cls.primary_image_inputs(contract, declared_inputs) if primary_images: return primary_images object_inputs = ArtifactSpecCollection(declared_inputs).of_artifact_type( ObjectLabelsArtifactType ) if cls.executes_per_object_measurements(object_inputs): - return object_inputs[:1] + return object_inputs return tuple( artifact_input for artifact_input in declared_inputs diff --git a/openhcs/interop/cellprofiler/module_declarations.py b/openhcs/interop/cellprofiler/module_declarations.py index 196f030113..62c99d4dd7 100644 --- a/openhcs/interop/cellprofiler/module_declarations.py +++ b/openhcs/interop/cellprofiler/module_declarations.py @@ -27,7 +27,10 @@ FunctionStepExecutionScope, ) from openhcs.core.config import ProcessingConfig, StepSourceBindingsConfig -from openhcs.core.invocation_artifacts import ArtifactDeclarationStepContext +from openhcs.core.invocation_artifacts import ( + ArtifactDeclarationStepContext, + ArtifactInputPlan, +) from openhcs.core.source_bindings import ( SourceBindingsConfig, ) @@ -489,13 +492,16 @@ def for_callable_contract( module_type = cls.for_callable_import_identity(identity) if module_type is None: return None - canonical_callable = module_type.require_callable(identity.function_name) + canonical_callable = module_type._require_declared_callable( + identity.function_name + ) if raw_callable is not canonical_callable: raise ValueError( f"Callable import identity {identity.import_path!r} claims " f"CellProfiler module {module_type.__name__}, but its object is " "not the declaration-owned canonical callable." ) + module_type._validate_callable_parameter_exclusions(raw_callable, contract) return module_type @classmethod @@ -531,11 +537,11 @@ def require_module_name(cls) -> str: return _required_string(cls.module_name, "module_name", cls.__name__) @classmethod - def require_callable( + def _require_declared_callable( cls, function_name: str | None = None, ) -> Callable[..., Any]: - """Load one raw backend callable declared by this module class.""" + """Resolve the current exact callable without repeating authored preparation.""" selected_name = cls.function_name if function_name is None else function_name selected_name = _required_string( selected_name, @@ -554,10 +560,32 @@ def require_callable( f"CellProfiler module {cls.module_name!r} declares missing " f"callable {selected_name!r} in {cls.__module__!r}." ) + return implementation + + @classmethod + def require_callable( + cls, + function_name: str | None = None, + ) -> Callable[..., Any]: + """Prepare and admit one raw callable at the authored declaration boundary.""" + + implementation = cls._require_declared_callable(function_name) cls._install_callable_parameter_help(implementation) + cls._validate_callable_parameter_exclusions( + implementation, CallableContract.from_callable(implementation), + ) + return implementation + + @classmethod + def _validate_callable_parameter_exclusions( + cls, + implementation: Callable[..., Any], + contract: CallableContract, + ) -> None: + """Keep current exclusion admission while reusing the owned declaration.""" + from python_introspect import parameter_exclusions - contract = CallableContract.from_callable(implementation) excluded_names = parameter_exclusions(implementation) unowned_exclusions = tuple( sorted(excluded_names - contract.runtime_owned_parameter_names) @@ -565,11 +593,10 @@ def require_callable( if unowned_exclusions: raise ValueError( f"CellProfiler module {cls.module_name!r} callable " - f"{selected_name!r} excludes parameters without a runtime-owned " + f"{contract.function_name!r} excludes parameters without a runtime-owned " "callable contract declaration: " f"{unowned_exclusions!r}." ) - return implementation @classmethod def _install_callable_parameter_help( @@ -881,6 +908,31 @@ def resolve_function( del module, contract, source_bindings return cls.require_callable() + @classmethod + def input_source_for_contract( + cls, + callable_contract: CallableContract, + *, + step_context: ArtifactDeclarationStepContext, + ) -> InputSource: + """Resolve the main-flow anchor independently of auxiliary source inputs.""" + produced_refs = frozenset( + producer.spec.ref().for_plan_type(ArtifactInputPlan) + for producer in step_context.available_artifact_producers + ) + if any( + step_context.main_flow_artifacts.by_ref(spec.ref()) is not None + and spec.ref() in produced_refs + for spec in callable_contract.artifact_inputs + ): + return InputSource.PREVIOUS_STEP + if any( + step_context.source_bindings.binding_for_artifact_ref(spec.ref()) is not None + for spec in callable_contract.artifact_inputs + ): + return InputSource.PIPELINE_START + return InputSource.PREVIOUS_STEP + @classmethod def processing_config( cls, @@ -919,11 +971,7 @@ def processing_config( grouping_component = AllComponents.from_value(group_by.value) source_anchor_group_keys = step_context.source_bindings.component_group_keys_for_artifact_specs( grouping_component, - tuple( - spec - for spec in callable_contract.artifact_inputs - if spec.parameter_name is None - ), + cls.processing_group_scope_inputs(callable_contract), step_context.available_artifacts, ) if len(source_anchor_group_keys) > 1: @@ -934,3 +982,15 @@ def processing_config( group_by=group_by, input_source=input_source, ) + + @classmethod + def processing_group_scope_inputs( + cls, + callable_contract: CallableContract, + ) -> tuple[ArtifactSpec, ...]: + """Keep the complete unbound payload domain available for an invocation.""" + return tuple( + spec + for spec in callable_contract.artifact_inputs + if spec.parameter_name is None + ) diff --git a/openhcs/interop/cellprofiler/pipeline_import.py b/openhcs/interop/cellprofiler/pipeline_import.py index c40de79690..b9785bcdfa 100644 --- a/openhcs/interop/cellprofiler/pipeline_import.py +++ b/openhcs/interop/cellprofiler/pipeline_import.py @@ -492,25 +492,9 @@ def _parsed_target_units( raise ValueError( f"CellProfiler module {module.name} resolved a noncanonical callable." ) - follows_produced_main_flow = any( - declaration_context.main_flow_artifacts.by_ref(spec.ref()) is not None - and any( - producer.spec.ref().for_plan_type(ArtifactInputPlan) == spec.ref() - for producer in declaration_context.available_artifact_producers - ) - for spec in contract.artifact_inputs - ) - input_source = ( - InputSource.PREVIOUS_STEP - if follows_produced_main_flow - else ( - InputSource.PIPELINE_START - if any( - source_bindings.binding_for_artifact_ref(spec.ref()) is not None - for spec in contract.artifact_inputs - ) - else InputSource.PREVIOUS_STEP - ) + input_source = module_type.input_source_for_contract( + contract, + step_context=declaration_context, ) public_source_bindings = _public_step_source_bindings( source_bindings, @@ -528,7 +512,7 @@ def _parsed_target_units( inherited_processing_config, input_source=input_source, ), - step_context=processing_context, + step_context=declaration_context, ) public_source_bindings = _public_step_source_bindings( source_bindings, @@ -585,7 +569,7 @@ def _parsed_target_units( inherited_processing_config, input_source=input_source, ), - step_context=resolved_context, + step_context=declaration_context, ) public_source_bindings = _public_step_source_bindings( source_bindings, diff --git a/openhcs/interop/cellprofiler/runtime/adapter.py b/openhcs/interop/cellprofiler/runtime/adapter.py index a50c05656a..0a9f3909b7 100644 --- a/openhcs/interop/cellprofiler/runtime/adapter.py +++ b/openhcs/interop/cellprofiler/runtime/adapter.py @@ -14,6 +14,7 @@ from openhcs.core.artifacts import ( ArtifactOutputPlan, ArtifactSpec, + ArtifactSpecCollection, ArtifactType, ImageArtifactType, MeasurementsArtifactType, @@ -22,10 +23,7 @@ RelationshipsArtifactType, SpatialGridArtifactType, ) -from openhcs.core.runtime_adapters import RuntimeAdapterRequest -from openhcs.core.runtime_artifact_queries import ( - MeasurementTableUnion, -) +from openhcs.core.runtime_adapters import RuntimeAdapterRequest, RuntimeAdapterSpec from openhcs.core.runtime_artifact_values import ( RuntimeValue, ) @@ -90,6 +88,22 @@ def validate_measurement_subject(cls, spec: ArtifactSpec) -> None: spec.require_measurement_feature_owner() +class CellProfilerRuntimeAdapterSpec(RuntimeAdapterSpec): + """Derive CP invocation carriers from the module's declared input domain.""" + + __slots__ = () + + def invocation_domain_inputs( + self, contract: CallableContract, + ) -> ArtifactSpecCollection: + from openhcs.interop.cellprofiler.module_declarations import CellProfilerModule + + module = CellProfilerModule.require_callable_contract_owner(contract) + return ArtifactSpecCollection(module.invocation_domain_inputs( + contract, contract.artifact_inputs.specs, + )) + + @dataclass(slots=True) class CellProfilerRuntimeAdapter(RuntimePlaneAxisProjector): """CellProfiler-like API backed by typed OpenHCS runtime state. @@ -109,13 +123,12 @@ def require_parameter_name(cls) -> str: def runtime_adapter_spec(cls): """Return the sole compiled CellProfiler runtime-adapter declaration.""" - from openhcs.core.runtime_adapters import RuntimeAdapterSpec from openhcs.interop.cellprofiler.runtime.module_execution import ( cellprofiler_runtime_adapter_factory, cellprofiler_runtime_callable_factory, ) - return RuntimeAdapterSpec( + return CellProfilerRuntimeAdapterSpec( parameter_name=cls.require_parameter_name(), factory=cellprofiler_runtime_adapter_factory, manages_artifact_inputs=True, @@ -218,7 +231,7 @@ def artifact_output_value(self, output_plan: ArtifactOutputPlan) -> object: f"CellProfiler output {output_plan.ref()!r} requires exactly one " f"invocation record, got {len(records)}." ) - return RuntimeValue.compose((records[0].value,)) + return RuntimeValue.compose((records[0],)) def require_artifact_available( self, @@ -436,10 +449,9 @@ def get_measurements( MeasurementsArtifactType, group_key=group_key, ) - return MeasurementTableUnion( - name, - tuple(cast(MeasurementTable, record.value.data) for record in records), - ).as_table() + return MeasurementTable.join( + name, tuple(cast(MeasurementTable, record.data) for record in records) + ) def measurement_tables( self, @@ -452,7 +464,7 @@ def measurement_tables( group_key=group_key, match_group=match_group, ) - return tuple(cast(MeasurementTable, record.value.data) for record in records) + return tuple(cast(MeasurementTable, record.data) for record in records) def declared_measurement_input_records( self, diff --git a/openhcs/interop/cellprofiler/runtime/artifact_binding.py b/openhcs/interop/cellprofiler/runtime/artifact_binding.py index 89ce0c7f18..b09760303e 100644 --- a/openhcs/interop/cellprofiler/runtime/artifact_binding.py +++ b/openhcs/interop/cellprofiler/runtime/artifact_binding.py @@ -2,30 +2,21 @@ from __future__ import annotations -from abc import ABC from collections.abc import Callable, Sequence from dataclasses import dataclass, replace -from functools import lru_cache import inspect -from typing import TypeAlias, cast, get_origin +from typing import cast, get_origin from openhcs.core.artifacts import ( - ArtifactOutputPlan, ArtifactSpec, ArtifactSpecCollection, ArtifactSpecRef, - ArtifactType, - ArtifactTypeStrategyMatchMixin, ImageArtifactType, ObjectLabelsArtifactType, - ObjectLineageArtifactType, MeasurementsArtifactType, - SpatialGridArtifactType, ) from openhcs.core.aligned_image_payload import ( - AlignedImageSliceContext, AlignedImageStack, - ImageOutputBundle, ) from openhcs.core.function_patterns import ( InvocationArtifactInputEdgePlan, @@ -34,30 +25,22 @@ from openhcs.core.pipeline.function_contracts import ( object_label_input_execution_mode_from_callable, ) -from openhcs.core.runtime_artifact_queries import MeasurementTableUnion from openhcs.core.runtime_array_values import RuntimeArrayData from openhcs.core.runtime_image_values import ( - image_payload_data, - image_payload_mask, image_payload_metadata, ) from openhcs.core.runtime_measurements import ( MeasurementTable, ) from openhcs.core.runtime_object_labels import ( - ObjectLabelSet, ObjectLabelValue, ) -from openhcs.core.runtime_object_label_building import ( - SourceImageObjectLabelBuildRequest, -) from openhcs.core.runtime_slice_alignment import ( RuntimeSliceAlignedValues, ) from openhcs.core.runtime_slice_projection import RuntimeSliceProjection from openhcs.core.source_matching import SourceImageSetIdentityPolicy from openhcs.core.source_plane_alignment import ( - SourcePayloadPlaneIdentitySequence, SourcePlaneIdentitySequenceAlignment, ) from openhcs.core.runtime_measurements import ( @@ -71,301 +54,17 @@ from openhcs.core.variable_component_stack_requirement import ( VariableComponentStackRequirementRequest, ) -from openhcs.interop.cellprofiler.image_normalization import ( - normalize_cellprofiler_image_payload, -) from openhcs.interop.cellprofiler.runtime.adapter import ( CellProfilerRuntimeAdapter, ) -from openhcs.interop.cellprofiler.runtime.measurement_source_names import ( - single_source_name, -) -from openhcs.interop.cellprofiler.runtime.main_flow import ( - cellprofiler_main_flow_output, +from openhcs.interop.cellprofiler.runtime.output_recording import ( + CellProfilerOutputRecorder, ) from openhcs.core.steps.function_runtime import ( RuntimeCallableArgument, RuntimeCallableKwargs, RuntimeFunctionOutput, ) -from openhcs.core.registry_strategies import ( - MostDerivedContextStrategyMixin, -) - -RuntimeMainFlowArtifactOutput: TypeAlias = tuple[ - ArtifactOutputPlan, - ArtifactSpec, - RuntimeCallableArgument, -] - - -class RuntimeArtifactTypeStrategy( - ArtifactTypeStrategyMatchMixin, - MostDerivedContextStrategyMixin[type[ArtifactType]], - ABC, -): - """Nominal strategy family for ArtifactType-specific runtime semantics.""" - - @classmethod - @lru_cache(maxsize=None) - def for_artifact_type( - cls, - artifact_type: ArtifactType, - ) -> "RuntimeArtifactTypeStrategy": - return cls.for_context( - ArtifactType.coerce(artifact_type), - error_subject="CellProfiler runtime artifact type strategy", - ) - - @classmethod - def for_main_flow_outputs( - cls, - outputs: tuple[RuntimeMainFlowArtifactOutput, ...], - ) -> "RuntimeArtifactTypeStrategy": - """Select one nominal strategy from the complete exact output set.""" - - artifact_types = frozenset( - spec.artifact_type for _plan, spec, _value in outputs - ) - if not artifact_types: - raise ValueError("CellProfiler main-flow publication requires an output.") - if len(artifact_types) != 1: - raise TypeError( - "CellProfiler main-flow outputs require one exact artifact type; " - f"got {tuple(sorted(kind.require_value() for kind in artifact_types))!r}." - ) - (artifact_type,) = artifact_types - return cls.for_artifact_type(artifact_type) - - def runtime_input_value( - self, spec: ArtifactSpec, value: RuntimeCallableArgument - ) -> RuntimeCallableArgument: - """Return the runtime payload bound into absorbed function kwargs.""" - - return value - - def raw_runtime_input_value( - self, spec: ArtifactSpec, value: RuntimeCallableArgument - ) -> RuntimeCallableArgument: - """Return the runtime payload before CellProfiler intensity coercion.""" - return self.runtime_input_value(spec, value) - - def source_image_name( - self, - spec: ArtifactSpec, - value: RuntimeCallableArgument, - ) -> str | None: - """Return the transitive source image name for one artifact input.""" - del spec, value - return None - - def source_image_payload( - self, - spec: ArtifactSpec, - value: RuntimeCallableArgument, - ) -> RuntimeCallableArgument | None: - """Return an image payload that carries this artifact's source paths.""" - return None - - def published_main_flow_output( - self, - input_value: RuntimeCallableArgument, - outputs: tuple[RuntimeMainFlowArtifactOutput, ...], - plane_projection: RuntimePlaneAxisValueProjection | None, - ) -> RuntimeCallableArgument: - """Publish one recorded artifact through the canonical OpenHCS flow.""" - - del input_value, plane_projection - self.validate_main_flow_outputs(outputs) - if len(outputs) != 1: - raise ValueError( - f"{type(self).__name__} requires exactly one main-flow output, " - f"got {len(outputs)}." - ) - return outputs[0][2] - - def validate_main_flow_outputs( - self, - outputs: tuple[RuntimeMainFlowArtifactOutput, ...], - ) -> None: - """Require every published output to belong to this nominal strategy.""" - - artifact_type = type(self).artifact_type - mismatched = tuple( - spec.ref() - for _plan, spec, _value in outputs - if spec.artifact_type is not artifact_type - ) - if mismatched: - raise TypeError( - f"{type(self).__name__} cannot publish outputs {mismatched!r}." - ) - - -class ImageArtifactTypeStrategy(RuntimeArtifactTypeStrategy): - """Resolve image artifact payloads and source-image lineage.""" - - artifact_type = ImageArtifactType - - def raw_runtime_input_value( - self, spec: ArtifactSpec, value: RuntimeCallableArgument - ) -> RuntimeCallableArgument: - payload = value - metadata = image_payload_metadata(payload) - metadata = metadata.with_source_provenance( - metadata.source_provenance.with_derived_source_image_names( - (spec.name,) - ) - ) - return metadata.payload_with( - image_payload_data(payload), - mask=image_payload_mask(payload), - ) - - def runtime_input_value( - self, spec: ArtifactSpec, value: RuntimeCallableArgument - ) -> RuntimeCallableArgument: - return normalize_cellprofiler_image_payload( - self.raw_runtime_input_value(spec, value) - ) - - def source_image_name( - self, - spec: ArtifactSpec, - value: RuntimeCallableArgument, - ) -> str | None: - return single_source_name( - image_payload_metadata( - self.raw_runtime_input_value(spec, value) - ).source_provenance.represented_source_image_names - ) - - def source_image_payload( - self, - spec: ArtifactSpec, - value: RuntimeCallableArgument, - ) -> RuntimeCallableArgument | None: - return self.raw_runtime_input_value(spec, value) - - def published_main_flow_output( - self, - input_value: RuntimeCallableArgument, - outputs: tuple[RuntimeMainFlowArtifactOutput, ...], - plane_projection: RuntimePlaneAxisValueProjection | None, - ) -> RuntimeCallableArgument: - """Publish one or more named image outputs with exact plane context.""" - - self.validate_main_flow_outputs(outputs) - if not outputs: - raise ValueError("Image main-flow publication requires an output.") - return ImageOutputBundle( - tuple( - cellprofiler_main_flow_output( - input_value, - output_value, - plane_projection, - ) - for _plan, _spec, output_value in outputs - ), - AlignedImageSliceContext.main_flow_for_output_plans( - tuple(plan for plan, _spec, _value in outputs) - ), - ) - - -class ObjectLabelsArtifactTypeStrategy(RuntimeArtifactTypeStrategy): - """Resolve object-label payloads and lineage.""" - - artifact_type = ObjectLabelsArtifactType - - def object_labels( - self, - spec: ArtifactSpec, - value: RuntimeCallableArgument, - ) -> ObjectLabelSet: - """Return the native object value carrying its source-image provenance.""" - - if isinstance(value, ObjectLabelSet): - return value - metadata = image_payload_metadata(value) - return SourceImageObjectLabelBuildRequest( - image=value, - labels=image_payload_data(value), - plane_projection=RuntimePlaneAxisValueProjection.from_source_declaration( - metadata.plane_axis, metadata.source_provenance, - ), - ).label_set( - name=spec.name, - source_image_name=spec.name, - ) - - def runtime_input_value( - self, spec: ArtifactSpec, value: RuntimeCallableArgument - ) -> RuntimeCallableArgument: - return self.object_labels(spec, value) - - def raw_runtime_input_value( - self, - spec: ArtifactSpec, - value: RuntimeCallableArgument, - ) -> RuntimeCallableArgument: - """Return the nominal label set in the invocation's component scope.""" - - return self.object_labels(spec, value) - - def source_image_name( - self, - spec: ArtifactSpec, - value: RuntimeCallableArgument, - ) -> str | None: - return self.object_labels(spec, value).source_image_name - - def source_image_payload( - self, - spec: ArtifactSpec, - value: RuntimeCallableArgument, - ) -> RuntimeCallableArgument | None: - return self.object_labels(spec, value) - - -class MeasurementsArtifactTypeStrategy(RuntimeArtifactTypeStrategy): - """Resolve measurement payloads and lineage.""" - - artifact_type = MeasurementsArtifactType - - def runtime_input_value( - self, spec: ArtifactSpec, value: RuntimeCallableArgument - ) -> RuntimeCallableArgument: - if not isinstance(value, MeasurementTable): - raise TypeError( - f"Measurement artifact {spec.name!r} requires a " - f"MeasurementTable, got {type(value).__name__}." - ) - return value.rows - - def source_image_name( - self, - spec: ArtifactSpec, - value: RuntimeCallableArgument, - ) -> str | None: - if not isinstance(value, MeasurementTable): - raise TypeError( - f"Measurement artifact {spec.name!r} requires a " - f"MeasurementTable, got {type(value).__name__}." - ) - return value.source_image_name - - -class RelationshipsArtifactTypeStrategy(RuntimeArtifactTypeStrategy): - """Resolve relationship payloads.""" - - artifact_type = ObjectLineageArtifactType - - -class SpatialGridArtifactTypeStrategy(RuntimeArtifactTypeStrategy): - """Resolve spatial-grid payloads.""" - - artifact_type = SpatialGridArtifactType @dataclass(frozen=True, slots=True, kw_only=True) @@ -519,13 +218,13 @@ def declared_measurement_tables(self) -> tuple[MeasurementTable, ...]: slice_axis = MeasurementRowAxisField.SLICE_INDEX for spec in measurement_specs: spec_tables = tuple( - cast(MeasurementTable, record.value.data) + cast(MeasurementTable, record.data) for record in self.adapter.artifact_input_records( spec.name, MeasurementsArtifactType, ) ) - MeasurementTableUnion(spec.name, spec_tables).row_axis_domain(slice_axis) + MeasurementTable.shared_row_axis_domain(spec.name, spec_tables, slice_axis) tables.extend(spec_tables) return tuple(tables) @@ -577,7 +276,7 @@ def stack_broadcast_source_value( if source_ref in self.declared_inputs.ref_set(): source_spec = self.declared_inputs.by_ref(source_ref) source_edge = self.input_edge_for_spec(source_spec) - return RuntimeArtifactTypeStrategy.for_artifact_type( + return CellProfilerOutputRecorder.for_artifact_type( ImageArtifactType ).runtime_input_value(source_edge.spec, self.artifact_value(source_edge)) @@ -612,20 +311,20 @@ def artifact_value( ) source_plan = self.adapter.request.source_binding_plan source_binding = source_plan.binding_for_artifact_ref(spec.ref()) - consumes_main_flow = edge.consumes_main_flow + primary_projection = edge.main_flow_projection source_artifact_binding = ( source_binding - if edge.storage_plan is None and not consumes_main_flow + if edge.storage_plan is None and primary_projection is None else None ) runtime_edge = ( - edge if edge.storage_plan is not None and not consumes_main_flow else None + edge if edge.storage_plan is not None and primary_projection is None else None ) authority_count = sum( ( source_artifact_binding is not None, runtime_edge is not None, - consumes_main_flow, + primary_projection is not None, ) ) if authority_count != 1: @@ -674,7 +373,9 @@ def artifact_value_for_spec( return self.artifact_value(self.input_edge_for_spec(spec)) def label_payload_for(self, spec: ArtifactSpec) -> ObjectLabelValue: - return ObjectLabelsArtifactTypeStrategy().object_labels( + return CellProfilerOutputRecorder.for_artifact_type( + ObjectLabelsArtifactType + ).object_labels( spec, self.artifact_value_for_spec(spec) ) @@ -806,13 +507,15 @@ def runtime_value( spec = edge.spec if spec.artifact_type is ObjectLabelsArtifactType: - payload = ObjectLabelsArtifactTypeStrategy().object_labels( + payload = CellProfilerOutputRecorder.for_artifact_type( + ObjectLabelsArtifactType + ).object_labels( spec, self.artifact_value(edge) ) if parameter_name is not None: return self.project_label_argument(payload) return payload - value = RuntimeArtifactTypeStrategy.for_artifact_type( + value = CellProfilerOutputRecorder.for_artifact_type( spec.artifact_type ).runtime_input_value(spec, self.artifact_value(edge)) if spec.artifact_type is not ImageArtifactType: @@ -856,14 +559,12 @@ def runtime_value( identity_policy = SourceImageSetIdentityPolicy.from_source_bindings( self.adapter.request.source_binding_plan ) - image_axis = SourcePayloadPlaneIdentitySequence( - broadcast_source, - identity_policy, - ).runtime_axis_identities() - value_axis = SourcePayloadPlaneIdentitySequence( - value, - identity_policy, - ).runtime_axis_identities() + image_axis = image_payload_metadata( + broadcast_source + ).source_provenance.image_set_axis(identity_policy) + value_axis = image_payload_metadata(value).source_provenance.image_set_axis( + identity_policy + ) selected_indices = SourcePlaneIdentitySequenceAlignment( image_axis, value_axis, diff --git a/openhcs/interop/cellprofiler/runtime/function_contract_execution.py b/openhcs/interop/cellprofiler/runtime/function_contract_execution.py index c1279ed9cd..199f2dea38 100644 --- a/openhcs/interop/cellprofiler/runtime/function_contract_execution.py +++ b/openhcs/interop/cellprofiler/runtime/function_contract_execution.py @@ -8,11 +8,9 @@ import numpy as np from openhcs.core.aligned_image_payload import ( - AlignedImageSliceContext, AlignedImageStack, ImagePayloadExecutionMode, aligned_image_stack_kwargs, - pack_aligned_image_outputs, ) from openhcs.core.callable_contract import CallableContract from openhcs.core.image_shapes import ArrayShape @@ -20,7 +18,6 @@ from openhcs.core.memory import detect_memory_type, stack_slices from openhcs.core.runtime_batch_contracts import ( Pure2DSliceBatchExecutor, - RuntimeBatchExecutionDomain, RuntimeBatchInvocationRequest, RuntimePure2DSliceBatchRequest, SliceIndexRuntimeParameter, @@ -30,7 +27,7 @@ image_payload_mask, image_payload_metadata, ) -from openhcs.core.runtime_output_matching import split_runtime_output +from openhcs.core.runtime_output_matching import RuntimeReturnedOutputMatcher from openhcs.core.runtime_plane_projection import ( RuntimePlaneAxis, RuntimePlaneAxisValueProjection, @@ -59,10 +56,12 @@ RuntimeCallablePolicy, RuntimeCallableView, RuntimeInvocationKwargPolicy, + contextualize_main_image_output, ) _CELLPROFILER_RUNTIME_CALLABLE_POLICY = RuntimeCallablePolicy( - callable_view=RuntimeCallableView.RAW, + # execute() resolves the compiled raw target before processing dispatch. + callable_view=RuntimeCallableView.DECORATED, kwarg_policy=RuntimeInvocationKwargPolicy.SIGNATURE_FILTERED, ) @@ -112,6 +111,7 @@ def execute( executor = type(self)(plane_projection=plane_projection) function_name = callable_contract.function_name processing_contract = callable_contract.require_processing_contract() + runtime_func = callable_contract.resolve_raw_runtime_callable() mode = execution_mode CellProfilerRuntimeProfileLogger.log_module_profile( "cp_executor_mode_resolution", @@ -131,12 +131,19 @@ def execute( | ProcessingContract.FLEXIBLE | ProcessingContract.VOLUMETRIC_TO_SLICE, ): + runtime_kwargs = dict(kwargs) + runtime_kwargs.update( + processing_contract.declaration.consume_semantic_controls( + runtime_kwargs, + parameters=callable_contract.canonical_signature.parameters, + ) + ) result = processing_contract.execute( executor, - func, + runtime_func, image, callable_contract=callable_contract, - **dict(kwargs), + **runtime_kwargs, ) case ( ImagePayloadExecutionMode.FULL_STACK, @@ -146,7 +153,7 @@ def execute( | ProcessingContract.VOLUMETRIC_TO_SLICE, ): result = executor.execute_pure_3d( - func, + runtime_func, image, callable_contract=callable_contract, **dict(kwargs), @@ -160,7 +167,7 @@ def execute( ): result = executor._execute_aligned_multi_image_stack( callable_contract, - func, + runtime_func, image, **dict(kwargs), ) @@ -176,79 +183,10 @@ def execute( function=function_name, mode=mode.value, ) - return executor._contextualize_multi_canonical_output( + return RuntimeReturnedOutputMatcher( callable_contract, result, - ) - - def _contextualize_multi_canonical_output( - self, - callable_contract: CallableContract, - result: RuntimeCallableArgument, - ) -> RuntimeCallableArgument: - """Attach the compiled canonical ABI to one exact returned image axis.""" - - canonical_specs = callable_contract.canonical_return_output_specs.specs - if len(canonical_specs) <= 1: - return result - canonical_output, trailing_outputs = split_runtime_output(result) - if isinstance(canonical_output, AlignedImageStack): - if canonical_output.slice_contexts: - return result - output_values = canonical_output.slices - else: - projection = self.plane_projection - function_name = callable_contract.function_name - if projection is None: - raise RuntimeSliceProjectionDeclarationError( - f"{function_name} declares {len(canonical_specs)} canonical " - "outputs but returned a non-aligned payload without a " - "compiled plane projection." - ) - if projection.plane_index is not None: - raise RuntimeSliceProjectionDeclarationError( - f"{function_name} declares {len(canonical_specs)} canonical " - "outputs after the compiled plane projection already selected " - f"plane {projection.plane_index}." - ) - if projection.axis_size != len(canonical_specs): - raise ValueError( - f"{function_name} declares {len(canonical_specs)} canonical " - "outputs but its compiled plane projection declares " - f"{projection.axis_size} value(s)." - ) - output_axis = image_payload_metadata(canonical_output).plane_axis - if output_axis is not projection.axis: - raise RuntimeSliceProjectionDeclarationError( - f"{function_name} declares {len(canonical_specs)} canonical " - "outputs but its returned payload does not declare the " - f"compiled {projection.axis.value!r} plane axis; got " - f"{output_axis!r}." - ) - output_values = tuple( - RuntimeSliceProjection.value_for_slice( - canonical_output, - projection.selected_plane(output_index), - ) - for output_index in range(projection.axis_size) - ) - if len(output_values) != len(canonical_specs): - raise ValueError( - f"{callable_contract.function_name} returned {len(output_values)} " - "canonical output value(s) for " - f"{len(canonical_specs)} compiled output spec(s)." - ) - contextualized_output = pack_aligned_image_outputs( - output_values, - slice_contexts=AlignedImageSliceContext.main_flow_for_artifact_specs( - canonical_specs - ), - ) - return ( - (contextualized_output, *trailing_outputs) - if trailing_outputs - else contextualized_output - ) + ).contextualize_canonical_output(plane_projection=executor.plane_projection) def execute_pure_2d_slice_batch( self, @@ -273,18 +211,12 @@ def execute_pure_2d_slice_batch( slices_2d=slices_2d, kwargs=kwargs, execute_slice=execute_slice, + signature=callable_contract.raw_runtime_signature, ) if slice_request.slice_count <= 0: return [], 0.0 - declared_batch_executor = callable_contract.runtime_batch_executor( - RuntimeBatchExecutionDomain.PURE_2D_SLICES - ) - batch_executor = ( - declared_batch_executor - if callable(declared_batch_executor) - else Pure2DSliceBatchExecutor.default_executor() - ) + batch_executor = Pure2DSliceBatchExecutor.from_executors(callable_contract.runtime_batch_executors) slice_started_at = time.perf_counter() if batch_executor is not None and slice_request.slice_count > 1: slice_results = list(batch_executor(slice_request)) @@ -323,9 +255,10 @@ def execute_pure_3d( ), ) call_started_at = time.perf_counter() - result = _CELLPROFILER_RUNTIME_CALLABLE_POLICY.invocation( + result = _CELLPROFILER_RUNTIME_CALLABLE_POLICY.contract_invocation( + callable_contract, func, - (projected_image,), + projected_image, projected_kwargs, ).call() CellProfilerRuntimeProfileLogger.log_module_profile( @@ -401,9 +334,10 @@ def execute_aligned_stack_slice( slice_index: int, slice_count: int, ) -> RuntimeCallableArgument: - return _CELLPROFILER_RUNTIME_CALLABLE_POLICY.invocation( + return _CELLPROFILER_RUNTIME_CALLABLE_POLICY.contract_invocation( + callable_contract, slice_func, - (slice_payload,), + slice_payload, aligned_image_stack_kwargs( slice_kwargs, slice_index, @@ -519,9 +453,10 @@ def execute_pure_2d( ) image_data = image_payload_data(image) if not isinstance(image_data, np.ndarray): - return _CELLPROFILER_RUNTIME_CALLABLE_POLICY.invocation( + return _CELLPROFILER_RUNTIME_CALLABLE_POLICY.contract_invocation( + callable_contract, func, - (image,), + image, kwargs, ).call() @@ -546,9 +481,10 @@ def execute_pure_2d( "declared plane projection. Kwargs cannot create image-axis " "execution semantics." ) - return _CELLPROFILER_RUNTIME_CALLABLE_POLICY.invocation( + return _CELLPROFILER_RUNTIME_CALLABLE_POLICY.contract_invocation( + callable_contract, func, - (image,), + image, kwargs, ).call() declared_plane_axis = image_payload_metadata(image).plane_axis @@ -650,10 +586,10 @@ def execute_volumetric_to_slice( callable_contract: CallableContract, **kwargs: RuntimeCallableArgument, ) -> RuntimeCallableArgument: - del callable_contract - result_2d = _CELLPROFILER_RUNTIME_CALLABLE_POLICY.invocation( + result_2d = _CELLPROFILER_RUNTIME_CALLABLE_POLICY.contract_invocation( + callable_contract, func, - (image,), + image, kwargs, ).call() result_data = image_payload_data(result_2d) @@ -683,11 +619,13 @@ def execute_pure_2d_slice( sliced_kwargs = dict(sliced_kwargs) slice_index_name = SliceIndexRuntimeParameter.require_parameter_name() sliced_kwargs[slice_index_name] = slice_index - return _CELLPROFILER_RUNTIME_CALLABLE_POLICY.invocation( + result = _CELLPROFILER_RUNTIME_CALLABLE_POLICY.contract_invocation( + callable_contract, func, - (slice_2d,), + slice_2d, sliced_kwargs, ).call() + return contextualize_main_image_output(slice_2d, result) def slice_pure_2d_kwargs( self, diff --git a/openhcs/interop/cellprofiler/runtime/invocation.py b/openhcs/interop/cellprofiler/runtime/invocation.py index fff2312c33..31876eec10 100644 --- a/openhcs/interop/cellprofiler/runtime/invocation.py +++ b/openhcs/interop/cellprofiler/runtime/invocation.py @@ -11,12 +11,10 @@ from openhcs.core.alias_property import AliasProperty from openhcs.core.aligned_image_payload import ( AlignedImageStack, - payload_slices_for_alignment, ) from openhcs.core.equivalence.keys import RuntimeMeasurementSourcePair from openhcs.core.measurement_image_alignment import ( MeasurementImageAlignmentSource, - MeasurementImageLabelAlignmentStrategy, MeasurementImageReferenceDomain, PreparedMeasurementObjectLabels, ) @@ -36,8 +34,12 @@ from openhcs.core.runtime_plane_projection import ( RuntimePlaneAxisProjector, ) -from openhcs.core.runtime_slice_alignment import RuntimeSliceAlignedValues +from openhcs.core.runtime_slice_alignment import ( + RuntimeSliceAlignedValues, + RuntimeSliceAlignedValueSet, +) from openhcs.core.runtime_slice_projection import RuntimeSliceProjection +from openhcs.core.source_image_provenance import SourceImageProvenance from openhcs.core.source_spatial_domain import CommonRuntimeValue from openhcs.core.steps.function_runtime import RuntimeCallableArgument @@ -135,35 +137,96 @@ def composed_source_metadata( return None if mode is None: mode = cls.source_metadata_composition_mode(sources) - source_payloads = tuple( - source_payload + scalar_sources = tuple( + provenance for source in sources - for source_payload in payload_slices_for_alignment(source.payload) + for provenance in cls.source_provenances(source.payload) ) - source_metadata = tuple( - ImagePayloadMetadata( - source_provenance=( - ImagePayloadMetadata.compose( - payload_slices_for_alignment(payload), - mode=ImagePayloadMetadataCompositionMode.BUNDLE, - ) - .collapse_leading_plane_axis() - .source_provenance - if isinstance(payload, AlignedImageStack) - else image_payload_metadata(payload).source_provenance - ) + if not scalar_sources: + raise ValueError("Image metadata composition payloads cannot be empty.") + provenances = tuple( + ( + provenance.for_source_plane(0) + if provenance.source_plane_count == 1 + else provenance ) - for payload in source_payloads + for provenance in scalar_sources ) - metadata = ImagePayloadMetadata.compose( - source_payloads, - mode=mode, - source_metadata=source_metadata, + if not any(provenance.has_values for provenance in provenances): + return ImagePayloadMetadata(plane_axis=mode.plane_axis) + provenance = ( + SourceImageProvenance.stack(provenances, scalar_sources=scalar_sources) + if mode is ImagePayloadMetadataCompositionMode.STACK + else SourceImageProvenance.bundle( + provenances, scalar_sources=scalar_sources + ) + ) + metadata = ImagePayloadMetadata( + source_provenance=provenance, + source_plane_intensity_scales=(None,) * len(provenances), + source_plane_dtypes=(None,) * len(provenances), + plane_axis=mode.plane_axis, ) - if not metadata.has_values: - return None return metadata + @classmethod + def source_provenances( + cls, payload: RuntimeCallableArgument + ) -> tuple[SourceImageProvenance, ...]: + """Read the declared runtime source roster without projecting image pixels.""" + if isinstance(payload, AlignedImageStack): + return tuple( + cls.scalar_source_provenance(value) for value in payload.slices + ) + if isinstance(payload, RuntimeSliceAlignedValueSet): + return tuple( + cls.scalar_source_provenance(payload.value_for_slice(index)) + for index in range(payload.slice_count) + ) + count = RuntimeSliceProjection.slice_count_from_values((payload,)) + metadata = image_payload_metadata(payload) + provenance = metadata.source_provenance + if count is None: + return (provenance,) + if metadata.source_channel_axis == 0: + raise ValueError( + "Image metadata cannot declare the same leading axis as both " + "plane and channel." + ) + return tuple(provenance.for_source_plane(index) for index in range(count)) + + @staticmethod + def scalar_source_provenance( + payload: RuntimeCallableArgument, + ) -> SourceImageProvenance: + """Collapse an inner image bundle's source topology at its actual read epoch.""" + if not isinstance(payload, AlignedImageStack): + return image_payload_metadata(payload).source_provenance + metadata = tuple(image_payload_metadata(value) for value in payload.slices) + provenances = tuple( + ( + fields.source_provenance.for_source_plane(0) + if fields.plane_axis is None + and fields.source_provenance.source_plane_count == 1 + else fields.source_provenance + ) + for fields in metadata + ) + preserve_topology = ( + len(metadata) == 1 + and metadata[0].plane_axis + is ImagePayloadMetadataCompositionMode.BUNDLE.plane_axis + ) + scalar_sources = tuple(fields.source_provenance for fields in metadata) + provenance = SourceImageProvenance.bundle( + provenances, + scalar_sources=scalar_sources, + preserve_single_topology=preserve_topology, + ) + return ( + provenance.with_runtime_planes_as_contributors().with_common_scalar_identity_from_planes() + ) + @classmethod def source_metadata_composition_mode( cls, @@ -401,12 +464,14 @@ def align_image_to_labels( plane_projector: RuntimePlaneAxisProjector | None = None, ) -> RuntimeCallableArgument: """Project this measurement image payload into the supplied label domain.""" - return MeasurementImageLabelAlignmentStrategy.align( + return ( self.alignment_request( labels=labels, label_payload=label_payload, plane_projector=plane_projector, ) + .aligned() + .image ) diff --git a/openhcs/interop/cellprofiler/runtime/measurement_execution_support.py b/openhcs/interop/cellprofiler/runtime/measurement_execution_support.py index 92c93a7309..61c4adfc56 100644 --- a/openhcs/interop/cellprofiler/runtime/measurement_execution_support.py +++ b/openhcs/interop/cellprofiler/runtime/measurement_execution_support.py @@ -24,7 +24,10 @@ from openhcs.core.runtime_object_labels import ( ObjectLabelValue, ) -from openhcs.core.runtime_batch_contracts import RuntimeBatchInvocationRequest +from openhcs.core.runtime_batch_contracts import ( + RuntimeBatchExecutionDomain, + RuntimeBatchInvocationRequest, +) from openhcs.interop.cellprofiler.runtime.adapter import CellProfilerRuntimeAdapter from openhcs.interop.cellprofiler.runtime.function_contract_execution import ( _execute_runtime_batch_invocation, @@ -212,111 +215,6 @@ class PreparedObjectMeasurementInvocation(RuntimeBatchInvocationRequest): invocation: "ObjectMeasurementInvocation" completion_label_payload: RuntimeCallableArgument - def record_output( - self, - output_recorder: "ObjectMeasurementOutputRecorder", - raw_output: RuntimeCallableArgument, - ) -> None: - """Record one raw invocation output through the shared recorder.""" - output_recorder.record( - raw_output, - measurement_image=self.measurement_image, - object_spec=self.object_spec, - completion_label_payload=self.completion_label_payload, - invocation=self.invocation, - ) - - -@dataclass(frozen=True, slots=True) -class PreparedObjectMeasurementInvocationBatch: - """Execute prepared object-measurement invocations in declared batch order.""" - - callable_contract: CallableContract - func: Callable[..., RuntimeFunctionOutput] - function_name: str - invocations: tuple[PreparedObjectMeasurementInvocation, ...] - batch_executor: ObjectMeasurementBatchExecutor | None - - def execute( - self, - output_recorder: "ObjectMeasurementOutputRecorder", - ) -> float: - """Execute all invocations, record outputs, and return contract seconds.""" - if self.batch_executor is not None: - return self._execute_batched(output_recorder) - return self._execute_serial(output_recorder) - - def _execute_serial( - self, - output_recorder: "ObjectMeasurementOutputRecorder", - ) -> float: - contract_execute_seconds = 0.0 - for prepared_invocation in self.invocations: - contract_started_at = time.perf_counter() - raw_output = _execute_runtime_batch_invocation( - self.callable_contract, - self.func, - prepared_invocation, - ) - contract_execute_seconds += time.perf_counter() - contract_started_at - prepared_invocation.record_output(output_recorder, raw_output) - return contract_execute_seconds - - def _execute_batched( - self, - output_recorder: "ObjectMeasurementOutputRecorder", - ) -> float: - batch_requests = tuple( - invocation.batch_executor_request() for invocation in self.invocations - ) - if any(request is None for request in batch_requests): - return self._execute_serial(output_recorder) - executable_requests = tuple( - request for request in batch_requests if request is not None - ) - contract_started_at = time.perf_counter() - raw_outputs = tuple( - self.require_batch_executor()( - self.func, - executable_requests, - partial( - _execute_runtime_batch_invocation, - self.callable_contract, - ), - ) - ) - contract_execute_seconds = time.perf_counter() - contract_started_at - if len(raw_outputs) != len(self.invocations): - raise ValueError( - f"{self.function_name} measurement-image batch executor returned " - f"{len(raw_outputs)} outputs for {len(self.invocations)} requests." - ) - - ordered_batch_outputs = { - prepared_invocation.batch_index: ( - raw_output, - prepared_invocation, - ) - for raw_output, prepared_invocation in zip( - raw_outputs, - self.invocations, - strict=True, - ) - } - for order_index in range(len(ordered_batch_outputs)): - raw_output, prepared_invocation = ordered_batch_outputs[order_index] - prepared_invocation.record_output(output_recorder, raw_output) - return contract_execute_seconds - - def require_batch_executor(self) -> ObjectMeasurementBatchExecutor: - """Return the declared batch executor for the batched path.""" - if self.batch_executor is None: - raise RuntimeError( - "PreparedObjectMeasurementInvocationBatch requires a batch executor " - "for batched execution." - ) - return self.batch_executor - def object_label_stage_event( stage: str, @@ -381,45 +279,109 @@ def record_events( @dataclass(slots=True) -class ObjectMeasurementOutputTimings: - """Mutable timings for per-object measurement output handling.""" - - split_seconds: float = 0.0 - complete_rows_seconds: float = 0.0 - annotate_seconds: float = 0.0 - - -@dataclass(frozen=True, slots=True) class ObjectMeasurementOutputRecorder: - """Record one per-object CellProfiler measurement output.""" + """Execute and record an ordered object-measurement roster.""" callable_contract: CallableContract measurement_output_plan: ArtifactOutputPlan row_policy: "CellProfilerObjectMeasurementRowPolicy" module_type: type["CellProfilerModule"] - func: Callable[..., RuntimeFunctionOutput] - adapter: CellProfilerRuntimeAdapter measurement_images: tuple["CellProfilerMeasurementImage", ...] object_inputs: tuple[ArtifactSpec, ...] image_measurement_rows: list[ColumnarRows] columnar_rows: list[ColumnarRows] - timings: ObjectMeasurementOutputTimings + split_seconds: float = 0.0 + complete_rows_seconds: float = 0.0 + annotate_seconds: float = 0.0 + + def execute( + self, + invocations: tuple[PreparedObjectMeasurementInvocation, ...], + ) -> float: + """Execute all invocations, record outputs, and return contract seconds.""" + batch_executor = self.callable_contract.runtime_batch_executor( + RuntimeBatchExecutionDomain.MEASUREMENT_IMAGES + ) + if batch_executor is not None: + return self._execute_batched(invocations, batch_executor) + return self._execute_serial(invocations) + + def _execute_serial( + self, + invocations: tuple[PreparedObjectMeasurementInvocation, ...], + ) -> float: + func = self.callable_contract.resolve_canonical_raw_callable() + contract_execute_seconds = 0.0 + for prepared_invocation in invocations: + contract_started_at = time.perf_counter() + raw_output = _execute_runtime_batch_invocation( + self.callable_contract, + func, + prepared_invocation, + ) + contract_execute_seconds += time.perf_counter() - contract_started_at + self.record(raw_output, prepared_invocation) + return contract_execute_seconds + + def _execute_batched( + self, + invocations: tuple[PreparedObjectMeasurementInvocation, ...], + batch_executor: ObjectMeasurementBatchExecutor, + ) -> float: + func = self.callable_contract.resolve_canonical_raw_callable() + batch_requests = tuple( + invocation.batch_executor_request() for invocation in invocations + ) + if any(request is None for request in batch_requests): + return self._execute_serial(invocations) + executable_requests = tuple( + request for request in batch_requests if request is not None + ) + contract_started_at = time.perf_counter() + raw_outputs = tuple( + batch_executor( + func, + executable_requests, + partial( + _execute_runtime_batch_invocation, + self.callable_contract, + ), + ) + ) + contract_execute_seconds = time.perf_counter() - contract_started_at + if len(raw_outputs) != len(invocations): + raise ValueError( + f"{self.callable_contract.function_name} measurement-image batch executor returned " + f"{len(raw_outputs)} outputs for {len(invocations)} requests." + ) + + ordered_batch_outputs = { + prepared_invocation.batch_index: ( + raw_output, + prepared_invocation, + ) + for raw_output, prepared_invocation in zip( + raw_outputs, + invocations, + strict=True, + ) + } + for order_index in range(len(ordered_batch_outputs)): + raw_output, prepared_invocation = ordered_batch_outputs[order_index] + self.record(raw_output, prepared_invocation) + return contract_execute_seconds def record( self, raw_output: RuntimeCallableArgument, - *, - measurement_image: "CellProfilerMeasurementImage", - object_spec: ArtifactSpec, - completion_label_payload: RuntimeCallableArgument, - invocation: "ObjectMeasurementInvocation", + prepared_invocation: PreparedObjectMeasurementInvocation, ) -> None: split_started_at = time.perf_counter() _returned_values, matched_outputs = RuntimeReturnedOutputMatcher( callable_contract=self.callable_contract, returned_output=raw_output, ).resolve_plan_values((self.measurement_output_plan,)) - self.timings.split_seconds += time.perf_counter() - split_started_at + self.split_seconds += time.perf_counter() - split_started_at _output_plan, _output_spec, output_value = matched_outputs[0] emitted_measurement_rows = measurement_table_rows(output_value) CellProfilerRuntimeProfileLogger.log_module_profile( @@ -431,23 +393,23 @@ def record( ) raw_measurement_rows = self.row_policy.project_rows( emitted_measurement_rows, - invocation, + prepared_invocation.invocation, ) object_measurement_rows, non_object_measurement_rows = ( self.row_policy.split_scoped_rows(raw_measurement_rows) ) measurement_rows = self.completed_measurement_rows( object_measurement_rows, - completion_label_payload, + prepared_invocation.completion_label_payload, ) self.record_non_object_rows( non_object_measurement_rows, - measurement_image, + prepared_invocation.measurement_image, ) self.record_object_rows( measurement_rows, - object_spec, - measurement_image, + prepared_invocation.object_spec, + prepared_invocation.measurement_image, ) def completed_measurement_rows( @@ -460,9 +422,7 @@ def completed_measurement_rows( object_measurement_rows, label_payload=completion_label_payload, ) - self.timings.complete_rows_seconds += ( - time.perf_counter() - complete_rows_started_at - ) + self.complete_rows_seconds += time.perf_counter() - complete_rows_started_at return measurement_rows def project_owned_rows( @@ -500,7 +460,7 @@ def record_non_object_rows( row_object_name=None, ) self.image_measurement_rows.append(projected_rows) - self.timings.annotate_seconds += time.perf_counter() - annotate_started_at + self.annotate_seconds += time.perf_counter() - annotate_started_at def record_object_rows( self, @@ -515,4 +475,4 @@ def record_object_rows( row_object_name=object_spec.name, ) self.columnar_rows.append(projected_rows) - self.timings.annotate_seconds += time.perf_counter() - annotate_started_at + self.annotate_seconds += time.perf_counter() - annotate_started_at diff --git a/openhcs/interop/cellprofiler/runtime/measurement_recording.py b/openhcs/interop/cellprofiler/runtime/measurement_recording.py index 63cacedd72..047158341e 100644 --- a/openhcs/interop/cellprofiler/runtime/measurement_recording.py +++ b/openhcs/interop/cellprofiler/runtime/measurement_recording.py @@ -247,7 +247,7 @@ def measurement_record_source_image_name( request.callable_contract ) primary_image_inputs = module_type.primary_image_inputs( - request.callable_contract.resolve_canonical_raw_callable(), + request.callable_contract, request.callable_contract.artifact_inputs.specs, ) current_source_name = request.source.source_image_name @@ -742,7 +742,6 @@ def measurement_record_source_metadata( ) from openhcs.core.source_matching import SourceImageSetIdentityPolicy from openhcs.core.source_plane_alignment import ( - SourcePayloadPlaneIdentitySequence, SourcePlaneIdentitySequenceAlignment, ) @@ -765,10 +764,9 @@ def measurement_record_source_metadata( request.adapter.request.source_binding_plan ) identity_axes = tuple( - SourcePayloadPlaneIdentitySequence( - payload, - identity_policy, - ).runtime_axis_identities() + image_payload_metadata(payload).source_provenance.image_set_axis( + identity_policy + ) for payload in source_payloads ) missing_identity_specs = tuple( diff --git a/openhcs/interop/cellprofiler/runtime/module_execution.py b/openhcs/interop/cellprofiler/runtime/module_execution.py index e21d58258b..e3ea0f9637 100644 --- a/openhcs/interop/cellprofiler/runtime/module_execution.py +++ b/openhcs/interop/cellprofiler/runtime/module_execution.py @@ -41,9 +41,8 @@ from openhcs.core.runtime_adapters import ( RuntimeAdapterRequest, ) -from openhcs.core.runtime_artifact_queries import MeasurementTableUnion -from openhcs.core.runtime_batch_contracts import RuntimeBatchExecutionDomain from openhcs.core.runtime_image_values import ( + ImagePayloadMetadata, image_payload_metadata, preserved_image_plane_projection, ) @@ -74,7 +73,6 @@ from openhcs.interop.cellprofiler.runtime.adapter import CellProfilerRuntimeAdapter from openhcs.interop.cellprofiler.runtime.artifact_binding import ( RuntimeInputBindingRequest, - RuntimeArtifactTypeStrategy, ) from openhcs.interop.cellprofiler.runtime.function_contract_execution import ( _CELLPROFILER_FUNCTION_CONTRACT_EXECUTOR, @@ -87,9 +85,7 @@ from openhcs.interop.cellprofiler.runtime.measurement_execution_support import ( CellProfilerRuntimeProfiler, ObjectMeasurementOutputRecorder, - ObjectMeasurementOutputTimings, PreparedObjectMeasurementInvocation, - PreparedObjectMeasurementInvocationBatch, object_measurement_batch_group_key, object_measurement_runtime_inputs, ) @@ -180,15 +176,7 @@ def __post_init__(self) -> None: f"{self.callable_contract.function_name!r} does not match resolved " f"raw callable {self.raw_func.__name__!r}." ) - module_type = self.module_type() - if self.raw_func is not module_type.require_callable( - self.callable_contract.function_name - ): - raise ValueError( - f"CellProfiler callable {self.callable_contract.function_name!r} " - f"is not the declaration-owned callable for module " - f"{module_type.require_module_name()!r}." - ) + self.module_type() def module_type(self) -> type[CellProfilerModule]: """Return the nominal module declaration that owns this callable.""" @@ -240,12 +228,8 @@ def measurement_output_plan( def prepare(self) -> None: """Resolve nominal policies used by this executor before timed execution.""" - for strategy_type in RuntimeArtifactTypeStrategy.registered_strategy_types(): - RuntimeArtifactTypeStrategy.for_artifact_type(strategy_type.artifact_type) - for artifact_type in frozenset( - output.artifact_type for output in self.callable_contract.artifact_outputs - ): - CellProfilerOutputRecorder.for_artifact_type(artifact_type) + for strategy_type in CellProfilerOutputRecorder.registered_strategy_types(): + CellProfilerOutputRecorder.for_artifact_type(strategy_type.artifact_type) def __call__( self, @@ -295,7 +279,11 @@ def __call__( module_type=module_type, ) image_request = None - if primary_image_inputs: + if ( + primary_image_inputs + and self.callable_contract.image_payload_consumption + is ImagePayloadConsumption.COMPOSED + ): image_request = self._image_request( image, cellprofiler_runtime, @@ -321,6 +309,7 @@ def __call__( adapter=cellprofiler_runtime, kwargs=kwargs, image_request=image_request, + image_inputs=primary_image_inputs, module_type=module_type, active_input_specs=active_inputs.specs, active_output_plans=active_outputs, @@ -528,7 +517,7 @@ def _replacement_main_flow_output( ) for output_plan, spec in outputs ) - replacement = RuntimeArtifactTypeStrategy.for_main_flow_outputs( + replacement = CellProfilerOutputRecorder.for_main_flow_outputs( output_values ).published_main_flow_output( invocation_image, @@ -606,7 +595,7 @@ def _primary_image_inputs( current_image=current_image, ) return module_type.primary_image_inputs( - self.raw_func, + self.callable_contract, request.primary_image_inputs, ) @@ -616,13 +605,9 @@ def _measurement_image_inputs( current_image: RuntimeCallableArgument, image_request: CellProfilerImageRequest | None, *, + image_inputs: tuple[ArtifactSpec, ...], module_type: type[CellProfilerModule], ) -> tuple[CellProfilerMeasurementImage, ...]: - image_inputs = self._primary_image_inputs( - current_image, - adapter, - module_type=module_type, - ) if not image_inputs: return () if ( @@ -716,26 +701,25 @@ def _resolved_measurement_image( current_image=current_image, ).artifact_value_for_spec(spec) payload = normalize_cellprofiler_image_payload( - RuntimeArtifactTypeStrategy.for_artifact_type( + CellProfilerOutputRecorder.for_artifact_type( ImageArtifactType, ).raw_runtime_input_value(spec, value) ) - metadata = image_payload_metadata(payload) - plane_axis = metadata.plane_axis + plane_projection = ( + preserved_image_plane_projection(payload, adapter, source_aliases) + if image_payload_metadata(payload).plane_axis is not None + else None + ) return CellProfilerMeasurementImage( source_image_name=spec.name, source_aliases=source_aliases, payload=payload, plane_projection=( replace( - preserved_image_plane_projection( - payload, - adapter, - source_aliases, - ), + plane_projection, source_aliases=source_aliases, ) - if plane_axis is not None + if plane_projection is not None else None ), reference_domain=reference_domain, @@ -776,6 +760,7 @@ def _run_per_object_measurement( adapter: CellProfilerRuntimeAdapter, kwargs: RuntimeCallableKwargs, image_request: "CellProfilerImageRequest | None", + image_inputs: tuple[ArtifactSpec, ...], module_type: type[CellProfilerModule], active_input_specs: tuple[ArtifactSpec, ...], active_output_plans: tuple[ArtifactOutputPlan, ...], @@ -784,9 +769,6 @@ def _run_per_object_measurement( current_image = image input_image = image cellprofiler_runtime = adapter - source_image_name = ( - None if image_request is None else image_request.source_image_name - ) kwargs = dict(kwargs) function_name = self.callable_contract.function_name profiler = CellProfilerRuntimeProfiler( @@ -805,8 +787,61 @@ def _run_per_object_measurement( cellprofiler_runtime, current_image, image_request, + image_inputs=image_inputs, module_type=module_type, ) + if image_request is not None: + source_image_name = image_request.source_image_name + elif not image_inputs: + source_image_name = None + else: + image_strategy = CellProfilerOutputRecorder.for_artifact_type( + ImageArtifactType + ) + runtime_projection = RuntimePlaneAxisValueProjection.from_projector( + adapter, + RuntimePlaneAxis.RUNTIME_SLICE, + (), + ) + projected_binding = ( + RuntimeInputBindingRequest( + adapter=adapter, + kwargs={}, + current_image=RuntimeSliceProjection.value_for_slice( + current_image, + runtime_projection, + ), + ) + if runtime_projection is not None + and runtime_projection.plane_index is not None + else None + ) + source_names = [] + for spec, measurement_image in zip( + image_inputs, measurement_images, strict=True + ): + edge = ( + adapter.request.require_artifact_input_edge(spec.ref()) + if projected_binding is not None + else None + ) + if edge is not None and edge.main_flow_projection is not None: + source_name = image_strategy.source_image_name( + spec, + projected_binding.main_flow_value( + spec, + projection=edge.main_flow_projection, + ), + ) + else: + source_name = image_strategy.source_image_name_from_value( + measurement_image.payload + ) + source_names.append(source_name) + source_image_name = self._primary_image_source_name_from_sources( + image_inputs, + tuple(source_names), + ) if not measurement_images: measurement_images = tuple( self._object_label_measurement_image( @@ -816,28 +851,6 @@ def _run_per_object_measurement( ) for object_spec in object_inputs ) - measurement_object_pairs = tuple( - ( - measurement_image, - object_spec, - True, - ) - for measurement_image, object_spec in zip( - measurement_images, - object_inputs, - strict=True, - ) - ) - else: - measurement_object_pairs = tuple( - ( - measurement_image, - object_spec, - object_index == 0, - ) - for measurement_image in measurement_images - for object_index, object_spec in enumerate(object_inputs) - ) profile_events: list[CellProfilerRuntimeProfileEvent] = [] if profile_enabled: profile_events.append( @@ -857,108 +870,98 @@ def _run_per_object_measurement( label_payload_seconds = 0.0 label_align_seconds = 0.0 contract_execute_seconds = 0.0 - output_timings = ObjectMeasurementOutputTimings() columnar_rows: list[ColumnarRows] = [] - batch_executor = self.callable_contract.runtime_batch_executor( - RuntimeBatchExecutionDomain.MEASUREMENT_IMAGES - ) processing_contract = self.callable_contract.require_processing_contract() output_recorder = ObjectMeasurementOutputRecorder( callable_contract=self.callable_contract, measurement_output_plan=measurement_output_plan, row_policy=measurement_row_policy, module_type=module_type, - func=func, - adapter=cellprofiler_runtime, measurement_images=measurement_images, object_inputs=object_inputs, image_measurement_rows=image_measurement_rows, columnar_rows=columnar_rows, - timings=output_timings, ) measurement_invocations = tuple( measurement_row_policy.invocations(measurement_image, kwargs) - for ( - measurement_image, - _object_spec, - _include_image_measurements, - ) in measurement_object_pairs + for measurement_image in measurement_images ) total_measurement_batch_count = sum( - (len(invocations) for invocations in measurement_invocations) - ) + len(invocations) for invocations in measurement_invocations + ) * (len(object_inputs) if image_inputs else 1) prepared_invocations: list[PreparedObjectMeasurementInvocation] = [] - for ( - measurement_image, - object_spec, - include_image_measurements, - ), invocations in zip( - measurement_object_pairs, measurement_invocations, strict=True + for image_index, (measurement_image, invocations) in enumerate( + zip( + measurement_images, + measurement_invocations, + strict=True, + ) ): - label_payload = RuntimeInputBindingRequest( - adapter=cellprofiler_runtime, - kwargs=kwargs, - current_image=measurement_image.payload, - ).label_payload_for(object_spec) - ( - aligned_measurement_image, - executable_labels, - completion_label_payload, - execution_mode, - preparation_profile_events, - label_payload_elapsed, - label_align_elapsed, - ) = object_measurement_runtime_inputs( - object_label_execution=object_label_input_execution_mode_from_callable( - self.raw_func - ), - measurement_image=measurement_image, - object_spec=object_spec, - label_payload=label_payload, - adapter=cellprofiler_runtime, + measured_objects = ( + object_inputs if image_inputs else (object_inputs[image_index],) ) - profile_events.extend(preparation_profile_events) - label_payload_seconds += label_payload_elapsed - label_align_seconds += label_align_elapsed - for invocation in invocations: - invocation_kwargs = module_type.object_measurement_invocation_kwargs( - invocation.lowered_kwargs(), - include_image_measurements=include_image_measurements, + for object_index, object_spec in enumerate(measured_objects): + include_image_measurements = object_index == 0 + label_payload = RuntimeInputBindingRequest( + adapter=cellprofiler_runtime, + kwargs=kwargs, + current_image=measurement_image.payload, + ).label_payload_for(object_spec) + ( + aligned_measurement_image, + executable_labels, + completion_label_payload, + execution_mode, + preparation_profile_events, + label_payload_elapsed, + label_align_elapsed, + ) = object_measurement_runtime_inputs( + object_label_execution=object_label_input_execution_mode_from_callable( + self.raw_func + ), + measurement_image=measurement_image, + object_spec=object_spec, + label_payload=label_payload, + adapter=cellprofiler_runtime, ) - prepared_invocations.append( - PreparedObjectMeasurementInvocation( - source_image_name=aligned_measurement_image.source_image_name, - execution_mode=execution_mode, - plane_projection=aligned_measurement_image.plane_projection, - func=func, - image=aligned_measurement_image.payload, - kwargs={ - **invocation_kwargs, - **shared_runtime_kwargs, - **_execution_mode_semantic_control_kwargs( - processing_contract, - execution_mode, + profile_events.extend(preparation_profile_events) + label_payload_seconds += label_payload_elapsed + label_align_seconds += label_align_elapsed + for invocation in invocations: + invocation_kwargs = ( + module_type.object_measurement_invocation_kwargs( + invocation.lowered_kwargs(), + include_image_measurements=include_image_measurements, + ) + ) + prepared_invocations.append( + PreparedObjectMeasurementInvocation( + source_image_name=aligned_measurement_image.source_image_name, + execution_mode=execution_mode, + plane_projection=aligned_measurement_image.plane_projection, + func=func, + image=aligned_measurement_image.payload, + kwargs={ + **invocation_kwargs, + **shared_runtime_kwargs, + **_execution_mode_semantic_control_kwargs( + processing_contract, + execution_mode, + ), + "labels": executable_labels, + }, + batch_index=len(prepared_invocations), + batch_count=total_measurement_batch_count, + semantic_group_key=object_measurement_batch_group_key( + object_spec=object_spec, labels=completion_label_payload ), - "labels": executable_labels, - }, - batch_index=len(prepared_invocations), - batch_count=total_measurement_batch_count, - semantic_group_key=object_measurement_batch_group_key( - object_spec=object_spec, labels=completion_label_payload - ), - measurement_image=aligned_measurement_image, - object_spec=object_spec, - invocation=invocation, - completion_label_payload=completion_label_payload, + measurement_image=aligned_measurement_image, + object_spec=object_spec, + invocation=invocation, + completion_label_payload=completion_label_payload, + ) ) - ) - contract_execute_seconds = PreparedObjectMeasurementInvocationBatch( - callable_contract=self.callable_contract, - func=func, - function_name=function_name, - invocations=tuple(prepared_invocations), - batch_executor=batch_executor, - ).execute(output_recorder) + contract_execute_seconds = output_recorder.execute(tuple(prepared_invocations)) if profile_enabled: profile_events.extend( ( @@ -972,15 +975,15 @@ def _run_per_object_measurement( "cp_per_object_contract_execute", contract_execute_seconds ), CellProfilerRuntimeProfileEvent( - "cp_per_object_split_output", output_timings.split_seconds + "cp_per_object_split_output", output_recorder.split_seconds ), CellProfilerRuntimeProfileEvent( "cp_per_object_complete_rows", - output_timings.complete_rows_seconds, + output_recorder.complete_rows_seconds, ), CellProfilerRuntimeProfileEvent( "cp_per_object_annotate_rows", - output_timings.annotate_seconds, + output_recorder.annotate_seconds, ( ( "rows", @@ -1208,10 +1211,11 @@ def _run_per_image_measurement( ) if rows_only_declare_object_name: image_measurement_source_name = None - source_metadata = MeasurementTableUnion( - measurement_output_plan.name, - tuple(combined_tables), - ).source_metadata() + source_metadata = ImagePayloadMetadata( + source_provenance=MeasurementTable.joined_source_provenance( + measurement_output_plan.name, tuple(combined_tables) + ) + ) record_started_at = time.perf_counter() cellprofiler_runtime.add_measurements( module_type.build_measurement_table( @@ -1268,7 +1272,7 @@ def _image_request( current_image=current_image, ) image_inputs = module_type.primary_image_inputs( - self.raw_func, + self.callable_contract, input_binding.primary_image_inputs, ) runtime_projection = RuntimePlaneAxisValueProjection.from_projector( @@ -1321,16 +1325,20 @@ def _image_request( adapter, ), ) + image_input_specs = ArtifactSpecCollection(image_inputs) payloads = [] source_names: list[str | None] = [] - image_strategy = RuntimeArtifactTypeStrategy.for_artifact_type( + image_strategy = CellProfilerOutputRecorder.for_artifact_type( ImageArtifactType ) input_binding = replace(input_binding, current_image=current_runtime_payload) for spec in image_inputs: value = input_binding.artifact_value_for_spec(spec) - payloads.append(image_strategy.runtime_input_value(spec, value)) - source_names.append(image_strategy.source_image_name(spec, value)) + payload = image_strategy.runtime_input_value(spec, value) + payloads.append(payload) + source_names.append( + image_strategy.source_image_name_from_value(payload) + ) parameter_image_inputs = input_binding.image_inputs broadcast_sources = tuple( sources[0] @@ -1356,8 +1364,8 @@ def _image_request( if align_primary_images else () ), - stack_broadcast_source_indices=self._stack_broadcast_source_indices( - image_inputs + stack_broadcast_source_indices=( + image_input_specs.stack_broadcast_source_indices() ), ) return CellProfilerImageRequest( @@ -1365,12 +1373,12 @@ def _image_request( source_image_name=self._primary_image_source_name_from_sources( image_inputs, tuple(source_names) ), - source_aliases=ArtifactSpecCollection(image_inputs).names(), + source_aliases=image_input_specs.names(), image_count=len(payloads), execution_mode=composition.execution_mode, plane_projection=composition.preserved_plane_projection( adapter, - source_aliases=ArtifactSpecCollection(image_inputs).names(), + source_aliases=image_input_specs.names(), ), ) @@ -1390,7 +1398,7 @@ def _input_source_image_name( for spec in active_input_specs: if not spec.artifact_type.carries_source_image_context: continue - source_name = RuntimeArtifactTypeStrategy.for_artifact_type( + source_name = CellProfilerOutputRecorder.for_artifact_type( spec.artifact_type ).source_image_name(spec, input_binding.artifact_value_for_spec(spec)) if source_name is not None: @@ -1407,40 +1415,6 @@ def _primary_image_source_name_from_sources( return None return source_names[0] - @staticmethod - def _stack_broadcast_source_indices( - input_specs: tuple[ArtifactSpec, ...], - ) -> tuple[int | None, ...]: - """Resolve exact stack-broadcast owners from declared input relations.""" - - indices_by_ref: dict[ArtifactSpecRef, list[int]] = {} - for input_index, spec in enumerate(input_specs): - indices_by_ref.setdefault(spec.ref(), []).append(input_index) - - result: list[int | None] = [] - for input_index, spec in enumerate(input_specs): - sources = spec.stack_broadcast_sources() - if len(sources) > 1: - raise ValueError( - f"Input {spec.ref()!r} declares multiple stack-broadcast " - f"owners: {sources!r}." - ) - if not sources: - result.append(None) - continue - source_indices = tuple(indices_by_ref.get(sources[0], ())) - if len(source_indices) != 1: - raise ValueError( - f"Input {spec.ref()!r} requires exactly one active occurrence " - f"of stack-broadcast owner {sources[0]!r}, got " - f"{source_indices!r}." - ) - source_index = source_indices[0] - if source_index == input_index: - raise ValueError(f"Input {spec.ref()!r} cannot broadcast from itself.") - result.append(source_index) - return tuple(result) - def _invocation_request( self, *, diff --git a/openhcs/interop/cellprofiler/runtime/object_label_measurements.py b/openhcs/interop/cellprofiler/runtime/object_label_measurements.py index 19c2890811..b2e04553a2 100644 --- a/openhcs/interop/cellprofiler/runtime/object_label_measurements.py +++ b/openhcs/interop/cellprofiler/runtime/object_label_measurements.py @@ -40,13 +40,14 @@ from openhcs.interop.cellprofiler.measurement_lookup import ( child_count_feature_child_name, ) -from openhcs.interop.cellprofiler.runtime.object_measurement_tables import ( - ObjectMeasurementTableIndex, +from openhcs.core.measurement_feature_queries import ( + ColumnarMeasurementTableSchema, ) if TYPE_CHECKING: from openhcs.interop.cellprofiler.runtime.adapter import CellProfilerRuntimeAdapter + @dataclass(frozen=True, slots=True, kw_only=True) class ObjectFeatureMeasurementContext(RuntimeObjectSliceMeasurementQuery): """Nominal context for one object-feature measurement lookup.""" @@ -80,14 +81,13 @@ def measurement_tables( ) if not records: return () - object_table_index = ObjectMeasurementTableIndex.from_tables( - tuple(cast(MeasurementTable, record.value.data) for record in records) - ) - tables = object_table_index.for_object_feature( + tables = ColumnarMeasurementTableSchema.tables_for_object_feature( + tuple(cast(MeasurementTable, record.data) for record in records), self.object_name, self.feature_name, + dialect=CELLPROFILER_MEASUREMENT_LOOKUP_DIALECT, ) - return () if tables is None else tables + return tables @dataclass(frozen=True, slots=True) diff --git a/openhcs/interop/cellprofiler/runtime/object_measurement_tables.py b/openhcs/interop/cellprofiler/runtime/object_measurement_tables.py deleted file mode 100644 index 2fd94cf9d8..0000000000 --- a/openhcs/interop/cellprofiler/runtime/object_measurement_tables.py +++ /dev/null @@ -1,130 +0,0 @@ -"""Object-measurement table indexes.""" - -from __future__ import annotations - -from collections.abc import Mapping -from dataclasses import dataclass -from types import MappingProxyType - -from openhcs.core.measurement_feature_queries import ( - MeasurementFeatureQuery, - MeasurementTableObjectFeatureSemantics, -) -from openhcs.core.measurement_lookup_dialect import ( - RuntimeMeasurementLookupDialectLike, - resolve_runtime_measurement_lookup_dialect, -) -from openhcs.core.runtime_measurements import ( - MeasurementTable, -) -from openhcs.interop.cellprofiler.measurement_dialect import ( - CELLPROFILER_MEASUREMENT_LOOKUP_DIALECT, -) - -MeasurementTableSelection = tuple[MeasurementTable, ...] | None -MeasurementTablesByObject = Mapping[str, tuple[MeasurementTable, ...]] -MutableMeasurementTablesByObject = dict[str, tuple[MeasurementTable, ...]] - - -@dataclass(frozen=True, slots=True) -class ObjectMeasurementTableIndex: - """Nominal object-subject measurement table index.""" - - tables: tuple[MeasurementTable, ...] - tables_by_object: MeasurementTablesByObject - feature_names_by_table: Mapping[int, frozenset[str]] - complete: bool = False - - @classmethod - def from_tables( - cls, - tables: tuple[MeasurementTable, ...], - ) -> "ObjectMeasurementTableIndex": - """Return a complete index over the provided measurement tables.""" - table_lists: dict[str, list[MeasurementTable]] = {} - feature_names_by_table: dict[int, frozenset[str]] = {} - for table in tables: - table_semantics = MeasurementTableObjectFeatureSemantics.from_table(table) - feature_names_by_table[id(table)] = table_semantics.feature_names - for table_object_name in table_semantics.object_names: - table_lists.setdefault(table_object_name, []).append(table) - indexed_tables: MutableMeasurementTablesByObject = { - object_name: tuple(object_tables) - for object_name, object_tables in table_lists.items() - } - return cls( - tables=tables, - tables_by_object=MappingProxyType(indexed_tables), - feature_names_by_table=MappingProxyType(feature_names_by_table), - complete=True, - ) - - @staticmethod - def table_object_names(table: MeasurementTable) -> tuple[str, ...]: - """Return all object subjects declared by a measurement table.""" - return MeasurementTableObjectFeatureSemantics.from_table(table).object_names - - def for_object(self, object_name: str) -> MeasurementTableSelection: - """Return indexed tables for one object, or ``None`` when unknown.""" - if not self.complete: - return None - if object_name not in self.tables_by_object: - return () - return self.tables_by_object[object_name] - - def for_object_feature( - self, - object_name: str, - feature_name: str, - *, - dialect: RuntimeMeasurementLookupDialectLike = ( - CELLPROFILER_MEASUREMENT_LOOKUP_DIALECT - ), - ) -> MeasurementTableSelection: - """Return indexed object tables that may carry one feature.""" - query_object_name = ( - resolve_runtime_measurement_lookup_dialect(dialect) - .feature_lookup(feature_name) - .query_object_name(object_name) - ) - if query_object_name is None: - tables = self.tables - elif not self.complete: - tables = None - elif query_object_name in self.tables_by_object: - tables = self.tables_by_object[query_object_name] - else: - tables = () - if tables is None: - return None - if not tables and query_object_name is not None: - tables = self.unnamed_object_feature_tables() - query = MeasurementFeatureQuery(feature_name, dialect=dialect) - return tuple( - table for table in tables if self._table_may_carry_feature(table, query) - ) - - def unnamed_object_feature_tables(self) -> tuple[MeasurementTable, ...]: - """Return object-id tables that do not declare a specific object name.""" - return tuple( - table - for table in self.tables - if table.subject.object_id_field is not None - and not MeasurementTableObjectFeatureSemantics.from_table( - table - ).object_names - ) - - def _table_may_carry_feature( - self, - table: MeasurementTable, - query: MeasurementFeatureQuery, - ) -> bool: - feature_names = self.feature_names_by_table.get(id(table)) - semantics = None - if feature_names is not None: - semantics = MeasurementTableObjectFeatureSemantics( - object_names=(), - feature_names=feature_names, - ) - return query.table_may_carry_feature(table, semantics) diff --git a/openhcs/interop/cellprofiler/runtime/object_measurement_vectors.py b/openhcs/interop/cellprofiler/runtime/object_measurement_vectors.py index 858e1e7ce8..7c9e2b0873 100644 --- a/openhcs/interop/cellprofiler/runtime/object_measurement_vectors.py +++ b/openhcs/interop/cellprofiler/runtime/object_measurement_vectors.py @@ -53,8 +53,8 @@ from openhcs.interop.cellprofiler.runtime.object_label_measurements import ( ObjectLabelMeasurementSliceRequest, ) -from openhcs.interop.cellprofiler.runtime.object_measurement_tables import ( - ObjectMeasurementTableIndex, +from openhcs.core.measurement_feature_queries import ( + ColumnarMeasurementTableSchema, ) from openhcs.interop.cellprofiler.runtime.runtime_profile import ( CellProfilerRuntimeProfileLogger, @@ -252,7 +252,7 @@ def runtime_feature_tables( ) table_records = [] for record in source_records: - table = cast(MeasurementTable, record.value.data) + table = cast(MeasurementTable, record.data) if ( query.table_may_carry_feature(table) or query.optional_value_index((table,)) is not None @@ -432,9 +432,11 @@ def measurement_tables( f"{self.request.adapter.request.require_callable_contract().module_name} feature {self.feature_name!r} " "requires a declared MeasurementsArtifactType runtime input." ) - matches = ObjectMeasurementTableIndex.from_tables(declared).for_object_feature( + matches = ColumnarMeasurementTableSchema.tables_for_object_feature( + declared, self.object_name, self.feature_name, + dialect=CELLPROFILER_MEASUREMENT_LOOKUP_DIALECT, ) if not matches: raise ValueError( diff --git a/openhcs/interop/cellprofiler/runtime/output_record_request.py b/openhcs/interop/cellprofiler/runtime/output_record_request.py index 2f20f721fb..dd429f7613 100644 --- a/openhcs/interop/cellprofiler/runtime/output_record_request.py +++ b/openhcs/interop/cellprofiler/runtime/output_record_request.py @@ -16,7 +16,6 @@ from openhcs.core.runtime_object_label_domains import ObjectLabelDomainScope from openhcs.core.source_matching import SourceImageSetIdentityPolicy from openhcs.core.source_plane_alignment import ( - SourcePayloadPlaneIdentitySequence, SourcePlaneIdentitySequenceAlignment, ) from openhcs.core.runtime_image_values import ( @@ -30,7 +29,6 @@ CellProfilerMeasurementImage, ) from openhcs.interop.cellprofiler.runtime.artifact_binding import ( - RuntimeArtifactTypeStrategy, RuntimeInputBindingRequest, ) from openhcs.core.steps.function_runtime import ( @@ -194,10 +192,9 @@ def measurement_source_metadata( ) ) image_set_axes = tuple( - SourcePayloadPlaneIdentitySequence( - value, - identity_policy, - ).runtime_axis_identities() + image_payload_metadata(value).source_provenance.image_set_axis( + identity_policy + ) for value in artifact_values ) unaligned_indexes = SourcePlaneIdentitySequenceAlignment.unaligned_axis_indexes( @@ -221,10 +218,7 @@ def artifact_source_payload( spec = edge.spec RuntimeInputBindingRequest.__post_init__(self) - payload = RuntimeArtifactTypeStrategy.for_artifact_type( - spec.artifact_type - ).source_image_payload( - spec, + payload = spec.artifact_type.source_image_payload_from_runtime_value( self.runtime_value( edge, parameter_name=spec.parameter_name, diff --git a/openhcs/interop/cellprofiler/runtime/output_recording.py b/openhcs/interop/cellprofiler/runtime/output_recording.py index 66cdd0e0bf..ee1f5f89a6 100644 --- a/openhcs/interop/cellprofiler/runtime/output_recording.py +++ b/openhcs/interop/cellprofiler/runtime/output_recording.py @@ -8,10 +8,11 @@ from functools import lru_cache from graphlib import TopologicalSorter from types import MappingProxyType -from typing import ClassVar +from typing import TYPE_CHECKING, ClassVar, cast from openhcs.core.artifacts import ( ArtifactOutputPlan, + ArtifactSpec, ArtifactSpecCollection, ArtifactSpecRef, ArtifactType, @@ -26,8 +27,27 @@ from openhcs.core.callable_contract import CallableContract from openhcs.core.function_patterns import InvocationArtifactInputEdgePlan from openhcs.core.registry_strategies import MostDerivedContextStrategyMixin -from openhcs.core.runtime_image_values import image_payload_metadata +from openhcs.core.aligned_image_payload import ( + AlignedImageSliceContext, + ImageOutputBundle, +) +from openhcs.core.runtime_image_values import ( + image_payload_data, + image_payload_mask, + image_payload_metadata, +) +from openhcs.core.runtime_measurements import MeasurementTable +from openhcs.core.runtime_object_label_building import SourceImageObjectLabelBuildRequest +from openhcs.core.runtime_plane_projection import RuntimePlaneAxisValueProjection +from openhcs.interop.cellprofiler.image_normalization import ( + normalize_cellprofiler_image_payload, +) +from openhcs.interop.cellprofiler.runtime.main_flow import cellprofiler_main_flow_output +from openhcs.interop.cellprofiler.runtime.measurement_source_names import ( + single_source_name, +) from openhcs.core.runtime_object_labels import ( + ObjectLabelSet, ObjectLabelValue, ) from openhcs.core.runtime_output_matching import RuntimeMatchedOutput @@ -36,7 +56,6 @@ ObjectRelationship, ObjectRelationshipDeclaration, ) -from openhcs.core.steps.function_runtime import FunctionOutputContextStrategy from openhcs.interop.cellprofiler.module_declarations import CellProfilerModule from openhcs.interop.cellprofiler.runtime.adapter import CellProfilerRuntimeAdapter from openhcs.interop.cellprofiler.runtime.invocation import ( @@ -45,9 +64,6 @@ from openhcs.interop.cellprofiler.runtime.measurement_recording import ( measurement_table_for_module, ) -from openhcs.interop.cellprofiler.runtime.output_record_request import ( - CellProfilerOutputRecordRequest, -) from openhcs.core.steps.function_runtime import RuntimeCallableArgument from openhcs.interop.cellprofiler.runtime.profile_fields import ( cellprofiler_profile_payload_fields, @@ -57,12 +73,18 @@ ) +if TYPE_CHECKING: + from openhcs.interop.cellprofiler.runtime.output_record_request import ( + CellProfilerOutputRecordRequest, + ) + + class CellProfilerOutputRecorder( ArtifactTypeStrategyMatchMixin, MostDerivedContextStrategyMixin[type[ArtifactType]], ABC, ): - """Nominal output writer selected by artifact type.""" + """Own CellProfiler input binding, output recording and publication by artifact kind.""" artifact_type: ClassVar[type[ArtifactType] | None] = None @@ -77,6 +99,90 @@ def for_artifact_type( error_subject="CellProfiler output recorder", ) + @classmethod + def for_main_flow_outputs( + cls, + outputs: tuple[RuntimeMatchedOutput, ...], + ) -> "CellProfilerOutputRecorder": + """Select one nominal strategy from the complete exact output set.""" + + artifact_types = frozenset( + spec.artifact_type for _plan, spec, _value in outputs + ) + if not artifact_types: + raise ValueError("CellProfiler main-flow publication requires an output.") + if len(artifact_types) != 1: + raise TypeError( + "CellProfiler main-flow outputs require one exact artifact type; " + f"got {tuple(sorted(kind.require_value() for kind in artifact_types))!r}." + ) + (artifact_type,) = artifact_types + return cls.for_artifact_type(artifact_type) + + def runtime_input_value( + self, spec: ArtifactSpec, value: RuntimeCallableArgument + ) -> RuntimeCallableArgument: + """Return the runtime payload bound into absorbed function kwargs.""" + + return value + + def raw_runtime_input_value( + self, spec: ArtifactSpec, value: RuntimeCallableArgument + ) -> RuntimeCallableArgument: + """Return the runtime payload before CellProfiler intensity coercion.""" + return self.runtime_input_value(spec, value) + + def source_image_name( + self, + spec: ArtifactSpec, + value: RuntimeCallableArgument, + ) -> str | None: + """Return the transitive source image name for one artifact input.""" + del spec, value + return None + + def source_image_name_from_value( + self, + value: RuntimeCallableArgument, + ) -> str | None: + """Project a source name from an already resolved artifact value.""" + del value + return None + + def published_main_flow_output( + self, + input_value: RuntimeCallableArgument, + outputs: tuple[RuntimeMatchedOutput, ...], + plane_projection: RuntimePlaneAxisValueProjection | None, + ) -> RuntimeCallableArgument: + """Publish one recorded artifact through the canonical OpenHCS flow.""" + + del input_value, plane_projection + self.validate_main_flow_outputs(outputs) + if len(outputs) != 1: + raise ValueError( + f"{type(self).__name__} requires exactly one main-flow output, " + f"got {len(outputs)}." + ) + return outputs[0][2] + + def validate_main_flow_outputs( + self, + outputs: tuple[RuntimeMatchedOutput, ...], + ) -> None: + """Require every published output to belong to this nominal strategy.""" + + artifact_type = type(self).artifact_type + mismatched = tuple( + spec.ref() + for _plan, spec, _value in outputs + if spec.artifact_type is not artifact_type + ) + if mismatched: + raise TypeError( + f"{type(self).__name__} cannot publish outputs {mismatched!r}." + ) + @classmethod def transient_output_values( cls, @@ -113,6 +219,9 @@ def record_module_outputs( current_image: RuntimeCallableArgument, ) -> Mapping[ArtifactSpecRef, RuntimeCallableArgument]: """Record one module invocation's returned artifacts.""" + from openhcs.interop.cellprofiler.runtime.output_record_request import ( + CellProfilerOutputRecordRequest, + ) function_name = callable_contract.function_name active_output_plans = tuple(plan for plan, _spec, _value in matched_outputs) active_output_refs = frozenset(plan.ref() for plan in active_output_plans) @@ -186,15 +295,75 @@ class ImageOutputRecorder(CellProfilerOutputRecorder): artifact_type = ImageArtifactType + def raw_runtime_input_value( + self, spec: ArtifactSpec, value: RuntimeCallableArgument + ) -> RuntimeCallableArgument: + payload = value + metadata = image_payload_metadata(payload) + metadata = metadata.with_source_provenance( + metadata.source_provenance.with_derived_source_image_names( + (spec.name,) + ) + ) + return metadata.payload_with( + image_payload_data(payload), + mask=image_payload_mask(payload), + ) + + def runtime_input_value( + self, spec: ArtifactSpec, value: RuntimeCallableArgument + ) -> RuntimeCallableArgument: + return normalize_cellprofiler_image_payload( + self.raw_runtime_input_value(spec, value) + ) + + def source_image_name( + self, + spec: ArtifactSpec, + value: RuntimeCallableArgument, + ) -> str | None: + return self.source_image_name_from_value(self.raw_runtime_input_value(spec, value)) + + def source_image_name_from_value( + self, + value: RuntimeCallableArgument, + ) -> str | None: + return single_source_name( + image_payload_metadata(value).source_provenance.represented_source_image_names + ) + + def published_main_flow_output( + self, + input_value: RuntimeCallableArgument, + outputs: tuple[RuntimeMatchedOutput, ...], + plane_projection: RuntimePlaneAxisValueProjection | None, + ) -> RuntimeCallableArgument: + """Publish one or more named image outputs with exact plane context.""" + + self.validate_main_flow_outputs(outputs) + if not outputs: + raise ValueError("Image main-flow publication requires an output.") + return ImageOutputBundle( + tuple( + cellprofiler_main_flow_output( + input_value, + output_value, + plane_projection, + ) + for _plan, _spec, output_value in outputs + ), + AlignedImageSliceContext.main_flow_for_output_plans( + tuple(plan for plan, _spec, _value in outputs) + ), + ) + def record(self, request: CellProfilerOutputRecordRequest) -> None: module_type = CellProfilerModule.require_callable_contract_owner( request.callable_contract ) output_value = module_type.output_value(request) source_payload = module_type.source_payload(request) - value = FunctionOutputContextStrategy.for_output_plan( - request.output_plan, - ).contextualize( + value = request.output_plan.artifact_type.contextualize_output( source_payload, output_value, request.output_plan, @@ -212,6 +381,54 @@ class ObjectLabelsOutputRecorder(CellProfilerOutputRecorder): artifact_type = ObjectLabelsArtifactType + def object_labels( + self, + spec: ArtifactSpec, + value: RuntimeCallableArgument, + ) -> ObjectLabelSet: + """Return the native object value carrying its source-image provenance.""" + + if isinstance(value, ObjectLabelSet): + return value + metadata = image_payload_metadata(value) + return SourceImageObjectLabelBuildRequest( + image=value, + labels=image_payload_data(value), + plane_projection=RuntimePlaneAxisValueProjection.from_source_declaration( + metadata.plane_axis, metadata.source_provenance, + ), + ).label_set( + name=spec.name, + source_image_name=spec.name, + ) + + def runtime_input_value( + self, spec: ArtifactSpec, value: RuntimeCallableArgument + ) -> RuntimeCallableArgument: + return self.object_labels(spec, value) + + def raw_runtime_input_value( + self, + spec: ArtifactSpec, + value: RuntimeCallableArgument, + ) -> RuntimeCallableArgument: + """Return the nominal label set in the invocation's component scope.""" + + return self.object_labels(spec, value) + + def source_image_name( + self, + spec: ArtifactSpec, + value: RuntimeCallableArgument, + ) -> str | None: + return self.source_image_name_from_value(self.object_labels(spec, value)) + + def source_image_name_from_value( + self, + value: RuntimeCallableArgument, + ) -> str | None: + return cast(ObjectLabelSet, value).source_image_name + def record(self, request: CellProfilerOutputRecordRequest) -> None: module_type = CellProfilerModule.require_callable_contract_owner( request.callable_contract @@ -244,6 +461,28 @@ class MeasurementsOutputRecorder(CellProfilerOutputRecorder): artifact_type = MeasurementsArtifactType + def runtime_input_value( + self, spec: ArtifactSpec, value: RuntimeCallableArgument + ) -> RuntimeCallableArgument: + if not isinstance(value, MeasurementTable): + raise TypeError( + f"Measurement artifact {spec.name!r} requires a " + f"MeasurementTable, got {type(value).__name__}." + ) + return value.rows + + def source_image_name( + self, + spec: ArtifactSpec, + value: RuntimeCallableArgument, + ) -> str | None: + if not isinstance(value, MeasurementTable): + raise TypeError( + f"Measurement artifact {spec.name!r} requires a " + f"MeasurementTable, got {type(value).__name__}." + ) + return value.source_image_name + def record(self, request: CellProfilerOutputRecordRequest) -> None: module_type = CellProfilerModule.require_callable_contract_owner( request.callable_contract diff --git a/openhcs/interop/cellprofiler/runtime/primary_image_input_policies.py b/openhcs/interop/cellprofiler/runtime/primary_image_input_policies.py index 40a9e40801..93d2cf83f9 100644 --- a/openhcs/interop/cellprofiler/runtime/primary_image_input_policies.py +++ b/openhcs/interop/cellprofiler/runtime/primary_image_input_policies.py @@ -2,16 +2,15 @@ from __future__ import annotations -from collections.abc import Callable from dataclasses import replace from openhcs.core.artifacts import ( ArtifactSpec, ) +from openhcs.core.callable_contract import CallableContract from openhcs.core.runtime_object_labels import ObjectLabelValue from openhcs.core.steps.function_runtime import ( RuntimeCallableKwargs, - RuntimeFunctionOutput, ) from openhcs.interop.cellprofiler.runtime.invocation import CellProfilerImageRequest @@ -22,21 +21,21 @@ class ObjectLabelDrivenPrimaryImageInputPolicy: @classmethod def primary_image_inputs( cls, - func: Callable[..., RuntimeFunctionOutput], + contract: CallableContract, declared_inputs: tuple[ArtifactSpec, ...], ) -> tuple[ArtifactSpec, ...]: - del cls, func, declared_inputs + del cls, contract, declared_inputs return () @classmethod def invocation_domain_inputs( cls, - func: Callable[..., RuntimeFunctionOutput], + contract: CallableContract, declared_inputs: tuple[ArtifactSpec, ...], ) -> tuple[ArtifactSpec, ...]: """Return the exact object-label input that owns one invocation.""" - del func + del contract binding = cls.primary_image_domain_input_binding() parameter_name = binding.require_runtime_parameter_name() artifact_type = binding.require_artifact_type() diff --git a/openhcs/microscopes/openhcs.py b/openhcs/microscopes/openhcs.py index 08f98ca4c4..c9392894c8 100644 --- a/openhcs/microscopes/openhcs.py +++ b/openhcs/microscopes/openhcs.py @@ -29,7 +29,10 @@ SourceComponentProjectionStrategy, SourceVoxelSpacing, ) -from openhcs.core.source_workspace_projection import VirtualWorkspaceSourceProjection +from openhcs.core.source_workspace_projection import ( + VirtualWorkspaceSourceProjection, + VirtualWorkspaceSourceProjectionBuilder, +) from metaclass_registry import AutoRegisterMeta from polystore.exceptions import MetadataNotFoundError from polystore.filemanager import FileManager @@ -39,6 +42,9 @@ FIELDS, METADATA_CONFIG, MetadataWriteError, + OpenHCSMetadataSubdirectories, + VirtualWorkspaceMapping, + VirtualWorkspaceSourceProjectionEntries, component_metadata_field, get_metadata_path, ) @@ -381,7 +387,65 @@ def analysis_result_directories( plate_root, metadata_document ) ) + return self._analysis_result_directories( + plate_root, subdirectories, source_projection + ) + + def reconciliation_directories( + self, plate_path: Union[str, Path], backend: str + ) -> tuple[Path, ...]: + """Derive artifact and result destinations from one admitted document. + Projection records are admitted before workspace fields, as required by + completed-plate reconciliation. The same admitted records then populate + the result-directory source authority; they are not decoded a second time. + """ + plate_root = Path(plate_path) + metadata_path = METADATA_CONFIG.metadata_path(plate_root) + if not metadata_path.is_file(): + return tuple( + directory.path + for directory in self.analysis_result_directories(plate_root) + ) + document = OpenHCSMetadataSubdirectories.from_path(metadata_path) + admitted = tuple( + ( + subdirectory, + VirtualWorkspaceSourceProjectionEntries.from_subdirectory(subdirectory), + ) + for _name, subdirectory in document.items() + ) + directories = tuple( + plate_root / directory + for _subdirectory, entries in admitted + for path, projection in entries.entries.items() + if (directory := projection.artifact_result_directory(path, backend)) + is not None + ) + subdirectories = self._metadata_subdirectories(document.metadata, plate_root) + source_projection = None + if document.has_workspace_mapping(): + builder = VirtualWorkspaceSourceProjectionBuilder(plate_root) + for subdirectory, entries in admitted: + builder.ingest_workspace_mapping( + VirtualWorkspaceMapping.from_subdirectory(subdirectory) + ) + builder.ingest_admitted_subdirectory(subdirectory, entries) + source_projection = builder.projection() + results = self._analysis_result_directories( + plate_root, subdirectories, source_projection + ) + return tuple( + dict.fromkeys((*directories, *(directory.path for directory in results))) + ) + + def _analysis_result_directories( + self, + plate_root: Path, + subdirectories: Mapping[str, Mapping[str, Any]], + source_projection: VirtualWorkspaceSourceProjection | None, + ) -> tuple[AnalysisResultDirectory, ...]: + """Admit declared result paths against their document's source authority.""" result_directories = [] for subdirectory_name, subdirectory_data in subdirectories.items(): result_dir_name = _optional_metadata_field(subdirectory_data, "results_dir") diff --git a/openhcs/processing/backends/cellprofiler/_backend.py b/openhcs/processing/backends/cellprofiler/_backend.py index e37742d5b1..811a6deebc 100644 --- a/openhcs/processing/backends/cellprofiler/_backend.py +++ b/openhcs/processing/backends/cellprofiler/_backend.py @@ -14,6 +14,7 @@ from openhcs.constants.constants import MemoryType from openhcs.core.callable_contract import CallableContract from openhcs.core.processing_preparation import PersistentNumbaKernelPreparation +from openhcs.core.runtime_object_labels import DenseArrayObjectLabelStorageStrategy from openhcs.core.runtime_plane_projection import RuntimeSliceInvariantValue @@ -306,6 +307,7 @@ def prepare_registered_family(cls) -> None: """Prepare every registered backend implementation for compiler warmup.""" if cls is CellProfilerBackendStrategyMixin: return + DenseArrayObjectLabelStorageStrategy.prepare_coordinates() snapshot = CellProfilerBackendRegistrySnapshot.for_family( cls, MemoryType.NUMPY, diff --git a/openhcs/processing/backends/cellprofiler/_preparation.py b/openhcs/processing/backends/cellprofiler/_preparation.py index 933a8a3795..cea2850ff1 100644 --- a/openhcs/processing/backends/cellprofiler/_preparation.py +++ b/openhcs/processing/backends/cellprofiler/_preparation.py @@ -3,6 +3,7 @@ from __future__ import annotations from openhcs.core.processing_preparation import RegisteredNumbaKernelPreparation +from openhcs.core.runtime_object_labels import DenseArrayObjectLabelStorageStrategy from openhcs.processing.backends.cellprofiler.perf_fixtures import capture_enabled @@ -20,4 +21,5 @@ def can_prepare_in_child(cls) -> bool: def prepare_registered_family(cls) -> None: if capture_enabled(): return + DenseArrayObjectLabelStorageStrategy.prepare_coordinates() super().prepare_registered_family() diff --git a/openhcs/processing/backends/cellprofiler/alignment.py b/openhcs/processing/backends/cellprofiler/alignment.py index 9ef9b11ba2..b32e4a5ef5 100644 --- a/openhcs/processing/backends/cellprofiler/alignment.py +++ b/openhcs/processing/backends/cellprofiler/alignment.py @@ -40,6 +40,7 @@ RuntimePlaneAxisValueProjection, ) from openhcs.core.runtime_slice_projection import RuntimeSliceProjection +from openhcs.core.runtime_array_values import RuntimeArrayData from openhcs.core.runtime_image_values import ( ImagePayloadMetadata, MaskedImagePayload, @@ -1083,7 +1084,7 @@ def prepare_align() -> None: @required_variable_components(VariableComponents.CHANNEL) @numpy(contract=ProcessingContract.PURE_3D) def align( - image: np.ndarray, + image: RuntimeArrayData, *, method: AlignModule.Method = AlignModule.Method.MUTUAL_INFORMATION, crop_mode: AlignModule.CropMode = AlignModule.CropMode.KEEP_SIZE, diff --git a/openhcs/processing/backends/cellprofiler/area_occupied.py b/openhcs/processing/backends/cellprofiler/area_occupied.py index 44049e52b8..e748871e96 100644 --- a/openhcs/processing/backends/cellprofiler/area_occupied.py +++ b/openhcs/processing/backends/cellprofiler/area_occupied.py @@ -728,7 +728,7 @@ def measure(self) -> AreaOccupiedMeasurement: SliceIndexRuntimeParameter, ) def measure_image_area_occupied( - image: np.ndarray, + image: RuntimeArrayData, *, operand_choices: Sequence[OperandChoice] = (OperandChoice.BINARY_IMAGE,), area_occupied_rows: Sequence[AreaOccupiedRow] = (), diff --git a/openhcs/processing/backends/cellprofiler/calculate_statistics.py b/openhcs/processing/backends/cellprofiler/calculate_statistics.py index a9bae1830b..87d75b88ca 100644 --- a/openhcs/processing/backends/cellprofiler/calculate_statistics.py +++ b/openhcs/processing/backends/cellprofiler/calculate_statistics.py @@ -25,7 +25,7 @@ from openhcs.core.memory.decorators import numpy from openhcs.core.measurement_feature_queries import ( MeasurementFeatureQuery, - MeasurementTableObjectFeatureSemantics, + ColumnarMeasurementTableSchema, ) from openhcs.core.measurement_row_materialization import ( MeasurementProjectedColumnarRows, @@ -417,17 +417,17 @@ def _statistics_feature_series( for table in measurement_tables: if table.subject.scope not in {MeasurementScope.IMAGE, MeasurementScope.OBJECT}: continue - semantics = MeasurementTableObjectFeatureSemantics.from_table(table) + semantics = ColumnarMeasurementTableSchema.from_table(table) object_names = ( (MeasurementScope.IMAGE.value.title(),) if table.subject.scope is MeasurementScope.IMAGE - else semantics.object_names + else semantics.object_names(table) ) for object_name in object_names: query_object_name = ( None if table.subject.scope is MeasurementScope.IMAGE else object_name ) - for feature_name in sorted(semantics.feature_names): + for feature_name in sorted(semantics.feature_names(table)): if ( feature_name in MeasurementRowAxisField.field_names() or feature_name in MeasurementRowValueField.field_names() diff --git a/openhcs/processing/backends/cellprofiler/classification.py b/openhcs/processing/backends/cellprofiler/classification.py index 4783e7e795..d265f9fa3d 100644 --- a/openhcs/processing/backends/cellprofiler/classification.py +++ b/openhcs/processing/backends/cellprofiler/classification.py @@ -74,7 +74,7 @@ ) if TYPE_CHECKING: - from openhcs.core.function_patterns import FunctionInvocation + from openhcs.core.function_patterns import NormalizedFunctionItem from openhcs.interop.cellprofiler.parser import ModuleBlock from openhcs.interop.cellprofiler.settings_binder import SettingsBinder @@ -1317,7 +1317,7 @@ def classified_image_outputs( @abstractmethod def finalize_mode_blocks( self, module_type: type[ClassifyObjectsSingleMeasurementModule], - blocks: tuple[ModuleBlock, ...], invocation: FunctionInvocation, + blocks: tuple[ModuleBlock, ...], invocation: NormalizedFunctionItem, ) -> tuple[ModuleBlock, ...]: """Complete this mode after the shared template emits its literal.""" @@ -1472,7 +1472,7 @@ def classified_image_outputs( def finalize_module_blocks( self, module_type: type[ClassifyObjectsSingleMeasurementModule], - blocks: tuple[ModuleBlock, ...], invocation: FunctionInvocation, + blocks: tuple[ModuleBlock, ...], invocation: NormalizedFunctionItem, ) -> tuple[ModuleBlock, ...]: blocks = tuple( replace( @@ -2028,7 +2028,7 @@ def object_classification_backend( SliceIndexRuntimeParameter, ) def classify_objects_single_measurement( - image: np.ndarray, + image: RuntimeArrayData, labels: ObjectLabelValue, measurement_feature: str = "", measurement_values: np.ndarray | None = None, diff --git a/openhcs/processing/backends/cellprofiler/colocalization.py b/openhcs/processing/backends/cellprofiler/colocalization.py index 21eff8b11f..3ce87eb13e 100644 --- a/openhcs/processing/backends/cellprofiler/colocalization.py +++ b/openhcs/processing/backends/cellprofiler/colocalization.py @@ -2522,7 +2522,7 @@ def _colocalization_unit_interval_scale( @numpy(contract=ProcessingContract.FLEXIBLE) @runtime_bound_parameters(_ColocalizationThresholdMaskOutputsRuntimeParameter) def measure_colocalization( - image: np.ndarray, + image: RuntimeArrayData, channel_1: int = 0, channel_2: int = 1, threshold_percent: float = 15.0, @@ -2790,7 +2790,7 @@ def _measure_colocalization_objects_core( _ColocalizationCostesThresholdBatchRuntimeParameter, ) def measure_colocalization_objects( - image: np.ndarray, + image: RuntimeArrayData, labels: ObjectLabelValue, measurement_scope: CellProfilerMeasurementTargetScope = CellProfilerMeasurementTargetScope.OBJECT, channel_1: int = 0, @@ -2881,7 +2881,7 @@ def measure_colocalization_objects( def _colocalization_threshold_mask_canonical_output( - image: np.ndarray, + image: RuntimeArrayData, *, threshold_mask_groups: tuple[ColocalizationThresholdMaskGroup, ...], threshold_mask_outputs: tuple[ColocalizationThresholdMaskRuntimeOutput, ...], @@ -2911,7 +2911,7 @@ def _colocalization_threshold_mask_canonical_output( def _colocalization_threshold_mask( - image: np.ndarray, + image: RuntimeArrayData, request: ColocalizationThresholdMaskRuntimeOutput, ) -> RuntimeArrayData: """Apply CellProfiler's whole-image or per-object percentage threshold.""" diff --git a/openhcs/processing/backends/cellprofiler/color.py b/openhcs/processing/backends/cellprofiler/color.py index a762c62592..16ebc86a8e 100644 --- a/openhcs/processing/backends/cellprofiler/color.py +++ b/openhcs/processing/backends/cellprofiler/color.py @@ -1542,7 +1542,7 @@ def run(self, request: GrayToColorRequest) -> np.ndarray: @composed_image_payload @numpy(contract=ProcessingContract.PURE_3D) def gray_to_color( - image: np.ndarray, + image: RuntimeArrayData, color_scheme: GrayToColorModule.Scheme = GrayToColorModule.Scheme.RGB, rescale_intensity: bool = True, red_channel: int = -1, @@ -1641,7 +1641,7 @@ def gray_to_color( ) @numpy(contract=ProcessingContract.FLEXIBLE) def color_to_gray( - image: np.ndarray, + image: RuntimeArrayData, mode: ColorToGrayMode = ColorToGrayMode.SPLIT, image_type: ImageChannelType = ImageChannelType.RGB, channel_indices: tuple[int, ...] = ColorToGrayModule.default_channel_indices, @@ -1673,7 +1673,7 @@ def color_to_gray( def _invert_for_printing_channels( - image: np.ndarray, + image: RuntimeArrayData, *, input_mode: InvertInputMode, use_red_input: bool, @@ -1715,7 +1715,7 @@ def _invert_for_printing_channels( def _invert_for_printing_result( - image: np.ndarray, + image: RuntimeArrayData, *, input_mode: InvertInputMode, use_red_input: bool, @@ -1797,7 +1797,7 @@ def _invert_for_printing_result( @composed_image_payload @numpy(contract=ProcessingContract.PURE_3D) def invert_for_printing( - image: np.ndarray, + image: RuntimeArrayData, input_mode: InvertInputMode = InvertInputMode.COLOR, use_red_input: bool = True, use_green_input: bool = True, @@ -1833,7 +1833,7 @@ def invert_for_printing( @composed_image_payload @numpy(contract=ProcessingContract.PURE_3D) def invert_for_printing_grayscale( - image: np.ndarray, + image: RuntimeArrayData, input_mode: InvertInputMode = InvertInputMode.COLOR, use_red_input: bool = True, use_green_input: bool = True, @@ -1876,7 +1876,7 @@ def invert_for_printing_grayscale( @composed_image_payload @numpy(contract=ProcessingContract.PURE_3D) def invert_for_printing_without_output( - image: np.ndarray, + image: RuntimeArrayData, input_mode: InvertInputMode = InvertInputMode.COLOR, use_red_input: bool = True, use_green_input: bool = True, @@ -1915,7 +1915,7 @@ def invert_for_printing_without_output( def combine_color_to_gray( - image: np.ndarray, + image: RuntimeArrayData, channel_indices: tuple[int, ...], contributions: tuple[float, ...], ) -> np.ndarray: @@ -1931,7 +1931,7 @@ def combine_color_to_gray( return restore_color_to_gray_shape(image, result) -def color_to_gray_combine_output_metadata(image: np.ndarray): +def color_to_gray_combine_output_metadata(image: RuntimeArrayData): """Return metadata for a color-to-grayscale semantic collapse.""" return ( image_payload_metadata(image) @@ -1941,7 +1941,7 @@ def color_to_gray_combine_output_metadata(image: np.ndarray): def split_color_to_gray( - image: np.ndarray, image_type: ImageChannelType, channel_indices: tuple[int, ...] + image: RuntimeArrayData, image_type: ImageChannelType, channel_indices: tuple[int, ...] ) -> tuple[np.ndarray, ...]: color_stack = nhwc_color_stack(image).astype(np.float32) source_stack = ( @@ -1967,7 +1967,7 @@ def color_to_gray_channel(color_stack: np.ndarray, channel_index: int) -> np.nda return color_stack[..., channel_index] -def nhwc_color_stack(image: np.ndarray) -> np.ndarray: +def nhwc_color_stack(image: RuntimeArrayData) -> np.ndarray: """Return NHWC pixels from explicitly declared image layout metadata.""" image_data = np.asarray(image_payload_data(image)) metadata = image_payload_metadata(image) @@ -1998,7 +1998,7 @@ def nhwc_color_stack(image: np.ndarray) -> np.ndarray: return channel_last -def restore_color_to_gray_shape(original: np.ndarray, stack: np.ndarray) -> np.ndarray: +def restore_color_to_gray_shape(original: RuntimeArrayData, stack: np.ndarray) -> np.ndarray: metadata = image_payload_metadata(original) if metadata.is_declared_source_channel_plane(original): if stack.shape[0] != 1: @@ -2056,7 +2056,7 @@ def rgb_to_hsv_stack(rgb_stack: np.ndarray) -> np.ndarray: @numpy(contract=ProcessingContract.FLEXIBLE) def unmix_colors( - image: np.ndarray, + image: RuntimeArrayData, stain_names: Sequence[StainType] = (), custom_absorbances: Sequence[Sequence[float] | None] = (), stain1: StainType = StainType.HEMATOXYLIN, diff --git a/openhcs/processing/backends/cellprofiler/crop.py b/openhcs/processing/backends/cellprofiler/crop.py index 62fd7e1ba9..79db9fe1e5 100644 --- a/openhcs/processing/backends/cellprofiler/crop.py +++ b/openhcs/processing/backends/cellprofiler/crop.py @@ -24,6 +24,7 @@ ) from openhcs.core.pipeline.function_contracts import special_inputs from openhcs.core.runtime_measurements import RuntimeMeasurementFeature +from openhcs.core.runtime_array_values import RuntimeArrayData from openhcs.core.runtime_image_values import ( ImagePayloadMetadata, image_payload_data, @@ -608,7 +609,7 @@ def cropped_pixels(self) -> np.ndarray: class CropRequest: """Executable CellProfiler Crop request.""" - image: np.ndarray + image: RuntimeArrayData mask_plane: np.ndarray | None = None crop_shape: CropModule.Shape = CropModule.Shape.RECTANGLE cropping_method: CropModule.Method = CropModule.Method.COORDINATES @@ -857,7 +858,7 @@ def crop_output_metadata( @numpy_decorator(contract=ProcessingContract.PURE_2D) @special_inputs("topology_inputs") def crop( - image: np.ndarray, + image: RuntimeArrayData, topology_inputs: tuple[np.ndarray | ObjectLabelValue, ...] = (), crop_shape: CropModule.Shape = CropModule.Shape.RECTANGLE, cropping_method: CropModule.Method = CropModule.Method.COORDINATES, diff --git a/openhcs/processing/backends/cellprofiler/display_modules.py b/openhcs/processing/backends/cellprofiler/display_modules.py index 28c40ce4f4..d5566f0a94 100644 --- a/openhcs/processing/backends/cellprofiler/display_modules.py +++ b/openhcs/processing/backends/cellprofiler/display_modules.py @@ -29,6 +29,7 @@ special_inputs, ) from openhcs.core.registry_strategies import EnumKeyedStrategyMixin +from openhcs.core.runtime_array_values import RuntimeArrayData from openhcs.core.runtime_image_values import ( image_payload_data, image_payload_metadata, @@ -492,7 +493,7 @@ def render_slice(self) -> np.ndarray: @special_inputs("labels") @runtime_bound_parameters(_DisplayMeasurementsRuntimeParameter) def display_data_on_image( - image: np.ndarray, + image: RuntimeArrayData, labels: Optional[ObjectLabelValue] = None, measurements: Optional[np.ndarray] = None, measurement_feature: Optional[str] = None, diff --git a/openhcs/processing/backends/cellprofiler/edge.py b/openhcs/processing/backends/cellprofiler/edge.py index 30bc44280d..5e01b30a19 100644 --- a/openhcs/processing/backends/cellprofiler/edge.py +++ b/openhcs/processing/backends/cellprofiler/edge.py @@ -50,6 +50,7 @@ class EnhanceEdgesModule(CellProfilerModule): from numba import njit from openhcs.core.memory.decorators import numpy as numpy_decorator from openhcs.core.public_api import public_names_from_objects +from openhcs.core.runtime_array_values import RuntimeArrayData from openhcs.core.runtime_image_values import ( image_payload_data, image_payload_mask, @@ -508,7 +509,7 @@ def _native_kirsch(image: np.ndarray) -> np.ndarray: @numpy_decorator(contract=ProcessingContract.PURE_2D) def enhance_edges( - image: np.ndarray, + image: RuntimeArrayData, method: EdgeMethod = EdgeMethod.SOBEL, direction: EdgeDirection = EdgeDirection.ALL, edge_backend_provider: BackendProviderInput = DEFAULT_CELLPROFILER_BACKEND_SELECTION, diff --git a/openhcs/processing/backends/cellprofiler/feature_enhancement.py b/openhcs/processing/backends/cellprofiler/feature_enhancement.py index b8f6bd7bda..a2b813799b 100644 --- a/openhcs/processing/backends/cellprofiler/feature_enhancement.py +++ b/openhcs/processing/backends/cellprofiler/feature_enhancement.py @@ -13,6 +13,7 @@ from openhcs.core.callable_contract import processing_prepare from openhcs.core.memory.decorators import numpy from openhcs.core.registry_strategies import EnumKeyedStrategyMixin +from openhcs.core.runtime_array_values import RuntimeArrayData from openhcs.core.runtime_image_values import ( image_payload_data, image_payload_mask, @@ -65,7 +66,7 @@ class NeuriteMethod(Enum): @numpy(contract=ProcessingContract.PURE_2D) def enhance_or_suppress_features( - image: np.ndarray, + image: RuntimeArrayData, method: OperationMethod = OperationMethod.ENHANCE, enhance_method: EnhanceMethod = EnhanceMethod.SPECKLES, radius: float = 10.0, diff --git a/openhcs/processing/backends/cellprofiler/gaussian_filter.py b/openhcs/processing/backends/cellprofiler/gaussian_filter.py index 187d4d972d..7018d62595 100644 --- a/openhcs/processing/backends/cellprofiler/gaussian_filter.py +++ b/openhcs/processing/backends/cellprofiler/gaussian_filter.py @@ -7,6 +7,7 @@ from openhcs.core.aligned_image_payload import ImagePayloadExecutionMode from openhcs.core.callable_contract import runtime_image_execution_mode +from openhcs.core.runtime_array_values import RuntimeArrayData from openhcs.core.runtime_image_values import ( image_payload_data, image_payload_metadata, @@ -41,7 +42,7 @@ class GaussianFilterModule(CellProfilerModule): @runtime_image_execution_mode(ImagePayloadExecutionMode.FULL_STACK) @numpy(contract=ProcessingContract.FLEXIBLE) -def gaussian_filter(image: np.ndarray, sigma: float = 1.0) -> np.ndarray: +def gaussian_filter(image: RuntimeArrayData, sigma: float = 1.0) -> np.ndarray: """ Apply CellProfiler-compatible Gaussian smoothing to an image. diff --git a/openhcs/processing/backends/cellprofiler/grid.py b/openhcs/processing/backends/cellprofiler/grid.py index ad92c9b044..3c83012bde 100644 --- a/openhcs/processing/backends/cellprofiler/grid.py +++ b/openhcs/processing/backends/cellprofiler/grid.py @@ -18,6 +18,7 @@ from openhcs.constants.constants import VariableComponents from openhcs.core.aligned_image_payload import ImagePayloadExecutionMode +from openhcs.core.runtime_array_values import RuntimeArrayData from openhcs.core.artifacts import ( ArtifactSpecCollection, ArtifactSpecRelation, @@ -1293,14 +1294,14 @@ class IdentifyObjectsInGridRequest(GridShapeContext): """Executable request for CellProfiler IdentifyObjectsInGrid semantics.""" registry_key = "identify_objects" - image: np.ndarray + image: RuntimeArrayData shape_choice: ShapeChoice @classmethod def from_runtime( cls, *, - image: np.ndarray, + image: RuntimeArrayData, grid_definition: GridRuntimeDefinitionRequest, shape_choice: ShapeChoice, diameter_choice: DiameterChoice, @@ -1485,7 +1486,7 @@ def draw_grid_overlay( @numpy(contract=ProcessingContract.PURE_2D) @special_inputs("topology_inputs") def identify_objects_in_grid( - image: np.ndarray, + image: RuntimeArrayData, topology_inputs: tuple[SpatialGrid | ObjectLabelValue, ...], grid_rows: int = 8, grid_columns: int = 12, diff --git a/openhcs/processing/backends/cellprofiler/illumination.py b/openhcs/processing/backends/cellprofiler/illumination.py index db283789d6..3c53edf1f8 100644 --- a/openhcs/processing/backends/cellprofiler/illumination.py +++ b/openhcs/processing/backends/cellprofiler/illumination.py @@ -922,7 +922,7 @@ def image_payload( @numpy(contract=ProcessingContract.FLEXIBLE) def correct_illumination_calculate( - image: np.ndarray, + image: RuntimeArrayData, intensity_choice: IntensityChoice = IntensityChoice.REGULAR, dilate_objects: bool = False, object_dilation_radius: int = 1, diff --git a/openhcs/processing/backends/cellprofiler/image_geometry.py b/openhcs/processing/backends/cellprofiler/image_geometry.py index 61bdddcca5..f51560c8a8 100644 --- a/openhcs/processing/backends/cellprofiler/image_geometry.py +++ b/openhcs/processing/backends/cellprofiler/image_geometry.py @@ -1093,12 +1093,12 @@ def align_label_plane_to_shape( @numpy(contract=ProcessingContract.FLEXIBLE) @special_inputs("mask") def mask_image( - image: np.ndarray, + image: RuntimeArrayData, mask: np.ndarray | ObjectLabelValue, mask_source: MaskSource = MaskSource.IMAGE, invert_mask: bool = False, binary_threshold: float = 0.5, -) -> np.ndarray: +) -> RuntimeArrayData: """Mask an image using CellProfiler image/object mask semantics. Args: @@ -1130,7 +1130,7 @@ def mask_image( def masked_image_plane( - image: np.ndarray, binary_mask: np.ndarray, *, invert_mask: bool + image: RuntimeArrayData, binary_mask: np.ndarray, *, invert_mask: bool ) -> tuple[np.ndarray, np.ndarray]: image_data = image_payload_data(image) if invert_mask: @@ -1159,7 +1159,7 @@ def masked_image_plane( @numpy(contract=ProcessingContract.PURE_2D) def mask_image_with_binary( - image: np.ndarray, invert_mask: bool = False + image: RuntimeArrayData, invert_mask: bool = False ) -> RuntimeArrayData: """Return a binary mask plane, optionally inverted.""" binary_mask = image_payload_data(image) > 0.5 @@ -1220,7 +1220,7 @@ def tile_output_shape( @numpy(contract=ProcessingContract.FLEXIBLE) def tile( - image: np.ndarray, + image: RuntimeArrayData, rows: int = 8, columns: int = 12, place_first: PlaceFirst = PlaceFirst.TOP_LEFT, @@ -1276,14 +1276,14 @@ def tile( @numpy(contract=ProcessingContract.PURE_2D) def resize( - image: np.ndarray, + image: RuntimeArrayData, resize_method: ResizeMethod = ResizeMethod.BY_FACTOR, resizing_factor_x: float = 0.25, resizing_factor_y: float = 0.25, specific_width: int = 100, specific_height: int = 100, interpolation: InterpolationMethod = InterpolationMethod.NEAREST_NEIGHBOR, -) -> np.ndarray: +) -> RuntimeArrayData: """Resize a CellProfiler image plane by factor or explicit dimensions.""" pixels = image_payload_data(image) geometry = ResizeGeometry.from_parameters( @@ -1298,7 +1298,7 @@ def resize( @numpy(contract=ProcessingContract.PURE_3D) def resize_volumetric( - image: np.ndarray, + image: RuntimeArrayData, resize_method: ResizeMethod = ResizeMethod.BY_FACTOR, resizing_factor_x: float = 0.25, resizing_factor_y: float = 0.25, @@ -1307,7 +1307,7 @@ def resize_volumetric( specific_height: int = 100, specific_planes: int = 10, interpolation: InterpolationMethod = InterpolationMethod.NEAREST_NEIGHBOR, -) -> np.ndarray: +) -> RuntimeArrayData: """Resize a CellProfiler ZYX image volume by factor or explicit dimensions.""" pixels = image_payload_data(image) geometry = ResizeGeometry.from_trailing_spatial_parameters( @@ -1322,7 +1322,7 @@ def resize_volumetric( @numpy(contract=ProcessingContract.PURE_2D) def flip_and_rotate( - image: np.ndarray, + image: RuntimeArrayData, flip_method: FlipMethod = FlipMethod.NONE, rotate_method: RotateMethod = RotateMethod.NONE, rotation_angle: float = 0.0, diff --git a/openhcs/processing/backends/cellprofiler/image_quality.py b/openhcs/processing/backends/cellprofiler/image_quality.py index e4338ba2f8..741d26e074 100644 --- a/openhcs/processing/backends/cellprofiler/image_quality.py +++ b/openhcs/processing/backends/cellprofiler/image_quality.py @@ -2,6 +2,7 @@ from __future__ import annotations +from openhcs.core.runtime_array_values import RuntimeArrayData from openhcs.core.process_local_cache import RegisteredProcessLocalBoundedCache from abc import ABC, abstractmethod @@ -1565,7 +1566,7 @@ def _haralick_h3_numba(image: np.ndarray, scale: int) -> float: @numpy(contract=ProcessingContract.PURE_2D) def measure_image_quality( - image: np.ndarray, + image: RuntimeArrayData, include_scaling: bool = True, calculate_blur: bool = True, calculate_saturation: bool = True, diff --git a/openhcs/processing/backends/cellprofiler/infrastructure.py b/openhcs/processing/backends/cellprofiler/infrastructure.py index 8fc913576d..809171fe43 100644 --- a/openhcs/processing/backends/cellprofiler/infrastructure.py +++ b/openhcs/processing/backends/cellprofiler/infrastructure.py @@ -41,6 +41,7 @@ ) from openhcs.core.source_matching import source_metadata_component from openhcs.core.source_metadata import SourceVoxelSpacing +from openhcs.core.source_spatial_domain import VolumeSourceSpatialDomain from openhcs.core.runtime_tabular_values import FieldSpec from openhcs.interop.cellprofiler.cellprofiler_literals import ( decode_cellprofiler_setting_literal, @@ -1408,10 +1409,12 @@ def contribute_source_bindings( explicit_sources.append(explicit_source) source_stack_components = config.source_stack_components + source_spatial_domain = config.source_spatial_domain if module.get_setting("Process as 3D?", "No").strip().casefold() == "yes": source_stack_components = tuple( dict.fromkeys((*source_stack_components, AllComponents.Z_INDEX)) ) + source_spatial_domain = VolumeSourceSpatialDomain() voxel_spacing = SourceVoxelSpacing.from_cellprofiler_xyz( x=_positive_float_setting( module, @@ -1436,6 +1439,7 @@ def contribute_source_bindings( dict.fromkeys((*config.image_plane_sources, *explicit_sources)) ), source_stack_components=source_stack_components, + source_spatial_domain=source_spatial_domain, source_voxel_spacing=voxel_spacing, ) diff --git a/openhcs/processing/backends/cellprofiler/intensity.py b/openhcs/processing/backends/cellprofiler/intensity.py index 7575aba5f7..f7bed622bf 100644 --- a/openhcs/processing/backends/cellprofiler/intensity.py +++ b/openhcs/processing/backends/cellprofiler/intensity.py @@ -303,6 +303,7 @@ def active_artifact_bindings( from openhcs.core.runtime_plane_projection import ( RuntimePlaneAxis, ) +from openhcs.core.runtime_array_values import RuntimeArrayData from openhcs.core.runtime_image_values import ( ImageMetadataPayload, MaskedImagePayload, @@ -1560,7 +1561,7 @@ def _object_intensity_batch_key( @object_label_input_execution_mode(ObjectLabelInputExecutionMode.SLICE_ALIGNED) @runtime_bound_parameters(SliceIndexRuntimeParameter) def measure_object_intensity( - image: np.ndarray, + image: RuntimeArrayData, labels: ObjectLabelValue, object_intensity_backend_provider: BackendProviderInput = DEFAULT_CELLPROFILER_BACKEND_SELECTION, slice_index: int = OBJECT_INTENSITY_DEFAULT_SLICE_INDEX, @@ -1857,7 +1858,7 @@ def run(self, context: RescaleIntensityContext) -> np.ndarray: @runtime_image_execution_mode(ImagePayloadExecutionMode.FULL_STACK) @numpy_decorator(contract=ProcessingContract.PURE_2D) def rescale_intensity( - image: np.ndarray, + image: RuntimeArrayData, rescale_method: RescaleMethod = RescaleMethod.STRETCH, automatic_low: AutomaticLow = AutomaticLow.EACH_IMAGE, automatic_high: AutomaticHigh = AutomaticHigh.EACH_IMAGE, diff --git a/openhcs/processing/backends/cellprofiler/intensity_distribution.py b/openhcs/processing/backends/cellprofiler/intensity_distribution.py index c9c89ba06d..535a9a4ff2 100644 --- a/openhcs/processing/backends/cellprofiler/intensity_distribution.py +++ b/openhcs/processing/backends/cellprofiler/intensity_distribution.py @@ -102,7 +102,6 @@ ) from openhcs.interop.cellprofiler.measurement_dialect import ( CELLPROFILER_MEASUREMENT_DIALECT, - cellprofiler_projected_measurement_feature_name, ) from openhcs.processing.backends.lib_registry.unified_registry import ProcessingContract from openhcs.processing.backends.cellprofiler._backend import ( @@ -416,7 +415,7 @@ def feature_name(cls, identity: object) -> str: raise TypeError( "Radial feature rendering requires IndexedRadialDistributionFeature." ) - return cellprofiler_projected_measurement_feature_name( + return CELLPROFILER_MEASUREMENT_DIALECT.projected_feature_name( identity.feature.source_qualified_name( source_image_name=identity.source_image_name ), @@ -2461,7 +2460,7 @@ def _radial_distribution_arrays_from_bin_totals_numba( _IntensityDistributionHeatmapOutputsRuntimeParameter, ) def measure_object_intensity_distribution( - image: np.ndarray, + image: RuntimeArrayData, labels: ObjectLabelValue, bin_count: int = 4, wants_scaled: bool = True, @@ -2562,7 +2561,7 @@ def measure_object_intensity_distribution( def _intensity_distribution_heatmap( - image: np.ndarray, + image: RuntimeArrayData, request: IntensityDistributionHeatmapRuntimeOutput, *, radial_backend: "RadialDistributionBackendStrategy", diff --git a/openhcs/processing/backends/cellprofiler/manual_objects.py b/openhcs/processing/backends/cellprofiler/manual_objects.py index f4c64435b8..6ae87fa586 100644 --- a/openhcs/processing/backends/cellprofiler/manual_objects.py +++ b/openhcs/processing/backends/cellprofiler/manual_objects.py @@ -16,6 +16,7 @@ import numpy as np +from openhcs.core.runtime_array_values import RuntimeArrayData from openhcs.core.artifacts import ( ArtifactSpec, ImageArtifactType, @@ -63,7 +64,7 @@ class ManualObjectStats: ) @numpy(contract=ProcessingContract.PURE_2D) def identify_objects_manually( - image: np.ndarray, + image: RuntimeArrayData, labels_input: np.ndarray | None = None, ) -> tuple[ np.ndarray, diff --git a/openhcs/processing/backends/cellprofiler/median_filter.py b/openhcs/processing/backends/cellprofiler/median_filter.py index ca24bd2c00..ec19edfcc9 100644 --- a/openhcs/processing/backends/cellprofiler/median_filter.py +++ b/openhcs/processing/backends/cellprofiler/median_filter.py @@ -19,6 +19,7 @@ RuntimePure2DSliceBatchRequest, pure_2d_batch_executor, ) +from openhcs.core.runtime_array_values import RuntimeArrayData from openhcs.core.runtime_image_values import ( image_payload_data, with_image_payload_data, @@ -371,7 +372,7 @@ def median_filter_backend( @runtime_image_execution_mode(ImagePayloadExecutionMode.FULL_STACK) @numpy(contract=ProcessingContract.FLEXIBLE) def medianfilter( - image: np.ndarray, + image: RuntimeArrayData, window_size: int = 3, mode: ScipyBoundaryMode = ScipyBoundaryMode.CONSTANT, ) -> np.ndarray: diff --git a/openhcs/processing/backends/cellprofiler/morphology.py b/openhcs/processing/backends/cellprofiler/morphology.py index e79df88ea6..eeff8a0b25 100644 --- a/openhcs/processing/backends/cellprofiler/morphology.py +++ b/openhcs/processing/backends/cellprofiler/morphology.py @@ -690,6 +690,7 @@ def artifact_output_relations( object_label_identity_lineage_payload, object_label_parent_child_payload, ) +from openhcs.core.runtime_array_values import RuntimeArrayData from openhcs.core.runtime_image_values import ( ImagePayloadMetadata, image_payload_data, @@ -1491,7 +1492,7 @@ def _morph_image_pixels( def _morph_image_payload( - image: np.ndarray, + image: RuntimeArrayData, structuring_element: StructuringElement, size: int, operation: Callable[[np.ndarray, np.ndarray], np.ndarray], @@ -1508,7 +1509,7 @@ def _morph_image_payload( @runtime_image_execution_mode(ImagePayloadExecutionMode.FULL_STACK) @numpy_decorator(contract=ProcessingContract.FLEXIBLE) def closing( - image: np.ndarray, + image: RuntimeArrayData, structuring_element: StructuringElementInput = StructuringElement.DISK, size: StructuringElementSize = 3, morphology_backend_provider: BackendProviderInput = CellProfilerBackendProvider.NATIVE, @@ -1530,7 +1531,7 @@ def closing( @runtime_image_execution_mode(ImagePayloadExecutionMode.FULL_STACK) @numpy_decorator(contract=ProcessingContract.FLEXIBLE) def opening( - image: np.ndarray, + image: RuntimeArrayData, structuring_element: StructuringElementInput = StructuringElement.DISK, size: StructuringElementSize = 3, morphology_backend_provider: BackendProviderInput = CellProfilerBackendProvider.NATIVE, diff --git a/openhcs/processing/backends/cellprofiler/object_images.py b/openhcs/processing/backends/cellprofiler/object_images.py index 2ec98235ff..81912cc368 100644 --- a/openhcs/processing/backends/cellprofiler/object_images.py +++ b/openhcs/processing/backends/cellprofiler/object_images.py @@ -10,6 +10,7 @@ from metaclass_registry import AutoRegisterMeta import numpy as np +from openhcs.core.runtime_array_values import RuntimeArrayData from openhcs.core.artifacts import ImageArtifactType, ObjectLabelsArtifactType from openhcs.core.memory import numpy as numpy_decorator from openhcs.core.measurement_row_materialization import ( @@ -181,7 +182,7 @@ def object_label_colormap(colormap_name: str, num_labels: int) -> np.ndarray: @numpy_decorator(contract=ProcessingContract.PURE_2D) def convert_image_to_objects( - image: np.ndarray, + image: RuntimeArrayData, cast_to_bool: bool = False, preserve_label: bool = False, background: int = 0, diff --git a/openhcs/processing/backends/cellprofiler/outlines.py b/openhcs/processing/backends/cellprofiler/outlines.py index cdaeb5cefd..d0e4791fe7 100644 --- a/openhcs/processing/backends/cellprofiler/outlines.py +++ b/openhcs/processing/backends/cellprofiler/outlines.py @@ -878,7 +878,7 @@ def render_single_plane(self, image_sources: tuple[np.ndarray, ...]) -> np.ndarr @object_label_input_execution_mode(ObjectLabelInputExecutionMode.MATCH_IMAGE_STACK) @special_inputs("object_labels") def overlay_outlines( - image: np.ndarray, + image: RuntimeArrayData, *, blank_image: bool = False, display_mode: OutlineDisplayMode = OutlineDisplayMode.COLOR, @@ -922,7 +922,7 @@ def overlay_outlines( @object_label_input_execution_mode(ObjectLabelInputExecutionMode.MATCH_IMAGE_STACK) @special_inputs("labels") def overlay_objects( - image: np.ndarray, + image: RuntimeArrayData, labels: ObjectLabelValue, opacity: float = 0.3, max_label: int | None = None, @@ -1000,7 +1000,7 @@ def overlay_objects( def _overlay_objects_array( - image: np.ndarray, + image: RuntimeArrayData, labels: np.ndarray, *, opacity: float, @@ -1181,7 +1181,7 @@ def _draw_object_labels( def _draw_outline_image( output: np.ndarray, - outline_image: np.ndarray, + outline_image: RuntimeArrayData, color: tuple[float, float, float], *, outline_intensity: float, @@ -1200,7 +1200,7 @@ def _draw_outline_image( return output -def _outline_image_mask(outline_image: np.ndarray) -> np.ndarray: +def _outline_image_mask(outline_image: RuntimeArrayData) -> np.ndarray: mask = np.asarray(image_payload_data(outline_image)) > 0 channel_axis = image_payload_metadata(outline_image).normalized_source_channel_axis( outline_image diff --git a/openhcs/processing/backends/cellprofiler/primary_objects.py b/openhcs/processing/backends/cellprofiler/primary_objects.py index 70c083129a..897f377167 100644 --- a/openhcs/processing/backends/cellprofiler/primary_objects.py +++ b/openhcs/processing/backends/cellprofiler/primary_objects.py @@ -11,6 +11,7 @@ from enum import Enum from openhcs.core.memory import numpy from openhcs.core.public_api import public_names_from_objects +from openhcs.core.runtime_array_values import RuntimeArrayData from openhcs.core.runtime_image_values import ( ImagePayloadMetadata, image_payload_data, @@ -89,6 +90,7 @@ from openhcs.processing.backends.cellprofiler.enum_attributes import ( CellProfilerEnumAttributeMixin, ) +from openhcs.core.callable_contract import CallableContract from openhcs.core.artifacts import ( ArtifactSpecCollection, ImageArtifactType, @@ -123,7 +125,7 @@ class ExcessObjectHandling(CellProfilerEnumAttributeMixin, Enum): @numpy(contract=ProcessingContract.PURE_2D) def identify_primary_objects( - image: np.ndarray, + image: RuntimeArrayData, min_diameter: int = 10, max_diameter: int = 40, exclude_size: bool = True, @@ -645,7 +647,10 @@ def finalize_artifact_contract_outputs( artifact_outputs=artifact_outputs, ) source = cls.primary_image_inputs( - cls.require_callable(invocation_key.function_name), artifact_inputs.specs + CallableContract.from_prepared_callable( + cls.require_callable(invocation_key.function_name) + ), + artifact_inputs.specs, ) if len(source) != 1: raise ValueError("IdentifyPrimaryObjects diagnostics require one source image.") diff --git a/openhcs/processing/backends/cellprofiler/relationships.py b/openhcs/processing/backends/cellprofiler/relationships.py index 49e33db5e4..29d74b37ea 100644 --- a/openhcs/processing/backends/cellprofiler/relationships.py +++ b/openhcs/processing/backends/cellprofiler/relationships.py @@ -33,8 +33,8 @@ ) from openhcs.core.runtime_relationships import ObjectRelationshipDeclaration from openhcs.core.runtime_identifier import normalize_runtime_identifier +from openhcs.core.runtime_image_values import image_payload_metadata from openhcs.core.runtime_measurements import ( - MeasurementScalarLiteral, MeasurementStatistic, RuntimeMeasurementFeatureDeclaration, RuntimeMeasurementFeatureSemanticMarker, @@ -202,12 +202,6 @@ def aggregates_child_measurement_feature(cls, feature_name: str) -> bool: RelateObjectsChildMeanFeatureMarker, ) - @staticmethod - def aggregate_child_measurement_value_is_qualified(value: object) -> bool: - """Retain explicit missing values so child means propagate them.""" - - return not MeasurementScalarLiteral(value).is_absent - class DistanceMeasurementFeature(FormattingMeasurementFeatureTemplate): """Parent-qualified distance features emitted by RelateObjects.""" @@ -749,10 +743,10 @@ def feature_name(cls, identity: object) -> str: from openhcs.constants.constants import MemoryType from openhcs.core.memory.decorators import numpy as numpy_decorator from openhcs.core.measurement_feature_queries import ( + ColumnarMeasurementTableSchema, MeasurementAxisValueProjection, MeasurementFeatureQuery, MeasurementFeatureValueIndex, - MeasurementTableObjectFeatureSemantics, ) from openhcs.core.measurement_row_materialization import ( ConcatenatedColumnarRows, @@ -766,7 +760,6 @@ def feature_name(cls, identity: object) -> str: RuntimeOutputBundle, ) from openhcs.core.source_plane_alignment import ( - SourcePayloadPlaneIdentitySequence, SourcePlaneIdentitySequenceAlignment, ) from openhcs.core.runtime_slice_alignment import RuntimeSliceAlignedValues @@ -833,9 +826,6 @@ def aggregate_child_feature_name( return feature.unqualified_feature_name -from openhcs.interop.cellprofiler.runtime.object_measurement_tables import ( - ObjectMeasurementTableIndex, -) from openhcs.processing.backends.cellprofiler._backend import ( BackendProviderInput, DEFAULT_CELLPROFILER_BACKEND_SELECTION, @@ -864,6 +854,7 @@ def aggregate_child_feature_name( ) from openhcs.core.runtime_tabular_values import ColumnarRows from openhcs.core.runtime_object_labels import ( + dense_label_centers_2d_numba, ObjectLabelValue, object_label_value_with_dense_labels, ) @@ -1476,8 +1467,8 @@ def parent_mean_upstream_measurement_rows( payload: ObjectRelationship, ) -> MeasurementSparseColumnarRows: """Return CellProfiler per-parent means over prior child measurements.""" - values_by_child = self.upstream_child_measurement_values(child_spec) - if not values_by_child: + indexes_by_slice = self.upstream_child_feature_indexes(child_spec) + if not indexes_by_slice: return MeasurementSparseColumnarRows.from_rows((), fields=()) sliced_pairs = payload.payload.runtime_slice_pairs() relationship_slices = ( @@ -1505,55 +1496,55 @@ def parent_mean_upstream_measurement_rows( fields.append(FieldSpec(MeasurementRowAxisField.SLICE_INDEX.value, int)) for slice_index, pairs in relationship_slices: value_slice_index = 0 if slice_index is None else slice_index - feature_values_by_parent: dict[int, dict[str, list[float]]] = {} + children_by_parent: dict[int, list[int]] = {} for parent_id, child_id in pairs: - if int(parent_id) <= 0: - continue - child_values = values_by_child.get( - (value_slice_index, int(child_id)), - {}, - ) - if not child_values: - continue - parent_feature_values = feature_values_by_parent.setdefault( - int(parent_id), - {}, - ) - for feature_name, value in child_values.items(): - parent_feature_values.setdefault(feature_name, []).append(value) - for parent_id, feature_values in sorted(feature_values_by_parent.items()): - means = { - RelateObjectsModule.AggregateMeasurementFeature.MEAN_CHILD.feature_name( - child_object_name=child_spec.name, - child_feature_name=feature_name, - ): float( - np.mean(values) + if int(parent_id) > 0: + children_by_parent.setdefault(int(parent_id), []).append( + int(child_id) ) - for feature_name, values in sorted(feature_values.items()) - if values - } - if means: - rows.append( - { - MeasurementRowAxisField.OBJECT_NAME.value: parent_spec.name, - MeasurementRowAxisField.OBJECT_LABEL.value: parent_id, - **( - {} - if slice_index is None - else { - MeasurementRowAxisField.SLICE_INDEX.value: slice_index - } - ), - **means, - } + means_by_parent: dict[int, dict[str, float]] = {} + for feature_name, feature_index in sorted( + indexes_by_slice.get(value_slice_index, {}).items() + ): + values_by_label = feature_index.values_by_label + mean_feature = RelateObjectsModule.AggregateMeasurementFeature.MEAN_CHILD.feature_name( + child_object_name=child_spec.name, + child_feature_name=feature_name, + ) + for parent_id, child_ids in children_by_parent.items(): + values = np.fromiter( + ( + values_by_label[child_id] + for child_id in child_ids + if child_id in values_by_label + ), + dtype=float, ) - fields.extend( - RelateObjectsModule.AggregateMeasurementFeature.MEAN_CHILD.field_spec( - feature_name, - required=False, + if values.size: + means_by_parent.setdefault(parent_id, {})[mean_feature] = float( + np.mean(values) ) - for feature_name in means + for parent_id, means in sorted(means_by_parent.items()): + rows.append( + { + MeasurementRowAxisField.OBJECT_NAME.value: parent_spec.name, + MeasurementRowAxisField.OBJECT_LABEL.value: parent_id, + **( + {} + if slice_index is None + else { + MeasurementRowAxisField.SLICE_INDEX.value: slice_index + } + ), + **means, + } + ) + fields.extend( + RelateObjectsModule.AggregateMeasurementFeature.MEAN_CHILD.field_spec( + feature_name, required=False ) + for feature_name in means + ) return MeasurementSparseColumnarRows.from_rows( rows, fields=FieldSpec.merge_exact( @@ -1562,11 +1553,11 @@ def parent_mean_upstream_measurement_rows( ), ) - def upstream_child_measurement_values( + def upstream_child_feature_indexes( self, child_spec: ArtifactSpec, - ) -> dict[tuple[int, int], dict[str, float]]: - """Index upstream child values on the relationship's declared plane axis.""" + ) -> dict[int, dict[str, MeasurementFeatureValueIndex]]: + """Index upstream features once on the relationship's declared plane axis.""" declared_tables: list[MeasurementTable] = [] for spec in self.request.callable_contract.artifact_inputs.specs: if spec.artifact_type is not MeasurementsArtifactType: @@ -1575,27 +1566,22 @@ def upstream_child_measurement_values( spec.name, MeasurementsArtifactType, ): - table = record.value.data + table = record.data if not isinstance(table, MeasurementTable): raise TypeError( f"Declared measurement input {spec.name!r} carries " f"{type(table).__name__}, not MeasurementTable." ) declared_tables.append(table) - tables = ObjectMeasurementTableIndex.from_tables( - tuple(declared_tables) - ).for_object(child_spec.name) - if tables is None: - raise RuntimeError( - "A complete object-measurement table index returned an unknown " - "selection." - ) + tables = ColumnarMeasurementTableSchema.tables_for_object( + tuple(declared_tables), child_spec.name + ) child_labels = self.unprojected_object_labels(child_spec) core_rows = ObjectLocationMeasurementRows( child_labels, child_spec.name, ) - values_by_child: dict[tuple[int, int], dict[str, float]] = {} + indexes_by_slice: dict[int, dict[str, MeasurementFeatureValueIndex]] = {} for raw_row in core_rows.rows().iter_row_mappings(): row = measurement_row_mapping(raw_row) slice_index = measurement_axis_integer_value( @@ -1608,9 +1594,13 @@ def upstream_child_measurement_values( "CellProfiler core object rows require slice and object-label " "identity." ) - values_by_child.setdefault((slice_index, object_label), {})[ - str(row[MeasurementRowAxisField.FEATURE_NAME.value]) - ] = float(row[MeasurementRowValueField.RESULT_VALUE.value]) + feature_name = str(row[MeasurementRowAxisField.FEATURE_NAME.value]) + indexes = indexes_by_slice.setdefault(slice_index, {}) + if feature_name not in indexes: + indexes[feature_name] = MeasurementFeatureValueIndex() + indexes[feature_name].add( + object_label, row[MeasurementRowValueField.RESULT_VALUE.value] + ) plane_domains = core_rows.label_plane_domains() payload_scoped = ( @@ -1622,20 +1612,21 @@ def upstream_child_measurement_values( slice_index=None if payload_scoped else slice_index, slice_count=None if payload_scoped else len(plane_domains), ) + indexes = indexes_by_slice.setdefault(slice_index, {}) + feature_name = CellProfilerObjectCoreMeasurementFeature.OBJECT_NUMBER.value + if feature_name not in indexes: + indexes[feature_name] = MeasurementFeatureValueIndex() for object_label, object_number in object_numbers.items(): - values_by_child.setdefault((slice_index, object_label), {})[ - CellProfilerObjectCoreMeasurementFeature.OBJECT_NUMBER.value - ] = float(object_number) + indexes[feature_name].add(object_label, object_number) if not tables: - return values_by_child + return indexes_by_slice identity_policy = ( self.request.adapter.request.context.source_image_set_identity_policy ) - child_axis = SourcePayloadPlaneIdentitySequence( - child_labels, - identity_policy, - ).runtime_axis_identities() + child_axis = image_payload_metadata( + child_labels + ).source_provenance.image_set_axis(identity_policy) if not child_axis: raise ValueError( f"RelateObjects child measurements for {child_spec.name!r} require " @@ -1644,7 +1635,7 @@ def upstream_child_measurement_values( row_axis = MeasurementRowAxisField.SLICE_INDEX for table in tables: - semantics = MeasurementTableObjectFeatureSemantics.from_table(table) + semantics = ColumnarMeasurementTableSchema.from_table(table) table_axis = table.source_provenance.image_set_axis(identity_policy) if not table_axis: raise ValueError( @@ -1663,7 +1654,7 @@ def upstream_child_measurement_values( aggregate_features = tuple( sorted( feature_name - for feature_name in semantics.feature_names + for feature_name in semantics.feature_names(table) if RelateObjectsModule.aggregates_child_measurement_feature( feature_name ) @@ -1721,40 +1712,52 @@ def upstream_child_measurement_values( table_dialect = cellprofiler_lookup_dialect_for_measurement_owner( table.measurement_feature_owner ) - queries = tuple( - ( + queries = { + feature_name: MeasurementFeatureQuery( feature_name, - MeasurementFeatureQuery( - feature_name, - object_name=child_spec.name, - dialect=table_dialect, - ), + object_name=child_spec.name, + dialect=table_dialect, ) for feature_name in aggregate_features - ) - for _local_slice_index, target_slice_index, row_mask in slice_projections: - for feature_name, query in queries: - feature_indexes = MeasurementFeatureValueIndex.from_columnar_table_by_object( - table, - query, - {child_spec.name: query.query_object_name}, - row_mask=row_mask, - measurement_value_qualifier=( - RelateObjectsModule.aggregate_child_measurement_value_is_qualified - ), - ) + } + target_slices = { + local_slice_index: target_slice_index + for local_slice_index, target_slice_index, _row_mask in slice_projections + } + for ( + feature_name, + indexes_by_local_slice, + ) in ColumnarMeasurementTableSchema.from_table( + table + ).non_absent_feature_value_indexes( + table, + queries, + { + feature_name: {child_spec.name: query.query_object_name} + for feature_name, query in queries.items() + }, + index_type=MeasurementFeatureValueIndex, + row_masks={ + local_slice_index: row_mask + for local_slice_index, _target_slice_index, row_mask in slice_projections + }, + ): + for ( + local_slice_index, + feature_indexes, + ) in indexes_by_local_slice.items(): feature_index = feature_indexes.get(child_spec.name) if feature_index is None: continue + target_slice_index = target_slices[local_slice_index] + target_index = indexes_by_slice.setdefault( + target_slice_index, {} + ).setdefault(feature_name, MeasurementFeatureValueIndex()) for ( object_label, numeric_value, ) in feature_index.values_by_label.items(): - child_values = values_by_child.setdefault( - (target_slice_index, object_label), - {}, - ) - previous = child_values.get(feature_name) + previous = target_index.values_by_label.get(object_label) if previous is not None and not ( previous == numeric_value or (np.isnan(previous) and np.isnan(numeric_value)) @@ -1765,8 +1768,8 @@ def upstream_child_measurement_values( f"{target_slice_index}, object {object_label}: " f"{previous!r} != {numeric_value!r}." ) - child_values[feature_name] = numeric_value - return values_by_child + target_index.values_by_label[object_label] = numeric_value + return indexes_by_slice class NumbaNumpyObjectRelationshipBackendStrategy(ObjectRelationshipBackendStrategy): @@ -1853,7 +1856,9 @@ def label_centers(self, labels: np.ndarray) -> np.ndarray: label_count = int(labels.max()) if label_count == 0: return np.empty((0, 2), dtype=np.float64) - centroids = _label_centroids_numba(np.ascontiguousarray(labels), label_count) + centroids = dense_label_centers_2d_numba( + np.ascontiguousarray(labels), label_count + ) return centroids[1:] @@ -2192,29 +2197,6 @@ def _parents_of_from_overlap_counts_numba( return parents_of -@njit(cache=True) -def _label_centroids_numba(labels: np.ndarray, label_count: int) -> np.ndarray: - sums = np.zeros((label_count + 1, 2), dtype=np.float64) - counts = np.zeros(label_count + 1, dtype=np.int64) - height, width = labels.shape - for row in range(height): - for col in range(width): - label_id = int(labels[row, col]) - if label_id > 0 and label_id <= label_count: - sums[label_id, 0] += row - sums[label_id, 1] += col - counts[label_id] += 1 - centroids = np.empty((label_count + 1, 2), dtype=np.float64) - for label_id in range(label_count + 1): - if counts[label_id] == 0: - centroids[label_id, 0] = np.nan - centroids[label_id, 1] = np.nan - else: - centroids[label_id, 0] = sums[label_id, 0] / counts[label_id] - centroids[label_id, 1] = sums[label_id, 1] / counts[label_id] - return centroids - - @njit(cache=True) def _calculate_centroid_distances_numba( parent_labels: np.ndarray, @@ -2228,8 +2210,8 @@ def _calculate_centroid_distances_numba( distances[child_idx] = np.nan if child_count == 0 or parent_count == 0: return distances - parent_centroids = _label_centroids_numba(parent_labels, parent_count) - child_centroids = _label_centroids_numba(child_labels, child_count) + parent_centroids = dense_label_centers_2d_numba(parent_labels, parent_count) + child_centroids = dense_label_centers_2d_numba(child_labels, child_count) for child_idx in range(child_count): parent_id = int(parents_of[child_idx]) child_id = child_idx + 1 @@ -2281,7 +2263,7 @@ def _calculate_minimum_distances_numba( distances[child_idx] = np.nan if child_count == 0 or parent_count == 0: return distances - child_centroids = _label_centroids_numba(child_labels, child_count) + child_centroids = dense_label_centers_2d_numba(child_labels, child_count) height, width = parent_labels.shape counts = np.zeros(parent_count + 1, dtype=np.int64) for row in range(height): diff --git a/openhcs/processing/backends/cellprofiler/secondary.py b/openhcs/processing/backends/cellprofiler/secondary.py index 973a360374..d31dbc0f8c 100644 --- a/openhcs/processing/backends/cellprofiler/secondary.py +++ b/openhcs/processing/backends/cellprofiler/secondary.py @@ -38,6 +38,7 @@ EnumKeyedStrategyMixin, RegisteredLeafClassSpec, ) +from openhcs.core.runtime_array_values import RuntimeArrayData from openhcs.core.runtime_image_values import ( image_payload_data, image_payload_mask, @@ -1147,7 +1148,7 @@ def _replacement_primary_output_from_relationship( def _execute_identify_secondary_objects( - image: np.ndarray, + image: RuntimeArrayData, primary_labels: ObjectLabelValue, method: SecondaryMethod = SecondaryMethod.PROPAGATION, threshold_scope: CellProfilerThresholdScope = CellProfilerThresholdScope.GLOBAL, @@ -1337,7 +1338,7 @@ def _execute_identify_secondary_objects( @numpy(contract=ProcessingContract.PURE_2D) @special_inputs("primary_labels") def identify_secondary_objects( - image: np.ndarray, + image: RuntimeArrayData, primary_labels: ObjectLabelValue, method: SecondaryMethod = SecondaryMethod.PROPAGATION, threshold_scope: CellProfilerThresholdScope = CellProfilerThresholdScope.GLOBAL, @@ -1407,7 +1408,7 @@ def identify_secondary_objects( @numpy(contract=ProcessingContract.PURE_2D) @special_inputs("primary_labels") def identify_secondary_objects_with_replacement_primary( - image: np.ndarray, + image: RuntimeArrayData, primary_labels: ObjectLabelValue, method: SecondaryMethod = SecondaryMethod.PROPAGATION, threshold_scope: CellProfilerThresholdScope = CellProfilerThresholdScope.GLOBAL, diff --git a/openhcs/processing/backends/cellprofiler/skeleton.py b/openhcs/processing/backends/cellprofiler/skeleton.py index 947ca74c01..ba8c710ced 100644 --- a/openhcs/processing/backends/cellprofiler/skeleton.py +++ b/openhcs/processing/backends/cellprofiler/skeleton.py @@ -359,7 +359,7 @@ def measure_object_skeleton( @numpy_backend(contract=ProcessingContract.PURE_2D) @special_inputs("seed_labels") def measure_object_skeleton_with_branchpoint_image( - image: np.ndarray, + image: RuntimeArrayData, seed_labels: SeedObjectLabelsInput, fill_small_holes: bool = True, maximum_hole_size: int = 10, diff --git a/openhcs/processing/backends/cellprofiler/smoothing.py b/openhcs/processing/backends/cellprofiler/smoothing.py index 0b803b2294..6ac97257a9 100644 --- a/openhcs/processing/backends/cellprofiler/smoothing.py +++ b/openhcs/processing/backends/cellprofiler/smoothing.py @@ -5,6 +5,7 @@ from typing import Any from openhcs.core.aligned_image_payload import ImagePayloadExecutionMode from openhcs.core.callable_contract import runtime_image_execution_mode +from openhcs.core.runtime_array_values import RuntimeArrayData from openhcs.core.runtime_image_values import ( image_payload_data, with_image_payload_data, @@ -790,7 +791,7 @@ def _fit_polynomial( def smooth_image( - image: np.ndarray, + image: RuntimeArrayData, smoothing_method: SmoothingMethod = SmoothingMethod.GAUSSIAN_FILTER, auto_object_size: bool = True, object_size: float = 16.0, @@ -839,7 +840,7 @@ def smooth_image( @numpy_decorator(contract=ProcessingContract.PURE_2D) def smooth( - image: np.ndarray, + image: RuntimeArrayData, smoothing_method: SmoothingMethod = SmoothingMethod.GAUSSIAN_FILTER, auto_object_size: bool = True, object_size: float = 16.0, @@ -862,7 +863,7 @@ def smooth( @runtime_image_execution_mode(ImagePayloadExecutionMode.FULL_STACK) @numpy_decorator(contract=ProcessingContract.FLEXIBLE) def reducenoise( - image: np.ndarray, + image: RuntimeArrayData, patch_size: int = 5, patch_distance: int = 6, cutoff_distance: float = 0.1, diff --git a/openhcs/processing/backends/cellprofiler/spreadsheet_export.py b/openhcs/processing/backends/cellprofiler/spreadsheet_export.py index 3682699839..f1463de65b 100644 --- a/openhcs/processing/backends/cellprofiler/spreadsheet_export.py +++ b/openhcs/processing/backends/cellprofiler/spreadsheet_export.py @@ -35,7 +35,6 @@ execution_scope, runtime_bound_parameters, ) -from openhcs.core.runtime_artifact_queries import MeasurementTableUnion from openhcs.core.runtime_tabular_values import ( FieldSpec, ) @@ -58,7 +57,7 @@ source_component_metadata_consensus, ) from openhcs.core.source_metadata import ( - SourceMetadataRoleView, + SourceMetadataFields, ) from openhcs.interop.cellprofiler.image_set_numbering import ( CellProfilerImageSetNumbering, @@ -72,7 +71,6 @@ from openhcs.interop.cellprofiler.module_declarations import CellProfilerModule from openhcs.interop.cellprofiler.measurement_dialect import ( CELLPROFILER_MEASUREMENT_DIALECT, - cellprofiler_projected_measurement_feature_name, ) from openhcs.interop.cellprofiler.parser import ModuleBlock from openhcs.interop.cellprofiler.setting_names import ( @@ -468,13 +466,13 @@ def _measurement_tables( for axis_records in records_by_axis.values() for record in axis_records ) - tables = tuple(cast(MeasurementTable, record.value.data) for record in records) + tables = tuple(cast(MeasurementTable, record.data) for record in records) all_tables.extend(tables) slice_axis = MeasurementRowAxisField.SLICE_INDEX row_domains = tuple( MeasurementRowsAxisProjection.from_rows(table.rows) for table in tables ) - MeasurementTableUnion(spec.name, tables).row_axis_domain(slice_axis) + MeasurementTable.shared_row_axis_domain(spec.name, tables, slice_axis) for record, table, row_domain in zip( records, tables, @@ -487,12 +485,12 @@ def _measurement_tables( slice_indices=row_domain.present_axis_values(slice_axis.value), owner=table.name, ) - accumulator.add( + accumulator.add_declared_rows( image_numbers.project_measurement_rows( scope=record.key.scope, table=table, ), - cellprofiler_projected_measurement_feature_name, + CELLPROFILER_MEASUREMENT_DIALECT, default_subject=_measurement_subject_name(table), default_scope=table.subject.scope, source_image_name=table.source_image_name, @@ -511,9 +509,9 @@ def _measurement_tables( [], ).append(metadata) for table in CellProfilerModule.derive_experiment_measurement_tables(all_tables): - accumulator.add( + accumulator.add_declared_rows( table.rows, - cellprofiler_projected_measurement_feature_name, + CELLPROFILER_MEASUREMENT_DIALECT, default_subject=_measurement_subject_name(table), default_scope=table.subject.scope, source_image_name=table.source_image_name, @@ -543,7 +541,7 @@ def _measurement_tables( if field_name != MeasurementRowAxisField.SLICE_INDEX.value ) ) - accumulator.add( + accumulator.add_declared_rows( MeasurementSparseColumnarRows.from_rows( source_metadata_rows, fields=( @@ -554,7 +552,7 @@ def _measurement_tables( ), ), ), - cellprofiler_projected_measurement_feature_name, + CELLPROFILER_MEASUREMENT_DIALECT, default_subject="Image", default_scope=MeasurementScope.IMAGE, ) @@ -583,8 +581,7 @@ def _source_metadata_measurement_rows( ).source_component_metadata if metadata is None: continue - role_view = SourceMetadataRoleView(metadata) - original_metadata = dict(role_view.original_items()) + original_metadata = dict(SourceMetadataFields.original_items(metadata)) if original_metadata: rows.append((image_numbers_by_slice[slice_index], original_metadata)) return tuple(rows) @@ -599,7 +596,7 @@ def _relationship_rows( artifact_batch, RelationshipsArtifactType, ): - relationship = cast(ObjectRelationship, record.value.data) + relationship = cast(ObjectRelationship, record.data) image_numbers_by_slice = image_numbers.for_source_slices( scope=record.key.scope, provenance=relationship.source_provenance, diff --git a/openhcs/processing/backends/cellprofiler/thresholding.py b/openhcs/processing/backends/cellprofiler/thresholding.py index eeac9dd3fb..7cd50a34d1 100644 --- a/openhcs/processing/backends/cellprofiler/thresholding.py +++ b/openhcs/processing/backends/cellprofiler/thresholding.py @@ -45,6 +45,7 @@ from openhcs.core.pipeline.function_contracts import runtime_bound_parameters from openhcs.core.public_api import public_names_from_objects from openhcs.core.registry_strategies import EnumKeyedStrategyMixin +from openhcs.core.runtime_array_values import RuntimeArrayData from openhcs.core.runtime_image_values import ( ImagePayloadMetadata, image_intensity_scale_for_dtype, @@ -549,7 +550,7 @@ class GlobalThresholdSourceSelection: method_parameters: GlobalThresholdMethodParameters -def normalize_cellprofiler_image(image: np.ndarray) -> np.ndarray: +def normalize_cellprofiler_image(image: RuntimeArrayData) -> np.ndarray: """Return an image in CellProfiler's normalized pixel-data convention.""" return image_payload_data( normalize_cellprofiler_image_payload( @@ -2578,7 +2579,7 @@ class _ThresholdEmbeddedMaskRuntimeParameter(KeywordRuntimeParameter): @runtime_image_execution_mode(ImagePayloadExecutionMode.FULL_STACK) @numpy(contract=ProcessingContract.PURE_2D) def threshold( - image: np.ndarray, + image: RuntimeArrayData, mask: np.ndarray | None = None, threshold_scope: ThresholdScope = ThresholdScope.GLOBAL, threshold_method: ThresholdMethod = ThresholdMethod.OTSU, diff --git a/openhcs/processing/backends/cellprofiler/tracking.py b/openhcs/processing/backends/cellprofiler/tracking.py index 3a36e51e4e..e591ba0d42 100644 --- a/openhcs/processing/backends/cellprofiler/tracking.py +++ b/openhcs/processing/backends/cellprofiler/tracking.py @@ -39,6 +39,7 @@ from openhcs.core.registry_strategies import EnumKeyedStrategyMixin from openhcs.core.runtime_object_labels import ( ObjectLabelValue, + dense_label_centers_2d_numba, object_label_dense_array, ) from openhcs.core.runtime_relationships import ObjectRelationshipDeclaration @@ -830,7 +831,7 @@ def label_centers(self, labels: np.ndarray) -> tuple[np.ndarray, np.ndarray]: label_count = int(labels_array.max()) if labels_array.size else 0 if label_count == 0: return (np.array([], dtype=np.float64), np.array([], dtype=np.float64)) - centers = _label_centers_numba(np.ascontiguousarray(labels_array), label_count) + centers = dense_label_centers_2d_numba(np.ascontiguousarray(labels_array), label_count) return (centers[1:, 0], centers[1:, 1]) def track_by_overlap( @@ -1461,29 +1462,6 @@ def _apply_final_age_measurements(frame_results: TrackingFrameResults) -> None: final_age_records[slice_index, object_label].final_age = int(lifetime) -@njit(cache=True) -def _label_centers_numba(labels: np.ndarray, label_count: int) -> np.ndarray: - sums = np.zeros((label_count + 1, 2), dtype=np.float64) - counts = np.zeros(label_count + 1, dtype=np.int64) - height, width = labels.shape - for y in range(height): - for x in range(width): - label_id = int(labels[y, x]) - if label_id > 0 and label_id <= label_count: - sums[label_id, 0] += y - sums[label_id, 1] += x - counts[label_id] += 1 - centers = np.empty((label_count + 1, 2), dtype=np.float64) - for label_id in range(label_count + 1): - if counts[label_id] == 0: - centers[label_id, 0] = np.nan - centers[label_id, 1] = np.nan - else: - centers[label_id, 0] = sums[label_id, 0] / counts[label_id] - centers[label_id, 1] = sums[label_id, 1] / counts[label_id] - return centers - - @njit(cache=True) def _track_by_overlap_numba( frame: TrackingKernelFrame, @@ -1528,8 +1506,8 @@ def _track_by_overlap_numba( def _track_by_distance_numba( frame: TrackingKernelFrame, pixel_radius: int ) -> tuple[np.ndarray, np.ndarray, np.ndarray, int]: - current_centers = _label_centers_numba(frame.current_labels, frame.current_count) - old_centers = _label_centers_numba(frame.old_labels, frame.old_count) + current_centers = dense_label_centers_2d_numba(frame.current_labels, frame.current_count) + old_centers = dense_label_centers_2d_numba(frame.old_labels, frame.old_count) new_labels = np.zeros(frame.current_count, dtype=np.int64) parent_object_numbers = np.zeros(frame.current_count, dtype=np.int64) parent_image_numbers = np.zeros(frame.current_count, dtype=np.int64) diff --git a/openhcs/processing/backends/cellprofiler/worms.py b/openhcs/processing/backends/cellprofiler/worms.py index 240070daef..1f0964c1a6 100644 --- a/openhcs/processing/backends/cellprofiler/worms.py +++ b/openhcs/processing/backends/cellprofiler/worms.py @@ -1709,7 +1709,7 @@ def canonical_image_output( def _execute_untangle_worms( - image: np.ndarray, + image: RuntimeArrayData, min_worm_area: float = 100.0, max_worm_area: float = 5000.0, num_control_points: int = 21, @@ -1868,7 +1868,7 @@ def _execute_untangle_worms( def _untangle_worms_output( - image: np.ndarray, + image: RuntimeArrayData, *, expected_style: OverlapStyle, overlap_style: OverlapStyle, @@ -1940,7 +1940,7 @@ def _untangle_worms_output( @numpy(contract=ProcessingContract.PURE_2D) def untangle_worms( - image: np.ndarray, + image: RuntimeArrayData, overlap_style: OverlapStyle = OverlapStyle.WITHOUT_OVERLAP, min_worm_area: float = 100.0, max_worm_area: float = 5000.0, @@ -1993,7 +1993,7 @@ def untangle_worms( @numpy(contract=ProcessingContract.PURE_2D) def untangle_worms_with_overlap( - image: np.ndarray, + image: RuntimeArrayData, overlap_style: OverlapStyle = OverlapStyle.WITH_OVERLAP, min_worm_area: float = 100.0, max_worm_area: float = 5000.0, @@ -2046,7 +2046,7 @@ def untangle_worms_with_overlap( @numpy(contract=ProcessingContract.PURE_2D) def untangle_worms_both( - image: np.ndarray, + image: RuntimeArrayData, overlap_style: OverlapStyle = OverlapStyle.BOTH, min_worm_area: float = 100.0, max_worm_area: float = 5000.0, @@ -2112,7 +2112,7 @@ def untangle_worms_both( @special_inputs("worm_labels") @runtime_bound_parameters(_StraightenWormControlPointsRuntimeParameter) def straighten_worms( - image: np.ndarray, + image: RuntimeArrayData, worm_labels: ObjectLabelValue, control_points: np.ndarray | None = None, worm_width: int = 20, @@ -2226,7 +2226,7 @@ def straighten_worms( @numpy(contract=ProcessingContract.PURE_2D) def identify_dead_worms( - image: np.ndarray, + image: RuntimeArrayData, worm_width: int = 10, worm_length: int = 100, angle_count: int = 32, diff --git a/openhcs/processing/backends/lib_registry/registry_service.py b/openhcs/processing/backends/lib_registry/registry_service.py index 453e1f734a..dd327c12a5 100644 --- a/openhcs/processing/backends/lib_registry/registry_service.py +++ b/openhcs/processing/backends/lib_registry/registry_service.py @@ -148,11 +148,11 @@ def prepare_in_current_process( cls._metadata_cache = cls._metadata_from_instances( cls._available_registry_instances() ) - callables = tuple( + callables = tuple(dict.fromkeys( target for metadata in cls._metadata_cache.values() for target in CallableProjection.from_callable(metadata.func).prepare_targets() - ) + )) emit_status("Preparing registered kernel caches") PreparationCacheBatch.from_callables(callables).populate_child_caches( max_workers=os.cpu_count() or 1, @@ -164,6 +164,9 @@ def prepare_in_current_process( emit_status( f"Prepared callable {preparation.projection.module_name}.{preparation.projection.name}" ) + emit_status("Resolving prepared callable signatures") + for func in callables: + CallableProjection.from_callable(func).warm_canonical_signature() emit_status("Preparing registered configuration source declarations") for declaration in dict.fromkeys( declaration diff --git a/openhcs/processing/backends/lib_registry/unified_registry.py b/openhcs/processing/backends/lib_registry/unified_registry.py index 4e60c05d3d..a30e9af840 100644 --- a/openhcs/processing/backends/lib_registry/unified_registry.py +++ b/openhcs/processing/backends/lib_registry/unified_registry.py @@ -75,7 +75,6 @@ from openhcs.core.runtime_array_values import RuntimeArrayPayload, is_array_payload from openhcs.core.runtime_batch_contracts import ( Pure2DSliceBatchExecutor, - RuntimeBatchExecutionDomain, RuntimePure2DSliceBatchRequest, runtime_batch_executors_from_callable, ) @@ -207,6 +206,7 @@ def accepted_kwargs( self, func: Callable[..., Any], kwargs: Mapping[str, Any], + *, signature: inspect.Signature | None = None, ) -> dict[str, Any]: """Return kwargs accepted by ``func`` under this policy.""" @@ -220,8 +220,9 @@ def accepted_kwargs( self, func: Callable[..., Any], kwargs: Mapping[str, Any], + *, signature: inspect.Signature | None = None, ) -> dict[str, Any]: - del func + del func, signature return dict(kwargs) @@ -234,8 +235,11 @@ def accepted_kwargs( self, func: Callable[..., Any], kwargs: Mapping[str, Any], + *, signature: inspect.Signature | None = None, ) -> dict[str, Any]: - parameters = _runtime_callable_parameters(func) + from openhcs.core.callable_contract import CallableMetadata + + parameters = (CallableMetadata.callable_signature(func) if signature is None else signature).parameters if any( parameter.kind is inspect.Parameter.VAR_KEYWORD for parameter in parameters.values() @@ -255,6 +259,7 @@ class RuntimeCallableInvocation: kwarg_policy: RuntimeInvocationKwargPolicy = ( RuntimeInvocationKwargPolicy.PASS_THROUGH ) + signature: inspect.Signature | None = None def call(self) -> Any: target = RuntimeCallableViewStrategy.for_view(self.callable_view).resolve( @@ -264,7 +269,7 @@ def call(self) -> Any: *self.args, **RuntimeInvocationKwargPolicyStrategy.for_policy( self.kwarg_policy - ).accepted_kwargs(target, self.kwargs), + ).accepted_kwargs(target, self.kwargs, signature=self.signature), ) @@ -277,11 +282,22 @@ class RuntimeCallablePolicy: RuntimeInvocationKwargPolicy.PASS_THROUGH ) + def contract_invocation( + self, contract: "CallableContract", func: Callable[..., Any], + image: Any, kwargs: Mapping[str, Any], + ) -> RuntimeCallableInvocation: + """Bind the prepared main-image carrier and actual raw execution ABI.""" + return self.invocation( + func, (contract.raw_main_flow_call_argument(image),), kwargs, + signature=contract.raw_runtime_signature, + ) + def invocation( self, func: Callable[..., Any], args: tuple[Any, ...], kwargs: Mapping[str, Any], + *, signature: inspect.Signature | None = None, ) -> RuntimeCallableInvocation: return RuntimeCallableInvocation( func=func, @@ -289,16 +305,10 @@ def invocation( kwargs=kwargs, callable_view=self.callable_view, kwarg_policy=self.kwarg_policy, + signature=signature, ) -@lru_cache(maxsize=256) -def _runtime_callable_parameters( - func: Callable[..., Any], -) -> Mapping[str, inspect.Parameter]: - return inspect.signature(func).parameters - - def _registry_runtime_parameter_exclusions( signature: inspect.Signature, parameter_names: tuple[str, ...], @@ -1012,7 +1022,7 @@ def main_flow_call_argument( self, callable_contract: "CallableContract", source_payload: Any, ) -> Any: """Expose the raw ABI when this contract needs no earlier plane slicing.""" - return callable_contract.raw_main_flow_call_argument(source_payload) + return callable_contract.runtime_main_flow_call_argument(source_payload) def injected_semantic_control_parameter_names(self) -> frozenset[str]: """Semantic controls that this contract may inject into public callables.""" @@ -1027,10 +1037,14 @@ def consume_semantic_controls( kwargs: MutableMapping[str, Any], *, func: Callable[..., Any] | None = None, + parameters: Mapping[str, inspect.Parameter] | None = None, ) -> dict[str, Any]: """Consume and return semantic selectors owned by this declaration.""" - parameters = {} if func is None else inspect.signature(func).parameters + if parameters is None: + from openhcs.core.callable_contract import CallableMetadata + + parameters = {} if func is None else CallableMetadata.callable_signature(func).parameters values: dict[str, Any] = {} for parameter_type in self.runtime_parameter_types(): if not parameter_type.is_semantic_control: @@ -1739,7 +1753,7 @@ def execute_pure_3d(self, func, image, *args, **kwargs): RuntimeCallablePolicy() .invocation( func, - (callable_contract.raw_main_flow_call_argument(image), *args), + (callable_contract.runtime_main_flow_call_argument(image), *args), kwargs, ) .call() @@ -1773,7 +1787,7 @@ def execute_pure_2d(self, func, image, *args, **kwargs): result = ( RuntimeCallablePolicy().invocation( func, - (callable_contract.raw_main_flow_call_argument(image), *args), + (callable_contract.runtime_main_flow_call_argument(image), *args), kwargs, ).call() ) @@ -1808,14 +1822,7 @@ def execute_pure_2d(self, func, image, *args, **kwargs): kwargs.setdefault(parameter.name, value) args = args[len(positional_parameters) :] slices = slicer.slice_value(image, input_memory_type) - declared_batch_executor = runtime_batch_executors_from_callable(func).get( - RuntimeBatchExecutionDomain.PURE_2D_SLICES - ) - batch_executor = ( - declared_batch_executor - if callable(declared_batch_executor) - else Pure2DSliceBatchExecutor.default_executor() - ) + batch_executor = Pure2DSliceBatchExecutor.from_executors(runtime_batch_executors_from_callable(func)) def execute_slice( slice_func: Callable[..., Any], @@ -1837,7 +1844,7 @@ def execute_slice( RuntimeCallablePolicy() .invocation( slice_func, - (callable_contract.raw_main_flow_call_argument(slice_2d), *args), + (callable_contract.runtime_main_flow_call_argument(slice_2d), *args), projected_kwargs, ) .call() diff --git a/openhcs/processing/materialization/__init__.py b/openhcs/processing/materialization/__init__.py index 4e920f0ee9..c161998f13 100644 --- a/openhcs/processing/materialization/__init__.py +++ b/openhcs/processing/materialization/__init__.py @@ -6,11 +6,14 @@ ) from openhcs.processing.materialization.core import ( BackendSaver, + MaterializationBatch, MaterializationContext, MaterializationSpec, Output, + SavedMaterializationOutputs, PathHelper, materialize, + prepare_materialization, materialization_outputs, registered_materialization_option_types, tabular_field_names_from_materialization, @@ -57,11 +60,14 @@ "MaterializationSpec", "TerminalMaterializationSpec", "StreamingOnlyMaterializationSpec", + "MaterializationBatch", "MaterializationContext", "Output", + "SavedMaterializationOutputs", "PathHelper", "BackendSaver", "materialize", + "prepare_materialization", "materialization_outputs", "registered_materialization_option_types", "FileOutputOptions", diff --git a/openhcs/processing/materialization/core.py b/openhcs/processing/materialization/core.py index 2bde639ae3..e282d23497 100644 --- a/openhcs/processing/materialization/core.py +++ b/openhcs/processing/materialization/core.py @@ -17,12 +17,13 @@ from dataclasses import dataclass, field, is_dataclass, replace from functools import lru_cache, singledispatch from pathlib import Path, PurePosixPath, PureWindowsPath +from types import MappingProxyType from typing import TYPE_CHECKING, ClassVar, TypeAlias import numpy as np import pandas as pd from metaclass_registry import AutoRegisterMeta -from polystore.config import TiffConfig, tiff_write_batches +from polystore.config import TiffConfig from polystore.streaming.viewer_transport import ( PathMappedViewerStreamSourceMetadata, ViewerStreamBackendKwargs, @@ -75,8 +76,7 @@ from openhcs.core.source_metadata import SourceVoxelSpacing from openhcs.core.source_spatial_domain import SourceSpatialDomain from openhcs.core.steps.function_output_identity import ( - FunctionOutputIdentityAuthority, - FunctionOutputPathAuthority, + FunctionOutputIdentity, ) from openhcs.core.steps.stream_component_semantics import ( StreamImagePayloadMetadataProjector, @@ -200,8 +200,18 @@ def filemanager_batches( **({"tiff_config": config} if config is not None else {}), }, ) - for indices, config in tiff_write_batches( - tuple(output.path for output in outputs), self.tiff_config + for indices, config in ImageFileFormat.storage_write_batches( + tuple( + ( + output.metadata.attach_to(output.content) + if output.metadata is not None + and ImageFileFormat.is_image_path(output.path) + else output.content + ) + for output in outputs + ), + tuple(output.path for output in outputs), + self.tiff_config, ) ) @@ -1306,6 +1316,47 @@ def from_runtime_slice_projected_value( ), ) + @classmethod + def from_image_value( + cls, + value: MaterializationValue, + options: SourceOptions, + ) -> "MaterializationInput": + """Preserve intrinsic images while projecting ordinary runtime planes.""" + unprojected = cls.from_value(value, options) + items = [] + for image in unprojected.items: + if image.metadata.persists_whole_image(): + items.append(image) + else: + items.extend( + MaterializationInputItem( + value=item.value, + source_description=item.source_description, + runtime_plane_metadata=item.runtime_plane_metadata, + ) + for item in ( + RuntimeProjectionSourceIdentityRequirement.OPTIONAL + ).project_payload_items( + RuntimeProjectionSourceIdentityRequest( + value=image.value, + source_description=image.source_description, + plane_projection=( + image.value.declared_plane_projection() + if isinstance(image.value, ObjectLabelValue) + else None + ), + ) + ) + ) + return replace( + unprojected, + items=tuple(items), + source_plane_projection=SourcePlaneProjectionContract.from_payloads( + tuple(item.value for item in unprojected.items) + ), + ) + @property def data(self) -> MaterializationValue: data_items = [item.data for item in self.items] @@ -1625,7 +1676,7 @@ def projected_outputs(self, outputs: Sequence[Output]) -> tuple[Output, ...]: continue output_path = Path(output.path) for item in items: - identity = FunctionOutputIdentityAuthority.identity_from_metadata( + identity = FunctionOutputIdentity.from_metadata( parser, item.metadata, fallback_identity_path=output.path, @@ -1633,10 +1684,7 @@ def projected_outputs(self, outputs: Sequence[Output]) -> tuple[Output, ...]: if identity is None: raise ValueError("Projected viewer output requires a filename identity.") identity = replace(identity, extension=output_path.suffix) - filename = FunctionOutputPathAuthority.filename_for_identity( - parser, - identity.with_filename_qualifier(output_path.stem), - ) + filename = identity.with_filename_qualifier(output_path.stem).filename(parser) result.append( replace( output, @@ -1702,7 +1750,8 @@ def __init__( def save_all( self, outputs: Sequence[Output], - ) -> None: + ) -> Mapping[str, tuple[Output, ...]]: + saved_outputs: dict[str, tuple[Output, ...]] = {} for backend in self.backends: backend_instance = self.filemanager._get_backend(backend) output_acceptance = tuple( @@ -1732,6 +1781,7 @@ def save_all( kwargs_payload = self.backend_kwargs[backend] else: kwargs_payload = EMPTY_BACKEND_CALL_KWARGS + written_outputs: list[Output] = [] for batch_outputs, kwargs in kwargs_payload.filemanager_batches( supported_outputs ): @@ -1741,6 +1791,9 @@ def save_all( backend, **kwargs, ) + written_outputs.extend(batch_outputs) + saved_outputs[backend] = tuple(written_outputs) + return saved_outputs def _prepare_path(self, backend: str, backend_instance, path: str) -> None: if not backend_instance.requires_filesystem_validation: @@ -1775,6 +1828,25 @@ class MaterializationContext: source_paths: tuple[str, ...] = () pipeline_position: int | None = None output_plan: ArtifactOutputPlan | None = None + materialization_spec: MaterializationSpec | None = None + + def named_source_filename( + self, metadata: ImagePayloadMetadata, extension: str, + ) -> str | None: + """Name a retained image from the actual rendering purpose and role.""" + if self.materialization_spec is None: + return None + qualifier = self.materialization_spec.filename_qualifier(self.output_plan) + if qualifier is None: + return None + parser = SourceStemAuthoritySelection.from_processing_context(self.context).required_parser() + identity = FunctionOutputIdentity.from_filename_metadata(parser, metadata) + if identity is None: + raise ValueError("Retained image output has no addressable source filename identity.") + identity = self.materialization_spec.filename_identity_for_output( + replace(identity, extension=extension), self.output_plan, + ) + return identity.filename(parser) def paths(self, options: FileOutputOptions) -> PathHelper: return PathHelper(self.base_path, options) @@ -2523,7 +2595,7 @@ def write_image_file( context: MaterializationContext, ) -> list[Output]: """Write image payloads through the nominal image serialization format.""" - materialization_input = MaterializationInput.from_runtime_slice_projected_value( + materialization_input = MaterializationInput.from_image_value( data, options, ) @@ -2554,32 +2626,25 @@ def write_image_file( options.filename_identity is MaterializedFilenameIdentity.ARTIFACT_NAME or paths.source_identity_base_path(options) is not None ) - outputs = tuple( - ( - ( - _image_relative_output_path( - item.value, - options, - context, - sequence_index=sequence_index, - ) - if options.relative_path_template is not None - else ( - paths.primary_output_path(options) - if preserves_planned_path - else str( - paths.parent - / ( - source_stem_authority.required_source_stem(item.metadata) - + options.primary_output_suffix - ) + outputs = [] + for sequence_index, item in enumerate(projected_items, start=1): + if options.relative_path_template is not None: + path = _image_relative_output_path( + item.value, options, context, sequence_index=sequence_index, + ) + elif preserves_planned_path: + path = paths.primary_output_path(options) + else: + filename = context.named_source_filename(item.metadata, options.primary_output_suffix) + if filename is None: + filename = ( + source_stem_authority.required_source_stem( + item.metadata, context.artifact_filename_identity, ) + + options.primary_output_suffix ) - ), - item, - ) - for sequence_index, item in enumerate(projected_items, start=1) - ) + path = str(paths.parent / filename) + outputs.append((path, item)) output_paths = tuple(path for path, _item in outputs) if len(set(output_paths)) != len(output_paths): raise ValueError( @@ -3453,12 +3518,7 @@ def image_file_emits_variable_component_planes( or _image_template_uses_sequence_index(options.relative_path_template) ): return False - return ( - len( - MaterializationInput.from_runtime_slice_projected_value(data, options).items - ) - > 1 - ) + return len(MaterializationInput.from_image_value(data, options).items) > 1 @materialization_emits_variable_component_planes.register(ROIOptions) @@ -3668,8 +3728,8 @@ def metadata_with_artifact_source_identity( source_path=self.artifact_source_identity.path, source_component_metadata=self.artifact_source_identity.component_metadata, ) - return metadata.with_source_provenance( - metadata.source_provenance.with_missing_from(artifact_provenance) + return metadata.with_source_context_from( + ImagePayloadMetadata(source_provenance=artifact_provenance) ) def ordered_axes(self) -> tuple[str, ...]: @@ -4053,6 +4113,10 @@ def participates_in_runtime_export_observation(self) -> bool: """Explicit materialization specs are externally observed exports.""" return True + def filename_qualifier(self, output_plan: ArtifactOutputPlan | None) -> str | None: + """Preserve the source filenames authored by an explicit export.""" + return None + def participates_in_persistent_materialization(self) -> bool: """Explicit materialization specs write to configured persistent targets.""" return True @@ -4187,28 +4251,70 @@ def validate(spec: MaterializationSpec, backends: list[str]) -> None: ) -def _materialization_output_groups( - spec: MaterializationSpec, - data: MaterializationValue, - context: MaterializationContext, - *, - output_path_filter: Callable[[Path], bool] | None = None, -) -> tuple[tuple[WriterSpec, tuple[Output, ...]], ...]: - """Render requested outputs through each writer's declared path projection.""" +@dataclass(frozen=True) +class SavedMaterializationOutputs: + """Backend-indexed outputs from completed saves, independent of artifact kind.""" - return tuple( - ( - writer, - tuple( - output.with_source_identity_fallback( - context.artifact_source_identity - ).with_variable_components(context.variable_components) - for output in writer.outputs(data, options, context, output_path_filter) - ), + outputs_by_backend: Mapping[str, tuple[Output, ...]] + + def outputs_for_backend(self, backend: str) -> tuple[Output, ...]: + return self.outputs_by_backend.get(backend, ()) + + +@dataclass(frozen=True) +class MaterializationBatch: + """One rendered writer batch shared by saving and immediate publication.""" + + context: MaterializationContext + output_groups: tuple[tuple[WriterSpec, tuple[Output, ...]], ...] + primary: int + + @classmethod + def render( + cls, + spec: MaterializationSpec, + data: MaterializationValue, + context: MaterializationContext, + *, + output_path_filter: Callable[[Path], bool] | None = None, + ) -> MaterializationBatch: + context = replace(context, materialization_spec=spec) + groups = tuple( + ( + writer, + tuple( + output.with_source_identity_fallback( + context.artifact_source_identity + ).with_variable_components(context.variable_components) + for output in writer.outputs( + data, options, context, output_path_filter + ) + ), + ) + for options in spec.outputs + for writer in (_WRITERS_BY_OPTIONS[options.__class__],) ) - for options in spec.outputs - for writer in (_WRITERS_BY_OPTIONS[options.__class__],) - ) + return cls(context=context, output_groups=groups, primary=spec.primary) + + @property + def outputs(self) -> tuple[Output, ...]: + return tuple( + output for _writer, outputs in self.output_groups for output in outputs + ) + + @property + def primary_path(self) -> str: + writer, outputs = self.output_groups[self.primary] + return writer.primary_path(list(outputs)) + + def save(self) -> SavedMaterializationOutputs: + """Return only outputs accepted and successfully saved by each backend.""" + saved: dict[str, tuple[Output, ...]] = {} + saver = self.context.saver + for _writer, outputs in self.output_groups: + for backend, saved_outputs in saver.save_all(outputs).items(): + saved[backend] = (*saved.get(backend, ()), *saved_outputs) + return SavedMaterializationOutputs(MappingProxyType(saved)) def materialization_outputs( @@ -4248,19 +4354,15 @@ def materialization_outputs( pipeline_position=pipeline_position, output_plan=output_plan, ) - return tuple( - output - for _writer, outputs in _materialization_output_groups( - spec, - data, - materialization_context, - output_path_filter=output_path_filter, - ) - for output in outputs - ) + return MaterializationBatch.render( + spec, + data, + materialization_context, + output_path_filter=output_path_filter, + ).outputs -def materialize( +def prepare_materialization( spec: MaterializationSpec, data: MaterializationValue, path: str, @@ -4276,8 +4378,8 @@ def materialize( source_paths: Sequence[str] = (), pipeline_position: int | None = None, output_plan: ArtifactOutputPlan | None = None, -) -> str: - """Materialize data to one or more backends.""" +) -> MaterializationBatch: + """Prepare one exact batch for saving and immediate publication.""" normalized_backends = BackendSequenceAuthority.normalize(backends) AllowedBackendsAuthority.validate(spec, normalized_backends) @@ -4303,11 +4405,42 @@ def materialize( output_plan=output_plan, ) - primary_path = "" + return MaterializationBatch.render(spec, data, ctx) - for i, (writer, outs) in enumerate(_materialization_output_groups(spec, data, ctx)): - ctx.saver.save_all(outs) - if i == spec.primary: - primary_path = writer.primary_path(list(outs)) - return primary_path +def materialize( + spec: MaterializationSpec, + data: MaterializationValue, + path: str, + filemanager: FileManager, + backends: Sequence[str] | str, + backend_kwargs: BackendKwargsInput = BACKEND_KWARGS_ABSENT, + context: ProcessingContext | None = None, + extra_inputs: dict | None = None, + *, + artifact_source_identity: SourceImageIdentity | None = None, + artifact_filename_identity: SourceImageIdentity | None = None, + variable_components: Sequence[VariableComponents] = (), + source_paths: Sequence[str] = (), + pipeline_position: int | None = None, + output_plan: ArtifactOutputPlan | None = None, +) -> str: + """Materialize data and return the primary path derived from its writer batch.""" + batch = prepare_materialization( + spec, + data, + path, + filemanager, + backends, + backend_kwargs, + context=context, + extra_inputs=extra_inputs, + artifact_source_identity=artifact_source_identity, + artifact_filename_identity=artifact_filename_identity, + variable_components=variable_components, + source_paths=source_paths, + pipeline_position=pipeline_position, + output_plan=output_plan, + ) + batch.save() + return batch.primary_path diff --git a/openhcs/processing/materialization/persistence.py b/openhcs/processing/materialization/persistence.py index 7d976d1d09..4fd675fc20 100644 --- a/openhcs/processing/materialization/persistence.py +++ b/openhcs/processing/materialization/persistence.py @@ -1,5 +1,11 @@ """Shared persistence and export-observation policies for materialized artifacts.""" +from __future__ import annotations +from typing import TYPE_CHECKING + +if TYPE_CHECKING: + from openhcs.core.artifacts import ArtifactOutputPlan + from .core import MaterializationSpec @@ -9,6 +15,12 @@ class TerminalMaterializationSpec(MaterializationSpec): def participates_in_runtime_export_observation(self) -> bool: return False + def filename_qualifier(self, output_plan: ArtifactOutputPlan | None) -> str | None: + """Retain the compiled image role without changing its source address.""" + if output_plan is None: + return None + return output_plan.artifact_type.retained_filename_qualifier(output_plan.name) + class StreamingOnlyMaterializationSpec(MaterializationSpec): """Prepare viewer outputs without declaring persistent or external exports.""" diff --git a/openhcs/processing/presets/pipelines/czi_brain_axon_cellbody.py b/openhcs/processing/presets/pipelines/czi_brain_axon_cellbody.py index a9896b3930..5c23e04a39 100644 --- a/openhcs/processing/presets/pipelines/czi_brain_axon_cellbody.py +++ b/openhcs/processing/presets/pipelines/czi_brain_axon_cellbody.py @@ -51,9 +51,7 @@ SourceSelector, ) from openhcs.core.source_projection import SourceCandidate, SourcePlaneDataset -from openhcs.core.steps.function_output_manifest import ( - FunctionStepOutputProducerIdentityRequest, -) +from openhcs.core.compiled_step_plan import CompiledStepPlan from openhcs.core.steps.function_step import FunctionStep from openhcs.microscopes.bioformats import BioFormatsHandler, BioFormatsMetadataHandler from openhcs.microscopes.bioformats_adapter import BIOFORMATS_MANIFEST_FILENAME @@ -478,7 +476,7 @@ def artifact_presentation( ) -> StreamProducerIdentity: return StreamProducerIdentity.pipeline_output( output_kind=( - FunctionStepOutputProducerIdentityRequest.ARTIFACT_OUTPUT_KIND + CompiledStepPlan.ARTIFACT_OUTPUT_KIND ), output_key=output_spec.name, projection_key=output_spec.name, diff --git a/openhcs/processing/presets/pipelines/loose_operaphenix_neurite_outgrowth.py b/openhcs/processing/presets/pipelines/loose_operaphenix_neurite_outgrowth.py index 3434bf4d51..7aea13ca99 100644 --- a/openhcs/processing/presets/pipelines/loose_operaphenix_neurite_outgrowth.py +++ b/openhcs/processing/presets/pipelines/loose_operaphenix_neurite_outgrowth.py @@ -47,9 +47,7 @@ SourceFilterSubject, SourceSelector, ) -from openhcs.core.steps.function_output_manifest import ( - FunctionStepOutputProducerIdentityRequest, -) +from openhcs.core.compiled_step_plan import CompiledStepPlan from openhcs.core.steps.function_step import FunctionStep from openhcs.processing.backends.analysis.neurite_outgrowth import ( CELLPROFILER_NEURITE_ENGINE_PROFILE, @@ -433,7 +431,7 @@ def prepare() -> None: pipeline_steps=tuple(pipeline_steps), presentation_identity=StreamProducerIdentity.pipeline_output( output_kind=( - FunctionStepOutputProducerIdentityRequest.ARTIFACT_OUTPUT_KIND + CompiledStepPlan.ARTIFACT_OUTPUT_KIND ), output_key=secondary_output_name, projection_key=secondary_output_name, diff --git a/openhcs/processing/presets/pipelines/neuroncyto_ii_crossover_neurite_outgrowth.py b/openhcs/processing/presets/pipelines/neuroncyto_ii_crossover_neurite_outgrowth.py index f97743b068..d7acf246a8 100644 --- a/openhcs/processing/presets/pipelines/neuroncyto_ii_crossover_neurite_outgrowth.py +++ b/openhcs/processing/presets/pipelines/neuroncyto_ii_crossover_neurite_outgrowth.py @@ -44,9 +44,7 @@ SourceFilterSubject, SourceSelector, ) -from openhcs.core.steps.function_output_manifest import ( - FunctionStepOutputProducerIdentityRequest, -) +from openhcs.core.compiled_step_plan import CompiledStepPlan from openhcs.core.steps.function_step import FunctionStep from openhcs.processing.backends.analysis.neurite_outgrowth import ( NEURITE_MORPHOLOGY_OUTPUT, @@ -295,7 +293,7 @@ def prepare() -> None: pipeline_steps=tuple(pipeline_steps), presentation_identity=StreamProducerIdentity.pipeline_output( output_kind=( - FunctionStepOutputProducerIdentityRequest.ARTIFACT_OUTPUT_KIND + CompiledStepPlan.ARTIFACT_OUTPUT_KIND ), output_key=NEURITE_MORPHOLOGY_OUTPUT.name, projection_key=NEURITE_MORPHOLOGY_OUTPUT.name, diff --git a/openhcs/runtime/zmq_compilation.py b/openhcs/runtime/zmq_compilation.py index 69949296a5..0364e409d8 100644 --- a/openhcs/runtime/zmq_compilation.py +++ b/openhcs/runtime/zmq_compilation.py @@ -19,6 +19,7 @@ from openhcs.runtime.zmq_execution_signature import OpenHCSExecutionConfigBundle if TYPE_CHECKING: + from openhcs.core.config import GlobalPipelineConfig from openhcs.core.orchestrator.orchestrator import PipelineOrchestrator @@ -74,6 +75,7 @@ class ZMQCompilationRequest: plate_id: str pipeline_steps: list[AbstractStep] orchestrator: "PipelineOrchestrator" + resolved_config: GlobalPipelineConfig wells: list[str] compile_artifact_id: str | None compilation_signature: str @@ -153,6 +155,7 @@ def compile_fresh(self) -> ZMQCompilationResult: well_filter=self.wells, is_zmq_execution=True, debug_execution_policy=self.debug_execution_policy, + resolved_config=self.resolved_config, ) finally: set_progress_queue(None) diff --git a/openhcs/runtime/zmq_execution_client.py b/openhcs/runtime/zmq_execution_client.py index 9965ec8672..590d301fc8 100644 --- a/openhcs/runtime/zmq_execution_client.py +++ b/openhcs/runtime/zmq_execution_client.py @@ -9,6 +9,7 @@ import time from collections.abc import Callable, Mapping, Sequence from concurrent.futures import CancelledError +from copy import deepcopy from contextlib import AbstractContextManager, nullcontext from dataclasses import dataclass, replace from enum import Enum @@ -39,6 +40,7 @@ ControlMessageType, ControlRequestHeader, EndpointApplicationCompatibilityError, + ExecutionRecord, MessageFields, PongResponse, ServerRole, @@ -341,9 +343,6 @@ def compile_artifact_id(self) -> str | None: def compile_only(self) -> bool: return self.compile_control.compile_only - def to_task(self) -> "OpenHCSExecutionSubmission": - return self - def with_config_params( self, config_params: ZMQParams ) -> "OpenHCSExecutionSubmission": @@ -396,9 +395,6 @@ def with_compile_artifact_id( def pipeline_code(self) -> str: return PipelineDocumentAuthority.execution_source(self.pipeline_document) - def step_count_label(self) -> str: - return str(len(self.pipeline_steps)) - class ZMQPipelineRunPhase(Enum): """Source-owned boundaries for one compiled pipeline execution.""" @@ -415,17 +411,16 @@ class ZMQCompiledPipelineRun: compile_artifact_id: str execution_id: str - completion_response: Mapping[str, Any] + request: ZMQExecutionRequestBuilder + compile_record: ExecutionRecord + execution_record: ExecutionRecord completion_observed_at: float @property def results_summary(self) -> Mapping[str, Any]: """Project the completed wait response's ordinary result summary.""" - value = self.completion_response.get("results") - if not value: - value = self.completion_response.get(MessageFields.RESULTS_SUMMARY) - return dict(value) if isinstance(value, Mapping) else {} + return dict(self.execution_record.results_summary or {}) @property def output_plate(self) -> ExecutionOutputPlateSummary: @@ -448,8 +443,9 @@ def phase_scope(phase: ZMQPipelineRunPhase) -> AbstractContextManager[None]: return nullcontext() if phase_context is None else phase_context(phase) with phase_scope(ZMQPipelineRunPhase.SUBMIT_COMPILE): + request = ZMQExecutionRequestBuilder.from_task(submission) compile_response = ExecutionSubmissionResponse.from_wire( - client.submit_compile(submission) + client.submit_prepared_pipeline(request.compile_request()) ) if not compile_response.accepted: raise RuntimeError( @@ -463,14 +459,16 @@ def phase_scope(phase: ZMQPipelineRunPhase) -> AbstractContextManager[None]: compile_artifact_id, poll_interval=_COMPILED_PIPELINE_POLL_INTERVAL_SECONDS, ) - ExecutionWaitResult.from_wire(compile_wait_response).require_complete( - "OpenHCS ZMQ compilation failed" + compile_record = ExecutionWaitResult.from_wire( + compile_wait_response + ).require_completed_execution( + "OpenHCS ZMQ compilation failed", expected_execution_id=compile_artifact_id ) - execution_submission = submission.with_compile_artifact_id(compile_artifact_id) + execution_request = request.with_compile_artifact_id(compile_artifact_id) with phase_scope(ZMQPipelineRunPhase.SUBMIT_EXECUTION): execution_response = ExecutionSubmissionResponse.from_wire( - client.submit_pipeline(execution_submission) + client.submit_prepared_pipeline(execution_request) ) if not execution_response.accepted: raise RuntimeError( @@ -485,13 +483,17 @@ def phase_scope(phase: ZMQPipelineRunPhase) -> AbstractContextManager[None]: poll_interval=_COMPILED_PIPELINE_POLL_INTERVAL_SECONDS, ) completion_observed_at = time.time() - ExecutionWaitResult.from_wire(completion_response).require_complete( - "OpenHCS ZMQ execution failed" + execution_record = ExecutionWaitResult.from_wire( + completion_response + ).require_completed_execution( + "OpenHCS ZMQ execution failed", expected_execution_id=execution_id ) return ZMQCompiledPipelineRun( compile_artifact_id=compile_artifact_id, execution_id=execution_id, - completion_response=completion_response, + request=execution_request, + compile_record=compile_record, + execution_record=execution_record, completion_observed_at=completion_observed_at, ) @@ -507,9 +509,10 @@ def _pycodify_config_source( @dataclass(frozen=True, slots=True) class ZMQExecutionRequestBuilder: - task: OpenHCSExecutionSubmission + identity: ZMQExecutionIdentity + compile_control: ZMQExecutionCompileControl pipeline_code: str - config_projection: "ZMQConfigProjection" + config_projection: ZMQConfigProjection @classmethod def from_task( @@ -517,18 +520,40 @@ def from_task( task: OpenHCSExecutionSubmission, ) -> "ZMQExecutionRequestBuilder": return cls( - task=task, + identity=task.identity, + compile_control=task.compile_control, pipeline_code=task.pipeline_code(), config_projection=ZMQConfigProjection.from_task(task), ) + def compile_request(self) -> ZMQExecutionRequestBuilder: + return replace(self, compile_control=self.compile_control.as_compile_request()) + + def with_compile_artifact_id(self, artifact_id: str) -> ZMQExecutionRequestBuilder: + return replace( + self, + compile_control=self.compile_control.as_execution_request(artifact_id), + ) + + @property + def global_config_code(self) -> str: + fields = self.config_projection.source_fields + if fields is None or fields.config_code is None: + raise RuntimeError("Prepared execution request has no global config source") + return fields.config_code + + @property + def config_params(self) -> ZMQParams | None: + boundary = self.config_projection.params_boundary + return None if boundary is None else boundary.params + @property def request_payload(self) -> ZMQExecutionRequestPayload: return ZMQExecutionRequestPayload( - identity=self.task.identity, + identity=self.identity, pipeline_code=self.pipeline_code, config_transport=self.config_projection.signature_transport(), - compile_control=self.task.compile_control, + compile_control=self.compile_control, ) def request(self) -> "ZMQRequest": @@ -536,8 +561,8 @@ def request(self) -> "ZMQRequest": ( (MessageFields.TYPE, ControlMessageType.EXECUTE.value), (MessageFields.PIPELINE_CODE, self.pipeline_code), - *self.task.identity.request_items(), - *self.task.compile_control.request_items(), + *self.identity.request_items(), + *self.compile_control.request_items(), *self.config_projection.request_items(), ) ) @@ -623,7 +648,7 @@ def from_task( config_source = _pycodify_config_source(task.global_pipeline_config) return cls( params_boundary=( - task.config_boundary + ZMQConfigParamsBoundary(deepcopy(task.config_boundary.params)) if task.config_boundary.params is not None else None ), @@ -1026,15 +1051,18 @@ def serialize_task( task: OpenHCSExecutionSubmission, config=None, ) -> dict[str, ZMQValue]: - request_builder = ZMQExecutionRequestBuilder.from_task(task) + return self.serialize_prepared_request(ZMQExecutionRequestBuilder.from_task(task)) + + def serialize_prepared_request( + self, request_builder: ZMQExecutionRequestBuilder + ) -> dict[str, ZMQValue]: request = request_builder.request() request_payload = request_builder.request_payload logger.info( - "Serialize task: plate=%s compile_only=%s artifact_id=%s step_count=%s pipeline_sha=%s config_sha=%s", - task.plate_id, - task.compile_only, - task.compile_artifact_id, - task.step_count_label(), + "Serialize task: plate=%s compile_only=%s artifact_id=%s pipeline_sha=%s config_sha=%s", + request_builder.identity.plate_id, + request_builder.compile_control.compile_only, + request_builder.compile_control.compile_artifact_id, request_payload.pipeline_sha, request_builder.config_projection.config_sha, ) @@ -1047,7 +1075,19 @@ def submit_pipeline( timeout_ms: int | None = None, ): return self._submit_submission( - submission.to_task(), + lambda: self.serialize_task(submission), + timeout_ms=self._submission_timeout_ms(timeout_ms), + ) + + def submit_prepared_pipeline( + self, + request: ZMQExecutionRequestBuilder, + *, + timeout_ms: int | None = None, + ): + """Submit the exact declaration already admitted for a compiled run.""" + return self._submit_submission( + lambda: self.serialize_prepared_request(request), timeout_ms=self._submission_timeout_ms(timeout_ms), ) @@ -1062,7 +1102,9 @@ def submit_debug_pipeline( submission.config_params ).with_updates(debug_config.to_config_params()) return self._submit_submission( - submission.with_config_params(config_params_boundary.params).to_task(), + lambda: self.serialize_task( + submission.with_config_params(config_params_boundary.params) + ), timeout_ms=self._submission_timeout_ms(timeout_ms), ) @@ -1073,7 +1115,7 @@ def submit_compile( timeout_ms: int | None = None, ): return self._submit_submission( - submission.compile_request().to_task(), + lambda: self.serialize_task(submission.compile_request()), timeout_ms=self._submission_timeout_ms(timeout_ms), ) @@ -1129,7 +1171,7 @@ def _submission_timeout_ms(self, timeout_ms: int | None) -> int: def _submit_submission( self, - submission: OpenHCSExecutionSubmission, + build_request: Callable[[], dict[str, ZMQValue]], *, timeout_ms: int, ): @@ -1150,7 +1192,7 @@ def _submit_submission( self._ensure_progress_subscription( timeout_ms=deadline.remaining_milliseconds() ) - request = self.serialize_task(submission, None) + request = build_request() if MessageFields.TYPE not in request: request[MessageFields.TYPE] = ControlMessageType.EXECUTE.value request_timeout_ms = deadline.remaining_milliseconds() diff --git a/openhcs/runtime/zmq_execution_observation.py b/openhcs/runtime/zmq_execution_observation.py index fecffce412..f75dc3072d 100644 --- a/openhcs/runtime/zmq_execution_observation.py +++ b/openhcs/runtime/zmq_execution_observation.py @@ -9,7 +9,11 @@ from pathlib import Path from openhcs.core.context.processing_context import ProcessingContext -from openhcs.core.orchestrator.execution_result import ExecutionResult, ExecutionStatus +from openhcs.core.orchestrator.execution_result import ( + ExecutionResult, + RuntimeExecutionObservation, + ExecutionStatus, +) from openhcs.core.runtime_execution_validation import ( RuntimeArtifactExecutionExpectation, RuntimeArtifactExecutionObservation, @@ -215,11 +219,12 @@ def from_execution( compiled_contexts: Mapping[str, ProcessingContext], execution_results: Mapping[str, ExecutionResult], output_roots: tuple[Path, ...], + runtime_observations: tuple[RuntimeExecutionObservation, ...], server_environment: RuntimeEnvironmentSnapshot | None = None, execution_id: str | None = None, ) -> ZMQRuntimeExecutionObservationExport: observation = RuntimeArtifactExecutionObservation.from_contexts( - compiled_contexts + compiled_contexts, runtime_observations=runtime_observations ) return cls( schema_version=ZMQ_RUNTIME_OBSERVATION_EXPORT_SCHEMA_VERSION, diff --git a/openhcs/runtime/zmq_execution_server.py b/openhcs/runtime/zmq_execution_server.py index 909b47f906..1bfaccde3a 100644 --- a/openhcs/runtime/zmq_execution_server.py +++ b/openhcs/runtime/zmq_execution_server.py @@ -21,6 +21,7 @@ from zmqruntime.startup import EndpointStartupStatusCallback from openhcs.core.config import GlobalPipelineConfig, PipelineConfig +from objectstate.object_state import ObjectState from openhcs.core.config_document import ConfigDocumentAuthority from openhcs.core.orchestrator.cancellation import ExecutionCancelledError from openhcs.core.pipeline_document import PipelineDocumentAuthority @@ -271,7 +272,7 @@ def _enqueue_progress(self, progress_update: dict) -> None: list(progress_update.keys()), event.step_name, ) - self.progress_queue.put(event.to_dict()) + self.send_progress_update(event.to_dict()) def _forward_worker_progress(self, worker_queue) -> None: import logging @@ -293,7 +294,7 @@ def _forward_worker_progress(self, worker_queue) -> None: "Execution-level progress cannot carry a worker claim: " f"{progress_update}" ) - self.progress_queue.put( + self.send_progress_update( event.with_worker_topology( worker_assignments=assignments, total_wells=sorted( @@ -338,7 +339,7 @@ def _forward_worker_progress(self, worker_queue) -> None: enriched_event.step_name, enriched_event.worker_slot, ) - self.progress_queue.put(enriched_event.to_dict()) + self.send_progress_update(enriched_event.to_dict()) def _worker_assignments_for_execution( self, @@ -550,10 +551,14 @@ def _execute_with_orchestrator( request_context.compile_artifact_id, ) self._ensure_request_global_config_context(request_context) + resolved_config = ObjectState( + request_context.pipeline_config + ).to_saved_resolved_object() orchestrator = self._initialize_orchestrator( request_context.execution_id, plate_path_str, request_context.pipeline_config, + resolved_config=resolved_config, selected_pipeline_path=request_context.request_payload.selected_pipeline_path, execution_bundle=( self._compiled_artifacts[ @@ -582,6 +587,7 @@ def _execute_with_orchestrator( debug_execution_config=debug_execution_config, debug_execution_policy=debug_execution_policy, progress_emitter=progress_emitter, + resolved_config=resolved_config, ) compilation_resolved = True self._record_compilation_outputs(request_context.execution_id, compilation) @@ -632,6 +638,8 @@ def _initialize_orchestrator( execution_id: str, plate_path_str: str, pipeline_config, + *, + resolved_config: GlobalPipelineConfig, selected_pipeline_path: str | None = None, execution_bundle=None, ): @@ -642,13 +650,14 @@ def _initialize_orchestrator( orchestrator = PipelineOrchestrator( plate_path=Path(plate_path_str), pipeline_config=pipeline_config, + resolved_config=resolved_config, selected_pipeline_path=selected_pipeline_path, progress_callback=None, transport_config=self.config, ) orchestrator.execution_id = execution_id if execution_bundle is None: - orchestrator.initialize() + orchestrator.initialize(resolved_config=resolved_config) else: orchestrator.adopt_compiled_execution(execution_bundle) self.active_executions[execution_id].set_extra("orchestrator", orchestrator) @@ -703,6 +712,7 @@ def _resolve_compilation( debug_execution_config, debug_execution_policy, progress_emitter: ZMQProgressEmitter, + resolved_config: GlobalPipelineConfig, ): if request_context.compile_artifact_id is not None: self._cleanup_compiled_artifacts() @@ -711,6 +721,7 @@ def _resolve_compilation( plate_id=request_context.plate_id, pipeline_steps=request_context.pipeline_steps, orchestrator=orchestrator, + resolved_config=resolved_config, wells=wells, compile_artifact_id=request_context.compile_artifact_id, compilation_signature=request_context.compilation_signature, @@ -812,17 +823,8 @@ def _export_runtime_observation( is ZMQRuntimeObservationExportScope.OUTCOMES ): observed_exports = RuntimeExportObservation.from_runtime_observations( - tuple( - result.runtime_observation for result in execution_results.values() - ) + execution_results.runtime_observations ) - if execution_bundle.requires_parent_runtime_observation: - parent_exports = RuntimeExportObservation.from_execution_contexts( - execution_bundle.runtime_contexts - ) - observed_exports = RuntimeExportObservation.from_output_paths( - (*observed_exports.output_files, *parent_exports.output_files) - ) export = ZMQRuntimeExecutionOutcomeExport.from_execution( compiled_axis_ids=execution_bundle.runtime_contexts, execution_results=execution_results, @@ -835,6 +837,7 @@ def _export_runtime_observation( export = ZMQRuntimeExecutionObservationExport.from_execution( compiled_contexts=execution_bundle.runtime_contexts, execution_results=execution_results, + runtime_observations=execution_results.runtime_observations, output_roots=output_roots, server_environment=self._server_environment, execution_id=request_context.execution_id, diff --git a/pyproject.toml b/pyproject.toml index 94c4cf162b..08178edaf5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -101,7 +101,7 @@ dependencies = [ # External dependencies (PyPI versions for production builds) "zmqruntime>=0.3.0,<0.4", "pycodify>=0.1.3,<0.2", - "objectstate>=1.1.8,<2", + "objectstate>=1.1.9,<2", "python-introspect>=0.1.16,<0.2", "metaclass-registry>=0.2.2,<0.3", "arraybridge>=0.3.6,<0.4", diff --git a/tests/diagnostics/owned_bootstrap_readback.py b/tests/diagnostics/owned_bootstrap_readback.py index c9d4956509..a90c30258c 100644 --- a/tests/diagnostics/owned_bootstrap_readback.py +++ b/tests/diagnostics/owned_bootstrap_readback.py @@ -107,7 +107,7 @@ def record(name): expected_runtime_paths.add(matched.path) return matched - image = record(image_name).value.data + image = record(image_name).data np.testing.assert_array_equal(image_payload_data(image), expected) assert addresses(image_payload_metadata(image)) == expected_addresses flow = summary.main_flow_materialization @@ -132,8 +132,8 @@ def record(name): result['steps'].append(step_result) if summary.step_index % 3 == 0: continue - labels = record('volume_fixture_labels_v2').value.data - rows = record('volume_fixture_rows_v2').value.data + labels = record('volume_fixture_labels_v2').data + rows = record('volume_fixture_rows_v2').data np.testing.assert_array_equal(object_label_dense_array(labels), expected.astype(np.int32)) assert addresses(image_payload_metadata(labels)) == expected_addresses assert rows.subject.object_name == plans['volume_fixture_labels_v2'].name diff --git a/tests/integration/test_bioformats_handler_runtime.py b/tests/integration/test_bioformats_handler_runtime.py index 2dbe39259c..e4f6f3409a 100644 --- a/tests/integration/test_bioformats_handler_runtime.py +++ b/tests/integration/test_bioformats_handler_runtime.py @@ -3,7 +3,7 @@ import numpy as np from openhcs.constants.constants import Backend -from openhcs.core.steps.function_io import bulk_preload_step_images +from openhcs.core.source_binding_selection import SourceFileUniverse from openhcs.microscopes.bioformats import BioFormatsHandler from tests.unit.bioformats_fixture import ( bioformats_filemanager, @@ -11,7 +11,7 @@ ) -def test_bioformats_handler_preloads_planes_through_runtime_path( +def test_bioformats_handler_loads_selected_planes_through_runtime_path( tmp_path: Path, ) -> None: stack = write_bioformats_manifest_fixture(tmp_path) @@ -19,14 +19,9 @@ def test_bioformats_handler_preloads_planes_through_runtime_path( handler = BioFormatsHandler(filemanager) handler.initialize_workspace(tmp_path, filemanager) - bulk_preload_step_images( - step_input_dir=tmp_path, - axis_id="A01", - read_backend=Backend.VIRTUAL_WORKSPACE.value, - filemanager=filemanager, - microscope_handler=handler, - patterns_to_preload=("A01_s001_w1_z001_t001.tif",), - ) + SourceFileUniverse( + (str(tmp_path / "A01_s001_w1_z001_t001.tif"),), Backend.VIRTUAL_WORKSPACE, + ).load_images(filemanager) loaded = filemanager.load_batch( [str(tmp_path / "A01_s001_w1_z001_t001.tif")], diff --git a/tests/integration/test_cellprofiler_generated_pipeline.py b/tests/integration/test_cellprofiler_generated_pipeline.py index f1b9b35131..57d3eba777 100644 --- a/tests/integration/test_cellprofiler_generated_pipeline.py +++ b/tests/integration/test_cellprofiler_generated_pipeline.py @@ -287,10 +287,10 @@ def _runtime_export_has_semantic_record( "Structured endpoint identity is only valid for relationship records." ) return any( - isinstance(record.value.data, ObjectRelationship) + isinstance(record.data, ObjectRelationship) and ( - record.value.data.declaration.source.name, - record.value.data.declaration.target.name, + record.data.declaration.source.name, + record.data.declaration.target.name, ) == name for record in _runtime_records( @@ -466,7 +466,7 @@ def test_cppipe_import_executes_through_canonical_zmq_path( axis_id="A01", ) assert len(nuclei_records) == 1 - assert object_label_dense_array(nuclei_records[0].value.data).max() > 0 + assert object_label_dense_array(nuclei_records[0].data).max() > 0 def test_bbbc021_cppipe_executes_named_channel_bindings_through_zmq( @@ -495,7 +495,7 @@ def test_bbbc021_cppipe_executes_named_channel_bindings_through_zmq( axis_id="A01", ) assert len(nuclei_records) == 1 - assert object_label_dense_array(nuclei_records[0].value.data).max() > 0 + assert object_label_dense_array(nuclei_records[0].data).max() > 0 assert len(composite_records) == 1 @@ -565,7 +565,7 @@ def test_loadimages_cppipe_preserves_source_artifact_bindings_through_zmq( axis_id="A01", ) assert len(corrected_records) == 1 - assert np.asarray(corrected_records[0].value.data).shape[-2:] == (64, 64) + assert np.asarray(corrected_records[0].data).shape[-2:] == (64, 64) def test_legacy_examplefly_load_data_cppipe_fails_at_nominal_import_boundary() -> None: @@ -607,7 +607,7 @@ def test_cppipe_relationship_outputs_are_compiler_derived_over_zmq( ) assert relationship_records assert measurement_records - relationship = cast(ObjectRelationship, relationship_records[0].value.data) + relationship = cast(ObjectRelationship, relationship_records[0].data) assert relationship.declaration.source.name == "Nuclei" assert relationship.declaration.target.name == "Cells" assert relationship.declaration.relationship_type == "Parent" @@ -675,10 +675,10 @@ def test_percent_positive_cppipe_executes_measurement_consumers_over_zmq( export, artifact_type=MeasurementsArtifactType, ) - if isinstance(record.value.data, MeasurementTable) + if isinstance(record.data, MeasurementTable) if any( row_mapping["output_name"] == "PercentPositive" - for row in record.value.data.rows.iter_row_mappings() + for row in record.data.rows.iter_row_mappings() for row_mapping in (measurement_row_mapping(row),) if "output_name" in row_mapping ) @@ -686,7 +686,7 @@ def test_percent_positive_cppipe_executes_measurement_consumers_over_zmq( assert calculate_math_records calculate_math_table = cast( MeasurementTable, - calculate_math_records[0].value.data, + calculate_math_records[0].data, ) calculate_math_rows = tuple( measurement_row_mapping(row) @@ -722,7 +722,7 @@ def test_examplehuman_cppipe_executes_source_bound_objects_over_zmq( axis_id=axis_id, ) assert len(cytoplasm_records) == 1 - cytoplasm = object_label_dense_array(cytoplasm_records[0].value.data) + cytoplasm = object_label_dense_array(cytoplasm_records[0].data) assert cytoplasm.ndim == 2 or cytoplasm.ndim == 3 and cytoplasm.shape[0] == 1 assert _runtime_export_has_semantic_record( export, @@ -760,7 +760,7 @@ def test_official_untangleworms_preserves_overlay_shape_over_zmq( axis_id=axis_id, ) assert len(overlay_records) == 1 - overlay = np.asarray(overlay_records[0].value.data) + overlay = np.asarray(overlay_records[0].data) assert overlay.ndim == 4 assert overlay.shape[0] == 2 assert overlay.shape[-1] == 3 @@ -832,8 +832,8 @@ def test_official_colocalization_preserves_relationships_and_configured_export( ( record.key.scope.component, record.key.scope.value_text, - object_label_dense_array(record.value.data).shape, - cast(ObjectLabelValue, record.value.data).plane_axis, + object_label_dense_array(record.data).shape, + cast(ObjectLabelValue, record.data).plane_axis, ) for record in records ) @@ -871,8 +871,8 @@ def test_official_colocalization_preserves_relationships_and_configured_export( ) assert { ( - record.value.data.declaration.source.name, - record.value.data.declaration.target.name, + record.data.declaration.source.name, + record.data.declaration.target.name, ) for record in relationship_records } == { @@ -888,8 +888,8 @@ def test_official_colocalization_preserves_relationships_and_configured_export( ) assert { ( - record.value.data.declaration.source.name, - record.value.data.declaration.target.name, + record.data.declaration.source.name, + record.data.declaration.target.name, ) for record in lineage_records } == { @@ -897,7 +897,7 @@ def test_official_colocalization_preserves_relationships_and_configured_export( ("Objects1", "ColocalizedRegion"), } relationships = tuple( - cast(ObjectRelationship, record.value.data) for record in relationship_records + cast(ObjectRelationship, record.data) for record in relationship_records ) assert { ( @@ -947,7 +947,7 @@ def test_official_neighbors_preserves_measurement_and_image_exports_over_zmq( axis_id=axis_id, ) assert cells_records - assert object_label_dense_array(cells_records[0].value.data).max() > 0 + assert object_label_dense_array(cells_records[0].data).max() > 0 assert _runtime_export_has_semantic_record( export, name="MeasureObjectNeighbors_6_measurements", diff --git a/tests/integration/test_chained_callable_lineage_journey.py b/tests/integration/test_chained_callable_lineage_journey.py index 59c840578c..8960728d8c 100644 --- a/tests/integration/test_chained_callable_lineage_journey.py +++ b/tests/integration/test_chained_callable_lineage_journey.py @@ -1,8 +1,10 @@ """Canonical callable twice through document, compiler, execution and publication.""" from csv import DictReader +from inspect import unwrap import numpy as np +import pytest import tifffile from openhcs.agent.services.execution_session_service import ( @@ -35,15 +37,32 @@ SourceSelector, ) from openhcs.core.steps.function_step import FunctionStep +from openhcs.processing.custom_functions.runtime_registry import ( + CustomFunctionRuntimeRegistry, + register_custom_function, +) from polystore.roi import load_rois_from_zip # Reuse the public reference's authoritative code block, not a copied callable. from tests.unit.agent.test_callable_artifact_reference import reference_namespace # noqa: F401 +@pytest.fixture +def registered_reference_callable(reference_namespace): + """Give the executable public example its actual custom catalog lifetime.""" + function = reference_namespace["inspect_label_fixture"] + registered = register_custom_function(function) + try: + assert unwrap(registered) is unwrap(function) + yield function + finally: + CustomFunctionRuntimeRegistry.remove(function.__name__) + + def test_chained_public_callable_uses_declared_main_flow_not_storage_argument( - tmp_path, reference_namespace, + tmp_path, reference_namespace, registered_reference_callable, ): + assert reference_namespace["inspect_label_fixture"] is registered_reference_callable plate = tmp_path / "plate" plate.mkdir() fixture = np.zeros((8, 8), dtype=np.uint16) @@ -106,7 +125,7 @@ def test_chained_public_callable_uses_declared_main_flow_not_storage_argument( assert edge.spec.ref() == incoming_ref assert edge.spec.parameter_name is None assert second_invocation.contract.group_scope_inputs.ref_set() == {incoming_ref} - assert edge.consumes_main_flow + assert edge.main_flow_projection is not None assert edge.main_flow_projection is MainFlowInputProjection.COMPLETE_PAYLOAD assert edge.storage_plan is None assert edge.projection is None @@ -140,7 +159,7 @@ def test_chained_public_callable_uses_declared_main_flow_not_storage_argument( ) ) records.append(record) - image, labels, rows = (record.value.data for record in records) + image, labels, rows = (record.data for record in records) np.testing.assert_array_equal(np.squeeze(image_payload_data(image)), fixture) np.testing.assert_array_equal(np.squeeze(object_label_dense_array(labels)), fixture) assert rows.subject.object_name == labels_plan.name diff --git a/tests/integration/test_measurement_declaration_journey.py b/tests/integration/test_measurement_declaration_journey.py index bbcf1dd880..c1efc52742 100644 --- a/tests/integration/test_measurement_declaration_journey.py +++ b/tests/integration/test_measurement_declaration_journey.py @@ -4,6 +4,7 @@ from dataclasses import dataclass, replace from csv import DictReader +from inspect import unwrap import numpy as np import pytest @@ -57,6 +58,8 @@ SourceFilterMatchType, SourceFilterSubject, SourceSelector, + SourceBindingMatchMethod, + SourceBindingMatchPlan, StepSourceBindingsConfig, ) from openhcs.core.steps.function_step import FunctionStep @@ -82,6 +85,10 @@ CellProfilerThresholdMethod, ) from openhcs.processing.backends.lib_registry.unified_registry import ProcessingContract +from openhcs.processing.custom_functions.runtime_registry import ( + CustomFunctionRuntimeRegistry, + register_custom_function, +) from openhcs.processing.materialization import CsvOptions, MaterializationSpec @@ -136,6 +143,17 @@ def count_with_image_subject(image): ) +@pytest.fixture +def registered_count_callable(valid): + function = count_with_image_subject if valid else count_without_subject + registered = register_custom_function(function) + try: + assert unwrap(registered) is unwrap(function) + yield registered + finally: + CustomFunctionRuntimeRegistry.remove(function.__name__) + + def _binding_name(module, plan_type, artifact_type): (binding,) = module.declared_artifact_bindings( plan_type=plan_type, artifact_type=artifact_type @@ -307,15 +325,15 @@ def test_exact_secondary_selector_survives_authoring_compile_and_execution(tmp_p assert secondary.key.scope.value_text_for_component(AllComponents.CHANNEL) == ( "1" if same_source else "2" ) - primary_area = np.count_nonzero(object_label_dense_array(primary.value.data)) - secondary_area = np.count_nonzero(object_label_dense_array(secondary.value.data)) + primary_area = np.count_nonzero(object_label_dense_array(primary.data)) + secondary_area = np.count_nonzero(object_label_dense_array(secondary.data)) assert secondary_area > primary_area > 0 [output] = invocation.artifact_output_plans [measurement] = store.find(name=output.name, artifact_type=MeasurementsArtifactType, axis_id="A01") - assert measurement.value.data.subject.object_name == "Cells" + assert measurement.data.subject.object_name == "Cells" image_name = "DNA" if same_source else "Actin" values = measurement_values_for_feature( - (measurement.value.data,), + (measurement.data,), f"Intensity_IntegratedIntensity_{image_name}", object_count=1, object_name="Cells", @@ -329,7 +347,7 @@ def test_exact_secondary_selector_survives_authoring_compile_and_execution(tmp_p def test_omitted_secondary_selector_still_fails_closed(tmp_path): _write_plate(tmp_path) - with pytest.raises(ValueError, match="labels.*multiple exact artifact occurrences"): + with pytest.raises(ValueError, match="cannot reconstruct an exact module block"): _compile( tmp_path, _document(selected=False), @@ -337,6 +355,73 @@ def test_omitted_secondary_selector_still_fails_closed(tmp_path): ) +@pytest.mark.parametrize("producer_group_by", [GroupBy.NONE, GroupBy.CHANNEL]) +def test_explicit_measurement_rosters_survive_one_matched_source_anchor( + tmp_path, producer_group_by, +): + from openhcs.core.steps.function_execution import FunctionStepExecutor + + _write_plate(tmp_path) + original = _document() + for producer in original.pipeline_steps[:-1]: + producer.processing_config = replace( + producer.processing_config, group_by=producer_group_by, + ) + original.pipeline_steps[-1] = _step( + measure_object_intensity, + "Measure both source images and object sets", + { + MeasureObjectIntensityModule.image_measurement_binding.require_parameter_name(): ("DNA", "Actin"), + MeasureObjectIntensityModule.object_measurement_binding.require_parameter_name(): ("Nuclei", "Cells"), + }, + ) + document = PipelineDocumentAuthority.from_values( + pipeline_config=replace( + original.pipeline_config, + source_bindings_config=LazySourceBindingsConfig( + bindings=(_source("DNA", "1"), _source("Actin", "2")), + match_plan=SourceBindingMatchPlan(method=SourceBindingMatchMethod.ORDER), + ), + ), + pipeline_steps=original.pipeline_steps, + ) + document = PipelineDocumentAuthority.from_source(PipelineDocumentAuthority.render(document)) + bundle = _compile(tmp_path, document, GlobalPipelineConfig(num_workers=1, use_threading=True)) + context = bundle.runtime_contexts["A01"] + executor = FunctionStepExecutor(context, 2) + prepared = executor._prepare_groups(executor._detect_patterns()) + assert prepared.total_count() == 1 + invocation = next(executor.plan.compiled_function_pattern.iter_invocations()) + assert tuple( + spec.name for spec in invocation.contract.artifact_inputs.of_artifact_type(ImageArtifactType) + ) == ("DNA", "Actin") + results = _execute(tmp_path, document, bundle) + assert results["A01"].is_success(), results["A01"].error_message + (output,) = invocation.artifact_output_plans + (measurement,) = context.runtime_value_store.find( + name=output.name, artifact_type=MeasurementsArtifactType, axis_id="A01", + ) + for object_name in ("Nuclei", "Cells"): + (labels,) = context.runtime_value_store.find(name=object_name, axis_id="A01") + area = np.count_nonzero(object_label_dense_array(labels.data)) + for image_name, integrated in (("DNA", 4.0), ("Actin", float(area))): + expected_features = { + "IntegratedIntensity": integrated, + "MeanIntensity": integrated / area, + "MinIntensity": 1.0 if integrated == area else 0.0, + "MaxIntensity": 1.0, + } + for feature, expected in expected_features.items(): + values = measurement_values_for_feature( + (measurement.data,), + f"Intensity_{feature}_{image_name}", + object_count=1, + object_name=object_name, + dialect=CELLPROFILER_MEASUREMENT_LOOKUP_DIALECT, + ) + assert tuple(values) == pytest.approx((expected,)) + + def test_omitted_selector_remains_valid_for_one_label_producer(tmp_path): _write_plate(tmp_path) bundle = _compile( @@ -355,7 +440,9 @@ def test_omitted_selector_remains_valid_for_one_label_producer(tmp_path): @pytest.mark.parametrize("valid", [False, True]) -def test_headless_entrypoint_requires_subject_and_executes_corrected_rows(tmp_path, valid): +def test_headless_entrypoint_requires_subject_and_executes_corrected_rows( + tmp_path, valid, registered_count_callable, +): _write_plate(tmp_path) document = PipelineDocumentAuthority.from_values( pipeline_config=PipelineConfig( @@ -365,7 +452,7 @@ def test_headless_entrypoint_requires_subject_and_executes_corrected_rows(tmp_pa ), ), pipeline_steps=[_step( - count_with_image_subject if valid else count_without_subject, + registered_count_callable, "Count pixels", {}, )], ) @@ -409,8 +496,8 @@ def test_headless_entrypoint_requires_subject_and_executes_corrected_rows(tmp_pa [counts] = store.find(name="PixelCounts", axis_id="A01") [image] = store.find(name="CountedImage", axis_id="A01") assert image.key.artifact_type is ImageArtifactType - assert counts.value.data.subject.source_image_name == "CountedImage" - assert tuple(counts.value.data.rows.column_values("pixel_count")) == (4,) + assert counts.data.subject.source_image_name == "CountedImage" + assert tuple(counts.data.rows.column_values("pixel_count")) == (4,) step_plan = bundle.runtime_contexts["A01"].step_plans[0] [csv_path] = step_plan.artifact_analysis_output_dir.glob( f"*_{counts.key.name}_step{step_plan.step_index}_details.csv" @@ -418,4 +505,4 @@ def test_headless_entrypoint_requires_subject_and_executes_corrected_rows(tmp_pa with csv_path.open(newline="") as stream: [persisted] = DictReader(stream) assert persisted["pixel_count"] == "4" - assert persisted["source_image_name"] == counts.value.data.subject.source_image_name + assert persisted["source_image_name"] == counts.data.subject.source_image_name diff --git a/tests/integration/test_primary_segmentation_diagnostics_journey.py b/tests/integration/test_primary_segmentation_diagnostics_journey.py index c73c3577a2..cc114b48d4 100644 --- a/tests/integration/test_primary_segmentation_diagnostics_journey.py +++ b/tests/integration/test_primary_segmentation_diagnostics_journey.py @@ -307,14 +307,14 @@ def step(func, name, kwargs): store = context.runtime_value_store (primary_record,) = store.find(name="Nuclei", axis_id="A01") (secondary_record,) = store.find(name="Cells", axis_id="A01") - source_metadata = primary_record.value.data.metadata + source_metadata = primary_record.data.metadata assert ( - np.count_nonzero(object_label_dense_array(secondary_record.value.data)) - >= np.count_nonzero(object_label_dense_array(primary_record.value.data)) + np.count_nonzero(object_label_dense_array(secondary_record.data)) + >= np.count_nonzero(object_label_dense_array(primary_record.data)) > 0 ) - primary_labels = object_label_dense_array(primary_record.value.data) - secondary_labels = object_label_dense_array(secondary_record.value.data) + primary_labels = object_label_dense_array(primary_record.data) + secondary_labels = object_label_dense_array(secondary_record.data) np.testing.assert_array_equal( np.unique(primary_labels), np.unique(secondary_labels) ) @@ -337,10 +337,10 @@ def step(func, name, kwargs): ) (options,) = spec.materialization.outputs (plane,) = MaterializationInput.from_runtime_slice_projected_value( - record.value.data, options + record.data, options ).items np.testing.assert_array_equal(tifffile.imread(saved_path), plane.data) - metadata = image_payload_metadata(record.value.data) + metadata = image_payload_metadata(record.data) # Sidecars have their own runtime alias, retaining the same source # address and pixel contributors as the primary object payload. assert metadata.source_provenance.scalar_source_identity == ( @@ -349,14 +349,14 @@ def step(func, name, kwargs): assert metadata.source_image_provenance_planes.as_contributors().identity == ( source_metadata.source_image_provenance_planes.as_contributors().identity ) - persisted.append(record.value.data) + persisted.append(record.data) diagnostics = PrimaryObjectDiagnosticPlanes(*persisted) np.testing.assert_array_equal( - diagnostics.unedited_objects.data, primary_record.value.data.unedited_labels + diagnostics.unedited_objects.data, primary_record.data.unedited_labels ) np.testing.assert_array_equal( diagnostics.small_removed_objects.data, - primary_record.value.data.small_removed_labels, + primary_record.data.small_removed_labels, ) # A memory-backed first step still owns persistent image artifacts. Later diff --git a/tests/integration/test_source_store_code_mode_zmq.py b/tests/integration/test_source_store_code_mode_zmq.py index f8858301d9..749b273b4a 100644 --- a/tests/integration/test_source_store_code_mode_zmq.py +++ b/tests/integration/test_source_store_code_mode_zmq.py @@ -42,7 +42,7 @@ SourceFilterSubject, SourceSelector, ) -from openhcs.core.source_metadata import SourceMetadataRoleView +from openhcs.core.source_metadata import SourceMetadataFields from openhcs.core.steps.function_step import FunctionStep from openhcs.microscopes.bioformats_adapter import ( BioFormatsAdapterUnavailableError, @@ -316,9 +316,7 @@ def test_code_mode_and_zmq_wire_preserve_mixed_store_sources( } for alias, (source_path, pixels) in stores.items(): virtual_path, record = records_by_alias[alias] - filter_paths = SourceMetadataRoleView( - record.source_metadata - ).source_filter_paths() + filter_paths = SourceMetadataFields.source_filter_paths(record.source_metadata) assert source_path.name in filter_paths assert str(source_path) in filter_paths np.testing.assert_array_equal( diff --git a/tests/unit/agent/test_agent_services.py b/tests/unit/agent/test_agent_services.py index 9dbec7888e..0ca97d73aa 100644 --- a/tests/unit/agent/test_agent_services.py +++ b/tests/unit/agent/test_agent_services.py @@ -324,6 +324,11 @@ def __init__(self) -> None: def endpoint_handshake(self): return None + def submit_prepared_pipeline(self, request, *, timeout_ms=OPENHCS_ZMQ_CONFIG.execution_submission_timeout_ms): + if request.compile_control.compile_only: + return self.submit_compile(request, timeout_ms=timeout_ms) + return self.submit_pipeline(request, timeout_ms=timeout_ms) + def submit_compile( self, submission, @@ -3135,13 +3140,13 @@ def test_execution_session_service_submits_compile_and_execution_jobs( ("compile", OPENHCS_ZMQ_CONFIG.execution_submission_timeout_ms), ("execute", OPENHCS_ZMQ_CONFIG.execution_submission_timeout_ms), ] - assert fake_client.compile_submissions[0].plate_id == str(tmp_path.resolve()) + assert fake_client.compile_submissions[0].identity.plate_id == str(tmp_path.resolve()) assert ( session.pipeline_config_id == pipeline_service.get_pipeline(pipeline_ref).pipeline_config_id ) assert ( - fake_client.compile_submissions[0].pipeline_document.pipeline_config + PipelineDocumentAuthority.from_source(fake_client.compile_submissions[0].pipeline_code).pipeline_config == pipeline_service.to_pipeline_document(pipeline_ref).pipeline_config ) assert fake_client.status_requests[0] == ( @@ -3155,11 +3160,11 @@ def test_execution_session_service_submits_compile_and_execution_jobs( assert len(fake_client.status_requests) == 1 assert fake_client.disconnect_count == 1 assert ( - fake_client.execution_submissions[0].compile_artifact_id + fake_client.execution_submissions[0].compile_control.compile_artifact_id == _ExecutionTestId.COMPILE ) - assert type(fake_client.compile_submissions[0].pipeline_steps) is list - assert len(fake_client.compile_submissions[0].pipeline_steps) == 1 + assert type(PipelineDocumentAuthority.from_source(fake_client.compile_submissions[0].pipeline_code).pipeline_steps) is list + assert len(PipelineDocumentAuthority.from_source(fake_client.compile_submissions[0].pipeline_code).pipeline_steps) == 1 assert not hasattr(fake_client.compile_submissions[0], "submission_pipeline") @@ -3378,11 +3383,9 @@ def test_execution_session_service_preserves_pipeline_source_document( execution_service.submit_compile(session_ref.session_id) submission = fake_client.compile_submissions[0] - assert submission.pipeline_document.original_source == pipeline_source - assert submission.pipeline_code() == pipeline_source - assert submission.pipeline_steps == [] - assert submission.pipeline_config == pipeline_config - assert submission.pipeline_code() == pipeline_source + assert submission.pipeline_code == pipeline_source + assert PipelineDocumentAuthority.from_source(submission.pipeline_code).pipeline_steps == [] + assert PipelineDocumentAuthority.from_source(submission.pipeline_code).pipeline_config == pipeline_config assert not hasattr(submission, "pipeline_steps_boundary") @@ -3895,8 +3898,8 @@ def test_pipeline_source_session_uses_prepared_execution_plate(tmp_path: Path): assert session.selected_pipeline_path is None job = service.submit_execution(session_ref.session_id) assert job.server_execution_id == _ExecutionTestId.EXECUTE - assert fake_client.execution_submissions[0].execution_plate_id == str(prepared) - assert fake_client.execution_submissions[0].selected_pipeline_path is None + assert fake_client.execution_submissions[0].identity.execution_plate_id == str(prepared) + assert fake_client.execution_submissions[0].identity.selected_pipeline_path is None with pytest.raises(AgentPathPolicyError, match="outside allowed roots"): service.create_session_from_pipeline_source_request( @@ -3951,7 +3954,7 @@ def get_status( completed = service.require_completed_pipeline_execution(job.job_id) - assert completed.submission is fake_client.execution_submissions[0] + assert completed.request is fake_client.execution_submissions[0] assert completed.record.start_time == 10.0 assert completed.record.end_time == 12.0 assert completed.record.results_summary == {"output_plate_root": str(tmp_path)} @@ -4015,8 +4018,9 @@ def test_execution_session_service_reports_nested_runtime_status( ): fake_client = _EnvelopeStatusExecutionClient() fake_client.progress_by_execution_id[_ExecutionTestId.COMPILE] = ( - ExecutionProgressObservation.first( - { + ExecutionProgressObservation( + sequence=1, + event={ "execution_id": _ExecutionTestId.COMPILE, "phase": "compile", "status": "running", diff --git a/tests/unit/agent/test_callable_artifact_reference.py b/tests/unit/agent/test_callable_artifact_reference.py index 97e8911296..965d416f87 100644 --- a/tests/unit/agent/test_callable_artifact_reference.py +++ b/tests/unit/agent/test_callable_artifact_reference.py @@ -47,7 +47,7 @@ RuntimePlaneAxis, RuntimePlaneAxisValueProjection, ) -from openhcs.core.steps.function_runtime import FunctionOutputContextStrategy + from openhcs.processing.custom_functions import manager as custom_manager from openhcs.processing.materialization import materialize from polystore.disk import DiskStorageBackend @@ -306,8 +306,8 @@ def test_plate_reference_prepares_compiles_and_runs_in_original_parent( context = plate["_plate_context"](axis_id, (plan,)) plate["_record_measurements"](context, name=source.name, path=path, count=0) record = context.runtime_value_store.values()[0] - assert isinstance(record.value.data, MeasurementTable) - record.value.data.rows = reference_namespace["inspect_label_fixture"](fixture)[2] + assert isinstance(record.data, MeasurementTable) + record.data.rows = reference_namespace["inspect_label_fixture"](fixture)[2] plate["_record_measurements"]( context, name="unrelated_rows", path=f"/memory/{axis_id}/unrelated", count=99, ) @@ -319,7 +319,7 @@ def test_plate_reference_prepares_compiles_and_runs_in_original_parent( if record.key.name == output.name ) assert len(summaries) == 1 # one parent result, not one execution per axis - table = summaries[0].value.data + table = summaries[0].data assert summaries[0].key.artifact_type is SpecialArtifactType assert isinstance(table, DataclassMeasurementColumnarRows) assert table.row_mappings() == ( @@ -373,9 +373,7 @@ def test_reference_retains_plane_domain_until_raw_numpy_invocation( plane_index=None, axis_size=plane_count, ) ) - label_payload = FunctionOutputContextStrategy.for_context( - ObjectLabelsArtifactType, - ).contextualize(stack, labels, None, projection) + label_payload = ObjectLabelsArtifactType.contextualize_output(stack, labels, None, projection) assert isinstance(label_payload, ObjectLabelPayload) np.testing.assert_array_equal(label_payload.labels, stack.data) assert label_payload.plane_axis is ( @@ -393,9 +391,7 @@ def test_reference_retains_plane_domain_until_raw_numpy_invocation( plane_axis=RuntimePlaneAxis.RUNTIME_SLICE, ).payload_with(stack.data[:, :-1, :]) with pytest.raises(ValueError, match="Object-label spatial shape"): - FunctionOutputContextStrategy.for_context( - ObjectLabelsArtifactType, - ).contextualize(stack, wrong_spatial_shape, None, projection) + ObjectLabelsArtifactType.contextualize_output(stack, wrong_spatial_shape, None, projection) assert not manager.storage_dir.exists() diff --git a/tests/unit/agent/test_cold_inspection_feedback.py b/tests/unit/agent/test_cold_inspection_feedback.py index 57db9b0f62..32d6a7d586 100644 --- a/tests/unit/agent/test_cold_inspection_feedback.py +++ b/tests/unit/agent/test_cold_inspection_feedback.py @@ -63,7 +63,7 @@ def test_new_gateway_hook_cooperates_in_both_mros_before_terminal_result(tmp_pat """Independent audit capability needs no edits to service or MCP consumers.""" identity = ContextVar("cold-feedback-request", default="outside") calls, messages = [], [] - emitted = threading.Event() + compile_entered = threading.Event() release = threading.Event() error = ValueError("original declared compiler error") @@ -77,8 +77,8 @@ def compile(self, request): class DeclaredGateway(_FakeCompileInspectionGateway): def _compile(self, request): assert threading.current_thread() is threading.main_thread() + compile_entered.set() self.emit_progress(request) - emitted.set() assert release.wait(3), "Actual stage relay was not delivered during held work" if fails: raise error @@ -97,7 +97,7 @@ async def report_progress(self, progress, total=None, message=None): assert threading.current_thread() is not threading.main_thread() messages.append(message) if "compile: running: A01: compilation" in message: - assert emitted.is_set() + assert compile_entered.is_set() release.set() executor = McpTransportExecutor() @@ -105,7 +105,7 @@ async def report_progress(self, progress, total=None, message=None): try: for gateway_type in (Before, After): release.clear() - emitted.clear() + compile_entered.clear() gateway = gateway_type() service = ExecutionSessionService( path_policy=AgentPathPolicy.with_roots( diff --git a/tests/unit/cellprofiler_runtime_test_support.py b/tests/unit/cellprofiler_runtime_test_support.py index c387ce86f4..f5bcb02e8f 100644 --- a/tests/unit/cellprofiler_runtime_test_support.py +++ b/tests/unit/cellprofiler_runtime_test_support.py @@ -29,8 +29,8 @@ from openhcs.core.source_matching import SourceImageSetIdentityPolicy from openhcs.core.steps.function_output_identity import FunctionOutputIdentityCache from openhcs.interop.cellprofiler.runtime.adapter import CellProfilerRuntimeAdapter -from openhcs.interop.cellprofiler.runtime.object_measurement_tables import ( - ObjectMeasurementTableIndex, +from openhcs.core.measurement_feature_queries import ( + ColumnarMeasurementTableSchema, ) from openhcs.microscopes.imagexpress import ImageXpressFilenameParser @@ -126,14 +126,10 @@ def object_measurement_tables_for_test( ) -> tuple[MeasurementTable, ...]: """Query object measurement tables through their nominal index owner.""" - index = ObjectMeasurementTableIndex.from_tables( - adapter.measurement_tables( - group_key=group_key, - match_group=match_group, - ) + return ColumnarMeasurementTableSchema.tables_for_object( + adapter.measurement_tables(group_key=group_key, match_group=match_group), + object_name, ) - tables = index.for_object(object_name) - return () if tables is None else tables def runtime_adapter_request_for_test( diff --git a/tests/unit/pyqt_gui/test_plate_manager_widget.py b/tests/unit/pyqt_gui/test_plate_manager_widget.py index 44e9097966..f90c0362a7 100644 --- a/tests/unit/pyqt_gui/test_plate_manager_widget.py +++ b/tests/unit/pyqt_gui/test_plate_manager_widget.py @@ -46,7 +46,6 @@ ) from openhcs.core.input_workspace import InputWorkspacePreparationResult from openhcs.core.orchestrator.orchestrator import PipelineOrchestrator -from openhcs.core.pipeline.step_snapshot import StepSnapshot from openhcs.core.pipeline_document import PipelineDocumentAuthority from openhcs.core.progress import ( ProgressEvent, @@ -1085,27 +1084,19 @@ def test_cellprofiler_import_applies_pipeline_config_to_orchestrator_state( ) plate_state = ObjectStateRegistry.get_by_scope(plate_scope) - editor_state = PipelineObjectStateBinding.editor_state_for_plate( - plate_scope - ) + editor_state = PipelineObjectStateBinding.editor_state_for_plate(plate_scope) assert plate_state is not None assert widget.plate_configs[plate_scope] == pipeline_config assert ( - plate_state.get_saved_resolved_value( - "source_bindings_config.match_plan" - ) + plate_state.get_saved_resolved_value("source_bindings_config.match_plan") == match_plan ) step_scope_id = editor_state.step_scope_ids[0] step_state = ObjectStateRegistry.get_by_scope(step_scope_id) assert step_state is not None - snapshot = StepSnapshot( - index=0, - scope_id=step_state.scope_id, - step=step_state.to_saved_resolved_object(), - ) - assert snapshot.step.source_bindings.match_plan == match_plan + snapshot = step_state.to_saved_resolved_object() + assert snapshot.source_bindings.match_plan == match_plan finally: close_widget(widget) ObjectStateRegistry.clear() diff --git a/tests/unit/test_aligned_image_payload_device.py b/tests/unit/test_aligned_image_payload_device.py index 4e0d4c2bb9..db18f9fa59 100644 --- a/tests/unit/test_aligned_image_payload_device.py +++ b/tests/unit/test_aligned_image_payload_device.py @@ -37,3 +37,33 @@ def test_image_bundle_stacks_on_the_payload_framework_device(monkeypatch) -> Non assert context.compose_unmasked(payloads) == "stacked" assert observed == [(payloads, MemoryType.CUPY.value, 7)] + + +def test_independent_cohort_copy_retains_nested_named_bundle_domains(): + from openhcs.core.aligned_image_payload import ( + AlignedImageSliceContext, AlignedImageStack, ImageOutputBundle, + ImagePayloadStackComposition, + ) + from openhcs.core.runtime_image_values import ( + ImagePayloadMetadata, image_payload_data, image_payload_mask, + ) + + pixels = np.arange(12, dtype=np.float32).reshape(3, 4) + mask = np.ones((3, 4), dtype=bool) + payload = ImagePayloadMetadata(source_image_names=("Canonical",)).payload_with(pixels, mask) + context = AlignedImageSliceContext.main_flow("Canonical") + named = ImageOutputBundle((payload,), (context,)) + nested = AlignedImageStack((named,)) + copied = ImagePayloadStackComposition.copy_whole_image( + nested, memory_type="numpy", device_id=None, + ) + assert type(copied) is AlignedImageStack + assert type(copied.slices[0]) is ImageOutputBundle + assert copied.slices[0].slice_contexts == (context,) + member = copied.slices[0].slices[0] + assert not np.shares_memory(image_payload_data(member), pixels) + assert not np.shares_memory(image_payload_mask(member), mask) + image_payload_data(member)[:] = -1 + image_payload_mask(member)[:] = False + np.testing.assert_array_equal(pixels, np.arange(12).reshape(3, 4)) + assert mask.all() diff --git a/tests/unit/test_aligned_image_payload_registry.py b/tests/unit/test_aligned_image_payload_registry.py index d86066c90b..67411bad17 100644 --- a/tests/unit/test_aligned_image_payload_registry.py +++ b/tests/unit/test_aligned_image_payload_registry.py @@ -1,100 +1,86 @@ from __future__ import annotations +from abc import ABC from collections.abc import Iterator -from typing import Any +import numpy as np import pytest from openhcs.core.aligned_image_payload import ( - AlignedImageStackKwargResolutionStrategy, AlignedImageStackKwargResolver, - ImagePayloadAlignedKwargResolutionStrategy, - NestedAlignedImageStackKwargResolutionStrategy, - ObjectLabelAlignedKwargResolutionStrategy, - PassThroughAlignedKwargResolutionStrategy, - RuntimeSliceAlignedValueKwargResolutionStrategy, - RuntimeSliceProjectableAlignedKwargResolutionStrategy, - TupleAlignedKwargResolutionStrategy, + AlignedImageSliceContext, + ImageOutputBundle, ) +from openhcs.core.runtime_image_values import ( + ImagePayloadMetadata, + ImagePayloadMetadataCarrier, + ImageMetadataPayload, + image_payload_data, +) +from openhcs.core.runtime_object_labels import ObjectLabelSet, ObjectLabelVariantData +from openhcs.core.runtime_object_label_domains import ObjectLabelDomain, ObjectLabelDomainScope +from openhcs.core.runtime_plane_projection import ( + RuntimePlaneAxis, + RuntimePlaneAxisValueProjection, + RuntimeSliceProjectableValue, +) +from openhcs.core.runtime_slice_alignment import RuntimeSliceAlignedValues +from openhcs.core.runtime_slice_projection import ( + RuntimeSliceProjection, + RuntimeSliceProjectionDeclarationError, + RuntimeSliceProjectionStrategy, + ImagePayloadRuntimeSliceProjectionStrategy, + SequenceRuntimeSliceProjectionStrategy, +) + + +def _clear_strategy_caches() -> None: + RuntimeSliceProjectionStrategy.registered_strategy_types.cache_clear() + RuntimeSliceProjectionStrategy.strategy_types_for_nominal_type.cache_clear() + RuntimeSliceProjectionStrategy.strategy_types_for_aligned_kwarg_type.cache_clear() @pytest.fixture -def isolated_strategy_registry() -> ( - Iterator[dict[str, type[AlignedImageStackKwargResolutionStrategy]]] -): - registry = AlignedImageStackKwargResolutionStrategy.__registry__ +def isolated_strategy_registry() -> Iterator[dict[str, type[RuntimeSliceProjectionStrategy]]]: + registry = RuntimeSliceProjectionStrategy.__registry__ snapshot = registry.copy() - AlignedImageStackKwargResolutionStrategy.registered_strategy_types.cache_clear() - AlignedImageStackKwargResolutionStrategy.strategy_types_for_nominal_type.cache_clear() + _clear_strategy_caches() try: yield registry finally: registry.clear() registry.update(snapshot) - AlignedImageStackKwargResolutionStrategy.registered_strategy_types.cache_clear() - AlignedImageStackKwargResolutionStrategy.strategy_types_for_nominal_type.cache_clear() - - -def test_existing_aligned_kwarg_strategies_register_automatically() -> None: - expected = { - TupleAlignedKwargResolutionStrategy, - ImagePayloadAlignedKwargResolutionStrategy, - ObjectLabelAlignedKwargResolutionStrategy, - RuntimeSliceAlignedValueKwargResolutionStrategy, - RuntimeSliceProjectableAlignedKwargResolutionStrategy, - PassThroughAlignedKwargResolutionStrategy, - NestedAlignedImageStackKwargResolutionStrategy, - } - - assert type(AlignedImageStackKwargResolutionStrategy.__registry__) is dict - assert ( - set(AlignedImageStackKwargResolutionStrategy.__registry__.values()) == expected + _clear_strategy_caches() + + +def _resolver(*, axis=RuntimePlaneAxis.RUNTIME_SLICE, size=2, index=1): + return AlignedImageStackKwargResolver( + RuntimePlaneAxisValueProjection.from_selected_plane( + axis=axis, plane_index=index, axis_size=size, + ), ) - assert len(AlignedImageStackKwargResolutionStrategy.__registry__) == len(expected) -def test_dynamic_aligned_kwarg_strategy_registers_at_class_definition( - isolated_strategy_registry: dict[ - str, type[AlignedImageStackKwargResolutionStrategy] - ], -) -> None: +def test_dynamic_aligned_operation_registers_on_existing_projection_family(isolated_strategy_registry): class DynamicKwarg: pass - class DynamicKwargResolutionStrategy(AlignedImageStackKwargResolutionStrategy): + marker = object() + + class DynamicProjectionStrategy(RuntimeSliceProjectionStrategy): value_type = DynamicKwarg - def resolve( - self, - value: Any, - resolver: AlignedImageStackKwargResolver, - ) -> Any: - del resolver - return value - - assert DynamicKwargResolutionStrategy.value_type_label is not None - assert ( - isolated_strategy_registry[DynamicKwargResolutionStrategy.value_type_label] - is DynamicKwargResolutionStrategy - ) - assert ( - type( - AlignedImageStackKwargResolutionStrategy.require_nominal_value( - DynamicKwarg(), - context="dynamic aligned kwarg", - ) - ) - is DynamicKwargResolutionStrategy - ) + def resolve_aligned_kwarg(self, value, resolver): + assert isinstance(value, DynamicKwarg) + assert resolver.projection_axis.axis_size == 2 + return marker + assert DynamicProjectionStrategy.value_type_label is not None + assert isolated_strategy_registry[DynamicProjectionStrategy.value_type_label] is DynamicProjectionStrategy + assert _resolver().resolve(DynamicKwarg()) is marker -def test_aligned_kwarg_strategy_resolution_follows_exact_value_mro( - isolated_strategy_registry: dict[ - str, type[AlignedImageStackKwargResolutionStrategy] - ], -) -> None: - del isolated_strategy_registry +def test_aligned_operation_follows_exact_value_mro(isolated_strategy_registry): class BaseKwarg: pass @@ -104,41 +90,250 @@ class DerivedKwarg(BaseKwarg): class MostDerivedKwarg(DerivedKwarg): pass - class BaseKwargResolutionStrategy(AlignedImageStackKwargResolutionStrategy): + base_marker, derived_marker = object(), object() + + class BaseProjectionStrategy(RuntimeSliceProjectionStrategy): value_type = BaseKwarg - def resolve( - self, - value: Any, - resolver: AlignedImageStackKwargResolver, - ) -> Any: - del resolver - return value + def resolve_aligned_kwarg(self, value, resolver): + return base_marker - class DerivedKwargResolutionStrategy(AlignedImageStackKwargResolutionStrategy): + class DerivedProjectionStrategy(BaseProjectionStrategy): value_type = DerivedKwarg - def resolve( - self, - value: Any, - resolver: AlignedImageStackKwargResolver, - ) -> Any: - del resolver - return value - - assert AlignedImageStackKwargResolutionStrategy.strategy_types_for_nominal_type( - MostDerivedKwarg - ) == ( - DerivedKwargResolutionStrategy, - BaseKwargResolutionStrategy, - PassThroughAlignedKwargResolutionStrategy, + def resolve_aligned_kwarg(self, value, resolver): + return derived_marker + + assert RuntimeSliceProjectionStrategy.strategy_types_for_aligned_kwarg_type(MostDerivedKwarg) == ( + DerivedProjectionStrategy, BaseProjectionStrategy, ) - assert ( - type( - AlignedImageStackKwargResolutionStrategy.require_nominal_value( - MostDerivedKwarg(), - context="MRO-aligned kwarg", - ) - ) - is DerivedKwargResolutionStrategy + assert _resolver().resolve(MostDerivedKwarg()) is derived_marker + + +def test_default_aligned_hook_does_not_steal_projectable_operation_through_mi(isolated_strategy_registry): + class OrdinaryOwner: + pass + + class MixedKwarg(OrdinaryOwner, RuntimeSliceProjectableValue): + def project_runtime_slice(self, slice_index): + pytest.fail("ordinary nominal owner must determine the inner projection") + + marker = object() + + class OrdinaryOnlyProjectionStrategy(RuntimeSliceProjectionStrategy): + value_type = OrdinaryOwner + + def value_for_slice(self, value, context): + assert isinstance(value, MixedKwarg) + assert context.require_plane_index() == 1 + return marker + + ordinary = RuntimeSliceProjectionStrategy.strategy_types_for_nominal_type(MixedKwarg) + aligned = RuntimeSliceProjectionStrategy.strategy_types_for_aligned_kwarg_type(MixedKwarg) + assert ordinary[0] is OrdinaryOnlyProjectionStrategy + assert OrdinaryOnlyProjectionStrategy not in aligned + assert _resolver().resolve(MixedKwarg()) is marker + + +def test_virtual_abc_ties_follow_single_canonical_registry_order(isolated_strategy_registry): + class FirstMember(ABC): + pass + + class SecondMember(ABC): + pass + + class VirtualValue: + pass + + FirstMember.register(VirtualValue) + SecondMember.register(VirtualValue) + first, second = object(), object() + + class FirstProjectionStrategy(RuntimeSliceProjectionStrategy): + value_type = FirstMember + + def value_for_slice(self, value, context): + return first + + def resolve_aligned_kwarg(self, value, resolver): + return first + + class SecondProjectionStrategy(RuntimeSliceProjectionStrategy): + value_type = SecondMember + + def value_for_slice(self, value, context): + return second + + def resolve_aligned_kwarg(self, value, resolver): + return second + + value, resolver = VirtualValue(), _resolver() + assert resolver.resolve(value) is first + assert RuntimeSliceProjection.value_for_slice(value, resolver.projection_axis) is first + key = FirstProjectionStrategy.value_type_label + isolated_strategy_registry[key] = isolated_strategy_registry.pop(key) + _clear_strategy_caches() + assert resolver.resolve(value) is second + assert RuntimeSliceProjection.value_for_slice(value, resolver.projection_axis) is second + + +def test_tuple_recurses_while_list_stays_in_its_original_domain(): + projection = _resolver().projection_axis + elements = [object(), object()] + # A projection declaration has its own meaningful projectable capability. + values = (projection, elements) + result = _resolver().resolve(values) + assert type(result) is tuple + assert result[0].require_plane_index() == 1 + assert result[1] is elements + assert _resolver().resolve(elements) is elements + + +def test_unknown_aligned_value_passes_through_but_ordinary_projection_stays_strict(): + class Unknown: + pass + + value = Unknown() + assert _resolver().resolve(value) is value + with pytest.raises(RuntimeSliceProjectionDeclarationError, match="no nominal strategy"): + RuntimeSliceProjection.value_for_slice(value, _resolver().projection_axis) + + +def test_broad_image_carrier_aligned_operation_preserves_declared_stack(): + class BroadCarrier(ImagePayloadMetadataCarrier): + def __init__(self): + self.pixels = np.ones((2, 3, 4), dtype=np.float32) + self._metadata = ImagePayloadMetadata(plane_axis=RuntimePlaneAxis.RUNTIME_SLICE) + + def image_data(self): + return self.pixels + + @property + def metadata(self): + return self._metadata + + value = BroadCarrier() + assert _resolver().resolve(value) is value + assert value.image_data().shape == (2, 3, 4) + with pytest.raises(RuntimeSliceProjectionDeclarationError, match="no nominal strategy"): + RuntimeSliceProjection.value_for_slice(value, _resolver().projection_axis) + + +def test_image_aligned_operation_does_not_remove_runtime_plane_axis(): + value = ImagePayloadMetadata(plane_axis=RuntimePlaneAxis.RUNTIME_SLICE).payload_with( + np.arange(24, dtype=np.float32).reshape(2, 3, 4), + ) + resolver = _resolver() + assert resolver.resolve(value) is value + ordinary = RuntimeSliceProjection.value_for_slice(value, resolver.projection_axis) + np.testing.assert_array_equal(image_payload_data(ordinary), image_payload_data(value)[1]) + assert image_payload_data(ordinary).shape == (3, 4) + + +def test_image_output_bundle_aligned_operation_selects_outer_member_then_recurses(): + first, second = tuple( + ImagePayloadMetadata(plane_axis=RuntimePlaneAxis.RUNTIME_SLICE).payload_with( + np.full((2, 3, 4), index, dtype=np.float32), + ) for index in (1, 2) + ) + bundle = ImageOutputBundle( + (first, second), + tuple(AlignedImageSliceContext.independent_main_flow(name) for name in ("First", "Second")), + ) + resolver = _resolver() + assert resolver.resolve(bundle) is second + assert image_payload_data(resolver.resolve(bundle)).shape == (2, 3, 4) + ordinary = RuntimeSliceProjection.value_for_slice(bundle, resolver.projection_axis) + assert isinstance(ordinary, ImageOutputBundle) + assert [image_payload_data(value).shape for value in ordinary.slices] == [(3, 4), (3, 4)] + + +@pytest.mark.parametrize("axis", (RuntimePlaneAxis.RUNTIME_SLICE, RuntimePlaneAxis.SOURCE_BINDING)) +def test_aligned_capability_owns_outer_count_for_both_declared_axes(axis): + first, second = object(), object() + value = RuntimeSliceAlignedValues((first, second)) + resolver = _resolver(axis=axis) + assert resolver.resolve(value) is second + if axis is RuntimePlaneAxis.SOURCE_BINDING: + assert RuntimeSliceProjection.value_for_slice(value, resolver.projection_axis) is value + with pytest.raises(ValueError, match="count must exactly match"): + _resolver(axis=axis, size=3).resolve(value) + + +def test_object_label_count_is_checked_before_projection_and_spatial_alignment(monkeypatch): + labels = ObjectLabelSet( + name="Labels", variant_data=ObjectLabelVariantData(labels=np.ones((2, 3, 4), dtype=np.int32)), + plane_axis=RuntimePlaneAxis.RUNTIME_SLICE, + domain=ObjectLabelDomain( + declared_object_id_domains=((1,), (1,)), + scope=ObjectLabelDomainScope.PLANE, + ), ) + monkeypatch.setattr(RuntimeSliceProjection, "value_for_slice", lambda *_args: pytest.fail("cardinality comes first")) + monkeypatch.setattr(AlignedImageStackKwargResolver, "resolve_source_spatial_value", lambda *_args: pytest.fail("cardinality comes before spatial alignment")) + with pytest.raises(ValueError, match="cardinality must exactly match"): + _resolver(size=3).resolve(labels) + + +def test_narrower_image_owner_inherits_operation_scope_from_its_own_declaration(isolated_strategy_registry): + class DerivedImage(ImageMetadataPayload): + pass + + marker = object() + + class DerivedImageProjectionStrategy(ImagePayloadRuntimeSliceProjectionStrategy): + value_type = DerivedImage + + def resolve_aligned_kwarg(self, value, resolver): + return marker + + value = DerivedImage( + data=np.arange(24, dtype=np.float32).reshape(2, 3, 4), + metadata=ImagePayloadMetadata(plane_axis=RuntimePlaneAxis.RUNTIME_SLICE), + ) + assert RuntimeSliceProjectionStrategy.strategy_types_for_aligned_kwarg_type(DerivedImage)[0] is DerivedImageProjectionStrategy + assert RuntimeSliceProjectionStrategy.strategy_types_for_nominal_type(DerivedImage)[0] is DerivedImageProjectionStrategy + assert _resolver().resolve(value) is marker + ordinary = RuntimeSliceProjection.value_for_slice(value, _resolver().projection_axis) + np.testing.assert_array_equal(image_payload_data(ordinary), value.data[1]) + + +def test_narrower_sequence_owner_can_declare_aligned_list_capability(isolated_strategy_registry): + class DeclaredList(list): + pass + + class DeclaredListProjectionStrategy(SequenceRuntimeSliceProjectionStrategy): + value_type = DeclaredList + + resolver = _resolver() + projection = resolver.projection_axis + original = DeclaredList([projection, object()]) + assert RuntimeSliceProjectionStrategy.strategy_types_for_aligned_kwarg_type(DeclaredList)[0] is DeclaredListProjectionStrategy + aligned = resolver.resolve(original) + assert isinstance(aligned, tuple) + assert aligned[0].require_plane_index() == 1 + assert aligned[1] is original[1] + plain = list(original) + assert resolver.resolve(plain) is plain + + +def test_derived_dispatch_cache_uses_the_same_explicit_registry_mutation_boundary(isolated_strategy_registry): + class DynamicKwarg: + pass + + resolver, value = _resolver(), DynamicKwarg() + assert resolver.resolve(value) is value + marker = object() + + class DynamicProjectionStrategy(RuntimeSliceProjectionStrategy): + value_type = DynamicKwarg + + def resolve_aligned_kwarg(self, value, resolver): + return marker + + _clear_strategy_caches() + assert resolver.resolve(value) is marker + before = RuntimeSliceProjectionStrategy.strategy_types_for_aligned_kwarg_type.cache_info() + assert resolver.resolve(value) is marker + after = RuntimeSliceProjectionStrategy.strategy_types_for_aligned_kwarg_type.cache_info() + assert after.hits == before.hits + 1 diff --git a/tests/unit/test_aligned_main_flow_projection.py b/tests/unit/test_aligned_main_flow_projection.py index b4e4e05b03..0bc40ba4da 100644 --- a/tests/unit/test_aligned_main_flow_projection.py +++ b/tests/unit/test_aligned_main_flow_projection.py @@ -52,6 +52,62 @@ def _input_ref( return ArtifactSpec.input(name, artifact_type).ref() +@pytest.mark.parametrize("carrier_type", (AlignedImageStack, ImageOutputBundle)) +def test_aligned_stack_binds_complete_declared_output_roster( + carrier_type: type[AlignedImageStack], +) -> None: + first = ArtifactSpec.output("First", ImageArtifactType) + second = ArtifactSpec.output("Second", ImageArtifactType) + first_context, second_context = AlignedImageSliceContext.main_flow_for_artifact_specs( + (first, second) + ) + first_value = object() + carrier = carrier_type( + (None, first_value), + (second_context, first_context), + ) + + assert carrier.output_values_for_artifact_specs((first, second)) == { + first.ref(): first_value, + second.ref(): None, + } + with pytest.raises(ValueError, match="duplicate named contexts"): + carrier.output_values_for_artifact_specs((first, first)) + + +@pytest.mark.parametrize( + ("contexts", "message"), + ( + ((), "require exact AlignedImageStack"), + (("first", "first"), "contains duplicate context"), + (("first",), "does not carry every declared output"), + (("first", "unknown"), "context is not declared"), + (("first", "non-main"), "contains a non-main-flow"), + ), +) +def test_aligned_stack_rejects_incomplete_or_conflicting_output_rosters( + contexts: tuple[str, ...], + message: str, +) -> None: + first = ArtifactSpec.output("First", ImageArtifactType) + second = ArtifactSpec.output("Second", ImageArtifactType) + first_context, second_context = AlignedImageSliceContext.main_flow_for_artifact_specs( + (first, second) + ) + selected = { + "first": first_context, + "unknown": replace(second_context, output_key="Unknown"), + "non-main": replace(second_context, output_kind="artifact"), + } + carrier = AlignedImageStack( + tuple(object() for _ in contexts) if contexts else (object(), object()), + tuple(selected[name] for name in contexts), + ) + + with pytest.raises(ValueError, match=message): + carrier.output_values_for_artifact_specs((first, second)) + + def _named_carrier() -> tuple[AlignedImageStack, np.ndarray, np.ndarray]: mcherry = np.full((3, 4), 3.0, dtype=np.float32) gfp = np.full((3, 4), 2.0, dtype=np.float32) diff --git a/tests/unit/test_aligned_output_projection.py b/tests/unit/test_aligned_output_projection.py index 191f1c0a98..54f7462a09 100644 --- a/tests/unit/test_aligned_output_projection.py +++ b/tests/unit/test_aligned_output_projection.py @@ -51,13 +51,13 @@ def counted(payload): ), ) ) - result = runtime._validate_and_unstack(bundle, None) + result = runtime._project_output_slices(bundle, []) assert len(calls) == 2 assert calls[0] is payloads[0] and calls[1] is payloads[1] - assert result.slice_contexts == (contexts[0],) * 3 + (contexts[1],) * 2 + assert tuple(context for _payload, context in result) == (contexts[0],) * 3 + (contexts[1],) * 2 assert len(result) == 5 - for index, payload in enumerate(result.slices): + for index, payload in enumerate(payload for payload, _context in result): source = first if index < 3 else second plane = index if index < 3 else index - 3 np.testing.assert_array_equal(image_payload_data(payload), source[plane]) diff --git a/tests/unit/test_artifact_input_parameter_normalization.py b/tests/unit/test_artifact_input_parameter_normalization.py index b2fe6c88ac..45ce2d4f71 100644 --- a/tests/unit/test_artifact_input_parameter_normalization.py +++ b/tests/unit/test_artifact_input_parameter_normalization.py @@ -4,13 +4,14 @@ import pytest -from openhcs.core.artifacts import ArtifactSpec, SpecialArtifactType +from openhcs.core.artifacts import ArtifactSpec, ObjectLabelsArtifactType, SpecialArtifactType from openhcs.core.callable_contract import CallableContract from openhcs.core.function_patterns import compile_function_pattern from openhcs.core.invocation_artifacts import ( InvocationContractPlan, InvocationContractProvider, ) +from openhcs.core.runtime_adapters import runtime_adapter from openhcs.core.pipeline.function_contracts import ( artifact_inputs, special_input_names_from_callable, @@ -61,6 +62,28 @@ def consume(image, *, labels=None): assert received == [None] +@pytest.mark.parametrize("managed", [False, True]) +def test_scalar_artifact_roster_cardinality_belongs_to_its_runtime_binder(managed) -> None: + inputs = tuple( + ArtifactSpec.input(name, ObjectLabelsArtifactType, parameter_name="labels") + for name in ("Nuclei", "Cells") + ) + + @runtime_adapter("runtime", lambda request: object(), manages_artifact_inputs=managed) + @artifact_inputs(*inputs) + def consume(image, *, labels, runtime): + raise AssertionError("Contract admission must not execute the callable") + + if not managed: + with pytest.raises(ValueError, match="labels.*multiple exact artifact occurrences"): + compile_function_pattern(consume, {}, {}) + return + compiled = compile_function_pattern(consume, {}, {}) + (invocation,) = compiled.default_group.invocations + assert invocation.contract.artifact_inputs.specs == inputs + assert invocation.contract.artifact_input_parameter_names == ("labels",) + + def test_artifact_spec_only_parameter_declaration_compiles() -> None: labels = ArtifactSpec.input( "StoredLabels", diff --git a/tests/unit/test_artifact_output_ownership.py b/tests/unit/test_artifact_output_ownership.py index 34dd5785d4..04a0491855 100644 --- a/tests/unit/test_artifact_output_ownership.py +++ b/tests/unit/test_artifact_output_ownership.py @@ -1,5 +1,7 @@ """Compile invariants apply independently of artifact recording ownership.""" +from openhcs.core.pipeline.compilation_session import ResolvedPipelineDefinition + from dataclasses import replace from types import SimpleNamespace @@ -192,7 +194,12 @@ def measure(image, labels=None, *, runtime): compile_function_pattern(measure, {}, {}) # Output obligations remain mandatory once input selection is unambiguous. - with pytest.raises(ValueError, match="multiple measurement subjects"): + obligation = ( + "declared measurement_feature_owner" + if output_policy is CellProfilerRecordedArtifactOutputPolicy + else "multiple measurement subjects" + ) + with pytest.raises(ValueError, match=obligation): CallableContract.from_callable(measure).validate_artifact_output_declarations() @@ -295,6 +302,42 @@ def measure(image, *, runtime): assert compiled is not None +@pytest.mark.parametrize("policy", [ + NativeReturnArtifactOutputPolicy, + AdapterRecordedArtifactOutputPolicy, + CellProfilerRecordedArtifactOutputPolicy, +]) +def test_measurement_row_owner_controls_named_object_roster_admission(policy): + from openhcs.core.artifacts import ArtifactSpecRelation + from openhcs.processing.backends.cellprofiler.intensity import MeasureObjectIntensityModule + + objects = tuple( + ArtifactSpec.input(name, ObjectLabelsArtifactType) + for name in ("Nuclei", "Cells") + ) + measurements = ArtifactSpec.output( + "Measurements", MeasurementsArtifactType, + relations=tuple(ObjectMeasurementSubjectRelation(spec.ref()) for spec in objects), + measurement_feature_owner=MeasureObjectIntensityModule, + ) + + @runtime_adapter("runtime", lambda request: object(), artifact_output_policy=policy) + @artifact_inputs(*objects) + @artifact_outputs(measurements) + def measure(image, *, runtime): + raise AssertionError("Compile admission must not execute a callable") + + if policy is not CellProfilerRecordedArtifactOutputPolicy: + with pytest.raises(ValueError, match="multiple measurement subjects"): + compile_function_pattern(measure, {}, {}) + return + compiled = compile_function_pattern(measure, {}, {}) + subjects = ArtifactSpecRelation.measurement_subjects_for_output(measurements) + assert tuple(subject.name for subject in subjects) == ("Nuclei", "Cells") + assert len({subject.row_identity_domain for subject in subjects}) == 2 + assert compiled.default_group.invocations[0].contract.artifact_outputs.specs == (measurements,) + + def test_real_cellprofiler_declaration_compiles_without_a_table_wide_subject(): """The real module/provider declares the owner, not a compiler exemption.""" from openhcs.core.compiled_step_plan import CompiledStepPlan @@ -302,7 +345,6 @@ def test_real_cellprofiler_declaration_compiles_without_a_table_wide_subject(): from openhcs.core.context.processing_context import ProcessingContext from openhcs.core.invocation_artifacts import ArtifactDeclarationStepContext from openhcs.core.pipeline.compilation_session import CompilationSession - from openhcs.core.pipeline.step_snapshot import StepSnapshot from openhcs.core.source_bindings import ( NamedSourceBinding, StepSourceBindingsConfig, @@ -356,11 +398,12 @@ def test_real_cellprofiler_declaration_compiles_without_a_table_wide_subject(): ), }, ), - steps=[step], orchestrator=SimpleNamespace(pipeline_config=PipelineConfig()), global_config=GlobalPipelineConfig(), - step_state_map={0: object()}, - snapshots=(StepSnapshot(index=0, scope_id="test::cp-output-owner", step=step),), + pipeline=ResolvedPipelineDefinition( + steps=(step,), + step_state_map={0: SimpleNamespace(scope_id="plate::functionstep_0")}, + ), ) provider = CellProfilerInvocationContractProviderFactory.provider_for_session( session diff --git a/tests/unit/test_artifact_spec_collection.py b/tests/unit/test_artifact_spec_collection.py index db6e37dd1c..6b7daab570 100644 --- a/tests/unit/test_artifact_spec_collection.py +++ b/tests/unit/test_artifact_spec_collection.py @@ -1,5 +1,7 @@ from __future__ import annotations +from dataclasses import replace + import pytest from openhcs.core.artifacts import ( @@ -9,9 +11,12 @@ ArtifactSpecCollection, GroupLineageSourceRelation, ImageArtifactType, + InputImageSetContextSourceRelation, + InputStackBroadcastSourceRelation, MainFlowPlaneProjectionOutputSpec, MeasurementsArtifactType, ObjectLabelsArtifactType, + SpatialGraphArtifactType, ) from openhcs.core.runtime_measurements import RuntimeMeasurementFeatureOwner @@ -51,6 +56,83 @@ def test_artifact_spec_collection_queries_ordered_artifact_contracts() -> None: assert collection.by_name_and_artifact_type("Nuclei", ImageArtifactType) is None +def test_stack_broadcast_indices_use_exact_ordered_occurrences() -> None: + primary = ArtifactSpec.input("Primary", ImageArtifactType) + secondary = ArtifactSpec.input( + "Secondary", + ImageArtifactType, + relations=(InputStackBroadcastSourceRelation(source=primary.ref()),), + ) + unrelated = ArtifactSpec.input("Primary", ObjectLabelsArtifactType) + + assert ArtifactSpecCollection(()).stack_broadcast_source_indices() == () + assert ArtifactSpecCollection( + (secondary, unrelated, primary) + ).stack_broadcast_source_indices() == (2, None, None) + + for specs in ((secondary,), (primary, secondary, primary)): + with pytest.raises(ValueError, match="exactly one active occurrence"): + ArtifactSpecCollection(specs).stack_broadcast_source_indices() + + self_broadcast = replace( + primary, + relations=(InputStackBroadcastSourceRelation(source=primary.ref()),), + ) + with pytest.raises(ValueError, match="cannot broadcast from itself"): + ArtifactSpecCollection((self_broadcast,)).stack_broadcast_source_indices() + + other = ArtifactSpec.input("Other", ImageArtifactType) + multiple_owners = replace( + secondary, + relations=( + InputStackBroadcastSourceRelation(source=primary.ref()), + InputStackBroadcastSourceRelation(source=other.ref()), + ), + ) + with pytest.raises(ValueError, match="multiple stack-broadcast owners"): + ArtifactSpecCollection( + (primary, other, multiple_owners) + ).stack_broadcast_source_indices() + + +@pytest.mark.parametrize( + "artifact_type", (ImageArtifactType, ObjectLabelsArtifactType, SpatialGraphArtifactType) +) +def test_input_image_set_context_does_not_regroup_or_broadcast(artifact_type) -> None: + image = ArtifactSpec.input("Actin", ImageArtifactType) + relation = InputImageSetContextSourceRelation(image.ref()) + target = ArtifactSpec.input("Subject", artifact_type, relations=(relation,)) + + assert target.source_context_sources() == (image.ref(),) + assert target.group_scope_sources() == () + assert target.source_stack_scope_sources() == () + assert target.stack_broadcast_sources() == () + assert relation.dependency_refs() == (image.ref(),) + assert target.for_plan_type(ArtifactOutputPlan).relations == () + + +@pytest.mark.parametrize( + "source", + ( + ArtifactSpec.output("Actin", ImageArtifactType), + ArtifactSpec.input("Cells", ObjectLabelsArtifactType), + ), +) +def test_input_image_set_context_requires_an_input_image_source(source) -> None: + with pytest.raises(ValueError, match="requires an input image source"): + InputImageSetContextSourceRelation(source.ref()) + + +def test_input_image_set_context_rejects_output_and_contextless_targets() -> None: + relation = InputImageSetContextSourceRelation( + ArtifactSpec.input("Actin", ImageArtifactType).ref() + ) + with pytest.raises(ValueError, match="target plan role"): + ArtifactSpec.output("Cells", ObjectLabelsArtifactType, relations=(relation,)) + with pytest.raises(ValueError, match="carrying source-image context"): + ArtifactSpec.input("Measurements", MeasurementsArtifactType, relations=(relation,)) + + def test_artifact_spec_collection_deduplicates_or_fails_loudly() -> None: image = ArtifactSpec.output("DNA", ImageArtifactType) diff --git a/tests/unit/test_automatic_image_role_materialization_435.py b/tests/unit/test_automatic_image_role_materialization_435.py new file mode 100644 index 0000000000..8e501c928e --- /dev/null +++ b/tests/unit/test_automatic_image_role_materialization_435.py @@ -0,0 +1,378 @@ +"""Default retained image artifacts keep their declared output role identity.""" + +from dataclasses import replace +from pathlib import Path +import json + +import pytest +import numpy as np +import tifffile +from polystore.disk import DiskStorageBackend +from polystore.filemanager import FileManager +from polystore.memory import MemoryStorageBackend + +from test_function_outputs import context_stub, function_step_plan, record_output_path +from openhcs.constants.constants import Backend, Microscope, VariableComponents +from openhcs.core.aligned_image_payload import AlignedImageSliceContext, ImagePayloadBundleContext +from openhcs.core.artifacts import ArtifactOutputPlan, ArtifactSpec, ImageArtifactType +from openhcs.core.compiled_step_plan import RuntimeArtifactMaterializationPlan +from openhcs.core.pipeline.artifact_planning import ArtifactOutputMaterializationPlanner +from openhcs.core.runtime_artifact_values import RuntimeValue +from openhcs.core.runtime_image_values import ImageMetadataPayload, ImagePayloadMetadata, ImagePayloadMetadataCompositionMode +from openhcs.core.runtime_stores import RuntimeValueStore +from openhcs.core.source_metadata import SourceVoxelSpacing +from openhcs.core.source_projection import SourceProjectionMetadataSerializer +from openhcs.core.source_workspace_projection import VirtualWorkspaceSourceProjection +from openhcs.core.steps.function_output_identity import ( + FunctionOutputIdentity, +) +from openhcs.core.steps.function_outputs import ( + PrimaryImageMetadataTarget, RuntimeArtifactMaterializationAuthority, +) +from openhcs.microscopes.source_schema import SourceSchemaFilenameParser + + +@pytest.mark.parametrize("plane_count", (1, 2)) +def test_automatic_two_role_images_publish_their_actual_saved_occurrences(tmp_path, plane_count): + filemanager = FileManager({ + Backend.DISK.value: DiskStorageBackend(), + Backend.MEMORY.value: MemoryStorageBackend(), + }) + context = context_stub(filemanager, parser=SourceSchemaFilenameParser()) + context.microscope_handler.microscope_type = Microscope.OPENHCS.value + context.runtime_value_store = RuntimeValueStore() + context.metadata_cache = {} + context.tiff_config = None + plan = function_step_plan( + "Declared raw and capped roles", + variable_components=((VariableComponents.Z_INDEX,) if plane_count > 1 else ()), + ) + plan.streaming_configs = {} + plan.write_backend = Backend.DISK.value + plan.output_plate_root = str(tmp_path) + plan.output_dir = tmp_path / "images" + plan.sub_dir = "images" + plan.analysis_results_dir = str(plan.output_dir) + plan.runtime_artifact_materialization = RuntimeArtifactMaterializationPlan( + persistent_enabled=True, persistent_backend=Backend.DISK.value, + ) + context.step_plans = {plan.step_index: plan} + plans = tuple( + ArtifactOutputPlan( + name=name, path=f"/memory/{name}.pkl", artifact_type=ImageArtifactType, + producer_step_index=plan.step_index, + producer_step_scope_id=plan.step_scope_id, + producer_step_name=plan.step_name, + materialization=ArtifactOutputMaterializationPlanner.materialization_for( + ArtifactSpec(name=name, artifact_type=ImageArtifactType, plan_type=ArtifactOutputPlan), (), + ), + ) + for name in ("raw_body_processing_role", "capped_outgrowth_processing_role") + ) + plan.artifact_outputs = {output.ref(): output for output in plans} + contexts = AlignedImageSliceContext.main_flow_for_output_plans(plans) + expected = {} + for output, output_context, factor in zip(plans, contexts, (1.0, 0.5), strict=True): + payloads = tuple( + ImageMetadataPayload( + (np.arange(20, dtype=np.float32).reshape(4, 5) + index) * factor, + ImagePayloadMetadata( + source_component_metadata={ + "well": "A01", "site": "1", "channel": "2", "z_index": str(index), + "timepoint": "1", "extension": ".tif", + }, + source_image_names=(output.name,), + source_voxel_spacing=SourceVoxelSpacing((1.3556, 1.3556)), + ), + ) + for index in range(1, plane_count + 1) + ) + value = ( + payloads[0] if plane_count == 1 else ImagePayloadBundleContext.from_payloads( + payloads, metadata_mode=ImagePayloadMetadataCompositionMode.STACK, + ).compose() + ) + context.runtime_value_store.record( + RuntimeValue.normalize(output, value, axis_id="A01"), + path=output.path, backend=Backend.MEMORY.value, + ) + expected[output.name] = [] + for payload in payloads: + identity = FunctionOutputIdentity.from_filename_metadata( + context.microscope_handler.parser, payload.metadata, + ).with_filename_qualifier(output_context.output_key) + destination = plan.output_dir / identity.filename(context.microscope_handler.parser) + filemanager.ensure_directory(plan.output_dir, Backend.MEMORY.value) + filemanager.ensure_directory(plan.output_dir, Backend.DISK.value) + filemanager.save(payload, str(destination), Backend.MEMORY.value) + filemanager.save(payload.data, str(destination), Backend.DISK.value) + record_output_path( + context, plan, str(destination), output_context=output_context, + image_metadata=payload.metadata, identity=identity, + ) + expected[output.name].append((destination, payload.data)) + saved = RuntimeArtifactMaterializationAuthority.materialize(context, plan) + target = replace(PrimaryImageMetadataTarget.from_plan(plan), artifact_materializations=saved) + # The original implementation raises its real duplicate projection guard + # here: both automatic materializations used the same unqualified path. + structured = target.produced_projection_entries(context, plan) + structured = SourceProjectionMetadataSerializer.projection_fields( + structured.projection_paths + ) + assert {item["source_alias"] for item in structured["source_projection"]} == set(expected) + assert len(structured["source_projection"]) == 2 * plane_count + for materialized in saved: + outputs = materialized.outputs_for_backend(Backend.DISK.value) + assert len(outputs) == plane_count + for actual, (path, pixels) in zip(outputs, expected[materialized.materialization.output_plan.name], strict=True): + assert actual.path == str(path) + np.testing.assert_array_equal(tifffile.imread(path), pixels) + target.write(context, produced_plan=plan) + document = json.loads((tmp_path / "openhcs_metadata.json").read_text()) + reopened = VirtualWorkspaceSourceProjection.from_openhcs_metadata(tmp_path, document) + for name, expected_planes in expected.items(): + for path, pixels in expected_planes: + projection = reopened.source_projections_by_virtual_path[str(path.relative_to(tmp_path))] + assert projection.source_alias == name + assert projection.address.as_component_metadata()["channel"] == "2" + assert projection.image_metadata.source_voxel_spacing == SourceVoxelSpacing((1.3556, 1.3556)) + np.testing.assert_array_equal(tifffile.imread(tmp_path / projection.ref.backend_address), pixels) + + +@pytest.mark.parametrize("purpose", ( + "explicit_source", "explicit_template", "terminal_template", + "explicit_artifact", "terminal_artifact", "unnamed_terminal", "unnamed_explicit", + "explicit_source_declared_terminal", "terminal_source_declared_explicit", +)) +def test_retained_role_policy_preserves_authored_and_unnamed_image_paths(tmp_path, purpose): + from openhcs.processing.materialization import ( + ImageFileOptions, MaterializationSpec, MaterializedFilenameIdentity, + TerminalMaterializationSpec, materialization_outputs, + ) + + options = ImageFileOptions( + filename_suffix=".tif", + relative_path_template=("authored/plane_{index}.tif" if purpose.endswith("template") else None), + filename_identity=( + MaterializedFilenameIdentity.ARTIFACT_NAME if purpose.endswith("artifact") + else MaterializedFilenameIdentity.SOURCE_IDENTITY + ), + ) + spec = ( + TerminalMaterializationSpec(options) if purpose.startswith("terminal") or purpose == "unnamed_terminal" + else MaterializationSpec(options) + ) + declared_spec = ( + TerminalMaterializationSpec(options) if purpose == "explicit_source_declared_terminal" + else MaterializationSpec(options) if purpose == "terminal_source_declared_explicit" + else spec + ) + output_plan = None if purpose in ("unnamed_terminal", "unnamed_explicit") else ArtifactOutputPlan( + name="DeclaredRole", path="/memory/DeclaredRole.pkl", + artifact_type=ImageArtifactType, materialization=declared_spec, + ) + payloads = tuple( + ImageMetadataPayload(np.ones((4, 5), dtype=np.float32) * index, ImagePayloadMetadata( + source_component_metadata={ + "well": "A01", "site": "1", "channel": "2", "z_index": str(index), + "timepoint": "1", "extension": ".tif", + }, + )) + for index in (1, 2) + ) + value = ImagePayloadBundleContext.from_payloads( + payloads, metadata_mode=ImagePayloadMetadataCompositionMode.STACK, + ).compose() + filemanager = FileManager({Backend.MEMORY.value: MemoryStorageBackend()}) + context = context_stub(filemanager, parser=SourceSchemaFilenameParser()) + outputs = materialization_outputs( + spec, value, str(tmp_path / "AuthoredBase"), filemanager, + context=context, output_plan=output_plan, + variable_components=(VariableComponents.Z_INDEX,), + ) + expected_paths = ( + ("authored/plane_1.tif", "authored/plane_2.tif") if purpose.endswith("template") + else ("AuthoredBase.tif",) if purpose.endswith("artifact") + else ("A01_s001_w2_z001_t001_DeclaredRole.tif", "A01_s001_w2_z002_t001_DeclaredRole.tif") if purpose == "terminal_source_declared_explicit" + else ("A01_s001_w2_z001_t001.tif", "A01_s001_w2_z002_t001.tif") + ) + assert tuple(Path(output.path).relative_to(tmp_path).as_posix() for output in outputs) == expected_paths + if len(outputs) == 2: + for actual, expected in zip(outputs, payloads, strict=True): + np.testing.assert_array_equal(actual.content, expected.data) + else: + np.testing.assert_array_equal(outputs[0].content, value.data) + + +def test_authored_duplicate_template_still_fails_before_any_save(tmp_path): + from openhcs.processing.materialization import ImageFileOptions, TerminalMaterializationSpec, materialization_outputs + + spec = TerminalMaterializationSpec(ImageFileOptions( + filename_suffix=".tif", relative_path_template="same.tif", + )) + output_plan = ArtifactOutputPlan(name="NamedRole", path="/memory/role.pkl", artifact_type=ImageArtifactType, materialization=spec) + payloads = tuple( + ImageMetadataPayload(np.ones((4, 5), dtype=np.float32), ImagePayloadMetadata( + source_component_metadata={"well": "A01", "site": "1", "channel": "2", "z_index": str(index), "timepoint": "1", "extension": ".tif"}, + )) for index in (1, 2) + ) + value = ImagePayloadBundleContext.from_payloads(payloads, metadata_mode=ImagePayloadMetadataCompositionMode.STACK).compose() + manager = FileManager({Backend.MEMORY.value: MemoryStorageBackend()}) + with pytest.raises(ValueError, match="produced duplicate paths"): + materialization_outputs(spec, value, str(tmp_path / "role"), manager, + context=context_stub(manager, parser=SourceSchemaFilenameParser()), + output_plan=output_plan) + assert not (tmp_path / "same.tif").exists() + + +@pytest.mark.parametrize("suffix", (".tif", ".png", ".ome.tif", ".labels.tif")) +@pytest.mark.parametrize("plane_count", (1, 2)) +def test_retained_image_qualifier_respects_complete_writer_suffix(tmp_path, suffix, plane_count): + from openhcs.core.steps.function_artifact_materialization import RuntimeArtifactMaterialization + from openhcs.processing.materialization import ImageFileOptions, TerminalMaterializationSpec + + manager = FileManager({Backend.MEMORY.value: MemoryStorageBackend()}) + context = context_stub(manager, parser=SourceSchemaFilenameParser()) + plan = function_step_plan("Retained format role", variable_components=(VariableComponents.Z_INDEX,) if plane_count > 1 else ()) + plan.output_dir = tmp_path / "images" + plan.analysis_results_dir = str(plan.output_dir) + output_plan = ArtifactOutputPlan( + name="Role Name", path="/memory/role.pkl", artifact_type=ImageArtifactType, + materialization=TerminalMaterializationSpec(ImageFileOptions(filename_suffix=suffix)), + ) + payloads = tuple( + ImageMetadataPayload(np.ones((4, 5), dtype=np.uint8) * index, ImagePayloadMetadata( + source_component_metadata={"well": "A01", "site": "1", "channel": "2", "z_index": str(index), "timepoint": "1", "extension": ".tif"}, + )) for index in range(1, plane_count + 1) + ) + value = payloads[0] if plane_count == 1 else ImagePayloadBundleContext.from_payloads( + payloads, metadata_mode=ImagePayloadMetadataCompositionMode.STACK, + ).compose() + store = RuntimeValueStore() + record = store.record(RuntimeValue.normalize(output_plan, value, axis_id="A01"), path=output_plan.path, backend=Backend.MEMORY.value) + outputs = RuntimeArtifactMaterialization.from_record( + output_plan=output_plan, record=record, plan=plan, context=context, + ).outputs(plan, context) + assert len(outputs) == plane_count + for index, (output, payload) in enumerate(zip(outputs, payloads, strict=True), 1): + identity = FunctionOutputIdentity.from_filename_metadata( + context.microscope_handler.parser, payload.metadata, + ).with_filename_qualifier(output_plan.name) + expected = replace(identity, extension=suffix).filename(context.microscope_handler.parser) + assert Path(output.path).name == expected + assert Path(output.path).name.endswith("_Role_Name" + suffix) + assert output.metadata.source_component_metadata["channel"] == "2" + assert output.metadata.source_component_metadata["z_index"] == str(index) + np.testing.assert_array_equal(output.content, payload.data) + + +def test_distinct_aliases_that_normalize_to_one_filename_still_conflict(tmp_path): + from openhcs.core.steps.function_artifact_materialization import RuntimeArtifactMaterialization + from openhcs.processing.materialization import ImageFileOptions, TerminalMaterializationSpec + + manager = FileManager({Backend.MEMORY.value: MemoryStorageBackend()}) + context = context_stub(manager, parser=SourceSchemaFilenameParser()) + plan = function_step_plan("Ambiguous role spelling") + plan.output_dir = tmp_path / "images" + plan.analysis_results_dir = str(plan.output_dir) + value = ImageMetadataPayload(np.ones((4, 5), dtype=np.float32), ImagePayloadMetadata( + source_component_metadata={"well": "A01", "site": "1", "channel": "2", "z_index": "1", "timepoint": "1", "extension": ".tif"}, + )) + paths = [] + store = RuntimeValueStore() + for name in ("a/b", "a b"): + output_plan = ArtifactOutputPlan(name=name, path=f"/memory/{name}.pkl", artifact_type=ImageArtifactType, + materialization=TerminalMaterializationSpec(ImageFileOptions(filename_suffix=".tif"))) + record = store.record(RuntimeValue.normalize(output_plan, value, axis_id="A01"), path=output_plan.path, backend=Backend.MEMORY.value) + outputs = RuntimeArtifactMaterialization.from_record(output_plan=output_plan, record=record, plan=plan, context=context).outputs(plan, context) + paths.append(outputs[0].path) + assert paths[0] == paths[1] + # Existing main-flow destination authority rejects this declared naming + # collision instead of choosing a new suffix or inventing a channel. + from openhcs.core.steps.function_runtime import OutputPathBatchUniqueness + with pytest.raises(ValueError, match="duplicate"): + OutputPathBatchUniqueness(output_paths=paths, input_paths=[], step_name=plan.step_name, pattern_repr="declared roles").validate() + + +def test_batch_binds_actual_purpose_once_without_rewriting_plan_or_source(monkeypatch, tmp_path): + from openhcs.processing.materialization import ImageFileOptions, MaterializationSpec, TerminalMaterializationSpec + from openhcs.processing.materialization.constants import MaterializationFormat + from openhcs.processing.materialization.core import MaterializationBatch, MaterializationContext, Output, WriterSpec, _WRITERS_BY_OPTIONS + + options = ImageFileOptions(filename_suffix=".tif") + declared = TerminalMaterializationSpec(options) + explicit = MaterializationSpec(options) + plan = ArtifactOutputPlan(name="Role", path="/memory/role", artifact_type=ImageArtifactType, materialization=declared) + manager = FileManager({Backend.MEMORY.value: MemoryStorageBackend()}) + source = {"physical_source": "original"} + context = MaterializationContext( + base_path=str(tmp_path / "role"), backends=[], backend_kwargs={}, + filemanager=manager, extra_inputs=source, output_plan=plan, + materialization_spec=declared, + ) + seen = [] + def custom_writer(data, actual_options, actual_context): + assert actual_options is options + assert actual_context.output_plan is plan + assert actual_context.extra_inputs is source + seen.append(actual_context) + return [Output(path=str(tmp_path / "custom.tif"), content=data)] + monkeypatch.setitem(_WRITERS_BY_OPTIONS, ImageFileOptions, WriterSpec( + format=MaterializationFormat.IMAGE_FILE, options_type=ImageFileOptions, + write=custom_writer, primary_path=lambda outputs: outputs[0].path, + candidate_paths=lambda _options, base: (base,), + )) + pixels = np.ones((4, 5), dtype=np.float32) + first = MaterializationBatch.render(explicit, pixels, context) + second = MaterializationBatch.render(declared, pixels, first.context) + assert seen == [first.context, second.context] + assert seen[0] is first.context and seen[1] is second.context + assert first.context.materialization_spec is explicit + assert second.context.materialization_spec is declared + assert context.materialization_spec is declared + assert plan.materialization is declared + assert source == {"physical_source": "original"} + + +def test_direct_image_writer_without_purpose_binding_retains_legacy_source_path(tmp_path): + from openhcs.processing.materialization import ImageFileOptions, TerminalMaterializationSpec + from openhcs.processing.materialization.core import MaterializationContext, write_image_file + + options = ImageFileOptions(filename_suffix=".tif") + plan = ArtifactOutputPlan(name="Role", path="/memory/role", artifact_type=ImageArtifactType, + materialization=TerminalMaterializationSpec(options)) + manager = FileManager({Backend.MEMORY.value: MemoryStorageBackend()}) + value = ImageMetadataPayload(np.ones((4, 5), dtype=np.float32), ImagePayloadMetadata( + source_component_metadata={"well": "A01", "site": "1", "channel": "2", "z_index": "1", "timepoint": "1", "extension": ".tif"}, + )) + context = MaterializationContext(base_path=str(tmp_path / "role"), backends=[], backend_kwargs={}, + filemanager=manager, extra_inputs={}, output_plan=plan, + context=context_stub(manager, parser=SourceSchemaFilenameParser())) + outputs = write_image_file(value, options, context) + assert Path(outputs[0].path).name == "A01_s001_w2_z001_t001.tif" + assert context.materialization_spec is None + assert context.output_plan is plan + np.testing.assert_array_equal(outputs[0].content, value.data) + + +@pytest.mark.parametrize("purpose", ("named_terminal", "explicit", "unnamed_terminal")) +def test_parser_free_render_requires_parser_only_for_automatic_named_role(tmp_path, purpose): + from openhcs.processing.materialization import ImageFileOptions, MaterializationSpec, TerminalMaterializationSpec, materialization_outputs + + options = ImageFileOptions(filename_suffix=".tif") + spec = MaterializationSpec(options) if purpose == "explicit" else TerminalMaterializationSpec(options) + plan = None if purpose == "unnamed_terminal" else ArtifactOutputPlan( + name="Role", path="/memory/role", artifact_type=ImageArtifactType, materialization=spec, + ) + manager = FileManager({Backend.MEMORY.value: MemoryStorageBackend()}) + value = ImageMetadataPayload(np.ones((4, 5), dtype=np.float32), ImagePayloadMetadata( + source_path="/physical/OriginalSource.tif", + )) + if purpose == "named_terminal": + with pytest.raises(ValueError, match="Parser-backed source-stem authority requires a parser"): + materialization_outputs(spec, value, str(tmp_path / "Role"), manager, output_plan=plan) + else: + outputs = materialization_outputs(spec, value, str(tmp_path / "Role"), manager, output_plan=plan) + assert Path(outputs[0].path).name == "OriginalSource.tif" + np.testing.assert_array_equal(outputs[0].content, value.data) + assert value.metadata.source_path == "/physical/OriginalSource.tif" diff --git a/tests/unit/test_benchmark_control.py b/tests/unit/test_benchmark_control.py index 833e0e1434..1f392de25f 100644 --- a/tests/unit/test_benchmark_control.py +++ b/tests/unit/test_benchmark_control.py @@ -64,7 +64,7 @@ InstalledDistributionVersion, RuntimeEnvironmentSnapshot, ) -from openhcs.runtime.zmq_execution_client import OpenHCSExecutionSubmission +from openhcs.runtime.zmq_execution_client import OpenHCSExecutionSubmission, ZMQExecutionRequestBuilder from openhcs.runtime.zmq_execution_signature import ZMQAuxiliaryExecutionParams @@ -635,7 +635,7 @@ class CompletedJobService: def require_completed_pipeline_execution(self, job_id: str): assert job_id == "job-1" return CompletedPipelineExecution( - submission=submission, + request=ZMQExecutionRequestBuilder.from_task(submission), record=ExecutionRecord( execution_id="execution-1", plate_id=str(tmp_path), diff --git a/tests/unit/test_callable_abi_preparation.py b/tests/unit/test_callable_abi_preparation.py new file mode 100644 index 0000000000..046995f880 --- /dev/null +++ b/tests/unit/test_callable_abi_preparation.py @@ -0,0 +1,401 @@ +"""Prepared canonical signatures survive compilation and worker transport.""" + +import inspect +import pickle +from types import SimpleNamespace +from dataclasses import replace +from functools import wraps +from unittest.mock import Mock +from typing import Any + +import cloudpickle +import numpy as np +import pytest +from arraybridge import ArrayPayload + +import openhcs.core.callable_contract as contract_module +from openhcs.core.callable_contract import ( + CallableContract, CallableImportIdentity, CallableMetadata, CallableProjection, + attach_callable_contract_metadata, attach_processing_prepare, +) +from openhcs.core.function_contract_metadata import FunctionContractAttribute +from openhcs.core.function_patterns import NormalizedFunctionGroup +from openhcs.core.function_reference import ImportableFunctionReference +from openhcs.core.processing_preparation import CallablePreparation, PreparationCacheBatch +from openhcs.core.runtime_image_values import ImagePayloadMetadata, image_payload_data +from openhcs.core.runtime_plane_projection import RuntimePlaneAxis +from openhcs.core.pipeline.function_contracts import composed_image_payload +from openhcs.processing.backends.lib_registry.registry_service import RegistryService +from openhcs.core.runtime_batch_contracts import ( + Pure2DSliceBatchExecutor, RuntimeBatchExecutionDomain, + SerialPure2DSliceBatchExecutor, runtime_callable_defaults, +) +from openhcs.core.pipeline.function_contracts import resolved_callable_parameter +from openhcs.processing.backends.lib_registry.unified_registry import ( + RuntimeCallablePolicy, RuntimeInvocationKwargPolicy, +) + + +def raw_numeric(image: np.ndarray, scale: float = 2.0) -> np.ndarray: + return image * scale + + +@composed_image_payload +def unannotated_composed_echo(image): + return image + + +@pytest.mark.parametrize( + ("composed", "annotation", "retains_payload"), + ((True, inspect.Parameter.empty, True), + (False, inspect.Parameter.empty, False), + (True, np.ndarray, False), + (True, Any, False), + (True, ArrayPayload, True)), +) +def test_composition_default_respects_explicit_raw_carrier_boundary( + composed, annotation, retains_payload, fake_preparation, +): + received = [] + def raw(image): + received.append(image) + return image + if annotation is not inspect.Parameter.empty: + raw.__annotations__["image"] = annotation + if composed: + composed_image_payload(raw) + contract = CallableContract.from_prepared_callable(raw) + pixels = np.arange(20, dtype=np.float32).reshape(1, 4, 5) + mask = np.ones((1, 4, 5), dtype=bool) + mask[0, 0, 0] = False + source = ImagePayloadMetadata( + plane_axis=RuntimePlaneAxis.SOURCE_BINDING, + source_image_names=("FITC",), + ).payload_with(pixels, mask) + expected = source if retains_payload else pixels + + result = RuntimeCallablePolicy().contract_invocation(contract, raw, source, {}).call() + + assert result is expected + assert received[0] is expected + assert source.metadata.plane_axis is RuntimePlaneAxis.SOURCE_BINDING + np.testing.assert_array_equal(source.mask, mask) + + +@pytest.mark.parametrize("serializer", (pickle, cloudpickle)) +def test_prepared_composition_default_survives_transport_without_introspection( + serializer, fake_preparation, monkeypatch, +): + contract = CallableContract.from_prepared_callable(unannotated_composed_echo) + reference = ImportableFunctionReference( + import_identity=CallableImportIdentity.from_callable(unannotated_composed_echo), + composite_key="test:unannotated_composed_echo", metadata=contract.metadata, + ) + restored = CallableContract.from_callable(serializer.loads(serializer.dumps(reference))) + def forbidden(*args, **kwargs): + pytest.fail("Prepared composed ABI must not inspect live callable declarations") + monkeypatch.setattr(contract_module, "get_type_hints", forbidden) + monkeypatch.setattr(inspect, "signature", forbidden) + payload = ImagePayloadMetadata( + plane_axis=RuntimePlaneAxis.SOURCE_BINDING, + source_image_names=("FITC",), + ).payload_with(np.ones((1, 4, 5)), np.ones((1, 4, 5), dtype=bool)) + for _ in range(40): + assert restored.raw_main_flow_call_argument(payload) is payload + + +@pytest.fixture +def fake_preparation(monkeypatch): + prepare = Mock() + monkeypatch.setattr(CallablePreparation, "prepare", prepare) + monkeypatch.setattr(PreparationCacheBatch, "populate_child_caches", lambda *a, **k: None) + return prepare + + +def test_registry_resolves_signatures_after_all_hooks_and_before_ready(monkeypatch): + events = [] + + def first(image: np.ndarray): + return image + + def last(image: np.ndarray): + return image + + first.__dict__[FunctionContractAttribute.raw_processing_function] = last + metadata = {"first": SimpleNamespace(func=first), "alias": SimpleNamespace(func=first)} + monkeypatch.setattr(RegistryService, "_metadata_cache", metadata) + monkeypatch.setattr(PreparationCacheBatch, "populate_child_caches", lambda *a, **k: None) + + def prepare(owner): + events.append(("prepare", owner.projection.func)) + if owner.projection.func is last: + last.__annotations__["image"] = ArrayPayload + + original_hints = contract_module.get_type_hints + + def hints(func, **kwargs): + events.append(("signature", func)) + return original_hints(func, **kwargs) + + monkeypatch.setattr(CallablePreparation, "prepare", prepare) + monkeypatch.setattr(contract_module, "get_type_hints", hints) + assert RegistryService.prepare_in_current_process(status_callback=events.append) is metadata + preparations = [i for i, item in enumerate(events) if isinstance(item, tuple) and item[0] == "prepare"] + signatures = [i for i, item in enumerate(events) if isinstance(item, tuple) and item[0] == "signature"] + assert len(preparations) == 2 + assert max(preparations) < min(signatures) + assert max(signatures) < next(i for i, item in enumerate(events) if isinstance(item, str) and "kernels ready" in item) + assert CallableContract.from_callable(first).canonical_parameter_annotations["image"] is ArrayPayload + assert CallableContract.from_callable(last).canonical_parameter_annotations["image"] is ArrayPayload + + +def test_explicit_library_rewarm_refreshes_new_contract_not_existing_snapshot(monkeypatch, fake_preparation): + def raw(image: np.ndarray): + return image + + metadata = {"raw": SimpleNamespace(func=raw)} + monkeypatch.setattr(RegistryService, "_metadata_cache", metadata) + RegistryService.prepare_in_current_process() + first = CallableContract.from_callable(raw) + raw.__annotations__["image"] = ArrayPayload + assert CallableContract.from_callable(raw).canonical_parameter_annotations["image"] is np.ndarray + RegistryService.prepare_in_current_process() + second = CallableContract.from_callable(raw) + assert first.canonical_parameter_annotations["image"] is np.ndarray + assert second.canonical_parameter_annotations["image"] is ArrayPayload + + +def test_authored_compilation_prepares_before_signature_and_refreshes_each_compilation(monkeypatch): + def raw(image: np.ndarray, scale=2): + return image + + desired_annotations = [ArrayPayload, np.ndarray] + + def prepare(owner): + raw.__annotations__["image"] = desired_annotations.pop(0) + + monkeypatch.setattr(CallablePreparation, "prepare", prepare) + first = NormalizedFunctionGroup.from_pattern("group", raw).items[0].contract + second = NormalizedFunctionGroup.from_pattern("group", raw).items[0].contract + assert first.canonical_parameter_annotations["image"] is ArrayPayload + assert second.canonical_parameter_annotations["image"] is np.ndarray + assert FunctionContractAttribute.canonical_signature not in vars(raw) + + +def test_authored_preparation_precedes_metadata_validation(monkeypatch): + def raw(image: np.ndarray): + return image + events = [] + original = CallableMetadata.from_projection.__func__ + + def validate(cls, projection): + assert events == ["prepared"] + return original(cls, projection) + + monkeypatch.setattr(CallablePreparation, "prepare", lambda self: events.append("prepared")) + monkeypatch.setattr(CallableMetadata, "from_projection", classmethod(validate)) + contract = CallableContract.from_prepared_callable(raw) + assert contract.canonical_parameter_annotations["image"] is np.ndarray + + +def test_unprepared_function_reference_compilation_reads_prepared_live_declaration(monkeypatch, fake_preparation): + reference = ImportableFunctionReference( + import_identity=CallableImportIdentity.from_callable(raw_numeric), + composite_key="test:raw_numeric", + ) + contract = NormalizedFunctionGroup.from_pattern("group", reference).items[0].contract + assert contract.func is reference + assert contract.canonical_parameter_annotations["image"] is np.ndarray + assert fake_preparation.call_count == 1 + + +@pytest.mark.parametrize("serializer", [pickle, cloudpickle]) +def test_prepared_signature_metadata_namespace_and_reference_transport(serializer, fake_preparation): + contract = CallableContract.from_prepared_callable(raw_numeric) + metadata = contract.metadata + + def proxy(image): + return image + + proxy.__dict__.update(metadata.as_namespace()) + assert CallableMetadata.from_callable(proxy).canonical_signature == metadata.canonical_signature + reference = ImportableFunctionReference( + import_identity=CallableImportIdentity.from_callable(raw_numeric), + composite_key="test:raw_numeric", metadata=metadata, + ) + restored = serializer.loads(serializer.dumps(reference)) + assert restored.metadata.canonical_signature == metadata.canonical_signature + restored_contract = CallableContract.from_callable(restored) + assert restored_contract.canonical_parameter_annotations["image"] is np.ndarray + assert restored_contract.canonical_signature.parameters["scale"].default == 2.0 + assert restored_contract.canonical_signature.return_annotation is np.ndarray + + +def test_compiled_raw_projection_never_queries_signature_or_annotations(monkeypatch, fake_preparation): + contract = CallableContract.from_prepared_callable(raw_numeric) + reference = ImportableFunctionReference( + import_identity=CallableImportIdentity.from_callable(raw_numeric), + composite_key="test:raw_numeric", metadata=contract.metadata, + ) + restored = CallableContract.from_callable(pickle.loads(pickle.dumps(reference))) + def forbidden(*args, **kwargs): + raise AssertionError("Compiled runtime queried a live signature") + monkeypatch.setattr(contract_module, "get_type_hints", forbidden) + monkeypatch.setattr(inspect, "signature", forbidden) + payload = ImagePayloadMetadata(source_image_names=("DNA",)).payload_with(np.ones((2, 3)), None) + for _ in range(40): + assert restored.raw_main_flow_call_argument(payload) is image_payload_data(payload) + assert restored.primary_input_parameter_name == "image" + assert restored.canonical_parameter_annotations["image"] is np.ndarray + + +def test_custom_signature_and_mutable_default_are_retained_until_recompilation(monkeypatch, fake_preparation): + default = [] + def raw(image, values=None): + return image + raw.__signature__ = inspect.Signature([ + inspect.Parameter("image", inspect.Parameter.POSITIONAL_ONLY, annotation=ArrayPayload), + inspect.Parameter("values", inspect.Parameter.KEYWORD_ONLY, default=default), + ]) + first = CallableContract.from_prepared_callable(raw) + assert first.canonical_signature.parameters["values"].default is default + raw.__signature__ = raw.__signature__.replace(parameters=[ + inspect.Parameter("image", inspect.Parameter.POSITIONAL_ONLY, annotation=np.ndarray), + ]) + second = CallableContract.from_prepared_callable(raw) + assert first.canonical_parameter_annotations["image"] is ArrayPayload + assert second.canonical_parameter_annotations["image"] is np.ndarray + + +@pytest.mark.parametrize("mutation", [ + lambda func: attach_processing_prepare(func, lambda: None), + lambda func: attach_callable_contract_metadata(func, raw_processing_function=raw_numeric), +]) +def test_supported_declaration_changes_invalidate_published_signature(mutation): + def raw(image: np.ndarray): + return image + CallableProjection.from_callable(raw).warm_canonical_signature() + assert FunctionContractAttribute.canonical_signature in vars(raw) + mutation(raw) + assert FunctionContractAttribute.canonical_signature not in vars(raw) + + +def test_malformed_signature_declaration_is_rejected(): + def raw(image): + return image + raw.__dict__[FunctionContractAttribute.canonical_signature] = "not a signature" + with pytest.raises(TypeError, match="inspect.Signature"): + CallableMetadata.from_callable(raw) + + +def test_exact_raw_default_filter_and_type_views_refresh_with_library_snapshot(): + def raw(image: np.ndarray, scale: float = 2): + return image * scale + CallableProjection.from_callable(raw).warm_canonical_signature() + policy = RuntimeCallablePolicy(kwarg_policy=RuntimeInvocationKwargPolicy.SIGNATURE_FILTERED) + assert runtime_callable_defaults(raw)["scale"] == 2 + assert resolved_callable_parameter(raw, "scale").annotation is float + assert policy.invocation(raw, (np.ones((2, 3)),), {"scale":3, "unknown":9}).call()[0,0] == 3 + raw.__defaults__ = (4,) + raw.__annotations__["scale"] = int + assert runtime_callable_defaults(raw)["scale"] == 2 + assert resolved_callable_parameter(raw, "scale").annotation is float + CallableProjection.from_callable(raw).warm_canonical_signature() + assert runtime_callable_defaults(raw)["scale"] == 4 + assert resolved_callable_parameter(raw, "scale").annotation is int + + +def test_different_wrapper_signature_remains_live_for_default_filter_and_parameter_queries(): + def raw(image: np.ndarray, private: int = 8): + return image + def wrapper(image: np.ndarray, public: int = 2): + return image * public + wrapper.__dict__[FunctionContractAttribute.raw_processing_function] = raw + CallableProjection.from_callable(wrapper).warm_canonical_signature() + assert runtime_callable_defaults(wrapper) == {"public":2} + assert resolved_callable_parameter(wrapper, "public").annotation is int + policy = RuntimeCallablePolicy(kwarg_policy=RuntimeInvocationKwargPolicy.SIGNATURE_FILTERED) + assert policy.invocation(wrapper, (np.ones((2, 3)),), {"public":3, "private":99}).call()[0,0] == 3 + wrapper.__defaults__ = (5,) + assert runtime_callable_defaults(wrapper) == {"public":5} + assert policy.invocation(wrapper, (np.ones((2, 3)),), {"private":99}).call()[0,0] == 5 + + +def test_prepared_type_query_preserves_legacy_nested_annotation_stripping(): + from typing import Annotated, get_type_hints + def raw(image, labels): + return image + raw.__annotations__ = {"image":Annotated[np.ndarray,"image"],"labels":tuple[Annotated[int,"id"],...],"return":Annotated[np.ndarray,"result"]} + expected = get_type_hints(raw) + CallableProjection.from_callable(raw).warm_canonical_signature() + assert resolved_callable_parameter(raw,"image").annotation == expected["image"] + assert resolved_callable_parameter(raw,"labels").annotation == expected["labels"] + assert CallableContract.from_callable(raw).canonical_parameter_annotations["labels"] == raw.__annotations__["labels"] + + +def test_distinct_authored_runtime_signature_transport_and_new_compilation_refresh(fake_preparation): + def raw(image: np.ndarray, scale: int = 2) -> np.ndarray: + return image * scale + @wraps(raw) + def wrapper(*args, **kwargs): + return raw(*args, **kwargs) + wrapper.__signature__ = inspect.signature(raw).replace(parameters=[ + *inspect.signature(raw).parameters.values(), + inspect.Parameter("injected",inspect.Parameter.KEYWORD_ONLY,default=False), + ]) + first = CallableContract.from_prepared_callable(wrapper) + assert "injected" in first.canonical_signature.parameters + assert "injected" not in first.raw_runtime_signature.parameters + assert first.metadata.raw_runtime_signature is not None + restored = pickle.loads(pickle.dumps(first.metadata)) + assert restored.raw_runtime_signature == first.raw_runtime_signature + assert restored.as_namespace()[FunctionContractAttribute.raw_runtime_signature] == first.raw_runtime_signature + assert FunctionContractAttribute.canonical_signature not in vars(raw) + assert FunctionContractAttribute.canonical_signature not in vars(wrapper) + raw.__defaults__ = (4,) + raw.__annotations__["scale"] = float + second = CallableContract.from_prepared_callable(wrapper) + assert first.raw_runtime_signature.parameters["scale"].default == 2 + assert second.raw_runtime_signature.parameters["scale"].default == 4 + assert second.raw_runtime_signature.parameters["scale"].annotation is float + + +def test_distinct_targets_own_signatures_even_when_layouts_match_without_comparing_defaults(fake_preparation): + class RejectEquality: + def __eq__(self, other): + raise AssertionError("Signature reuse compared a mutable default") + default = RejectEquality() + def raw(image: np.ndarray, values=default) -> np.ndarray: + return image + @wraps(raw) + def wrapper(*args, **kwargs): + return raw(*args, **kwargs) + contract = CallableContract.from_prepared_callable(wrapper) + assert contract.metadata.raw_runtime_signature is not None + assert contract.raw_runtime_signature is not contract.canonical_signature + assert contract.raw_runtime_signature.parameters["values"].default is default + raw.__defaults__ = ("new raw default",) + second = CallableContract.from_prepared_callable(wrapper) + assert second.raw_runtime_signature.parameters["values"].default == "new raw default" + assert contract.raw_runtime_signature.parameters["values"].default is default + + +def test_same_actual_target_shares_canonical_signature(fake_preparation): + contract = CallableContract.from_prepared_callable(raw_numeric) + assert contract.metadata.raw_runtime_signature is None + assert contract.raw_runtime_signature is contract.canonical_signature + + +@pytest.mark.parametrize("executors", (None, {}, {RuntimeBatchExecutionDomain.PURE_2D_SLICES: None})) +def test_pure_2d_executor_selection_retains_serial_fallback(executors): + assert isinstance(Pure2DSliceBatchExecutor.from_executors(executors), SerialPure2DSliceBatchExecutor) + + +def test_pure_2d_executor_selection_retains_exact_declared_executor(): + def declared(*args, **kwargs): + raise AssertionError("Selecting an executor must not execute it") + + selected = Pure2DSliceBatchExecutor.from_executors({ + RuntimeBatchExecutionDomain.PURE_2D_SLICES: declared, + }) + assert selected is declared diff --git a/tests/unit/test_callable_contract.py b/tests/unit/test_callable_contract.py index 35591dd9e3..cc9e0f0dd9 100644 --- a/tests/unit/test_callable_contract.py +++ b/tests/unit/test_callable_contract.py @@ -553,7 +553,9 @@ def test_function_reference_preserves_batching_through_compiler_and_transport( contract = normalized.groups[0].items[0].contract restored = pickle.loads(pickle.dumps(contract)) assert restored.func == reference - assert restored.metadata == reference.metadata + expected_metadata = reference.metadata.with_prepared_signatures(func, func) + assert restored.metadata.canonical_signature == expected_metadata.canonical_signature + assert restored.metadata == expected_metadata assert restored.runtime_batch_executor( RuntimeBatchExecutionDomain.PURE_2D_SLICES ) is _batch_executor diff --git a/tests/unit/test_callable_contract_runtime_resolution.py b/tests/unit/test_callable_contract_runtime_resolution.py new file mode 100644 index 0000000000..c6283be88f --- /dev/null +++ b/tests/unit/test_callable_contract_runtime_resolution.py @@ -0,0 +1,51 @@ +from dataclasses import replace + +from openhcs.core.artifacts import ArtifactSpec, ImageArtifactType +from openhcs.core.callable_contract import CallableContract, CallableMetadata +from openhcs.core.runtime_adapters import RuntimeAdapterSpec + + +def test_custom_runtime_wrapper_is_retained_for_its_exact_contract(): + prepared = [] + + def raw(image): + return image + + def runtime_callable(registered_func, contract): + prepared.append(contract) + + def execute(image): + return contract.artifact_outputs[0].name, registered_func(image) + + return execute + + first = CallableContract( + func=raw, + function_name=raw.__name__, + module_name=raw.__module__, + metadata=CallableMetadata( + input_memory_type="python", + output_memory_type="python", + artifact_outputs=(ArtifactSpec.output("First", ImageArtifactType),), + runtime_adapter=RuntimeAdapterSpec( + parameter_name="runtime", + factory=lambda request: request, + runtime_callable_factory=runtime_callable, + ), + ), + ) + second = replace( + first, + metadata=replace( + first.metadata, + artifact_outputs=(ArtifactSpec.output("Second", ImageArtifactType),), + ), + ) + first_callable = first.resolve_runtime_callable() + second_callable = second.resolve_runtime_callable() + assert first_callable(7) == ("First", 7) + assert second_callable(9) == ("Second", 9) + assert first.resolve_runtime_callable() is first_callable + assert second.resolve_runtime_callable() is second_callable + assert len(prepared) == 2 + assert prepared[0] is first and prepared[1] is second diff --git a/tests/unit/test_cellprofiler_adapter.py b/tests/unit/test_cellprofiler_adapter.py index afe8d73571..a4f01925bc 100644 --- a/tests/unit/test_cellprofiler_adapter.py +++ b/tests/unit/test_cellprofiler_adapter.py @@ -38,7 +38,6 @@ from openhcs.core.runtime_stores import RuntimeValueStore from openhcs.core.source_bindings import ( ImportedMetadataTable, - SourceBindingRuntimeContext, ) from tests.unit.cellprofiler_runtime_test_support import ( cellprofiler_runtime_adapter_for_test, diff --git a/tests/unit/test_cellprofiler_additional_prepared_payload_abi.py b/tests/unit/test_cellprofiler_additional_prepared_payload_abi.py new file mode 100644 index 0000000000..1ceb91da58 --- /dev/null +++ b/tests/unit/test_cellprofiler_additional_prepared_payload_abi.py @@ -0,0 +1,234 @@ +"""Prepared raw arguments retain context consumed by nominal CP request owners.""" +from dataclasses import replace + +import numpy as np +import pytest + +from openhcs.core.aligned_image_payload import ImagePayloadExecutionMode +from openhcs.core.callable_contract import CallableContract +from openhcs.core.runtime_image_values import ( + ImagePayloadMetadata, + image_payload_data, + image_payload_mask, + image_payload_metadata, + normalize_image_payload_intensity, +) +from openhcs.core.runtime_plane_projection import RuntimePlaneAxis +from openhcs.core.source_image_provenance import SourceImageProvenancePlanes +from openhcs.core.source_spatial_domain import SourceSpatialDomain +from openhcs.interop.cellprofiler.runtime.adapter import CellProfilerRuntimeAdapter +from openhcs.interop.cellprofiler.runtime.function_contract_execution import ( + CellProfilerFunctionContractExecutor, +) +from openhcs.processing.backends.cellprofiler.alignment import AlignModule, align +from openhcs.processing.backends.cellprofiler.area_occupied import measure_image_area_occupied +from openhcs.processing.backends.cellprofiler.crop import CropModule, crop +from openhcs.processing.backends.cellprofiler.grid import ShapeChoice, identify_objects_in_grid +from openhcs.core.runtime_object_label_building import SourceImageObjectLabelBuildRequest +from openhcs.core.runtime_spatial_grid import SpatialGrid +from openhcs.core.source_metadata import SourceVoxelSpacing +from openhcs.processing.backends.cellprofiler.image_quality import measure_image_quality +from openhcs.processing.backends.cellprofiler.intensity import measure_object_intensity +from openhcs.processing.backends.cellprofiler.manual_objects import identify_objects_manually +from openhcs.processing.backends.cellprofiler.object_images import convert_image_to_objects +from openhcs.processing.backends.cellprofiler.thresholding import threshold +from openhcs.processing.backends.cellprofiler.worms import ( + identify_dead_worms, + untangle_worms, + untangle_worms_both, + untangle_worms_with_overlap, +) + + +def _prepared_contract(func): + contract = CallableContract.from_callable(func).with_prepared_signature() + return replace( + contract, + metadata=replace( + contract.metadata, + runtime_adapter=CellProfilerRuntimeAdapter.runtime_adapter_spec(), + ), + ) + + +@pytest.mark.parametrize( + "func", + ( + align, + crop, + measure_image_area_occupied, + measure_object_intensity, + measure_image_quality, + identify_objects_manually, + identify_objects_in_grid, + convert_image_to_objects, + identify_dead_worms, + threshold, + untangle_worms, + untangle_worms_with_overlap, + untangle_worms_both, + ), +) +def test_prepared_primary_context_consumers_keep_nominal_payload_and_bare_pixels(func): + pixels = np.arange(60, dtype=np.float32).reshape(4, 5, 3) + mask = np.ones((4, 5), dtype=bool) + mask[0] = False + source = ImagePayloadMetadata( + source_path="/input/rgb.tif", + source_image_names=("RGB",), + source_channel_axis=-1, + source_spatial_domain=SourceSpatialDomain( + origin_yx=(2, 3), source_shape_yx=(8, 10) + ), + ).payload_with(pixels, mask) + contract = _prepared_contract(func) + + projected = contract.raw_main_flow_call_argument(source) + + assert projected is source + assert image_payload_mask(projected) is mask + assert image_payload_metadata(projected).source_spatial_domain.origin_yx == (2, 3) + assert image_payload_metadata(projected).source_image_paths == ("/input/rgb.tif",) + assert contract.raw_main_flow_call_argument(pixels) is pixels + + +@pytest.mark.parametrize("shape", ((5, 5), (4, 7))) +@pytest.mark.parametrize("shape_choice", (ShapeChoice.RECTANGLE, ShapeChoice.NATURAL, ShapeChoice.CIRCLE_NATURAL)) +def test_prepared_grid_objects_preserve_rgb_mask_calibration_and_crop_domain(shape, shape_choice): + pixels = np.arange(np.prod(shape) * 3, dtype=np.float32).reshape(*shape, 3) + mask = np.ones(shape, dtype=bool) + mask[0] = False + metadata = ImagePayloadMetadata( + source_path="/input/grid_rgb.tif", + source_channel_axis=-1, + source_voxel_spacing=SourceVoxelSpacing((2.0, 0.7, 0.9)), + source_spatial_domain=SourceSpatialDomain( + origin_yx=(2, 3), source_shape_yx=(shape[0] + 4, shape[1] + 6), + ), + ) + source = metadata.payload_with(pixels, mask) + grid = SpatialGrid( + name="Grid", rows=1, columns=1, x_spacing=4.0, y_spacing=4.0, + x_origin=2.0, y_origin=2.0, source_spatial_shape_yx=shape, + ) + guide_pixels = np.zeros(shape, dtype=np.int32) + guide_pixels[1:3, 1:4] = 1 + guides = SourceImageObjectLabelBuildRequest(image=source, labels=guide_pixels).payload() + topology_inputs = (grid,) if shape_choice is ShapeChoice.RECTANGLE else (grid, guides) + contract = _prepared_contract(identify_objects_in_grid) + + returned_image, _rows, objects = CellProfilerFunctionContractExecutor().execute( + contract, contract.resolve_canonical_raw_callable(), source, + {"topology_inputs": topology_inputs, "shape_choice": shape_choice}, + execution_mode=ImagePayloadExecutionMode.FULL_STACK, + ) + + assert returned_image is source + assert image_payload_mask(returned_image) is mask + assert objects.source_provenance == metadata.source_provenance + assert objects.source_spatial_domain.origin_yx == (2, 3) + assert objects.source_spatial_domain.source_shape_yx == metadata.source_spatial_domain.source_shape_yx + assert objects.parent_image_source_voxel_spacing == metadata.source_voxel_spacing + assert objects.labels.shape == shape + assert objects.domain.declared_object_count == 1 + assert objects.domain.declared_object_ids == (1,) + expanded = objects.source_spatial_domain.materialize(objects.labels, spatial_axes_yx=(0, 1)) + assert expanded.shape == metadata.source_spatial_domain.source_shape_yx + np.testing.assert_array_equal(expanded[2:2 + shape[0], 3:3 + shape[1]], objects.labels) + + +@pytest.mark.parametrize("color", (False, True)) +def test_prepared_align_preserves_named_plane_axis_masks_and_source_identity(color): + shape = (8, 9, 3) if color else (8, 9) + image = np.random.default_rng(1).random(shape, dtype=np.float32) + pixels = np.stack((image, image)) + masks = np.ones((2, 8, 9), dtype=bool) + masks[:, 0] = False + metadata = ImagePayloadMetadata( + source_image_names=("First", "Second"), + source_image_provenance_planes=SourceImageProvenancePlanes.from_components( + paths=("/input/first.tif", "/input/second.tif"), + component_metadata=({"well": "A01", "channel": "1"}, {"well": "A01", "channel": "2"}), + ), + plane_axis=RuntimePlaneAxis.SOURCE_BINDING, + source_channel_axis=3 if color else None, + source_spatial_domain=SourceSpatialDomain( + origin_yx=(2, 3), source_shape_yx=(14, 17) + ), + ) + source = metadata.payload_with(pixels, masks) + contract = _prepared_contract(align) + + outputs, measurements = CellProfilerFunctionContractExecutor().execute( + contract, + contract.resolve_canonical_raw_callable(), + source, + {"method": AlignModule.Method.NORMALIZED_CROSS_CORRELATION, + "crop_mode": AlignModule.CropMode.KEEP_SIZE}, + execution_mode=ImagePayloadExecutionMode.FULL_STACK, + ) + + assert len(outputs.slices) == 2 + assert measurements.row_count() == 2 + for index, output in enumerate(outputs.slices): + np.testing.assert_array_equal(image_payload_data(output), pixels[index]) + np.testing.assert_array_equal(image_payload_mask(output), masks[index]) + output_metadata = image_payload_metadata(output) + assert output_metadata.source_image_paths == (("/input/first.tif", "/input/second.tif")[index],) + assert output_metadata.source_spatial_domain == metadata.source_spatial_domain + assert output_metadata.source_channel_axis == (2 if color else None) + + +def test_prepared_crop_preserves_rgb_spatial_mask_and_calibrated_source_domain(): + pixels = np.arange(60, dtype=np.float32).reshape(4, 5, 3) + parent_mask = np.ones((4, 5), dtype=bool) + parent_mask[0] = False + domain = SourceSpatialDomain(origin_yx=(2, 3), source_shape_yx=(8, 10)) + source = ImagePayloadMetadata( + source_channel_axis=-1, + source_image_names=("RGB",), + source_path="/input/rgb.tif", + source_spatial_domain=domain, + ).payload_with(pixels, parent_mask) + contract = _prepared_contract(crop) + + output, cropping, measurements = CellProfilerFunctionContractExecutor().execute( + contract, + contract.resolve_canonical_raw_callable(), + source, + {"left_right_rectangle_positions": (1, 4), + "top_bottom_rectangle_positions": (0, 3), + "removal_method": CropModule.RemovalMethod.NO}, + execution_mode=ImagePayloadExecutionMode.NATURAL, + ) + + expected_crop = np.zeros((4, 5), dtype=bool) + expected_crop[:3, 1:4] = True + expected_pixels = pixels.copy() + expected_pixels[~expected_crop] = 0 + np.testing.assert_array_equal(cropping, expected_crop) + np.testing.assert_array_equal(image_payload_data(output), expected_pixels) + np.testing.assert_array_equal(image_payload_mask(output), expected_crop & parent_mask) + output_metadata = image_payload_metadata(output) + assert output_metadata.source_channel_axis == -1 + assert output_metadata.source_spatial_domain == domain + assert output_metadata.source_image_paths == ("/input/rgb.tif",) + assert measurements.row_count() == 1 + + +def test_prepared_threshold_keeps_owned_unit_interval_proof_and_mask(): + pixels = np.arange(20, dtype=np.uint8).reshape(4, 5) + mask = np.ones(pixels.shape, dtype=bool) + mask[0] = False + source = normalize_image_payload_intensity( + ImagePayloadMetadata.for_array(pixels).payload_with(pixels, mask), + dtype=np.float32, + ) + contract = _prepared_contract(threshold) + + projected = contract.raw_main_flow_call_argument(source) + + assert projected is source + assert image_payload_metadata(projected).unit_interval_intensity_scale == 255 + assert image_payload_mask(projected) is mask + np.testing.assert_array_equal(image_payload_data(projected), pixels.astype(np.float32) / 255) diff --git a/tests/unit/test_cellprofiler_artifact_declarations.py b/tests/unit/test_cellprofiler_artifact_declarations.py index 1515156c70..8331ca4488 100644 --- a/tests/unit/test_cellprofiler_artifact_declarations.py +++ b/tests/unit/test_cellprofiler_artifact_declarations.py @@ -2,6 +2,8 @@ from __future__ import annotations +from openhcs.core.pipeline.compilation_session import ResolvedPipelineDefinition + from dataclasses import replace from pathlib import Path from types import SimpleNamespace @@ -21,6 +23,7 @@ ArtifactSpecRelation, GroupLineageSourceRelation, ImageArtifactType, + InputImageSetContextSourceRelation, InputGroupLineageSourceRelation, MeasurementsArtifactType, ObjectLabelsArtifactType, @@ -47,7 +50,6 @@ ArtifactProducer, artifact_producers_for_outputs, ) -from openhcs.core.pipeline.step_snapshot import StepSnapshot from openhcs.core.source_bindings import ( ComponentSelector, NamedSourceBinding, @@ -157,7 +159,6 @@ def _compiler_contracts( ObjectStateRegistry.register(pipeline_state, _skip_snapshot=True) resolved_steps: list[FunctionStep] = [] step_states: dict[int, ObjectState] = {} - snapshots: list[StepSnapshot] = [] for index, step in enumerate(steps): step_state = ObjectState( step, @@ -169,13 +170,6 @@ def _compiler_contracts( assert isinstance(resolved_step, FunctionStep) resolved_steps.append(resolved_step) step_states[index] = step_state - snapshots.append( - StepSnapshot( - index=index, - scope_id=step_state.scope_id, - step=resolved_step, - ) - ) context = ProcessingContext( step_plans={ @@ -191,31 +185,29 @@ def _compiler_contracts( ) session = CompilationSession.from_context( context=context, - steps=resolved_steps, orchestrator=SimpleNamespace( pipeline_config=pipeline_state.to_object(), ), global_config=global_config, - step_state_map=step_states, - snapshots=tuple(snapshots), + pipeline=ResolvedPipelineDefinition( + steps=resolved_steps, step_state_map=step_states + ), ) provider = PipelineInvocationContractProviderAuthority.provider_for_session( session, ) contracts: list[CallableContract] = [] - for snapshot in snapshots: - invocations = tuple( - normalize_function_pattern(snapshot.step.func).iter_items() - ) + for index, snapshot in enumerate(resolved_steps): + invocations = tuple(normalize_function_pattern(snapshot.func).iter_items()) assert len(invocations) == 1 plan = provider( invocations[0], ArtifactDeclarationStepContext( - step_name=snapshot.step.name, - step_index=snapshot.index, - source_bindings=snapshot.step.source_bindings, - group_by=snapshot.step.processing_config.group_by, - input_source=snapshot.step.processing_config.input_source, + step_name=snapshot.name, + step_index=index, + source_bindings=snapshot.source_bindings, + group_by=snapshot.processing_config.group_by, + input_source=snapshot.processing_config.input_source, ), ) assert plan is not None @@ -444,6 +436,59 @@ def test_measurement_output_separates_provenance_from_invocation_group_scope() - assert output.source_stack_scope_sources() == () +def test_object_measurement_context_uses_only_selected_image_inputs() -> None: + available = ArtifactSpecCollection( + ( + ArtifactSpec.output("DNA", ImageArtifactType), + ArtifactSpec.output("Actin", ImageArtifactType), + ArtifactSpec.output("Unselected", ImageArtifactType), + ArtifactSpec.output("Nuclei", ObjectLabelsArtifactType), + ArtifactSpec.output("Cells", ObjectLabelsArtifactType), + ) + ) + contract = _callable_contract( + _module( + 3, + "MeasureObjectIntensity", + { + "Select images to measure": "DNA,Actin", + "Select objects to measure": "Nuclei,Cells", + }, + ), + step_index=2, + available_artifacts=available, + main_flow_artifacts=ArtifactSpecCollection(()), + ) + images = contract.artifact_inputs.of_artifact_type(ImageArtifactType) + objects = contract.artifact_inputs.of_artifact_type(ObjectLabelsArtifactType) + assert tuple(spec.name for spec in images) == ("DNA", "Actin") + assert tuple(spec.name for spec in objects) == ("Nuclei", "Cells") + for spec in objects: + assert spec.source_context_sources() == tuple(image.ref() for image in images) + assert spec.relations == tuple( + InputImageSetContextSourceRelation(image.ref()) for image in images + ) + assert spec.group_scope_sources() == () + assert spec.source_stack_scope_sources() == () + assert spec.stack_broadcast_sources() == () + + +def test_object_only_measurement_does_not_inherit_visible_image_context() -> None: + contract = _callable_contract( + _module(3, "MeasureObjectSizeShape", {"Select objects to measure": "Cells"}), + step_index=2, + available_artifacts=ArtifactSpecCollection( + ( + ArtifactSpec.input("DNA", ImageArtifactType), + ArtifactSpec.output("Cells", ObjectLabelsArtifactType), + ) + ), + main_flow_artifacts=ArtifactSpecCollection(()), + ) + (objects,) = contract.artifact_inputs.of_artifact_type(ObjectLabelsArtifactType) + assert objects.source_context_sources() == () + + def test_prior_measurement_selects_its_declared_producer_group_scope() -> None: green = ArtifactSpec.input("OrigGreen", ImageArtifactType) blue = ArtifactSpec.input("OrigBlue", ImageArtifactType) diff --git a/tests/unit/test_cellprofiler_backend_public_api.py b/tests/unit/test_cellprofiler_backend_public_api.py index 9e78196358..e71d99fd6f 100644 --- a/tests/unit/test_cellprofiler_backend_public_api.py +++ b/tests/unit/test_cellprofiler_backend_public_api.py @@ -284,6 +284,35 @@ def test_callable_ownership_uses_complete_import_identity() -> None: assert CellProfilerModule.for_callable_contract(numpy_contract) is None + +@pytest.mark.parametrize("mutation", ("replacement", "unowned_exclusion")) +def test_compiled_callable_owner_keeps_current_declaration_admission( + monkeypatch: pytest.MonkeyPatch, + mutation: str, +) -> None: + module = CellProfilerModule.require_module("Crop") + raw = module.require_callable() + contract = CallableContract.from_prepared_callable(raw) + if mutation == "replacement": + implementation_module = importlib.import_module(module.__module__) + monkeypatch.setattr( + implementation_module, contract.function_name, lambda image: image + ) + with pytest.raises( + ValueError, match="not the declaration-owned canonical callable" + ): + CellProfilerModule.require_callable_contract_owner(contract) + else: + from python_introspect import parameter_exclusions, set_parameter_exclusions + + original = parameter_exclusions(raw) + try: + set_parameter_exclusions(raw, (*original, "undeclared_runtime_input")) + with pytest.raises(ValueError, match="undeclared_runtime_input"): + CellProfilerModule.require_callable_contract_owner(contract) + finally: + set_parameter_exclusions(raw, original) + def test_duplicate_function_ownership_fails_during_module_declaration() -> None: existing_owner = CellProfilerModule.require_module("Crop") diff --git a/tests/unit/test_cellprofiler_combineobjects_source_scope.py b/tests/unit/test_cellprofiler_combineobjects_source_scope.py index 08323bf0a5..2328a2c0f3 100644 --- a/tests/unit/test_cellprofiler_combineobjects_source_scope.py +++ b/tests/unit/test_cellprofiler_combineobjects_source_scope.py @@ -30,7 +30,6 @@ PathPlannerExecutionGroups, PathPlannerGroupScope, ) -from openhcs.core.pipeline.step_snapshot import StepSnapshot from openhcs.core.progress import set_progress_queue from openhcs.core.source_bindings import ( NamedSourceBinding, @@ -103,7 +102,7 @@ def combine(object_labels): ), source_bindings=source_bindings, ) - snapshot = StepSnapshot(index=0, scope_id="combine", step=step) + snapshot = step planner = SimpleNamespace( declared={}, artifact_context=ArtifactDeclarationStepContext( @@ -112,7 +111,6 @@ def combine(object_labels): session=SimpleNamespace( realized_source_metadata=({"source_alias": source.name, "channel": "2"},), ), - source_bindings_for_snapshot=lambda _snapshot: source_bindings, ) scope = PathPlannerExecutionGroups(planner).artifact_owned_execution_scope( diff --git a/tests/unit/test_cellprofiler_conditional_topology_declarations.py b/tests/unit/test_cellprofiler_conditional_topology_declarations.py index c07c1b331b..118dd97e6a 100644 --- a/tests/unit/test_cellprofiler_conditional_topology_declarations.py +++ b/tests/unit/test_cellprofiler_conditional_topology_declarations.py @@ -583,7 +583,7 @@ def test_watershed_contract_uses_active_roles_and_preserves_reuse() -> None: "Input", ) assert WatershedModule.primary_image_inputs( - watershed_library, + contracts[0], contracts[0].artifact_inputs, ) == (contracts[0].artifact_inputs[0],) assert _contract_input_names(contracts[0]) == ("Input",) diff --git a/tests/unit/test_cellprofiler_display_manual_projection_declarations.py b/tests/unit/test_cellprofiler_display_manual_projection_declarations.py index 32f5048dd3..3c69d8f79e 100644 --- a/tests/unit/test_cellprofiler_display_manual_projection_declarations.py +++ b/tests/unit/test_cellprofiler_display_manual_projection_declarations.py @@ -329,7 +329,7 @@ def test_histogram_float_range_reconstructs_as_one_cellprofiler_setting_row() -> assert consumed == () assert len(blocks) == 1 range_rows = tuple( - record.value + record for record in blocks[0].setting_records if record.name == "Minimum/maximum values for the X-axis" ) diff --git a/tests/unit/test_cellprofiler_export_measurement_outputs.py b/tests/unit/test_cellprofiler_export_measurement_outputs.py index 1617ca8a64..ec642a0379 100644 --- a/tests/unit/test_cellprofiler_export_measurement_outputs.py +++ b/tests/unit/test_cellprofiler_export_measurement_outputs.py @@ -42,7 +42,7 @@ SourceImageSetIdentityPolicy, with_original_source_metadata, ) -from openhcs.core.steps.function_runtime import FunctionOutputContextStrategy + from openhcs.interop.cellprofiler.parser import ModuleBlock, ModuleSetting from openhcs.interop.cellprofiler.setting_names import optional_setting_value from openhcs.processing.backends.cellprofiler.export_to_database import ( @@ -379,9 +379,7 @@ def test_save_images_file_measurement_output_and_rows_are_conditional() -> None: source_path="/input/DNA.png", source_image_names=("DNA",), ).payload_with(image, None) - contextualized = FunctionOutputContextStrategy.for_output_plan( - measurement_plan - ).contextualize(source, rows, measurement_plan, None) + contextualized = (ImageArtifactType if measurement_plan is None else measurement_plan.artifact_type).contextualize_output(source, rows, measurement_plan, None) assert isinstance(contextualized, MeasurementTable) assert contextualized.name == measurement.name diff --git a/tests/unit/test_cellprofiler_function_contract_execution.py b/tests/unit/test_cellprofiler_function_contract_execution.py index 2a61995cec..76ca8ec07f 100644 --- a/tests/unit/test_cellprofiler_function_contract_execution.py +++ b/tests/unit/test_cellprofiler_function_contract_execution.py @@ -2,10 +2,16 @@ from __future__ import annotations -from collections.abc import Callable +from collections.abc import Callable, Sequence +from dataclasses import dataclass, replace +from functools import wraps +import inspect +from typing import Annotated, Any, Union import numpy as np import pytest +from arraybridge import ArrayPayload +import openhcs.core.callable_contract as callable_contract_module from openhcs.core.aligned_image_payload import ( AlignedImageStack, @@ -18,7 +24,12 @@ ImageArtifactType, MeasurementsArtifactType, ) -from openhcs.core.callable_contract import CallableContract, CallableMetadata +from openhcs.core.callable_contract import ( + CallableContract, + CallableMetadata, + CallableProjection, + callable_request, +) from openhcs.core.runtime_plane_projection import ( RuntimePlaneAxis, RuntimePlaneAxisValueProjection, @@ -28,15 +39,26 @@ from openhcs.core.runtime_image_values import ( ImagePayloadMetadata, image_payload_data, + image_payload_mask, + image_payload_metadata, ) +from openhcs.core.runtime_array_values import RuntimeArrayData from openhcs.core.source_spatial_domain import SourceSpatialDomain from openhcs.core.source_image_provenance import SourceImageProvenancePlanes from openhcs.interop.cellprofiler.runtime.function_contract_execution import ( CellProfilerFunctionContractExecutor, ) +from openhcs.interop.cellprofiler.runtime.adapter import CellProfilerRuntimeAdapter from openhcs.processing.backends.cellprofiler.alignment import AlignShiftMeasurement -from openhcs.processing.backends.cellprofiler.morphology import morphologicalskeleton +from openhcs.processing.backends.cellprofiler.morphology import ( + MorphOperation, + morph, + morphologicalskeleton, +) from openhcs.processing.backends.lib_registry.unified_registry import ProcessingContract +from openhcs.processing.backends.lib_registry.unified_registry import ( + RuntimeCallablePolicy, RuntimeInvocationKwargPolicy, +) def _compiled_contract( @@ -55,7 +77,7 @@ def _compiled_contract( artifact_inputs=artifact_inputs, artifact_outputs=artifact_outputs, ), - ) + ).with_prepared_signature() def test_morphological_skeleton_executes_one_planar_runtime_image() -> None: @@ -76,6 +98,545 @@ def test_morphological_skeleton_executes_one_planar_runtime_image() -> None: assert image_payload_data(result).shape == image.shape +def test_registered_morph_distance_projects_raw_abi_and_retains_source_context() -> None: + contract = CallableContract.from_callable(morph) + contract = replace( + contract, + metadata=replace( + contract.metadata, + runtime_adapter=CellProfilerRuntimeAdapter.runtime_adapter_spec(), + artifact_outputs=(ArtifactSpec.output("Distance", ImageArtifactType),), + ), + ) + pixels = np.zeros((1, 7, 7), dtype=np.float32) + pixels[:, 2:5, 2:5] = 1 + mask = np.ones_like(pixels, dtype=bool) + source = ImagePayloadMetadata( + plane_axis=RuntimePlaneAxis.RUNTIME_SLICE, + source_image_names=("SavedLabels",), + source_image_provenance_planes=SourceImageProvenancePlanes.from_components( + paths=("/tmp/saved-labels.tif",), + component_metadata=({"channel": "2", "well": "A01"},), + ), + ).payload_with(pixels, mask) + expected = contract.resolve_raw_runtime_callable()( + pixels[0], operation=MorphOperation.DISTANCE + ) + + result = CellProfilerFunctionContractExecutor().execute( + contract, + contract.resolve_canonical_raw_callable(), + source, + {"operation": MorphOperation.DISTANCE}, + execution_mode=ImagePayloadExecutionMode.NATURAL, + plane_projection=RuntimePlaneAxisValueProjection.preserve( + axis=RuntimePlaneAxis.RUNTIME_SLICE, axis_size=1, + ), + ) + + np.testing.assert_array_equal(image_payload_data(result), expected[None]) + np.testing.assert_array_equal(image_payload_mask(result), mask) + metadata = image_payload_metadata(result) + assert metadata.plane_axis is RuntimePlaneAxis.RUNTIME_SLICE + assert metadata.source_image_names == ("SavedLabels",) + assert metadata.source_image_provenance_planes.paths == ("/tmp/saved-labels.tif",) + assert metadata.source_image_provenance_planes.component_metadata == ( + {"channel": "2", "well": "A01"}, + ) + + +@pytest.mark.parametrize("payload_annotation", (False, True)) +def test_raw_slice_abi_retains_declared_payloads_and_projects_kwargs( + payload_annotation: bool, +) -> None: + seen = [] + + def array_raw(image: np.ndarray, *, labels: np.ndarray) -> np.ndarray: + assert isinstance(image, np.ndarray) + seen.append((image, labels)) + return image + labels + + def payload_raw(image: ArrayPayload, *, labels: np.ndarray) -> ArrayPayload: + assert isinstance(image, ArrayPayload) + seen.append((image, labels)) + return image_payload_metadata(image).payload_with( + image_payload_data(image) + labels, image_payload_mask(image), + ) + + raw = payload_raw if payload_annotation else array_raw + contract = _compiled_contract(raw, ProcessingContract.PURE_2D) + contract = replace( + contract, + metadata=replace( + contract.metadata, + runtime_adapter=CellProfilerRuntimeAdapter.runtime_adapter_spec(), + ), + ) + source = ImagePayloadMetadata(source_image_names=("DNA",)).payload_with( + np.ones((3, 4), dtype=np.float32), np.ones((3, 4), dtype=bool), + ) + selected_labels = np.full((3, 4), 5, dtype=np.float32) + executor = CellProfilerFunctionContractExecutor( + plane_projection=RuntimePlaneAxisValueProjection.preserve( + axis=RuntimePlaneAxis.RUNTIME_SLICE, axis_size=2, + ), + ) + + assert contract.runtime_main_flow_call_argument(source) is source + result = executor.execute_pure_2d_slice( + contract, raw, source, + {"labels": RuntimeSliceAlignedValues(slices=(np.zeros((3, 4)), selected_labels)), + "adapter_only_control": 1}, + 1, 2, + ) + + assert seen[0][0] is (source if payload_annotation else image_payload_data(source)) + assert seen[0][1] is selected_labels + np.testing.assert_array_equal(image_payload_data(result), np.full((3, 4), 6)) + np.testing.assert_array_equal(image_payload_mask(result), image_payload_mask(source)) + assert image_payload_metadata(result).source_image_names == ("DNA",) + + +def test_raw_slice_abi_does_not_relax_output_mask_shape_validation() -> None: + def bad_shape(image: np.ndarray) -> np.ndarray: + assert isinstance(image, np.ndarray) + return image[:1] + + contract = _compiled_contract(bad_shape, ProcessingContract.PURE_2D) + source = ImagePayloadMetadata(source_image_names=("DNA",)).payload_with( + np.ones((3, 4)), np.ones((3, 4), dtype=bool), + ) + executor = CellProfilerFunctionContractExecutor( + plane_projection=RuntimePlaneAxisValueProjection.preserve( + axis=RuntimePlaneAxis.RUNTIME_SLICE, axis_size=1, + ), + ) + with pytest.raises(ValueError, match="[Mm]ask.*shape|shape.*[Mm]ask"): + executor.execute_pure_2d_slice(contract, bad_shape, source, {}, 0, 1) + + +@pytest.mark.parametrize("payload_annotation", (False, True)) +@pytest.mark.parametrize( + ("processing_contract", "execution_mode"), + ( + (ProcessingContract.PURE_2D, ImagePayloadExecutionMode.NATURAL), + (ProcessingContract.PURE_3D, ImagePayloadExecutionMode.NATURAL), + (ProcessingContract.PURE_2D, ImagePayloadExecutionMode.FULL_STACK), + (ProcessingContract.PURE_3D, ImagePayloadExecutionMode.FULL_STACK), + ), +) +def test_raw_abi_projection_matches_declared_argument_in_single_and_full_stack_modes( + payload_annotation: bool, + processing_contract: ProcessingContract, + execution_mode: ImagePayloadExecutionMode, +) -> None: + seen = [] + + def array_raw(image: np.ndarray) -> np.ndarray: + assert isinstance(image, np.ndarray) + seen.append(image) + return image + + def payload_raw(image: ArrayPayload) -> ArrayPayload: + assert isinstance(image, ArrayPayload) + seen.append(image) + return image + + raw = payload_raw if payload_annotation else array_raw + contract = _compiled_contract(raw, processing_contract) + contract = replace( + contract, + metadata=replace( + contract.metadata, + runtime_adapter=CellProfilerRuntimeAdapter.runtime_adapter_spec(), + artifact_outputs=(ArtifactSpec.output("Result", ImageArtifactType),), + ), + ) + source = ImagePayloadMetadata(source_image_names=("DNA",)).payload_with( + np.ones((3, 4)), None, + ) + + result = CellProfilerFunctionContractExecutor().execute( + contract, raw, source, {}, execution_mode=execution_mode, + ) + + assert seen == [source if payload_annotation else image_payload_data(source)] + assert seen[0] is (source if payload_annotation else image_payload_data(source)) + assert result is seen[0] + + +@pytest.mark.parametrize( + ("annotation", "retains_payload"), + ( + (np.ndarray, False), + (ArrayPayload, True), + (RuntimeArrayData, True), + (Union[ArrayPayload, np.ndarray], True), + (Annotated[ArrayPayload, "source context"], True), + (Annotated[RuntimeArrayData, "source context"], True), + (Union[Annotated[ArrayPayload, "source context"], np.ndarray], True), + (Union[Annotated[RuntimeArrayData, "source context"], None], True), + (object, True), + (Any, False), + (inspect.Parameter.empty, False), + (Sequence[ArrayPayload], False), + (tuple[ArrayPayload, ...], False), + ), +) +def test_canonical_argument_projection_uses_declared_nominal_annotation( + annotation: object, retains_payload: bool, +) -> None: + def raw(image): + return image + + if annotation is not inspect.Parameter.empty: + raw.__annotations__["image"] = annotation + contract = _compiled_contract(raw, ProcessingContract.PURE_2D) + source = ImagePayloadMetadata(source_image_names=("DNA",)).payload_with( + np.ones((3, 4)), None, + ) + expected = source if retains_payload else image_payload_data(source) + + assert contract.raw_main_flow_call_argument(source) is expected + assert contract.runtime_main_flow_call_argument(source) is expected + adapted = replace( + contract, + metadata=replace( + contract.metadata, + runtime_adapter=CellProfilerRuntimeAdapter.runtime_adapter_spec(), + ), + ) + assert adapted.raw_main_flow_call_argument(source) is expected + assert adapted.runtime_main_flow_call_argument(source) is source + + +def test_raw_slice_argument_retains_buffer_identity_for_inplace_array_callable() -> None: + def inplace(image: np.ndarray) -> np.ndarray: + image[0, 0] = 7 + return image + + contract = _compiled_contract(inplace, ProcessingContract.PURE_2D) + pixels = np.zeros((3, 4)) + source = ImagePayloadMetadata(source_image_names=("DNA",)).payload_with( + pixels, None, + ) + executor = CellProfilerFunctionContractExecutor( + plane_projection=RuntimePlaneAxisValueProjection.preserve( + axis=RuntimePlaneAxis.RUNTIME_SLICE, axis_size=1, + ), + ) + result = executor.execute_pure_2d_slice(contract, inplace, source, {}, 0, 1) + + assert image_payload_data(result) is pixels + assert pixels[0, 0] == 7 + + +def test_prepared_raw_abi_performs_no_introspection_until_explicit_refresh( + monkeypatch: pytest.MonkeyPatch, +) -> None: + seen = [] + + def raw(image: np.ndarray) -> np.ndarray: + seen.append(isinstance(image, ArrayPayload)) + return image_payload_data(image) + + contract = _compiled_contract( + raw, ProcessingContract.PURE_2D, + artifact_outputs=(ArtifactSpec.output("Result", ImageArtifactType),), + ) + source = ImagePayloadMetadata( + plane_axis=RuntimePlaneAxis.RUNTIME_SLICE, source_image_names=("DNA",), + ).payload_with(np.ones((12, 3, 4)), None) + projection = RuntimePlaneAxisValueProjection.preserve( + axis=RuntimePlaneAxis.RUNTIME_SLICE, axis_size=12, + ) + executor = CellProfilerFunctionContractExecutor(plane_projection=projection) + hints = [] + signatures = [] + original_hints = callable_contract_module.get_type_hints + original_signature = inspect.signature + + def counted_hints(func, **kwargs): + hints.append((func, kwargs)) + return original_hints(func, **kwargs) + + def counted_signature(func, **kwargs): + caller = inspect.currentframe().f_back + if caller.f_globals is callable_contract_module.__dict__: + signatures.append(caller.f_code.co_name) + return original_signature(func, **kwargs) + + monkeypatch.setattr(callable_contract_module, "get_type_hints", counted_hints) + monkeypatch.setattr(inspect, "signature", counted_signature) + + for annotation in (np.ndarray, ArrayPayload): + raw.__annotations__["image"] = annotation + contract = contract.with_prepared_signature() + result = executor.execute( + contract, raw, source, {}, + execution_mode=ImagePayloadExecutionMode.NATURAL, + plane_projection=projection, + ) + np.testing.assert_array_equal(image_payload_data(result), image_payload_data(source)) + + assert seen == [False] * 12 + [True] * 12 + assert hints == [(raw, {"include_extras": True})] * 2 + assert signatures == ["resolve_signature"] * 2 + assert not hasattr(executor, "_raw_argument_types") + + +def test_raw_abi_derivation_follows_existing_input_guards(monkeypatch) -> None: + def raw(image: np.ndarray) -> np.ndarray: + raise AssertionError("Invalid image reached raw execution") + + contract = _compiled_contract(raw, ProcessingContract.PURE_2D) + + def reject_premature_annotations(self): + raise AssertionError("Input guard resolved the raw ABI prematurely") + + monkeypatch.setattr( + CallableContract, "canonical_parameter_declarations", + property(reject_premature_annotations), + ) + with pytest.raises(TypeError, match="requires AlignedImageStack"): + CellProfilerFunctionContractExecutor().execute( + contract, raw, np.zeros((2, 3)), {}, + execution_mode=ImagePayloadExecutionMode.ALIGNED_MULTI_IMAGE_STACK, + ) + projection = RuntimePlaneAxisValueProjection.preserve( + axis=RuntimePlaneAxis.RUNTIME_SLICE, axis_size=2, + ) + mismatched_image = ImagePayloadMetadata( + plane_axis=RuntimePlaneAxis.SOURCE_BINDING, + ).payload_with(np.zeros((2, 3, 4)), None) + with pytest.raises(RuntimeSliceProjectionDeclarationError, match="conflicts"): + CellProfilerFunctionContractExecutor().execute( + contract, raw, mismatched_image, {}, + execution_mode=ImagePayloadExecutionMode.NATURAL, + plane_projection=projection, + ) + + +def test_raw_abi_child_preserves_cooperative_executor_constructor_contract() -> None: + constructed = [] + raw_calls = [] + + class CooperativeExecutor(CellProfilerFunctionContractExecutor): + def __init__(self, plane_projection=None): + super().__init__(plane_projection=plane_projection) + constructed.append(self) + + def execute_pure_2d_slice(self, *args, **kwargs): + raw_calls.append(self) + return super().execute_pure_2d_slice(*args, **kwargs) + + def raw(image: np.ndarray) -> np.ndarray: + assert isinstance(image, np.ndarray) + return image + + contract = _compiled_contract( + raw, ProcessingContract.PURE_2D, + artifact_outputs=(ArtifactSpec.output("Result", ImageArtifactType),), + ) + source = ImagePayloadMetadata(plane_axis=RuntimePlaneAxis.RUNTIME_SLICE).payload_with( + np.ones((2, 3, 4)), None, + ) + executor = CooperativeExecutor() + result = executor.execute( + contract, raw, source, {}, execution_mode=ImagePayloadExecutionMode.NATURAL, + plane_projection=RuntimePlaneAxisValueProjection.preserve( + axis=RuntimePlaneAxis.RUNTIME_SLICE, axis_size=2, + ), + ) + + assert len(constructed) == 2 + assert raw_calls == [constructed[1]] * 2 + assert not hasattr(executor, "_raw_argument_types") + np.testing.assert_array_equal(image_payload_data(result), image_payload_data(source)) + + def foreign_raw(image: ArrayPayload) -> ArrayPayload: + assert isinstance(image, ArrayPayload) + return image + + foreign_contract = _compiled_contract(foreign_raw, ProcessingContract.PURE_2D) + child = constructed[1] + policy = RuntimeCallablePolicy(kwarg_policy=RuntimeInvocationKwargPolicy.SIGNATURE_FILTERED) + assert policy.contract_invocation(foreign_contract, foreign_raw, source, {}).call() is source + assert not hasattr(child, "_scope_contract") + + +def test_actual_prepared_executor_planes_make_no_signature_or_hint_queries(monkeypatch) -> None: + calls = [] + def raw(image: np.ndarray, scale: int = 2) -> np.ndarray: + calls.append(image.shape) + return image * scale + CallableProjection.from_callable(raw).warm_canonical_signature() + contract = _compiled_contract( + raw, ProcessingContract.PURE_2D, + artifact_outputs=(ArtifactSpec.output("Result",ImageArtifactType),), + ) + source = ImagePayloadMetadata( + plane_axis=RuntimePlaneAxis.RUNTIME_SLICE,source_image_names=("DNA",), + ).payload_with(np.ones((12,3,4)),None) + projection = RuntimePlaneAxisValueProjection.preserve(axis=RuntimePlaneAxis.RUNTIME_SLICE,axis_size=12) + def forbidden(*args, **kwargs): + raise AssertionError("Prepared execution introspected a live callable") + monkeypatch.setattr(inspect,"signature",forbidden) + monkeypatch.setattr(callable_contract_module,"get_type_hints",forbidden) + result = CellProfilerFunctionContractExecutor().execute( + contract,raw,source,{},execution_mode=ImagePayloadExecutionMode.NATURAL, + plane_projection=projection, + ) + np.testing.assert_array_equal(image_payload_data(result),np.full((12,3,4),2)) + assert calls == [(3,4)]*12 + + +def test_authored_distinct_raw_abi_batch_has_no_runtime_queries_and_filters_controls(monkeypatch) -> None: + from openhcs.core.processing_preparation import CallablePreparation + calls = [] + def raw(image: np.ndarray, scale: int = 2) -> np.ndarray: + calls.append(image.shape) + return image * scale + @wraps(raw) + def wrapper(*args, **kwargs): + return raw(*args, **kwargs) + wrapper.__signature__ = inspect.signature(raw).replace(parameters=[ + *inspect.signature(raw).parameters.values(), + inspect.Parameter("injected",inspect.Parameter.KEYWORD_ONLY,default=False), + ]) + monkeypatch.setattr(CallablePreparation,"prepare",lambda self:None) + contract = CallableContract.from_prepared_callable(wrapper) + contract = replace(contract,metadata=replace( + contract.metadata,processing_contract=ProcessingContract.PURE_2D, + artifact_outputs=(ArtifactSpec.output("Result",ImageArtifactType),), + )) + source = ImagePayloadMetadata(plane_axis=RuntimePlaneAxis.RUNTIME_SLICE,source_image_names=("DNA",)).payload_with(np.ones((12,3,4)),None) + projection = RuntimePlaneAxisValueProjection.preserve(axis=RuntimePlaneAxis.RUNTIME_SLICE,axis_size=12) + def forbidden(*args, **kwargs): + raise AssertionError("Prepared authored raw target queried a live signature") + monkeypatch.setattr(inspect,"signature",forbidden) + monkeypatch.setattr(callable_contract_module,"get_type_hints",forbidden) + result = CellProfilerFunctionContractExecutor().execute( + contract,wrapper,source,{"injected":True}, + execution_mode=ImagePayloadExecutionMode.NATURAL,plane_projection=projection, + ) + np.testing.assert_array_equal(image_payload_data(result),np.full((12,3,4),2)) + assert calls == [(3,4)]*12 + + +def test_compiled_slice_execution_resolves_raw_target_once_and_preserves_request_binding( + monkeypatch: pytest.MonkeyPatch, +) -> None: + @dataclass(frozen=True, slots=True) + class ScaleRequest: + image: object + scale: int + + seen: list[tuple[int, ...]] = [] + + @callable_request(ScaleRequest) + def request_bound(request: ScaleRequest) -> object: + data = image_payload_data(request.image) + seen.append(data.shape) + return data * request.scale + + @wraps(request_bound) + def decorated(*args: object, **kwargs: object) -> object: + raise AssertionError("CellProfiler invoked an outer runtime wrapper") + + contract = CallableContract.from_callable(decorated).with_prepared_signature() + contract = replace( + contract, + metadata=replace( + contract.metadata, + processing_contract=ProcessingContract.PURE_2D, + ), + ) + raw_target = contract.resolve_canonical_raw_callable() + resolve_raw = CallableContract.resolve_raw_runtime_callable + resolutions: list[CallableContract] = [] + + def resolve_once(self: CallableContract) -> Callable[..., object]: + resolutions.append(self) + return resolve_raw(self) + + def reject_reconstruction(*args: object, **kwargs: object) -> CallableContract: + raise AssertionError("Runtime execution rebuilt its compiled contract") + + monkeypatch.setattr(CallableContract, "resolve_raw_runtime_callable", resolve_once) + monkeypatch.setattr(CallableContract, "from_callable", reject_reconstruction) + image = ImagePayloadMetadata( + plane_axis=RuntimePlaneAxis.RUNTIME_SLICE + ).payload_with(np.ones((3, 4, 5), dtype=np.float32), None) + + result = CellProfilerFunctionContractExecutor().execute( + contract, + raw_target, + image, + {"scale": 4, "adapter_control": 17}, + execution_mode=ImagePayloadExecutionMode.NATURAL, + plane_projection=RuntimePlaneAxisValueProjection.preserve( + axis=RuntimePlaneAxis.RUNTIME_SLICE, + axis_size=3, + ), + ) + + assert resolutions == [contract] + assert seen == [(4, 5)] * 3 + assert isinstance(result, RuntimeSliceAlignedValues) + np.testing.assert_array_equal( + np.stack(tuple(image_payload_data(value) for value in result.slices)), + np.full((3, 4, 5), 4.0), + ) + + +@pytest.mark.parametrize("canonical_default", (False, True)) +def test_flexible_dispatch_preserves_canonical_signature_control_defaults( + canonical_default: bool, +) -> None: + seen: list[tuple[tuple[int, ...], bool]] = [] + + def raw(image: np.ndarray, *, slice_by_slice: bool = False) -> np.ndarray: + seen.append((image.shape, slice_by_slice)) + return image + + @wraps(raw) + def decorated(*args: object, **kwargs: object) -> object: + raise AssertionError("CellProfiler invoked an outer runtime wrapper") + + signature = inspect.signature(raw) + decorated.__signature__ = signature.replace( + parameters=( + parameter.replace(default=canonical_default) + if parameter.name == "slice_by_slice" + else parameter + for parameter in signature.parameters.values() + ) + ) + contract = _compiled_contract(decorated, ProcessingContract.FLEXIBLE) + image = ImagePayloadMetadata( + plane_axis=RuntimePlaneAxis.RUNTIME_SLICE + ).payload_with(np.ones((3, 4, 5), dtype=np.float32), None) + + CellProfilerFunctionContractExecutor().execute( + contract, + decorated, + image, + {}, + execution_mode=ImagePayloadExecutionMode.NATURAL, + plane_projection=RuntimePlaneAxisValueProjection.preserve( + axis=RuntimePlaneAxis.RUNTIME_SLICE, + axis_size=3, + ), + ) + + assert seen == ( + [((4, 5), True)] * 3 + if canonical_default + else [((3, 4, 5), False)] + ) + + @pytest.mark.parametrize("processing_contract", tuple(ProcessingContract)) @pytest.mark.parametrize( ("image_mode", "expected_call_count"), diff --git a/tests/unit/test_cellprofiler_geometry_prepared_payload_abi.py b/tests/unit/test_cellprofiler_geometry_prepared_payload_abi.py new file mode 100644 index 0000000000..a0396a3de5 --- /dev/null +++ b/tests/unit/test_cellprofiler_geometry_prepared_payload_abi.py @@ -0,0 +1,154 @@ +"""Geometry declarations preserve the payload their raw implementations consume.""" + +from dataclasses import replace +from typing import get_type_hints + +import numpy as np +import pytest + +from openhcs.core.aligned_image_payload import ImagePayloadExecutionMode +from openhcs.core.callable_contract import CallableContract +from openhcs.core.runtime_array_values import RuntimeArrayData +from openhcs.core.runtime_image_values import ( + ImagePayloadMetadata, + image_payload_data, + image_payload_mask, + image_payload_metadata, +) +from openhcs.core.runtime_plane_projection import RuntimePlaneAxis +from openhcs.core.source_spatial_domain import ( + SourceSpatialDomain, + VolumeSourceSpatialDomain, +) +from openhcs.interop.cellprofiler.runtime.adapter import CellProfilerRuntimeAdapter +from openhcs.interop.cellprofiler.runtime.function_contract_execution import ( + CellProfilerFunctionContractExecutor, +) +from openhcs.processing.backends.cellprofiler.image_geometry import ( + mask_image, + resize, + resize_volumetric, +) + + +def _prepared_contract(func): + contract = CallableContract.from_callable(func).with_prepared_signature() + return replace( + contract, + metadata=replace( + contract.metadata, + runtime_adapter=CellProfilerRuntimeAdapter.runtime_adapter_spec(), + ), + ) + + +@pytest.mark.parametrize("func", (resize, resize_volumetric)) +def test_prepared_resize_preserves_typed_primary_and_bare_array(func): + pixels = np.arange(24, dtype=np.float32).reshape(4, 6) + source = ImagePayloadMetadata( + source_path="/images/input.tif", source_image_names=("Original",), + ).payload_with(pixels, pixels % 2 == 0) + contract = _prepared_contract(func) + + assert contract.raw_main_flow_call_argument(source) is source + assert contract.raw_main_flow_call_argument(pixels) is pixels + + +@pytest.mark.parametrize("axis", (None, RuntimePlaneAxis.RUNTIME_SLICE)) +@pytest.mark.parametrize("z_factor", (1.0, 2.0)) +@pytest.mark.parametrize( + "domain_type", (SourceSpatialDomain, VolumeSourceSpatialDomain) +) +def test_prepared_full_stack_resize_preserves_existing_metadata_and_mask( + axis, + z_factor, + domain_type, +): + planes = tuple( + ImagePayloadMetadata( + source_path=f"/images/z{index}.tif", + source_image_names=("Original",), + source_component_metadata={"z_index": index, "timepoint": 1, "well": "W001"}, + source_spatial_domain=SourceSpatialDomain( + origin_yx=(2, 3), source_shape_yx=(8, 10), + ), + ).payload_with(np.full((4, 6), index, dtype=np.float32), None) + for index in (3, 1, 2) + ) + metadata = ImagePayloadMetadata.compose(planes).replace_fields(plane_axis=axis) + if domain_type is VolumeSourceSpatialDomain: + metadata = metadata.replace_fields( + source_spatial_domain=VolumeSourceSpatialDomain( + source_depth=3 + ).admit_source_cohort( + metadata.source_spatial_domain, + depth=3, + ) + ) + pixels = np.stack(tuple(image_payload_data(plane) for plane in planes)) + mask = np.ones(pixels.shape, dtype=bool) + mask[:, 0, 0] = False + source = metadata.payload_with(pixels, mask) + contract = _prepared_contract(resize_volumetric) + canonical = contract.resolve_canonical_raw_callable() + kwargs = dict( + resizing_factor_x=0.5, resizing_factor_y=0.5, resizing_factor_z=z_factor, + ) + expected = canonical(source, **kwargs) + + result = CellProfilerFunctionContractExecutor().execute( + contract, canonical, source, kwargs, + execution_mode=ImagePayloadExecutionMode.FULL_STACK, + ) + + np.testing.assert_array_equal( + image_payload_data(result), image_payload_data(expected) + ) + np.testing.assert_array_equal( + image_payload_mask(result), image_payload_mask(expected) + ) + assert image_payload_metadata(result) == image_payload_metadata(expected) + assert image_payload_metadata(result).plane_axis is axis + assert image_payload_metadata(result).source_image_paths == metadata.source_image_paths + assert image_payload_metadata(result).source_provenance == metadata.source_provenance + assert image_payload_metadata(result).source_spatial_domain.source_shape_yx == (2, 3) + assert isinstance(image_payload_metadata(result).source_spatial_domain, domain_type) + if domain_type is VolumeSourceSpatialDomain: + assert image_payload_metadata(result).source_spatial_domain.source_depth == 3 + assert image_payload_data(result).shape[0] == int(3 * z_factor) + assert image_payload_metadata(source) is metadata + np.testing.assert_array_equal(image_payload_data(source), pixels) + np.testing.assert_array_equal(image_payload_mask(source), mask) + + +@pytest.mark.parametrize("func", (resize, resize_volumetric)) +def test_prepared_resize_bare_pixels_preserve_canonical_return_contract(func): + pixels = np.arange(24, dtype=np.float32).reshape(4, 6) + contract = _prepared_contract(func) + canonical = contract.resolve_canonical_raw_callable() + kwargs = dict(resizing_factor_x=0.5, resizing_factor_y=0.5) + if func is resize_volumetric: + kwargs["resizing_factor_z"] = 1.0 + expected = canonical(pixels, **kwargs) + + result = CellProfilerFunctionContractExecutor().execute( + contract, canonical, pixels, kwargs, + execution_mode=ImagePayloadExecutionMode.FULL_STACK, + ) + + assert isinstance(result, RuntimeArrayData) + assert type(result) is type(expected) + np.testing.assert_array_equal(image_payload_data(result), image_payload_data(expected)) + np.testing.assert_array_equal(image_payload_mask(result), image_payload_mask(expected)) + assert image_payload_metadata(result) == image_payload_metadata(expected) + + +def test_mask_image_declares_its_actual_nominal_return_family(): + contract = _prepared_contract(mask_image) + canonical = contract.resolve_canonical_raw_callable() + assert get_type_hints(canonical)["return"] == RuntimeArrayData + pixels = np.arange(12, dtype=np.float32).reshape(3, 4) + source = ImagePayloadMetadata(source_path="/images/input.tif").payload_with(pixels) + result = canonical(source, pixels > 3) + assert isinstance(result, RuntimeArrayData) + assert image_payload_metadata(result).source_image_paths == ("/images/input.tif",) diff --git a/tests/unit/test_cellprofiler_image_quality.py b/tests/unit/test_cellprofiler_image_quality.py index 64165a0639..97a7b55813 100644 --- a/tests/unit/test_cellprofiler_image_quality.py +++ b/tests/unit/test_cellprofiler_image_quality.py @@ -31,7 +31,6 @@ ) from openhcs.core.runtime_image_values import ImagePayloadMetadata from openhcs.core.runtime_measurements import MeasurementTable -from openhcs.core.runtime_artifact_queries import MeasurementTableUnion from openhcs.core.runtime_tabular_values import ( FieldSpec, ) @@ -506,13 +505,14 @@ def test_quality_control_measurements_keep_distinct_site_image_identities() -> N ) for channel in range(1, 6) ) - union = MeasurementTableUnion("quality_metrics", tables) table = MeasureImageQualityModule.build_measurement_table( name="quality_metrics", - rows=union.rows(), + rows=ConcatenatedColumnarRows(tuple(table.rows for table in tables)), object_name=None, source_image_name=None, - source_metadata=union.source_metadata(), + source_metadata=ImagePayloadMetadata( + source_provenance=MeasurementTable.joined_source_provenance("quality_metrics", tables), + ), ) projected_rows = CellProfilerImageSetNumbering( diff --git a/tests/unit/test_cellprofiler_measurement_slice_consumers.py b/tests/unit/test_cellprofiler_measurement_slice_consumers.py index b03af8ce1e..b0091af7bc 100644 --- a/tests/unit/test_cellprofiler_measurement_slice_consumers.py +++ b/tests/unit/test_cellprofiler_measurement_slice_consumers.py @@ -3,7 +3,6 @@ from __future__ import annotations from dataclasses import replace -from types import SimpleNamespace from openhcs.core.artifacts import ( ArtifactInputPlan, @@ -33,8 +32,8 @@ from openhcs.interop.cellprofiler.runtime.artifact_binding import ( RuntimeInputBindingRequest, ) -from openhcs.interop.cellprofiler.runtime.object_measurement_tables import ( - ObjectMeasurementTableIndex, +from openhcs.core.measurement_feature_queries import ( + ColumnarMeasurementTableSchema, ) from openhcs.interop.cellprofiler.runtime.object_measurement_vectors import ( MeasurementImageOperandVectorResolution, @@ -52,7 +51,7 @@ def _measurement_consumer(image): class _MeasurementInputAdapter: def __init__( self, - runtime_values: tuple[object, ...], + runtime_values: tuple[RuntimeValue, ...], callable_contract: CallableContract, measurement_spec: ArtifactSpec, ) -> None: @@ -87,11 +86,11 @@ def artifact_input_records( self, name: str, artifact_type: type[MeasurementsArtifactType], - ) -> tuple[SimpleNamespace, ...]: + ) -> tuple[RuntimeValue, ...]: self.measurement_record_queries += 1 assert name == "measurements" assert artifact_type is MeasurementsArtifactType - return tuple(SimpleNamespace(value=value) for value in self._runtime_values) + return self._runtime_values def declared_measurement_input_records( self, @@ -99,7 +98,7 @@ def declared_measurement_input_records( group_key: str | None = None, match_group: bool = True, current_image: object | None = None, - ) -> tuple[SimpleNamespace, ...]: + ) -> tuple[RuntimeValue, ...]: del group_key, match_group, current_image return self.artifact_input_records("measurements", MeasurementsArtifactType) @@ -123,10 +122,11 @@ def test_object_measurement_index_preserves_producer_slice_indexes() -> None: for value in (11.0, 13.0) ) - indexed = ObjectMeasurementTableIndex.from_tables(tables) + indexed = tables assert tuple( - table.rows[0]["slice_index"] for table in indexed.for_object("Cells") + table.rows[0]["slice_index"] + for table in ColumnarMeasurementTableSchema.tables_for_object(indexed, "Cells") ) == (0, 0) @@ -147,9 +147,11 @@ def test_object_measurement_index_preserves_mixed_payload_and_slice_rows() -> No subject=MeasurementSubject(MeasurementScope.OBJECT, "Cells", "object_label"), ) - indexed = ObjectMeasurementTableIndex.from_tables((table,)) + indexed = (table,) - (indexed_table,) = indexed.for_object("Cells") + (indexed_table,) = ColumnarMeasurementTableSchema.tables_for_object( + indexed, "Cells" + ) assert tuple(indexed_table.rows) == tuple(table.rows) diff --git a/tests/unit/test_cellprofiler_measurement_source_names.py b/tests/unit/test_cellprofiler_measurement_source_names.py index fa1fcc1c84..73db9d361e 100644 --- a/tests/unit/test_cellprofiler_measurement_source_names.py +++ b/tests/unit/test_cellprofiler_measurement_source_names.py @@ -80,7 +80,7 @@ def source_image_name(spec: ArtifactSpec, value: SimpleNamespace) -> str: ) monkeypatch.setattr( module_execution, - "RuntimeArtifactTypeStrategy", + "CellProfilerOutputRecorder", SimpleNamespace(for_artifact_type=lambda _artifact_type: ArtifactStrategy()), ) @@ -110,9 +110,6 @@ def test_composed_measurement_caller_preserves_ordered_source_aliases() -> None: callable_contract=SimpleNamespace( image_payload_consumption=ImagePayloadConsumption.COMPOSED ), - _primary_image_inputs=lambda current_image, adapter, *, module_type: ( - image_inputs - ), ) measurement_images = CellProfilerModuleExecutor._measurement_image_inputs( @@ -120,6 +117,7 @@ def test_composed_measurement_caller_preserves_ordered_source_aliases() -> None: adapter=SimpleNamespace(), current_image=payload, image_request=image_request, + image_inputs=image_inputs, module_type=SimpleNamespace(), ) diff --git a/tests/unit/test_cellprofiler_module_execution.py b/tests/unit/test_cellprofiler_module_execution.py index 623f967c7f..6d4e7da927 100644 --- a/tests/unit/test_cellprofiler_module_execution.py +++ b/tests/unit/test_cellprofiler_module_execution.py @@ -54,6 +54,7 @@ from openhcs.core.callable_contract import ( CallableContract, CallableMetadata, + ImagePayloadConsumption, attach_callable_contract_metadata, runtime_image_execution_mode, ) @@ -64,10 +65,12 @@ from openhcs.core.config import DtypeConfig from openhcs.core.compiled_step_plan import CompiledStepPlan from openhcs.core.equivalence.keys import RuntimeMeasurementSourcePair -from openhcs.core.function_patterns import InvocationArtifactInputEdgePlan +from openhcs.core.function_patterns import ( + InvocationArtifactInputEdgePlan, + MainFlowInputProjection, +) from openhcs.core.measurement_image_alignment import ( - MeasurementImageLabelAlignmentStrategy, - MeasurementLabelSourceAlignmentStrategy, + MeasurementImageLabelAlignmentRequest, PreparedMeasurementObjectLabels, ) from openhcs.core.measurement_row_materialization import ( @@ -84,7 +87,6 @@ ) from openhcs.core.runtime_artifact_queries import ( MeasurementTableAxisProjection, - MeasurementTableUnion, RuntimeArtifactQueryContext, ) from openhcs.core.runtime_artifact_values import RuntimeValue @@ -93,6 +95,7 @@ ImagePayloadSliceProjector, ImageMetadataPayload, ImagePayloadMetadata, + ImagePayloadMetadataCompositionMode, MaskedImagePayload, image_payload_data, image_payload_mask, @@ -166,9 +169,9 @@ CompiledSourceBindingPlan, ComponentSelector, NamedSourceBinding, - SourceBindingRuntimeContext, ) from openhcs.core.source_image_provenance import ( + SourceImageProvenance, SourceImageProvenancePlanes, ) from openhcs.core.source_matching import ( @@ -177,8 +180,6 @@ from openhcs.core.source_metadata import SourceVoxelSpacing from openhcs.core.source_spatial_domain import SourceSpatialDomain from openhcs.core.steps.function_runtime import ( - FunctionOutputContextStrategy, - PatternGroupData, PatternGroupRuntime, ) from openhcs.core.steps.stream_component_semantics import ( @@ -201,7 +202,6 @@ ) from openhcs.interop.cellprofiler.runtime.artifact_binding import ( RuntimeInputBindingRequest, - RuntimeArtifactTypeStrategy, ) from openhcs.interop.cellprofiler.runtime.function_contract_execution import ( CellProfilerFunctionContractExecutor, @@ -217,7 +217,6 @@ ) from openhcs.interop.cellprofiler.runtime.measurement_execution_support import ( ObjectMeasurementOutputRecorder, - ObjectMeasurementOutputTimings, object_measurement_runtime_inputs, ) from openhcs.interop.cellprofiler.runtime.measurement_recording import ( @@ -447,6 +446,38 @@ def _module_executor( return executor + +def test_compiled_image_request_does_not_repeat_authored_callable_preparation( + monkeypatch: pytest.MonkeyPatch, +) -> None: + module = CellProfilerModule.require_module("Crop") + raw = module.require_callable() + source_spec = ArtifactSpec.input("Input", ImageArtifactType) + contract = _compiled_callable_contract(raw, artifact_inputs=(source_spec,)) + image = np.full((4, 5), 0.25, dtype=np.float32) + adapter = _FakeCellProfilerRuntime( + {source_spec.name: image}, + callable_contract=contract, + artifact_input_edges=(_artifact_input_edge_for_test(source_spec),), + ) + + def reject_authored_preparation(*args, **kwargs): + raise AssertionError("Runtime re-entered authored callable preparation") + + monkeypatch.setattr(CallableContract, "from_callable", reject_authored_preparation) + monkeypatch.setattr( + module, "_install_callable_parameter_help", reject_authored_preparation + ) + executor = CellProfilerModuleExecutor(raw, contract) + image_request = executor._image_request( + image, adapter, + module_type=executor.module_type(), + active_input_specs=contract.artifact_inputs.specs, + ) + + assert image_request.source_aliases == (source_spec.name,) + np.testing.assert_array_equal(image_payload_data(image_request.payload), image) + def test_default_invocation_keeps_compiled_source_bindings_outside_anchor_group() -> ( None ): @@ -943,12 +974,15 @@ def _measurement_image_for_labels( payload=image, reference_domain=reference_domain, ) - return MeasurementImageLabelAlignmentStrategy.align( + return ( source.alignment_request( labels=labels, label_payload=label_payload, plane_projector=plane_projector, - ).with_source_projected_image() + ) + .with_source_projected_image() + .aligned() + .image ) @@ -1361,7 +1395,9 @@ def test_runtime_binding_uses_full_compiled_special_input_contract() -> None: np.testing.assert_array_equal(image_payload_data(topology_inputs[1]), 1.0) -def test_image_artifact_resolution_uses_declared_artifact_alias() -> None: +def test_image_artifact_resolution_uses_declared_artifact_alias( + monkeypatch: pytest.MonkeyPatch, +) -> None: spec = ArtifactSpec.input("IllumStain1", ImageArtifactType) source = ImagePayloadMetadata( source_image_provenance_planes=SourceImageProvenancePlanes.from_components( @@ -1369,7 +1405,7 @@ def test_image_artifact_resolution_uses_declared_artifact_alias() -> None: ), source_image_names=("OrigStain1",), ).payload_with(np.ones((4, 5), dtype=np.float32), None) - payload = RuntimeArtifactTypeStrategy.for_artifact_type( + payload = CellProfilerOutputRecorder.for_artifact_type( ImageArtifactType ).raw_runtime_input_value( spec=spec, value=source @@ -1379,11 +1415,22 @@ def test_image_artifact_resolution_uses_declared_artifact_alias() -> None: assert metadata.source_image_names == ("IllumStain1",) assert metadata.source_image_provenance_planes.paths == ("/input/A01_s001_w1.tif",) assert ( - RuntimeArtifactTypeStrategy.for_artifact_type( + CellProfilerOutputRecorder.for_artifact_type( ImageArtifactType ).source_image_name(spec=spec, value=source) is None ) + strategy = CellProfilerOutputRecorder.for_artifact_type(ImageArtifactType) + + def reject_second_resolution(*args, **kwargs): + raise AssertionError("Source-name projection resolved the image again") + + monkeypatch.setattr( + type(strategy), "raw_runtime_input_value", reject_second_resolution + ) + # The original name remains a contributor; the alias alone is not a + # unique represented source name. + assert strategy.source_image_name_from_value(payload) is None def test_main_flow_image_artifact_selects_declared_alias_plane() -> None: @@ -1414,12 +1461,12 @@ def test_main_flow_image_artifact_selects_declared_alias_plane() -> None: artifact_input_edges=( replace( _artifact_input_edge_for_test(first_spec, stored=False), - consumes_main_flow=True, + main_flow_projection=MainFlowInputProjection.DECLARED_SOURCE_IMAGE, ), ), ) - payload = RuntimeArtifactTypeStrategy.for_artifact_type( + payload = CellProfilerOutputRecorder.for_artifact_type( ImageArtifactType ).raw_runtime_input_value( first_spec, RuntimeInputBindingRequest( @@ -1459,7 +1506,7 @@ def test_single_main_flow_image_artifact_selects_declared_source_binding_plane() None, ) - payload = RuntimeArtifactTypeStrategy.for_artifact_type( + payload = CellProfilerOutputRecorder.for_artifact_type( ImageArtifactType ).raw_runtime_input_value( spec, RuntimeInputBindingRequest( @@ -1469,7 +1516,7 @@ def test_single_main_flow_image_artifact_selects_declared_source_binding_plane() artifact_input_edges=( replace( _artifact_input_edge_for_test(spec, stored=False), - consumes_main_flow=True, + main_flow_projection=MainFlowInputProjection.DECLARED_SOURCE_IMAGE, ), ), ), @@ -1510,7 +1557,7 @@ def test_main_flow_image_artifact_projects_named_provenance_plane() -> None: None, ) - payload = RuntimeArtifactTypeStrategy.for_artifact_type( + payload = CellProfilerOutputRecorder.for_artifact_type( ImageArtifactType ).raw_runtime_input_value( first_spec, RuntimeInputBindingRequest( @@ -1520,7 +1567,7 @@ def test_main_flow_image_artifact_projects_named_provenance_plane() -> None: artifact_input_edges=( replace( _artifact_input_edge_for_test(first_spec, stored=False), - consumes_main_flow=True, + main_flow_projection=MainFlowInputProjection.DECLARED_SOURCE_IMAGE, ), ), ), @@ -1555,7 +1602,7 @@ def test_main_flow_image_artifact_preserves_declared_runtime_slice_stack() -> No None, ) - payload = RuntimeArtifactTypeStrategy.for_artifact_type( + payload = CellProfilerOutputRecorder.for_artifact_type( ImageArtifactType ).raw_runtime_input_value( first_spec, RuntimeInputBindingRequest( @@ -1565,7 +1612,7 @@ def test_main_flow_image_artifact_preserves_declared_runtime_slice_stack() -> No artifact_input_edges=( replace( _artifact_input_edge_for_test(first_spec, stored=False), - consumes_main_flow=True, + main_flow_projection=MainFlowInputProjection.DECLARED_SOURCE_IMAGE, ), ), ), @@ -1580,7 +1627,9 @@ def test_main_flow_image_artifact_preserves_declared_runtime_slice_stack() -> No assert image_payload_metadata(payload).source_image_names == ("Stain1",) -def test_main_flow_projection_binds_singleton_broadcast_artifact_as_2d() -> None: +def test_main_flow_projection_binds_singleton_broadcast_artifact_as_2d( + monkeypatch: pytest.MonkeyPatch, +) -> None: original_spec = ArtifactSpec.input("OrigStain1", ImageArtifactType) illumination_spec = ArtifactSpec.input( "IllumStain1", @@ -1623,7 +1672,7 @@ def test_main_flow_projection_binds_singleton_broadcast_artifact_as_2d() -> None artifact_input_edges=( replace( _artifact_input_edge_for_test(original_spec, stored=False), - consumes_main_flow=True, + main_flow_projection=MainFlowInputProjection.DECLARED_SOURCE_IMAGE, ), _artifact_input_edge_for_test( illumination_spec, @@ -1633,12 +1682,25 @@ def test_main_flow_projection_binds_singleton_broadcast_artifact_as_2d() -> None executor = _module_executor(contract) _activate_runtime_contract(executor.callable_contract, runtime) + strategy_type = type( + CellProfilerOutputRecorder.for_artifact_type(ImageArtifactType) + ) + resolve_image = strategy_type.raw_runtime_input_value + resolved_specs: list[ArtifactSpec] = [] + + def record_resolution(self, spec: ArtifactSpec, value): + resolved_specs.append(spec) + return resolve_image(self, spec, value) + + monkeypatch.setattr(strategy_type, "raw_runtime_input_value", record_resolution) + image_request = executor._image_request( current_image, runtime, module_type=CorrectIlluminationApplyModule, active_input_specs=contract.artifact_inputs.specs, ) + assert resolved_specs == [original_spec] runtime_kwargs = executor._runtime_input_kwargs( runtime, current_image, @@ -1651,6 +1713,57 @@ def test_main_flow_projection_binds_singleton_broadcast_artifact_as_2d() -> None assert image_payload_data(runtime_kwargs["illumination_function"]).shape == (4, 5) +def test_composed_measurement_images_keep_declared_aliases_and_resolved_payload() -> None: + image_spec = ArtifactSpec.input("DeclaredImage", ImageArtifactType) + contract = _compiled_callable_contract( + CellProfilerModule.require_module("MeasureObjectIntensity").require_callable(), + artifact_inputs=(image_spec,), + ) + contract = replace( + contract, + metadata=replace( + contract.metadata, + image_payload_consumption=ImagePayloadConsumption.COMPOSED, + ), + ) + image = np.ones((4, 5), dtype=np.float32) + runtime = _FakeCellProfilerRuntime( + {image_spec.name: image}, + artifact_input_edges=(_artifact_input_edge_for_test(image_spec),), + ) + executor = _module_executor(contract) + _activate_runtime_contract(contract, runtime) + image_request = CellProfilerImageRequest( + payload=image, + source_image_name="RuntimeAlias", + source_aliases=("RuntimeAlias",), + image_count=1, + execution_mode=ImagePayloadExecutionMode.NATURAL, + ) + + (measurement_image,) = executor._measurement_image_inputs( + runtime, + image, + image_request, + image_inputs=(image_spec,), + module_type=MeasureObjectIntensityModule, + ) + + assert measurement_image.source_aliases == (image_spec.name,) + assert measurement_image.payload is image_request.payload + assert measurement_image.execution_mode is image_request.execution_mode + assert measurement_image.plane_projection is image_request.plane_projection + assert not measurement_image.align_to_labels + with pytest.raises(ValueError, match="requires a composed measurement image request"): + executor._measurement_image_inputs( + runtime, + image, + None, + image_inputs=(image_spec,), + module_type=MeasureObjectIntensityModule, + ) + + def test_repeated_broadcast_inputs_consume_their_declared_source_group_axes() -> None: original_specs = tuple( ArtifactSpec.input(f"OrigStain{index}", ImageArtifactType) for index in (1, 2) @@ -1704,7 +1817,7 @@ def test_repeated_broadcast_inputs_consume_their_declared_source_group_axes() -> *( replace( _artifact_input_edge_for_test(spec, stored=False), - consumes_main_flow=True, + main_flow_projection=MainFlowInputProjection.DECLARED_SOURCE_IMAGE, ) for spec in original_specs ), @@ -1759,7 +1872,7 @@ def test_single_main_flow_image_preserves_runtime_slice_axis() -> None: plane_axis=RuntimePlaneAxis.RUNTIME_SLICE, ).payload_with(np.ones((1, 4, 5), dtype=np.float32), None) - payload = RuntimeArtifactTypeStrategy.for_artifact_type( + payload = CellProfilerOutputRecorder.for_artifact_type( ImageArtifactType ).raw_runtime_input_value( spec, RuntimeInputBindingRequest( @@ -1769,7 +1882,7 @@ def test_single_main_flow_image_preserves_runtime_slice_axis() -> None: artifact_input_edges=( replace( _artifact_input_edge_for_test(spec, stored=False), - consumes_main_flow=True, + main_flow_projection=MainFlowInputProjection.DECLARED_SOURCE_IMAGE, ), ), ), @@ -1784,7 +1897,6 @@ def test_single_main_flow_image_preserves_runtime_slice_axis() -> None: def test_object_artifact_source_payload_uses_native_object_provenance() -> None: - object_spec = ArtifactSpec.input("Nuclei", ObjectLabelsArtifactType) objects = ObjectLabelSet( name="Nuclei", variant_data=ObjectLabelVariantData( @@ -1795,9 +1907,7 @@ def test_object_artifact_source_payload_uses_native_object_provenance() -> None: paths=("/input/A01_s001_w1.tif",), ), ) - payload = RuntimeArtifactTypeStrategy.for_artifact_type( - ObjectLabelsArtifactType - ).source_image_payload(object_spec, objects) + payload = ObjectLabelsArtifactType.source_image_payload_from_runtime_value(objects) assert payload is objects assert image_payload_metadata(payload).source_image_provenance_planes.paths == ( @@ -3083,7 +3193,7 @@ def test_object_output_measurements_derive_count_and_locations_from_output_label ArtifactSpec.input("Mask", ImageArtifactType), stored=False, ), - consumes_main_flow=True, + main_flow_projection=MainFlowInputProjection.DECLARED_SOURCE_IMAGE, ), ), output_plans=tuple( @@ -3246,7 +3356,7 @@ def test_compiled_measurement_output_preserves_image_and_object_row_ownership() artifact_input_edges=( replace( _artifact_input_edge_for_test(source_spec, stored=False), - consumes_main_flow=True, + main_flow_projection=MainFlowInputProjection.DECLARED_SOURCE_IMAGE, ), ), output_plans=tuple( @@ -3280,7 +3390,7 @@ def test_compiled_measurement_output_preserves_image_and_object_row_ownership() artifact_type=MeasurementsArtifactType, axis_id="A01_s001", ) - tables = tuple(cast(MeasurementTable, record.value.data) for record in records) + tables = tuple(cast(MeasurementTable, record.data) for record in records) assert len(tables) == 1 table = tables[0] assert table.subject is not None @@ -3618,7 +3728,7 @@ def test_main_flow_strategy_rejects_mixed_artifact_types_in_either_order() -> No for outputs in (values, tuple(reversed(values))): with pytest.raises(TypeError, match="require one exact artifact type"): - RuntimeArtifactTypeStrategy.for_main_flow_outputs(outputs) + CellProfilerOutputRecorder.for_main_flow_outputs(outputs) def test_cellprofiler_adapter_preserves_object_label_source_component_metadata() -> ( @@ -3660,24 +3770,24 @@ def test_cellprofiler_adapter_preserves_object_label_source_component_metadata() record = adapter.add_objects("Nuclei", labels) - assert isinstance(record.value.data, ObjectLabelSet) - assert record.value.data.source_path == "/input/01_POS002_D.TIF" - assert dict(record.value.data.source_component_metadata) == { + assert isinstance(record.data, ObjectLabelSet) + assert record.data.source_path == "/input/01_POS002_D.TIF" + assert dict(record.data.source_component_metadata) == { "well": "01", "site": "POS002", "channel": "D", } - assert record.value.data.source_image_provenance_planes.paths == ( + assert record.data.source_image_provenance_planes.paths == ( "/input/01_POS002_D.TIF", ) assert tuple( dict(metadata) - for metadata in record.value.data.source_image_provenance_planes.component_metadata + for metadata in record.data.source_image_provenance_planes.component_metadata if metadata is not None ) == ( {"well": "01", "site": "POS002", "channel": "D"}, ) - assert filemanager.saved[0][0] is record.value.data + assert filemanager.saved[0][0] is record.data def test_default_row_policy_accepts_multi_source_image_row_ownership() -> None: @@ -3855,13 +3965,10 @@ def test_object_measurement_output_recorder_completes_exact_columnar_rows() -> N ), row_policy=row_policy, module_type=MeasureObjectIntensityModule, - func=_synthetic_object_measurement_function, - adapter=cast(CellProfilerRuntimeAdapter, object()), measurement_images=(), object_inputs=(), image_measurement_rows=[], columnar_rows=[], - timings=ObjectMeasurementOutputTimings(), ) completed = recorder.completed_measurement_rows(source_rows, payload) @@ -3926,7 +4033,6 @@ def __init__( tuple[ArtifactSpec, ArtifactOutputPlan], ... ] = (), source_bindings: tuple[NamedSourceBinding, ...] = (), - ordered_pipeline_image_paths: tuple[str, ...] = (), variable_components: tuple[VariableComponents, ...] = (), plane_projection: RuntimePlaneProjection = RuntimePlaneProjection.stack(), axis_scope: RuntimeExecutionAxisScope | None = None, @@ -3941,11 +4047,6 @@ def __init__( value=None, ) source_binding_plan = CompiledSourceBindingPlan(bindings=source_bindings) - source_binding_context = SourceBindingRuntimeContext( - step_input_files=ordered_pipeline_image_paths, - current_step_input_files=ordered_pipeline_image_paths, - pipeline_input_files=ordered_pipeline_image_paths, - ) processing_context = SimpleNamespace( microscope_handler=SimpleNamespace( parser=SimpleNamespace(semantic_identity=lambda: ()), @@ -3968,7 +4069,6 @@ def __init__( artifact_inputs={edge.key: edge for edge in indexed_input_edges}, artifact_output_bindings=artifact_output_bindings, source_binding_plan=source_binding_plan, - source_binding_context=source_binding_context, microscope_handler=processing_context.microscope_handler, variable_components=variable_components, plane_projection=plane_projection, @@ -4009,7 +4109,6 @@ def __init__( table, ) ) - self.ordered_pipeline_image_paths = ordered_pipeline_image_paths self.measurements: list[MeasurementTable] = [] self.objects: list[tuple[str, np.ndarray, dict[str, object]]] = [] self.spatial_grids: dict[str, SpatialGrid] = {} @@ -4126,7 +4225,7 @@ def get_objects( artifact_type=ObjectLabelsArtifactType, purpose="test object-label artifact", ) - return cast(ObjectLabelSet, record.value.data) + return cast(ObjectLabelSet, record.data) def get_objects_across_groups(self, name: str) -> ObjectLabelSet: return self.runtime_objects[name] @@ -4258,7 +4357,7 @@ def add_spatial_grid( record = super().add_spatial_grid(name, grid) self.spatial_grids[name] = cast( SpatialGrid | RuntimeSliceAlignedValues, - record.value.data, + record.data, ) return record @@ -4299,7 +4398,7 @@ def test_object_label_output_domain_scope_preserves_declared_source_stack() -> N artifact_input_edges=( replace( _artifact_input_edge_for_test(source_spec, stored=False), - consumes_main_flow=True, + main_flow_projection=MainFlowInputProjection.DECLARED_SOURCE_IMAGE, ), ), output_plans=tuple(_artifact_output_plan(item) for item in ((output_spec,))), @@ -4337,7 +4436,7 @@ def test_object_label_output_domain_scope_uses_declared_group_lineage() -> None: artifact_input_edges=( replace( _artifact_input_edge_for_test(source_spec, stored=False), - consumes_main_flow=True, + main_flow_projection=MainFlowInputProjection.DECLARED_SOURCE_IMAGE, ), ), output_plans=tuple(_artifact_output_plan(item) for item in ((output_spec,))), @@ -9195,6 +9294,13 @@ def test_measurement_images_flatten_aligned_runtime_slices_for_source_metadata() {"well": "A01", "site": "1"}, {"well": "A01", "site": "2"}, ) + assert tuple( + tuple(contributor.path for contributor in plane.contributors) + for plane in metadata.source_image_provenance_planes.planes + ) == ( + ("/plate/A01_s001_w1.tif", "/plate/A01_s001_w2.tif"), + ("/plate/A01_s002_w1.tif", "/plate/A01_s002_w2.tif"), + ) def test_measurement_images_preserve_runtime_slice_axis_across_source_aliases() -> None: @@ -9235,6 +9341,122 @@ def source_payload(alias: str, channel: int) -> AlignedImageStack: ) +@pytest.mark.parametrize( + ("incoming_axis", "mode", "expected_planes"), + ( + (None, ImagePayloadMetadataCompositionMode.STACK, 2), + (None, ImagePayloadMetadataCompositionMode.BUNDLE, 1), + (RuntimePlaneAxis.RUNTIME_SLICE, ImagePayloadMetadataCompositionMode.STACK, 2), + (RuntimePlaneAxis.RUNTIME_SLICE, ImagePayloadMetadataCompositionMode.BUNDLE, 1), + (RuntimePlaneAxis.SOURCE_BINDING, ImagePayloadMetadataCompositionMode.STACK, 1), + (RuntimePlaneAxis.SOURCE_BINDING, ImagePayloadMetadataCompositionMode.BUNDLE, 2), + ), +) +def test_image_source_composition_preserves_only_compatible_incoming_topology( + incoming_axis, mode, expected_planes +) -> None: + paths = ("/input/A01_s1_w1.tif", "/input/A01_s1_w2.tif") + metadata = ImagePayloadMetadata( + source_image_provenance_planes=SourceImageProvenancePlanes.from_components( + paths=paths, + component_metadata=({"channel": "1"}, {"channel": "2"}), + ), + plane_axis=incoming_axis, + ) + payload = metadata.payload_with(np.zeros((2, 4, 5), dtype=np.float32)) + + composed = ImagePayloadMetadata.compose((payload,), mode=mode) + + planes = composed.source_image_provenance_planes + assert planes.count == expected_planes + if expected_planes == 2: + assert planes.paths == paths + else: + assert tuple(contributor.path for contributor in planes.plane(0).contributors) == paths + + +def test_measurement_source_composition_reads_dense_plane_facts_without_pixel_projection( + monkeypatch, +) -> None: + paths = tuple(f"/input/A01_s1_w2_z{index + 1}.tif" for index in range(60)) + + def provenance(channel, alias): + return SourceImageProvenance( + source_image_provenance_planes=SourceImageProvenancePlanes.from_components( + paths=paths, + component_metadata=tuple( + { + "well": "A01", + "site": "1", + "channel": str(channel), + "z_index": str(index + 1), + } + for index in range(60) + ), + ), + source_image_names=(alias,), + ) + + metadata = ImagePayloadMetadata( + source_provenance=provenance(2, "OrigBlue"), + plane_axis=RuntimePlaneAxis.RUNTIME_SLICE, + ) + source = CellProfilerMeasurementImage( + source_image_name="OrigBlue", + payload=metadata.payload_with(np.zeros((60, 4, 5), dtype=np.float32)), + ) + + def reject_image_projection(*args, **kwargs): + raise AssertionError( + "Source facts must not require image or metadata projection" + ) + + monkeypatch.setattr( + RuntimeSliceProjection, "value_for_slice", reject_image_projection + ) + monkeypatch.setattr(ImagePayloadMetadata, "compose", reject_image_projection) + monkeypatch.setattr( + ImagePayloadMetadata, "for_leading_source_plane", reject_image_projection + ) + + first = CellProfilerMeasurementImage.composed_source_metadata((source,)) + assert first.source_image_provenance_planes.paths == paths + assert first.source_image_names == ("OrigBlue",) * 60 + assert tuple( + values["z_index"] + for values in first.source_image_provenance_planes.component_metadata + ) == tuple(str(index + 1) for index in range(60)) + + metadata.source_provenance = provenance(3, "OrigGreen") + second = CellProfilerMeasurementImage.composed_source_metadata((source,)) + assert second.source_image_names == ("OrigGreen",) * 60 + assert second.source_component_metadata["channel"] == "3" + assert first.source_component_metadata["channel"] == "2" + + +def test_measurement_source_composition_retains_authored_scalar_coordinates() -> None: + metadata = ImagePayloadMetadata( + source_component_metadata={"well": "A01"}, + source_image_provenance_planes=SourceImageProvenancePlanes.from_components( + paths=("/input/A01_s1_w2.tif",), + component_metadata=({"well": "A01", "site": "1", "channel": "2"},), + ), + source_image_names=("OrigBlue",), + ) + source = CellProfilerMeasurementImage( + source_image_name="OrigBlue", + payload=metadata.payload_with(np.zeros((4, 5), dtype=np.float32)), + ) + + composed = CellProfilerMeasurementImage.composed_source_metadata((source,)) + + assert dict(composed.source_component_metadata) == {"well": "A01"} + assert composed.source_image_provenance_planes.paths == ("/input/A01_s1_w2.tif",) + assert composed.source_image_provenance_planes.component_metadata == ( + {"well": "A01", "site": "1", "channel": "2"}, + ) + + def test_measurement_tables_compose_provenance_after_object_rows_clear_source() -> None: first_metadata = ImagePayloadMetadata( source_image_provenance_planes=SourceImageProvenancePlanes.from_components( @@ -9279,7 +9501,7 @@ def test_measurement_tables_compose_provenance_after_object_rows_clear_source() ), ) - combined = MeasurementTableUnion("Locations", tables).as_table() + combined = MeasurementTable.join("Locations", tables) assert all(table.source_image_name is None for table in tables) assert tuple( @@ -9304,7 +9526,7 @@ def test_image_output_context_preserves_aligned_image_stack_payload(): ) aligned = AlignedImageStack(slices=(dna_payload, rna_payload)) - result = FunctionOutputContextStrategy.for_output_plan(None).contextualize( + result = ImageArtifactType.contextualize_output( dna_payload, aligned, None, @@ -9340,17 +9562,16 @@ def test_pattern_group_runtime_unstacks_aligned_image_stack_output(): source_image_names=("OrigRNA",), ).payload_with(np.full((4, 5), 2, dtype=np.float32), None) aligned = AlignedImageStack(slices=(dna_payload, rna_payload)) - loaded = PatternGroupData( - matching_files=["dna.tif", "rna.tif"], - main_data_stack=np.zeros((2, 4, 5), dtype=np.float32), - ) + matching_files = ["dna.tif", "rna.tif"] runtime = _pattern_group_runtime_for_output_memory("numpy") - output = runtime._validate_and_unstack(aligned, loaded) - - assert output == [dna_payload, rna_payload] + output = runtime._project_output_slices(aligned, matching_files) + stack_payload = aligned.copy_projected_output_stack( + output, memory_type="numpy", device_id=None, + ) + assert [payload for payload, _context in output] == [dna_payload, rna_payload] assert image_payload_metadata( - output.stack_payload + stack_payload ).source_plane_intensity_scales == (65535, 65535) @@ -9396,13 +9617,11 @@ def test_pattern_group_runtime_does_not_invent_nested_axes_from_image_rank(): None, ) aligned = AlignedImageStack(slices=(first_site, second_site)) - loaded = PatternGroupData( - matching_files=["A01_s001_w2_z001_t001.tif"], - main_data_stack=np.zeros((4, 5), dtype=np.float32), - ) + matching_files = ["A01_s001_w2_z001_t001.tif"] runtime = _pattern_group_runtime_for_output_memory("numpy") - output_slices = runtime._validate_and_unstack(aligned, loaded) + projected = runtime._project_output_slices(aligned, matching_files) + output_slices = tuple(payload for payload, _context in projected) assert len(output_slices) == 2 np.testing.assert_array_equal(image_payload_data(output_slices[0]), first_site.data) @@ -9422,16 +9641,14 @@ def test_pattern_group_runtime_leaves_variable_shape_aligned_outputs_uncached(): first = np.ones((4, 5), dtype=np.float32) second = np.ones((3, 4), dtype=np.float32) aligned = AlignedImageStack(slices=(first, second)) - loaded = PatternGroupData( - matching_files=["first.tif", "second.tif"], - main_data_stack=np.zeros((2, 4, 5), dtype=np.float32), - ) + matching_files = ["first.tif", "second.tif"] runtime = _pattern_group_runtime_for_output_memory("numpy") - output = runtime._validate_and_unstack(aligned, loaded) - - assert output == [first, second] - assert output.stack_payload is None + output = runtime._project_output_slices(aligned, matching_files) + assert [payload for payload, _context in output] == [first, second] + assert aligned.copy_projected_output_stack( + output, memory_type="numpy", device_id=None, + ) is None def test_invocation_request_keeps_original_aliases_when_labels_change_image_domain( @@ -9762,7 +9979,7 @@ def test_mask_objects_uses_object_labels_as_primary_execution_domain() -> None: module_type = MaskObjectsModule assert ( module_type.primary_image_inputs( - mask_objects, + contract, contract.artifact_inputs, ) == () @@ -13562,7 +13779,10 @@ def test_relateobjects_relationship_rows_project_parent_mean_distances() -> None assert "Mean_Children_Distance_Minimum_Parents" in mean_rows[0] -def test_relateobjects_parent_means_align_scoped_child_tables_by_source_plane() -> None: +@pytest.mark.parametrize("conflicting_upstream", (False, True)) +def test_relateobjects_parent_means_align_scoped_child_tables_by_source_plane( + conflicting_upstream: bool, +) -> None: source_paths = ("/source/site1.tif", "/source/site2.tif") source_metadata = ( {"well": "A14", "site": "1", "channel": "3"}, @@ -13627,6 +13847,16 @@ def test_relateobjects_parent_means_align_scoped_child_tables_by_source_plane() ) for site_index, values in enumerate(((0.2, 0.6, 99.0), (0.8, 1.0))) ) + if conflicting_upstream: + first = scoped_tables[0] + changed_rows = MeasurementSparseColumnarRows( + columns={ + **first.rows.columns, + colocalization_feature: (123.0, *first.rows.column_values(colocalization_feature)[1:]), + }, + fields=first.rows.fields, + ) + scoped_tables = (*scoped_tables, replace(first, rows=changed_rows)) unrelated_table = MeasurementTable( name="Unrelated_measurements", rows=MeasurementSparseColumnarRows.from_rows( @@ -13734,6 +13964,13 @@ def test_relateobjects_parent_means_align_scoped_child_tables_by_source_plane() child_spec = executor.callable_contract.artifact_inputs.by_ref(declaration.target) assert parent_spec is not None assert child_spec is not None + if conflicting_upstream: + with pytest.raises(ValueError, match="conflicting values"): + projector.parent_mean_upstream_measurement_rows( + parent_spec=parent_spec, child_spec=child_spec, + payload=runtime.relationships[0], + ) + return rows = projector.parent_mean_upstream_measurement_rows( parent_spec=parent_spec, child_spec=child_spec, @@ -15095,27 +15332,23 @@ def source_binding_axis_size( ), ).payload_with(image, None), ) - aligned_labels = ( - MeasurementLabelSourceAlignmentStrategy.align_request_labels_to_image_source( - measurement_image.alignment_request( - labels=label_planes, - label_payload=labels, - plane_projector=projector, - ) - ) - ) + aligned_labels = measurement_image.alignment_request( + labels=label_planes, + label_payload=labels, + plane_projector=projector, + ).labels_in_image_source() np.testing.assert_array_equal( object_label_dense_array(aligned_labels), label_planes[1], ) np.testing.assert_array_equal( - MeasurementImageLabelAlignmentStrategy.align( - measurement_image.alignment_request( - labels=aligned_labels, - plane_projector=projector, - ) - ), + measurement_image.alignment_request( + labels=aligned_labels, + plane_projector=projector, + ) + .aligned() + .image, image[1], ) @@ -15171,11 +15404,13 @@ def source_binding_axis_size( payload=payload, ) - aligned = MeasurementImageLabelAlignmentStrategy.align( + aligned = ( measurement_image.alignment_request( labels=np.ones((4, 5), dtype=np.int32), plane_projector=Projector(), ) + .aligned() + .image ) assert isinstance(aligned, MaskedImagePayload) @@ -15233,15 +15468,11 @@ def source_binding_axis_size( source_aliases=("rawDNA", "rawGFP"), payload=image, ) - aligned_labels = ( - MeasurementLabelSourceAlignmentStrategy.align_request_labels_to_image_source( - measurement_image.alignment_request( - labels=labels, - label_payload=labels, - plane_projector=Projector(), - ) - ) - ) + aligned_labels = measurement_image.alignment_request( + labels=labels, + label_payload=labels, + plane_projector=Projector(), + ).labels_in_image_source() assert isinstance(aligned_labels, ObjectLabelSet) np.testing.assert_array_equal( @@ -15386,7 +15617,9 @@ def test_measurement_labels_preserve_stack_for_object_domain_alignment() -> None image = np.ones((1, 4, 5), dtype=np.float32) labels = np.arange(2 * 4 * 5, dtype=np.int32).reshape(2, 4, 5) - measurement_labels = MeasurementLabelSourceAlignmentStrategy.align(image, labels) + measurement_labels = MeasurementImageLabelAlignmentRequest.labels_for_image( + image, labels + ) assert measurement_labels.shape == labels.shape np.testing.assert_array_equal(measurement_labels, labels) @@ -15422,7 +15655,7 @@ def test_measurement_label_alignment_preserves_runtime_slice_payload_for_aligned ), ) - measurement_labels = MeasurementLabelSourceAlignmentStrategy.align( + measurement_labels = MeasurementImageLabelAlignmentRequest.labels_for_image( AlignedImageStack((first_image, second_image)), labels, label_payload=label_payload, @@ -15447,7 +15680,7 @@ def test_measurement_label_alignment_preserves_runtime_slice_payload_for_dense_s ), ) - measurement_labels = MeasurementLabelSourceAlignmentStrategy.align( + measurement_labels = MeasurementImageLabelAlignmentRequest.labels_for_image( image, labels, label_payload=label_payload, @@ -15541,7 +15774,9 @@ def test_measurement_labels_do_not_infer_broadcast_from_equal_planes() -> None: label_plane = np.arange(4 * 5, dtype=np.int32).reshape(4, 5) labels = np.stack((label_plane, label_plane)) - measurement_labels = MeasurementLabelSourceAlignmentStrategy.align(image, labels) + measurement_labels = MeasurementImageLabelAlignmentRequest.labels_for_image( + image, labels + ) assert measurement_labels.shape == labels.shape np.testing.assert_array_equal(measurement_labels, labels) @@ -15798,7 +16033,9 @@ def source_binding_axis_plane_index( ) del measurement_image - measurement_labels = MeasurementLabelSourceAlignmentStrategy.align(image, labels) + measurement_labels = MeasurementImageLabelAlignmentRequest.labels_for_image( + image, labels + ) assert measurement_labels.shape == labels.shape np.testing.assert_array_equal(measurement_labels, labels) @@ -16329,7 +16566,7 @@ def test_object_label_payload_preserves_source_metadata_for_measurements() -> No ) _activate_runtime_contract(executor.callable_contract, runtime) - payload = RuntimeArtifactTypeStrategy.for_artifact_type( + payload = CellProfilerOutputRecorder.for_artifact_type( spec.artifact_type ).raw_runtime_input_value( spec, RuntimeInputBindingRequest( @@ -16387,7 +16624,7 @@ def test_runtime_object_label_payload_ignores_measurement_image_as_selector() -> measurement_image = ImagePayloadMetadata( source_component_metadata={"well": "A01"}, ).payload_with(image, None) - payload = RuntimeArtifactTypeStrategy.for_artifact_type( + payload = CellProfilerOutputRecorder.for_artifact_type( spec.artifact_type ).raw_runtime_input_value( spec, RuntimeInputBindingRequest( @@ -16438,7 +16675,7 @@ def test_full_stack_object_measurement_resolves_complete_label_artifact() -> Non ) _activate_runtime_contract(executor.callable_contract, runtime) - label_payload = RuntimeArtifactTypeStrategy.for_artifact_type( + label_payload = CellProfilerOutputRecorder.for_artifact_type( object_spec.artifact_type ).raw_runtime_input_value( object_spec, RuntimeInputBindingRequest( @@ -16518,7 +16755,7 @@ def test_object_label_payload_for_measurement_image_projects_source_spatial_crop ) _activate_runtime_contract(executor.callable_contract, runtime) - label_payload = RuntimeArtifactTypeStrategy.for_artifact_type( + label_payload = CellProfilerOutputRecorder.for_artifact_type( spec.artifact_type ).raw_runtime_input_value( spec, RuntimeInputBindingRequest( @@ -17621,9 +17858,7 @@ def test_convert_objects_to_image_uses_declared_label_source_for_runtime_plane_d variable_components=(AllComponents.Z_INDEX,), relations=(GroupLineageSourceRelation(source_spec.ref()),), ) - result = FunctionOutputContextStrategy.for_output_plan( - output_plan, - ).contextualize_from_projector( + result = (ImageArtifactType if output_plan is None else output_plan.artifact_type).contextualize_output_from_projector( label_payload, raw_result, output_plan, @@ -17659,9 +17894,7 @@ def test_object_label_image_output_rejects_source_plane_count_drift() -> None: ValueError, match="source-plane provenance must match the declared runtime plane axis", ): - FunctionOutputContextStrategy.for_output_plan( - output_plan, - ).contextualize_from_projector( + (ImageArtifactType if output_plan is None else output_plan.artifact_type).contextualize_output_from_projector( label_payload, ImagePayloadMetadata().payload_with( np.zeros(labels.shape, dtype=np.uint16) @@ -17692,9 +17925,7 @@ def test_object_label_singleton_volume_output_declares_runtime_plane_axis() -> N relations=(GroupLineageSourceRelation(source_spec.ref()),), ) - result = FunctionOutputContextStrategy.for_output_plan( - output_plan, - ).contextualize_from_projector( + result = (ImageArtifactType if output_plan is None else output_plan.artifact_type).contextualize_output_from_projector( label_payload, raw_result, output_plan, @@ -17726,9 +17957,7 @@ def test_object_label_scalar_image_output_does_not_invent_runtime_plane_axis() - relations=(GroupLineageSourceRelation(source_spec.ref()),), ) - result = FunctionOutputContextStrategy.for_output_plan( - output_plan, - ).contextualize_from_projector( + result = (ImageArtifactType if output_plan is None else output_plan.artifact_type).contextualize_output_from_projector( label_payload, raw_result, output_plan, @@ -18028,3 +18257,258 @@ def test_object_measurement_execution_policy_keeps_declared_full_stack_for_2d_la ) assert mode is ImagePayloadExecutionMode.FULL_STACK + + +@pytest.mark.parametrize("image_count", (1, 2)) +def test_natural_object_measurement_resolves_one_roster_without_eager_composition( + monkeypatch, image_count +) -> None: + image_specs = tuple( + ArtifactSpec.input(name, ImageArtifactType) + for name in ("DNA", "ER")[:image_count] + ) + object_spec = ArtifactSpec.input("Cells", ObjectLabelsArtifactType) + measurement_spec = ArtifactSpec.output( + "MeasureObjectIntensity_roster", MeasurementsArtifactType + ) + labels = ObjectLabelSet( + name="Cells", + variant_data=ObjectLabelVariantData(labels=np.ones((3, 4), dtype=np.int32)), + domain=ObjectLabelDomain(declared_object_ids=(1,)), + ) + images = { + spec.name: ImagePayloadMetadata( + source_image_names=(f"Original{spec.name}",) + ).payload_with(np.full((3, 4), value, dtype=np.float32)) + for spec, value in zip(image_specs, (1, 2)[:image_count], strict=True) + } + runtime = _FakeCellProfilerRuntime( + images, + {"Cells": labels}, + artifact_input_edges=tuple( + _artifact_input_edge_for_test(spec) + for spec in (*image_specs, object_spec) + ), + artifact_output_bindings=( + (measurement_spec, _artifact_output_plan(measurement_spec)), + ), + ) + contract = _compiled_callable_contract( + MeasureObjectIntensityModule.require_callable(), + artifact_inputs=(*image_specs, object_spec), + artifact_outputs=(measurement_spec,), + ) + executor = _module_executor(contract) + monkeypatch.setattr( + CellProfilerModuleExecutor, + "_image_request", + lambda *_args, **_kwargs: pytest.fail( + "NATURAL measurements do not compose the image roster" + ), + ) + strategy_type = type( + CellProfilerOutputRecorder.for_artifact_type(ImageArtifactType) + ) + original_resolution = strategy_type.raw_runtime_input_value + resolutions = [] + + def resolve(self, spec, value): + resolutions.append(spec.name) + return original_resolution(self, spec, value) + + monkeypatch.setattr(strategy_type, "raw_runtime_input_value", resolve) + policy_type = type( + MeasureObjectIntensityModule.runtime_object_measurement_row_policy() + ) + original_table_name = policy_type.table_source_image_name + fallbacks = [] + + def table_name(self, measurement_images, source_image_name): + fallbacks.append(source_image_name) + return original_table_name(self, measurement_images, source_image_name) + + monkeypatch.setattr(policy_type, "table_source_image_name", table_name) + current = np.zeros((3, 4), dtype=np.float32) + assert _run_module(executor, current, cellprofiler_runtime=runtime) is current + assert resolutions == ["DNA", "ER"][:image_count] + assert fallbacks == [None if image_count == 1 else "dna__er"] + table = next( + table for table in runtime.measurements + if table.subject == MeasurementSubject(MeasurementScope.OBJECT, "Cells") + ) + rows = table.rows.row_mappings() + assert [ + row[f"Intensity_IntegratedIntensity_{spec.name}"] + for row, spec in zip(rows, image_specs, strict=True) + ] == [12.0, 24.0][:image_count] + + +def test_natural_measurement_fallback_preserves_selected_main_flow_plane(monkeypatch): + from openhcs.core.runtime_image_values import ImagePayloadMetadataCompositionMode + + image_spec = ArtifactSpec.input("DNA", ImageArtifactType) + object_spec = ArtifactSpec.input("Cells", ObjectLabelsArtifactType) + output_spec = ArtifactSpec.output("SelectedPlaneIntensity", MeasurementsArtifactType) + planes = tuple( + ImagePayloadMetadata(source_image_names=(name,)).payload_with( + np.ones((3, 4), dtype=np.float32) + ) for name in ("DNA", "ER") + ) + image = ImagePayloadMetadata.compose( + planes, mode=ImagePayloadMetadataCompositionMode.STACK + ).payload_with(np.ones((2, 3, 4), dtype=np.float32)) + labels = ObjectLabelSet( + name="Cells", + variant_data=ObjectLabelVariantData(labels=np.ones((2, 3, 4), dtype=np.int32)), + plane_axis=RuntimePlaneAxis.RUNTIME_SLICE, + domain=ObjectLabelDomain( + scope=ObjectLabelDomainScope.PLANE, + declared_object_id_domains=((1,), (1,)), + ), + ) + runtime = _FakeCellProfilerRuntime( + {}, {"Cells": labels}, + artifact_input_edges=( + replace( + _artifact_input_edge_for_test(image_spec, stored=False), + main_flow_projection=MainFlowInputProjection.COMPLETE_PAYLOAD, + ), + _artifact_input_edge_for_test(object_spec), + ), + artifact_output_bindings=((output_spec, _artifact_output_plan(output_spec)),), + plane_projection=RuntimePlaneProjection(plane_index=0, plane_count=2), + ) + executor = _module_executor(_compiled_callable_contract( + MeasureObjectIntensityModule.require_callable(), + artifact_inputs=(image_spec, object_spec), artifact_outputs=(output_spec,), + )) + _activate_runtime_contract(executor.callable_contract, runtime) + original_fallback = executor._image_request( + image, runtime, module_type=MeasureObjectIntensityModule, + active_input_specs=(image_spec, object_spec), + ).source_image_name + assert original_fallback == "DNA" + monkeypatch.setattr( + CellProfilerModuleExecutor, "_image_request", + lambda *_args, **_kwargs: pytest.fail("unused composed request"), + ) + policy_type = type(MeasureObjectIntensityModule.runtime_object_measurement_row_policy()) + original_table_name = policy_type.table_source_image_name + fallbacks = [] + def table_name(self, measurement_images, source_image_name): + fallbacks.append(source_image_name) + return original_table_name(self, measurement_images, source_image_name) + monkeypatch.setattr(policy_type, "table_source_image_name", table_name) + assert _run_module(executor, image, cellprofiler_runtime=runtime) is image + assert fallbacks == [original_fallback] + + +@pytest.mark.parametrize("batched", (False, True)) +def test_composed_measurement_roster_keeps_all_object_source_pairs( + monkeypatch, batched +): + from openhcs.core.runtime_batch_contracts import RuntimeBatchExecutionDomain + + image_specs = tuple( + ArtifactSpec.input(name, ImageArtifactType) for name in ("DNA", "ER", "RNA") + ) + object_specs = tuple( + ArtifactSpec.input(name, ObjectLabelsArtifactType) + for name in ("Cells", "Nuclei") + ) + output = ArtifactSpec.output("PairMeasurements", MeasurementsArtifactType) + pixels = np.arange(1, 13, dtype=np.float32).reshape(3, 4) / 12 + images = { + spec.name: ImagePayloadMetadata(source_image_names=(spec.name,)).payload_with( + pixels * scale + ) + for spec, scale in zip(image_specs, (1.0, 0.5, 0.25), strict=True) + } + objects = { + spec.name: ObjectLabelSet( + name=spec.name, + variant_data=ObjectLabelVariantData(labels=np.ones((3, 4), dtype=np.int32)), + domain=ObjectLabelDomain(declared_object_ids=(1,)), + ) + for spec in object_specs + } + contract = _compiled_callable_contract( + MeasureColocalizationModule.require_callable("measure_colocalization_objects"), + artifact_inputs=(*image_specs, *object_specs), + artifact_outputs=(output,), + ) + batch_executor = contract.runtime_batch_executor( + RuntimeBatchExecutionDomain.MEASUREMENT_IMAGES + ) + assert batch_executor is not None + batches = [] + + def execute_batch(func, requests, execute_one): + batches.append( + tuple( + (request.object_spec.name, request.batch_index, request.batch_count) + for request in requests + ) + ) + return batch_executor(func, requests, execute_one) + + contract = replace( + contract, + runtime_batch_executors={ + RuntimeBatchExecutionDomain.MEASUREMENT_IMAGES: execute_batch + } + if batched + else {}, + ) + runtime = _FakeCellProfilerRuntime( + images, + objects, + artifact_input_edges=tuple( + _artifact_input_edge_for_test(spec) + for spec in (*image_specs, *object_specs) + ), + artifact_output_bindings=((output, _artifact_output_plan(output)),), + ) + policy_type = type( + MeasureColocalizationModule.runtime_object_measurement_row_policy() + ) + original_invocations = policy_type.invocations + source_rosters = [] + + def invocations(policy, measurement_image, kwargs): + source_rosters.append(measurement_image.source_aliases) + return original_invocations(policy, measurement_image, kwargs) + + monkeypatch.setattr(policy_type, "invocations", invocations) + current = np.zeros((3, 4), dtype=np.float32) + assert ( + _run_module( + _module_executor(contract), + current, + cellprofiler_runtime=runtime, + do_costes=False, + do_manders=False, + do_rwc=False, + do_overlap=False, + ) + is current + ) + assert source_rosters == [("DNA", "ER", "RNA")] + assert batches == ( + [ + tuple( + (name, index, 6) + for index, name in enumerate(("Cells",) * 3 + ("Nuclei",) * 3) + ) + ] + if batched + else [] + ) + rows = tuple( + row for table in runtime.measurements for row in table.rows.iter_row_mappings() + ) + for name in ("Cells", "Nuclei"): + owned = tuple(row for row in rows if row.get("object_name") == name) + assert len(owned) == 3 + for row, pair in zip(owned, ("DNA_ER", "DNA_RNA", "ER_RNA"), strict=True): + assert row[f"Correlation_Correlation_{pair}"] == pytest.approx(1.0) diff --git a/tests/unit/test_cellprofiler_module_execution_semantics.py b/tests/unit/test_cellprofiler_module_execution_semantics.py index 6a5209eaaf..70bee71ff8 100644 --- a/tests/unit/test_cellprofiler_module_execution_semantics.py +++ b/tests/unit/test_cellprofiler_module_execution_semantics.py @@ -25,6 +25,7 @@ from openhcs.core.callable_contract import CallableContract from openhcs.core.component_group_scope import RuntimeExecutionAxisScope from openhcs.core.function_patterns import ( + MainFlowInputProjection, DEFAULT_GROUP_KEY, FunctionInvocationKey, InvocationArtifactInputEdgePlan, @@ -109,7 +110,7 @@ def _runtime_with_outputs( spec=spec, storage_plan=None, projection=None, - consumes_main_flow=True, + main_flow_projection=MainFlowInputProjection.DECLARED_SOURCE_IMAGE, ) for input_index, spec in enumerate(main_flow_inputs) ) diff --git a/tests/unit/test_cellprofiler_morphology_public_contracts.py b/tests/unit/test_cellprofiler_morphology_public_contracts.py index 904e5852b5..a0aef06dad 100644 --- a/tests/unit/test_cellprofiler_morphology_public_contracts.py +++ b/tests/unit/test_cellprofiler_morphology_public_contracts.py @@ -2,6 +2,8 @@ from __future__ import annotations +from openhcs.core.pipeline.compilation_session import ResolvedPipelineDefinition + from dataclasses import dataclass from types import SimpleNamespace @@ -32,7 +34,6 @@ artifact_outputs, special_input_names_from_callable, ) -from openhcs.core.pipeline.step_snapshot import StepSnapshot from openhcs.core.source_bindings import ( NamedSourceBinding, SourceProjectionRole, @@ -189,14 +190,7 @@ def fixture_producer(image): producer_step = FunctionStep(func=fixture_producer, name="FixtureProducer") steps = (producer_step, step) - snapshots = tuple( - StepSnapshot( - index=index, - scope_id=f"test::morphology::{index}", - step=current_step, - ) - for index, current_step in enumerate(steps) - ) + snapshots = tuple(current_step for index, current_step in enumerate(steps)) session = CompilationSession.from_context( context=ProcessingContext( step_plans={ @@ -210,11 +204,12 @@ def fixture_producer(image): }, axis_id="A01", ), - steps=steps, orchestrator=SimpleNamespace(pipeline_config=PipelineConfig()), global_config=GlobalPipelineConfig(), - step_state_map={index: object() for index in range(len(steps))}, - snapshots=snapshots, + pipeline=ResolvedPipelineDefinition( + steps=snapshots, + step_state_map={index: object() for index in range(len(steps))}, + ), ) provider = CellProfilerInvocationContractProviderFactory.provider_for_session( session diff --git a/tests/unit/test_cellprofiler_neighbors_contract.py b/tests/unit/test_cellprofiler_neighbors_contract.py index 46cefbd2a0..20c2b77933 100644 --- a/tests/unit/test_cellprofiler_neighbors_contract.py +++ b/tests/unit/test_cellprofiler_neighbors_contract.py @@ -2,6 +2,8 @@ from __future__ import annotations +from openhcs.core.pipeline.compilation_session import ResolvedPipelineDefinition + import inspect from types import SimpleNamespace from typing import get_type_hints @@ -30,7 +32,6 @@ from openhcs.core.pipeline.artifact_planning import artifact_producers_for_outputs from openhcs.core.pipeline.function_contracts import artifact_outputs from openhcs.core.memory.decorators import numpy -from openhcs.core.pipeline.step_snapshot import StepSnapshot from openhcs.core.runtime_object_labels import ( ObjectLabelSet, ObjectLabelPayload, @@ -102,11 +103,7 @@ def test_relationship_module_number_is_derived_after_public_transport() -> None: (restored_step,) = FunctionStepTransportAuthority.pipeline_steps_from_namespace( namespace ) - snapshot = StepSnapshot( - index=0, - scope_id="test::neighbors-module-order", - step=restored_step, - ) + snapshot = restored_step session = CompilationSession.from_context( context=ProcessingContext( step_plans={ @@ -119,11 +116,12 @@ def test_relationship_module_number_is_derived_after_public_transport() -> None: }, axis_id="A01", ), - steps=[restored_step], orchestrator=SimpleNamespace(pipeline_config=PipelineConfig()), global_config=GlobalPipelineConfig(), - step_state_map={0: object()}, - snapshots=(snapshot,), + pipeline=ResolvedPipelineDefinition( + steps=(snapshot,), + step_state_map={0: SimpleNamespace(scope_id="plate::functionstep_0")}, + ), ) provider = CellProfilerInvocationContractProviderFactory.provider_for_session( @@ -142,7 +140,7 @@ def test_relationship_module_number_is_derived_after_public_transport() -> None: def _compiled_neighbor_invocation(): step = _reconstructed_neighbor_step() - snapshot = StepSnapshot(index=0, scope_id="test::neighbors", step=step) + snapshot = step context = ProcessingContext( step_plans={ 0: CompiledStepPlan( @@ -156,11 +154,12 @@ def _compiled_neighbor_invocation(): ) session = CompilationSession.from_context( context=context, - steps=[step], orchestrator=SimpleNamespace(pipeline_config=PipelineConfig()), global_config=GlobalPipelineConfig(), - step_state_map={0: object()}, - snapshots=(snapshot,), + pipeline=ResolvedPipelineDefinition( + steps=(snapshot,), + step_state_map={0: SimpleNamespace(scope_id="plate::functionstep_0")}, + ), ) provider = CellProfilerInvocationContractProviderFactory.provider_for_session( session @@ -363,14 +362,7 @@ def fixture_producer(image): name="LaterNeighbors", ), ) - snapshots = tuple( - StepSnapshot( - index=index, - scope_id=f"test::numbered-neighbors::{index}", - step=step, - ) - for index, step in enumerate(steps) - ) + snapshots = tuple(step for index, step in enumerate(steps)) session = CompilationSession.from_context( context=ProcessingContext( step_plans={ @@ -384,11 +376,12 @@ def fixture_producer(image): }, axis_id="A01", ), - steps=steps, orchestrator=SimpleNamespace(pipeline_config=PipelineConfig()), global_config=GlobalPipelineConfig(), - step_state_map={index: object() for index in range(len(steps))}, - snapshots=snapshots, + pipeline=ResolvedPipelineDefinition( + steps=snapshots, + step_state_map={index: object() for index in range(len(steps))}, + ), ) provider = CellProfilerInvocationContractProviderFactory.provider_for_session( @@ -511,14 +504,7 @@ def fixture_producer(image): FunctionStep(func=neighbor_pattern, name="MeasureObjectNeighbors"), FunctionStep(func=relate_pattern, name="RelateObjects"), ) - snapshots = tuple( - StepSnapshot( - index=index, - scope_id=f"test::advanced-module-numbering::{index}", - step=step, - ) - for index, step in enumerate(steps) - ) + snapshots = tuple(step for index, step in enumerate(steps)) session = CompilationSession.from_context( context=ProcessingContext( step_plans={ @@ -532,11 +518,12 @@ def fixture_producer(image): }, axis_id="A01", ), - steps=steps, orchestrator=SimpleNamespace(pipeline_config=PipelineConfig()), global_config=GlobalPipelineConfig(), - step_state_map={index: object() for index in range(len(steps))}, - snapshots=snapshots, + pipeline=ResolvedPipelineDefinition( + steps=snapshots, + step_state_map={index: object() for index in range(len(steps))}, + ), ) provider = CellProfilerInvocationContractProviderFactory.provider_for_session( session diff --git a/tests/unit/test_cellprofiler_output_record_occurrence.py b/tests/unit/test_cellprofiler_output_record_occurrence.py index 0e66b8cb3f..29f0320b63 100644 --- a/tests/unit/test_cellprofiler_output_record_occurrence.py +++ b/tests/unit/test_cellprofiler_output_record_occurrence.py @@ -19,8 +19,19 @@ MainFlowInputProjection, ) from openhcs.core.runtime_adapters import RuntimeAdapterRequest -from openhcs.core.runtime_image_values import image_payload_data, image_payload_metadata -from openhcs.interop.cellprofiler.runtime.artifact_binding import RuntimeInputBindingRequest +from openhcs.core.runtime_image_values import ( + ImagePayloadMetadata, + image_payload_data, + image_payload_mask, + image_payload_metadata, +) +from openhcs.core.source_image_provenance import SourceImageProvenancePlanes +from openhcs.interop.cellprofiler.runtime.artifact_binding import ( + RuntimeInputBindingRequest, +) +from openhcs.interop.cellprofiler.runtime.output_recording import ( + ImageOutputRecorder, +) from openhcs.interop.cellprofiler.runtime.output_record_request import ( CellProfilerOutputRecordRequest, ) @@ -54,7 +65,7 @@ def _output_record_request( spec=spec, storage_plan=None, projection=None, - consumes_main_flow=True, + main_flow_projection=MainFlowInputProjection.DECLARED_SOURCE_IMAGE, ) for input_index, spec in active_occurrences ) @@ -124,7 +135,7 @@ def test_output_source_uses_compiled_runtime_occurrence_for_repeated_roles( spec=spec, storage_plan=None, projection=None, - consumes_main_flow=True, + main_flow_projection=MainFlowInputProjection.DECLARED_SOURCE_IMAGE, ) for input_index, spec in enumerate(contract.artifact_inputs) ) @@ -319,6 +330,70 @@ def test_record_binding_reads_current_pixels_and_mutable_kwargs_without_holder_a assert image_payload_metadata(source).source_image_names == (spec.name,) +def test_record_source_binds_current_image_once_and_preserves_intensity_mask_lineage( + monkeypatch, +) -> None: + request, spec = _image_record_request() + pixels = np.full((3, 4), 65535, dtype=np.uint16) + mask = np.ones((3, 4), dtype=bool) + payload = ImagePayloadMetadata( + source_image_names=("Acquired",), + source_image_provenance_planes=SourceImageProvenancePlanes.from_components( + paths=("/input/actual.tif",), + ), + ).payload_with(pixels, mask) + request = replace(request, current_image=payload) + original_bind = ImageOutputRecorder.raw_runtime_input_value + binding_inputs = [] + + def observe_bind(strategy, input_spec, value): + binding_inputs.append(value) + return original_bind(strategy, input_spec, value) + + monkeypatch.setattr( + ImageOutputRecorder, "raw_runtime_input_value", observe_bind + ) + for pixel_value in (65535, 32768): + pixels[:] = pixel_value + binding_inputs.clear() + source = request.artifact_source_payload(request.active_input_edges[0]) + assert binding_inputs == [payload] + assert image_payload_data(source).dtype == np.float32 + np.testing.assert_allclose( + image_payload_data(source), np.float32(pixel_value) / 65535, + ) + assert image_payload_mask(source) is mask + metadata = image_payload_metadata(source) + assert metadata.source_image_names == (spec.name,) + assert metadata.source_image_provenance_planes.paths == ("/input/actual.tif",) + assert set(metadata.source_provenance.represented_source_image_names) == { + "Acquired", spec.name, + } + + +def test_record_source_returns_the_actual_bound_value_without_rebinding(monkeypatch) -> None: + request, _spec = _image_record_request() + bound = ImagePayloadMetadata( + source_image_names=("Original",), + ).payload_with(np.ones((3, 4), dtype=np.float32)) + reads = [] + + def runtime_value(binding, edge, parameter_name=None): + reads.append((edge, parameter_name)) + return bound + + def reject_rebinding(*_args, **_kwargs): + raise AssertionError("Source context rebound an already bound runtime image") + + monkeypatch.setattr(RuntimeInputBindingRequest, "runtime_value", runtime_value) + monkeypatch.setattr( + ImageOutputRecorder, "raw_runtime_input_value", reject_rebinding + ) + edge = request.active_input_edges[0] + assert request.artifact_source_payload(edge) is bound + assert reads == [(edge, edge.spec.parameter_name)] + + def test_record_endpoint_identity_does_not_change_reference_broadcast_selection() -> None: request, spec = _image_record_request() equivalent = replace(spec) diff --git a/tests/unit/test_cellprofiler_pipeline_import.py b/tests/unit/test_cellprofiler_pipeline_import.py index d687c1079b..947486fbd0 100644 --- a/tests/unit/test_cellprofiler_pipeline_import.py +++ b/tests/unit/test_cellprofiler_pipeline_import.py @@ -16,7 +16,9 @@ ArtifactInputPlan, ArtifactSpec, ArtifactSpecCollection, + ArtifactSpecRelation, ImageArtifactType, + MeasurementsArtifactType, ObjectLabelsArtifactType, ) from openhcs.core.callable_contract import CallableContract, FunctionStepExecutionScope @@ -35,6 +37,7 @@ ComponentSelector, NamedSourceBinding, SourceBindingMatchMethod, + SourceBindingsConfig, SourceProjectionRole, StepSourceBindingsConfig, ) @@ -43,14 +46,16 @@ from openhcs.interop.cellprofiler.module_declarations import ( CellProfilerModule, ) -from openhcs.interop.cellprofiler.parser import ModuleBlock, ModuleSetting +from openhcs.interop.cellprofiler.parser import CPPipeParser, ModuleBlock, ModuleSetting from openhcs.interop.cellprofiler.pipeline_import import ( + _parsed_pipeline_declaration, _ParsedTargetUnit, _public_kwargs_for_target, _public_step_source_bindings, _SelectedInputBindingOccurrence, import_cellprofiler_pipeline, ) +from openhcs.interop.cellprofiler.settings_binder import SettingsBinder from openhcs.interop.cellprofiler.setting_names import ( SettingNameFamily, setting_values, @@ -1180,7 +1185,7 @@ def test_active_channel_outputs_preserve_declared_identity_without_consumers() - ) == ("CorrectedStain1", "CorrectedStain2") -def test_repeated_natural_measurement_images_use_group_local_source_identity() -> None: +def test_repeated_measurement_images_preserve_one_complete_module_roster() -> None: cppipe_path = Path("pipelines/grouped-measurements.cppipe") filemanager = _MemoryFileManager( {cppipe_path: """CellProfiler Pipeline: https://cellprofiler.org @@ -1214,28 +1219,27 @@ def test_repeated_natural_measurement_images_use_group_local_source_identity() - step for step in pipeline_steps if step.name == "MeasureObjectIntensity" ) invocations = tuple(normalize_function_pattern(measurement_step.func).iter_items()) - assert tuple(invocation.key.group_key for invocation in invocations) == ("1", "2") - assert all( - "select_images_to_measure" not in invocation.kwargs_dict - for invocation in invocations - ) - assert tuple(invocation.kwargs_dict for invocation in invocations) == ( - {}, - {"select_object_sets_to_measure": "Nuclei"}, + assert tuple(invocation.key.group_key for invocation in invocations) == ( + DEFAULT_GROUP_KEY, ) + assert invocations[0].kwargs_dict["select_images_to_measure"] == ("DNA", "PH3") with config_context(pipeline_config): - assert measurement_step.processing_config.group_by is GroupBy.CHANNEL + assert measurement_step.processing_config.group_by is GroupBy.NONE + assert measurement_step.processing_config.input_source is InputSource.PIPELINE_START -def test_repeated_object_measurements_retain_each_scalar_object_selection() -> None: +def test_measurement_rosters_preserve_exact_subjects_across_public_transport() -> None: cppipe_path = Path("pipelines/repeated-object-measurements.cppipe") filemanager = _MemoryFileManager( {cppipe_path: """CellProfiler Pipeline: https://cellprofiler.org NamesAndTypes:[module_num:1|enabled:True] - Assignments count:1 + Assignments count:2 Select the image type:Grayscale image Name to assign these images:DNA Select the rule criteria:and (metadata does channel "1") + Select the image type:Grayscale image + Name to assign these images:RNA + Select the rule criteria:and (metadata does channel "2") MedianFilter:[module_num:2|enabled:True] Select the input image:DNA Name the output image:CorrDNA @@ -1252,7 +1256,7 @@ def test_repeated_object_measurements_retain_each_scalar_object_selection() -> N Select the smaller identified objects:Nuclei Name the tertiary objects to be identified:Cytoplasm MeasureObjectIntensity:[module_num:6|enabled:True] - Select images to measure:CorrDNA + Select images to measure:CorrDNA, RNA Select objects to measure:Nuclei, Cells, Cytoplasm """} ) @@ -1270,10 +1274,11 @@ def test_repeated_object_measurements_retain_each_scalar_object_selection() -> N measurement_invocations = tuple( normalize_function_pattern(measurement_steps[0].func).iter_items() ) - assert tuple( - invocation.kwargs_dict["select_object_sets_to_measure"] - for invocation in measurement_invocations - ) == ("Nuclei", "Cells", "Cytoplasm") + assert len(measurement_invocations) == 1 + assert measurement_invocations[0].key.group_key == DEFAULT_GROUP_KEY + assert measurement_invocations[0].kwargs_dict["select_images_to_measure"] == ( + "CorrDNA", "RNA", + ) source = FunctionStepTransportAuthority.source_from_pipeline(pipeline_steps) namespace: dict[str, object] = {} @@ -1286,12 +1291,104 @@ def test_repeated_object_measurements_retain_each_scalar_object_selection() -> N ) assert FunctionStepTransportAuthority.source_from_pipeline(reconstructed) == source assert tuple( - invocation.kwargs_dict["select_object_sets_to_measure"] + invocation.key for step in reconstructed_measurements for invocation in normalize_function_pattern(step.func).iter_items() + ) == (measurement_invocations[0].key,) + + parser = CPPipeParser() + modules = tuple( + parser.parse(cppipe_path, filemanager=filemanager, backend=Backend.MEMORY) + ) + declaration = _parsed_pipeline_declaration( + modules, + CellProfilerModule.source_bindings_for_modules( + modules, + SourceBindingsConfig(image_plane_sources=parser.image_plane_sources), + ), + binder=SettingsBinder(source_root=cppipe_path.parent), + ) + target = next( + unit for unit in declaration.target_units + if unit.module.name == "MeasureObjectIntensity" + ) + module_type = CellProfilerModule.require_module("MeasureObjectIntensity") + reconstructed_invocation = next( + normalize_function_pattern(reconstructed_measurements[0].func).iter_items() + ) + blocks, consumed = module_type.module_blocks_for_invocation( + invocation=reconstructed_invocation, step_context=target.context, + ) + assert len(blocks) == 1 + numbered, _next_module_num = CellProfilerModule.number_step_invocation_blocks( + (blocks,), first_module_num=1, + ) + contract, _consumed = module_type.invocation_callable_contract( + invocation=reconstructed_invocation, + numbered_module_blocks=numbered[0], + consumed_kwarg_names=consumed, + step_context=target.context, + ) + assert tuple(spec.ref() for spec in contract.artifact_inputs) == tuple( + spec.ref() for spec in target.contract.artifact_inputs + ) + assert tuple(spec.name for spec in contract.artifact_inputs) == ( + "CorrDNA", "RNA", "Nuclei", "Cells", "Cytoplasm", + ) + (measurement_output,) = contract.artifact_outputs.of_artifact_type( + MeasurementsArtifactType, + ) + assert tuple( + subject.name + for subject in ArtifactSpecRelation.measurement_subjects_for_output( + measurement_output, + ) ) == ("Nuclei", "Cells", "Cytoplasm") +def test_object_measurement_subjects_across_channels_share_one_invocation() -> None: + cppipe_path = Path("pipelines/cross-channel-object-measurements.cppipe") + filemanager = _MemoryFileManager( + {cppipe_path: """CellProfiler Pipeline: https://cellprofiler.org +NamesAndTypes:[module_num:1|enabled:True] + Assignments count:2 + Select the image type:Grayscale image + Name to assign these images:DNA + Select the rule criteria:and (metadata does channel "1") + Select the image type:Grayscale image + Name to assign these images:RNA + Select the rule criteria:and (metadata does channel "2") +IdentifyPrimaryObjects:[module_num:2|enabled:True] + Select the input image:DNA + Name the primary objects to be identified:Nuclei +IdentifyPrimaryObjects:[module_num:3|enabled:True] + Select the input image:RNA + Name the primary objects to be identified:Cells +IdentifyPrimaryObjects:[module_num:4|enabled:True] + Select the input image:RNA + Name the primary objects to be identified:Unmeasured +MeasureObjectSizeShape:[module_num:5|enabled:True] + Select object sets to measure:Nuclei, Cells +"""} + ) + steps, config = import_cellprofiler_pipeline( + cppipe_path, filemanager=filemanager, backend=Backend.MEMORY, + ) + (measurement_step,) = tuple( + step for step in steps if step.name == "MeasureObjectSizeShape" + ) + (invocation,) = tuple( + normalize_function_pattern(measurement_step.func).iter_items() + ) + assert invocation.key.group_key == DEFAULT_GROUP_KEY + assert invocation.kwargs_dict["select_object_sets_to_measure"] == ( + "Nuclei", "Cells", + ) + with config_context(config): + assert measurement_step.processing_config.group_by is GroupBy.NONE + assert measurement_step.processing_config.input_source is InputSource.PREVIOUS_STEP + + def test_mixed_source_and_produced_measurements_share_one_step() -> None: cppipe_path = Path("pipelines/mixed-source-produced-measurements.cppipe") filemanager = _MemoryFileManager( diff --git a/tests/unit/test_cellprofiler_prepared_payload_abi.py b/tests/unit/test_cellprofiler_prepared_payload_abi.py new file mode 100644 index 0000000000..30becbea9b --- /dev/null +++ b/tests/unit/test_cellprofiler_prepared_payload_abi.py @@ -0,0 +1,127 @@ +"""Compiled raw calls preserve metadata required by declared image consumers.""" + +from dataclasses import replace + +import numpy as np +from scipy import ndimage + +from openhcs.core.aligned_image_payload import ImagePayloadExecutionMode +from openhcs.core.function_patterns import NormalizedFunctionGroup +from openhcs.core.runtime_image_values import ( + ImagePayloadMetadata, + image_payload_data, + image_payload_mask, + image_payload_metadata, + normalize_image_payload_intensity, +) +from openhcs.core.runtime_object_label_building import SourceImageObjectLabelBuildRequest +from openhcs.core.runtime_object_labels import object_label_dense_array +from openhcs.core.source_spatial_domain import SourceSpatialDomain +from openhcs.interop.cellprofiler.runtime.adapter import CellProfilerRuntimeAdapter +from openhcs.interop.cellprofiler.runtime.function_contract_execution import ( + CellProfilerFunctionContractExecutor, +) +from openhcs.processing.backends.cellprofiler.color import ColorToGrayMode, color_to_gray +from openhcs.processing.backends.cellprofiler.median_filter import medianfilter +from openhcs.processing.backends.cellprofiler.secondary import ( + SecondaryMethod, + identify_secondary_objects, +) + + +def _execute_prepared(func, source, kwargs, mode=ImagePayloadExecutionMode.NATURAL): + contract = NormalizedFunctionGroup.from_pattern("image", func).items[0].contract + contract = replace( + contract, + metadata=replace( + contract.metadata, + runtime_adapter=CellProfilerRuntimeAdapter.runtime_adapter_spec(), + ), + ) + assert contract.metadata.canonical_signature is not None + assert contract.raw_main_flow_call_argument(source) is source + return CellProfilerFunctionContractExecutor().execute( + contract, + contract.resolve_canonical_raw_callable(), + source, + kwargs, + execution_mode=mode, + ) + + +def test_prepared_color_to_gray_preserves_channel_mask_and_spatial_domain(): + pixels = np.arange(4 * 5 * 3, dtype=np.float32).reshape(4, 5, 3) + mask = np.ones(pixels.shape[:2], dtype=bool) + mask[0] = False + mask[-1] = False + domain = SourceSpatialDomain(origin_yx=(2, 3), source_shape_yx=(8, 10)) + source = ImagePayloadMetadata( + source_channel_axis=-1, + source_image_names=("RGB",), + source_path="/input/rgb.tif", + source_spatial_domain=domain, + ).payload_with(pixels, mask) + + result = _execute_prepared( + color_to_gray, source, + {"mode": ColorToGrayMode.COMBINE, + "channel_indices": (0, 2), "contributions": (1.0, 3.0)}, + ) + + np.testing.assert_array_equal(image_payload_data(result), (pixels[..., 0] + 3 * pixels[..., 2]) / 4) + np.testing.assert_array_equal(image_payload_mask(result), mask) + metadata = image_payload_metadata(result) + assert metadata.source_channel_axis is None + assert metadata.source_spatial_domain == domain + assert metadata.source_image_paths == ("/input/rgb.tif",) + + +def test_prepared_medianfilter_keeps_original_intensity_scale_and_mask(): + pixels = np.arange(25, dtype=np.uint16).reshape(5, 5) + mask = np.ones(pixels.shape, dtype=bool) + mask[0] = False + source = normalize_image_payload_intensity( + ImagePayloadMetadata.for_array(pixels).payload_with(pixels, mask), + dtype=np.float32, + ) + + result = _execute_prepared( + medianfilter, source, {"window_size": 3}, ImagePayloadExecutionMode.FULL_STACK, + ) + + np.testing.assert_array_equal( + image_payload_data(result), + ndimage.median_filter(image_payload_data(source), size=3, mode="constant"), + ) + np.testing.assert_array_equal(image_payload_mask(result), mask) + assert image_payload_metadata(result).unit_interval_intensity_scale == 65535 + assert image_payload_data(result).dtype == np.float32 + + +def test_prepared_secondary_object_output_keeps_actual_source_spatial_domain(): + pixels = np.zeros((9, 9), dtype=np.float32) + domain = SourceSpatialDomain(origin_yx=(3, 4), source_shape_yx=(15, 16)) + source = ImagePayloadMetadata( + source_image_names=("DNA",), source_path="/input/dna.tif", + source_spatial_domain=domain, + ).payload_with(pixels, None) + seed_pixels = np.zeros(pixels.shape, dtype=np.int32) + seed_pixels[4, 4] = 1 + seeds = SourceImageObjectLabelBuildRequest( + image=source, labels=seed_pixels, declared_object_ids=(1,), + ).payload() + + result = _execute_prepared( + identify_secondary_objects, source, + {"primary_labels": seeds, "method": SecondaryMethod.DISTANCE_N, + "distance_to_dilate": 1, "fill_holes": False}, + ) + + _image, _rows, relationship, objects = result + expected = ndimage.distance_transform_edt(seed_pixels == 0) <= 1 + np.testing.assert_array_equal(object_label_dense_array(objects), expected.astype(np.int32)) + assert objects.source_spatial_domain.origin_yx == domain.origin_yx + assert objects.source_spatial_domain.source_shape_yx == domain.source_shape_yx + assert objects.source_provenance == image_payload_metadata(source).source_provenance + assert relationship.source_ids == (1,) + assert relationship.target_ids == (1,) diff --git a/tests/unit/test_cellprofiler_runtime_adapter.py b/tests/unit/test_cellprofiler_runtime_adapter.py index c5a86f3d1b..64112d5905 100644 --- a/tests/unit/test_cellprofiler_runtime_adapter.py +++ b/tests/unit/test_cellprofiler_runtime_adapter.py @@ -34,6 +34,7 @@ ) from openhcs.core.config import DtypeConfig from openhcs.core.function_patterns import ( + MainFlowInputProjection, DEFAULT_GROUP_KEY, FunctionInvocationKey, InvocationArtifactInputEdgePlan, @@ -59,7 +60,6 @@ from openhcs.core.runtime_artifact_queries import ( MeasurementLabelSliceFeatureQuery, MeasurementTableAxisProjection, - MeasurementTableUnion, ) from openhcs.core.runtime_artifact_values import RuntimeValue from openhcs.core.runtime_batch_contracts import SliceIndexRuntimeParameter @@ -122,7 +122,6 @@ CompiledSourceBindingPlan, NamedSourceBinding, SourceBindingOrigin, - SourceBindingRuntimeContext, SourceFilterClause, SourceFilterMatchType, SourceFilterSubject, @@ -155,8 +154,8 @@ ObjectLabelMeasurementSliceRequest, RelationshipPlaneProjectionResolution, ) -from openhcs.interop.cellprofiler.runtime.object_measurement_tables import ( - ObjectMeasurementTableIndex, +from openhcs.core.measurement_feature_queries import ( + ColumnarMeasurementTableSchema, ) from openhcs.interop.cellprofiler.runtime.object_measurement_vectors import ( MeasurementImageOperandVectorResolution, @@ -283,7 +282,7 @@ def _output_objects(adapter: CellProfilerRuntimeAdapter, name: str) -> ObjectLab _selected_output_plan(adapter, name, ObjectLabelsArtifactType) ) assert len(records) == 1 - value = records[0].value.data + value = records[0].data assert isinstance(value, ObjectLabelSet) return value @@ -295,9 +294,9 @@ def _output_measurements( records = adapter.artifact_output_records( _selected_output_plan(adapter, name, MeasurementsArtifactType) ) - tables = tuple(record.value.data for record in records) + tables = tuple(record.data for record in records) assert all(isinstance(table, MeasurementTable) for table in tables) - return MeasurementTableUnion(name, tables).as_table() + return MeasurementTable.join(name, tables) def _output_relationship( @@ -307,7 +306,7 @@ def _output_relationship( records = adapter.artifact_output_records( _selected_output_plan(adapter, name, RelationshipsArtifactType) ) - relationships = tuple(record.value.data for record in records) + relationships = tuple(record.data for record in records) assert all(isinstance(value, ObjectRelationship) for value in relationships) if len(relationships) == 1: return relationships[0] @@ -321,7 +320,7 @@ def _output_spatial_grid( records = adapter.artifact_output_records( _selected_output_plan(adapter, name, SpatialGridArtifactType) ) - value = RuntimeValue.compose(tuple(record.value for record in records)) + value = RuntimeValue.compose(tuple(record for record in records)) assert isinstance(value, (SpatialGrid, RuntimeSliceAlignedValues)) return value @@ -649,7 +648,6 @@ def _adapter( source_bindings=StepSourceBindingsConfig( bindings=(NamedSourceBinding(alias=DNA_IMAGE),) ), - source_binding_context=SourceBindingRuntimeContext.empty(), processing_context=None, plane_projection=RuntimePlaneProjection.stack(1), callable_contract=None, @@ -660,7 +658,6 @@ def _adapter( axis_scope=runtime_axis_scope(AXIS_ID), artifact_output_bindings=output_bindings, source_binding_plan=_compiled_source_binding_plan(source_bindings), - source_binding_context=source_binding_context, plane_projection=plane_projection, callable_contract=callable_contract, microscope_handler=( @@ -691,7 +688,6 @@ def _pipeline_start_contains_binding(alias): def _source_bound_image_adapter(output_bindings, images): filemanager = FileManagerStub() - paths = tuple(f"/src/{alias}.tif" for alias in images) for alias, image in images.items(): filemanager.saved[("memory", f"/src/{alias}.tif")] = image context = ContextStub(filemanager) @@ -707,12 +703,6 @@ def _source_bound_image_adapter(output_bindings, images): ) ) ), - source_binding_context=SourceBindingRuntimeContext( - step_input_files=paths, - step_input_dir="/src", - pipeline_input_files=paths, - pipeline_input_backend="memory", - ), microscope_handler=(context).microscope_handler, filemanager=filemanager, ) @@ -829,7 +819,11 @@ def _executor_for_contract( spec=spec, storage_plan=None, projection=None, - consumes_main_flow=spec.ref() in main_flow_input_refs, + main_flow_projection=( + MainFlowInputProjection.DECLARED_SOURCE_IMAGE + if spec.ref() in main_flow_input_refs + else None + ), ) ) continue @@ -1019,8 +1013,8 @@ def test_cellprofiler_adapter_adds_and_reads_objects_through_runtime_store(): ) objects = _output_objects(adapter, NUCLEI) - assert isinstance(record.value.data, ObjectLabelSet) - assert record.value.data.name == NUCLEI + assert isinstance(record.data, ObjectLabelSet) + assert record.data.name == NUCLEI assert objects.labels is labels assert objects.source_image_name == DNA_IMAGE assert objects.dimensions == ("y", "x") @@ -1062,14 +1056,14 @@ def test_cellprofiler_adapter_contextualizes_source_aligned_object_label_stack() source_image_payload=source_image, ) - assert isinstance(record.value.data, ObjectLabelSet) - assert record.value.data.source_image_provenance_planes.paths == ( + assert isinstance(record.data, ObjectLabelSet) + assert record.data.source_image_provenance_planes.paths == ( "/src/A01_s001_w1_z001_t001.tif", "/src/A01_s002_w1_z001_t001.tif", ) assert tuple( dict(metadata) - for metadata in record.value.data.source_image_provenance_planes.component_metadata + for metadata in record.data.source_image_provenance_planes.component_metadata if metadata is not None ) == ( {"well": "A01", "site": "1", "channel": "1"}, @@ -1079,7 +1073,7 @@ def test_cellprofiler_adapter_contextualizes_source_aligned_object_label_stack() assert isinstance(saved_payload, ObjectLabelSet) assert ( saved_payload.source_image_provenance_planes.paths - == record.value.data.source_image_provenance_planes.paths + == record.data.source_image_provenance_planes.paths ) @@ -1119,7 +1113,7 @@ def test_cellprofiler_adapter_contextualizes_single_source_aligned_label_plane() source_image_payload=source_image, ) - object_labels = record.value.data + object_labels = record.data assert isinstance(object_labels, ObjectLabelSet) object_labels.validate_source_alignment(NUCLEI) assert object_labels.source_image_provenance_planes.paths == (source_path,) @@ -1151,9 +1145,9 @@ def test_cellprofiler_adapter_preserves_sparse_ijv_object_value_representation() record = adapter.add_objects(NUCLEI, labels) - assert isinstance(record.value.data, ObjectLabelSet) - assert record.value.data.representation is ObjectLabelRepresentation.SPARSE_IJV - assert record.value.data.labels is sparse_rows + assert isinstance(record.data, ObjectLabelSet) + assert record.data.representation is ObjectLabelRepresentation.SPARSE_IJV + assert record.data.labels is sparse_rows objects = _output_objects(adapter, NUCLEI) assert objects.representation is ObjectLabelRepresentation.SPARSE_IJV assert objects.labels is sparse_rows @@ -1214,11 +1208,6 @@ def test_cellprofiler_adapter_does_not_cache_current_image_object_selection(): "/src/A01_s001_w1_z001_t001.tif", "/src/A01_s002_w1_z001_t001.tif", ) - source_binding_context = SourceBindingRuntimeContext( - step_input_files=source_paths, - step_input_dir="/src", - pipeline_input_files=source_paths, - ) filemanager = FileManagerStub() processing_context = ContextStub(filemanager) @@ -1230,7 +1219,6 @@ def test_cellprofiler_adapter_does_not_cache_current_image_object_selection(): runtime_value_store=store, axis_scope=runtime_axis_scope(AXIS_ID), artifact_output_bindings=output_bindings, - source_binding_context=source_binding_context, group_key=group_key, microscope_handler=( processing_context.microscope_handler @@ -1280,7 +1268,6 @@ def test_cellprofiler_adapter_does_not_cache_current_image_object_selection(): ) }, variable_components=(VariableComponents.SITE,), - source_binding_context=source_binding_context, microscope_handler=( processing_context.microscope_handler if processing_context is not None @@ -1562,9 +1549,6 @@ def test_cellprofiler_adapter_does_not_source_scope_default_image_records(): axis_scope=runtime_axis_scope(AXIS_ID), artifact_inputs=_compiled_artifact_inputs, variable_components=(VariableComponents.SITE,), - source_binding_context=SourceBindingRuntimeContext( - step_input_files=("/src/A01_s003_w1.tif",), - ), filemanager=filemanager, callable_contract=_compiled_callable_contract( calculate_math, @@ -1626,11 +1610,6 @@ def test_cellprofiler_adapter_stacks_declared_default_image_input_runtime_groups ).payload_with(np.full((2, 2), value, dtype=np.float32), None), ) - source_binding_context = SourceBindingRuntimeContext( - step_input_files=source_paths, - current_step_input_files=source_paths, - pipeline_input_files=source_paths, - ) _compiled_artifact_inputs = { edge.key: edge for edge in ( @@ -1662,7 +1641,6 @@ def test_cellprofiler_adapter_stacks_declared_default_image_input_runtime_groups runtime_value_store=store, axis_scope=runtime_axis_scope(AXIS_ID, "well", AXIS_ID), artifact_inputs=_compiled_artifact_inputs, - source_binding_context=source_binding_context, microscope_handler=(context).microscope_handler, filemanager=filemanager, variable_components=(VariableComponents.SITE,), @@ -1759,12 +1737,6 @@ def test_cellprofiler_adapter_keeps_multisource_current_image_grouped_when_files runtime_value_store=store, axis_scope=runtime_axis_scope(AXIS_ID), artifact_inputs=_compiled_artifact_inputs, - source_binding_context=SourceBindingRuntimeContext( - step_input_files=source_paths, - current_step_input_files=(source_paths[0],), - pipeline_input_files=source_paths, - source_metadata_by_path=source_metadata_by_path, - ), microscope_handler=(context).microscope_handler, filemanager=filemanager, variable_components=(VariableComponents.SITE,), @@ -1831,11 +1803,6 @@ def test_cellprofiler_adapter_stacks_declared_image_input_for_pattern_group(): ).payload_with(np.full((2, 2), value, dtype=np.float32), None), ) - source_binding_context = SourceBindingRuntimeContext( - step_input_files=source_paths, - current_step_input_files=source_paths, - pipeline_input_files=source_paths, - ) _compiled_artifact_inputs = { edge.key: edge for edge in ( @@ -1861,7 +1828,6 @@ def test_cellprofiler_adapter_stacks_declared_image_input_for_pattern_group(): axis_scope=runtime_axis_scope(AXIS_ID), group_key="A01_s{iii}_w1_z001_t001.tif", artifact_inputs=_compiled_artifact_inputs, - source_binding_context=source_binding_context, microscope_handler=(context).microscope_handler, filemanager=filemanager, variable_components=(VariableComponents.SITE,), @@ -1896,7 +1862,6 @@ def test_cellprofiler_adapter_records_output_in_declared_invocation_group(): filemanager = FileManagerStub() output_name = "MembMasked" source_path = "/plate/Images/3d_monolayer_xy1_ch3.tif" - mask_path = "/plate/Images/3d_monolayer_xy1_ch1.tif" output_plan = ArtifactOutputPlan( name=output_name, path=f"/memory/{output_name}.pkl", @@ -1923,15 +1888,6 @@ def test_cellprofiler_adapter_records_output_in_declared_invocation_group(): artifact_output_bindings=( _output_binding(output_name, ImageArtifactType, plan=output_plan), ), - source_binding_context=SourceBindingRuntimeContext( - step_input_files=(mask_path,), - current_step_input_files=(mask_path,), - pipeline_input_files=( - "/plate/Images/3d_monolayer_xy1_ch0.tif", - mask_path, - source_path, - ), - ), microscope_handler=(ContextStub(filemanager)).microscope_handler, filemanager=filemanager, ) @@ -2041,11 +1997,6 @@ def test_cellprofiler_adapter_projects_source_bound_runtime_image_to_group_plane group_key="2", plane_projection=RuntimePlaneProjection.selected(1, 2), artifact_inputs=_compiled_artifact_inputs, - source_binding_context=SourceBindingRuntimeContext( - source_metadata_by_path=dict( - zip(source_paths, source_metadata, strict=True) - ), - ), filemanager=filemanager, callable_contract=_compiled_callable_contract( calculate_math, @@ -2145,11 +2096,6 @@ def test_cellprofiler_adapter_deduplicates_grouped_runtime_image_input_locations axis_scope=runtime_axis_scope(AXIS_ID, "site", "2"), plane_projection=RuntimePlaneProjection.selected(1, 2), artifact_inputs=_compiled_artifact_inputs, - source_binding_context=SourceBindingRuntimeContext( - source_metadata_by_path=dict( - zip(source_paths, source_metadata, strict=True) - ), - ), filemanager=filemanager, callable_contract=_compiled_callable_contract( calculate_math, @@ -2724,9 +2670,6 @@ def test_cellprofiler_adapter_keeps_template_scoped_object_records_grouped(): axis_scope=runtime_axis_scope(AXIS_ID), artifact_inputs=_compiled_artifact_inputs, variable_components=(VariableComponents.SITE,), - source_binding_context=SourceBindingRuntimeContext( - step_input_files=("/src/A01_s{iii}_w1.tif",), - ), filemanager=filemanager, callable_contract=_compiled_callable_contract( calculate_math, @@ -3140,6 +3083,7 @@ def test_cellprofiler_adapter_discovers_single_realized_dynamic_grouped_input(): artifact_type=ObjectLabelsArtifactType, group_keys=(None,), group_component=AllComponents.CHANNEL, + paths_by_group={"1": realized_path}, ), invocation_scope=ComponentGroupScope.ungrouped(), producer_selection_scope=ComponentGroupScope.dynamic( @@ -3171,6 +3115,24 @@ def test_cellprofiler_adapter_discovers_single_realized_dynamic_grouped_input(): assert objects.plane_axis is RuntimePlaneAxis.RUNTIME_SLICE assert objects.domain.declared_object_id_domains == ((1,),) + # A dynamic component never grants access to another compiled producer path. + (edge,) = _compiled_artifact_inputs.values() + for undeclared_paths in (None, {"1": "/other/Nuclei_s1.pkl"}): + mismatched_edge = replace( + edge, + storage_plan=replace(edge.storage_plan, paths_by_group=undeclared_paths), + ) + mismatched_consumer = CellProfilerRuntimeAdapter( + request=replace( + consumer.request, artifact_inputs={edge.key: mismatched_edge} + ), + backend=consumer.backend, + ) + with pytest.raises( + RuntimeError, match="Missing dynamic grouped artifact input" + ): + mismatched_consumer.get_objects(NUCLEI) + def test_cellprofiler_adapter_discovers_realized_dynamic_grouped_object_inputs(): filemanager = FileManagerStub() @@ -3225,6 +3187,7 @@ def test_cellprofiler_adapter_discovers_realized_dynamic_grouped_object_inputs() artifact_type=ObjectLabelsArtifactType, group_keys=(None,), group_component=AllComponents.CHANNEL, + paths_by_group=group_paths, ), invocation_scope=ComponentGroupScope.ungrouped(), producer_selection_scope=ComponentGroupScope.dynamic( @@ -3395,22 +3358,6 @@ def test_cellprofiler_adapter_does_not_resolve_object_input_from_source_context( ), ) - source_binding_context = SourceBindingRuntimeContext( - step_input_files=( - "/plate/Images/A01_s002_w1_z001_t001.tif", - "/plate/Images/A01_s002_w2_z001_t001.tif", - ), - pipeline_input_files=( - "/plate/Images/A01_s001_w1_z001_t001.tif", - "/plate/Images/A01_s001_w2_z001_t001.tif", - "/plate/Images/A01_s002_w1_z001_t001.tif", - "/plate/Images/A01_s002_w2_z001_t001.tif", - ), - current_step_input_files=( - "/plate/Images/A01_s002_w1_z001_t001.tif", - "/plate/Images/A01_s002_w2_z001_t001.tif", - ), - ) _compiled_artifact_inputs = { edge.key: edge for edge in ( @@ -3440,7 +3387,6 @@ def test_cellprofiler_adapter_does_not_resolve_object_input_from_source_context( runtime_value_store=store, axis_scope=runtime_axis_scope(AXIS_ID), artifact_inputs=_compiled_artifact_inputs, - source_binding_context=source_binding_context, microscope_handler=(ContextStub(filemanager)).microscope_handler, filemanager=filemanager, variable_components=(VariableComponents.SITE,), @@ -3549,6 +3495,10 @@ def test_cellprofiler_adapter_preserves_ungrouped_runtime_slice_output_stack(): def test_cellprofiler_adapter_stacks_dynamic_compiled_grouped_images(): filemanager = FileManagerStub() store = RuntimeValueStore() + group_paths = { + "1": "/memory/DNA_s1.pkl", + "2": "/memory/DNA_s2.pkl", + } first = cellprofiler_runtime_adapter_for_test( runtime_value_store=store, axis_scope=runtime_axis_scope(AXIS_ID), @@ -3559,11 +3509,11 @@ def test_cellprofiler_adapter_stacks_dynamic_compiled_grouped_images(): ImageArtifactType, plan=ArtifactOutputPlan( name=DNA_IMAGE, - path="/memory/DNA_s1.pkl", + path=group_paths["1"], artifact_type=ImageArtifactType, group_keys=("1",), group_component=AllComponents.SITE, - paths_by_group={"1": "/memory/DNA_s1.pkl"}, + paths_by_group={"1": group_paths["1"]}, ), ), ), @@ -3579,11 +3529,11 @@ def test_cellprofiler_adapter_stacks_dynamic_compiled_grouped_images(): ImageArtifactType, plan=ArtifactOutputPlan( name=DNA_IMAGE, - path="/memory/DNA_s2.pkl", + path=group_paths["2"], artifact_type=ImageArtifactType, group_keys=("2",), group_component=AllComponents.SITE, - paths_by_group={"2": "/memory/DNA_s2.pkl"}, + paths_by_group={"2": group_paths["2"]}, ), ), ), @@ -3601,6 +3551,7 @@ def test_cellprofiler_adapter_stacks_dynamic_compiled_grouped_images(): artifact_type=ImageArtifactType, group_keys=(None,), group_component=AllComponents.SITE, + paths_by_group=group_paths, ), invocation_scope=ComponentGroupScope.ungrouped(), producer_selection_scope=ComponentGroupScope.dynamic( @@ -3728,7 +3679,7 @@ def test_cellprofiler_adapter_relationships_validate_declared_inputs_by_location ) ) - assert relationship.value.artifact_type is RelationshipsArtifactType + assert relationship.artifact_type is RelationshipsArtifactType def test_cellprofiler_adapter_declared_relationship_allows_pruned_child_endpoint(): @@ -3759,9 +3710,9 @@ def test_cellprofiler_adapter_declared_relationship_allows_pruned_child_endpoint ) ) - assert relationship.value.artifact_type is RelationshipsArtifactType - assert isinstance(relationship.value.data, ObjectRelationship) - assert relationship.value.data.declaration.target.name == "FilteredCells" + assert relationship.artifact_type is RelationshipsArtifactType + assert isinstance(relationship.data, ObjectRelationship) + assert relationship.data.declaration.target.name == "FilteredCells" def test_cellprofiler_adapter_relationships_accept_grouped_parent_inputs(): @@ -3858,7 +3809,7 @@ def test_cellprofiler_adapter_relationships_accept_grouped_parent_inputs(): ) ) - assert relationship.value.artifact_type is RelationshipsArtifactType + assert relationship.artifact_type is RelationshipsArtifactType def test_cellprofiler_adapter_relationships_allow_same_invocation_child_output(): @@ -3935,7 +3886,7 @@ def test_cellprofiler_adapter_relationships_allow_same_invocation_child_output() ) ) - assert relationship.value.artifact_type is RelationshipsArtifactType + assert relationship.artifact_type is RelationshipsArtifactType def test_cellprofiler_adapter_adds_and_reads_spatial_grid_artifacts(): @@ -4043,8 +3994,8 @@ def test_cellprofiler_adapter_replaces_existing_payload_with_latest_binding(): NUCLEI, ObjectLabelPayload(variant_data=ObjectLabelVariantData(labels=second)) ) - assert isinstance(record.value.data, ObjectLabelSet) - assert record.value.data.labels is second + assert isinstance(record.data, ObjectLabelSet) + assert record.data.labels is second assert filemanager.deleted == [("memory", "/memory/Nuclei.pkl")] saved_objects = filemanager.saved[("memory", "/memory/Nuclei.pkl")] assert isinstance(saved_objects, ObjectLabelSet) @@ -4139,7 +4090,7 @@ def test_cellprofiler_adapter_records_ungrouped_measurements_once(): ) assert len(records) == 1 - assert records[0].path == "/memory/A01_Measurements.pkl" + assert records[0].location.path == "/memory/A01_Measurements.pkl" def test_cellprofiler_adapter_uses_static_output_scope(): @@ -4268,7 +4219,7 @@ def test_cellprofiler_adapter_preserves_same_artifact_measurement_subjects(): ) tables = tuple( - record.value.data + record.data for record in adapter.artifact_output_records(measurement_output_plan) ) @@ -4358,14 +4309,6 @@ def test_cellprofiler_adapter_does_not_select_measurement_record_from_current_so ) ) - source_binding_context = SourceBindingRuntimeContext( - step_input_files=("/plate/Images/A01_s002_w1_z001_t001.tif",), - pipeline_input_files=( - "/plate/Images/A01_s001_w1_z001_t001.tif", - "/plate/Images/A01_s002_w1_z001_t001.tif", - ), - current_step_input_files=("/plate/Images/A01_s002_w1_z001_t001.tif",), - ) _compiled_artifact_inputs = { edge.key: edge for edge in ( @@ -4395,7 +4338,6 @@ def test_cellprofiler_adapter_does_not_select_measurement_record_from_current_so runtime_value_store=store, axis_scope=runtime_axis_scope(AXIS_ID), artifact_inputs=_compiled_artifact_inputs, - source_binding_context=source_binding_context, microscope_handler=(ContextStub(filemanager)).microscope_handler, filemanager=filemanager, variable_components=(VariableComponents.SITE,), @@ -4622,7 +4564,7 @@ def test_cellprofiler_adapter_hides_undeclared_same_name_object_table_occurrence NUCLEI_MEASUREMENTS, ), ) - ).value.data + ).data ) _compiled_artifact_inputs = { edge.key: edge @@ -7154,9 +7096,11 @@ def test_object_measurement_table_index_uses_declared_subject_for_unnamed_rows() ), ) - tables = ObjectMeasurementTableIndex.from_tables((table,)).for_object_feature( + tables = ColumnarMeasurementTableSchema.tables_for_object_feature( + (table,), "Cells", "AreaShape_FormFactor", + dialect=CELLPROFILER_MEASUREMENT_LOOKUP_DIALECT, ) assert tables == (table,) diff --git a/tests/unit/test_cellprofiler_runtime_cache_authorities.py b/tests/unit/test_cellprofiler_runtime_cache_authorities.py index 108d2cb0e1..1a40152c9a 100644 --- a/tests/unit/test_cellprofiler_runtime_cache_authorities.py +++ b/tests/unit/test_cellprofiler_runtime_cache_authorities.py @@ -329,7 +329,7 @@ def get_relationship( axis_id=AXIS_ID, ) assert len(records) == 1 - relationship = records[0].value.data + relationship = records[0].data assert isinstance(relationship, ObjectRelationship) return relationship diff --git a/tests/unit/test_cellprofiler_runtime_callable_introspection.py b/tests/unit/test_cellprofiler_runtime_callable_introspection.py index e435baed1f..d0078ba9e5 100644 --- a/tests/unit/test_cellprofiler_runtime_callable_introspection.py +++ b/tests/unit/test_cellprofiler_runtime_callable_introspection.py @@ -1,5 +1,7 @@ """CellProfiler runtime callable introspection behavior.""" +from openhcs.core.pipeline.compilation_session import ResolvedPipelineDefinition + import subprocess import sys from types import SimpleNamespace @@ -28,7 +30,6 @@ from openhcs.core.function_reference import FunctionReferenceTransportAuthority from openhcs.core.invocation_artifacts import ArtifactDeclarationStepContext from openhcs.core.pipeline.compilation_session import CompilationSession -from openhcs.core.pipeline.step_snapshot import StepSnapshot from openhcs.core.source_bindings import ( ComponentSelector, NamedSourceBinding, @@ -51,16 +52,9 @@ ) -def _snapshot_for_step(index: int, step: FunctionStep) -> StepSnapshot: - return StepSnapshot(index=index, scope_id=f"test::functionstep_{index}", step=step) - - def _compilation_session_for_steps( steps: list[FunctionStep], ) -> CompilationSession: - snapshots = tuple( - _snapshot_for_step(index, step) for index, step in enumerate(steps) - ) return CompilationSession.from_context( context=ProcessingContext( step_plans={ @@ -74,11 +68,11 @@ def _compilation_session_for_steps( }, axis_id="A01", ), - steps=steps, orchestrator=SimpleNamespace(pipeline_config=PipelineConfig()), global_config=GlobalPipelineConfig(), - step_state_map={index: object() for index in range(len(steps))}, - snapshots=snapshots, + pipeline=ResolvedPipelineDefinition( + steps=steps, step_state_map={index: object() for index in range(len(steps))} + ), ) diff --git a/tests/unit/test_cellprofiler_save_images.py b/tests/unit/test_cellprofiler_save_images.py index a6162bab2b..eab393b9f6 100644 --- a/tests/unit/test_cellprofiler_save_images.py +++ b/tests/unit/test_cellprofiler_save_images.py @@ -57,7 +57,6 @@ ) from openhcs.core.source_image_provenance import SourceImageProvenancePlanes from openhcs.core.steps.function_runtime import ( - FunctionOutputContextStrategy, project_declared_source_identity, ) from openhcs.interop.cellprofiler.module_declarations import ( @@ -961,9 +960,7 @@ def test_image_output_context_projects_declared_group_lineage_source() -> None: ), ) - contextualized = FunctionOutputContextStrategy.for_output_plan( - output_plan - ).contextualize( + contextualized = (ImageArtifactType if output_plan is None else output_plan.artifact_type).contextualize_output( project_declared_source_identity( source_slices, output_plan.source_context_source(), @@ -1043,9 +1040,7 @@ def test_declared_group_lineage_source_overrides_complete_output_identity() -> N ), ) - contextualized = FunctionOutputContextStrategy.for_output_plan( - output_plan - ).contextualize( + contextualized = (ImageArtifactType if output_plan is None else output_plan.artifact_type).contextualize_output( project_declared_source_identity( source_slices, output_plan.source_context_source(), @@ -1093,9 +1088,7 @@ def test_planned_image_output_restores_axis_without_duplicate_provenance() -> No ), ) - contextualized = FunctionOutputContextStrategy.for_output_plan( - output_plan - ).contextualize( + contextualized = (ImageArtifactType if output_plan is None else output_plan.artifact_type).contextualize_output( source_payload, source_payload, output_plan, @@ -1143,9 +1136,7 @@ def test_image_output_context_removes_selected_source_runtime_axis() -> None: ), ) - contextualized = FunctionOutputContextStrategy.for_output_plan( - output_plan - ).contextualize( + contextualized = (ImageArtifactType if output_plan is None else output_plan.artifact_type).contextualize_output( project_declared_source_identity( source_payload, output_plan.source_context_source(), @@ -1185,9 +1176,7 @@ def test_image_output_context_preserves_repeated_declared_source_planes() -> Non ), ) - contextualized = FunctionOutputContextStrategy.for_output_plan( - output_plan - ).contextualize( + contextualized = (ImageArtifactType if output_plan is None else output_plan.artifact_type).contextualize_output( project_declared_source_identity( source_payload, output_plan.source_context_source(), @@ -1227,9 +1216,7 @@ def test_image_output_context_accepts_exact_loaded_derived_artifact() -> None: relations=(SourceStackLineageSourceRelation(source=selected_artifact.ref()),), ) - contextualized = FunctionOutputContextStrategy.for_output_plan( - output_plan - ).contextualize( + contextualized = (ImageArtifactType if output_plan is None else output_plan.artifact_type).contextualize_output( source_payload, np.ones((2, 2), dtype=np.uint8), output_plan, diff --git a/tests/unit/test_cellprofiler_source_bindings.py b/tests/unit/test_cellprofiler_source_bindings.py index c5b44a9f57..1a6a5fc48e 100644 --- a/tests/unit/test_cellprofiler_source_bindings.py +++ b/tests/unit/test_cellprofiler_source_bindings.py @@ -21,9 +21,10 @@ PipelineConfig, ) from openhcs.core.source_metadata import SourceVoxelSpacing, SourceVoxelSpacingUnit -from openhcs.core.source_image_semantics import apply_source_binding_payload from openhcs.core.runtime_image_loading import ImagePayloadSourceMetadataContext from openhcs.core.runtime_image_values import ( + ImageMetadataPayload, + ImagePayloadMetadata, image_payload_data, image_payload_metadata, ) @@ -843,9 +844,8 @@ def test_names_and_types_contributes_payload_loading_semantics( multiband_data = np.zeros((5, 6, 2), dtype=np.float32) multiband_path = tmp_path / "multiband.tiff" tifffile.imwrite(multiband_path, multiband_data) - multiband = apply_source_binding_payload( + multiband = color.apply_loaded_payload( tifffile.imread(multiband_path), - color, ImagePayloadSourceMetadataContext( SourceImageIdentity(str(multiband_path)), ), @@ -853,12 +853,20 @@ def test_names_and_types_contributes_payload_loading_semantics( multiband_metadata = image_payload_metadata(multiband) assert multiband_metadata.source_channel_axis == -1 assert multiband_metadata.source_spatial_shape_yx == (5, 6) - grayscale = apply_source_binding_payload( + grayscale = color.apply_loaded_payload( np.zeros((512, 512), dtype=np.uint8), - color, None, ) assert image_payload_metadata(grayscale).source_channel_axis is None + grayscale = color.apply_loaded_payload( + ImageMetadataPayload( + np.zeros((512, 512), dtype=np.uint8), + ImagePayloadMetadata(source_channel_axis=-1), + ), + ImagePayloadSourceMetadataContext(SourceImageIdentity("grayscale.tif")), + ) + assert image_payload_metadata(grayscale).source_channel_axis is None + assert image_payload_metadata(grayscale).source_spatial_shape_yx == (512, 512) assert mask.artifact_kind is ImageArtifactType assert mask.load_as_mask is True assert objects.artifact_kind is ObjectLabelsArtifactType @@ -882,7 +890,7 @@ def test_monochrome_source_normalizes_before_collapsing_rgb_channels() -> None: source_channel_counts=frozenset((3, 4)), ) - observed = apply_source_binding_payload(rgb, binding, None) + observed = binding.apply_loaded_payload(rgb, None) expected = codes.astype(np.float32) / np.float32(255) np.testing.assert_array_equal(image_payload_data(observed), expected) @@ -909,7 +917,7 @@ def test_monochrome_source_uses_rgb_luminance_for_distinct_channels() -> None: source_channel_counts=frozenset((3, 4)), ) - observed = apply_source_binding_payload(rgb, binding, None) + observed = binding.apply_loaded_payload(rgb, None) expected = rgb2gray(rgb.astype(np.float32) / np.float32(255)) np.testing.assert_array_equal(image_payload_data(observed), expected) @@ -952,6 +960,9 @@ def test_names_and_types_contributes_3d_axis_and_voxel_spacing() -> None: config = _fold_setup_modules(module) + from openhcs.core.source_spatial_domain import VolumeSourceSpatialDomain + + assert isinstance(config.source_spatial_domain, VolumeSourceSpatialDomain) assert config.source_stack_components == (AllComponents.Z_INDEX,) assert config.source_voxel_spacing.values_zyx == (2.0, 1.0, 0.5) assert config.source_voxel_spacing.unit is SourceVoxelSpacingUnit.RELATIVE diff --git a/tests/unit/test_cellprofiler_special_io_declarations.py b/tests/unit/test_cellprofiler_special_io_declarations.py index a7dc1764a2..df42f66599 100644 --- a/tests/unit/test_cellprofiler_special_io_declarations.py +++ b/tests/unit/test_cellprofiler_special_io_declarations.py @@ -40,6 +40,7 @@ runtime_bound_parameter_names_from_callable, ) from openhcs.core.runtime_relationships import DirectedObjectRelationshipPayload +from openhcs.core.runtime_plane_projection import RuntimeSliceInvariantValue from openhcs.core.runtime_tabular_values import ColumnarRows from openhcs.interop.cellprofiler.module_artifact_declarations import ( MeasurementArtifactOutputModule, @@ -85,6 +86,9 @@ IdentifyPrimaryObjectsModule, identify_primary_objects, ) +from openhcs.processing.backends.cellprofiler.primary_object_diagnostics import ( + PrimaryObjectDiagnosticPlanes, +) from openhcs.processing.backends.cellprofiler.secondary import ( IdentifySecondaryObjectsModule, IdentifyTertiaryObjectsModule, @@ -427,11 +431,11 @@ def test_optional_object_special_input_does_not_consume_primary_image() -> None: objects = ArtifactSpec.input("Nuclei", ObjectLabelsArtifactType) assert MeasureImageIntensityModule.primary_image_inputs( - measure_image_intensity, + CallableContract.from_prepared_callable(measure_image_intensity), (image,), ) == (image,) assert MeasureImageIntensityModule.primary_image_inputs( - measure_image_intensity_objects, + CallableContract.from_prepared_callable(measure_image_intensity_objects), (image, objects), ) == (image,) @@ -603,7 +607,11 @@ def test_fixed_return_slots_follow_nominal_contract_output_order() -> None: main_flow=(dna,), ), identify_primary_objects, - (MeasurementsArtifactType, ObjectLabelsArtifactType), + ( + MeasurementsArtifactType, + ObjectLabelsArtifactType, + *((ImageArtifactType,) * len(PrimaryObjectDiagnosticPlanes._fields)), + ), ), ( _contract( @@ -707,6 +715,22 @@ def test_fixed_return_slots_follow_nominal_contract_output_order() -> None: len(contract.trailing_return_output_specs) + 1 ) + primary_contract = next( + contract + for contract, func, _artifact_types in contracts_and_functions + if func is identify_primary_objects + ) + diagnostic_outputs = primary_contract.trailing_return_output_specs[2:] + diagnostic_prefix = ArtifactSidecarRole.QA_CHECKPOINT.name_for(nuclei.name) + assert tuple(spec.name for spec in diagnostic_outputs) == tuple( + f"{diagnostic_prefix}__{stage}" + for stage in PrimaryObjectDiagnosticPlanes._fields + ) + assert all( + spec.sidecar_role is ArtifactSidecarRole.QA_CHECKPOINT + for spec in diagnostic_outputs + ) + def test_contract_order_owns_guided_grid_and_tertiary_input_mapping() -> None: grid = ArtifactSpec.output("Grid", SpatialGridArtifactType) @@ -803,9 +827,19 @@ def test_object_colocalization_rank_provider_is_runtime_bound() -> None: assert parameter.kind is inspect.Parameter.KEYWORD_ONLY assert runtime_bound_parameter_names_from_callable( measure_colocalization_objects - ) == ("rank_provider", "threshold_mask_outputs") - assert CallableContract.from_callable( - measure_colocalization_objects - ).config_bound_parameter_names == ("dtype_config",) + ) == ("rank_provider", "threshold_mask_outputs", "costes_threshold_batch") + contract = CallableContract.from_callable(measure_colocalization_objects) + assert contract.config_bound_parameter_names == ("dtype_config",) assert parameters["dtype_config"].annotation is LazyDtypeConfig assert "rank_provider" in parameter_exclusions(measure_colocalization_objects) + assert parameters["costes_threshold_batch"].kind is inspect.Parameter.KEYWORD_ONLY + assert parameters["costes_threshold_batch"].default is None + assert "costes_threshold_batch" in parameter_exclusions( + measure_colocalization_objects + ) + costes_declaration = next( + declaration + for declaration in contract.metadata.runtime_bound_parameters + if declaration.require_parameter_name() == "costes_threshold_batch" + ) + assert costes_declaration.annotation_type is RuntimeSliceInvariantValue diff --git a/tests/unit/test_cellprofiler_spreadsheet_export.py b/tests/unit/test_cellprofiler_spreadsheet_export.py index 80ed53ca20..5136fda7f7 100644 --- a/tests/unit/test_cellprofiler_spreadsheet_export.py +++ b/tests/unit/test_cellprofiler_spreadsheet_export.py @@ -1645,9 +1645,11 @@ def _measurement_record( axis_id=axis_id, ) return StoredRuntimeValue( - value, - RuntimeArtifactLocation(path=output_plan.path, backend="memory"), - ) + key=value.key, + data=value.data, + materialization_source_metadata=value.materialization_source_metadata, + location=RuntimeArtifactLocation(path=output_plan.path, backend="memory"), + ) def _fixture_field_dtype( @@ -1694,6 +1696,8 @@ def _relationship_record(name: str, *, axis_id: str) -> StoredRuntimeValue: axis_id=axis_id, ) return StoredRuntimeValue( - value, - RuntimeArtifactLocation(path=output_plan.path, backend="memory"), - ) + key=value.key, + data=value.data, + materialization_source_metadata=value.materialization_source_metadata, + location=RuntimeArtifactLocation(path=output_plan.path, backend="memory"), + ) diff --git a/tests/unit/test_cellprofiler_static_deletion_gates.py b/tests/unit/test_cellprofiler_static_deletion_gates.py index 1c48cb7972..8471b4ef75 100644 --- a/tests/unit/test_cellprofiler_static_deletion_gates.py +++ b/tests/unit/test_cellprofiler_static_deletion_gates.py @@ -794,7 +794,7 @@ def test_runtime_adapter_state_has_one_nominal_owner() -> None: } request = classes["RuntimeAdapterRequest"] adapter = classes["CellProfilerRuntimeAdapter"] - source_context = classes["SourceBindingRuntimeContext"] + assert "SourceBindingRuntimeContext" not in classes request_fields = { node.target.id @@ -826,9 +826,10 @@ def test_runtime_adapter_state_has_one_nominal_owner() -> None: isinstance(node, ast.AnnAssign) and isinstance(node.target, ast.Name) and node.target.id == "source_binding_context" - for node in source_context.body + for node in request.body ) - for class_name in ("FunctionRuntimeScope", "PatternGroupData"): + assert "FunctionRuntimeScope" not in classes + for class_name in ("PatternGroupData",): assert all( ast.unparse(base) != "SourceBindingRuntimeContext" for base in classes[class_name].bases @@ -1267,8 +1268,8 @@ def test_nominal_payloads_are_not_erased_before_semantic_projection() -> None: ) semantic_calls = frozenset( { - "MeasurementLabelSourceAlignmentStrategy.align", - "MeasurementLabelSourceAlignmentStrategy.align_request_labels_to_image_source", + "MeasurementImageLabelAlignmentRequest.labels_for_image", + "MeasurementImageLabelAlignmentRequest.labels_in_image_source", "RuntimeSliceProjection.value_for_slice", "SourceSpatialDomainAdapter.aligned_values", } diff --git a/tests/unit/test_child_measurement_producer_selection.py b/tests/unit/test_child_measurement_producer_selection.py index 43a0c28fe2..7493daf581 100644 --- a/tests/unit/test_child_measurement_producer_selection.py +++ b/tests/unit/test_child_measurement_producer_selection.py @@ -101,7 +101,7 @@ def _compiled_edge(*, dynamic=False, declared=True): consumer_variable_components=ComponentSet((AllComponents.SITE,)), source_bindings=EMPTY_SOURCE_BINDINGS, available_artifacts=ArtifactSpecCollection(()), - consumes_main_flow=False, + main_flow_projection=None, ) return edge, child @@ -212,13 +212,13 @@ def test_declared_child_measurements_gather_all_exact_producer_channels(dynamic) "3", "3", ] - from openhcs.interop.cellprofiler.runtime.object_measurement_tables import ( - ObjectMeasurementTableIndex, + from openhcs.core.measurement_feature_queries import ( + ColumnarMeasurementTableSchema, ) - children = ObjectMeasurementTableIndex.from_tables( - tuple(record.value.data for record in records) - ).for_object("Children") + children = ColumnarMeasurementTableSchema.tables_for_object( + tuple(record.data for record in records), "Children" + ) assert [table.source_image_name for table in children] == [ "Orig1", "Orig2", @@ -512,13 +512,13 @@ def _upstream_rows(*, sites=("1", "2"), well="A01", time="1"): def test_actual_upstream_consumer_preserves_all_channels_and_site_correlation(): rows, child, _ = _upstream_rows(sites=("2", "1")) - values = rows.upstream_child_measurement_values(child) + values = rows.upstream_child_feature_indexes(child) for channel in ("1", "2", "5", "3"): feature = f"Intensity_MeanIntensity_Orig{channel}" for index in (0, 1): for label in (1, 2): assert ( - values[index, label][feature] + values[index][feature].values_by_label[label] == int(channel) * 100 + (index + 1) * 10 + label ) @@ -527,7 +527,7 @@ def test_actual_upstream_consumer_preserves_all_channels_and_site_correlation(): def test_actual_upstream_consumer_rejects_incompatible_source_planes(kwargs): rows, child, _ = _upstream_rows(**kwargs) with pytest.raises(ValueError, match="does not align"): - rows.upstream_child_measurement_values(child) + rows.upstream_child_feature_indexes(child) def test_actual_parent_means_include_each_channel_without_merging_site_ids(): @@ -571,13 +571,13 @@ def test_actual_parent_means_include_each_channel_without_merging_site_ids(): def test_upstream_tables_without_source_coordinates_are_rejected(): rows, child, _ = _upstream_rows() table = next( - record.value.data + record.data for record in rows.request.adapter.request.context.runtime_value_store.values() - if isinstance(record.value.data, MeasurementTable) + if isinstance(record.data, MeasurementTable) ) table.source_image_provenance_planes = SourceImageProvenancePlanes() with pytest.raises(ValueError, match="complete source image-set identity"): - rows.upstream_child_measurement_values(child) + rows.upstream_child_feature_indexes(child) def test_input_relation_preserves_original_output_and_surviving_input_relations(): @@ -672,7 +672,7 @@ def test_complete_input_keeps_existing_record_scope_ambiguity_guard(): def test_upstream_repeated_source_coordinates_do_not_merge_distinct_row_planes(): rows, child, _ = _upstream_rows(sites=("1", "1")) with pytest.raises(ValueError, match="row axes .* exceed its source axis"): - rows.upstream_child_measurement_values(child) + rows.upstream_child_feature_indexes(child) @pytest.mark.parametrize( @@ -732,9 +732,9 @@ def test_complete_dynamic_input_rejects_foreign_producer_location(): foreign = RuntimeValueStore() for record in _measurement_store(edge).values(): foreign.record( - record.value, - path=record.path.replace("/memory/", "/another-producer/"), - backend=record.backend, + record, + path=record.location.path.replace("/memory/", "/another-producer/"), + backend=record.location.backend, ) with pytest.raises(RuntimeError, match="Missing dynamic grouped artifact input"): _runtime_input(edge).records(foreign) @@ -744,7 +744,7 @@ def test_complete_dynamic_input_rejects_foreign_producer_backend(): edge, _ = _compiled_edge(dynamic=True) foreign = RuntimeValueStore() for record in _measurement_store(edge).values(): - foreign.record(record.value, path=record.path, backend="disk") + foreign.record(record, path=record.location.path, backend="disk") with pytest.raises(RuntimeError, match="Missing dynamic grouped artifact input"): _runtime_input(edge).records(foreign) @@ -755,8 +755,8 @@ def test_complete_dynamic_input_selects_compiled_producer_after_workspace_rebind original = store.values() for record in original: store.replace( - record.value, - path=record.path.replace("/memory/", "/later-producer/"), - backend=record.backend, + record, + path=record.location.path.replace("/memory/", "/later-producer/"), + backend=record.location.backend, ) assert _runtime_input(edge).records(store) == original diff --git a/tests/unit/test_collapsed_persisted_occurrence_435.py b/tests/unit/test_collapsed_persisted_occurrence_435.py new file mode 100644 index 0000000000..11a52555cf --- /dev/null +++ b/tests/unit/test_collapsed_persisted_occurrence_435.py @@ -0,0 +1,392 @@ +"""Public same-path image publication controls; the original #494 pair is unknown.""" + +from dataclasses import fields, replace +from pathlib import Path +import json + +import numpy as np +import pytest +import tifffile + +from polystore.disk import DiskStorageBackend +from polystore.filemanager import FileManager +from polystore.memory import MemoryStorageBackend + +from openhcs.constants.constants import Backend, Microscope +from openhcs.core.aligned_image_payload import AlignedImageSliceContext +from openhcs.core.artifacts import ( + ArtifactOutputPlan, + ImageArtifactType, + ObjectLabelsArtifactType, +) +from openhcs.core.compiled_step_plan import RuntimeArtifactMaterializationPlan +from openhcs.core.runtime_artifact_values import RuntimeValue +from openhcs.core.runtime_image_values import ImageMetadataPayload, ImagePayloadMetadata +from openhcs.core.runtime_stores import RuntimeValueStore +from openhcs.core.source_image_provenance import ( + SourceImageProvenance, + SourceImageProvenancePlanes, +) +from openhcs.core.source_metadata import SourceVoxelSpacing +from openhcs.core.source_projection import ( + OpenHCSPlaneAddress, + SourcePixelRef, + SourcePlaneProjection, + SourceProjectionSet, + SourceProjectionMetadataSerializer, +) +from openhcs.core.source_workspace_projection import VirtualWorkspaceSourceProjection +from openhcs.core.steps.function_output_identity import FunctionOutputIdentity +from openhcs.core.steps.function_outputs import ( + PrimaryImageMetadataTarget, + RuntimeArtifactMaterializationAuthority, +) +from openhcs.microscopes.source_schema import SourceSchemaFilenameParser +from openhcs.processing.materialization import ( + ImageFileOptions, + MaterializationSpec, + MaterializedFilenameIdentity, +) + +from tests.unit.test_function_outputs import ( + context_stub, + function_step_plan, + record_output_path, +) + + +def _actual_saved_occurrence(tmp_path, scenario): + filemanager = FileManager( + { + Backend.DISK.value: DiskStorageBackend(), + Backend.MEMORY.value: MemoryStorageBackend(), + } + ) + context = context_stub(filemanager, parser=SourceSchemaFilenameParser()) + context.microscope_handler.microscope_type = Microscope.OPENHCS.value + context.runtime_value_store = RuntimeValueStore() + context.metadata_cache = {} + context.tiff_config = None + plan = function_step_plan("Collapsed public mosaic") + plan.streaming_configs = {} + plan.write_backend = Backend.DISK.value + plan.output_plate_root = str(tmp_path) + plan.output_dir = tmp_path / "images" + plan.sub_dir = "images" + plan.analysis_results_dir = str(plan.output_dir) + plan.runtime_artifact_materialization = RuntimeArtifactMaterializationPlan( + persistent_enabled=True, + persistent_backend=Backend.DISK.value, + ) + context.step_plans = {plan.step_index: plan} + filename = "A01_s001_w1_z001_t001_Mosaic.tif" + output_plan = ArtifactOutputPlan( + name="Mosaic", + path="/memory/Mosaic.pkl", + artifact_type=ImageArtifactType, + producer_step_index=plan.step_index, + producer_step_scope_id=plan.step_scope_id, + producer_step_name=plan.step_name, + materialization=MaterializationSpec( + ImageFileOptions( + filename_suffix=".tif", + filename_identity=MaterializedFilenameIdentity.ARTIFACT_NAME, + relative_path_template=filename, + ) + ), + ) + plan.artifact_outputs[output_plan.ref()] = output_plan + semantic_components = { + "well": "A01", + "channel": "1", + "z_index": "1", + "timepoint": "1", + } + if scenario != "collapsed_site": + semantic_components["site"] = "1" + provenance = SourceImageProvenance( + source_component_metadata=semantic_components, + source_image_provenance_planes=( + SourceImageProvenancePlanes.from_contributor_components( + paths=("/source/site-1.tif", "/source/site-2.tif"), + component_metadata=({"site": "1"}, {"site": "2"}), + ) + if scenario == "collapsed_site" + else SourceImageProvenancePlanes() + ), + source_image_names=("Mosaic",), + ) + metadata = ImagePayloadMetadata( + source_provenance=provenance, + source_voxel_spacing=SourceVoxelSpacing((0.5, 0.5)), + ) + pixels = np.arange( + 40 if scenario == "collapsed_site" else 20, dtype=np.uint16 + ).reshape((2, 4, 5) if scenario == "collapsed_site" else (4, 5)) + payload = ImageMetadataPayload(pixels, metadata) + artifact_payload = payload + if scenario == "metadata_conflict": + artifact_payload = metadata.replace_fields( + source_image_names=("IndependentRole",), + ).payload_with(pixels) + elif scenario == "scalar_address_conflict": + artifact_payload = metadata.with_source_component_metadata( + {**semantic_components, "site": "2"}, + ).payload_with(pixels) + context.runtime_value_store.record( + RuntimeValue.normalize(output_plan, artifact_payload, axis_id="A01"), + path=output_plan.path, + backend=Backend.MEMORY.value, + ) + destination = plan.output_dir / filename + filemanager.ensure_directory(plan.output_dir, Backend.MEMORY.value) + filemanager.ensure_directory(plan.output_dir, Backend.DISK.value) + filemanager.save(payload, str(destination), Backend.MEMORY.value) + filemanager.save(pixels, str(destination), Backend.DISK.value) + record_output_path( + context, + plan, + destination, + image_metadata=metadata, + output_context=AlignedImageSliceContext.main_flow( + output_key="Mosaic", + artifact_kind=ImageArtifactType.value, + ), + identity=FunctionOutputIdentity( + component_values=semantic_components, + filename_component_values={**semantic_components, "site": "1"}, + extension=".tif", + source="original collapsed-mosaic declaration", + ), + ) + target = PrimaryImageMetadataTarget.from_plan(plan) + # This is the existing accepted main-flow publication, before a mirror is added. + original = target.produced_projection_entries(context, plan) + original = SourceProjectionMetadataSerializer.projection_fields( + original.projection_paths + ) + assert len(original["source_projection"]) == 1 + if scenario == "collapsed_site": + row = original["source_projection"][0] + assert row["address"]["site"] == "1" + assert "site" not in row["source_metadata"] + saved = RuntimeArtifactMaterializationAuthority.materialize(context, plan) + assert len(saved) == 1 + (output,) = saved[0].outputs_for_backend(Backend.DISK.value) + assert output.path == str(destination) + persisted = tifffile.imread(destination) + np.testing.assert_array_equal(persisted, pixels) + assert persisted.dtype == pixels.dtype + return ( + context, + plan, + replace(target, artifact_materializations=saved), + output_plan, + pixels, + ) + + +def _rejected_original_pair(error): + """Read actual operands from the raising frame; do not copy the join algorithm.""" + frames = [] + traceback = error.__traceback__ + while traceback is not None: + frame = traceback.tb_frame + if ( + frame.f_code.co_name == "project_runtime_artifacts" + and frame.f_code.co_filename.endswith( + "/openhcs/core/steps/function_outputs.py" + ) + ): + frames.append(frame.f_locals.copy()) + traceback = traceback.tb_next + assert len(frames) == 1 + return frames[0] + + +@pytest.mark.parametrize( + "scenario", + ( + "scalar_address_conflict", + "metadata_conflict", + ), +) +def test_real_same_path_join_observes_original_rejected_pair(tmp_path, scenario): + context, plan, target, _output_plan, pixels = _actual_saved_occurrence( + tmp_path, scenario + ) + with pytest.raises( + ValueError, match="Conflicting metadata for persisted image occurrence" + ) as failure: + target.produced_projection_entries(context, plan) + pair = _rejected_original_pair(failure.value) + projection = pair["projection"] + metadata = pair["metadata"] + assert pair["record"].owns_persisted_artifact( + pair["materialization"].output_plan, + pair["destination"], + target.output_dir, + ) + # Comparisons below are post-exception observations, not admission replacements. + address_equal = projection.address == pair["address"] + metadata_equal = projection.image_metadata == metadata + differing_fields = [ + member.name + for member in fields(projection.image_metadata) + if getattr(projection.image_metadata, member.name) + != getattr(metadata, member.name) + ] + witness = { + "scenario": scenario, + "exception": str(failure.value), + "manifest_address": projection.address.as_component_metadata(), + "artifact_address": ( + None if pair["address"] is None else pair["address"].as_component_metadata() + ), + "address_equal": address_equal, + "metadata_equal": metadata_equal, + "differing_fields": differing_fields, + } + (tmp_path / "actual-rejected-pair.json").write_text(json.dumps(witness, indent=2)) + if scenario == "metadata_conflict": + assert address_equal + assert not metadata_equal + assert differing_fields == ["source_provenance"] + else: + assert not address_equal + assert not metadata_equal + assert differing_fields == ["source_provenance"] + assert pair["address"].as_component_metadata()["site"] == "2" + np.testing.assert_array_equal(pair["output"].content, pixels) + + +def test_real_scalar_same_path_mirror_remains_admissible(tmp_path): + context, plan, target, _output_plan, _pixels = _actual_saved_occurrence( + tmp_path, "scalar" + ) + structured = target.produced_projection_entries(context, plan) + structured = SourceProjectionMetadataSerializer.projection_fields( + structured.projection_paths + ) + assert len(structured["source_projection"]) == 1 + assert structured["source_projection"][0]["source_alias"] == "Mosaic" + + +@pytest.mark.parametrize("mismatch", ("alias", "kind", "scope", "path")) +def test_actual_producer_occurrence_never_matches_foreign_declaration( + tmp_path, mismatch +): + context, plan, target, output_plan, _pixels = _actual_saved_occurrence( + tmp_path, "scalar" + ) + (record,) = target.produced_records(context, plan) + destination = record.path_under(target.output_dir) + assert record.owns_persisted_artifact(output_plan, destination, target.output_dir) + if mismatch == "path": + destination = str(target.output_dir / "independent.tif") + else: + change = { + "alias": {"name": "IndependentRole"}, + "kind": {"artifact_type": ObjectLabelsArtifactType}, + "scope": {"producer_step_scope_id": "independent-step-scope"}, + }[mismatch] + output_plan = replace(output_plan, **change) + assert not record.owns_persisted_artifact( + output_plan, destination, target.output_dir + ) + + +def test_collapsed_same_path_mirror_retains_filename_and_semantic_views(tmp_path): + context, plan, target, _output_plan, pixels = _actual_saved_occurrence( + tmp_path, "collapsed_site" + ) + structured = target.produced_projection_entries(context, plan) + structured = SourceProjectionMetadataSerializer.projection_fields( + structured.projection_paths + ) + (row,) = structured["source_projection"] + assert row["address"]["site"] == "1" + assert row["source_alias"] == "Mosaic" + assert "site" not in row["source_metadata"] + metadata = ImagePayloadMetadata.from_mapping( + row[SourceProjectionMetadataSerializer.IMAGE_METADATA_FIELD] + ) + assert "site" not in metadata.source_component_metadata + assert len(metadata.source_provenance.represented_source_identities) == 2 + assert metadata.source_voxel_spacing == SourceVoxelSpacing((0.5, 0.5)) + assert metadata.plane_axis is None + target.write(context, produced_plan=plan) + document = json.loads((tmp_path / "openhcs_metadata.json").read_text()) + reopened = VirtualWorkspaceSourceProjection.from_openhcs_metadata( + tmp_path, document + ) + projection = reopened.source_projections_by_virtual_path[row["virtual_path"]] + assert projection.address.as_component_metadata()["site"] == "1" + assert "site" not in projection.image_metadata.source_component_metadata + assert ( + len(projection.image_metadata.source_provenance.represented_source_identities) + == 2 + ) + np.testing.assert_array_equal( + tifffile.imread(tmp_path / row["virtual_path"]), pixels + ) + + +def test_standalone_collapsed_artifact_keeps_semantic_optional_address(tmp_path): + context, plan, target, _output_plan, _pixels = _actual_saved_occurrence( + tmp_path, "collapsed_site" + ) + ((projection, _path),) = target.project_runtime_artifacts(context, plan) + assert projection.address is None + assert projection.execution_scope is not None + assert "site" not in projection.image_metadata.source_component_metadata + assert ( + len(projection.image_metadata.source_provenance.represented_source_identities) + == 2 + ) + assert SourceProjectionSet((projection,)).artifact_projections == (projection,) + + +@pytest.mark.parametrize("valid_address", (True, False)) +def test_supplied_projection_map_must_retain_the_manifest_filename_address( + tmp_path, valid_address +): + context, plan, target, output_plan, _pixels = _actual_saved_occurrence( + tmp_path, "scalar" + ) + (record,) = target.produced_records(context, plan) + destination = record.path_under(target.output_dir) + (payload,) = context.filemanager.load_batch((destination,), Backend.MEMORY.value) + metadata = target.persisted_image_metadata( + context, destination=destination, payload=payload + ) + address = record.filename_address + if not valid_address: + address = OpenHCSPlaneAddress.from_complete_source_metadata( + {**address.as_component_metadata(), "site": "2"}, + ) + projection = SourcePlaneProjection( + address=address, + ref=SourcePixelRef( + Backend.DISK.value, str(Path(destination).relative_to(tmp_path)) + ), + source_alias=record.output_context.persisted_source_alias, + source_metadata=metadata.source_component_metadata, + image_metadata=metadata, + ) + assert record.owns_persisted_artifact(output_plan, destination, target.output_dir) + supplied = {Path(destination): (record, projection)} + if valid_address: + assert ( + target.project_runtime_artifacts( + context, plan, produced_projections=supplied + ) + == () + ) + else: + with pytest.raises( + ValueError, match="Conflicting metadata for persisted image occurrence" + ): + target.project_runtime_artifacts( + context, plan, produced_projections=supplied + ) diff --git a/tests/unit/test_compilation_session.py b/tests/unit/test_compilation_session.py index d2656e432f..27a7d9f559 100644 --- a/tests/unit/test_compilation_session.py +++ b/tests/unit/test_compilation_session.py @@ -1,3 +1,4 @@ +from openhcs.core.pipeline.compilation_session import ResolvedPipelineDefinition from inspect import signature from types import SimpleNamespace @@ -22,6 +23,8 @@ ) from openhcs.core.context.processing_context import ProcessingContext from openhcs.core.function_patterns import ( + compile_function_pattern, + inject_artifact_input_values, normalize_function_pattern, ) from openhcs.core.invocation_artifacts import ArtifactDeclarationStepContext @@ -33,7 +36,7 @@ PathPlannerArtifactStage, PathPlannerExecutionGroups, ) -from openhcs.core.pipeline.step_snapshot import StepSnapshot +from openhcs.core.steps.abstract import AbstractStep from openhcs.core.source_bindings import ( EMPTY_SOURCE_BINDINGS, ComponentSelector, @@ -70,7 +73,7 @@ def test_compiler_captures_scoped_worker_count(pipeline_workers, expected_worker try: ObjectStateRegistry.register(global_state, _skip_snapshot=True) ObjectStateRegistry.register(pipeline_state, _skip_snapshot=True) - captured = PipelineCompiler._capture_pipeline_config(pipeline_state) + captured = pipeline_state.to_saved_resolved_object() assert captured.num_workers == expected_workers assignments = PipelineCompiler._calculate_worker_assignments( ["A", "B", "C", "D"], captured.num_workers @@ -92,8 +95,9 @@ def test_axis_session_initialization_requires_pipeline_resolved_state() -> None: PipelineCompiler.initialize_step_plans_for_context ).parameters - assert "step_state_map" in parameters - assert "step_snapshots" in parameters + assert "pipeline" in parameters + assert "step_state_map" not in parameters + assert "step_snapshots" not in parameters assert "steps_already_resolved" not in parameters assert "_resolve_steps_for_context" not in vars(PipelineCompiler) @@ -180,13 +184,12 @@ def _previous_step_and_external_source(image, dna): return image, dna -def _snapshot( +def _resolved_step( step: FunctionStep, - index: int, variable_components=(VariableComponents.SITE,), source_bindings=EMPTY_SOURCE_BINDINGS, input_source: InputSource = InputSource.PREVIOUS_STEP, -) -> StepSnapshot: +) -> AbstractStep: step.source_bindings = source_bindings step.processing_config = ProcessingConfig( variable_components=list(variable_components), @@ -194,11 +197,7 @@ def _snapshot( input_source=input_source, ) step.step_materialization_config = StepMaterializationConfig(enabled=False) - return StepSnapshot( - index=index, - scope_id=f"plate::functionstep_{index}", - step=step, - ) + return step def _context() -> SimpleNamespace: @@ -223,14 +222,13 @@ def _orchestrator(pipeline_config: PipelineConfig | None = None) -> SimpleNamesp def _compile_source_plans_for_contract( session: CompilationSession, - snapshot: StepSnapshot, + snapshot: AbstractStep, func, main_input_dependency: StepInputDependency = StepInputDependency.pipeline_start(), ): planner = SimpleNamespace( session=session, artifact_context=ArtifactDeclarationStepContext.empty(), - source_bindings_for_snapshot=(lambda value: value.step.source_bindings), ) stage = PathPlannerArtifactStage(planner) execution_bindings = stage.source_bindings_for_contracts( @@ -245,10 +243,10 @@ def _compile_source_plans_for_contract( class _EffectiveConfigContextOrchestrator: - def create_context(self, axis_id: str) -> ProcessingContext: + def create_context(self, axis_id: str, *, resolved_config) -> ProcessingContext: return ProcessingContext( axis_id=axis_id, - auto_add_output_plate_to_plate_manager=True, + auto_add_output_plate_to_plate_manager=resolved_config.auto_add_output_plate_to_plate_manager, ) @@ -271,67 +269,99 @@ def test_axis_compilation_request_preserves_effective_auto_add_flag(): ) -def test_compilation_session_owns_step_snapshot_plan_invariants(): +def test_compilation_session_shares_resolved_pipeline_and_owns_axis_plans(): step = FunctionStep(func=_identity, name="step") - step_state = object() + step_state = SimpleNamespace(scope_id="plate::functionstep_0") session = CompilationSession.from_context( context=_context(), - steps=[step], orchestrator=_orchestrator(), global_config=GlobalPipelineConfig(), - step_state_map={0: step_state}, - snapshots=(_snapshot(step, 0),), + pipeline=ResolvedPipelineDefinition( + steps=(_resolved_step(step),), step_state_map={0: step_state} + ), ) assert session.axis_id == "A01" - assert session.step(0) is step - assert session.step_state(0) is step_state - assert session.snapshot(0).step.name == "step" + assert session.pipeline.steps[0] is not step + assert step.func is _identity + captured = session.pipeline.steps[0].func + assert normalize_function_pattern(captured) is captured + assert next(captured.iter_items()).func is _identity + assert session.pipeline.step_state_map[0] is step_state + assert session.pipeline.steps[0].name == "step" assert session.plan(0).step_name == "step" -def test_compilation_session_rejects_missing_snapshot(): - step = FunctionStep(func=_identity, name="step") - - with pytest.raises(ValueError, match="one StepSnapshot per step"): - CompilationSession.from_context( - context=_context(), - steps=[step], - orchestrator=_orchestrator(), - global_config=GlobalPipelineConfig(), - step_state_map={0: object()}, - snapshots=(), - ) - - -def test_compilation_session_rejects_non_contiguous_snapshot_index(): - step = FunctionStep(func=_identity, name="step") - - with pytest.raises(ValueError, match="index mismatch"): - CompilationSession.from_context( - context=_context(), - steps=[step], - orchestrator=_orchestrator(), - global_config=GlobalPipelineConfig(), - step_state_map={0: object()}, - snapshots=(_snapshot(step, 1),), - ) +def test_resolved_declarations_reuse_contracts_but_keep_axis_and_author_epochs(monkeypatch): + from openhcs.core.pipeline.artifact_planning import extract_artifact_declarations + from openhcs.core.invocation_artifacts import InvocationContractPlan + + @artifact_inputs("grid_dimensions") + def needs_grid(image, grid_dimensions, *, sigma=1): + return image + + kwargs = {"grid_dimensions": None, "sigma": 2} + authored = FunctionStep( + func={1: [(needs_grid, kwargs), (_identity, {"enabled": False})]}, + name="Grid", + ) + definition = [authored] + state = SimpleNamespace(scope_id="plate::functionstep_0") + from_callable = CallableContract.from_callable.__func__ + calls = [] + + def count_contracts(cls, func): + calls.append(func) + return from_callable(cls, func) + + monkeypatch.setattr(CallableContract, "from_callable", classmethod(count_contracts)) + pipeline = PipelineCompiler._filter_enabled_steps(definition, {0: state}) + captured = pipeline.steps[0].func + (item,) = tuple(captured.iter_items()) + assert definition == [authored] and definition[0].func[1][0][1] is kwargs + assert captured.source_group_keys == (1,) + assert calls == [needs_grid] + assert normalize_function_pattern(captured) is captured + extract_artifact_declarations(captured) + injected = inject_artifact_input_values(captured, {"grid_dimensions": (3, 4)}) + other_axis = inject_artifact_input_values(captured, {"grid_dimensions": (8, 9)}) + compiled = compile_function_pattern(injected, {}, {}) + assert calls == [needs_grid] + assert next(injected.iter_items()).contract is item.contract + assert next(other_axis.iter_items()).contract is item.contract + assert next(compiled.iter_invocations()).contract is item.contract + assert next(injected.iter_items()).kwargs_dict["grid_dimensions"] == (3, 4) + assert next(other_axis.iter_items()).kwargs_dict["grid_dimensions"] == (8, 9) + assert item.kwargs_dict == {"grid_dimensions": None, "sigma": 2} + + replacement = from_callable(CallableContract, needs_grid) + provider_compiled = compile_function_pattern( + injected, + {}, + {}, + invocation_contract_provider=lambda _item, _context: InvocationContractPlan( + replacement + ), + ) + assert next(provider_compiled.iter_invocations()).contract is replacement + kwargs["sigma"] = 7 + assert item.kwargs_dict["sigma"] == 2 + recaptured = ResolvedPipelineDefinition(definition, {0: state}) + assert next(recaptured.steps[0].func.iter_items()).kwargs_dict["sigma"] == 7 + assert calls == [needs_grid, needs_grid] def test_compiler_keeps_variable_components_as_stack_source(): step = FunctionStep(func=_identity, name="step") session = CompilationSession.from_context( context=_context(), - steps=[step], orchestrator=_orchestrator(), global_config=GlobalPipelineConfig(), - step_state_map={0: object()}, - snapshots=( - _snapshot( - step, - 0, - variable_components=(VariableComponents.CHANNEL,), + pipeline=ResolvedPipelineDefinition( + steps=( + _resolved_step(step, variable_components=(VariableComponents.CHANNEL,)), ), + step_state_map={0: SimpleNamespace(scope_id="plate::functionstep_0")}, ), ) @@ -382,18 +412,14 @@ def test_path_planner_source_binding_plan_comes_from_objectstate_snapshot(): ) ObjectStateRegistry.register(step_state, _skip_snapshot=True) resolved_step = step_state.to_saved_resolved_object() - snapshot = StepSnapshot( - index=0, - scope_id=step_state.scope_id, - step=resolved_step, - ) + snapshot = resolved_step session = CompilationSession.from_context( context=_context(), - steps=[resolved_step], orchestrator=_orchestrator(pipeline_state.to_object()), global_config=GlobalPipelineConfig(), - step_state_map={0: step_state}, - snapshots=(snapshot,), + pipeline=ResolvedPipelineDefinition( + steps=(snapshot,), step_state_map={0: step_state} + ), ) execution_bindings, (source_binding_plan, _source_universe_plan) = ( @@ -406,9 +432,9 @@ def test_path_planner_source_binding_plan_comes_from_objectstate_snapshot(): finally: ObjectStateRegistry.clear() - assert snapshot.step.source_bindings.bindings == (binding,) - assert snapshot.step.source_bindings.metadata_rules == (metadata_rule,) - assert snapshot.step.source_bindings.match_plan == match_plan + assert snapshot.source_bindings.bindings == (binding,) + assert snapshot.source_bindings.metadata_rules == (metadata_rule,) + assert snapshot.source_bindings.match_plan == match_plan assert execution_bindings.bindings == (binding,) assert source_binding_plan.bindings == (binding,) assert source_binding_plan.metadata_rules == (metadata_rule,) @@ -443,20 +469,16 @@ def test_compiler_streaming_config_snapshot_preserves_inherited_port(): ) ObjectStateRegistry.register(step_state, _skip_snapshot=True) resolved_step = step_state.to_saved_resolved_object() - snapshot = StepSnapshot( - index=0, - scope_id=step_state.scope_id, - step=resolved_step, - ) + snapshot = resolved_step context = _context() context.required_visualizers = [] session = CompilationSession.from_context( context=context, - steps=[resolved_step], orchestrator=_orchestrator(pipeline_state.to_object()), global_config=global_config, - step_state_map={0: step_state}, - snapshots=(snapshot,), + pipeline=ResolvedPipelineDefinition( + steps=(snapshot,), step_state_map={0: step_state} + ), ) PipelineCompiler._collect_streaming_configs(session) @@ -474,18 +496,17 @@ def test_compiler_streaming_config_snapshot_preserves_inherited_port(): def test_compiler_disabled_source_bindings_stay_inert_without_contract_requirement(): binding = NamedSourceBinding(alias="DNA") step = FunctionStep(func=_identity, name="source-bound") - snapshot = _snapshot( - step, - 0, - source_bindings=StepSourceBindingsConfig(bindings=(binding,)), + snapshot = _resolved_step( + step, source_bindings=StepSourceBindingsConfig(bindings=(binding,)) ) session = CompilationSession.from_context( context=_context(), - steps=[step], orchestrator=_orchestrator(), global_config=GlobalPipelineConfig(), - step_state_map={0: object()}, - snapshots=(snapshot,), + pipeline=ResolvedPipelineDefinition( + steps=(snapshot,), + step_state_map={0: SimpleNamespace(scope_id="plate::functionstep_0")}, + ), ) PipelineCompiler._supplement_step_plans(session) @@ -496,19 +517,19 @@ def test_compiler_disabled_source_bindings_stay_inert_without_contract_requireme def test_path_planner_activates_declared_source_binding_for_pipeline_start(): binding = NamedSourceBinding(alias="DNA") step = FunctionStep(func=_external_source_consumer, name="source-bound") - snapshot = _snapshot( + snapshot = _resolved_step( step, - 0, source_bindings=StepSourceBindingsConfig(bindings=(binding,)), input_source=InputSource.PIPELINE_START, ) session = CompilationSession.from_context( context=_context(), - steps=[step], orchestrator=_orchestrator(), global_config=GlobalPipelineConfig(), - step_state_map={0: object()}, - snapshots=(snapshot,), + pipeline=ResolvedPipelineDefinition( + steps=(snapshot,), + step_state_map={0: SimpleNamespace(scope_id="plate::functionstep_0")}, + ), ) _execution_bindings, (source_binding_plan, _source_universe_plan) = ( @@ -530,9 +551,8 @@ def test_plate_export_contract_construction_projects_inputs_to_runtime_batch(): binding = NamedSourceBinding(alias="DNA") step = FunctionStep(func=export_to_database, name="ExportToDatabase") - snapshot = _snapshot( + snapshot = _resolved_step( step, - 0, variable_components=(), source_bindings=StepSourceBindingsConfig( enabled=True, @@ -542,11 +562,12 @@ def test_plate_export_contract_construction_projects_inputs_to_runtime_batch(): ) session = CompilationSession.from_context( context=_context(), - steps=[step], orchestrator=_orchestrator(), global_config=GlobalPipelineConfig(), - step_state_map={0: object()}, - snapshots=(snapshot,), + pipeline=ResolvedPipelineDefinition( + steps=(snapshot,), + step_state_map={0: SimpleNamespace(scope_id="plate::functionstep_0")}, + ), ) dependency_before_provider = session.plan(0).main_input_dependency @@ -575,19 +596,19 @@ def test_plate_export_contract_construction_projects_inputs_to_runtime_batch(): def test_path_planner_preserves_pipeline_start_bindings_for_implicit_main_flow(): binding = NamedSourceBinding(alias="DNA") step = FunctionStep(func=_identity, name="source-bound measurement") - snapshot = _snapshot( + snapshot = _resolved_step( step, - 0, source_bindings=StepSourceBindingsConfig(bindings=(binding,)), input_source=InputSource.PIPELINE_START, ) session = CompilationSession.from_context( context=_context(), - steps=[step], orchestrator=_orchestrator(), global_config=GlobalPipelineConfig(), - step_state_map={0: object()}, - snapshots=(snapshot,), + pipeline=ResolvedPipelineDefinition( + steps=(snapshot,), + step_state_map={0: SimpleNamespace(scope_id="plate::functionstep_0")}, + ), ) execution_bindings, (source_binding_plan, source_universe_plan) = ( _compile_source_plans_for_contract(session, snapshot, _identity) @@ -605,18 +626,17 @@ def test_path_planner_step_output_projects_only_exact_source_artifacts() -> None func=_previous_step_and_external_source, name="previous-step plus exact source", ) - snapshot = _snapshot( - step, - 0, - source_bindings=StepSourceBindingsConfig(bindings=(dna, unrelated)), + snapshot = _resolved_step( + step, source_bindings=StepSourceBindingsConfig(bindings=(dna, unrelated)) ) session = CompilationSession.from_context( context=_context(), - steps=[step], orchestrator=_orchestrator(), global_config=GlobalPipelineConfig(), - step_state_map={0: object()}, - snapshots=(snapshot,), + pipeline=ResolvedPipelineDefinition( + steps=(snapshot,), + step_state_map={0: SimpleNamespace(scope_id="plate::functionstep_0")}, + ), ) execution_bindings, (source_binding_plan, _source_universe_plan) = ( @@ -646,9 +666,8 @@ def test_path_planner_preserves_metaxpress_primary_source_order() -> None: NamedSourceBinding(alias="Hoechst"), ) step = FunctionStep(func=neurite_outgrowth_metaxpress, name="neurite") - snapshot = _snapshot( + snapshot = _resolved_step( step, - 0, variable_components=(VariableComponents.CHANNEL,), source_bindings=StepSourceBindingsConfig( enabled=True, @@ -661,11 +680,12 @@ def test_path_planner_preserves_metaxpress_primary_source_order() -> None: ) session = CompilationSession.from_context( context=_context(), - steps=[step], orchestrator=_orchestrator(pipeline_config), global_config=GlobalPipelineConfig(), - step_state_map={0: object()}, - snapshots=(snapshot,), + pipeline=ResolvedPipelineDefinition( + steps=(snapshot,), + step_state_map={0: SimpleNamespace(scope_id="plate::functionstep_0")}, + ), ) contract = CallableContract.from_callable(neurite_outgrowth_metaxpress) @@ -703,9 +723,8 @@ def test_path_planner_execution_groups_use_resolved_source_bindings(): component_identity=(ComponentSelector(AllComponents.CHANNEL, "2"),), ), ) - snapshot = _snapshot( + snapshot = _resolved_step( step, - 0, source_bindings=StepSourceBindingsConfig( enabled=True, bindings=bindings, @@ -717,7 +736,7 @@ def test_path_planner_execution_groups_use_resolved_source_bindings(): scope = PathPlannerExecutionGroups(planner).source_binding_scope_for_group_by( snapshot, GroupBy.CHANNEL, - source_bindings=snapshot.step.source_bindings, + source_bindings=snapshot.source_bindings, ) assert scope.keys == ("1", "2") @@ -742,9 +761,8 @@ def test_path_planner_execution_groups_preserve_declared_component_identity() -> component_identity=(ComponentSelector(AllComponents.CHANNEL, "MCP_AGP"),), ), ) - snapshot = _snapshot( + snapshot = _resolved_step( step, - 0, source_bindings=StepSourceBindingsConfig( enabled=True, bindings=bindings, @@ -761,7 +779,7 @@ def test_path_planner_execution_groups_preserve_declared_component_identity() -> scope = PathPlannerExecutionGroups(planner).source_binding_scope_for_group_by( snapshot, GroupBy.CHANNEL, - source_bindings=snapshot.step.source_bindings, + source_bindings=snapshot.source_bindings, ) assert scope.keys == ("MCP_DNA", "MCP_AGP") @@ -772,9 +790,8 @@ def test_path_planner_freezes_only_contract_selected_source_bindings(): binding = NamedSourceBinding(alias="DNA") unused_binding = NamedSourceBinding(alias="Unused") step = FunctionStep(func=_external_source_consumer, name="source-bound") - snapshot = _snapshot( + snapshot = _resolved_step( step, - 0, source_bindings=StepSourceBindingsConfig( bindings=(binding, unused_binding), enabled=True, @@ -782,11 +799,12 @@ def test_path_planner_freezes_only_contract_selected_source_bindings(): ) session = CompilationSession.from_context( context=_context(), - steps=[step], orchestrator=_orchestrator(), global_config=GlobalPipelineConfig(), - step_state_map={0: object()}, - snapshots=(snapshot,), + pipeline=ResolvedPipelineDefinition( + steps=(snapshot,), + step_state_map={0: SimpleNamespace(scope_id="plate::functionstep_0")}, + ), ) execution_bindings, (source_binding_plan, _source_universe_plan) = ( _compile_source_plans_for_contract( @@ -848,5 +866,5 @@ def test_compiler_pipeline_scope_prevents_cross_pipeline_source_binding_inherita ) assert first_scope != second_scope - assert first_resolved.snapshots[0].step.source_bindings.bindings == (binding,) - assert second_resolved.snapshots[0].step.source_bindings.is_empty + assert first_resolved.steps[0].source_bindings.bindings == (binding,) + assert second_resolved.steps[0].source_bindings.is_empty diff --git a/tests/unit/test_compiled_execution.py b/tests/unit/test_compiled_execution.py index a15c47ff32..c95e7277d1 100644 --- a/tests/unit/test_compiled_execution.py +++ b/tests/unit/test_compiled_execution.py @@ -369,8 +369,10 @@ def execute_current_run( context, _lane_context, *, + context_key, cancellation=None, ): + assert context_key == "A01" current_records.append( context.runtime_value_store.replace( measurement_value(2), diff --git a/tests/unit/test_costes_parent_mean_qualification.py b/tests/unit/test_costes_parent_mean_qualification.py index b2d5ef007b..b4df7ffb73 100644 --- a/tests/unit/test_costes_parent_mean_qualification.py +++ b/tests/unit/test_costes_parent_mean_qualification.py @@ -3,6 +3,7 @@ import math from openhcs.core.measurement_feature_queries import ( + ColumnarMeasurementTableSchema, MeasurementFeatureQuery, MeasurementFeatureValueIndex, ) @@ -18,7 +19,6 @@ from openhcs.interop.cellprofiler.measurement_dialect import ( CELLPROFILER_MEASUREMENT_LOOKUP_DIALECT, ) -from openhcs.processing.backends.cellprofiler.relationships import RelateObjectsModule def test_relateobjects_child_mean_qualification_retains_explicit_nan_only() -> None: @@ -66,14 +66,16 @@ def test_relateobjects_child_mean_qualification_retains_explicit_nan_only() -> N query, {"Mitochondria": "Mitochondria"}, ) - qualified_indexes = MeasurementFeatureValueIndex.from_columnar_table_by_object( - table, - query, - {"Mitochondria": "Mitochondria"}, - measurement_value_qualifier=( - RelateObjectsModule.aggregate_child_measurement_value_is_qualified - ), - ) + qualified_indexes = next( + ColumnarMeasurementTableSchema.from_table( + table + ).non_absent_feature_value_indexes( + table, + {query.feature_name: query}, + {query.feature_name: {"Mitochondria": "Mitochondria"}}, + index_type=MeasurementFeatureValueIndex, + ) + )[1][None] assert default_indexes is not None assert qualified_indexes is not None diff --git a/tests/unit/test_debug_runtime.py b/tests/unit/test_debug_runtime.py index be71a846b7..3274195fb1 100644 --- a/tests/unit/test_debug_runtime.py +++ b/tests/unit/test_debug_runtime.py @@ -130,12 +130,12 @@ from openhcs.core.pipeline.function_contracts import artifact_inputs, artifact_outputs from openhcs.core.source_bindings import ( CompiledSourceBindingPlan, - SourceBindingRuntimeContext, ) from openhcs.core.source_load_plan import SourceLoadPlan from openhcs.core.steps.function_runtime import ( ComponentArtifactPlans, - FunctionRuntimeScope, + PatternGroupData, + PatternGroupRuntime, ) from openhcs.core.runtime_stores import RuntimeValueStore from openhcs.processing.backends.lib_registry.unified_registry import ProcessingContract @@ -338,11 +338,12 @@ def execute_function_chain( artifact_outputs=None, runtime_plane_index: int = 0, runtime_plane_count: int = 1, - source_binding_context: SourceBindingRuntimeContext | None = None, ): resolved_artifact_inputs = {} if artifact_inputs is None else artifact_inputs resolved_artifact_outputs = {} if artifact_outputs is None else artifact_outputs - runtime_scope = FunctionRuntimeScope( + runtime_scope = PatternGroupData( + matching_files=[f"input-{index}.tif" for index in range(runtime_plane_count)], + main_data_stack=initial_data_stack, context=context, execution_plan=cls.execution_plan( artifact_inputs=resolved_artifact_inputs, @@ -356,15 +357,10 @@ def execute_function_chain( inputs=resolved_artifact_inputs, outputs=resolved_artifact_outputs, ), - source_binding_context=( - SourceBindingRuntimeContext.empty() - if source_binding_context is None - else source_binding_context - ), runtime_plane_index=runtime_plane_index, runtime_plane_count=runtime_plane_count, ) - return runtime_scope.execute_chain(initial_data_stack) + return PatternGroupRuntime.execute_chain(runtime_scope) @classmethod def cursor(cls) -> DebugCursor: diff --git a/tests/unit/test_dense_object_coordinate_reduction.py b/tests/unit/test_dense_object_coordinate_reduction.py new file mode 100644 index 0000000000..a136d5828c --- /dev/null +++ b/tests/unit/test_dense_object_coordinate_reduction.py @@ -0,0 +1,298 @@ +"""Storage reduction preserves its generic oracle and compiled backend domains.""" + +import os +import subprocess +import sys +import textwrap +import warnings +from pathlib import Path + +import numpy as np +import pytest + +from openhcs.core.runtime_object_labels import ( + ObjectLabelPayload, + ObjectLabelStorageStrategy, + ObjectLabelVariantData, + object_label_axis_centers, +) +from openhcs.core.runtime_sparse_labels import SparseIJVLabelRows + + +def generic_centers(labels, domain): + return ObjectLabelStorageStrategy.axis_centers( + ObjectLabelStorageStrategy.for_value(labels), labels, domain=domain + ) + + +def assert_centers(actual, expected): + for actual_array, expected_array in zip( + (*actual[0], actual[1]), (*expected[0], expected[1]), strict=True + ): + np.testing.assert_array_equal(actual_array, expected_array) + assert actual_array.tobytes() == expected_array.tobytes() + assert actual_array.dtype == expected_array.dtype + assert actual_array.strides == expected_array.strides + assert actual_array.flags.owndata == expected_array.flags.owndata + assert actual_array.base is None + assert not np.shares_memory(*actual[0][:2]) + + +@pytest.mark.parametrize("wrapped", (False, True)) +@pytest.mark.parametrize("shape", ((4, 5), (3, 4, 5))) +def test_dense_storage_reduces_without_sparse_materialization(monkeypatch, wrapped, shape): + labels = np.zeros(shape, dtype=np.int32) + labels[..., 1:3, 2:4] = 1 + labels[..., 3, 0] = 4 + domain = (1, 2, 4, 7) + expected = generic_centers(labels, domain) + value = ( + ObjectLabelPayload(variant_data=ObjectLabelVariantData(labels=labels)) + if wrapped else labels + ) + before = labels.copy() + + def reject_materialization(_cls, _labels): + raise AssertionError("Coordinate reduction materialized sparse pixels") + + monkeypatch.setattr(SparseIJVLabelRows, "from_dense_stack", classmethod(reject_materialization)) + assert_centers(object_label_axis_centers(value, domain=domain), expected) + np.testing.assert_array_equal(labels, before) + + +@pytest.mark.parametrize("layout", ("c", "f", "view", "readonly", "empty")) +def test_layout_and_mutable_pixels_preserve_generic_result(layout): + labels = np.arange(30, dtype=np.int32).reshape(5, 6) % 5 + if layout == "f": + labels = np.asfortranarray(labels) + elif layout == "view": + labels = labels[::-1, ::2] + elif layout == "readonly": + labels.flags.writeable = False + elif layout == "empty": + labels = np.zeros((2, 0, 3), dtype=np.int32) + domain = (1, 2, 4, 9) + assert_centers(object_label_axis_centers(labels, domain=domain), generic_centers(labels, domain)) + if labels.size and labels.flags.writeable: + labels.flat[0] = 4 + assert_centers(object_label_axis_centers(labels, domain=domain), generic_centers(labels, domain)) + + +@pytest.mark.parametrize("dtype", (np.bool_, np.float64, np.int64, np.uint64)) +def test_other_dtype_conversion_and_warning_policy_stays_generic(dtype): + labels = np.array([[0, 1], [2, 3]], dtype=dtype) + if dtype is np.float64: + labels[0] = (0.5, np.nan) + elif dtype is np.uint64: + labels[0, 1] = 2**32 + 1 + outcomes = [] + for call in (generic_centers, lambda x, domain: object_label_axis_centers(x, domain=domain)): + with warnings.catch_warnings(record=True) as observed: + warnings.simplefilter("always") + try: + result = call(labels, (1, 2, 3, 8)) + except ValueError as error: + result = (type(error), str(error)) + outcomes.append((result, [(type(w.message), str(w.message)) for w in observed])) + if dtype is np.uint64: + assert outcomes[0][0] == outcomes[1][0] + else: + assert_centers(outcomes[0][0], outcomes[1][0]) + assert outcomes[0][1] == outcomes[1][1] + + +def test_sparse_overlap_and_subtype_keep_existing_representation(): + sparse = SparseIJVLabelRows(np.array([[0, 0, 1], [0, 0, 2], [2, 3, 1]], dtype=np.int32)) + assert_centers(object_label_axis_centers(sparse, domain=(1, 2, 4)), generic_centers(sparse, (1, 2, 4))) + + class DenseSubtype(np.ndarray): + @property + def dtype(self): + raise AssertionError("Subtype properties must not be probed before generic coercion") + + subtype = np.array([[1, 0], [2, 2]], dtype=np.int32).view(DenseSubtype) + assert_centers(object_label_axis_centers(subtype, domain=(1, 2, 4)), generic_centers(subtype, (1, 2, 4))) + + +@pytest.mark.parametrize("shape", ((), (4,), (2, 3, 4, 5))) +def test_invalid_shape_keeps_original_error(shape): + labels = np.zeros(shape, dtype=np.int32) + with pytest.raises(ValueError) as original: + generic_centers(labels, (1,)) + with pytest.raises(type(original.value), match="SparseIJVLabelRows.from_dense_stack") as current: + object_label_axis_centers(labels, domain=(1,)) + assert str(current.value) == str(original.value) + + +@pytest.mark.parametrize("failure", (None, "iterate", 1, 2, 3, 4, 5)) +def test_domain_callbacks_follow_pixel_snapshot_and_original_allocation_order(failure): + outcomes = [] + for call in (generic_centers, lambda labels, domain: object_label_axis_centers(labels, domain=domain)): + labels = np.array([[1, 1], [2, 0]], dtype=np.int32) + effects = [] + + class DomainInteger(int): + def __gt__(self, other): + effects.append("compare") + return super().__gt__(other) + + def __add__(self, other): + effects.append("add") + result = super().__add__(other) + return float(result) if effects.count("add") == failure else result + + class MutatingDomain: + def __iter__(self): + effects.append("iterate") + labels[:] = 3 + labels.shape = (1, 2, 2) + if failure == "iterate": + raise RuntimeError("Domain iteration failed after changing pixels") + yield DomainInteger(4) + + try: + result = call(labels, MutatingDomain()) + except (RuntimeError, TypeError) as error: + outcome = (type(error), str(error)) + else: + outcome = result + outcomes.append((outcome, effects, labels.copy())) + + if failure is None: + assert_centers(outcomes[0][0], outcomes[1][0]) + np.testing.assert_array_equal(outcomes[1][0][1], (0, 2, 1, 0, 0)) + assert len(outcomes[1][0][0]) == 2 + else: + assert outcomes[0][0] == outcomes[1][0] + assert outcomes[0][1] == outcomes[1][1] + np.testing.assert_array_equal(outcomes[0][2], outcomes[1][2]) + + +@pytest.mark.parametrize("domain", ((4.0,), (np.int64(np.iinfo(np.int64).max),), (2**63,))) +def test_domain_minlength_errors_and_warnings_remain_numpy_owned(domain): + outcomes = [] + for call in (generic_centers, lambda labels, domain: object_label_axis_centers(labels, domain=domain)): + with warnings.catch_warnings(record=True) as observed: + warnings.simplefilter("always") + try: + call(np.array([[1, 0], [2, 1]], dtype=np.int32), domain) + except (TypeError, ValueError, OverflowError) as error: + outcome = (type(error), str(error)) + else: + raise AssertionError("Invalid minlength unexpectedly succeeded") + outcomes.append((outcome, [(type(w.message), str(w.message)) for w in observed])) + assert outcomes[0] == outcomes[1] + + +def test_invalid_geometry_precedes_domain_iteration(): + for call in (generic_centers, lambda labels, domain: object_label_axis_centers(labels, domain=domain)): + effects = [] + + class Domain: + def __iter__(self): + effects.append("iterate") + yield 1 + + with pytest.raises(ValueError, match="SparseIJVLabelRows.from_dense_stack"): + call(np.zeros((2, 3, 4, 5), dtype=np.int32), Domain()) + assert not effects + + +@pytest.mark.parametrize("shape,label_id", (((1, 1), 2**31 - 1), ((64, 64), 4096))) +def test_sparse_high_ids_reach_domain_error_before_moment_allocation(monkeypatch, shape, label_id): + from openhcs.core import runtime_object_labels + + def reject_moment_allocation(*_args): + raise AssertionError("Sparse ID span must not allocate a dense moment table") + + monkeypatch.setattr(runtime_object_labels, "_dense_label_coordinate_moments_numba", reject_moment_allocation) + for call in (generic_centers, lambda labels, domain: object_label_axis_centers(labels, domain=domain)): + labels = np.zeros(shape, dtype=np.int32) + labels.flat[0] = label_id + effects = [] + + class Domain: + def __iter__(self): + effects.append("iterate") + labels.flat[0] = 1 + raise RuntimeError("Domain rejected sparse high IDs") + + with pytest.raises(RuntimeError, match="Domain rejected sparse high IDs"): + call(labels, Domain()) + assert effects == ["iterate"] + assert labels.flat[0] == 1 + + +@pytest.mark.parametrize("dimensions", (2, 3)) +@pytest.mark.parametrize("layout", ("fortran", "reversed", "broadcast")) +def test_coordinate_scan_borrows_strided_input_without_flatten_copy(monkeypatch, dimensions, layout): + from openhcs.core import runtime_object_labels + + labels = np.array([[0, 1, 1], [2, 0, 2]], dtype=np.int32) + if dimensions == 3: + labels = np.stack((labels, labels)) + if layout == "fortran": + labels = np.asfortranarray(labels) + elif layout == "reversed": + labels = labels[..., ::-1] + else: + labels = np.broadcast_to(labels[..., :1, :], (*labels.shape[:-2], 4, 3)) + expected = generic_centers(labels, (1, 2, 4)) + before = labels.copy() + original = runtime_object_labels._dense_label_coordinate_moments_numba + requests = [] + + def borrowed_scan(coordinate_planes, maximum_label): + assert coordinate_planes.ndim == 3 + assert np.shares_memory(coordinate_planes, labels) + assert coordinate_planes.flags.writeable == labels.flags.writeable + assert coordinate_planes.shape == ((1, *labels.shape) if dimensions == 2 else labels.shape) + requests.append(coordinate_planes) + return original(coordinate_planes, maximum_label) + + monkeypatch.setattr(runtime_object_labels, "_dense_label_coordinate_moments_numba", borrowed_scan) + assert_centers(object_label_axis_centers(labels, domain=(1, 2, 4)), expected) + assert len(requests) == 1 + np.testing.assert_array_equal(labels, before) + + +def test_primary_objects_preparation_readies_all_admitted_storage_signatures(tmp_path): + script = textwrap.dedent(""" + from unittest.mock import patch + import numpy as np + from openhcs.core.callable_contract import prepare_processing_callable + from openhcs.core.runtime_object_labels import ( + _dense_label_coordinate_moments_numba, dense_label_centers_2d_numba, + object_label_axis_centers, + ) + from openhcs.processing.backends.cellprofiler.primary_objects import identify_primary_objects + assert not _dense_label_coordinate_moments_numba.signatures + prepare_processing_callable(identify_primary_objects) + kernels = (_dense_label_coordinate_moments_numba, dense_label_centers_2d_numba) + signatures = tuple(tuple(kernel.signatures) for kernel in kernels) + assert all(signatures) + + def reject_compilation(*arguments): + raise AssertionError(('Late coordinate preparation', tuple(map(str, arguments)))) + + from contextlib import ExitStack + with ExitStack() as guards: + for kernel in kernels: + guards.enter_context(patch.object(kernel, 'compile', side_effect=reject_compilation)) + guards.enter_context(patch.object(kernel._cache, 'load_overload', side_effect=reject_compilation)) + for shape in ((4, 5), (3, 4, 5)): + base = np.arange(np.prod(shape), dtype=np.int32).reshape(shape) % 4 + for labels in (base, np.asfortranarray(base), base[..., ::-1], + np.broadcast_to(base[..., :1, :], shape), base.copy()): + object_label_axis_centers(labels, domain=(1, 2, 3, 6)) + labels.flags.writeable = False + object_label_axis_centers(labels, domain=(1, 2, 3, 6)) + assert tuple(tuple(kernel.signatures) for kernel in kernels) == signatures + """) + environment = os.environ.copy() + environment.update(OPENHCS_CPU_ONLY="true", NUMBA_CACHE_DIR=str(tmp_path / "kernels")) + result = subprocess.run( + (sys.executable, "-c", script), cwd=Path(__file__).parents[2], + env=environment, capture_output=True, text=True, timeout=120, + ) + assert result.returncode == 0, result.stdout + result.stderr diff --git a/tests/unit/test_derived_role_publication_435.py b/tests/unit/test_derived_role_publication_435.py new file mode 100644 index 0000000000..8b5e35763f --- /dev/null +++ b/tests/unit/test_derived_role_publication_435.py @@ -0,0 +1,394 @@ +"""Issue435: real saved image occurrences projected through two existing owners.""" + +from dataclasses import asdict, replace +import json + +import pytest +import numpy as np +import tifffile +from polystore.disk import DiskStorageBackend +from polystore.filemanager import FileManager +from polystore.memory import MemoryStorageBackend + +from test_function_outputs import ( + context_stub, function_step_plan, record_output_path, +) +from openhcs.microscopes.source_schema import SourceSchemaFilenameParser +from openhcs.constants.constants import ( + AllComponents, Backend, GroupBy, Microscope, VariableComponents, +) +from openhcs.core.aligned_image_payload import AlignedImageSliceContext, stack_image_payloads +from openhcs.core.artifacts import ArtifactOutputPlan, ImageArtifactType, ObjectLabelsArtifactType +from openhcs.core.component_group_scope import ComponentGroupScope, RuntimeExecutionAxisScope +from openhcs.core.compiled_step_plan import RuntimeArtifactMaterializationPlan +from openhcs.core.runtime_artifact_values import RuntimeValue +from openhcs.core.runtime_image_values import ( + ImageMetadataPayload, ImagePayloadMetadata, ImagePayloadMetadataCompositionMode, +) +from openhcs.core.runtime_stores import RuntimeValueStore +from openhcs.core.runtime_object_label_building import SourceImageObjectLabelBuildRequest +from openhcs.core.source_metadata import SourceVoxelSpacing +from openhcs.core.source_image_provenance import ( + SourceImageProvenance, SourceImageProvenancePlanes, +) +from openhcs.core.source_projection import SourceProjectionMetadataSerializer +from openhcs.core.source_workspace_projection import VirtualWorkspaceSourceProjection +from openhcs.core.steps.function_outputs import ( + PrimaryImageMetadataTarget, RuntimeArtifactMaterializationAuthority, +) +from openhcs.core.steps.function_output_identity import FunctionOutputIdentity + +from openhcs.core.runtime_plane_projection import RuntimePlaneAxis, RuntimePlaneAxisValueProjection +from openhcs.serialization.json import to_jsonable +from openhcs.processing.materialization import ( + ImageFileOptions, MaterializationSpec, MaterializedFilenameIdentity, +) + + +@pytest.mark.parametrize("scenario,aggregate", ( + *((scenario, False) for scenario in ( + "same_occurrence", "different_path", "stale_scope", "conflicting_metadata", "different_kind", + )), + *((scenario, True) for scenario in ( + "same_occurrence", "different_path", "stale_scope", "conflicting_metadata", "different_kind", + )), + ("conflicting_scope", True), + ("mosaic_context", False), +)) +def test_saved_roles_publish_once_per_persisted_occurrence(tmp_path, scenario, aggregate): + mosaic = scenario == "mosaic_context" + same_persisted_path = scenario != "different_path" + filemanager = FileManager({ + Backend.DISK.value: DiskStorageBackend(), + Backend.MEMORY.value: MemoryStorageBackend(), + }) + context = context_stub(filemanager, parser=SourceSchemaFilenameParser()) + context.microscope_handler.microscope_type = Microscope.OPENHCS.value + context.runtime_value_store = RuntimeValueStore() + context.metadata_cache = {} + context.tiff_config = None + plan = function_step_plan("Derived role images") + plan.streaming_configs = {} + plan.write_backend = Backend.DISK.value + plan.output_plate_root = str(tmp_path) + plan.output_dir = tmp_path / "images" + plan.sub_dir = "images" + plan.analysis_results_dir = str(plan.output_dir) + plan.runtime_artifact_materialization = RuntimeArtifactMaterializationPlan( + persistent_enabled=True, persistent_backend=Backend.DISK.value, + ) + context.step_plans = {plan.step_index: plan} + filemanager.ensure_directory(plan.output_dir, Backend.MEMORY.value) + components = { + "well": "A01", "site": "1", "channel": "2", + "z_index": "1", "timepoint": "1", "extension": ".tif", + } + roles = ( + (("MosaicRole", 1.0),) if mosaic + else (("RawRole", 1.0), ("CappedRole", 0.5)) + ) + if aggregate: + components.update(channel="1", z_index="0") + plan.variable_components = (VariableComponents.Z_INDEX,) + plan.group_by = GroupBy.CHANNEL + plan.execution_group_scope = ComponentGroupScope.from_raw( + ("1",), component=AllComponents.CHANNEL, + ) + source_planes = [] + source_dir = tmp_path / "physical_source" + filemanager.ensure_directory(source_dir, Backend.DISK.value) + pixels = np.arange(140, dtype=np.uint16).reshape((4, 5, 7)) + for z_index, plane in enumerate(pixels): + path = source_dir / f"A01_s001_w1_z{z_index:03d}_t001.tif" + filemanager.save(plane, str(path), Backend.DISK.value) + source_planes.append(ImagePayloadMetadata( + source_path=str(path), + source_component_metadata={**components, "z_index": str(z_index)}, + source_voxel_spacing=SourceVoxelSpacing((2.0, 0.65, 0.65)), + ).payload_with(filemanager.load(str(path), Backend.DISK.value))) + source_stack = stack_image_payloads( + source_planes, metadata_mode=ImagePayloadMetadataCompositionMode.STACK, + ) + roles = (("fixture_image_494", 1.0),) + for role, scale in roles: + tested_role = aggregate or role == "CappedRole" + filename = ( + f"A01_s001_w{components['channel']}" + f"_z{int(components['z_index']):03d}_t001_{role}.tif" + ) + output_plan = ArtifactOutputPlan( + name=role, path=f"/memory/{filename.removesuffix('.tif')}.pkl", + artifact_type=( + ObjectLabelsArtifactType + if scenario == "different_kind" and tested_role else ImageArtifactType + ), + producer_step_index=plan.step_index, + producer_step_scope_id=( + "different-step-scope" + if scenario == "stale_scope" and tested_role else plan.step_scope_id + ), + producer_step_name=plan.step_name, + materialization=MaterializationSpec(ImageFileOptions( + filename_suffix=".tif", + filename_identity=( + MaterializedFilenameIdentity.ARTIFACT_NAME if aggregate + else MaterializedFilenameIdentity.SOURCE_IDENTITY + ), + relative_path_template=(filename if same_persisted_path else filename.replace(".tif", "_independent.tif")), + )), + ) + if aggregate: + output_plan = replace( + output_plan, group_keys=("1",), group_component=AllComponents.CHANNEL, + variable_components=(AllComponents.Z_INDEX,), + ) + plan.artifact_outputs[output_plan.ref()] = output_plan + payload = ImageMetadataPayload( + np.ones((4, 5), dtype=np.float32) * scale, + ImagePayloadMetadata( + source_component_metadata=components, + source_image_names=(role,), + source_voxel_spacing=SourceVoxelSpacing((0.65, 0.65)), + ), + ) + if mosaic: + source_dir = tmp_path / "physical_source" + filemanager.ensure_directory(source_dir, Backend.DISK.value) + mosaic_pixels = np.arange(40, dtype=np.uint16).reshape(2, 4, 5) + contributor_paths = tuple( + source_dir / f"A01_s{site:03d}_w2_z001_t001.tif" for site in (1, 2) + ) + for path, plane in zip(contributor_paths, mosaic_pixels, strict=True): + filemanager.save(plane, str(path), Backend.DISK.value) + payload = ImagePayloadMetadata( + source_image_names=(role,), + source_voxel_spacing=SourceVoxelSpacing((0.5, 0.5)), + source_provenance=SourceImageProvenance( + source_component_metadata={ + key: value for key, value in components.items() if key != "site" + }, + source_image_provenance_planes=SourceImageProvenancePlanes.from_contributor_components( + paths=tuple(str(path) for path in contributor_paths), + component_metadata=({"site": "1"}, {"site": "2"}), + ), + ), + ).payload_with(np.stack([ + filemanager.load(str(path), Backend.DISK.value) + for path in contributor_paths + ])) + if aggregate: + payload = ImageArtifactType.contextualize_output( + source_stack, pixels.copy(), output_plan, + RuntimePlaneAxisValueProjection(RuntimePlaneAxis.RUNTIME_SLICE, (), None, 4), + ) + if aggregate: + execution_scope = RuntimeExecutionAxisScope.from_raw( + "A01", component=AllComponents.CHANNEL, value="1", + fixed_component_values=( + (AllComponents.SITE, "1"), (AllComponents.TIMEPOINT, "1"), + ), + ) + payload = RuntimeValue.normalize_for_execution_scope( + replace(output_plan, artifact_type=ImageArtifactType), payload, + execution_scope=execution_scope, + ).data + artifact_payload = payload + if tested_role and scenario == "conflicting_metadata": + conflicting_fields = ( + {"source_voxel_spacing": SourceVoxelSpacing((3.0, 0.65, 0.65))} + if aggregate else {"source_image_names": ("IndependentRole",)} + ) + artifact_payload = payload.metadata.replace_fields( + **conflicting_fields + ).payload_with(payload.data) + if tested_role and scenario == "different_kind": + artifact_payload = SourceImageObjectLabelBuildRequest( + image=payload, labels=np.ones(payload.data.shape, dtype=np.int32), + declared_object_count=1, declared_object_ids=(1,), + ).payload() + output_identity = ( + FunctionOutputIdentity.from_metadata( + context.microscope_handler.parser, payload.metadata, + variable_components=plan.variable_components, + ) if aggregate else None + ) + value = ( + RuntimeValue.normalize_for_execution_scope( + output_plan, artifact_payload, + execution_scope=( + RuntimeExecutionAxisScope.from_raw( + "A01", component=AllComponents.CHANNEL, value="1", + fixed_component_values=( + (AllComponents.SITE, "2"), (AllComponents.TIMEPOINT, "1"), + ), + ) if scenario == "conflicting_scope" else execution_scope + ), + ) if aggregate else ( + RuntimeValue.normalize_for_execution_scope( + output_plan, artifact_payload, + execution_scope=RuntimeExecutionAxisScope.from_raw( + "A01", component=None, value=None, fixed_component_values=( + (AllComponents.CHANNEL, "2"), (AllComponents.Z_INDEX, "1"), + (AllComponents.TIMEPOINT, "1"), + ), + ), + ) if mosaic else RuntimeValue.normalize(output_plan, artifact_payload, axis_id="A01") + ) + ) + if mosaic: + payload = value.data + output_identity = FunctionOutputIdentity( + component_values={ + key: value for key, value in components.items() + if key not in ("site", "extension") + }, + filename_component_values={ + key: value for key, value in components.items() if key != "extension" + }, + extension=".tif", source="collapsed Mosaic contributors", + ) + context.runtime_value_store.record( + value, + path=output_plan.path, backend=Backend.MEMORY.value, + ) + destination = plan.output_dir / filename + filemanager.save(payload, str(destination), Backend.MEMORY.value) + filemanager.ensure_directory(plan.output_dir, Backend.DISK.value) + filemanager.save(payload.data, str(destination), Backend.DISK.value) + record_output_path( + context, plan, str(destination), image_metadata=payload.metadata, + output_context=AlignedImageSliceContext.main_flow( + output_key=role, artifact_kind=ImageArtifactType.value, + ), + identity=output_identity, + ) + saved = RuntimeArtifactMaterializationAuthority.materialize(context, plan) + assert len(saved) == len(roles) + target = replace(PrimaryImageMetadataTarget.from_plan(plan), artifact_materializations=saved) + records = target.produced_records(context, plan) + artifacts = target.runtime_artifact_projection_paths(context, plan) + receipt = { + "source_scope": plan.step_scope_id, + "produced": [{"path": str(record.path_under(plan.output_dir)), + "identity": asdict(record.producer_identity), + "address": record.filename_address.as_component_metadata()} for record in records], + "materialized": [{"path": output.path, + "role": item.materialization.output_plan.name, + "semantic_source": None if item.materialization.source_identity is None else { + "path": item.materialization.source_identity.path, + "component_metadata": dict(item.materialization.source_identity.component_metadata or {}), + }, + "producer_scope": item.materialization.output_plan.producer_step_scope_id, + "stored_key": repr(item.materialization.record.key)} + for item in saved for output in item.outputs_for_backend(Backend.DISK.value)], + "artifact_projections": [{"path": path, + "role": projection.projection_role.value, + "address": None if projection.address is None else projection.address.as_component_metadata(), + "alias": projection.source_alias, + "kind": projection.artifact_kind.value} + for projection, path in artifacts], + "pre_join_main_flow": SourceProjectionMetadataSerializer.projection_records( + replace(target, artifact_materializations=()).produced_projection_entries(context, plan).projection_paths, + ), + "pre_join_artifacts": SourceProjectionMetadataSerializer.projection_records(artifacts), + "produced_records": [to_jsonable(record) for record in records], + } + (tmp_path / "persisted-occurrence-witness.json").write_text(json.dumps(receipt, indent=2)) + produced_paths = {item["path"] for item in receipt["produced"]} + materialized_paths = {item["path"] for item in receipt["materialized"]} + if same_persisted_path: + assert produced_paths == materialized_paths + else: + assert produced_paths.isdisjoint(materialized_paths) + if mosaic: + expected_sums = {780.0} + elif aggregate: + expected_sums = {140.0} if scenario == "different_kind" else {float(pixels.sum())} + else: + expected_sums = {20.0} if scenario == "different_kind" else {20.0, 10.0} + assert {float(tifffile.imread(item["path"]).sum()) for item in receipt["materialized"]} == expected_sums + if scenario not in ("same_occurrence", "mosaic_context") and not (aggregate and scenario == "different_path"): + message = ( + "Conflicting metadata for persisted image" + if scenario in ("conflicting_metadata", "conflicting_scope", "mosaic_context") + else "Duplicate source projection address" + ) + with pytest.raises(ValueError, match=message) as rejection: + target.produced_projection_entries(context, plan) + receipt["rejection"] = str(rejection.value) + (tmp_path / "persisted-occurrence-witness.json").write_text(json.dumps(receipt, indent=2)) + return + if aggregate: + (main_flow,) = receipt["pre_join_main_flow"] + (artifact,) = receipt["pre_join_artifacts"] + assert main_flow["address"] is artifact["address"] is None + assert main_flow["execution_scope"] == artifact["execution_scope"] == { + "axis_id": "A01", "component": "channel", "value": "1", + "fixed_component_values": [["site", "1"], ["timepoint", "1"]], + } + assert main_flow["image_metadata"] == artifact["image_metadata"] + assert main_flow["source_metadata"] == artifact["source_metadata"] + assert receipt["produced"][0]["address"]["z_index"] == "0" + assert "z_index" not in receipt["produced_records"][0]["component_values"] + metadata = main_flow["image_metadata"] + assert metadata["source_dtype"] == "uint16" + assert metadata["source_voxel_spacing"] == { + "values_zyx": [2.0, 0.65, 0.65], "unit": "micrometers", + } + provenance = metadata["source_provenance"] + assert "z_index" not in provenance["source_component_metadata"] + assert [plane["component_metadata"]["z_index"] for plane in + provenance["source_image_provenance_planes"]] == ["0", "1", "2", "3"] + assert [plane["path"] for plane in provenance["source_image_provenance_planes"]] == [ + str(source_dir / f"A01_s001_w1_z{z_index:03d}_t001.tif") for z_index in range(4) + ] + assert metadata["source_spatial_domain"]["spatial_dimensions"] == 2 + for path in produced_paths | materialized_paths: + image = tifffile.imread(path) + assert image.dtype == np.uint16 + np.testing.assert_array_equal(image, pixels) + structured = target.produced_projection_entries(context, plan) + if mosaic: + (main_flow,) = receipt["pre_join_main_flow"] + (artifact,) = receipt["pre_join_artifacts"] + assert main_flow["address"] is artifact["address"] is None + assert main_flow["execution_scope"] == artifact["execution_scope"] + assert main_flow["image_metadata"] == artifact["image_metadata"] + assert main_flow["source_metadata"] == artifact["source_metadata"] + assert receipt["produced"][0]["address"]["site"] == "1" + assert "site" not in receipt["materialized"][0]["semantic_source"]["component_metadata"] + structured = SourceProjectionMetadataSerializer.projection_fields( + structured.projection_paths + ) + occurrence_count = 2 if aggregate and scenario == "different_path" else 1 + assert len(structured["source_projection"]) == len(roles) * occurrence_count + assert {item["source_alias"] for item in structured["source_projection"]} == {role for role, _ in roles} + target.write(context, produced_plan=plan) + document = json.loads((tmp_path / "openhcs_metadata.json").read_text()) + reopened = VirtualWorkspaceSourceProjection.from_openhcs_metadata(tmp_path, document) + projections = reopened.source_projections_by_virtual_path + relative_paths = {path.removeprefix(str(tmp_path) + "/") for path in produced_paths | materialized_paths} + assert set(projections) == relative_paths | produced_paths | materialized_paths + assert {projection.source_alias for projection in projections.values()} == {role for role, _ in roles} + for relative_path in relative_paths: + projection = projections[relative_path] + if mosaic: + assert projection.address is None + metadata = projection.image_metadata + assert "site" not in metadata.source_component_metadata + assert metadata.source_provenance.source_plane_count == 0 + assert metadata.source_image_provenance_planes.contributor_count == 2 + assert metadata.source_voxel_spacing.values_zyx == (0.5, 0.5) + assert projection.execution_scope.fixed_component_values == ( + (AllComponents.CHANNEL, "2"), (AllComponents.Z_INDEX, "1"), + (AllComponents.TIMEPOINT, "1"), + ) + np.testing.assert_array_equal(tifffile.imread(tmp_path / relative_path), mosaic_pixels) + continue + if aggregate: + assert projection.address is None + np.testing.assert_array_equal(tifffile.imread(tmp_path / relative_path), pixels) + continue + assert projection.address.as_component_metadata() == {key: components[key] for key in ("well", "site", "channel", "z_index", "timepoint")} + expected_scale = 1.0 if projection.source_alias == "RawRole" else 0.5 + np.testing.assert_array_equal(tifffile.imread(tmp_path / relative_path), np.ones((4, 5), dtype=np.float32) * expected_scale) diff --git a/tests/unit/test_framework_execution_scope.py b/tests/unit/test_framework_execution_scope.py index c5e341073b..56227eef55 100644 --- a/tests/unit/test_framework_execution_scope.py +++ b/tests/unit/test_framework_execution_scope.py @@ -30,7 +30,7 @@ def memory_device_scope(declaration): events.append(("exit", declaration)) executor = FunctionCoreExecutor( - runtime_scope=SimpleNamespace( + group_data=SimpleNamespace( execution_plan=SimpleNamespace( memory_device_scope=memory_device_scope, ) diff --git a/tests/unit/test_function_artifact_materialization.py b/tests/unit/test_function_artifact_materialization.py index 7929a53f2a..129b392a18 100644 --- a/tests/unit/test_function_artifact_materialization.py +++ b/tests/unit/test_function_artifact_materialization.py @@ -116,24 +116,23 @@ SOURCE_PLANE_INDEX_FIELD, ) from openhcs.core.source_spatial_domain import SourceSpatialDomain +from openhcs.core.steps.abstract import StepExecutionObservation from openhcs.core.steps.function_artifact_materialization import ( ArtifactMaterializationBackendPlan, PersistentArtifactMaterializationTargetPlan, StreamingOnlyArtifactMaterializationTargetPlan, actual_materialization_records, materialize_artifact_outputs, - materialized_artifact_output_paths, - observed_materialized_artifact_locations_by_address, - observed_materialized_artifact_output_paths, + preview_reused_step_outputs, + RuntimeArtifactMaterialization, planned_materialization_preview, runtime_artifact_materializations, runtime_artifact_materializations_from_records, - runtime_export_artifact_output_paths, ) from openhcs.core.steps.function_output_identity import ( IncompleteFunctionOutputFilenameIdentityError, ) -from openhcs.core.steps.function_runtime import FunctionOutputContextStrategy + from openhcs.core.streaming_config_declarations import ViewerType from openhcs.core.streaming_config_factory import ( StreamingViewerRuntimeConfig, @@ -158,6 +157,7 @@ from openhcs.processing.materialization.core import ( MaterializationSpec, Output, + SavedMaterializationOutputs, materialization_outputs, ) from openhcs.processing.materialization.options import ( @@ -321,6 +321,14 @@ def ensure_directory(self, path, backend): def load(self, path, backend): return self.memory[path] + def load_text(self, path, backend): + for content, saved_path, saved_backend, _kwargs in reversed(self.saved): + if str(saved_path) == str(path) and saved_backend == backend: + if not isinstance(content, str): + raise TypeError("Saved output is not text") + return content + raise FileNotFoundError(path) + def save(self, content, path, backend, **kwargs): self.saved.append((content, path, backend, kwargs)) @@ -585,9 +593,7 @@ def test_slice_aligned_object_label_arrays_preserve_source_slice_metadata(): ) label_slices = RuntimeSliceAlignedValues(tuple(expected_labels)) - contextualized = FunctionOutputContextStrategy.for_output_plan( - output_plan - ).contextualize( + contextualized = (ImageArtifactType if output_plan is None else output_plan.artifact_type).contextualize_output( source, label_slices, output_plan, @@ -667,9 +673,7 @@ def test_image_outputs_merge_source_provenance_when_output_already_has_metadata( metadata=ImagePayloadMetadata(source_dtype="float32"), ) - contextualized = FunctionOutputContextStrategy.for_output_plan( - output_plan - ).contextualize( + contextualized = (ImageArtifactType if output_plan is None else output_plan.artifact_type).contextualize_output( source, output, output_plan, @@ -725,9 +729,7 @@ def test_object_label_payload_stack_preserves_source_slice_metadata(): ), ) - contextualized = FunctionOutputContextStrategy.for_output_plan( - output_plan - ).contextualize( + contextualized = (ImageArtifactType if output_plan is None else output_plan.artifact_type).contextualize_output( source, labels, output_plan, @@ -792,10 +794,10 @@ def test_materialize_artifact_outputs_uses_runtime_store_payload( def fake_materialize(_spec, data, path, *_args, **_kwargs): materialized.append((data, path)) - return path + return SimpleNamespace(save=lambda: SavedMaterializationOutputs({})) monkeypatch.setattr( - "openhcs.processing.materialization.materialize", + "openhcs.core.steps.function_artifact_materialization.prepare_materialization", fake_materialize, ) @@ -842,10 +844,10 @@ def test_materialize_artifact_outputs_attaches_image_schema_provenance(monkeypat def fake_materialize(_spec, data, path, *_args, **_kwargs): materialized.append((data, path)) - return path + return SimpleNamespace(save=lambda: SavedMaterializationOutputs({})) monkeypatch.setattr( - "openhcs.processing.materialization.materialize", + "openhcs.core.steps.function_artifact_materialization.prepare_materialization", fake_materialize, ) @@ -925,10 +927,10 @@ def fake_materialize(spec, data, path, manager, *_args, **kwargs): variable_components=kwargs["variable_components"], ) ) - return output_paths[0] + return SimpleNamespace(save=lambda: SavedMaterializationOutputs({})) monkeypatch.setattr( - "openhcs.processing.materialization.materialize", + "openhcs.core.steps.function_artifact_materialization.prepare_materialization", fake_materialize, ) @@ -943,7 +945,14 @@ def fake_materialize(spec, data, path, manager, *_args, **kwargs): expected_paths = tuple( Path(f"/images/A01_s{site:03d}_w1_z001_t001_saved.tif") for site in range(1, 4) ) - assert materialized_artifact_output_paths(plan, context) == expected_paths + assert ( + tuple( + Path(output.path) + for materialization in runtime_artifact_materializations(plan, context) + for output in materialization.outputs(plan, context) + ) + == expected_paths + ) materialize_artifact_outputs( filemanager, @@ -993,10 +1002,10 @@ def test_materialize_artifact_outputs_does_not_require_vfs_payload_for_store_rec def fake_materialize(_spec, data, path, *_args, **_kwargs): materialized.append((data, path)) - return path + return SimpleNamespace(save=lambda: SavedMaterializationOutputs({})) monkeypatch.setattr( - "openhcs.processing.materialization.materialize", + "openhcs.core.steps.function_artifact_materialization.prepare_materialization", fake_materialize, ) @@ -1048,10 +1057,10 @@ def test_materialize_artifact_outputs_uses_runtime_record_identity_not_final_pat def fake_materialize(_spec, data, path, *_args, **_kwargs): materialized.append((data, path)) - return path + return SimpleNamespace(save=lambda: SavedMaterializationOutputs({})) monkeypatch.setattr( - "openhcs.processing.materialization.materialize", + "openhcs.core.steps.function_artifact_materialization.prepare_materialization", fake_materialize, ) @@ -1102,10 +1111,10 @@ def test_materialize_artifact_outputs_uses_declared_measurement_csv_spec( def fake_materialize(spec, data, path, *_args, **_kwargs): materialized.append((spec, data, path)) - return path + return SimpleNamespace(save=lambda: SavedMaterializationOutputs({})) monkeypatch.setattr( - "openhcs.processing.materialization.materialize", + "openhcs.core.steps.function_artifact_materialization.prepare_materialization", fake_materialize, ) @@ -1525,9 +1534,10 @@ def test_multi_plane_roi_aggregate_defers_source_filenames_to_plane_writer(monke assert str(materialization.base_path) == ( "/analysis/A01_z_index-1_timepoint-1_segmentation_masks_step7.roi.zip" ) + roi_outputs = materialization.outputs(plan, context) assert tuple( output.path - for output in materialization.outputs(plan, context) + for output in roi_outputs if output.path.endswith(".roi.zip") ) == tuple( ( @@ -1550,8 +1560,8 @@ def test_multi_plane_roi_aggregate_defers_source_filenames_to_plane_writer(monke ), ) assert ( - RuntimeAnalysisConsolidationInputs.from_records( - context, context.runtime_value_store.observed_values, + RuntimeAnalysisConsolidationInputs.from_reused_outputs( + context, plan, materialization, roi_outputs, ) is None ) @@ -1704,21 +1714,32 @@ def record_for_site(site: str) -> None: current_execution_records = context.runtime_value_store.observed_values_after( current_execution_cursor ) - assert observed_materialized_artifact_output_paths( - plan, - context, - current_execution_records, + saved = materialize_artifact_outputs( + context.filemanager, plan, + PersistentArtifactMaterializationTargetPlan("disk"), context, + ) + selected_saved = tuple( + artifact for artifact in saved + if artifact.materialization.record.key == current_execution_records[0].key + ) + assert len(selected_saved) == 1 + selected_path = selected_saved[0].outputs_for_backend("disk")[0].path + historical_content = "cell_count\r\n99\r\n" + context.filemanager.save(historical_content, selected_path, "disk") + reused = preview_reused_step_outputs(plan, context, current_execution_records) + assert reused.analysis_inputs is not None + assert reused.analysis_inputs.outputs_by_directory[Path("/analysis")][0].csv_content == historical_content + assert tuple( + Path(location.path) + for locations in reused.materialized_locations_by_address.values() + for location in locations ) == ( Path( "/analysis/A01_site-2_z_index-1_timepoint-1_" "cell_counts_step7_details.csv" ), ) - assert observed_materialized_artifact_locations_by_address( - plan, - context, - current_execution_records, - ) == { + assert reused.materialized_locations_by_address == { RuntimeArtifactAddress.from_record(current_execution_records[0]): ( RuntimeArtifactLocation( path=( @@ -1730,9 +1751,7 @@ def record_for_site(site: str) -> None: ), } context.step_plans = {plan.step_index: plan} - consolidation_inputs = RuntimeAnalysisConsolidationInputs.from_records( - context, current_execution_records, - ) + consolidation_inputs = selected_saved[0].observation(plan, context).analysis_inputs assert consolidation_inputs is not None runtime_output = consolidation_inputs.outputs_by_directory[Path("/analysis")][0] assert runtime_output.path == Path( @@ -1777,13 +1796,10 @@ def test_terminal_persistence_is_reported_without_becoming_declared_export() -> persistent_backend="disk", ) - locations = observed_materialized_artifact_locations_by_address( - plan, - context, - (record,), - ) - - assert locations == { + reused = preview_reused_step_outputs(plan, context, (record,)) + assert reused.runtime_export_paths == () + assert reused.analysis_inputs is None + assert reused.materialized_locations_by_address == { RuntimeArtifactAddress.from_record(record): ( RuntimeArtifactLocation( path="/analysis/A01_cell_counts_step7_details.csv", @@ -1791,7 +1807,6 @@ def test_terminal_persistence_is_reported_without_becoming_declared_export() -> ), ), } - assert runtime_export_artifact_output_paths(plan, context) == () assert not output_plan.materialization.participates_in_runtime_export_observation() @@ -1835,9 +1850,13 @@ def test_consolidation_preserves_export_bundle_and_text_tables(options, payload) persistent_backend="disk", ) context.step_plans = {plan.step_index: plan} - consolidation = RuntimeAnalysisConsolidationInputs.from_records( - context, context.runtime_value_store.observed_values, + saved = materialize_artifact_outputs( + context.filemanager, plan, + PersistentArtifactMaterializationTargetPlan("disk"), context, ) + consolidation = StepExecutionObservation.combine( + artifact.observation(plan, context) for artifact in saved + ).analysis_inputs assert consolidation is not None outputs = tuple( output @@ -1855,7 +1874,7 @@ def test_consolidation_preserves_export_bundle_and_text_tables(options, payload) (RuntimeObservationMode.OMIT, RuntimeObservationMode.MERGE_INTO_PARENT), ) def test_completed_observation_projects_tables_before_worker_payload_release( - observation_mode, + observation_mode, monkeypatch, ): image_plan = ArtifactOutputPlan( name="Corrected", path="/memory/Corrected.pkl", artifact_type=ImageArtifactType, @@ -1897,10 +1916,23 @@ def test_completed_observation_projects_tables_before_worker_payload_release( ), path=table_plan.path, backend="memory", ) + saved = materialize_artifact_outputs( + context.filemanager, table_step, + PersistentArtifactMaterializationTargetPlan("disk"), context, + ) + monkeypatch.setattr( + RuntimeArtifactMaterialization, "outputs", + lambda *_args, **_kwargs: pytest.fail("Saved tables must not render again"), + ) + step_observation = StepExecutionObservation.combine( + artifact.observation(table_step, context) for artifact in saved + ) observation = RuntimeContextObservation.from_context( context_key="A01", context=context, records=context.runtime_value_store.observed_values, runtime_observation_mode=observation_mode, + runtime_export_paths=step_observation.runtime_export_paths, + analysis_inputs=step_observation.analysis_inputs, ) context.runtime_value_store.clear() del pixels @@ -1982,11 +2014,12 @@ def test_materialize_artifact_outputs_unions_measurement_subject_records( materialized = [] def fake_materialize(_spec, data, path, *_args, **_kwargs): + assert not data.source_provenance.has_values materialized.append((tuple(data.iter_row_mappings()), path)) - return path + return SimpleNamespace(save=lambda: SavedMaterializationOutputs({})) monkeypatch.setattr( - "openhcs.processing.materialization.materialize", + "openhcs.core.steps.function_artifact_materialization.prepare_materialization", fake_materialize, ) @@ -2079,7 +2112,7 @@ def test_fixed_component_scopes_materialize_distinct_measurement_paths() -> None materializations = runtime_artifact_materializations(plan, context) assert len(records) == 2 - assert tuple(record.value.data.rows.row_count() for record in records) == (2, 1) + assert tuple(record.data.rows.row_count() for record in records) == (2, 1) assert tuple( record.key.scope.value_text_for_component(AllComponents.Z_INDEX) for record in records @@ -2286,10 +2319,10 @@ def fake_materialize( **_kwargs, ): materialized.append((spec, data, path, backends, backend_kwargs)) - return path + return SimpleNamespace(save=lambda: SavedMaterializationOutputs({})) monkeypatch.setattr( - "openhcs.processing.materialization.materialize", + "openhcs.core.steps.function_artifact_materialization.prepare_materialization", fake_materialize, ) @@ -2352,10 +2385,10 @@ def test_materialize_artifact_outputs_uses_actual_group_records(monkeypatch): def fake_materialize(spec, data, path, *_args, **_kwargs): materialized.append((spec, data, path)) - return path + return SimpleNamespace(save=lambda: SavedMaterializationOutputs({})) monkeypatch.setattr( - "openhcs.processing.materialization.materialize", + "openhcs.core.steps.function_artifact_materialization.prepare_materialization", fake_materialize, ) @@ -2551,7 +2584,7 @@ def test_actual_materialization_records_uses_dynamic_runtime_groups(): ) assert tuple(record.key.scope.value_text for record in records) == ("1", "2") - assert tuple(record.path for record in records) == ( + assert tuple(record.location.path for record in records) == ( "/memory/A01_w1_segmentation_masks_step7.pkl", "/memory/A01_w2_segmentation_masks_step7.pkl", ) @@ -2632,10 +2665,10 @@ def test_materialize_artifact_outputs_uses_group_measurement_artifact_identity( def fake_materialize(spec, data, path, *_args, **_kwargs): materialized.append((spec, data, path)) - return path + return SimpleNamespace(save=lambda: SavedMaterializationOutputs({})) monkeypatch.setattr( - "openhcs.processing.materialization.materialize", + "openhcs.core.steps.function_artifact_materialization.prepare_materialization", fake_materialize, ) @@ -2696,10 +2729,10 @@ def test_materialize_artifact_outputs_keeps_grouped_artifact_record_path( def fake_materialize(spec, data, path, *_args, **_kwargs): materialized.append((spec, data, path)) - return path + return SimpleNamespace(save=lambda: SavedMaterializationOutputs({})) monkeypatch.setattr( - "openhcs.processing.materialization.materialize", + "openhcs.core.steps.function_artifact_materialization.prepare_materialization", fake_materialize, ) @@ -2762,10 +2795,10 @@ def fake_materialize( **_kwargs, ): materialized.append((spec, data, path, backends, backend_kwargs)) - return path + return SimpleNamespace(save=lambda: SavedMaterializationOutputs({})) monkeypatch.setattr( - "openhcs.processing.materialization.materialize", + "openhcs.core.steps.function_artifact_materialization.prepare_materialization", fake_materialize, ) @@ -2832,10 +2865,10 @@ def fake_materialize( **_kwargs, ): materialized.append((spec, data, path, backends, backend_kwargs)) - return path + return SimpleNamespace(save=lambda: SavedMaterializationOutputs({})) monkeypatch.setattr( - "openhcs.processing.materialization.materialize", + "openhcs.core.steps.function_artifact_materialization.prepare_materialization", fake_materialize, ) @@ -2982,10 +3015,10 @@ def test_materialize_artifact_outputs_uses_declared_metadata_json_spec( def fake_materialize(spec, data, path, *_args, **_kwargs): materialized.append((spec, data, path)) - return path + return SimpleNamespace(save=lambda: SavedMaterializationOutputs({})) monkeypatch.setattr( - "openhcs.processing.materialization.materialize", + "openhcs.core.steps.function_artifact_materialization.prepare_materialization", fake_materialize, ) @@ -3016,9 +3049,10 @@ def test_materialize_artifact_outputs_skips_special_without_explicit_spec( def fake_materialize(*args, **kwargs): materialized.append((args, kwargs)) + return SimpleNamespace(save=lambda: SavedMaterializationOutputs({})) monkeypatch.setattr( - "openhcs.processing.materialization.materialize", + "openhcs.core.steps.function_artifact_materialization.prepare_materialization", fake_materialize, ) @@ -3093,7 +3127,9 @@ def test_tile_positions_runtime_materializes_native_json_without_changing_payloa (retained,) = tuple((tmp_path / "results").rglob("*.json")) assert json.loads(retained.read_text()) == [list(pair) for pair in positions] assert positions == [(-1.25, 0.000000001), (921.600000001, -3.5), (1.0, 1843.2)] - assert record.value is value + assert record.key is value.key + assert record.data is value.data + assert record.materialization_source_metadata is value.materialization_source_metadata def test_materialize_artifact_outputs_skips_explicitly_disabled_artifact_without_record( @@ -3111,9 +3147,10 @@ def test_materialize_artifact_outputs_skips_explicitly_disabled_artifact_without def fake_materialize(*args, **kwargs): materialized.append((args, kwargs)) + return SimpleNamespace(save=lambda: SavedMaterializationOutputs({})) monkeypatch.setattr( - "openhcs.processing.materialization.materialize", + "openhcs.core.steps.function_artifact_materialization.prepare_materialization", fake_materialize, ) @@ -3151,10 +3188,10 @@ def test_materialize_artifact_outputs_uses_declared_object_labels_roi_spec(monke def fake_materialize(spec, data, path, *_args, **_kwargs): materialized.append((spec, data, path)) - return path + return SimpleNamespace(save=lambda: SavedMaterializationOutputs({})) monkeypatch.setattr( - "openhcs.processing.materialization.materialize", + "openhcs.core.steps.function_artifact_materialization.prepare_materialization", fake_materialize, ) @@ -3208,10 +3245,10 @@ def fake_materialize( **_kwargs, ): materialized.append((spec, data, path, backends, backend_kwargs)) - return path + return SimpleNamespace(save=lambda: SavedMaterializationOutputs({})) monkeypatch.setattr( - "openhcs.processing.materialization.materialize", + "openhcs.core.steps.function_artifact_materialization.prepare_materialization", fake_materialize, ) @@ -3297,9 +3334,10 @@ def fake_materialize( **_kwargs, ): materialized.append((backends, backend_kwargs)) + return SimpleNamespace(save=lambda: SavedMaterializationOutputs({})) monkeypatch.setattr( - "openhcs.processing.materialization.materialize", + "openhcs.core.steps.function_artifact_materialization.prepare_materialization", fake_materialize, ) @@ -3361,10 +3399,10 @@ def fake_materialize( **_kwargs, ): materialized.append((spec, data, path, backends, backend_kwargs)) - return path + return SimpleNamespace(save=lambda: SavedMaterializationOutputs({})) monkeypatch.setattr( - "openhcs.processing.materialization.materialize", + "openhcs.core.steps.function_artifact_materialization.prepare_materialization", fake_materialize, ) @@ -3443,10 +3481,10 @@ def fake_materialize( **_kwargs, ): materialized.append((spec, data, path, backends, backend_kwargs)) - return path + return SimpleNamespace(save=lambda: SavedMaterializationOutputs({})) monkeypatch.setattr( - "openhcs.processing.materialization.materialize", + "openhcs.core.steps.function_artifact_materialization.prepare_materialization", fake_materialize, ) @@ -3505,10 +3543,10 @@ def test_materialize_artifact_outputs_uses_runtime_plane_group_identity( def fake_materialize(_spec, data, path, *_args, **_kwargs): materialized.append((data, path)) - return path + return SimpleNamespace(save=lambda: SavedMaterializationOutputs({})) monkeypatch.setattr( - "openhcs.processing.materialization.materialize", + "openhcs.core.steps.function_artifact_materialization.prepare_materialization", fake_materialize, ) @@ -3576,10 +3614,10 @@ def fake_materialize( **_kwargs, ): materialized.append((spec, data, path, backends, backend_kwargs)) - return path + return SimpleNamespace(save=lambda: SavedMaterializationOutputs({})) monkeypatch.setattr( - "openhcs.processing.materialization.materialize", + "openhcs.core.steps.function_artifact_materialization.prepare_materialization", fake_materialize, ) @@ -3677,10 +3715,10 @@ def fake_materialize( **_kwargs, ): materialized.append((spec, data, path, backends, backend_kwargs)) - return path + return SimpleNamespace(save=lambda: SavedMaterializationOutputs({})) monkeypatch.setattr( - "openhcs.processing.materialization.materialize", + "openhcs.core.steps.function_artifact_materialization.prepare_materialization", fake_materialize, ) @@ -3849,10 +3887,10 @@ def fake_materialize( **_kwargs, ): materialized.append((spec, data, path, backends, backend_kwargs)) - return path + return SimpleNamespace(save=lambda: SavedMaterializationOutputs({})) monkeypatch.setattr( - "openhcs.processing.materialization.materialize", + "openhcs.core.steps.function_artifact_materialization.prepare_materialization", fake_materialize, ) @@ -3952,10 +3990,10 @@ def fake_materialize( **_kwargs, ): materialized.append((spec, data, path, backends, backend_kwargs)) - return path + return SimpleNamespace(save=lambda: SavedMaterializationOutputs({})) monkeypatch.setattr( - "openhcs.processing.materialization.materialize", + "openhcs.core.steps.function_artifact_materialization.prepare_materialization", fake_materialize, ) @@ -4038,10 +4076,10 @@ def test_materialize_image_uses_declared_filename_source_identity(monkeypatch): def fake_materialize(_spec, _data, path, *_args, **_kwargs): materialized.append(path) - return path + return SimpleNamespace(save=lambda: SavedMaterializationOutputs({})) monkeypatch.setattr( - "openhcs.processing.materialization.materialize", + "openhcs.core.steps.function_artifact_materialization.prepare_materialization", fake_materialize, ) @@ -4130,9 +4168,7 @@ def test_compiled_z_axis_reaches_source_named_image_materialization() -> None: selected_payload = ImagePayloadMetadata( source_image_names=(selected_image.name,), ).payload_with(np.ones((2, 5, 7), dtype=np.uint16), None) - saved_payload = FunctionOutputContextStrategy.for_output_plan( - output_plan, - ).contextualize_from_projector( + saved_payload = (ImageArtifactType if output_plan is None else output_plan.artifact_type).contextualize_output_from_projector( selected_payload, ImagePayloadMetadata( plane_axis=RuntimePlaneAxis.RUNTIME_SLICE, @@ -4198,7 +4234,11 @@ def test_compiled_z_axis_reaches_source_named_image_materialization() -> None: assert image_payload_metadata(saved_payload).plane_axis is ( RuntimePlaneAxis.RUNTIME_SLICE ) - assert materialized_artifact_output_paths(plan, context) == ( + assert tuple( + Path(output.path) + for materialization in runtime_artifact_materializations(plan, context) + for output in materialization.outputs(plan, context) + ) == ( Path("/images/A01_s001_w2_z001_t001_NucleiLabels.tif"), Path("/images/A01_s001_w2_z002_t001_NucleiLabels.tif"), ) @@ -4268,10 +4308,10 @@ def fake_materialize( **_kwargs, ): materialized.append((spec, data, path, backends, backend_kwargs)) - return path + return SimpleNamespace(save=lambda: SavedMaterializationOutputs({})) monkeypatch.setattr( - "openhcs.processing.materialization.materialize", + "openhcs.core.steps.function_artifact_materialization.prepare_materialization", fake_materialize, ) diff --git a/tests/unit/test_function_artifact_outputs.py b/tests/unit/test_function_artifact_outputs.py index 5cda2912d1..f858658d81 100644 --- a/tests/unit/test_function_artifact_outputs.py +++ b/tests/unit/test_function_artifact_outputs.py @@ -59,7 +59,6 @@ from openhcs.core.source_bindings import ( CompiledSourceBindingPlan, NamedSourceBinding, - SourceBindingRuntimeContext, ) from openhcs.core.source_load_plan import SourceLoadPlan from openhcs.core.source_metadata import ( @@ -78,12 +77,8 @@ from openhcs.core.steps.function_runtime import ( ComponentArtifactPlans, FunctionCoreExecutor, - FunctionOutputContextStrategy, - FunctionRuntimeScope, - ImageFunctionOutputContextStrategy, PatternGroupData, PatternGroupRuntime, - UnchangedFunctionOutputContextStrategy, ) from openhcs.core.aligned_image_payload import ( AlignedImageSliceContext, @@ -127,22 +122,6 @@ def passthrough(image): return image -def test_every_registered_artifact_type_has_one_context_strategy_owner() -> None: - for artifact_type in ArtifactType.__registry__.values(): - owners = FunctionOutputContextStrategy.owning_strategy_types(artifact_type) - assert len(owners) == 1, artifact_type - - -@pytest.mark.parametrize( - "artifact_type", - [SpecialArtifactType, MetadataArtifactType], -) -def test_context_free_artifacts_use_the_declared_root_strategy(artifact_type) -> None: - strategy = FunctionOutputContextStrategy.for_context(artifact_type) - - assert type(strategy) is UnchangedFunctionOutputContextStrategy - - def test_special_outputs_is_the_artifact_outputs_public_spelling() -> None: assert special_outputs is artifact_outputs @@ -265,7 +244,9 @@ def _execute_function_core(request: CoreExecutionRequest): component_value = ( None if request.execution_group_scope.is_ungrouped else request.group_key ) - runtime_scope = FunctionRuntimeScope( + runtime_scope = PatternGroupData( + matching_files=[f"input-{index}.tif" for index in range(request.runtime_plane_count)], + main_data_stack=request.main_data_arg, context=request.context, execution_plan=execution_plan, compiled_group=CompiledFunctionGroup( @@ -277,7 +258,6 @@ def _execute_function_core(request: CoreExecutionRequest): execution_plan, component_value, ), - source_binding_context=SourceBindingRuntimeContext.empty(), runtime_plane_index=0, runtime_plane_count=request.runtime_plane_count, ) @@ -285,7 +265,7 @@ def _execute_function_core(request: CoreExecutionRequest): return FunctionCoreExecutor( main_data_arg=request.main_data_arg, source_memory_type=MEMORY_TYPE_NUMPY, - runtime_scope=runtime_scope, + group_data=runtime_scope, invocation=invocation, artifacts=runtime_scope.artifacts.select_for_invocation( invocation, @@ -374,9 +354,7 @@ def test_image_output_context_preserves_stack_after_exact_source_projection(): relations=(GroupLineageSourceRelation(source_spec.ref()),), ) - result = FunctionOutputContextStrategy.for_output_plan( - output_plan, - ).contextualize( + result = (ImageArtifactType if output_plan is None else output_plan.artifact_type).contextualize_output( source, output, output_plan, @@ -426,9 +404,7 @@ def test_image_output_context_does_not_infer_axis_for_unmarked_payload(): relations=(GroupLineageSourceRelation(source_spec.ref()),), ) - result = FunctionOutputContextStrategy.for_output_plan( - output_plan, - ).contextualize_from_projector( + result = (ImageArtifactType if output_plan is None else output_plan.artifact_type).contextualize_output_from_projector( source, np.ones((2, 4, 5), dtype=np.uint16), output_plan, @@ -460,9 +436,7 @@ def test_image_output_context_rejects_declared_output_axis_shape_drift(): ValueError, match="declared 'runtime_slice' axis of size 2", ): - FunctionOutputContextStrategy.for_output_plan( - output_plan, - ).contextualize( + (ImageArtifactType if output_plan is None else output_plan.artifact_type).contextualize_output( np.ones((1, 4, 5), dtype=np.float32), output, output_plan, @@ -499,9 +473,7 @@ def test_image_output_context_preserves_complete_scalar_rgb_identity() -> None: relations=(GroupLineageSourceRelation(source_spec.ref()),), ) - result = FunctionOutputContextStrategy.for_output_plan( - output_plan, - ).contextualize_from_projector( + result = (ImageArtifactType if output_plan is None else output_plan.artifact_type).contextualize_output_from_projector( source, output, output_plan, @@ -528,7 +500,7 @@ def test_image_output_context_preserves_target_axis_across_source_rank_change() plane_axis=RuntimePlaneAxis.RUNTIME_SLICE, ).payload_with(np.ones((1, 2, 4, 5, 3), dtype=np.float32), None) - result = FunctionOutputContextStrategy.for_output_plan(None).contextualize( + result = ImageArtifactType.contextualize_output( source, output, None, @@ -587,9 +559,7 @@ def test_image_output_context_projects_complete_multi_plane_identity() -> None: relations=(GroupLineageSourceRelation(source_spec.ref()),), ) - result = FunctionOutputContextStrategy.for_output_plan( - output_plan, - ).contextualize_from_projector( + result = (ImageArtifactType if output_plan is None else output_plan.artifact_type).contextualize_output_from_projector( source, output, output_plan, @@ -630,9 +600,7 @@ def test_named_image_outputs_bypass_unrelated_source_axis_projection(): ), ) - result = FunctionOutputContextStrategy.for_output_plan( - None - ).contextualize_from_projector( + result = ImageArtifactType.contextualize_output_from_projector( source, bundle, None, @@ -660,21 +628,19 @@ def test_image_output_context_projector_proves_source_ownership_once( ).payload_with(np.zeros((2, 4, 5), dtype=np.uint16), None) output = np.ones((2, 4, 5), dtype=np.uint8) ownership_proofs = [] - original = ImageFunctionOutputContextStrategy.output_owns_source_context + original = ImageArtifactType.output_owns_source_context def track_ownership_proof(*args): ownership_proofs.append(args) return original(*args) monkeypatch.setattr( - ImageFunctionOutputContextStrategy, + ImageArtifactType, "output_owns_source_context", staticmethod(track_ownership_proof), ) - result = FunctionOutputContextStrategy.for_output_plan( - None - ).contextualize_from_projector( + result = ImageArtifactType.contextualize_output_from_projector( source, output, None, @@ -688,13 +654,6 @@ def track_ownership_proof(*args): ) -def test_image_output_context_uses_base_projector_resolution() -> None: - assert ( - "contextualize_from_projector" - not in ImageFunctionOutputContextStrategy.__dict__ - ) - - def test_composed_function_output_owns_collapsed_source_identity(): source = ImagePayloadMetadata( source_path="/input/A01_s001_w1_z001_t001.tif", @@ -1046,7 +1005,7 @@ def analyze(image): axis_id="A01", ) assert len(stored) == 1 - assert tuple(stored[0].value.data.rows) == ({"count": 2},) + assert tuple(stored[0].data.rows) == ({"count": 2},) def test_trailing_object_labels_do_not_replace_canonical_image_output(): @@ -1115,7 +1074,7 @@ def count(_image): name=labels_spec.name, axis_id=context.axis_id, ) - assert isinstance(stored_labels.value.data, ObjectLabelSet) + assert isinstance(stored_labels.data, ObjectLabelSet) def test_execute_function_core_attaches_execution_group_identity_to_artifact(): @@ -1174,7 +1133,7 @@ def segment(image): match_group=True, ) assert len(stored) == 1 - metadata = image_payload_metadata(stored[0].value.data) + metadata = image_payload_metadata(stored[0].data) assert dict(metadata.source_component_metadata) == { "well": "A01", "site": "1", @@ -1243,8 +1202,8 @@ def segment(image): match_group=True, ) assert len(stored) == 1 - assert stored[0].path == "/memory/A01_w2_segmentation_masks.pkl" - metadata = image_payload_metadata(stored[0].value.data) + assert stored[0].location.path == "/memory/A01_w2_segmentation_masks.pkl" + metadata = image_payload_metadata(stored[0].data) assert dict(metadata.source_component_metadata) == { "well": "A01", "site": "1", @@ -1341,8 +1300,8 @@ def corrected_images(image): green_records = context.runtime_value_store.find(name="Green", axis_id="A01") assert len(red_records) == 1 assert len(green_records) == 1 - assert image_payload_data(red_records[0].value.data)[0, 0] == 1 - assert image_payload_data(green_records[0].value.data)[0, 0] == 2 + assert image_payload_data(red_records[0].data)[0, 0] == 1 + assert image_payload_data(green_records[0].data)[0, 0] == 2 def test_execute_function_core_keeps_image_sidecar_out_of_main_flow(): @@ -1395,7 +1354,7 @@ def crop_outputs(source): ) assert len(mask_records) == 1 np.testing.assert_array_equal( - image_payload_data(mask_records[0].value.data), + image_payload_data(mask_records[0].data), mask, ) @@ -1446,12 +1405,83 @@ def produce_corrected_image(image): ) stored = context.runtime_value_store.find(name="CorrectedImage", axis_id="A01") assert len(stored) == 1 - np.testing.assert_array_equal(image_payload_data(stored[0].value.data), output) - assert image_payload_metadata(stored[0].value.data).source_image_names == ( + np.testing.assert_array_equal(image_payload_data(stored[0].data), output) + assert image_payload_metadata(stored[0].data).source_image_names == ( "CorrectedImage", ) +def test_saved_canonical_source_projection_survives_main_flow_return(): + from openhcs.core.projected_image_output import SelectedPlaneImageOutput + + context = ContextStub() + pixels = np.arange(12, dtype=np.uint16).reshape(2, 2, 3) + paths = ("/source/A01_s001_w2_z001_t001.tif", "/source/A01_s002_w2_z001_t001.tif") + source = ImagePayloadMetadata( + plane_axis=RuntimePlaneAxis.RUNTIME_SLICE, + source_image_provenance_planes=SourceImageProvenancePlanes.from_components( + paths=paths, + component_metadata=tuple( + {"well": "A01", "site": site, "channel": "2", "z_index": "1", "timepoint": "1"} + for site in ("1", "2") + ), + ), + ).payload_with(pixels) + output = ArtifactSpec.output("Selected", ImageArtifactType) + plan = ArtifactOutputPlan(name=output.name, path="/memory/selected.pkl", artifact_type=ImageArtifactType) + + @artifact_outputs(output) + def select_second_plane(image): + return SelectedPlaneImageOutput(image[1:2], (1,)) + + result = _execute_function_core(CoreExecutionRequest( + func_callable=select_second_plane, main_data_arg=source, base_kwargs={}, context=context, + artifact_inputs={}, artifact_outputs={plan.ref(): plan}, runtime_plane_count=2, + )) + stored = context.runtime_value_store.find(name=output.name, axis_id="A01") + assert len(stored) == 1 + for payload in (result, stored[0].data): + np.testing.assert_array_equal(image_payload_data(payload), pixels[1]) + metadata = image_payload_metadata(payload) + assert metadata.plane_axis is None + assert metadata.source_provenance.source_plane_count == 0 + assert metadata.source_path == paths[1] + assert metadata.source_component_metadata["site"] == "2" + assert metadata.source_image_names == (output.name,) + + +@pytest.mark.parametrize("declared_canonical", [False, True]) +def test_unsaved_main_return_reads_source_context_after_artifact_save(declared_canonical): + context = ContextStub() + source = ImagePayloadMetadata( + source_path="/source/before.tif", + source_component_metadata={"well": "A01", "site": "1", "channel": "2"}, + ).payload_with(np.zeros((2, 3), dtype=np.float32)) + sidecar = ArtifactSpec.output("Sidecar", MetadataArtifactType) + canonical = ArtifactSpec.output("Unselected", ImageArtifactType) + plan = ArtifactOutputPlan(name=sidecar.name, path="/memory/sidecar.pkl", artifact_type=MetadataArtifactType) + original_save = context.filemanager.save + + def save_and_change_source(value, path, backend): + original_save(value, path, backend) + source.metadata.source_path = "/source/after.tif" + source.metadata.source_component_metadata = {"well": "A01", "site": "9", "channel": "2"} + + context.filemanager.save = save_and_change_source + + @artifact_outputs(*(canonical, sidecar) if declared_canonical else (sidecar,)) + def produce(image): + return image + 1, {"note": "saved"} + + result = _execute_function_core(CoreExecutionRequest( + func_callable=produce, main_data_arg=source, base_kwargs={}, context=context, + artifact_inputs={}, artifact_outputs={plan.ref(): plan}, + )) + np.testing.assert_array_equal(image_payload_data(result), np.ones((2, 3))) + assert image_payload_metadata(result).source_path == "/source/after.tif" + assert image_payload_metadata(result).source_component_metadata["site"] == "9" + + def test_execute_function_core_names_slice_aligned_image_outputs() -> None: context = ContextStub() source_slices = tuple( @@ -1503,7 +1533,7 @@ def produce_image(image): name=output_spec.name, axis_id=context.axis_id, ) - stored_data = stored.value.data + stored_data = stored.data assert isinstance(stored_data, RuntimeSliceAlignedValues) for index, source_payload in enumerate(source_slices): output_payload = stored_data.value_for_slice(index) @@ -1596,7 +1626,7 @@ def analyze(image): match_group=True, ) assert len(stored) == 1 - assert stored[0].path == "/memory/A01_s2_measurements.pkl" + assert stored[0].location.path == "/memory/A01_s2_measurements.pkl" def test_execute_function_core_preserves_main_output_source_metadata(): @@ -1704,7 +1734,7 @@ def enhance(image, *, runtime): } -def test_pattern_group_runtime_stacks_nominal_scalar_rgb_output_as_one_slice(): +def test_pattern_group_runtime_retains_nominal_scalar_rgb_output_as_one_image(): scalar_output = ImagePayloadMetadata( source_path="/input/A01_s1_w3.tif", source_component_metadata={ @@ -1752,25 +1782,22 @@ def rgb_output(image): component_key=None, ) - output = runtime._validate_and_unstack( - scalar_output, - PatternGroupData( - matching_files=["source-1.tif", "source-2.tif"], - main_data_stack=np.zeros((2, 2, 3), dtype=np.uint16), - ), - ) - - assert output.slices == (scalar_output,) - assert output.slice_contexts == ( + output = runtime._project_output_slices(scalar_output, ["source-1.tif", "source-2.tif"]) + assert tuple(payload for payload, _context in output) == (scalar_output,) + assert tuple(context for _payload, context in output) == ( AlignedImageSliceContext.main_flow( "RGBImage", artifact_kind=ImageArtifactType.value, ), ) - assert image_payload_data(output.stack_payload).shape == (1, 2, 3, 3) - stack_metadata = image_payload_metadata(output.stack_payload) - assert stack_metadata.plane_axis is RuntimePlaneAxis.RUNTIME_SLICE - assert stack_metadata.source_channel_axis == 3 + from openhcs.core.aligned_image_payload import ImagePayloadStackComposition + stack_payload = ImagePayloadStackComposition.copy_whole_image( + scalar_output, memory_type=MEMORY_TYPE_NUMPY, device_id=None, + ) + assert image_payload_data(stack_payload).shape == (2, 3, 3) + stack_metadata = image_payload_metadata(stack_payload) + assert stack_metadata.plane_axis is None + assert stack_metadata.source_channel_axis == -1 def test_pattern_group_runtime_uses_declared_output_slice_cardinality(): @@ -1794,17 +1821,10 @@ def test_pattern_group_runtime_uses_declared_output_slice_cardinality(): component_key=None, ) - output = runtime._validate_and_unstack( - declared_output, - PatternGroupData( - matching_files=["source-1.tif", "source-2.tif"], - main_data_stack=np.zeros((2, 4, 5), dtype=np.float32), - ), - ) - - assert len(output.slices) == 1 - assert image_payload_data(output.slices[0]).shape == (4, 5) - assert output.stack_payload is declared_output + output = runtime._project_output_slices(declared_output, ["source-1.tif", "source-2.tif"]) + assert len(output) == 1 + assert image_payload_data(output[0][0]).shape == (4, 5) + assert image_payload_metadata(declared_output).plane_axis is RuntimePlaneAxis.RUNTIME_SLICE def test_pattern_group_runtime_projects_nominal_object_label_stack(): @@ -1841,28 +1861,21 @@ def test_pattern_group_runtime_projects_nominal_object_label_stack(): component_key=None, ) - output = runtime._validate_and_unstack( - declared_output, - PatternGroupData( - matching_files=["source-anchor.tif"], - main_data_stack=np.zeros((2, 2, 3), dtype=np.float32), - ), - ) - - assert output.stack_payload is declared_output - assert len(output.slices) == 2 - assert all(isinstance(value, ObjectLabelSet) for value in output.slices) - assert [value.name for value in output.slices] == ["SavedChildren"] * 2 - assert [value.plane_axis for value in output.slices] == [None, None] - assert [value.domain.scope for value in output.slices] == [ + projected = runtime._project_output_slices(declared_output, ["source-anchor.tif"]) + output = tuple(payload for payload, _context in projected) + assert len(output) == 2 + assert all(isinstance(value, ObjectLabelSet) for value in output) + assert [value.name for value in output] == ["SavedChildren"] * 2 + assert [value.plane_axis for value in output] == [None, None] + assert [value.domain.scope for value in output] == [ ObjectLabelDomainScope.PAYLOAD, ObjectLabelDomainScope.PAYLOAD, ] - assert [value.domain.declared_object_ids for value in output.slices] == [ + assert [value.domain.declared_object_ids for value in output] == [ (1,), (2,), ] - for output_slice, expected in zip(output.slices, label_planes, strict=True): + for output_slice, expected in zip(output, label_planes, strict=True): np.testing.assert_array_equal(output_slice.labels, expected) @@ -1905,16 +1918,16 @@ def module_step(image, *, runtime): return main_output contextualization_plans = [] - original_for_output_plan = FunctionOutputContextStrategy.for_output_plan + original_contextualize = ImageArtifactType.contextualize_output_from_projector - def track_contextualization(cls, output_plan): + def track_contextualization(cls, source, output, output_plan, projector): del cls contextualization_plans.append(output_plan) - return original_for_output_plan(output_plan) + return original_contextualize(source, output, output_plan, projector) monkeypatch.setattr( - FunctionOutputContextStrategy, - "for_output_plan", + ImageArtifactType, + "contextualize_output_from_projector", classmethod(track_contextualization), ) @@ -1974,10 +1987,10 @@ def calculate_illumination(image): ) assert len(stored) == 1 np.testing.assert_array_equal( - image_payload_data(stored[0].value.data), + image_payload_data(stored[0].data), source_data + 1, ) - stored_metadata = image_payload_metadata(stored[0].value.data) + stored_metadata = image_payload_metadata(stored[0].data) assert stored_metadata.source_image_names == (illumination_spec.name,) assert stored_metadata.source_provenance.represented_source_image_names == ( illumination_spec.name, @@ -2179,7 +2192,7 @@ def labels_to_image(image, labels: ObjectLabelValue): stored = context.runtime_value_store.find(name="label_image", axis_id="A01") assert len(stored) == 1 - metadata = image_payload_metadata(stored[0].value.data) + metadata = image_payload_metadata(stored[0].data) assert ( tuple( dict(item) @@ -2233,10 +2246,10 @@ def segment(image): stored = context.runtime_value_store.find(name="nuclei", axis_id="A01") assert len(stored) == 1 - assert isinstance(stored[0].value.data, ObjectLabelSet) - assert stored[0].value.data.name == "nuclei" - assert stored[0].value.data.source_path == "/input/01_POS002_D.TIF" - assert dict(stored[0].value.data.source_component_metadata) == { + assert isinstance(stored[0].data, ObjectLabelSet) + assert stored[0].data.name == "nuclei" + assert stored[0].data.source_path == "/input/01_POS002_D.TIF" + assert dict(stored[0].data.source_component_metadata) == { "well": "01", "site": "POS002", "channel": "D", @@ -2299,7 +2312,7 @@ def segment(image): name=output_spec.name, axis_id=context.axis_id, ) - label_set = stored.value.data + label_set = stored.data assert isinstance(label_set, ObjectLabelSet) assert label_set.name == output_spec.name assert label_set.plane_axis is RuntimePlaneAxis.RUNTIME_SLICE @@ -2381,11 +2394,11 @@ def count(image): ) ) [stored] = context.runtime_value_store.find(name=rows.name, axis_id=context.axis_id) - assert isinstance(stored.value.data, MeasurementTable) - assert stored.value.data.subject == MeasurementSubject( + assert isinstance(stored.data, MeasurementTable) + assert stored.data.subject == MeasurementSubject( MeasurementScope.IMAGE, image.name ) - assert tuple(stored.value.data.rows.column_values("cell_count")) == (2,) + assert tuple(stored.data.rows.column_values("cell_count")) == (2,) def test_compile_rejects_conflicting_measurement_subject_relations(): @@ -2446,7 +2459,7 @@ def count(image): name=measurement_spec.name, axis_id=context.axis_id, ) - table = stored.value.data + table = stored.data assert isinstance(table, MeasurementTable) assert table.name == measurement_spec.name assert table.subject == MeasurementSubject(MeasurementScope.ARTIFACT) @@ -2516,7 +2529,7 @@ def count(image): name=measurement_spec.name, axis_id=context.axis_id, ) - table = stored.value.data + table = stored.data assert isinstance(table, MeasurementTable) expected_rows = ( { @@ -2721,7 +2734,7 @@ def analyze(image): name="match_results", axis_id=context.axis_id, ) - assert stored.value.data is match_results + assert stored.data is match_results def test_execute_function_core_requires_store_record_even_when_vfs_payload_exists(): @@ -2907,15 +2920,14 @@ def declared_source_origin(image, *, image_to_save=None): spec=spec, storage_plan=None, projection=None, - consumes_main_flow=True, + main_flow_projection=main_flow_projection, ) invocation = invocation.with_artifact_input_edges((edge,)) return FunctionCoreExecutor( - runtime_scope=SimpleNamespace( + group_data=SimpleNamespace( context=ContextStub(), source_binding_plan=source_binding_plan, - source_binding_context=SourceBindingRuntimeContext.empty(), axis_scope=RuntimeExecutionAxisScope.from_raw( "A01", component=None, @@ -3106,7 +3118,7 @@ def test_missing_source_origin_is_not_satisfied_by_an_authored_kwarg(): spec = ArtifactSpec.input("MissingImage", ImageArtifactType, parameter_name="image_to_save") executor = _declared_source_executor(spec) (original_edge,) = executor.invocation.artifact_input_edges - edge = replace(original_edge, consumes_main_flow=False, main_flow_projection=None) + edge = replace(original_edge, main_flow_projection=None) primary = ImagePayloadMetadata().payload_with(np.zeros((1, 2, 3), dtype=np.uint16)) invocation = replace(executor.invocation, kwargs=(("image_to_save", primary),)) executor = replace(executor, invocation=invocation, diff --git a/tests/unit/test_function_core_executor_ownership.py b/tests/unit/test_function_core_executor_ownership.py new file mode 100644 index 0000000000..f53a51991c --- /dev/null +++ b/tests/unit/test_function_core_executor_ownership.py @@ -0,0 +1,152 @@ +"""One executor owns invocation state and polymorphic artifact-edge resolution.""" + +from dataclasses import FrozenInstanceError, MISSING, fields, replace +import inspect +import pickle +from types import SimpleNamespace + +import numpy as np +import pytest + +from openhcs.core.artifacts import ArtifactSpec, ArtifactSpecCollection, MetadataArtifactType +from openhcs.core.compiled_step_plan import CompiledStepPlan +from openhcs.core.component_group_scope import ComponentGroupScope +from openhcs.core.function_patterns import ( + CompiledMetadataArtifactInputEdgePlan, + InvocationArtifactInputEdgePlan, + InvocationArtifactInputProjectionKey, + compile_function_pattern, +) +from openhcs.core.pipeline.function_contracts import artifact_inputs +from openhcs.core.runtime_plane_projection import RuntimePlaneProjection +from openhcs.core.source_bindings import CompiledSourceBindingPlan +from openhcs.core.steps.function_runtime import ( + ComponentArtifactPlans, + FunctionCoreExecutor, + PatternGroupData, +) + + +_FIRST = ArtifactSpec.input("First", MetadataArtifactType, parameter_name="first") +_SECOND = ArtifactSpec.input("Second", MetadataArtifactType, parameter_name="second") + + +@artifact_inputs(_FIRST, _SECOND) +def _consume_metadata(image, *, first, second): + return image + + +def _executor(): + first = {"value": 1} + second = {"value": 2} + pattern = compile_function_pattern((_consume_metadata, {"first": first, "second": second}), {}, {}) + invocation = next(pattern.iter_invocations()) + edges = tuple( + InvocationArtifactInputEdgePlan.from_source_declarations( + key=InvocationArtifactInputProjectionKey(invocation_key=invocation.key, input_index=index), + spec=spec, + main_flow_artifacts=ArtifactSpecCollection(()), + invocation_sources=ArtifactSpecCollection(()), + metadata_available=True, + ) + for index, spec in enumerate((_FIRST, _SECOND)) + ) + invocation = invocation.with_artifact_input_edges(edges) + plan = CompiledStepPlan( + step_index=0, + step_type="FunctionStep", + step_name="MetadataBinding", + step_scope_id="metadata-binding", + axis_id="A01", + input_memory_type="numpy", + output_memory_type="numpy", + execution_group_scope=ComponentGroupScope.ungrouped(), + source_binding_plan=CompiledSourceBindingPlan.empty(), + ) + artifacts = ComponentArtifactPlans(inputs={edge.key: edge for edge in edges}, outputs={}) + initial_image = np.arange(6, dtype=np.float32).reshape(1, 2, 3) + scope = PatternGroupData( + matching_files=["input.tif"], + main_data_stack=initial_image, + context=SimpleNamespace(axis_id="A01"), + execution_plan=plan, + compiled_group=replace(pattern.default_group, invocations=(invocation,)), + artifacts=ComponentArtifactPlans(inputs={}, outputs={}), + runtime_plane_index=0, + runtime_plane_count=1, + ) + return FunctionCoreExecutor( + scope, invocation, artifacts, None, RuntimePlaneProjection.stack(), + initial_image, "numpy", + ) + + +def test_executor_retains_positional_layout_with_loaded_group_owner_and_frozen_slots(): + expected = ( + "group_data", "invocation", "artifacts", "group_key", "plane_projection", + "main_data_arg", "source_memory_type", + ) + declaration = fields(FunctionCoreExecutor) + assert tuple(field.name for field in declaration) == expected + assert tuple(inspect.signature(FunctionCoreExecutor).parameters) == expected + assert all(field.init and field.compare and field.repr and not field.kw_only for field in declaration) + assert all(field.default is MISSING and field.default_factory is MISSING for field in declaration) + executor = _executor() + assert not hasattr(executor, "__dict__") + with pytest.raises(FrozenInstanceError): + executor.source_memory_type = "other" + replaced = replace(executor, group_key="changed") + assert replaced.group_key == "changed" + assert replaced.group_data is executor.group_data + assert replaced.artifacts is executor.artifacts + + +def test_executor_pickle_retains_real_scope_edges_and_ordered_field_state(): + executor = _executor() + original_state = executor.__getstate__() + assert len(original_state) == len(fields(FunctionCoreExecutor)) + assert original_state[0] is executor.group_data + assert original_state[-1] == "numpy" + restored = pickle.loads(pickle.dumps(executor)) + assert type(restored) is FunctionCoreExecutor + assert restored.group_data.execution_plan.step_scope_id == "metadata-binding" + assert tuple(edge.spec.ref() for edge in restored.selected_artifact_input_edges) == (_FIRST.ref(), _SECOND.ref()) + assert all(isinstance(edge, CompiledMetadataArtifactInputEdgePlan) for edge in restored.selected_artifact_input_edges) + assert restored.invocation.kwargs_dict == executor.invocation.kwargs_dict + np.testing.assert_array_equal(restored.main_data_arg, executor.main_data_arg) + assert not hasattr(restored, "__dict__") + + +def test_metadata_edge_dispatch_keeps_live_compiled_arguments_and_declaration_order(monkeypatch): + executor = _executor() + + def unexpected_source_resolution(*args, **kwargs): + pytest.fail("metadata edge owns its compiled argument; no image-source lookup") + + monkeypatch.setattr(FunctionCoreExecutor, "declared_source_payload", unexpected_source_resolution) + kwargs = {} + loaded = executor.load_artifact_inputs(kwargs, executor.main_data_arg) + assert tuple(kwargs) == ("first", "second") + assert tuple(loaded) == (_FIRST.ref(), _SECOND.ref()) + assert kwargs["first"] is executor.invocation.kwargs_dict["first"] + kwargs["first"]["value"] = 7 + repeated = {} + executor.load_artifact_inputs(repeated, executor.main_data_arg) + assert repeated["first"] is kwargs["first"] + assert repeated["first"]["value"] == 7 + + +def test_missing_metadata_argument_error_stays_on_selected_edge_before_later_binding(): + executor = _executor() + invocation = replace(executor.invocation, kwargs=(("second", {"value": 2}),)) + executor = replace(executor, invocation=invocation) + kwargs = {} + with pytest.raises(ValueError, match="Metadata artifact .* has no compiled parameter value"): + executor.load_artifact_inputs(kwargs, executor.main_data_arg) + assert kwargs == {} + + +def test_missing_storage_error_remains_owned_by_executor(): + executor = _executor() + with pytest.raises(ValueError, match="storage-backed edge"): + executor.load_artifact_input("first", executor.selected_artifact_input_edges[0]) diff --git a/tests/unit/test_function_execution_lifecycle_anchors.py b/tests/unit/test_function_execution_lifecycle_anchors.py index 288c3eecc3..d6b2693dba 100644 --- a/tests/unit/test_function_execution_lifecycle_anchors.py +++ b/tests/unit/test_function_execution_lifecycle_anchors.py @@ -2,7 +2,9 @@ from __future__ import annotations +from pathlib import Path from types import SimpleNamespace +from unittest.mock import Mock import pytest @@ -21,16 +23,40 @@ from openhcs.core.pipeline.function_contracts import artifact_inputs from openhcs.core.pipeline.path_planner import PathPlanner, PathPlannerArtifactStage from openhcs.core.runtime_adapters import runtime_adapter +from openhcs.core.runtime_source_binding_cache import RuntimeSourceBindingContextCache +from openhcs.core.steps.function_output_manifest import _STEP_OUTPUT_MANIFESTS from openhcs.core.source_bindings import CompiledSourceBindingPlan, NamedSourceBinding from openhcs.core.step_dependencies import StepInputDependency -from openhcs.core.steps.function_execution import PatternGroups, StepAnchorPatternFilter +from openhcs.core.steps.function_execution import FunctionStepExecutor + + +def _anchor_executor( + *, plan, parser, output_manifest, source_workspace_projection_cache +): + executor = object.__new__(FunctionStepExecutor) + executor.plan = plan + executor.context = Mock( + plate_path=Path("."), + microscope_handler=SimpleNamespace( + parser=parser, + metadata_handler=SimpleNamespace( + source_workspace_metadata_document=lambda _path: None + ), + ), + filemanager=SimpleNamespace(exists=lambda *_args: False), + runtime_source_workspace_projection_cache=source_workspace_projection_cache, + runtime_source_binding_context_cache=RuntimeSourceBindingContextCache(), + ) + if output_manifest is not None: + _STEP_OUTPUT_MANIFESTS[executor.context] = output_manifest + return executor + -def _anchor_filter(plan: object, output_manifest: object) -> StepAnchorPatternFilter: - return StepAnchorPatternFilter( +def _anchor_filter(plan: object, output_manifest: object) -> FunctionStepExecutor: + return _anchor_executor( plan=plan, parser=object(), output_manifest=output_manifest, - source_workspace_authority=None, source_workspace_projection_cache=None, ) @@ -93,7 +119,7 @@ def consume_measurements(image, *, runtime): invocation = next(compiled_pattern.iter_invocations()) assert invocation.runtime_domain is RuntimeInvocationDomain.ARTIFACT_MANAGED assert all( - edge.storage_plan is not None and not edge.consumes_main_flow + edge.storage_plan is not None and not (edge.main_flow_projection is not None) for edge in invocation.artifact_input_edges ) @@ -120,17 +146,15 @@ def filter_to_producer_paths(self, _plan, paths, _parser): return [path for path in paths if "second" in path] manifest = ExactProducerManifest() - filtered = _anchor_filter(plan, manifest).filtered( - PatternGroups( - { - "1": ("first-anchor.tif",), - "2": ("second-anchor.tif",), - } - ) + filtered = _anchor_filter(plan, manifest)._filter_anchor_patterns( + { + "1": ("first-anchor.tif",), + "2": ("second-anchor.tif",), + } ) assert manifest.calls == 2 - assert filtered.groups == {"1": ("second-anchor.tif",)} + assert filtered == {"1": ("second-anchor.tif",)} def test_source_anchored_group_uses_exact_main_flow_producer_manifest() -> None: @@ -166,9 +190,9 @@ def producer_patterns_by_execution_group( return {None: patterns} manifest = ExactProducerManifest() - filtered = _anchor_filter(plan, manifest).filtered( - PatternGroups({None: ("unrelated-anchor.tif", "producer-anchor.tif")}) + filtered = _anchor_filter(plan, manifest)._filter_anchor_patterns( + {None: ("unrelated-anchor.tif", "producer-anchor.tif")} ) assert manifest.calls == 1 - assert filtered.groups == {None: ("producer-anchor.tif",)} + assert filtered == {None: ("producer-anchor.tif",)} diff --git a/tests/unit/test_function_invocation_callable_resolver.py b/tests/unit/test_function_invocation_callable_resolver.py deleted file mode 100644 index 0198cf7446..0000000000 --- a/tests/unit/test_function_invocation_callable_resolver.py +++ /dev/null @@ -1,62 +0,0 @@ -from openhcs.core.artifacts import ArtifactSpec, ImageArtifactType -from openhcs.core.callable_contract import ( - CallableContract, - CallableImportIdentity, - CallableMetadata, -) -from openhcs.core.function_patterns import ( - CompiledFunctionInvocation, - FunctionInvocationKey, -) -from openhcs.core.function_reference import ( - FunctionReference, - RegistryFunctionReference, -) -from openhcs.core.steps.function_runtime import FunctionInvocationCallableResolver - - -def _callable_contract_for_reference( - reference: FunctionReference, - output_spec: ArtifactSpec, -) -> CallableContract: - return CallableContract( - func=reference, - function_name=reference.function_name, - module_name=reference.original_module, - metadata=CallableMetadata( - input_memory_type="python", - output_memory_type="python", - artifact_outputs=(output_spec,), - ), - ) - - -def test_function_reference_cache_key_distinguishes_compiled_callable_contracts(): - reference = RegistryFunctionReference( - import_identity=CallableImportIdentity( - module_name="openhcs.processing.backends.cellprofiler", - function_name="image_math", - ), - composite_key="cellprofiler:image_math", - ) - first_contract = _callable_contract_for_reference( - reference, - ArtifactSpec.output("CombinedImage", ImageArtifactType), - ) - second_contract = _callable_contract_for_reference( - reference, - ArtifactSpec.output("SubtractedRed", ImageArtifactType), - ) - - first_invocation = CompiledFunctionInvocation( - key=FunctionInvocationKey.from_contract(first_contract, "default", 0), - contract=first_contract, - ) - second_invocation = CompiledFunctionInvocation( - key=FunctionInvocationKey.from_contract(second_contract, "default", 0), - contract=second_contract, - ) - - assert FunctionInvocationCallableResolver.cache_key( - first_invocation - ) != FunctionInvocationCallableResolver.cache_key(second_invocation) diff --git a/tests/unit/test_function_io.py b/tests/unit/test_function_io.py index b539238248..91ec46ff1f 100644 --- a/tests/unit/test_function_io.py +++ b/tests/unit/test_function_io.py @@ -31,7 +31,6 @@ ) from openhcs.core.source_workspace_projection import VirtualWorkspaceSourceProjection from openhcs.core.steps.function_io import ( - bulk_preload_step_images, get_all_image_paths, zarr_batch_layout, zarr_output_batch_layout, @@ -306,20 +305,16 @@ def test_bulk_preload_preserves_nested_virtual_workspace_paths(tmp_path: Path) - ] assert virtual_paths == expected_paths - bulk_preload_step_images( - workspace_root, - "A01", - Backend.VIRTUAL_WORKSPACE.value, - filemanager, - handler, - ) + SourceFileUniverse( + tuple(expected_paths), Backend.VIRTUAL_WORKSPACE, + ).load_images(filemanager) loaded = filemanager.load_batch(expected_paths, Backend.MEMORY.value) for payload, labels in zip(loaded, sources.values(), strict=True): np.testing.assert_array_equal(payload.data, labels) -def test_object_only_source_anchors_match_compiled_pattern_after_preload( +def test_object_only_source_anchors_match_compiled_pattern_after_loading( tmp_path: Path, ) -> None: source_root = tmp_path / "source" @@ -374,13 +369,10 @@ def test_object_only_source_anchors_match_compiled_pattern_after_preload( "A01_s001_w1_z001_t001.tif", "A01_s001_w2_z001_t001.tif", ) - bulk_preload_step_images( - workspace_root, - "A01", - Backend.VIRTUAL_WORKSPACE.value, - filemanager, - handler, - ) + SourceFileUniverse( + tuple(str(workspace_root / path) for path in materialization.artifact_mappings), + Backend.VIRTUAL_WORKSPACE, + ).load_images(filemanager) assert handler.path_list_from_pattern( workspace_root, @@ -464,13 +456,14 @@ def test_virtual_pipeline_source_universe_does_not_mix_physical_paths( source_projection=projection, ) + universe = request.source_universe() state = request.contribute_runtime_state( SourceUniverseRuntimeState(), universe, ) - assert state.pipeline_source_candidate_files == universe.files - assert not set(state.pipeline_source_candidate_files).intersection( + assert state.require_load_universe().files == universe.files + assert not set(state.require_load_universe().files).intersection( str(source_path) for source_path in source_paths ) @@ -534,13 +527,7 @@ def test_bulk_preload_loads_matlab_pixels_through_declared_vfs_backend( str(workspace_root / virtual_path) for virtual_path in materialization.plane_mappings ) - bulk_preload_step_images( - workspace_root, - "A01", - Backend.VIRTUAL_WORKSPACE.value, - filemanager, - SourceBindingsHandler(filemanager, source_bindings), - ) + SourceFileUniverse(virtual_paths, Backend.VIRTUAL_WORKSPACE).load_images(filemanager) loaded = filemanager.load_batch( list(virtual_paths), diff --git a/tests/unit/test_function_output_manifest_input_scope.py b/tests/unit/test_function_output_manifest_input_scope.py index d2b55b26fd..0613070e19 100644 --- a/tests/unit/test_function_output_manifest_input_scope.py +++ b/tests/unit/test_function_output_manifest_input_scope.py @@ -7,13 +7,21 @@ from openhcs.core.aligned_image_payload import AlignedImageSliceContext from openhcs.core.artifacts import ( ArtifactInputPlan, + ArtifactOutputPlan, ArtifactInputProjectionPlan, ArtifactSpec, ImageArtifactType, MeasurementsArtifactType, ObjectLabelsArtifactType, ) +from openhcs.core.compiled_step_plan import CompiledStepPlan +from openhcs.core.runtime_image_values import ImagePayloadMetadata +from openhcs.core.source_metadata import ( + SOURCE_VOXEL_SPACING_FIELD, + SourceVoxelSpacing, +) from openhcs.core.function_patterns import ( + MainFlowInputProjection, InvocationArtifactInputEdgePlan, InvocationArtifactInputProjectionKey, compile_function_pattern, @@ -22,22 +30,98 @@ from openhcs.core.step_dependencies import StepInputDependency from openhcs.core.steps.function_output_identity import FunctionOutputIdentity from openhcs.core.steps.function_output_manifest import ( - FunctionStepOutputProducerIdentityRequest, ProducedOutputSemantics, StepOutputManifestStore, ) from openhcs.microscopes.source_schema import SourceSchemaFilenameParser -def test_artifact_output_kind_is_declared_by_producer_identity_request() -> None: - request = FunctionStepOutputProducerIdentityRequest.from_artifact( - SimpleNamespace(), - SimpleNamespace(name="cells", artifact_type=ObjectLabelsArtifactType), +def test_artifact_output_kind_is_owned_by_original_compiled_plan() -> None: + plan = CompiledStepPlan( + step_index=3, + step_type="FunctionStep", + step_name="IdentifyCells", + step_scope_id="identify-cells", + pipeline_position=3, + axis_id="A01", ) + output = ArtifactOutputPlan( + name="cells", path="cells.pkl", artifact_type=ObjectLabelsArtifactType, + ) + identity = plan.producer_identity_for_artifact(output) + + assert identity.output_kind == CompiledStepPlan.ARTIFACT_OUTPUT_KIND + assert identity.output_key == identity.projection_key == "cells" + assert identity.artifact_kind == ObjectLabelsArtifactType.value + assert identity.step_name == "IdentifyCells" + assert identity.step_scope_id == "identify-cells" + assert identity.pipeline_position == 3 - assert request.output_kind == ( - FunctionStepOutputProducerIdentityRequest.ARTIFACT_OUTPUT_KIND + +def test_producer_identity_reads_current_plan_and_original_surface() -> None: + plan = CompiledStepPlan( + step_index=1, step_type="FunctionStep", step_name="Original", + step_scope_id="original", pipeline_position=1, axis_id="A01", ) + surface = AlignedImageSliceContext.main_flow("corrected") + original = plan.producer_identity_for_main_flow(surface) + plan.step_name = "Replacement" + plan.step_scope_id = "replacement" + plan.pipeline_position = 2 + replacement = plan.producer_identity_for_main_flow(surface) + + assert original.step_name == "Original" + assert original.step_scope_id == "original" + assert original.pipeline_position == 1 + assert replacement.step_name == "Replacement" + assert replacement.step_scope_id == "replacement" + assert replacement.pipeline_position == 2 + assert replacement.output_kind == surface.output_kind + assert replacement.output_key == surface.output_key + assert replacement.projection_key == surface.projection_key + assert replacement.artifact_kind == surface.artifact_kind + + +@pytest.mark.parametrize("saved_path", ("/saved/image.tif", "image.tif")) +def test_produced_occurrence_owns_memory_path_and_current_source_projection( + saved_path: str, +) -> None: + plan = CompiledStepPlan( + step_index=1, step_type="FunctionStep", step_name="Producer", axis_id="A01", + step_scope_id="producer", pipeline_position=1, output_dir=Path("/memory"), + ) + components = {"well": "A01", "channel": 2} + record = ProducedOutputSemantics( + producer_identity=plan.producer_identity_for_main_flow( + AlignedImageSliceContext.anonymous_main_flow() + ), + component_values=components, + filename_component_values={"well": "A01", "channel": 9}, + extension=".tif", source="test", output_path=saved_path, + relative_output_path="nested/image.tif", + ) + assert record.memory_path(plan) == ( + saved_path if saved_path.startswith("/") else "/memory/nested/image.tif" + ) + metadata = ImagePayloadMetadata( + source_component_metadata={"acquisition": "first", "channel": 1}, + source_voxel_spacing=SourceVoxelSpacing((0.5, 0.5)), + ) + original = record.source_metadata_for_projection(metadata, "/disk/output.tif") + assert original["channel"] == "2" + assert original["acquisition"] == "first" + assert original[SOURCE_VOXEL_SPACING_FIELD] == "0.5,0.5" + components["channel"] = 3 + metadata.source_component_metadata = {"acquisition": "second", "channel": 1} + current = record.source_metadata_for_projection(metadata, "/disk/output.tif") + assert current["channel"] == "3" + assert current["acquisition"] == "second" + assert original["channel"] == "2" + assert record.filename_values["channel"] == 9 + + metadata.source_component_metadata = {SOURCE_VOXEL_SPACING_FIELD: "1,1"} + with pytest.raises(RuntimeError, match="Conflicting source voxel spacing.*output.tif"): + record.source_metadata_for_projection(metadata, "/disk/output.tif") def _compiled_pattern_with_input_edges( @@ -124,7 +208,9 @@ def test_foreign_artifact_inputs_do_not_filter_lifecycle_producer( foreign_inputs: tuple[tuple[ArtifactSpec, str], ...], ) -> None: output_dir = tmp_path / "images" - producer = SimpleNamespace( + producer = CompiledStepPlan( + step_index=1, + step_type="FunctionStep", step_scope_id=dependency_scope, step_name="LifecycleProducer", pipeline_position=1, @@ -183,7 +269,9 @@ def test_compiled_main_flow_edge_selects_exact_producer_identity( tmp_path: Path, ) -> None: output_dir = tmp_path / "images" - producer = SimpleNamespace( + producer = CompiledStepPlan( + step_index=1, + step_type="FunctionStep", step_scope_id="align", step_name="Align", pipeline_position=1, @@ -208,7 +296,7 @@ def consume(image): spec=input_spec, storage_plan=None, projection=None, - consumes_main_flow=True, + main_flow_projection=MainFlowInputProjection.DECLARED_SOURCE_IMAGE, ), ) ) @@ -264,7 +352,9 @@ def test_storage_backed_primary_input_selects_exact_lifecycle_output( tmp_path: Path, ) -> None: output_dir = tmp_path / "images" - producer = SimpleNamespace( + producer = CompiledStepPlan( + step_index=1, + step_type="FunctionStep", step_scope_id="color_to_gray", step_name="ColorToGray", pipeline_position=1, @@ -361,7 +451,9 @@ def test_storage_backed_input_does_not_reclassify_lifecycle_output( tmp_path: Path, ) -> None: output_dir = tmp_path / "images" - producer = SimpleNamespace( + producer = CompiledStepPlan( + step_index=1, + step_type="FunctionStep", step_scope_id="artifact_producer", step_name="ArtifactProducer", pipeline_position=1, @@ -436,7 +528,9 @@ def test_same_scope_parameter_bound_input_does_not_select_lifecycle_output( parameter_name: str, ) -> None: output_dir = tmp_path / "images" - producer = SimpleNamespace( + producer = CompiledStepPlan( + step_index=1, + step_type="FunctionStep", step_scope_id="artifact_producer", step_name="ArtifactProducer", pipeline_position=1, diff --git a/tests/unit/test_function_outputs.py b/tests/unit/test_function_outputs.py index 3e2a76a8fc..db32b42fb1 100644 --- a/tests/unit/test_function_outputs.py +++ b/tests/unit/test_function_outputs.py @@ -1,5 +1,6 @@ import json from pathlib import Path +from dataclasses import replace from types import SimpleNamespace import numpy as np @@ -33,12 +34,13 @@ ) from openhcs.core.component_group_scope import RuntimeExecutionAxisScope from openhcs.core.components.parser_metaprogramming import FilenameParseResult -from openhcs.core.config import WellFilterMode +from openhcs.core.config import AnalysisConsolidationConfig, TiffConfig, WellFilterMode from openhcs.core.function_patterns import compile_function_pattern from openhcs.core.runtime_image_loading import ImagePayloadSourceMetadataContext from openhcs.core.runtime_image_values import ( ImageMetadataPayload, ImagePayloadMetadata, + image_payload_metadata, ) from openhcs.core.runtime_plane_projection import RuntimePlaneAxis from openhcs.core.source_image_provenance import ( @@ -52,29 +54,32 @@ SOURCE_VOXEL_SPACING_FIELD, SOURCE_VOXEL_SPACING_UNIT_FIELD, SourceVoxelSpacing, + SourceVoxelSpacingUnit, ) from openhcs.core.source_projection import SourceProjectionMetadataSerializer from openhcs.core.source_spatial_domain import SourceSpatialDomain from openhcs.core.step_dependencies import StepInputDependency from openhcs.core.steps.function_output_identity import ( FunctionOutputIdentity, - FunctionOutputIdentityAuthority, - FunctionOutputPathAuthority, FunctionOutputPathRequest, ) from openhcs.core.steps.function_output_manifest import ( ProducedOutputSemantics, step_output_manifest, ) +from openhcs.core.steps.function_artifact_materialization import ( + MaterializedRuntimeArtifact, + RuntimeArtifactMaterialization, +) from openhcs.core.steps.function_outputs import ( MaterializedImageOutputWriter, MemoryOutputWriter, OpenHCSMetadataWriter, - ProducedMemoryPathsAuthority, RuntimeArtifactMaterializationAuthority, MaterializedImageMetadataTarget, RuntimeArtifactMetadataTarget, StreamOutputsAuthority, + StreamOutputBatch, finalize_function_step_outputs, ) from openhcs.core.streaming_config_declarations import ViewerType @@ -87,6 +92,7 @@ MetadataWriteError, VirtualWorkspaceSourceProjectionEntries, ) +from openhcs.microscopes.imagexpress import ImageXpressFilenameParser from openhcs.microscopes.microscope_interfaces import MetadataHandler from openhcs.microscopes.openhcs import OpenHCSMetadataHandler from openhcs.microscopes.source_schema import SourceSchemaFilenameParser @@ -97,6 +103,7 @@ MaterializedFilenameIdentity, ) + @pytest.mark.parametrize("backend", [Backend.ZARR.value, "custom-array-store"]) def test_memory_output_writer_projects_runtime_image_payload_for_array_storage( backend, @@ -137,7 +144,9 @@ def test_function_step_metadata_follows_runtime_artifact_persistence( monkeypatch.setattr( authority, method_name, - lambda _context, _plan, event=event: events.append(event), + lambda _context, _plan, event=event, **_kwargs: (events.append(event), ())[ + 1 + ], ) finalize_function_step_outputs(context, plan) @@ -338,6 +347,8 @@ def context_stub(filemanager, parser=None): context.input_dir = Path("/tmp/plate/images") context.execution_runtime = SimpleNamespace(execution_axis_values=("A01",)) context.axis_id = "A01" + context.tiff_config = TiffConfig() + context.analysis_consolidation_config = AnalysisConsolidationConfig() context.step_axis_filters = {} return context @@ -424,6 +435,50 @@ def record_output_path( ) +def test_memory_output_writer_materializes_preserved_source_at_current_destination( + tmp_path, +): + source_dir = tmp_path / "source" + source_dir.mkdir() + source_path = source_dir / "A01_s1_w1.tif" + original_pixels = np.full((4, 5), 7, dtype=np.uint16) + tifffile.imwrite(source_path, original_pixels) + memory_pixels = np.full((4, 5), 3, dtype=np.uint16) + filemanager = FileManager( + { + Backend.DISK.value: DiskStorageBackend(), + Backend.MEMORY.value: MemoryStorageBackend(), + } + ) + filemanager.ensure_directory(source_dir, Backend.MEMORY.value) + filemanager.save(memory_pixels, str(source_path), Backend.MEMORY.value) + context = context_stub(filemanager) + source_plan = function_step_plan("Source", pipeline_position=0) + source_plan.output_dir = source_dir + record_output_path(context, source_plan, source_path) + + plan = function_step_plan("Preserve image", pipeline_position=1) + plan.output_plate_root = str(tmp_path / "output_plate") + plan.output_dir = Path(plan.output_plate_root) / "images" + plan.sub_dir = "images" + plan.analysis_results_dir = str(Path(plan.output_plate_root) / "results") + plan.write_backend = Backend.DISK.value + manifest = step_output_manifest(context) + (source_record,) = manifest.image_records_for(source_plan) + manifest.record_outputs(plan, (source_record.passed_through(plan),)) + + MemoryOutputWriter.write_if_needed(context, plan) + + destination = plan.output_dir / source_path.name + np.testing.assert_array_equal(tifffile.imread(destination), memory_pixels) + np.testing.assert_array_equal(tifffile.imread(source_path), original_pixels) + np.testing.assert_array_equal( + filemanager.load(str(source_path), Backend.MEMORY.value), memory_pixels + ) + (target,) = OpenHCSMetadataWriter.OutputTarget.for_execution(context, plan) + assert target.produced_projection_entries(context, plan) is not None + + def test_function_output_identity_preserves_non_axis_source_metadata() -> None: identity = FunctionOutputIdentity( component_values={"channel": "2", "site": "1"}, @@ -1368,13 +1423,16 @@ def test_image_persistence_skips_object_label_main_flow_payloads(): ), ) - assert ProducedMemoryPathsAuthority.paths(context, plan) == [] + assert step_output_manifest(context).image_records_for(plan) == () -def test_metadata_target_family_discovers_new_declaration_without_consumer_edits(tmp_path): +def test_metadata_target_family_discovers_new_declaration_without_consumer_edits( + tmp_path, +): registry = OpenHCSMetadataWriter.OutputTarget.__registry__ original_keys = set(registry) try: + class SupplementalImageMetadataTarget(OpenHCSMetadataWriter.OutputTarget): @classmethod def from_plan(cls, plan): @@ -1391,8 +1449,10 @@ def from_plan(cls, plan): context = context_stub(FileManagerStub({})) (target,) = OpenHCSMetadataWriter.OutputTarget.for_plan(plan) assert type(target) is SupplementalImageMetadataTarget - assert OpenHCSMetadataWriter.OutputTarget.for_execution(context, plan) == (target,) - assert target.produced_projection_metadata(context, plan) is None + assert OpenHCSMetadataWriter.OutputTarget.for_execution(context, plan) == ( + target, + ) + assert target.produced_projection_entries(context, plan) is None finally: for key in set(registry) - original_keys: del registry[key] @@ -1566,9 +1626,12 @@ def test_produced_projection_metadata_persists_typed_collapsed_semantics( ) assert "site" not in restored.source_component_metadata assert len(restored.source_provenance.represented_source_identities) == 2 - assert record["address"]["site"] == "1" + assert record["address"] is None + assert record["execution_scope"]["fixed_component_values"] == [ + ["channel", "1"], ["z_index", "1"], ["timepoint", "1"], + ] assert "site" not in record["source_metadata"] - assert subdirectory[FIELDS.SOURCE_METADATA]["images/A01_s1_w1.tif"]["site"] == "1" + assert "site" not in subdirectory[FIELDS.SOURCE_METADATA]["images/A01_s1_w1.tif"] def test_runtime_image_artifact_projects_persisted_source_binding( @@ -1638,13 +1701,16 @@ def test_runtime_image_artifact_projects_persisted_source_binding( ), outputs=lambda _plan, _context, **_kwargs: (output,), ) - monkeypatch.setattr( - "openhcs.core.steps.function_outputs.runtime_artifact_materializations", - lambda _plan, _context: (materialization,), + saved_artifacts = ( + MaterializedRuntimeArtifact( + outputs_by_backend={Backend.DISK.value: (output,)}, + materialization=materialization, + ), ) target = MaterializedImageMetadataTarget.from_plan(plan) assert target is not None + target = replace(target, artifact_materializations=saved_artifacts) [(projection, virtual_path)] = target.runtime_artifact_projection_paths( context, plan ) @@ -1661,7 +1727,10 @@ def test_runtime_image_artifact_projects_persisted_source_binding( assert projection.image_metadata is not None assert projection.image_metadata.source_dtype == "uint8" assert projection.ref == SourcePixelRef(Backend.DISK.value, virtual_path) - structured = target.produced_projection_metadata(context, plan) + structured = target.produced_projection_entries(context, plan) + structured = SourceProjectionMetadataSerializer.projection_fields( + structured.projection_paths + ) assert structured is not None [record] = structured[FIELDS.SOURCE_PROJECTION] assert record["virtual_path"] == virtual_path @@ -1755,9 +1824,11 @@ def test_runtime_multiplane_label_artifact_projects_persisted_source_binding( ), outputs=lambda _plan, _context, **_kwargs: (output,), ) - monkeypatch.setattr( - "openhcs.core.steps.function_outputs.runtime_artifact_materializations", - lambda _plan, _context: (materialization,), + saved_artifacts = ( + MaterializedRuntimeArtifact( + outputs_by_backend={Backend.DISK.value: (output,)}, + materialization=materialization, + ), ) output_plan = ArtifactOutputPlan( @@ -1769,6 +1840,7 @@ def test_runtime_multiplane_label_artifact_projects_persisted_source_binding( plan.artifact_outputs = {output_plan.ref(): output_plan} target = RuntimeArtifactMetadataTarget.from_plan(plan) assert target is not None + target = replace(target, artifact_materializations=saved_artifacts) [(projection, virtual_path)] = target.runtime_artifact_projection_paths( context, plan ) @@ -1788,7 +1860,10 @@ def test_runtime_multiplane_label_artifact_projects_persisted_source_binding( ] for index in range(2) ) == ("1", "2") - structured = target.produced_projection_metadata(context, plan) + structured = target.produced_projection_entries(context, plan) + structured = SourceProjectionMetadataSerializer.projection_fields( + structured.projection_paths + ) assert structured is not None [record] = structured[FIELDS.SOURCE_PROJECTION] assert record["artifact_kind"] == ObjectLabelsArtifactType.value @@ -1933,10 +2008,12 @@ def test_produced_address_publication_never_parses_generated_filenames( output_dir = plate_root / "images" output_dir.mkdir(parents=True) parser = SourceSchemaFilenameParser() - filemanager = FileManager({ - Backend.DISK.value: DiskStorageBackend(), - Backend.MEMORY.value: MemoryStorageBackend(), - }) + filemanager = FileManager( + { + Backend.DISK.value: DiskStorageBackend(), + Backend.MEMORY.value: MemoryStorageBackend(), + } + ) context = context_stub(filemanager, parser=parser) context.metadata_cache = { AllComponents.WELL: {well: None, "not-produced": None}, @@ -1962,16 +2039,21 @@ def test_produced_address_publication_never_parses_generated_filenames( metadata = ImagePayloadMetadata( source_path=source_path, source_component_metadata={ - "well": well, "site": 1, "channel": 1, - "z_index": z_index, "timepoint": 1, + "well": well, + "site": 1, + "channel": 1, + "z_index": z_index, + "timepoint": 1, }, source_voxel_spacing=SourceVoxelSpacing((0.5, 0.5)), ) - identity = FunctionOutputIdentityAuthority.identity_from_metadata(parser, metadata) + identity = FunctionOutputIdentity.from_metadata( + parser, metadata + ) assert identity is not None assert identity.extension == extension identity = identity.with_filename_qualifier("centre_dots") - filename = FunctionOutputPathAuthority.filename_for_identity(parser, identity) + filename = identity.filename(parser) assert filename == f"{well}_s001_w1_z{z_index:03d}_t001_centre_dots{extension}" # Readback is an external boundary; publication below must not parse. parsed = parser.parse_filename(filename) @@ -1980,14 +2062,20 @@ def test_produced_address_publication_never_parses_generated_filenames( assert parsed.value_for(AllComponents.WELL) == well path = output_dir / filename tifffile.imwrite(path, pixels) - filemanager.save(metadata.payload_with(pixels, None), str(path), Backend.MEMORY.value) - records.append(ProducedOutputSemantics.from_output( - plan, path, identity, - output_context=AlignedImageSliceContext.main_flow( - output_key="centre_dots", artifact_kind=ImageArtifactType.value - ), - image_metadata=metadata, - )) + filemanager.save( + metadata.payload_with(pixels, None), str(path), Backend.MEMORY.value + ) + records.append( + ProducedOutputSemantics.from_output( + plan, + path, + identity, + output_context=AlignedImageSliceContext.main_flow( + output_key="centre_dots", artifact_kind=ImageArtifactType.value + ), + image_metadata=metadata, + ) + ) paths.append(f"images/{filename}") step_output_manifest(context).record_outputs(plan, records) @@ -2029,11 +2117,15 @@ def reject_generated_path_parse(_filename): removed = paths[0] (plate_root / removed).unlink() OpenHCSMetadataWriter.finalize_completed_plate({well: context}) - reconciled = json.loads(metadata_path.read_text())[FIELDS.SUBDIRECTORIES]["images"] + reconciled = json.loads(metadata_path.read_text())[FIELDS.SUBDIRECTORIES][ + "images" + ] assert set(reconciled[FIELDS.IMAGE_FILES]) == set(paths[1:]) assert removed not in reconciled[FIELDS.WORKSPACE_MAPPING] assert removed not in reconciled[FIELDS.SOURCE_METADATA] - assert {record["virtual_path"] for record in reconciled[FIELDS.SOURCE_PROJECTION]} == set(paths[1:]) + assert { + record["virtual_path"] for record in reconciled[FIELDS.SOURCE_PROJECTION] + } == set(paths[1:]) assert set(reconciled["z_indexes"]) == {str(z) for z in z_values[1:]} @@ -2044,8 +2136,7 @@ def test_produced_stacked_dotted_identity_keeps_declared_extension( ): parser = SourceSchemaFilenameParser() source_paths = tuple( - f"/source/{well}_s001_w1_z{z:03d}_t001{extension}" - for z in (3, 1, 2) + f"/source/{well}_s001_w1_z{z:03d}_t001{extension}" for z in (3, 1, 2) ) metadata = ImagePayloadMetadata( source_image_provenance_planes=SourceImageProvenancePlanes.from_components( @@ -2055,18 +2146,18 @@ def test_produced_stacked_dotted_identity_keeps_declared_extension( request = FunctionOutputPathRequest( parser=parser, output_dir=tmp_path, - output_payload=metadata.payload_with(np.zeros((3, 4, 5), dtype=np.uint16), None), + output_payload=metadata.payload_with( + np.zeros((3, 4, 5), dtype=np.uint16), None + ), input_path=Path(source_paths[0]).name, variable_components=(VariableComponents.Z_INDEX,), ) - identity = FunctionOutputIdentityAuthority.identity(request) + identity = FunctionOutputIdentity.from_request(request) assert identity.extension == extension assert "z_index" not in identity.component_values assert identity.filename_address.value_for(AllComponents.Z_INDEX) == "3" assert identity.filename_address.value_for(AllComponents.WELL) == well - filename = FunctionOutputPathAuthority.filename_for_identity( - parser, identity.with_filename_qualifier("centre_dots") - ) + filename = identity.with_filename_qualifier("centre_dots").filename(parser) assert filename == f"{well}_s001_w1_z003_t001_centre_dots{extension}" @@ -2176,7 +2267,9 @@ def test_runtime_image_metadata_target_requires_persisted_images(tmp_path, conte if contents == "tables": (directory / "measurements.csv").write_text("ObjectNumber,Area\n1,4\n") else: - tifffile.imwrite(directory / "A01_s001_w2_z001_t001.tif", np.ones((2, 2), dtype=np.uint8)) + tifffile.imwrite( + directory / "A01_s001_w2_z001_t001.tif", np.ones((2, 2), dtype=np.uint8) + ) context = context_stub(FileManager({Backend.DISK.value: DiskStorageBackend()})) plan = function_step_plan("SaveImages") plan.write_backend = Backend.MEMORY.value @@ -2223,7 +2316,32 @@ def test_runtime_image_metadata_target_requires_persisted_images(tmp_path, conte target = RuntimeArtifactMetadataTarget.from_plan(plan) assert target is not None assert target.output_dir == directory - selected = OpenHCSMetadataWriter.OutputTarget.for_execution(context, plan) + saved_artifacts = () + if contents == "images": + record = context.runtime_value_store.values()[0] + materialization = RuntimeArtifactMaterialization.from_record( + output_plan=output_plan, + record=record, + plan=plan, + context=context, + ) + saved_artifacts = ( + MaterializedRuntimeArtifact( + outputs_by_backend={ + Backend.DISK.value: ( + Output.from_metadata( + path=str(directory / "A01_s001_w2_z001_t001.tif"), + content=record.data, + metadata=image_payload_metadata(record.data), + ), + ) + }, + materialization=materialization, + ), + ) + selected = OpenHCSMetadataWriter.OutputTarget.for_execution( + context, plan, artifact_materializations=saved_artifacts + ) if contents == "images": assert selected == (target,) else: @@ -2295,8 +2413,12 @@ def test_declared_image_destinations_publish_and_reconcile_after_value_cleanup( path=output_plan.path, backend=Backend.MEMORY.value, ) - RuntimeArtifactMaterializationAuthority.materialize(context, plan) - OpenHCSMetadataWriter.write(context, plan) + materializations = RuntimeArtifactMaterializationAuthority.materialize( + context, plan + ) + OpenHCSMetadataWriter.write( + context, plan, artifact_materializations=materializations + ) context.runtime_value_store.clear() if stray_image: tifffile.imwrite(tmp_path / "images/review/unowned.tif", pixels) @@ -2319,3 +2441,408 @@ def test_declared_image_destinations_publish_and_reconcile_after_value_cleanup( assert projection.component_value(AllComponents.CHANNEL) == "2" assert projection.source_metadata["site"] == "1" np.testing.assert_array_equal(tifffile.imread(tmp_path / path), pixels) + + +@pytest.mark.parametrize("with_raster", [False, True]) +def test_actual_array_exports_only_publish_declared_raster_inventory( + tmp_path, with_raster +): + """A saved NumPy array is an actual output, without being a raster inventory.""" + filemanager = FileManager( + { + Backend.DISK.value: DiskStorageBackend(), + Backend.MEMORY.value: MemoryStorageBackend(), + } + ) + context = context_stub(filemanager, parser=SourceSchemaFilenameParser()) + context.runtime_value_store = RuntimeValueStore() + context.metadata_cache = {} + context.tiff_config = None + plan = function_step_plan("Independent array and raster exports") + plan.streaming_configs = {} + plan.write_backend = Backend.MEMORY.value + plan.output_plate_root = str(tmp_path) + plan.output_dir = tmp_path / "images" + plan.sub_dir = "images" + plan.analysis_results_dir = str(tmp_path / "results") + plan.create_openhcs_metadata = True + plan.runtime_artifact_materialization = RuntimeArtifactMaterializationPlan( + persistent_enabled=True, + persistent_backend=Backend.DISK.value, + ) + context.step_plans = {plan.step_index: plan} + pixels = np.arange(20, dtype=np.float32).reshape(4, 5) / 7 + payload = ImageMetadataPayload( + pixels, + ImagePayloadMetadata( + source_component_metadata={ + "well": "A01", + "site": "1", + "channel": "2", + "z_index": "1", + "timepoint": "1", + }, + source_dtype="float32", + source_voxel_spacing=SourceVoxelSpacing( + (0.65, 0.65), SourceVoxelSpacingUnit.MICROMETERS + ), + ), + ) + declarations = [("NumericField", "exports/Illum.npy")] + if with_raster: + declarations.append(("RasterField", "exports/A01_s001_w2_z001_t001.tif")) + for name, relative_path in declarations: + output_plan = ArtifactOutputPlan( + name=name, + path=f"/memory/{name}.pkl", + artifact_type=ImageArtifactType, + materialization=MaterializationSpec( + ImageFileOptions( + filename_suffix=Path(relative_path).suffix, + relative_path_template=relative_path, + ) + ), + ) + plan.artifact_outputs[output_plan.ref()] = output_plan + context.runtime_value_store.record( + RuntimeValue.normalize(output_plan, payload, axis_id="A01"), + path=output_plan.path, + backend=Backend.MEMORY.value, + ) + + materializations = RuntimeArtifactMaterializationAuthority.materialize( + context, plan + ) + saved_outputs = tuple( + output + for artifact in materializations + for output in artifact.outputs_for_backend(Backend.DISK.value) + ) + expected_paths = { + tmp_path / "images" / relative_path for _name, relative_path in declarations + } + assert {Path(output.path) for output in saved_outputs} == expected_paths + assert all(path.is_file() for path in expected_paths) + np.testing.assert_array_equal( + np.load(tmp_path / "images/exports/Illum.npy", allow_pickle=False), pixels + ) + observed_locations = tuple( + location + for artifact in materializations + for locations in ( + artifact.observation(plan, context).materialized_locations_by_address.values() + ) + for location in locations + ) + assert {Path(location.path) for location in observed_locations} == expected_paths + + OpenHCSMetadataWriter.write( + context, plan, artifact_materializations=materializations + ) + context.runtime_value_store.clear() + OpenHCSMetadataWriter.finalize_completed_plate({"A01": context}) + metadata_path = tmp_path / "openhcs_metadata.json" + subdirectories = json.loads(metadata_path.read_text())[FIELDS.SUBDIRECTORIES] + assert set(subdirectories) == {"images/exports"} + subdirectory = subdirectories["images/exports"] + assert subdirectory[SourceProjectionMetadataSerializer.RESULTS_DIR_FIELD] == ( + "images/exports" + ) + if not with_raster: + assert subdirectory[FIELDS.IMAGE_FILES] == [] + assert ( + VirtualWorkspaceSourceProjectionEntries.from_subdirectory( + subdirectory + ).entries + == {} + ) + return + np.testing.assert_array_equal( + tifffile.imread(tmp_path / "images/exports/A01_s001_w2_z001_t001.tif"), pixels + ) + assert subdirectory[FIELDS.IMAGE_FILES] == [ + "images/exports/A01_s001_w2_z001_t001.tif" + ] + entries = VirtualWorkspaceSourceProjectionEntries.from_subdirectory( + subdirectory + ).entries + raster = entries["images/exports/A01_s001_w2_z001_t001.tif"] + assert raster.source_alias == "RasterField" + assert raster.image_metadata.source_voxel_spacing.values_zyx == (0.65, 0.65) + assert ( + raster.image_metadata.source_voxel_spacing.native_coordinate_unit + == "micrometer" + ) + + +def _stream_batch_sources(projections): + plan = function_step_plan("StreamOwned") + arrays = [np.full((2, 3), index, dtype=np.float32) for index in range(len(projections))] + paths = [str(plan.output_dir / f"A01_s1_w{index}.tif") for index in range(len(projections))] + records = tuple( + ProducedOutputSemantics.from_output( + plan, + path, + FunctionOutputIdentity( + component_values={"well": "A01", "site": "1", "channel": str(index)}, + extension=".tif", + source="stream source", + ), + output_context=AlignedImageSliceContext.main_flow( + output_key=f"image-{index}", projection_key=projection, + artifact_kind=ImageArtifactType.value, + ), + ) + for index, (path, projection) in enumerate(zip(paths, projections, strict=True)) + ) + return arrays, paths, records + + +def test_stream_batch_owns_correlated_projection_order_and_frozen_input_lists(monkeypatch): + arrays, paths, records = _stream_batch_sources(("second", "first", "second", "first")) + expected_arrays, expected_paths = tuple(arrays), tuple(paths) + observed = [] + original_project = StreamOutputBatch.project_item + + def project(request): + observed.append(request.source_description) + arrays.clear() + paths.clear() + return original_project(request) + + monkeypatch.setattr(StreamOutputBatch, "project_item", staticmethod(project)) + batches = StreamOutputBatch.from_projection_groups( + parser=ImageXpressFilenameParser(), payloads=arrays, paths=paths, + produced_outputs=records, + ) + assert observed == [expected_paths[index] for index in (0, 2, 1, 3)] + assert len(batches) == 2 + assert [item.output_path for batch in batches for item in batch.items] == observed + assert [item.producer_identity for batch in batches for item in batch.items] == [ + records[index].producer_identity for index in (0, 2, 1, 3) + ] + for item, index in zip( + (item for batch in batches for item in batch.items), (0, 2, 1, 3), strict=True, + ): + assert item.data is expected_arrays[index] + assert item.source_component_metadata["channel"] == str(index) + + +def test_stream_batch_keeps_first_projection_error_and_prior_callback_effects(monkeypatch): + arrays, paths, records = _stream_batch_sources(("first", "second", "first", "second")) + observed = [] + failure = ValueError("actual projector failure") + original_project = StreamOutputBatch.project_item + + def project(request): + observed.append(request.source_description) + if request.source_description == paths[1]: + raise failure + return original_project(request) + + monkeypatch.setattr(StreamOutputBatch, "project_item", staticmethod(project)) + with pytest.raises(ValueError) as raised: + StreamOutputBatch.from_projection_groups( + parser=ImageXpressFilenameParser(), payloads=arrays, paths=paths, + produced_outputs=records, + ) + assert raised.value is failure + assert observed == [paths[index] for index in (0, 2, 1)] + + +def test_stream_batch_validates_cardinality_and_routes_before_projecting(monkeypatch): + arrays, paths, records = _stream_batch_sources(("first", "second")) + + def forbidden_project(request): + raise AssertionError("invalid inputs reached projection") + + monkeypatch.setattr(StreamOutputBatch, "project_item", staticmethod(forbidden_project)) + parser = ImageXpressFilenameParser() + with pytest.raises(ValueError, match="payload/path cardinality mismatch"): + StreamOutputBatch.from_projection_groups( + parser=parser, payloads=arrays, paths=paths[:1], produced_outputs=(), + ) + with pytest.raises(ValueError, match="payload/output-record cardinality mismatch"): + StreamOutputBatch.from_projection_groups( + parser=parser, payloads=arrays, paths=paths, produced_outputs=records[:1], + ) + with pytest.raises(ValueError, match="at least one produced output record"): + StreamOutputBatch.from_projection_groups( + parser=parser, payloads=(), paths=(), produced_outputs=(), + ) + with pytest.raises(ValueError, match="cannot mix producer projections"): + StreamOutputBatch.from_projection( + parser=parser, payloads=arrays, paths=paths, produced_outputs=records, + ) + + +@pytest.mark.parametrize("with_artifact", (False, True)) +def test_whole_volume_checkpoint_publication_retains_exact_producer_scope( + tmp_path, with_artifact +): + from openhcs.core.source_spatial_domain import VolumeSourceSpatialDomain + from openhcs.core.source_projection import SourceArtifactProjection + + plate_root = tmp_path / "plate" + output_dir = plate_root / "images" + output_dir.mkdir(parents=True) + path = output_dir / "A01_s001_w2_z001_t001.tif" + pixels = np.arange(5 * 6 * 7, dtype=np.uint16).reshape(5, 6, 7) + components = tuple( + { + "well": "A01", + "site": 1, + "channel": 2, + "z_index": z, + "timepoint": 1, + "extension": ".tif", + } + for z in range(1, 6) + ) + metadata = ImagePayloadMetadata( + source_image_names=("DNA",), + plane_axis=RuntimePlaneAxis.RUNTIME_SLICE, + source_spatial_domain=VolumeSourceSpatialDomain( + source_depth=5, + origin_yx=(0, 0), + source_shape_yx=(6, 7), + ), + source_component_metadata={ + "well": "A01", + "site": 1, + "channel": 2, + "timepoint": 1, + "extension": ".tif", + }, + source_image_provenance_planes=SourceImageProvenancePlanes.from_components( + paths=tuple(f"/input/A01_s001_w2_z{z:03d}_t001.tif" for z in range(1, 6)), + component_metadata=components, + ), + ) + metadata = metadata.with_source_provenance( + metadata.source_provenance.with_derived_source_image_names(("DNA",)) + ) + incomplete = metadata.replace_fields( + source_component_metadata={ + key: value + for key, value in metadata.source_component_metadata.items() + if key != "timepoint" + } + ) + contextualized = incomplete.with_source_context_from( + ImagePayloadMetadata(source_component_metadata=components[0]) + ) + assert str(contextualized.source_component_metadata["timepoint"]) == "1" + assert "z_index" not in contextualized.source_component_metadata + assert contextualized.source_image_provenance_planes == metadata.source_image_provenance_planes + manager = FileManager( + {"disk": DiskStorageBackend(), "memory": MemoryStorageBackend()} + ) + manager.ensure_directory(output_dir, "memory") + manager.save(metadata.payload_with(pixels), str(path), "memory") + context = context_stub(manager, parser=SourceSchemaFilenameParser()) + plan = function_step_plan( + "Volume checkpoint", variable_components=(VariableComponents.Z_INDEX,) + ) + plan.output_dir = output_dir + plan.output_plate_root = str(plate_root) + plan.sub_dir = "images" + plan.analysis_results_dir = str(plate_root / "results") + plan.write_backend = "disk" + identity = FunctionOutputIdentity( + component_values={"well": "A01", "site": 1, "channel": 2, "timepoint": 1}, + filename_component_values=components[0], + extension=".tif", + source="declared volume", + ) + record_output_path( + context, + plan, + str(path), + image_metadata=metadata, + identity=identity, + output_context=AlignedImageSliceContext.main_flow( + output_key="DNA", artifact_kind=ImageArtifactType.value + ), + ) + MemoryOutputWriter.write_if_needed(context, plan) + np.testing.assert_array_equal(tifffile.imread(path), pixels) + (target,) = OpenHCSMetadataWriter.OutputTarget.for_execution(context, plan) + materializations = () + if with_artifact: + plan.streaming_configs = {} + context.runtime_value_store = RuntimeValueStore() + plan.runtime_artifact_materialization = RuntimeArtifactMaterializationPlan( + persistent_enabled=True, + persistent_backend=Backend.DISK.value, + ) + output_plan = ArtifactOutputPlan( + name="DNA", + path="/memory/DNA.pkl", + artifact_type=ImageArtifactType, + producer_step_scope_id=plan.step_scope_id, + materialization=MaterializationSpec( + ImageFileOptions(relative_path_template=path.name) + ), + ) + plan.artifact_outputs[output_plan.ref()] = output_plan + context.runtime_value_store.record( + RuntimeValue.normalize_for_execution_scope( + output_plan, + metadata.payload_with(pixels), + execution_scope=RuntimeExecutionAxisScope.from_raw( + "A01", + component=None, + value=None, + fixed_component_values=( + (AllComponents.CHANNEL, "2"), + (AllComponents.SITE, "1"), + (AllComponents.TIMEPOINT, "1"), + ), + ), + ), + path=output_plan.path, + backend=Backend.MEMORY.value, + ) + materializations = RuntimeArtifactMaterializationAuthority.materialize( + context, plan + ) + assert { + Path(output.path) + for artifact in materializations + for output in artifact.outputs_for_backend(Backend.DISK.value) + } == {path} + target = replace(target, artifact_materializations=materializations) + entries = target.produced_projection_entries(context, plan) + assert entries is not None + (projection,) = entries.entries.values() + assert isinstance(projection, SourceArtifactProjection) + assert projection.address is None + assert projection.source_alias == "DNA" + assert ( + projection.execution_scope.value_text_for_component(AllComponents.CHANNEL) + == "2" + ) + assert ( + projection.execution_scope.value_text_for_component(AllComponents.SITE) == "1" + ) + assert ( + projection.execution_scope.value_text_for_component(AllComponents.TIMEPOINT) + == "1" + ) + assert ( + projection.execution_scope.value_text_for_component(AllComponents.Z_INDEX) + is None + ) + assert ( + projection.image_metadata.source_image_provenance_planes.component_metadata + == metadata.source_image_provenance_planes.component_metadata + ) + document = {} + entries.merge_into_subdirectory(document) + decoded = VirtualWorkspaceSourceProjectionEntries.from_subdirectory( + json.loads(json.dumps(document)) + ) + restored = decoded.entries["images/A01_s001_w2_z001_t001.tif"] + assert restored.execution_scope == projection.execution_scope + assert restored.image_metadata.source_spatial_domain.source_depth == 5 diff --git a/tests/unit/test_function_patterns.py b/tests/unit/test_function_patterns.py index 831d714196..f3dc771ba0 100644 --- a/tests/unit/test_function_patterns.py +++ b/tests/unit/test_function_patterns.py @@ -27,6 +27,7 @@ from openhcs.core.context.processing_context import ProcessingContext from openhcs.core.function_contract_metadata import FunctionContractAttribute from openhcs.core.function_patterns import ( + MainFlowInputProjection, FunctionInvocationKey, InvocationArtifactInputEdgePlan, InvocationArtifactInputProjectionKey, @@ -632,7 +633,7 @@ def consume_source(image): spec=source_spec, storage_plan=None, projection=None, - consumes_main_flow=True, + main_flow_projection=MainFlowInputProjection.DECLARED_SOURCE_IMAGE, ) invocation = invocation.with_artifact_input_edges((edge,)) group = replace(compiled.default_group, invocations=(invocation,)) @@ -669,7 +670,7 @@ def consume_source(image): spec=source, storage_plan=None, projection=None, - consumes_main_flow=False, + ) group = replace( compiled.default_group, @@ -727,7 +728,7 @@ def measure_channels(image, *, runtime): spec=source, storage_plan=None, projection=None, - consumes_main_flow=True, + main_flow_projection=MainFlowInputProjection.DECLARED_SOURCE_IMAGE, ) for edge_key, source in zip( InvocationArtifactInputProjectionKey.for_input_count( @@ -771,8 +772,6 @@ def measure_channels(image, *, runtime): replace( edge, storage_plan=storage_plans[edge.spec.ref()], - consumes_main_flow=False, - main_flow_projection=None, projection=ArtifactInputProjectionPlan( invocation_scope=execution_scope, producer_selection_scope=storage_plans[edge.spec.ref()].producer_group_scope(), @@ -854,7 +853,7 @@ def measure_with_aggregate(image, *, runtime): spec=source, storage_plan=None, projection=None, - consumes_main_flow=True, + main_flow_projection=MainFlowInputProjection.DECLARED_SOURCE_IMAGE, ) invocation = invocation.with_artifact_input_edges((edge,)) @@ -1755,3 +1754,47 @@ def needs_grid(image, grid_dimensions): pattern, {"grid_dimensions": (3, 4)}, ) == (needs_grid, {"grid_dimensions": (3, 4), "sigma": 2}) + + +def test_artifact_binding_owner_does_not_erase_undeclared_raw_image_demand(): + source = ArtifactSpec.input("Source", ImageArtifactType) + + @artifact_inputs(source) + @runtime_adapter("runtime", lambda _request: object(), manages_artifact_inputs=True) + def consume(image, *, runtime): + return image + + compiled = compile_function_pattern(consume, {}, {}) + invocation = compiled.default_group.invocations[0] + edge = exact_input_edge( + invocation, input_index=0, spec=source, + storage_plan=ArtifactInputPlan(source.name, "/memory/source", artifact_type=ImageArtifactType), + parameter_name=None, + ) + invocation = invocation.with_artifact_input_edges((edge,)) + group = replace(compiled.default_group, invocations=(invocation,)) + assert invocation.adapter_manages_artifact_inputs + assert invocation.contract.accepts_implicit_main_flow_input + assert group.stored_primary_input_edges_for_component(ComponentGroupScope.ungrouped(), None) is None + primary = replace(edge, main_flow_projection=MainFlowInputProjection.COMPLETE_PAYLOAD) + group = replace(group, invocations=(invocation.with_artifact_input_edges((primary,)),)) + assert group.stored_primary_input_edges_for_component(ComponentGroupScope.ungrouped(), None) == (primary,) + + +def test_table_context_cannot_stand_in_for_an_image_cohort(): + table = ArtifactSpec.input("Measurements", MeasurementsArtifactType) + + @artifact_inputs(table) + @runtime_adapter("runtime", lambda _request: object(), manages_artifact_inputs=True) + def consume(*, runtime): + return None + + compiled = compile_function_pattern(consume, {}, {}) + invocation = compiled.default_group.invocations[0] + edge = exact_input_edge( + invocation, input_index=0, spec=table, + storage_plan=ArtifactInputPlan(table.name, "/memory/table", artifact_type=MeasurementsArtifactType), + parameter_name=None, + ) + group = replace(compiled.default_group, invocations=(invocation.with_artifact_input_edges((edge,)),)) + assert group.stored_primary_input_edges_for_component(ComponentGroupScope.ungrouped(), None) is None diff --git a/tests/unit/test_function_runtime_source_projection.py b/tests/unit/test_function_runtime_source_projection.py index d031997b88..fab4092caf 100644 --- a/tests/unit/test_function_runtime_source_projection.py +++ b/tests/unit/test_function_runtime_source_projection.py @@ -2,13 +2,19 @@ from dataclasses import replace from pathlib import Path from types import SimpleNamespace +from unittest.mock import Mock import numpy as np import pytest from objectstate.global_config import GlobalContextValues from polystore.virtual_workspace import SourcePixelRef -from openhcs.constants.constants import AllComponents, GroupBy, VariableComponents +from openhcs.constants.constants import ( + AllComponents, + Backend, + GroupBy, + VariableComponents, +) from openhcs.core.aligned_image_payload import ( AlignedImageSliceContext, ImagePayloadBundleContext, @@ -33,6 +39,7 @@ ) from openhcs.core.component_set import ComponentSet from openhcs.core.function_patterns import ( + MainFlowInputProjection, InvocationArtifactInputEdgePlan, InvocationArtifactInputProjectionKey, RuntimeInvocationDomain, @@ -57,6 +64,8 @@ from openhcs.core.runtime_plane_projection import RuntimePlaneAxis from openhcs.core.runtime_stack_cache import RuntimeImageStackCache from openhcs.core.source_binding_selection import SourcePatternResolutionContext +from openhcs.core.runtime_source_binding_cache import RuntimeSourceBindingContextCache +from openhcs.core.steps.function_output_manifest import _STEP_OUTPUT_MANIFESTS from openhcs.core.source_bindings import ( SOURCE_BINDING_ALIAS_METADATA_FIELD, CompiledSourceBindingPlan, @@ -65,7 +74,6 @@ SourceBindingMatchMethod, SourceBindingMatchPlan, SourceBindingOrigin, - SourceBindingRuntimeContext, SourceFilterClause, SourceFilterMatchType, SourceFilterSubject, @@ -91,14 +99,10 @@ from openhcs.core.step_dependencies import StepInputDependency from openhcs.core.steps.function_execution import ( FunctionStepExecutor, - PatternGroups, - StepAnchorPatternFilter, ) from openhcs.core.steps.function_output_identity import ( FunctionOutputIdentity, - FunctionOutputIdentityAuthority, FunctionOutputIdentityCache, - FunctionOutputPathAuthority, FunctionOutputPathRequest, ) from openhcs.core.steps.function_output_manifest import ( @@ -111,8 +115,32 @@ from openhcs.microscopes.source_schema import SourceSchemaFilenameParser +def _anchor_executor( + *, plan, parser, output_manifest, source_workspace_projection_cache +): + executor = object.__new__(FunctionStepExecutor) + executor.plan = plan + executor.context = Mock( + plate_path=Path("."), + microscope_handler=SimpleNamespace( + parser=parser, + metadata_handler=SimpleNamespace( + source_workspace_metadata_document=lambda _path: None + ), + ), + filemanager=SimpleNamespace(exists=lambda *_args: False), + runtime_source_workspace_projection_cache=source_workspace_projection_cache, + runtime_source_binding_context_cache=RuntimeSourceBindingContextCache(), + ) + if output_manifest is not None: + _STEP_OUTPUT_MANIFESTS[executor.context] = output_manifest + return executor + + def _source_manifest(plan, paths_and_components): - producer = SimpleNamespace( + producer = CompiledStepPlan( + step_index=plan.main_input_dependency.source_step_index, + step_type="FunctionStep", step_scope_id=plan.main_input_dependency.source_step_scope_id, step_name="producer", pipeline_position=plan.main_input_dependency.source_step_index, @@ -532,6 +560,69 @@ def resolve_address(backend_address, backend, *, base_path): assert metadata.source_image_names == ("OrigBlue",) +def test_physical_source_loading_preserves_tiff_calibration_and_live_buffers( + tmp_path: Path, +) -> None: + import tifffile + from polystore.base import ensure_storage_registry, storage_registry + from polystore.filemanager import FileManager + + from openhcs.constants.constants import Backend + from openhcs.core.runtime_image_values import image_payload_mask + from openhcs.core.runtime_source_binding_cache import RuntimeSourceBindingContextCache + from openhcs.core.steps.function_runtime import PatternGroupRuntime + from openhcs.microscopes.source_schema import SourceSchemaFilenameParser + + source_path = tmp_path / "A01_s002_w1_z003_t004.tif" + pixels = np.array([[0, 4095]], dtype=np.uint16) + mask = np.array([[True, False]]) + tifffile.imwrite(source_path, pixels, extratags=((281, "H", 1, 4095, False),)) + ensure_storage_registry() + filemanager = FileManager(dict(storage_registry)) + bindings = CompiledSourceBindingPlan.empty() + plan = CompiledStepPlan( + step_index=0, step_name="Physical source", step_type="FunctionStep", + axis_id="A01", input_dir=tmp_path, output_dir=tmp_path / "outputs", + output_plate_root=tmp_path / "outputs", sub_dir="images", + read_backend=Backend.DISK.value, write_backend=Backend.MEMORY.value, + pipeline_position=0, variable_components=(), source_binding_plan=bindings, + compiled_function_pattern=compile_function_pattern(lambda image: image, {}, {}), + ) + context = SimpleNamespace( + input_dir=tmp_path, filemanager=filemanager, + microscope_handler=SimpleNamespace( + parser=SourceSchemaFilenameParser(), + get_primary_backend=lambda *_args: Backend.DISK.value, + ), + runtime_source_binding_context_cache=RuntimeSourceBindingContextCache(), + ) + runtime = PatternGroupRuntime.__new__(PatternGroupRuntime) + runtime.request = SimpleNamespace( + context=context, execution_plan=plan, source_binding_plan=bindings, + ) + payload = ImagePayloadMetadata().payload_with(pixels, mask) + lookup = VirtualWorkspacePathLookup.from_paths(source_path.name, str(source_path)) + + (loaded,) = runtime._apply_source_image_loading_semantics( + (payload,), (lookup,), (), None, + ) + + metadata = image_payload_metadata(loaded) + assert metadata.intensity_scale == 4095.0 + assert metadata.source_dtype == "uint16" + assert metadata.source_path == str(source_path) + assert metadata.source_component_metadata["site"] == 2 + assert metadata.source_component_metadata["z_index"] == 3 + assert metadata.source_component_metadata["timepoint"] == 4 + assert image_payload_data(loaded) is pixels + assert image_payload_mask(loaded) is mask + np.testing.assert_array_equal(image_payload_data(loaded), [[0, 4095]]) + pixels[0, 0] = 17 + mask[0, 0] = False + assert image_payload_data(loaded)[0, 0] == 17 + assert not image_payload_mask(loaded)[0, 0] + + def test_virtual_workspace_source_filters_use_persisted_candidate_identity( tmp_path: Path, ) -> None: @@ -758,7 +849,9 @@ def test_payload_slices_do_not_infer_alignment_from_source_provenance() -> None: def test_step_output_manifest_scopes_previous_step_inputs(tmp_path: Path) -> None: output_dir = tmp_path / "images" - producer = SimpleNamespace( + producer = CompiledStepPlan( + step_index=1, + step_type="FunctionStep", step_scope_id="enhance", step_name="Enhance", pipeline_position=1, @@ -845,7 +938,9 @@ def test_step_output_manifest_pattern_lookup_returns_producer_memory_paths( tmp_path: Path, ) -> None: output_dir = tmp_path / "images" - producer = SimpleNamespace( + producer = CompiledStepPlan( + step_index=4, + step_type="FunctionStep", step_scope_id="mask_image", step_name="MaskImage", pipeline_position=4, @@ -901,11 +996,10 @@ def test_step_output_manifest_pattern_lookup_returns_producer_memory_paths( ), ) - assert store.producer_paths_matching_pattern( - consumer, - "A14_s{iii}_w3_z001_t001.tif", - SourceSchemaFilenameParser(), - ) == [ + index = store.producer_record_index_for(consumer, SourceSchemaFilenameParser()) + assert [record.output_path for record in index.matching_records( + "A14_s{iii}_w3_z001_t001.tif" + )] == [ str(output_dir / "A14_s001_w3_z001_t001.tif"), str(output_dir / "A14_s002_w3_z001_t001.tif"), ] @@ -915,14 +1009,18 @@ def test_step_output_manifest_does_not_treat_artifact_inputs_as_main_flow( tmp_path: Path, ) -> None: output_dir = tmp_path / "images" - cells_producer = SimpleNamespace( + cells_producer = CompiledStepPlan( + step_index=6, + step_type="FunctionStep", step_scope_id="identify_cells", step_name="IdentifySecondaryObjects", pipeline_position=6, axis_id="A14", output_dir=output_dir, ) - nuclei_producer = SimpleNamespace( + nuclei_producer = CompiledStepPlan( + step_index=5, + step_type="FunctionStep", step_scope_id="identify_nuclei", step_name="IdentifyPrimaryObjects", pipeline_position=5, @@ -1005,28 +1103,26 @@ def test_step_output_manifest_does_not_treat_artifact_inputs_as_main_flow( ), ) - assert ( - store.producer_paths_matching_pattern( - consumer, - "A14_s{iii}_w1_z001_t001.tif", - SourceSchemaFilenameParser(), - ) - == [] - ) + index = store.producer_record_index_for(consumer, SourceSchemaFilenameParser()) + assert index is None def test_step_output_manifest_uses_declared_artifact_producer_scope( tmp_path: Path, ) -> None: output_dir = tmp_path / "images" - requested_producer = SimpleNamespace( + requested_producer = CompiledStepPlan( + step_index=2, + step_type="FunctionStep", step_scope_id="crop_blue", step_name="CropBlue", pipeline_position=2, axis_id="A01", output_dir=output_dir, ) - previous_producer = SimpleNamespace( + previous_producer = CompiledStepPlan( + step_index=3, + step_type="FunctionStep", step_scope_id="crop_red", step_name="CropRed", pipeline_position=3, @@ -1121,7 +1217,9 @@ def test_special_artifact_input_does_not_narrow_step_output_main_flow( tmp_path: Path, ) -> None: output_dir = tmp_path / "images" - producer = SimpleNamespace( + producer = CompiledStepPlan( + step_index=2, + step_type="FunctionStep", step_scope_id="image_set", step_name="ImageSet", pipeline_position=2, @@ -1255,12 +1353,11 @@ def test_step_output_anchor_filter_skips_source_binding_filter() -> None: bindings=(NamedSourceBinding(alias="OrigDNA"),) ), ) - grouped_patterns = PatternGroups({None: ("A14_s{iii}_w1_z001_t001.tif",)}) - pattern_filter = StepAnchorPatternFilter( + grouped_patterns = {None: ("A14_s{iii}_w1_z001_t001.tif",)} + pattern_filter = _anchor_executor( plan=plan, parser=None, output_manifest=StepOutputManifestStore(), - source_workspace_authority=None, source_workspace_projection_cache=VirtualWorkspaceSourceProjectionCache(), ) @@ -1283,18 +1380,17 @@ def test_step_output_anchor_uses_compiler_owned_component_scope() -> None: ), compiled_function_pattern=compile_function_pattern(lambda image: image, {}, {}), ) - grouped_patterns = PatternGroups({"2": ("A01_s{iii}_w2_z001_t001.tif",)}) - pattern_filter = StepAnchorPatternFilter( + grouped_patterns = {"2": ("A01_s{iii}_w2_z001_t001.tif",)} + pattern_filter = _anchor_executor( plan=plan, parser=SourceSchemaFilenameParser(), output_manifest=_source_manifest( plan, [("A01_s001_w2_z001_t001.tif", {"channel": 0})] ), - source_workspace_authority=None, source_workspace_projection_cache=VirtualWorkspaceSourceProjectionCache(), ) - assert pattern_filter.execution_group_anchor_patterns(grouped_patterns).groups == { + assert pattern_filter.execution_group_anchor_patterns(grouped_patterns) == { "0": ("A01_s{iii}_w2_z001_t001.tif",), } @@ -1326,27 +1422,19 @@ def identify_secondary(image): ), compiled_function_pattern=compiled_pattern, ) - pattern_filter = StepAnchorPatternFilter( + pattern_filter = _anchor_executor( plan=plan, parser=SourceSchemaFilenameParser(), output_manifest=_source_manifest( plan, [("A01_s001_w1_z001_t001.tif", {"channel": 2})] ), - source_workspace_authority=None, source_workspace_projection_cache=VirtualWorkspaceSourceProjectionCache(), ) - monkeypatch.setattr( - StepAnchorPatternFilter, - "from_context", - classmethod(lambda cls, context, plan: pattern_filter), - ) - executor = object.__new__(FunctionStepExecutor) - executor.context = SimpleNamespace() - executor.plan = plan + executor = pattern_filter grouped = executor._prepare_groups({"A01": {"1": ("A01_s{iii}_w1_z001_t001.tif",)}}) - assert grouped.groups == { + assert grouped == { "2": ("A01_s{iii}_w1_z001_t001.tif",), } @@ -1412,26 +1500,23 @@ def identify_primary_objects(image, *, runtime): def filter_to_producer_paths(_plan, paths, _parser): return tuple(path for path in paths if "_w2_" in path) - pattern_filter = StepAnchorPatternFilter( + pattern_filter = _anchor_executor( plan=plan, parser=SourceSchemaFilenameParser(), output_manifest=SimpleNamespace( filter_to_producer_paths=filter_to_producer_paths, ), - source_workspace_authority=None, source_workspace_projection_cache=VirtualWorkspaceSourceProjectionCache(), ) - filtered = pattern_filter.filtered( - PatternGroups( - { - "1": ("A01_s{iii}_w1_z001_t001.tif",), - "2": ("A01_s{iii}_w2_z001_t001.tif",), - } - ) + filtered = pattern_filter._filter_anchor_patterns( + { + "1": ("A01_s{iii}_w1_z001_t001.tif",), + "2": ("A01_s{iii}_w2_z001_t001.tif",), + } ) - assert filtered.groups == { + assert filtered == { "1": ("A01_s{iii}_w2_z001_t001.tif",), } @@ -1481,13 +1566,11 @@ def test_step_output_anchor_resolves_dynamic_component_scope_from_patterns() -> {}, ), ) - grouped_patterns = PatternGroups( - { - "1": ("A01_s001_w{iii}_z001_t001.tif",), - "2": ("A01_s002_w{iii}_z001_t001.tif",), - } - ) - pattern_filter = StepAnchorPatternFilter( + grouped_patterns = { + "1": ("A01_s001_w{iii}_z001_t001.tif",), + "2": ("A01_s002_w{iii}_z001_t001.tif",), + } + pattern_filter = _anchor_executor( plan=plan, parser=SourceSchemaFilenameParser(), output_manifest=_source_manifest( @@ -1497,13 +1580,12 @@ def test_step_output_anchor_resolves_dynamic_component_scope_from_patterns() -> ("A01_s002_w1_z001_t001.tif", {}), ], ), - source_workspace_authority=None, source_workspace_projection_cache=VirtualWorkspaceSourceProjectionCache(), ) assert ( - pattern_filter.execution_group_anchor_patterns(grouped_patterns).groups - == grouped_patterns.groups + pattern_filter.execution_group_anchor_patterns(grouped_patterns) + == grouped_patterns ) @@ -1520,22 +1602,19 @@ def test_source_anchor_uses_compiler_owned_static_component_scope() -> None: {}, ), ) - grouped_patterns = PatternGroups( - { - "1": ("A01_s{iii}_w1_z001_t001.tif",), - "2": ("A01_s{iii}_w2_z001_t001.tif",), - "3": ("A01_s{iii}_w3_z001_t001.tif",), - } - ) - pattern_filter = StepAnchorPatternFilter( + grouped_patterns = { + "1": ("A01_s{iii}_w1_z001_t001.tif",), + "2": ("A01_s{iii}_w2_z001_t001.tif",), + "3": ("A01_s{iii}_w3_z001_t001.tif",), + } + pattern_filter = _anchor_executor( plan=plan, parser=None, output_manifest=StepOutputManifestStore(), - source_workspace_authority=None, source_workspace_projection_cache=VirtualWorkspaceSourceProjectionCache(), ) - assert pattern_filter.execution_group_anchor_patterns(grouped_patterns).groups == { + assert pattern_filter.execution_group_anchor_patterns(grouped_patterns) == { "1": ("A01_s{iii}_w1_z001_t001.tif",), } @@ -1605,33 +1684,28 @@ def measure_source_set(image): {plan.ref(): plan for plan in (measurement_plan,)}, ), ) - pattern_filter = StepAnchorPatternFilter( + pattern_filter = _anchor_executor( plan=plan, parser=SourceSchemaFilenameParser(), output_manifest=StepOutputManifestStore(), - source_workspace_authority=SimpleNamespace( - projection_or_empty=lambda: VirtualWorkspaceSourceProjection.empty() - ), source_workspace_projection_cache=VirtualWorkspaceSourceProjectionCache(), ) filtered = pattern_filter.source_bound_anchor_patterns( - PatternGroups( - { - "1": ( - "A01_s001_w1_z001_t001.tif", - "A01_s002_w1_z001_t001.tif", - ), - "2": ( - "A01_s001_w2_z001_t001.tif", - "A01_s002_w2_z001_t001.tif", - ), - "3": ("A01_s001_w3_z001_t001.tif",), - } - ) + { + "1": ( + "A01_s001_w1_z001_t001.tif", + "A01_s002_w1_z001_t001.tif", + ), + "2": ( + "A01_s001_w2_z001_t001.tif", + "A01_s002_w2_z001_t001.tif", + ), + "3": ("A01_s001_w3_z001_t001.tif",), + } ) - assert filtered.groups == { + assert filtered == { "1": ( "A01_s001_w1_z001_t001.tif", "A01_s002_w1_z001_t001.tif", @@ -1772,28 +1846,23 @@ def save_image(image, *, image_to_save: np.ndarray): ), compiled_function_pattern=compiled_pattern, ) - pattern_filter = StepAnchorPatternFilter( + pattern_filter = _anchor_executor( plan=plan, parser=SourceSchemaFilenameParser(), output_manifest=StepOutputManifestStore(), - source_workspace_authority=SimpleNamespace( - projection_or_empty=lambda: VirtualWorkspaceSourceProjection.empty() - ), source_workspace_projection_cache=VirtualWorkspaceSourceProjectionCache(), ) - grouped_patterns = PatternGroups( - { - "1": ("A01_s001_w1_z001_t001.tif",), - "3": ("A01_s001_w3_z001_t001.tif",), - } - ) + grouped_patterns = { + "1": ("A01_s001_w1_z001_t001.tif",), + "3": ("A01_s001_w3_z001_t001.tif",), + } source_anchors = pattern_filter.source_bound_anchor_patterns(grouped_patterns) - assert source_anchors.groups == { + assert source_anchors == { "1": (), "3": ("A01_s001_w3_z001_t001.tif",), } - assert pattern_filter.execution_group_anchor_patterns(source_anchors).groups == { + assert pattern_filter.execution_group_anchor_patterns(source_anchors) == { "3": ("A01_s001_w3_z001_t001.tif",), } @@ -1835,29 +1904,24 @@ def exact_source_input(image): ), compiled_function_pattern=compiled_pattern, ) - pattern_filter = StepAnchorPatternFilter( + pattern_filter = _anchor_executor( plan=plan, parser=SourceSchemaFilenameParser(), output_manifest=StepOutputManifestStore(), - source_workspace_authority=SimpleNamespace( - projection_or_empty=lambda: VirtualWorkspaceSourceProjection.empty() - ), source_workspace_projection_cache=VirtualWorkspaceSourceProjectionCache(), ) - grouped_patterns = PatternGroups( - { - "1": ("A01_s001_w1_z001_t001.tif",), - "2": ("A01_s001_w2_z001_t001.tif",), - } - ) + grouped_patterns = { + "1": ("A01_s001_w1_z001_t001.tif",), + "2": ("A01_s001_w2_z001_t001.tif",), + } source_anchors = pattern_filter.source_bound_anchor_patterns(grouped_patterns) - assert source_anchors.groups == { + assert source_anchors == { "1": ("A01_s001_w1_z001_t001.tif",), "2": (), } - assert pattern_filter.execution_group_anchor_patterns(source_anchors).groups == { + assert pattern_filter.execution_group_anchor_patterns(source_anchors) == { "1": ("A01_s001_w1_z001_t001.tif",), } @@ -1894,27 +1958,22 @@ def exact_source_input(image): ), compiled_function_pattern=compile_function_pattern(exact_source_input, {}, {}), ) - pattern_filter = StepAnchorPatternFilter( + pattern_filter = _anchor_executor( plan=plan, parser=SourceSchemaFilenameParser(), output_manifest=StepOutputManifestStore(), - source_workspace_authority=SimpleNamespace( - projection_or_empty=lambda: VirtualWorkspaceSourceProjection.empty() - ), source_workspace_projection_cache=VirtualWorkspaceSourceProjectionCache(), ) filtered = pattern_filter.source_bound_anchor_patterns( - PatternGroups( - { - "1": ("A01_s001_w1_z001_t001.tif",), - "2": ("A01_s001_w2_z001_t001.tif",), - "3": ("A01_s001_w3_z001_t001.tif",), - } - ) + { + "1": ("A01_s001_w1_z001_t001.tif",), + "2": ("A01_s001_w2_z001_t001.tif",), + "3": ("A01_s001_w3_z001_t001.tif",), + } ) - assert filtered.groups == { + assert filtered == { "1": ("A01_s001_w1_z001_t001.tif",), } @@ -1952,26 +2011,21 @@ def test_pipeline_start_anchors_project_raw_selectors_to_semantic_groups() -> No {}, ), ) - pattern_filter = StepAnchorPatternFilter( + pattern_filter = _anchor_executor( plan=plan, parser=SourceSchemaFilenameParser(), output_manifest=StepOutputManifestStore(), - source_workspace_authority=SimpleNamespace( - projection_or_empty=lambda: VirtualWorkspaceSourceProjection.empty() - ), source_workspace_projection_cache=VirtualWorkspaceSourceProjectionCache(), ) filtered = pattern_filter.source_bound_anchor_patterns( - PatternGroups( - { - "1": ("A01_s001_w1_z001_t001.tif",), - "2": ("A01_s001_w2_z001_t001.tif",), - } - ) + { + "1": ("A01_s001_w1_z001_t001.tif",), + "2": ("A01_s001_w2_z001_t001.tif",), + } ) - assert filtered.groups == { + assert filtered == { "MCP_DNA": ("A01_s001_w1_z001_t001.tif",), "MCP_AGP": ("A01_s001_w2_z001_t001.tif",), } @@ -2065,24 +2119,31 @@ def test_first_step_prepares_raw_source_anchors_under_semantic_binding_groups( assert executor.plan.main_input_dependency == StepInputDependency.pipeline_start() assert executor.plan.source_binding_plan.has_primary_content - assert grouped_patterns.groups == { + assert grouped_patterns == { "MCP_DNA": ("A01_s{iii}_w1_z001_t001.tif",), "MCP_AGP": ("A01_s{iii}_w2_z001_t001.tif",), } - executor._preload_inputs_if_needed(grouped_patterns) request = PatternGroupExecutionRequest( context=context, execution_plan=executor.plan, compiled_group=executor.plan.compiled_function_pattern.default_group, component_value="MCP_DNA", - pattern_group_info=grouped_patterns.groups["MCP_DNA"][0], + pattern_group_info=grouped_patterns["MCP_DNA"][0], component_index=0, component_count=2, ) loaded = PatternGroupRuntime(request)._load_input_stack() - assert loaded.matching_files == ["A01_s001_w1_z001_t001.tif"] + assert loaded[0] == ["A01_s001_w1_z001_t001.tif"] + assert context.filemanager.exists( + str(executor.plan.input_dir / "A01_s001_w1_z001_t001.tif"), + Backend.MEMORY.value, + ) + assert not context.filemanager.exists( + str(executor.plan.input_dir / "A01_s001_w2_z001_t001.tif"), + Backend.MEMORY.value, + ) def test_source_bound_artifact_managed_step_keeps_source_anchors() -> None: @@ -2128,25 +2189,20 @@ def source_bound_module(image, *, runtime): execution_group_scope=ComponentGroupScope.ungrouped(), compiled_function_pattern=compiled_pattern, ) - pattern_filter = StepAnchorPatternFilter( + pattern_filter = _anchor_executor( plan=plan, parser=SourceSchemaFilenameParser(), output_manifest=StepOutputManifestStore(), - source_workspace_authority=SimpleNamespace( - projection_or_empty=lambda: VirtualWorkspaceSourceProjection.empty() - ), source_workspace_projection_cache=VirtualWorkspaceSourceProjectionCache(), ) - grouped_patterns = PatternGroups( - { - None: ( - "A01_s001_w1_z001_t001.tif", - "A01_s002_w1_z001_t001.tif", - ) - } - ) + grouped_patterns = { + None: ( + "A01_s001_w1_z001_t001.tif", + "A01_s002_w1_z001_t001.tif", + ) + } - assert pattern_filter.filtered(grouped_patterns).groups == grouped_patterns.groups + assert pattern_filter._filter_anchor_patterns(grouped_patterns) == grouped_patterns def test_default_callable_runtime_scope_projects_bindings_to_selected_group() -> None: @@ -2228,13 +2284,13 @@ def test_dict_callable_runtime_scope_projects_bindings_to_selected_group() -> No def test_grouped_runtime_adapter_receives_component_selected_source_bindings() -> None: from openhcs.core.runtime_adapters import ( - RuntimeAdapterRequest, RuntimePlaneProjection, ) from openhcs.core.source_load_plan import SourceLoadPlan from openhcs.core.steps.function_runtime import ( ComponentArtifactPlans, - FunctionRuntimeScope, + PatternGroupData, + FunctionCoreExecutor, ) source_binding_plan = CompiledSourceBindingPlan( @@ -2265,25 +2321,26 @@ def test_grouped_runtime_adapter_receives_component_selected_source_bindings() - variable_components=(VariableComponents.SITE,), source_load_plan=SourceLoadPlan(), ) - scope = FunctionRuntimeScope( + scope = PatternGroupData( + matching_files=["first.tif", "second.tif"], + main_data_stack=np.zeros((2, 3, 4), dtype=np.uint16), context=SimpleNamespace(), execution_plan=execution_plan, compiled_group=compiled_pattern.default_group, component_value="1", artifacts=ComponentArtifactPlans(inputs={}, outputs={}), - source_binding_context=SourceBindingRuntimeContext.empty(), runtime_plane_index=0, runtime_plane_count=2, ) - request = RuntimeAdapterRequest.from_runtime_scope( - runtime_scope=scope, - artifact_inputs={}, - artifact_outputs={}, - group_key="1", - plane_projection=RuntimePlaneProjection.stack(), - source_payload=np.zeros((2, 3, 4), dtype=np.uint16), + executor = FunctionCoreExecutor( + group_data=scope, + invocation=compiled_pattern.default_group.invocations[0], + artifacts=ComponentArtifactPlans(inputs={}, outputs={}), + group_key="1", plane_projection=RuntimePlaneProjection.stack(), + main_data_arg=scope.main_data_stack, source_memory_type="numpy", ) + request = executor.runtime_adapter_request(scope.main_data_stack) assert tuple( binding.alias for binding in scope.source_binding_plan.binding_declarations @@ -2291,7 +2348,6 @@ def test_grouped_runtime_adapter_receives_component_selected_source_bindings() - assert tuple( binding.alias for binding in request.source_binding_plan.binding_declarations ) == ("OrigStain1",) - assert request.source_binding_context is scope.source_binding_context from openhcs.interop.cellprofiler.runtime.module_execution import ( cellprofiler_runtime_adapter_factory, @@ -2310,7 +2366,7 @@ def test_runtime_invocation_uses_only_active_source_bound_main_flow_edges( from openhcs.core.steps import function_runtime from openhcs.core.steps.function_runtime import ( ComponentArtifactPlans, - FunctionRuntimeScope, + PatternGroupData, ) source_binding_plan = CompiledSourceBindingPlan( @@ -2360,7 +2416,7 @@ def consume_channel_source(image): spec=spec, storage_plan=None, projection=None, - consumes_main_flow=True, + main_flow_projection=MainFlowInputProjection.DECLARED_SOURCE_IMAGE, ) for edge_key, spec in zip( InvocationArtifactInputProjectionKey.for_input_count( @@ -2390,13 +2446,14 @@ def consume_channel_source(image): artifact_inputs={}, artifact_outputs=output_plans, ) - scope = FunctionRuntimeScope( + scope = PatternGroupData( + matching_files=["input.tif"], + main_data_stack=np.zeros((1, 3, 4), dtype=np.uint16), context=SimpleNamespace(), execution_plan=execution_plan, compiled_group=compiled_group, component_value="1", artifacts=ComponentArtifactPlans.from_step_component(execution_plan, "1"), - source_binding_context=SourceBindingRuntimeContext.empty(), runtime_plane_index=0, runtime_plane_count=1, ) @@ -2420,7 +2477,8 @@ def execute(self, *, debug_sink=None): active_payload = ImagePayloadMetadata( source_image_names=("OrigStain1",), ).payload_with(np.zeros((1, 3, 4), dtype=np.uint16)) - result = scope.execute_chain(active_payload) + scope = replace(scope, main_data_stack=active_payload) + result = function_runtime.PatternGroupRuntime.execute_chain(scope) assert isinstance(result, NoMainFlowOutput) assert tuple( @@ -2443,6 +2501,43 @@ def execute(self, *, debug_sink=None): assert request.selected_artifact_input_specs().names() == ("OrigStain1",) +def test_source_roster_selection_cannot_replace_missing_stored_primary_epoch() -> None: + from openhcs.core.artifacts import ArtifactInputProjectionPlan + from openhcs.core.steps.function_runtime import ComponentArtifactPlans + + bindings = CompiledSourceBindingPlan(bindings=(NamedSourceBinding(alias="Original"),)) + (source_spec,) = tuple(binding.input_spec() for binding in bindings.binding_declarations) + + @runtime_adapter("runtime", lambda _request: object(), manages_artifact_inputs=True) + @artifact_inputs(source_spec) + def consume_original(image, *, runtime): + return image + + storage = ArtifactInputPlan( + name=source_spec.name, artifact_type=source_spec.artifact_type, + path="/memory/Original.pkl", source_step_id=0, + ) + invocation = compile_function_pattern(consume_original, {storage.ref(): storage}, {}).default_group.invocations[0] + (key,) = InvocationArtifactInputProjectionKey.for_input_count(invocation.key, 1) + invocation = invocation.with_artifact_input_edges(( + InvocationArtifactInputEdgePlan( + key=key, spec=source_spec, storage_plan=storage, + projection=ArtifactInputProjectionPlan( + invocation_scope=ComponentGroupScope.ungrouped(), + producer_selection_scope=storage.producer_group_scope(), + ), + main_flow_projection=MainFlowInputProjection.COMPLETE_PAYLOAD, + ), + )) + plans = ComponentArtifactPlans(inputs={storage.ref(): storage}, outputs={}) + with pytest.raises(ValueError, match="producer cannot substitute.*current payload epoch"): + plans.select_for_invocation( + invocation, execution_scope=ComponentGroupScope.ungrouped(), component_key=None, + declared_source_bindings=bindings, + active_source_bindings=CompiledSourceBindingPlan.empty(), + ) + + def test_runtime_chain_skips_adapter_invocation_without_component_outputs( monkeypatch: pytest.MonkeyPatch, ) -> None: @@ -2451,7 +2546,7 @@ def test_runtime_chain_skips_adapter_invocation_without_component_outputs( from openhcs.core.steps import function_runtime from openhcs.core.steps.function_runtime import ( ComponentArtifactPlans, - FunctionRuntimeScope, + PatternGroupData, ) first_spec = ArtifactSpec.output("FirstLabels", ObjectLabelsArtifactType) @@ -2529,13 +2624,14 @@ def record_second_labels(image, *, runtime): artifact_inputs={}, artifact_outputs=output_plans, ) - scope = FunctionRuntimeScope( + scope = PatternGroupData( + matching_files=["input.tif"], + main_data_stack=np.zeros((1, 3, 4), dtype=np.uint16), context=SimpleNamespace(), execution_plan=execution_plan, compiled_group=compiled_group, component_value="1", artifacts=ComponentArtifactPlans.from_step_component(execution_plan, "1"), - source_binding_context=SourceBindingRuntimeContext.empty(), runtime_plane_index=0, runtime_plane_count=1, ) @@ -2560,7 +2656,7 @@ def memory_types(self): lambda context: SimpleNamespace(captures_invocation_events=lambda: False), ) - scope.execute_chain(np.zeros((1, 3, 4), dtype=np.uint16)) + function_runtime.PatternGroupRuntime.execute_chain(scope) assert executed == ["record_first_labels"] @@ -2641,7 +2737,7 @@ def main_flow_with_auxiliary_source(image): spec=spec, storage_plan=None, projection=None, - consumes_main_flow=input_index == 0, + main_flow_projection=(MainFlowInputProjection.DECLARED_SOURCE_IMAGE if input_index == 0 else None), ) for input_index, (edge_key, spec) in enumerate( zip( @@ -2800,7 +2896,7 @@ def consume_channel_stack(image): spec=spec, storage_plan=None, projection=None, - consumes_main_flow=True, + main_flow_projection=MainFlowInputProjection.DECLARED_SOURCE_IMAGE, ) for edge_key, spec in zip( InvocationArtifactInputProjectionKey.for_input_count( @@ -2872,7 +2968,7 @@ def consume_selected_channels(image): spec=spec, storage_plan=None, projection=None, - consumes_main_flow=True, + main_flow_projection=MainFlowInputProjection.DECLARED_SOURCE_IMAGE, ) for edge_key, spec in zip( InvocationArtifactInputProjectionKey.for_input_count( @@ -2945,7 +3041,7 @@ def measure_neurites(image, pixel_size=1.0): spec=pixel_size_spec, storage_plan=None, projection=None, - consumes_main_flow=False, + ), ) ) @@ -3082,7 +3178,7 @@ def test_pipeline_start_main_flow_survives_prior_producer_image_input( ) == ("Primary",) assert mask_edge.spec == _MAIN_FLOW_MASK_INPUT assert mask_edge.storage_plan is not None - assert mask_edge.consumes_main_flow is False + assert (mask_edge.main_flow_projection is not None) is False assert invocation.contract.accepts_implicit_main_flow_input is True assert compiled_pattern.default_group.main_flow_input_refs is None assert tuple( @@ -3093,7 +3189,6 @@ def test_pipeline_start_main_flow_survives_prior_producer_image_input( def test_runtime_plane_count_comes_from_loaded_slices_not_dispatch_groups() -> None: from openhcs.core.steps.function_runtime import ( - FunctionRuntimeScope, PatternGroupData, PatternGroupExecutionRequest, ) @@ -3119,7 +3214,8 @@ def test_runtime_plane_count_comes_from_loaded_slices_not_dispatch_groups() -> N component_index=0, component_count=1, ) - loaded = PatternGroupData( + scope = PatternGroupData.from_loaded_group( + request, matching_files=[ "A01_s001_w1_z001_t001.tif", "A01_s002_w1_z001_t001.tif", @@ -3152,8 +3248,6 @@ def test_runtime_plane_count_comes_from_loaded_slices_not_dispatch_groups() -> N ).payload_with(np.zeros((2, 4, 5), dtype=np.float32)), ) - scope = FunctionRuntimeScope.from_pattern_group(request, loaded) - assert scope.runtime_plane_count == 2 assert scope.axis_scope.fixed_component_values == ( (AllComponents.Z_INDEX, "3"), @@ -3656,7 +3750,6 @@ def resolve_address(backend_address, backend, *, base_path): (payload,), (lookup,), workspace_source_lookups, - SourceBindingRuntimeContext.empty(), projection, ) @@ -3733,6 +3826,9 @@ def test_producer_anchored_pipeline_start_paths_use_exact_source_projection_bund """Producer bookkeeping must not override exact workspace source ownership.""" from openhcs.core.steps import function_runtime + from openhcs.core.runtime_source_binding_cache import ( + RuntimeSourceBindingContextCache, + ) virtual_paths = ( "A01_s001_w1_z001_t001.tif", @@ -3801,15 +3897,6 @@ def test_producer_anchored_pipeline_start_paths_use_exact_source_projection_bund ) ) - class SourceManifest: - @staticmethod - def producer_paths_matching_pattern(*_args): - return list(virtual_paths) - - @staticmethod - def filter_to_producer_paths(_plan, paths, _parser): - return list(paths) - class SourceFileManager: @staticmethod def load_batch(paths, backend): @@ -3831,16 +3918,7 @@ def resolve_address(backend_address, backend, *, base_path): monkeypatch.setattr( function_runtime, "step_output_manifest", - lambda _context: SourceManifest(), - ) - monkeypatch.setattr( - function_runtime.SourceBindingRuntimeContextRequest, - "from_context", - classmethod( - lambda cls, **_kwargs: SimpleNamespace( - runtime_context=SourceBindingRuntimeContext.empty - ) - ), + lambda _context: StepOutputManifestStore(), ) monkeypatch.setattr( function_runtime.PatternGroupRuntime, @@ -3858,6 +3936,7 @@ def resolve_address(backend_address, backend, *, base_path): step_type="FunctionStep", axis_id="A01", input_dir=tmp_path, + read_backend="memory", input_memory_type="numpy", variable_components=(), main_input_dependency=StepInputDependency.pipeline_start(), @@ -3870,6 +3949,7 @@ def resolve_address(backend_address, backend, *, base_path): ), filemanager=SourceFileManager(), runtime_image_stack_cache=RuntimeImageStackCache(), + runtime_source_binding_context_cache=RuntimeSourceBindingContextCache(), runtime_source_workspace_projection_cache=( VirtualWorkspaceSourceProjectionCache() ), @@ -3893,8 +3973,8 @@ def resolve_address(backend_address, backend, *, base_path): loaded = runtime._load_input_stack() - data = image_payload_data(loaded.main_data_stack) - metadata = image_payload_metadata(loaded.main_data_stack) + data = image_payload_data(loaded[1]) + metadata = image_payload_metadata(loaded[1]) assert data.shape == (2, 4, 5, 3) np.testing.assert_array_equal(data[1], np.full((4, 5, 3), 7, dtype=np.float32)) assert metadata.source_image_names == aliases @@ -3934,33 +4014,16 @@ def test_step_output_load_preserves_producer_stack_plane_provenance( ), ).payload_with(np.zeros((2, 4, 5), dtype=np.float32), None) - class ProducerManifest: - def producer_paths_matching_pattern(self, *_args): - return [str(output_path)] - - def filter_to_producer_paths(self, _plan, paths, _parser): - return list(paths) - class MemoryFileManager: def load_batch(self, paths, backend): assert paths == [str(output_path)] assert backend == "memory" return [producer_payload] - source_context = SourceBindingRuntimeContext() monkeypatch.setattr( function_runtime, "step_output_manifest", - lambda _context: ProducerManifest(), - ) - monkeypatch.setattr( - function_runtime.SourceBindingRuntimeContextRequest, - "from_context", - classmethod( - lambda cls, **_kwargs: SimpleNamespace( - runtime_context=lambda: source_context - ) - ), + lambda _context: producer_manifest, ) monkeypatch.setattr( function_runtime.PatternGroupRuntime, @@ -3987,7 +4050,26 @@ def load_batch(self, paths, backend): input_dir=tmp_path, input_memory_type="numpy", variable_components=(VariableComponents.Z_INDEX,), + compiled_function_pattern=compile_function_pattern(lambda image: image, {}, {}), + main_input_dependency=StepInputDependency.step_output( + source_step_index=0, source_step_scope_id="producer", + ), ) + producer = CompiledStepPlan( + step_index=0, step_name="producer", step_type="FunctionStep", + step_scope_id="producer", axis_id="A01", output_dir=tmp_path, + ) + producer_manifest = StepOutputManifestStore() + producer_manifest.begin_step(producer) + producer_manifest.record_outputs(producer, ( + ProducedOutputSemantics.from_output( + producer, output_path, + FunctionOutputIdentity( + component_values={"well": "A01", "site": "1", "channel": "2", "z_index": "1", "timepoint": "1"}, + extension=".tif", source="test", + ), + ).with_filename_qualifier("RescaledDNA"), + )) context = SimpleNamespace( microscope_handler=SimpleNamespace(parser=SourceSchemaFilenameParser()), filemanager=MemoryFileManager(), @@ -4008,7 +4090,7 @@ def load_batch(self, paths, backend): loaded = runtime._load_input_stack() provenance_planes = image_payload_metadata( - loaded.main_data_stack + loaded[1] ).source_image_provenance_planes assert provenance_planes.count == 2 assert provenance_planes.contributor_count == 0 @@ -4083,7 +4165,9 @@ def test_step_output_manifest_does_not_filter_main_flow_by_artifact_input( tmp_path: Path, ) -> None: output_dir = tmp_path / "images" - producer = SimpleNamespace( + producer = CompiledStepPlan( + step_index=1, + step_type="FunctionStep", step_scope_id="correct_illumination", step_name="CorrectIlluminationApply", pipeline_position=1, @@ -4170,7 +4254,9 @@ def test_step_output_manifest_filters_declared_main_flow_contract_identity( tmp_path: Path, ) -> None: output_dir = tmp_path / "images" - producer = SimpleNamespace( + producer = CompiledStepPlan( + step_index=2, + step_type="FunctionStep", step_scope_id="align", step_name="Align", pipeline_position=2, @@ -4195,7 +4281,7 @@ def identify_stain_1(image): spec=input_spec, storage_plan=None, projection=None, - consumes_main_flow=True, + main_flow_projection=MainFlowInputProjection.DECLARED_SOURCE_IMAGE, ), ) ) @@ -4264,14 +4350,18 @@ def test_step_output_manifest_updates_selected_slot_and_preserves_other_componen tmp_path: Path, ) -> None: output_dir = tmp_path / "images" - producer = SimpleNamespace( + producer = CompiledStepPlan( + step_index=1, + step_type="FunctionStep", step_scope_id="producer", step_name="Producer", pipeline_position=1, axis_id="A01", output_dir=output_dir, ) - update = SimpleNamespace( + update = CompiledStepPlan( + step_index=2, + step_type="FunctionStep", step_scope_id="update", step_name="Update", pipeline_position=2, @@ -4357,14 +4447,18 @@ def test_step_output_manifest_collapsed_domain_replaces_inherited_components( collapsed_input_domain: bool, ) -> None: output_dir = tmp_path / "images" - producer = SimpleNamespace( + producer = CompiledStepPlan( + step_index=1, + step_type="FunctionStep", step_scope_id="producer", step_name="Producer", pipeline_position=1, axis_id="A01", output_dir=output_dir, ) - collapse = SimpleNamespace( + collapse = CompiledStepPlan( + step_index=2, + step_type="FunctionStep", step_scope_id="collapse", step_name="Collapse", pipeline_position=2, @@ -4426,14 +4520,18 @@ def test_step_output_manifest_new_output_address_replaces_inherited_components( tmp_path: Path, ) -> None: output_dir = tmp_path / "images" - producer = SimpleNamespace( + producer = CompiledStepPlan( + step_index=1, + step_type="FunctionStep", step_scope_id="producer", step_name="Producer", pipeline_position=1, axis_id="A01", output_dir=output_dir, ) - replacement = SimpleNamespace( + replacement = CompiledStepPlan( + step_index=2, + step_type="FunctionStep", step_scope_id="replacement", step_name="Replacement", pipeline_position=2, @@ -4508,14 +4606,18 @@ def test_step_output_manifest_grouped_subset_replaces_inherited_components( tmp_path: Path, ) -> None: output_dir = tmp_path / "images" - producer = SimpleNamespace( + producer = CompiledStepPlan( + step_index=1, + step_type="FunctionStep", step_scope_id="producer", step_name="Producer", pipeline_position=1, axis_id="A01", output_dir=output_dir, ) - subset = SimpleNamespace( + subset = CompiledStepPlan( + step_index=2, + step_type="FunctionStep", step_scope_id="subset", step_name="Subset", pipeline_position=2, @@ -4579,7 +4681,9 @@ def test_step_output_manifest_preserves_anonymous_side_effect_main_flow( tmp_path: Path, ) -> None: output_dir = tmp_path / "images" - producer = SimpleNamespace( + producer = CompiledStepPlan( + step_index=2, + step_type="FunctionStep", step_scope_id="identify_primary", step_name="IdentifyPrimaryObjects", pipeline_position=2, @@ -4639,7 +4743,9 @@ def test_step_output_manifest_accepts_source_anchor_for_qualified_output( tmp_path: Path, ) -> None: output_dir = tmp_path / "images" - producer = SimpleNamespace( + producer = CompiledStepPlan( + step_index=4, + step_type="FunctionStep", step_scope_id="correct_illumination_apply", step_name="CorrectIlluminationApply", pipeline_position=4, @@ -4714,14 +4820,12 @@ def test_function_output_path_uses_payload_identity_over_input_carrier( }, ).payload_with(np.zeros((4, 5), dtype=np.float32), None) - output_path = FunctionOutputPathAuthority.output_path( - FunctionOutputPathRequest( + output_path = FunctionOutputIdentity.path_from_request(FunctionOutputPathRequest( parser=SourceSchemaFilenameParser(), output_dir=tmp_path, output_payload=payload, input_path="A14_s001_w1_z001_t001.tif", - ) - ) + )) assert output_path.name == "A14_s002_w3_z001_t001.tif" @@ -4740,14 +4844,12 @@ def test_function_output_path_uses_payload_identity_without_input_path( }, ).payload_with(np.zeros((4, 5), dtype=np.float32), None) - output_path = FunctionOutputPathAuthority.output_path( - FunctionOutputPathRequest( + output_path = FunctionOutputIdentity.path_from_request(FunctionOutputPathRequest( parser=SourceSchemaFilenameParser(), output_dir=tmp_path, output_payload=payload, input_path=None, - ) - ) + )) assert output_path.name == "A14_s001_w5_z001_t001.tif" @@ -4766,7 +4868,7 @@ def test_function_output_identity_completes_partial_payload_metadata_from_fallba }, ) - identity = FunctionOutputIdentityAuthority.identity_from_metadata( + identity = FunctionOutputIdentity.from_metadata( parser, metadata, fallback_identity_path="Sequence1_s001_w1_z001_t000.tif", @@ -4774,7 +4876,7 @@ def test_function_output_identity_completes_partial_payload_metadata_from_fallba assert identity is not None assert ( - FunctionOutputPathAuthority.filename_for_identity(parser, identity) + identity.filename(parser) == "Sequence1_s001_w1_z001_t000.tif" ) @@ -4793,7 +4895,7 @@ def test_function_output_identity_uses_fallback_path_extension_for_payload_ident }, ) - identity = FunctionOutputIdentityAuthority.identity_from_metadata( + identity = FunctionOutputIdentity.from_metadata( parser, metadata, fallback_identity_path="A01_s001_w1_z001_t001.png", @@ -4801,7 +4903,7 @@ def test_function_output_identity_uses_fallback_path_extension_for_payload_ident assert identity is not None assert ( - FunctionOutputPathAuthority.filename_for_identity(parser, identity) + identity.filename(parser) == "A01_s001_w2_z001_t001.png" ) @@ -4829,14 +4931,12 @@ def test_function_output_path_uses_input_identity_for_multi_plane_carrier( ), ).payload_with(np.zeros((2, 4, 5), dtype=np.float32), None) - output_path = FunctionOutputPathAuthority.output_path( - FunctionOutputPathRequest( + output_path = FunctionOutputIdentity.path_from_request(FunctionOutputPathRequest( parser=SourceSchemaFilenameParser(), output_dir=tmp_path, output_payload=payload, input_path="A14_s001_w1_z001_t001.tif", - ) - ) + )) assert output_path.name == "A14_s001_w1_z001_t001.tif" @@ -4854,14 +4954,12 @@ def test_function_output_path_rejects_multi_plane_carrier_without_input_path( ).payload_with(np.zeros((2, 4, 5), dtype=np.float32), None) with pytest.raises(ValueError, match="multi-plane source provenance"): - FunctionOutputPathAuthority.output_path( - FunctionOutputPathRequest( + FunctionOutputIdentity.path_from_request(FunctionOutputPathRequest( parser=SourceSchemaFilenameParser(), output_dir=tmp_path, output_payload=payload, input_path=None, - ) - ) + )) def test_function_output_path_uses_variable_component_identity( @@ -4899,11 +4997,8 @@ def test_function_output_path_uses_variable_component_identity( variable_components=(VariableComponents.Z_INDEX,), ) - identity = FunctionOutputIdentityAuthority.identity(request) - output_path = FunctionOutputPathAuthority.output_path_for_identity( - request, - identity, - ) + identity = FunctionOutputIdentity.from_request(request) + output_path = identity.path_for_request(request) assert output_path.name == "A14_s001_w1_z001_t001.tif" assert identity.component_values == { @@ -4957,15 +5052,12 @@ def test_collapsed_output_identity_uses_retained_source_contributors( variable_components=(VariableComponents.SITE,), ) - identity = FunctionOutputIdentityAuthority.identity(request) - filename_identity = FunctionOutputIdentityAuthority.filename_identity_from_metadata( + identity = FunctionOutputIdentity.from_request(request) + filename_identity = FunctionOutputIdentity.from_filename_metadata( request.parser, collapsed_metadata, ) - output_path = FunctionOutputPathAuthority.output_path_for_identity( - request, - identity, - ) + output_path = identity.path_for_request(request) assert collapsed_metadata.source_image_provenance_planes.count == 0 assert collapsed_metadata.source_image_provenance_planes.contributor_count == 2 @@ -4980,10 +5072,7 @@ def test_collapsed_output_identity_uses_retained_source_contributors( assert identity.filename_component_values["site"] == 1 assert filename_identity is not None assert ( - FunctionOutputPathAuthority.filename_for_identity( - request.parser, - filename_identity, - ) + filename_identity.filename(request.parser) == "A14_s001_w1_z001_t001.tif" ) @@ -5035,11 +5124,8 @@ def test_composite_then_z_collapse_uses_current_scalar_identity( variable_components=(VariableComponents.Z_INDEX,), ) - identity = FunctionOutputIdentityAuthority.identity(request) - output_path = FunctionOutputPathAuthority.output_path_for_identity( - request, - identity, - ) + identity = FunctionOutputIdentity.from_request(request) + output_path = identity.path_for_request(request) assert z_stack_metadata.source_provenance.source_plane_count == 3 assert projected_metadata.source_provenance.source_plane_count == 0 @@ -5075,11 +5161,8 @@ def test_variable_component_identity_uses_fallback_path_extension( variable_components=(VariableComponents.CHANNEL,), ) - identity = FunctionOutputIdentityAuthority.identity(request) - output_path = FunctionOutputPathAuthority.output_path_for_identity( - request, - identity, - ) + identity = FunctionOutputIdentity.from_request(request) + output_path = identity.path_for_request(request) assert output_path.name == "A01_s001_w1_z001_t001.png" assert identity.extension == ".png" @@ -5103,16 +5186,10 @@ def test_declared_main_flow_output_context_qualifies_output_filename( output_payload=payload, input_path="A01_s001_w1_z001_t001.jpg", ) - identity = FunctionOutputIdentityAuthority.identity(request) + identity = FunctionOutputIdentity.from_request(request) - red_path = FunctionOutputPathAuthority.output_path_for_identity( - request, - identity.with_filename_qualifier("CorrRed"), - ) - green_path = FunctionOutputPathAuthority.output_path_for_identity( - request, - identity.with_filename_qualifier("CorrGreen"), - ) + red_path = identity.with_filename_qualifier("CorrRed").path_for_request(request) + green_path = identity.with_filename_qualifier("CorrGreen").path_for_request(request) assert red_path.name == "A01_s001_w1_z001_t001_CorrRed.jpg" assert green_path.name == "A01_s001_w1_z001_t001_CorrGreen.jpg" @@ -5147,7 +5224,7 @@ def test_function_output_path_rejects_variation_outside_identity_components( ) with pytest.raises(ValueError, match="varies outside identity components"): - FunctionOutputIdentityAuthority.identity( + FunctionOutputIdentity.from_request( FunctionOutputPathRequest( parser=SourceSchemaFilenameParser(), output_dir=tmp_path, @@ -5171,7 +5248,7 @@ def test_function_output_path_rejects_group_by_component_stack_variation( ), ).payload_with(np.zeros((3, 4, 5), dtype=np.float32), None) with pytest.raises(ValueError, match="varies outside identity components"): - FunctionOutputIdentityAuthority.identity( + FunctionOutputIdentity.from_request( FunctionOutputPathRequest( parser=SourceSchemaFilenameParser(), output_dir=tmp_path, @@ -5202,11 +5279,8 @@ def test_input_aligned_stack_output_uses_input_filename_identity( input_aligned_output=True, ) - identity = FunctionOutputIdentityAuthority.identity(request) - output_path = FunctionOutputPathAuthority.output_path_for_identity( - request, - identity, - ) + identity = FunctionOutputIdentity.from_request(request) + output_path = identity.path_for_request(request) assert output_path.name == "A01_s002_w1_z001_t001.png" assert identity.component_values["site"] == 2 @@ -5249,11 +5323,8 @@ def test_function_output_path_keeps_payload_split_axis_over_input_alignment( input_aligned_output=True, ) - identity = FunctionOutputIdentityAuthority.identity(request) - output_path = FunctionOutputPathAuthority.output_path_for_identity( - request, - identity, - ) + identity = FunctionOutputIdentity.from_request(request) + output_path = identity.path_for_request(request) assert output_path.name == "A01_s001_w1_z001_t001.tif" assert identity.component_values["site"] == 1 @@ -5261,13 +5332,17 @@ def test_function_output_path_keeps_payload_split_axis_over_input_alignment( assert identity.filename_component_values["site"] == 1 +@pytest.mark.parametrize("named_topology", ["anonymous", "unwrapped", "explicit"]) def test_save_outputs_positional_lowering_preserves_explicit_payload_identity( tmp_path: Path, + named_topology: str, ) -> None: - from openhcs.core.steps.function_runtime import ( - PatternGroupOutputData, - PatternGroupRuntime, - ) + from openhcs.core.steps.function_runtime import PatternGroupRuntime + from openhcs.core.runtime_stack_cache import RuntimeImageStackCache + from openhcs.core.compiled_step_plan import CompiledStepPlan + from openhcs.core.component_group_scope import ComponentGroupScope + from openhcs.core.function_patterns import compile_function_pattern + from openhcs.core.aligned_image_payload import AlignedImageStack class OutputFileManager: saved_payloads: list[object] = [] @@ -5290,6 +5365,17 @@ def save_batch( self.saved_payloads = payloads self.saved_paths = paths + output_plans = {} + func = lambda image: image + if named_topology != "anonymous": + spec = ArtifactSpec.output("Corrected", ImageArtifactType) + output_plan = ArtifactOutputPlan( + name=spec.name, + path=str(tmp_path / "Corrected.pkl"), + artifact_type=spec.artifact_type, + ) + output_plans[output_plan.ref()] = output_plan + func = artifact_outputs(spec)(func) filemanager = OutputFileManager() runtime = PatternGroupRuntime( SimpleNamespace( @@ -5299,13 +5385,22 @@ def save_batch( parser=SourceSchemaFilenameParser(), ), runtime_function_output_identity_cache=FunctionOutputIdentityCache(), + runtime_image_stack_cache=RuntimeImageStackCache(), ), - execution_plan=SimpleNamespace( + compiled_group=compile_function_pattern(func, {}, output_plans).default_group, + component_key=None, + execution_plan=CompiledStepPlan( + step_index=0, + step_type="FunctionStep", + axis_id="A01", output_dir=tmp_path, + output_memory_type="numpy", variable_components=(VariableComponents.SITE,), step_name="ExplicitIdentity", pipeline_position=0, step_scope_id="explicit-identity", + execution_group_scope=ComponentGroupScope.ungrouped(), + artifact_outputs=output_plans, ), pattern_group_info="A01_s{iii}_w1_z001_t001.tif", ) @@ -5321,12 +5416,22 @@ def save_batch( }, ).payload_with(np.zeros((4, 5), dtype=np.float32), None) + named_context = AlignedImageSliceContext.main_flow( + "Corrected", artifact_kind=ImageArtifactType.value, + ) + output = ( + AlignedImageStack((payload,), (named_context,)) + if named_topology == "explicit" else payload + ) records = runtime._save_outputs( - PatternGroupOutputData(slices=[payload]), + output, ["A01_s003_w1_z001_t001.tif"], ) - assert Path(filemanager.saved_paths[0]).name == "A01_s001_w1_z001_t001.tif" + expected = "A01_s001_w1_z001_t001" + if named_topology == "explicit": + expected += "_Corrected" + assert Path(filemanager.saved_paths[0]).name == expected + ".tif" assert ( image_payload_metadata(filemanager.saved_payloads[0]).source_component_metadata[ "site" @@ -5334,14 +5439,25 @@ def save_batch( == "1" ) assert records[0].component_values["site"] == 1 + if named_topology != "anonymous": + assert records[0].output_context == named_context + assert image_payload_metadata(filemanager.saved_payloads[0]).source_image_names == ( + "Corrected", + ) + assert image_payload_data(filemanager.saved_payloads[0]) is image_payload_data(payload) @pytest.fixture def qualified_producer_manifest(tmp_path): parser = SourceSchemaFilenameParser() - producer = SimpleNamespace( - step_scope_id="producer", step_name="Producer", pipeline_position=0, - axis_id="A01", output_dir=tmp_path, + producer = CompiledStepPlan( + step_index=0, + step_type="FunctionStep", + step_scope_id="producer", + step_name="Producer", + pipeline_position=0, + axis_id="A01", + output_dir=tmp_path, ) consumer = SimpleNamespace( axis_id="A01", @@ -5355,14 +5471,22 @@ def qualified_producer_manifest(tmp_path): parsed = parser.parse_filename(f"A01_s001_w2_z{plane:03d}_t001.tif") identity = FunctionOutputIdentity( component_values=dict(parsed.component_wire_mapping()), - extension=".tif", source="test", filename_qualifier=f"Output{plane}", + extension=".tif", + source="test", + filename_qualifier=f"Output{plane}", + ) + records.append( + ProducedOutputSemantics.from_output( + producer, + tmp_path + / identity.filename(parser), + identity, + output_context=AlignedImageSliceContext.main_flow( + output_key=f"Output{plane}", + artifact_kind=ImageArtifactType.value, + ), + ) ) - records.append(ProducedOutputSemantics.from_output( - producer, tmp_path / FunctionOutputPathAuthority.filename_for_identity(parser, identity), - identity, output_context=AlignedImageSliceContext.main_flow( - output_key=f"Output{plane}", artifact_kind=ImageArtifactType.value, - ), - )) store = StepOutputManifestStore() store.begin_step(producer) store.record_outputs(producer, records) @@ -5370,17 +5494,20 @@ def qualified_producer_manifest(tmp_path): def test_step_output_manifest_batch_lookup_preserves_aliases_order_and_duplicates( - qualified_producer_manifest, monkeypatch, + qualified_producer_manifest, + monkeypatch, ): store, _producer, consumer, records, parser = qualified_producer_manifest calls = [] - original = FunctionOutputPathAuthority.filename_for_identity + original = FunctionOutputIdentity.filename - def count_filename(parser, identity): + def count_filename(identity, parser): calls.append(identity) - return original(parser, identity) + return original(identity, parser) - monkeypatch.setattr(FunctionOutputPathAuthority, "filename_for_identity", count_filename) + monkeypatch.setattr( + FunctionOutputIdentity, "filename", count_filename + ) paths = ( records[1].output_path, "A01_s001_w2_z001_t001.tif", @@ -5389,11 +5516,61 @@ def count_filename(parser, identity): ) result = store.producer_output_contexts_for_paths(consumer, paths, parser) assert tuple(context.output_key for context in result) == ( - "Output2", "Output1", "Output2", "Output1", + "Output2", + "Output1", + "Output2", + "Output1", ) assert len(calls) == len(records) +def test_produced_identity_owns_filename_and_live_storage_coordinate_cache( + qualified_producer_manifest, + tmp_path, + monkeypatch, +): + _store, _producer, _consumer, records, parser = qualified_producer_manifest + storage_components = dict(records[0].component_values) + storage_components["channel"] = 1 + semantic_components = {**storage_components, "well": "B02", "channel": 9} + record = replace( + records[0], + component_values=semantic_components, + filename_component_values=storage_components, + ).with_filename_qualifier(" ./Corrected signal?!.. ") + cache = FunctionOutputIdentityCache() + calls = [] + original_construct = parser.construct_filename + + def construct(bound): + calls.append(bound) + return original_construct(bound) + + monkeypatch.setattr(parser, "construct_filename", construct) + first = record.cached_filename(parser, cache) + assert first == "A01_s001_w1_z001_t001_Corrected_signal.tif" + assert record.cached_filename(parser, cache) == first + assert len(calls) == 1 + # The inherited formatter follows the original live storage mapping; + # semantic producer coordinates and its recorded path are independent. + storage_components["channel"] = 2 + second = record.cached_filename(parser, cache) + assert second == "A01_s001_w2_z001_t001_Corrected_signal.tif" + assert len(calls) == 2 + assert record.component_metadata()["well"] == "B02" + assert record.component_metadata()["channel"] == "9" + assert record.output_path == records[0].output_path + request = FunctionOutputPathRequest( + parser=parser, + output_dir=tmp_path / "other", + output_payload=np.zeros((3, 4), dtype=np.float32), + input_path=None, + identity_cache=cache, + ) + assert record.path_for_request(request) == tmp_path / "other" / second + assert len(calls) == 2 + + def test_step_output_manifest_batch_lookup_template_deduplicates_record_aliases( qualified_producer_manifest, ): @@ -5407,12 +5584,17 @@ def test_step_output_manifest_batch_lookup_template_deduplicates_record_aliases( assert index.matching_records(path) == (records[0],) -@pytest.mark.parametrize("path, count", [ - ("missing.tif", 0), - ("A01_s001_w2_z{plane}_t001.tif", 2), -]) +@pytest.mark.parametrize( + "path, count", + [ + ("missing.tif", 0), + ("A01_s001_w2_z{plane}_t001.tif", 2), + ], +) def test_step_output_manifest_batch_lookup_rejects_missing_and_ambiguous_templates( - qualified_producer_manifest, path, count, + qualified_producer_manifest, + path, + count, ): store, _producer, consumer, _records, parser = qualified_producer_manifest with pytest.raises(NoStepOutputManifestMatch, match=f"found {count}"): @@ -5425,10 +5607,12 @@ def test_step_output_manifest_batch_lookup_rejects_shared_basename( store, producer, consumer, records, parser = qualified_producer_manifest alias = records[0].relative_output_path other = ProducedOutputSemantics.from_output( - producer, producer.output_dir / "another" / alias, + producer, + producer.output_dir / "another" / alias, FunctionOutputIdentity( component_values=records[1].component_values, - extension=".tif", source="test", + extension=".tif", + source="test", ), output_context=records[1].output_context, ) @@ -5438,3 +5622,112 @@ def test_step_output_manifest_batch_lookup_rejects_shared_basename( assert store.producer_output_contexts_for_paths( consumer, (records[0].output_path, other.output_path), parser ) == (records[0].output_context, other.output_context) + + +def test_producer_admission_rederives_live_storage_aliases_each_epoch( + qualified_producer_manifest, +): + store, producer, consumer, records, parser = qualified_producer_manifest + storage_components = dict(records[0].filename_values) + record = replace(records[0], filename_component_values=storage_components) + store.record_outputs(producer, (record,)) + old_index = store.producer_record_index_for(consumer, parser) + storage_components["channel"] = 9 + new_alias = record.without_filename_qualifier().filename(parser) + + assert old_index.matching_records(new_alias) == () + current_index = store.producer_record_index_for(consumer, parser) + assert current_index.matching_records(new_alias) == (record,) + assert current_index.record_for_path(record.output_path) is record + + +def test_producer_loader_validates_ambiguity_before_cache( + monkeypatch, +): + from openhcs.core.steps import function_runtime + + producer = CompiledStepPlan( + step_index=0, step_name="producer", step_type="FunctionStep", + step_scope_id="producer", axis_id="A01", output_dir=Path("/memory"), + ) + plan = CompiledStepPlan( + step_index=1, step_name="consumer", step_type="FunctionStep", + axis_id="A01", input_dir=Path("/memory"), input_memory_type="numpy", + compiled_function_pattern=compile_function_pattern(lambda image: image, {}, {}), + main_input_dependency=StepInputDependency.step_output( + source_step_index=0, source_step_scope_id="producer", + ), + ) + manifest = StepOutputManifestStore() + manifest.begin_step(producer) + manifest.record_outputs(producer, ( + ProducedOutputSemantics.from_existing_main_flow_path( + producer, "A01_s001_w1_z001_t001.tif", SourceSchemaFilenameParser(), + ), + ProducedOutputSemantics.from_output( + producer, "/memory/other/A01_s001_w1_z001_t001.tif", + FunctionOutputIdentity( + component_values={"well": "A01", "site": 2, "channel": 1, "z_index": 1, "timepoint": 1}, + extension=".tif", source="test", + ), + ), + )) + class RejectImageCache: + def get(self, *_args, **_kwargs): + pytest.fail("Ambiguous producer admission must precede cached pixels") + + context = SimpleNamespace( + microscope_handler=SimpleNamespace(parser=SourceSchemaFilenameParser()), + runtime_image_stack_cache=RejectImageCache(), + ) + runtime = function_runtime.PatternGroupRuntime( + function_runtime.PatternGroupExecutionRequest( + context=context, execution_plan=plan, + compiled_group=plan.compiled_function_pattern.default_group, + pattern_group_info="A01_s001_w1_z001_t001.tif", component_index=0, component_count=1, + ) + ) + monkeypatch.setattr(function_runtime, "step_output_manifest", lambda _context: manifest) + monkeypatch.setattr(runtime, "source_workspace_projection_authority", lambda: SimpleNamespace( + projection_if_available=lambda: None, + )) + + with pytest.raises(NoStepOutputManifestMatch, match="found 2"): + runtime._load_input_stack() + + +def test_whole_volume_checkpoint_load_preserves_depth_and_independent_buffers(): + from openhcs.core.aligned_image_payload import ImagePayloadStackComposition + from openhcs.core.runtime_image_values import image_payload_mask + from openhcs.core.source_spatial_domain import VolumeSourceSpatialDomain + + pixels = np.arange(3 * 4 * 5, dtype=np.float32).reshape(3, 4, 5) + mask = pixels % 2 == 0 + metadata = ImagePayloadMetadata( + plane_axis=RuntimePlaneAxis.RUNTIME_SLICE, + source_spatial_domain=VolumeSourceSpatialDomain(source_depth=3), + ) + source = metadata.payload_with(pixels, mask) + plan = CompiledStepPlan( + step_index=0, + step_name="Volume", + step_type="FunctionStep", + axis_id="A01", + step_scope_id="volume", + input_memory_type="numpy", + ) + loaded = ImagePayloadStackComposition.from_loaded_images( + (source,), + producer_records=None, + execution_plan=plan, + source_projection=None, + workspace_source_lookups=(), + ) + assert image_payload_data(loaded).shape == pixels.shape + assert loaded.metadata.source_spatial_domain.source_depth == 3 + assert not np.shares_memory(image_payload_data(loaded), pixels) + assert not np.shares_memory(image_payload_mask(loaded), mask) + pixels[:] = -1 + mask[:] = False + assert np.all(image_payload_data(loaded) >= 0) + assert np.any(image_payload_mask(loaded)) diff --git a/tests/unit/test_function_step_execution_plan.py b/tests/unit/test_function_step_execution_plan.py index 1af5495d04..07c00a468a 100644 --- a/tests/unit/test_function_step_execution_plan.py +++ b/tests/unit/test_function_step_execution_plan.py @@ -276,7 +276,7 @@ def begin_step(self, plan, input_records=()): class ExecutionStub(function_execution.FunctionStepExecutor): def __init__(self): self.context = SimpleNamespace() - self.plan = SimpleNamespace( + self.plan = _compiled_plan( step_index=3, step_name="prepared-at-compile", axis_id="A01", @@ -302,12 +302,7 @@ def _apply_sequential_filter(self, patterns_by_axis): def _prepare_groups(self, patterns_by_axis): events.append(("groups", tuple(patterns_by_axis))) - return function_execution.PatternGroups.from_prepared( - {"default": ["image.tif"]} - ) - - def _preload_inputs_if_needed(self, grouped_patterns): - events.append(("preload", tuple(grouped_patterns.groups))) + return {None: ("image.tif",)} def _prepare_callables(self, grouped_patterns): raise AssertionError("callable warmup belongs to compilation") diff --git a/tests/unit/test_function_step_execution_scope.py b/tests/unit/test_function_step_execution_scope.py index 9836d217d2..246992ace6 100644 --- a/tests/unit/test_function_step_execution_scope.py +++ b/tests/unit/test_function_step_execution_scope.py @@ -23,7 +23,10 @@ SpecialArtifactType, ) from openhcs.core.callable_contract import CallableContract, FunctionStepExecutionScope -from openhcs.core.compiled_step_plan import CompiledStepPlan +from openhcs.core.compiled_step_plan import ( + CompiledStepPlan, + RuntimeArtifactMaterializationPlan, +) from openhcs.core.component_group_scope import RuntimeExecutionAxisScope from openhcs.core.component_group_scope import ComponentGroupScope from openhcs.core.component_set import ComponentSet @@ -58,7 +61,6 @@ PathPlannerStepAssemblyStage, PathPlannerValidationStage, ) -from openhcs.core.pipeline.step_snapshot import StepSnapshot from openhcs.core.runtime_artifact_values import RuntimeValue from openhcs.core.runtime_batch_contracts import RuntimeBatchExecutionDomain from openhcs.core.measurement_row_materialization import ( @@ -81,6 +83,8 @@ StepInputDependencyKind, ) from openhcs.core.steps.function_step import FunctionStep +from openhcs.microscopes.source_schema import SourceSchemaFilenameParser +from openhcs.processing.materialization import FileBundleOptions, MaterializationSpec def test_runtime_step_values_share_within_step_and_release_between_steps() -> None: @@ -129,6 +133,65 @@ def test_runtime_axis_scope_returns_none_only_without_declared_component_axis() ) +def test_runtime_axis_scope_joins_correlated_rows_without_inventing_states() -> None: + rows = tuple( + RuntimeExecutionAxisScope.from_raw( + "A01", component=None, value=None, + fixed_component_values=((AllComponents.SITE, site), (AllComponents.TIMEPOINT, timepoint)), + ) + for site, timepoint in (("1", "3"), ("2", "4")) + ) + time_three = RuntimeExecutionAxisScope.from_raw( + "A01", component=None, value=None, + fixed_component_values=((AllComponents.TIMEPOINT, "3"),), + ) + joined = tuple( + result for row in rows + if (result := row.join_execution_cohort(time_three)) is not None + ) + assert joined == (rows[0],) + assert rows[0].join_execution_cohort(rows[1]) is None + + +def test_runtime_axis_scope_empty_context_broadcasts_to_actual_correlated_row() -> None: + empty = RuntimeExecutionAxisScope.from_raw("A01", component=None, value=None) + source = RuntimeExecutionAxisScope.from_raw( + "A01", component=None, value=None, + fixed_component_values=((AllComponents.SITE, "1"), (AllComponents.TIMEPOINT, "3")), + ) + assert empty.join_execution_cohort(source) == source + assert source.join_execution_cohort(empty) == source + assert empty.join_execution_cohort(empty) == empty + + +@pytest.mark.parametrize("axis,component,value", [ + ("B01", AllComponents.CHANNEL, "1"), + ("A01", AllComponents.SITE, "1"), + ("A01", AllComponents.CHANNEL, "2"), +]) +def test_runtime_axis_scope_cannot_join_other_execution_group(axis, component, value) -> None: + own = RuntimeExecutionAxisScope.from_raw("A01", component=AllComponents.CHANNEL, value="1") + other = RuntimeExecutionAxisScope.from_raw(axis, component=component, value=value) + assert own.join_execution_cohort(other) is None + + +def test_runtime_axis_scope_join_derives_partial_fixed_context_union() -> None: + left = RuntimeExecutionAxisScope.from_raw( + "A01", component=None, value=None, + fixed_component_values=((AllComponents.SITE, "1"), (AllComponents.TIMEPOINT, "3")), + ) + right = RuntimeExecutionAxisScope.from_raw( + "A01", component=None, value=None, + fixed_component_values=((AllComponents.TIMEPOINT, "3"), (AllComponents.Z_INDEX, "2")), + ) + expected = RuntimeExecutionAxisScope.from_raw( + "A01", component=None, value=None, + fixed_component_values=((AllComponents.SITE, "1"), (AllComponents.TIMEPOINT, "3"), (AllComponents.Z_INDEX, "2")), + ) + assert left.join_execution_cohort(right) == expected + assert right.join_execution_cohort(left) == expected + + def test_function_step_execution_scope_is_exact_closed_enum() -> None: assert [(member.name, member.value) for member in FunctionStepExecutionScope] == [ ("AXIS", "axis"), @@ -163,11 +226,7 @@ def test_plate_scope_drives_no_main_flow_paths() -> None: output_dir = Path("/data/plate_processed/images") planner.paths = SimpleNamespace(build_output_path=lambda: output_dir) planner.steps = PathPlannerStepAssemblyStage(planner) - snapshot = StepSnapshot( - index=1, - scope_id="export", - step=FunctionStep(func=lambda image: image, name="export"), - ) + snapshot = FunctionStep(func=lambda image: image, name="export") dependency = planner.steps.main_input_dependency( snapshot, @@ -670,7 +729,7 @@ def export(*, artifact_batch: RuntimeArtifactBatch): assert events[-1].completed == events[-1].total == 2 -def test_plate_scope_observation_excludes_preexisting_runtime_history() -> None: +def test_plate_scope_observation_excludes_preexisting_runtime_history(tmp_path) -> None: output_spec = ArtifactSpec.output("ExportBundle", SpecialArtifactType) @execution_scope(FunctionStepExecutionScope.PLATE) @@ -678,7 +737,7 @@ def test_plate_scope_observation_excludes_preexisting_runtime_history() -> None: @artifact_outputs(output_spec) def export(*, artifact_batch: RuntimeArtifactBatch): del artifact_batch - return {"export.txt": b"data"} + return {"Image.csv": "ImageNumber,Count\r\n1,7\r\n"} plan = _plate_step_plan( axis_id="A01", @@ -689,10 +748,21 @@ def export(*, artifact_batch: RuntimeArtifactBatch): name=output_spec.name, path="/memory/plate/export", artifact_type=output_spec.artifact_type, + materialization=MaterializationSpec(FileBundleOptions()), ), metadata_writer=True, ) + plan.runtime_artifact_materialization = RuntimeArtifactMaterializationPlan( + persistent_enabled=True, persistent_backend=Backend.MEMORY.value, + ) + plan.output_plate_root = str(tmp_path) + plan.output_dir = tmp_path / "images" + plan.analysis_results_dir = str(tmp_path / "analysis") context = _plate_context("A01", (plan,)) + context.metadata_cache = {} + context.microscope_handler = SimpleNamespace( + parser=SourceSchemaFilenameParser(), microscope_type="test", + ) _record_measurements( context, name="prior_measurements", @@ -714,6 +784,16 @@ def export(*, artifact_batch: RuntimeArtifactBatch): assert {record.key.name for record in observation.contexts[0].records} == { output_spec.name } + analysis_inputs = observation.contexts[0].analysis_inputs + assert analysis_inputs is not None + assert analysis_inputs.destination.backend == Backend.MEMORY.value + (table,) = tuple( + output for group in analysis_inputs.outputs_by_directory.values() + for output in group + ) + assert table.csv_content == "ImageNumber,Count\r\n1,7\r\n" + assert table.well_id == "A01" + assert observation.contexts[0].runtime_export_paths == (table.path,) events = [ProgressEvent.from_dict(event) for event in progress_queue.events] assert events[-1].phase is ProgressPhase.STEP_COMPLETED @@ -883,7 +963,7 @@ def export(*, artifact_batch: RuntimeArtifactBatch): assert len(batches) == 1 selected = batches[0].records(measurement_spec.ref())["A01"] assert len(selected) == 2 - tables = tuple(record.value.data for record in selected) + tables = tuple(record.data for record in selected) assert all(isinstance(table, MeasurementTable) for table in tables) assert {table.subject.object_name for table in tables} == { "Nuclei", diff --git a/tests/unit/test_function_step_transport.py b/tests/unit/test_function_step_transport.py index 3d0bf7398d..47db0599aa 100644 --- a/tests/unit/test_function_step_transport.py +++ b/tests/unit/test_function_step_transport.py @@ -401,14 +401,11 @@ def test_bundle_transport_preserves_prepared_runtime_contract_identity() -> None ) from openhcs.core.compiled_step_plan import CompiledStepPlan from openhcs.core.context.processing_context import ProcessingContext - from openhcs.core.function_patterns import compile_function_pattern + from openhcs.core.function_patterns import compile_function_pattern, normalize_function_pattern from openhcs.core.orchestrator.execution_result import ( RuntimeExecutionTransportSerialization, ) - from openhcs.core.steps.function_runtime import ( - FunctionInvocationCallableCache, - FunctionInvocationCallableResolver, - ) + from openhcs.core.callable_contract import CallableContractRuntimeCache reference = FunctionReferenceTransportAuthority.function_reference( cellprofiler_backend.crop @@ -416,7 +413,28 @@ def test_bundle_transport_preserves_prepared_runtime_contract_identity() -> None reference = replace( reference, metadata=replace(reference.metadata, prepare=lambda: None) ) - pattern = compile_function_pattern(reference, {}, {}) + captured = normalize_function_pattern(reference) + captured_item = next(captured.iter_items()) + captured = replace( + captured, + groups=( + replace( + captured.groups[0], + items=( + replace( + captured_item, + contract=replace( + captured_item.contract, + metadata=replace( + captured_item.contract.metadata, prepare=lambda: None + ), + ), + ), + ), + ), + ), + ) + pattern = compile_function_pattern(captured, {}, {}) (invocation,) = tuple(pattern.iter_invocations()) invocation = replace( invocation, @@ -428,10 +446,10 @@ def test_bundle_transport_preserves_prepared_runtime_contract_identity() -> None pattern = replace( pattern, groups=(replace(pattern.groups[0], invocations=(invocation,)),) ) - prepared_callable = FunctionInvocationCallableResolver.resolve(invocation) + prepared_callable = invocation.contract.resolve_runtime_callable() plan = CompiledStepPlan( step_index=0, step_name="Crop", step_type="FunctionStep", axis_id="A01", - func=reference, compiled_function_pattern=pattern, + func=captured, compiled_function_pattern=pattern, ) context = ProcessingContext( axis_id="A01", step_plans={0: plan}, @@ -449,13 +467,16 @@ def test_bundle_transport_preserves_prepared_runtime_contract_identity() -> None transport_plan = transport_context.step_plans[0] assert transport_context is not context assert transport_plan is not plan - assert transport_plan.func.metadata.prepare is None + (transport_item,) = tuple(transport_plan.func.iter_items()) + assert transport_item.contract.metadata.prepare is None + assert transport_item.func.metadata.prepare is None (transport_invocation,) = tuple(transport_plan.compiled_function_pattern.iter_invocations()) assert transport_invocation.contract.metadata.prepare is None assert invocation.contract.metadata.prepare is not None - assert plan.func is reference and reference.metadata.prepare is not None + assert plan.func is captured and reference.metadata.prepare is not None + assert next(captured.iter_items()).contract.metadata.prepare is not None assert plan.compiled_function_pattern is pattern - assert FunctionInvocationCallableResolver.resolve(invocation) is prepared_callable + assert invocation.contract.resolve_runtime_callable() is prepared_callable assert transport_context.runtime_value_store is context.runtime_value_store assert transport_context.runtime_image_stack_cache is context.runtime_image_stack_cache assert transport_context.filemanager is context.filemanager @@ -467,15 +488,17 @@ def test_bundle_transport_preserves_prepared_runtime_contract_identity() -> None assert serialized_bundle.runtime_contexts is bundle.transport_contexts assert context.step_plans[0] is plan assert ( - FunctionInvocationCallableCache.process_cache().get_bound(invocation.contract) + CallableContractRuntimeCache.process_cache().get_bound(invocation.contract) is prepared_callable ) - assert FunctionInvocationCallableResolver.resolve(invocation) is prepared_callable + assert invocation.contract.resolve_runtime_callable() is prepared_callable RuntimeExecutionTransportSerialization.register() restored = pickle.loads(pickle.dumps(serialized_bundle)) restored_plan = restored.runtime_contexts["A01"].step_plans[0] - assert restored_plan.func.metadata.prepare is None - assert restored_plan.func.resolve() is reference.resolve() + (restored_item,) = tuple(restored_plan.func.iter_items()) + assert restored_item.contract.metadata.prepare is None + assert restored_item.func.metadata.prepare is None + assert restored_item.func.resolve() is reference.resolve() def test_generated_source_resolves_catalog_owned_cellprofiler_callable() -> None: diff --git a/tests/unit/test_graph_roi_source_roundtrip_134.py b/tests/unit/test_graph_roi_source_roundtrip_134.py index 83f0b9b478..7de36f894f 100644 --- a/tests/unit/test_graph_roi_source_roundtrip_134.py +++ b/tests/unit/test_graph_roi_source_roundtrip_134.py @@ -1,5 +1,7 @@ """Receiving #134: actual graph context/writer/ZIP, without a native process.""" +from openhcs.core.artifacts import ImageArtifactType + from pathlib import Path import numpy as np @@ -27,7 +29,7 @@ ) from openhcs.core.source_image_provenance import SourceImageProvenancePlanes from openhcs.core.source_metadata import SourceVoxelSpacing -from openhcs.core.steps.function_runtime import FunctionOutputContextStrategy + from openhcs.core.viewer_streaming_service import RoiStreamingRequest, StreamingService from openhcs.processing.materialization import ( MaterializationSpec, @@ -130,7 +132,7 @@ def contextualize(graph, plan): source_voxel_spacing=SourceVoxelSpacing(graph.coordinate_spacing), ) source = metadata.payload_with(np.zeros((2, 16, 16), dtype=np.uint8)) - result = FunctionOutputContextStrategy.for_output_plan(plan).contextualize( + result = (ImageArtifactType if plan is None else plan.artifact_type).contextualize_output( source, graph, plan, None ) assert result.source_provenance == metadata.source_provenance.for_source_plane( diff --git a/tests/unit/test_gray_to_color_binding_axis_432.py b/tests/unit/test_gray_to_color_binding_axis_432.py index a247b65a6f..321cc8ba0b 100644 --- a/tests/unit/test_gray_to_color_binding_axis_432.py +++ b/tests/unit/test_gray_to_color_binding_axis_432.py @@ -29,7 +29,9 @@ CellProfilerFunctionContractExecutor, ) from openhcs.interop.cellprofiler.runtime.module_execution import CellProfilerModuleExecutor -from openhcs.interop.cellprofiler.runtime.artifact_binding import RuntimeArtifactTypeStrategy +from openhcs.interop.cellprofiler.runtime.output_recording import ( + CellProfilerOutputRecorder, +) from openhcs.processing.backends.cellprofiler.color import GrayToColorModule, gray_to_color from test_cellprofiler_generic_special_input_binding import _compile_public_step from tests.unit.cellprofiler_runtime_test_support import cellprofiler_runtime_adapter_for_test @@ -193,7 +195,7 @@ def test_integer_primary_binding_units_are_owned_before_stack_rescale_flag(): pixels = np.arange(20, dtype=np.uint16).reshape(4, 5) * 1000 source = _source_plane(pixels, "FITC") spec = ArtifactSpec.input("FITC", ImageArtifactType) - binding_owner = RuntimeArtifactTypeStrategy.for_artifact_type(ImageArtifactType) + binding_owner = CellProfilerOutputRecorder.for_artifact_type(ImageArtifactType) bound = binding_owner.runtime_input_value(spec, source) # This conversion happens in the original input owner, before GrayToColor's # rescale_intensity argument. Do not claim a raw-unit-preserving four-step fix diff --git a/tests/unit/test_image_file_serialization.py b/tests/unit/test_image_file_serialization.py index 5646baefa8..fee02e3021 100644 --- a/tests/unit/test_image_file_serialization.py +++ b/tests/unit/test_image_file_serialization.py @@ -507,3 +507,31 @@ def test_png_image_format_uses_registered_png_leaf() -> None: def test_unknown_image_serialization_suffix_fails_loudly(path) -> None: with pytest.raises(ValueError, match="image|suffix|format"): ImageFileFormat.require_path(path) + + +@pytest.mark.parametrize("channel_axis", (None, -1, 1)) +def test_intrinsic_tiff_write_uses_declared_axes_not_rgb_shaped_dimensions( + tmp_path, channel_axis +): + from openhcs.core.source_spatial_domain import VolumeSourceSpatialDomain + + shape = ( + (3, 4, 4) + if channel_axis is None + else ((3, 4, 4, 3) if channel_axis == -1 else (3, 3, 4, 4)) + ) + pixels = np.arange(np.prod(shape), dtype=np.uint16).reshape(shape) + metadata = ImagePayloadMetadata( + plane_axis=RuntimePlaneAxis.RUNTIME_SLICE, + source_channel_axis=channel_axis, + source_spatial_domain=VolumeSourceSpatialDomain(source_depth=3), + ) + path = tmp_path / "volume.tif" + image_format = TiffImageFileFormat() + image_format.write(path, metadata.payload_with(pixels)) + np.testing.assert_array_equal(image_format.read(path), pixels) + header = image_format.require_source_metadata(path) + assert header.source_frame_shape == ((3,) if channel_axis != 1 else None) + assert header.pixel_semantics.channel_axis == channel_axis + assert header.pixel_semantics.channel_count == (None if channel_axis is None else 3) + assert header.image_shape_yx == (4, 4) diff --git a/tests/unit/test_image_output_context_projection_proof.py b/tests/unit/test_image_output_context_projection_proof.py index 7c42a5fa1d..69ff1c7be4 100644 --- a/tests/unit/test_image_output_context_projection_proof.py +++ b/tests/unit/test_image_output_context_projection_proof.py @@ -20,24 +20,21 @@ RuntimePlaneProjection, ) from openhcs.core.source_image_provenance import SourceImageProvenancePlanes -from openhcs.core.steps.function_runtime import ( - FunctionOutputContextStrategy, - ImageFunctionOutputContextStrategy, -) + def _track_ownership_proofs( monkeypatch: pytest.MonkeyPatch, ) -> list[tuple[object, ...]]: proof_calls: list[tuple[object, ...]] = [] - original = ImageFunctionOutputContextStrategy.output_owns_source_context + original = ImageArtifactType.output_owns_source_context def record_proof(*args: object) -> bool: proof_calls.append(args) return original(*args) monkeypatch.setattr( - ImageFunctionOutputContextStrategy, + ImageArtifactType, "output_owns_source_context", staticmethod(record_proof), ) @@ -108,9 +105,7 @@ def test_projected_variable_stack_proves_source_ownership_once( ) proof_calls = _track_ownership_proofs(monkeypatch) - result = FunctionOutputContextStrategy.for_output_plan( - output_plan, - ).contextualize_from_projector( + result = (ImageArtifactType if output_plan is None else output_plan.artifact_type).contextualize_output_from_projector( source, output, output_plan, @@ -152,9 +147,7 @@ def test_derived_2d_image_does_not_inherit_input_runtime_plane_axis() -> None: relations=(GroupLineageSourceRelation(source_spec.ref()),), ) - result = FunctionOutputContextStrategy.for_output_plan( - output_plan, - ).contextualize_from_projector( + result = (ImageArtifactType if output_plan is None else output_plan.artifact_type).contextualize_output_from_projector( source, image_payload_metadata(source) .collapse_leading_plane_axis() @@ -182,9 +175,7 @@ def test_bare_full_stack_image_inherits_source_runtime_plane_axis() -> None: relations=(GroupLineageSourceRelation(source_spec.ref()),), ) - result = FunctionOutputContextStrategy.for_output_plan( - output_plan, - ).contextualize_from_projector( + result = (ImageArtifactType if output_plan is None else output_plan.artifact_type).contextualize_output_from_projector( source, np.ones((2, 4, 5), dtype=np.float32), output_plan, @@ -212,9 +203,7 @@ def test_derived_image_preserves_explicit_output_runtime_plane_axis() -> None: relations=(GroupLineageSourceRelation(source_spec.ref()),), ) - result = FunctionOutputContextStrategy.for_output_plan( - output_plan, - ).contextualize_from_projector( + result = (ImageArtifactType if output_plan is None else output_plan.artifact_type).contextualize_output_from_projector( source, output, output_plan, @@ -270,9 +259,7 @@ def test_projected_crop_preserves_complete_spatial_domain_after_plane_compositio relations=(GroupLineageSourceRelation(source_spec.ref()),), ) - result = FunctionOutputContextStrategy.for_output_plan( - output_plan, - ).contextualize_from_projector( + result = (ImageArtifactType if output_plan is None else output_plan.artifact_type).contextualize_output_from_projector( source, output, output_plan, @@ -291,9 +278,7 @@ def test_projected_scalar_rgb_proves_complete_identity_once( source, output, output_plan = _scalar_rgb_output() proof_calls = _track_ownership_proofs(monkeypatch) - result = FunctionOutputContextStrategy.for_output_plan( - output_plan, - ).contextualize_from_projector( + result = (ImageArtifactType if output_plan is None else output_plan.artifact_type).contextualize_output_from_projector( source, output, output_plan, @@ -316,9 +301,7 @@ def test_owned_variable_output_without_projector_returns_after_one_proof( source, output, output_plan = _scalar_rgb_output() proof_calls = _track_ownership_proofs(monkeypatch) - result = FunctionOutputContextStrategy.for_output_plan( - output_plan, - ).contextualize_from_projector( + result = (ImageArtifactType if output_plan is None else output_plan.artifact_type).contextualize_output_from_projector( source, output, output_plan, @@ -347,9 +330,7 @@ def test_unowned_variable_output_without_projector_preserves_error( ValueError, match="runtime invocation supplies no plane projector", ): - FunctionOutputContextStrategy.for_output_plan( - output_plan, - ).contextualize_from_projector( + (ImageArtifactType if output_plan is None else output_plan.artifact_type).contextualize_output_from_projector( np.ones((2, 4, 5), dtype=np.float32), np.ones((2, 4, 5), dtype=np.uint16), output_plan, diff --git a/tests/unit/test_image_payload_projection_algebra.py b/tests/unit/test_image_payload_projection_algebra.py new file mode 100644 index 0000000000..677ed7beb1 --- /dev/null +++ b/tests/unit/test_image_payload_projection_algebra.py @@ -0,0 +1,495 @@ +"""Physical source-plane projection preserves composition and mutable isolation.""" + +from dataclasses import fields + +import numpy as np +import pytest + +from openhcs.core.runtime_image_values import ( + ImagePayloadMetadata, + ImagePayloadSliceProjector, + ImageUnitIntervalIntensityMetadata, + image_payload_mask, + image_payload_metadata, +) +from openhcs.core.runtime_plane_projection import RuntimePlaneAxis +from openhcs.core.source_image_provenance import ( + RuntimeSourceImageProvenancePlane, + SourceImageIdentity, + SourceImageProvenanceContributor, + SourceImageProvenancePlanes, +) +from openhcs.core.source_spatial_domain import SourceSpatialDomain + + +def _metadata(axis, channel_axis): + return ImagePayloadMetadata( + source_path="/tmp/parent.tif", + source_component_metadata={"well": "A01", "extension": ".tif"}, + source_image_provenance_planes=SourceImageProvenancePlanes.from_components( + paths=("/tmp/first.tif", "/tmp/second.tif"), + component_metadata=({"site": "1"}, {"site": "2"}), + ), + intensity_scale=255.0, + source_dtype="uint8", + source_plane_intensity_scales=(255.0, 65535.0), + source_plane_dtypes=("uint8", "uint16"), + unit_interval_intensity=ImageUnitIntervalIntensityMetadata( + scale=255, source_plane_scales=(255, 65535) + ), + source_image_names=("DNA", "RNA"), + source_channel_axis=channel_axis, + plane_axis=axis, + ) + + +@pytest.mark.parametrize("axis", tuple(RuntimePlaneAxis)) +@pytest.mark.parametrize("channel_axis", (None, 1, 3, -1)) +@pytest.mark.parametrize("plane", (0, 1)) +def test_physical_projection_agrees_with_separate_semantic_operations( + axis, channel_axis, plane +): + metadata = _metadata(axis, channel_axis) + sequential = metadata.for_source_plane(plane).without_leading_plane_axis() + projected = metadata.for_leading_source_plane(plane) + for member in fields(ImagePayloadMetadata): + assert getattr(projected, member.name) == getattr(sequential, member.name) + assert projected.source_path == ("/tmp/first.tif", "/tmp/second.tif")[plane] + assert projected.source_component_metadata["well"] == "A01" + assert projected.source_component_metadata["site"] == str(plane + 1) + assert projected.unit_interval_intensity.scale == (255, 65535)[plane] + assert projected.source_plane_intensity_scales == () + assert projected.source_plane_dtypes == () + assert projected.plane_axis is None + projected.source_provenance.source_identity.path = "/tmp/changed.tif" + assert metadata.source_path == "/tmp/parent.tif" + assert metadata.source_image_provenance_planes.paths[plane] != "/tmp/changed.tif" + + +def test_physical_projection_constructs_only_the_final_metadata(monkeypatch): + metadata = _metadata(RuntimePlaneAxis.RUNTIME_SLICE, None) + calls = [] + original = ImagePayloadMetadata.__post_init__ + + def observe(self, *values): + calls.append(self) + original(self, *values) + + monkeypatch.setattr(ImagePayloadMetadata, "__post_init__", observe) + projected = metadata.for_leading_source_plane(1) + assert calls == [projected] + + +def test_physical_projection_rejects_leading_channel_axis(): + metadata = _metadata(RuntimePlaneAxis.RUNTIME_SLICE, 0) + with pytest.raises(ValueError, match="both plane and channel"): + metadata.for_leading_source_plane(1) + + +def test_physical_projection_requires_declared_plane_axis(): + metadata = _metadata(None, None) + with pytest.raises(ValueError, match="declared plane axis"): + metadata.for_leading_source_plane(1) + + +@pytest.mark.parametrize("channel_axis", (False, True, "1", 1.5)) +def test_physical_projection_preserves_invalid_mutated_channel_error(channel_axis): + metadata = _metadata(RuntimePlaneAxis.RUNTIME_SLICE, None) + metadata.source_channel_axis = channel_axis + with pytest.raises(TypeError, match="must be int or None"): + metadata.for_source_plane(1).without_leading_plane_axis() + with pytest.raises(TypeError, match="must be int or None"): + metadata.for_leading_source_plane(1) + + +def test_physical_projection_preserves_invalid_mutated_plane_error(): + metadata = _metadata(RuntimePlaneAxis.RUNTIME_SLICE, None) + metadata.plane_axis = "invalid-axis" + with pytest.raises(ValueError): + metadata.for_source_plane(1).without_leading_plane_axis() + with pytest.raises(ValueError): + metadata.for_leading_source_plane(1) + + +def test_projection_preserves_selected_spacing_and_nested_contributors(): + contributor = SourceImageProvenanceContributor( + SourceImageIdentity("/tmp/contributor.tif", {"site": "3"}), + source_image_name="Original", + ) + metadata = ImagePayloadMetadata( + plane_axis=RuntimePlaneAxis.SOURCE_BINDING, + source_image_provenance_planes=SourceImageProvenancePlanes( + ( + RuntimeSourceImageProvenancePlane( + SourceImageIdentity( + "/tmp/selected.tif", + {"OpenHCSSourceVoxelSpacingZYX": "4,2,1"}, + ), + contributors=(contributor,), + source_image_name="DNA", + ), + ) + ), + ) + sequential = metadata.for_source_plane(0).without_leading_plane_axis() + projected = metadata.for_leading_source_plane(0) + for member in fields(ImagePayloadMetadata): + assert getattr(projected, member.name) == getattr(sequential, member.name) + assert projected.source_image_provenance_planes.planes == (contributor,) + + +def test_projection_observes_mask_and_metadata_mutation(): + metadata = _metadata(RuntimePlaneAxis.RUNTIME_SLICE, None) + mask = np.ones((2, 3, 4), dtype=bool) + projector = ImagePayloadSliceProjector(mask, metadata) + data = np.zeros((3, 4)) + first = projector.payload_for_slice(data, 1) + assert image_payload_metadata(first).intensity_scale == 65535.0 + metadata.source_plane_intensity_scales = (1.0, 2.0) + mask[1, 0, 0] = False + second = projector.payload_for_slice(data, 1) + assert image_payload_metadata(second).intensity_scale == 2.0 + assert not image_payload_mask(second)[0, 0] + mask.resize((2, 2, 6), refcheck=False) + with pytest.raises(ValueError, match="cannot be projected"): + projector.payload_for_slice(data, 1) + + +def _metadata_with_observed_plane_fields(*, proof_raises=False): + events = [] + + class ObservedInt(int): + def __int__(self): + events.append("proof-int") + if proof_raises: + raise RuntimeError("proof conversion observed") + return 1 + + class ObservedTuple(tuple): + def __getitem__(self, index): + events.append("intensity-getitem") + return super().__getitem__(index) + + metadata = ImagePayloadMetadata( + plane_axis=RuntimePlaneAxis.RUNTIME_SLICE, + source_plane_intensity_scales=ObservedTuple((2.0,)), + unit_interval_intensity=ImageUnitIntervalIntensityMetadata( + source_plane_scales=(ObservedInt(1),) + ), + ) + return metadata, events + + +def test_plane_proof_failure_precedes_leading_channel_guard(): + metadata, events = _metadata_with_observed_plane_fields(proof_raises=True) + metadata.source_channel_axis = 0 + with pytest.raises(RuntimeError, match="proof conversion observed"): + metadata.for_leading_source_plane(0) + assert events == ["intensity-getitem", "proof-int"] + + +def test_plane_field_effects_precede_leading_channel_guard(): + metadata, events = _metadata_with_observed_plane_fields() + metadata.source_channel_axis = 0 + with pytest.raises(ValueError, match="both plane and channel"): + metadata.for_leading_source_plane(0) + assert events == ["intensity-getitem", "proof-int"] + + +def test_source_plane_preserves_intensity_then_proof_effect_order(): + metadata, events = _metadata_with_observed_plane_fields() + projected = metadata.for_source_plane(0) + assert events == ["intensity-getitem", "proof-int"] + assert projected.intensity_scale == 2.0 + assert projected.unit_interval_intensity.scale == 1 + + +def test_plane_proof_failure_precedes_mutated_channel_type_guard(): + metadata, events = _metadata_with_observed_plane_fields(proof_raises=True) + metadata.source_channel_axis = False + with pytest.raises(RuntimeError, match="proof conversion observed"): + metadata.for_leading_source_plane(0) + assert events == ["intensity-getitem", "proof-int"] + + +@pytest.mark.parametrize( + "operation,channel_axis,broken,error,message", + ( + ("for_leading_source_plane", 0, "domain", ValueError, "spatial_origin_yx"), + ("for_leading_source_plane", 0, "spacing", ValueError, "finite and positive"), + ( + "for_leading_source_plane", + 0, + "spacing-value", + AttributeError, + "with_missing_from", + ), + ("for_leading_source_plane", 0, "plane", ValueError, "invalid-axis"), + ("for_leading_source_plane", False, "domain", ValueError, "spatial_origin_yx"), + ( + "for_leading_source_plane", + False, + "spacing", + ValueError, + "finite and positive", + ), + ("for_leading_source_plane", False, "plane", TypeError, "must be int or None"), + ("for_source_plane", False, "domain", ValueError, "spatial_origin_yx"), + ("for_source_plane", False, "spacing", ValueError, "finite and positive"), + ( + "for_source_plane", + False, + "spacing-value", + AttributeError, + "with_missing_from", + ), + ("for_source_plane", False, "plane", TypeError, "must be int or None"), + ( + "without_leading_plane_axis", + 0, + "domain", + ValueError, + "both plane and channel", + ), + ( + "without_leading_plane_axis", + 0, + "spacing", + ValueError, + "both plane and channel", + ), + ( + "without_leading_plane_axis", + 0, + "spacing-value", + ValueError, + "both plane and channel", + ), + ( + "without_leading_plane_axis", + 0, + "plane", + ValueError, + "both plane and channel", + ), + ("without_leading_plane_axis", "1", "plane", TypeError, "not supported"), + ), +) +def test_projection_preserves_cross_invalid_constructor_guard_order( + operation, channel_axis, broken, error, message +): + metadata = ImagePayloadMetadata( + source_path="/tmp/source.tif", + plane_axis=RuntimePlaneAxis.RUNTIME_SLICE, + ) + metadata.source_channel_axis = channel_axis + if broken == "domain": + metadata.source_spatial_domain = SourceSpatialDomain(origin_yx=(1,)) + elif broken == "spacing": + metadata.source_component_metadata = {"OpenHCSSourceVoxelSpacingZYX": "0,1,1"} + elif broken == "spacing-value": + metadata.source_voxel_spacing = None + else: + metadata.plane_axis = "invalid-axis" + with pytest.raises(error, match=message): + if operation == "without_leading_plane_axis": + metadata.without_leading_plane_axis() + else: + getattr(metadata, operation)(0) + + +def test_missing_leading_axis_precedes_plane_field_effects(): + metadata, events = _metadata_with_observed_plane_fields(proof_raises=True) + metadata.plane_axis = None + metadata.source_channel_axis = 0 + with pytest.raises(ValueError, match="requires a declared plane axis"): + metadata.for_leading_source_plane(0) + assert events == [] + + +def test_projection_spacing_failure_precedes_other_invalid_source_fields(): + metadata = ImagePayloadMetadata(plane_axis=RuntimePlaneAxis.RUNTIME_SLICE) + metadata.source_component_metadata = {"OpenHCSSourceVoxelSpacingZYX": "0,1,1"} + metadata.source_spatial_domain = SourceSpatialDomain(origin_yx=(1,)) + metadata.source_channel_axis = False + metadata.plane_axis = "invalid-axis" + with pytest.raises(ValueError, match="finite and positive"): + metadata.for_leading_source_plane(0) + + +@pytest.mark.parametrize( + "operation,normalization_axes", + ( + ("without_leading_plane_axis", (RuntimePlaneAxis.RUNTIME_SLICE, None)), + ( + "for_leading_source_plane", + (RuntimePlaneAxis.RUNTIME_SLICE, RuntimePlaneAxis.RUNTIME_SLICE, None), + ), + ), +) +def test_projection_normalizes_owned_metadata_at_each_historical_phase( + monkeypatch, operation, normalization_axes +): + metadata = _metadata(RuntimePlaneAxis.RUNTIME_SLICE, 2) + input_provenance = metadata.source_provenance + input_proof = metadata.unit_interval_intensity + births = [] + phases = [] + original_constructor = ImagePayloadMetadata.__post_init__ + original_normalize = ImagePayloadMetadata.normalize_metadata_fields + + def observe_constructor(self, *values): + births.append((self, self.plane_axis, self.source_channel_axis)) + original_constructor(self, *values) + + def observe_normalization(self): + phases.append((self, self.plane_axis, self.source_channel_axis)) + original_normalize(self) + + monkeypatch.setattr(ImagePayloadMetadata, "__post_init__", observe_constructor) + monkeypatch.setattr( + ImagePayloadMetadata, "normalize_metadata_fields", observe_normalization + ) + projected = ( + metadata.without_leading_plane_axis() + if operation == "without_leading_plane_axis" + else metadata.for_leading_source_plane(1) + ) + + assert births == [(projected, RuntimePlaneAxis.RUNTIME_SLICE, 2)] + assert tuple(axis for _, axis, _ in phases) == normalization_axes + assert all(owner is projected for owner, _, _ in phases) + assert tuple(channel for _, _, channel in phases) == (2,) * ( + len(normalization_axes) - 1 + ) + (1,) + assert projected is not metadata + assert metadata.source_provenance is input_provenance + assert metadata.unit_interval_intensity is input_proof + assert metadata.plane_axis is RuntimePlaneAxis.RUNTIME_SLICE + assert metadata.source_channel_axis == 2 + assert metadata.source_plane_intensity_scales == (255.0, 65535.0) + assert projected.source_provenance is not input_provenance + assert projected.unit_interval_intensity is not input_proof + + +@pytest.mark.parametrize("combined", (False, True)) +def test_projection_preserves_contributor_derivation_constructor_error_order( + monkeypatch, combined +): + metadata = _metadata(RuntimePlaneAxis.RUNTIME_SLICE, None) + invalid_domain = SourceSpatialDomain(origin_yx=(1,)) + metadata.source_spatial_domain = invalid_domain + provenance = metadata.source_provenance + calls = [] + + def fail_contributors(self): + calls.append(self) + raise RuntimeError("contributor derivation observed") + + monkeypatch.setattr( + type(provenance), "with_runtime_planes_as_contributors", fail_contributors + ) + if combined: + with pytest.raises(ValueError, match="spatial_origin_yx"): + metadata.for_leading_source_plane(1) + assert calls == [] + else: + with pytest.raises(RuntimeError, match="contributor derivation observed"): + metadata.without_leading_plane_axis() + assert calls == [provenance] + assert metadata.source_provenance is provenance + assert metadata.source_spatial_domain is invalid_domain + assert metadata.plane_axis is RuntimePlaneAxis.RUNTIME_SLICE + assert metadata.source_plane_intensity_scales == (255.0, 65535.0) + + +@pytest.mark.parametrize("combined", (False, True)) +def test_failed_owned_axis_transform_does_not_mutate_source(monkeypatch, combined): + metadata = _metadata(RuntimePlaneAxis.RUNTIME_SLICE, 2) + provenance = metadata.source_provenance + proof = metadata.unit_interval_intensity + + def fail_proof(self): + raise RuntimeError("axis proof derivation observed") + + monkeypatch.setattr( + ImageUnitIntervalIntensityMetadata, "without_source_planes", fail_proof + ) + with pytest.raises(RuntimeError, match="axis proof derivation observed"): + if combined: + metadata.for_leading_source_plane(1) + else: + metadata.without_leading_plane_axis() + assert metadata.source_provenance is provenance + assert metadata.unit_interval_intensity is proof + assert metadata.plane_axis is RuntimePlaneAxis.RUNTIME_SLICE + assert metadata.source_channel_axis == 2 + assert metadata.source_plane_intensity_scales == (255.0, 65535.0) + assert metadata.source_plane_dtypes == ("uint8", "uint16") + + +@pytest.mark.parametrize( + "plane_index,expected_scale", + ((None, 255), (-1, 255), (0, 255), (1, 65535), (2, 255)), +) +def test_owned_proof_projection_preserves_scalar_fallback_and_axis_removal( + plane_index, expected_scale +): + proof = ImageUnitIntervalIntensityMetadata( + scale=255, source_plane_scales=(None, 65535) + ) + metadata = ImagePayloadMetadata(unit_interval_intensity=proof) + projected = metadata.project_intensity_proof(plane_index) + assert projected is not proof + assert projected.scale == expected_scale + assert projected.source_plane_scales == () + assert metadata.unit_interval_intensity is proof + assert proof.source_plane_scales == (None, 65535) + if plane_index is not None: + assert metadata.unit_interval_intensity_scale_for_source_plane(plane_index) == ( + expected_scale + ) + + +@pytest.mark.parametrize("plane_index", (None, 0, 1)) +def test_owned_proof_projection_observes_absence_and_live_replacement(plane_index): + metadata = ImagePayloadMetadata(intensity_scale=255) + assert metadata.project_intensity_proof(plane_index) is None + if plane_index is not None: + assert ( + metadata.unit_interval_intensity_scale_for_source_plane(plane_index) is None + ) + proof = ImageUnitIntervalIntensityMetadata(scale=7, source_plane_scales=(11, 13)) + metadata.unit_interval_intensity = proof + assert metadata.project_intensity_proof(plane_index).scale == ( + 7 if plane_index is None else (11, 13)[plane_index] + ) + metadata.unit_interval_intensity = None + assert metadata.project_intensity_proof(plane_index) is None + + +def test_quantization_queries_preserve_integer_conversion_and_fallback_identity(): + calls = [] + + class ObservedInt(int): + def __int__(self): + calls.append(self) + return super().__int__() + + scalar = ObservedInt(255) + plane = ObservedInt(65535) + metadata = ImagePayloadMetadata( + unit_interval_intensity=ImageUnitIntervalIntensityMetadata( + scale=scalar, source_plane_scales=(None, plane) + ) + ) + assert metadata.unit_interval_intensity_scale_for_source_plane(0) is scalar + assert metadata.unit_interval_intensity_scale_for_source_plane(-1) is scalar + assert calls == [] + assert metadata.unit_interval_intensity_scale_for_source_plane(1) == 65535 + assert calls == [plane] + calls.clear() + assert metadata.project_intensity_proof(1).scale == 65535 + assert calls == [plane] + assert metadata.project_intensity_proof(None).scale is scalar + assert calls == [plane] diff --git a/tests/unit/test_implicit_main_flow_compilation.py b/tests/unit/test_implicit_main_flow_compilation.py index 4027933d56..5fc5263d3f 100644 --- a/tests/unit/test_implicit_main_flow_compilation.py +++ b/tests/unit/test_implicit_main_flow_compilation.py @@ -94,6 +94,6 @@ def test_native_grouped_main_flow_compiles_into_cellprofiler_consumer(tmp_path): assert threshold_plan.compiled_function_pattern is not None invocation = next(threshold_plan.compiled_function_pattern.iter_invocations()) (edge,) = invocation.artifact_input_edges - assert edge.consumes_main_flow + assert (edge.main_flow_projection is not None) assert edge.storage_plan is None assert invocation.contract.execution_scope is FunctionStepExecutionScope.AXIS diff --git a/tests/unit/test_invocation_contract_provider.py b/tests/unit/test_invocation_contract_provider.py index b987982643..6172ab7bbb 100644 --- a/tests/unit/test_invocation_contract_provider.py +++ b/tests/unit/test_invocation_contract_provider.py @@ -2,6 +2,8 @@ from __future__ import annotations +from openhcs.core.pipeline.compilation_session import ResolvedPipelineDefinition + from dataclasses import fields, replace import importlib from types import MappingProxyType, SimpleNamespace @@ -642,7 +644,6 @@ def test_cellprofiler_provider_reconstructs_exact_contract_from_public_step() -> ) from openhcs.core.context.processing_context import ProcessingContext from openhcs.core.pipeline.compilation_session import CompilationSession - from openhcs.core.pipeline.step_snapshot import StepSnapshot from openhcs.core.source_bindings import ( NamedSourceBinding, StepSourceBindingsConfig, @@ -680,9 +681,7 @@ def test_cellprofiler_provider_reconstructs_exact_contract_from_public_step() -> ), ), ) - snapshot = StepSnapshot( - index=0, scope_id="provider-test::functionstep_0", step=step - ) + snapshot = step session = CompilationSession.from_context( context=ProcessingContext( step_plans={ @@ -695,11 +694,12 @@ def test_cellprofiler_provider_reconstructs_exact_contract_from_public_step() -> }, axis_id="A01", ), - steps=(step,), orchestrator=SimpleNamespace(pipeline_config=PipelineConfig()), global_config=GlobalPipelineConfig(), - step_state_map={0: object()}, - snapshots=(snapshot,), + pipeline=ResolvedPipelineDefinition( + steps=(snapshot,), + step_state_map={0: SimpleNamespace(scope_id="plate::functionstep_0")}, + ), ) callable_state = vars(color_to_gray).copy() @@ -738,7 +738,6 @@ def test_cellprofiler_provider_advances_native_artifacts_through_generic_graph() from openhcs.core.config import GlobalPipelineConfig, PipelineConfig from openhcs.core.context.processing_context import ProcessingContext from openhcs.core.pipeline.compilation_session import CompilationSession - from openhcs.core.pipeline.step_snapshot import StepSnapshot from openhcs.core.steps.function_step import FunctionStep from openhcs.interop.cellprofiler.compile_time_contracts import ( CellProfilerInvocationContractProvider, @@ -759,13 +758,7 @@ def test_cellprofiler_provider_advances_native_artifacts_through_generic_graph() name="ColorToGray", ) - def snapshot(index: int, step: FunctionStep) -> StepSnapshot: - return StepSnapshot( - index=index, scope_id=f"mixed-provider::functionstep_{index}", step=step - ) - steps = (native_step, cellprofiler_step) - snapshots = tuple(snapshot(index, step) for index, step in enumerate(steps)) plans = { index: CompiledStepPlan( step_index=index, @@ -777,11 +770,15 @@ def snapshot(index: int, step: FunctionStep) -> StepSnapshot: } session = CompilationSession.from_context( context=ProcessingContext(step_plans=plans, axis_id="A01"), - steps=steps, orchestrator=SimpleNamespace(pipeline_config=PipelineConfig()), global_config=GlobalPipelineConfig(), - step_state_map={0: object(), 1: object()}, - snapshots=snapshots, + pipeline=ResolvedPipelineDefinition( + steps=steps, + step_state_map={ + 0: SimpleNamespace(scope_id="plate::functionstep_0"), + 1: SimpleNamespace(scope_id="plate::functionstep_1"), + }, + ), ) provider = CellProfilerInvocationContractProviderFactory.provider_for_session( @@ -812,7 +809,6 @@ def test_cellprofiler_provider_leaves_native_same_name_callable_unclaimed() -> N from openhcs.core.config import GlobalPipelineConfig, PipelineConfig from openhcs.core.context.processing_context import ProcessingContext from openhcs.core.pipeline.compilation_session import CompilationSession - from openhcs.core.pipeline.step_snapshot import StepSnapshot from openhcs.core.steps.function_step import FunctionStep from openhcs.interop.cellprofiler.compile_time_contracts import ( CellProfilerInvocationContractProviderFactory, @@ -820,11 +816,7 @@ def test_cellprofiler_provider_leaves_native_same_name_callable_unclaimed() -> N from openhcs.processing.backends.processors.numpy_processor import crop step = FunctionStep(func=crop, name="Native NumPy crop") - snapshot = StepSnapshot( - index=0, - scope_id="native-crop-provider::functionstep_0", - step=step, - ) + snapshot = step session = CompilationSession.from_context( context=ProcessingContext( step_plans={ @@ -837,11 +829,12 @@ def test_cellprofiler_provider_leaves_native_same_name_callable_unclaimed() -> N }, axis_id="A01", ), - steps=(step,), orchestrator=SimpleNamespace(pipeline_config=PipelineConfig()), global_config=GlobalPipelineConfig(), - step_state_map={0: object()}, - snapshots=(snapshot,), + pipeline=ResolvedPipelineDefinition( + steps=(snapshot,), + step_state_map={0: SimpleNamespace(scope_id="plate::functionstep_0")}, + ), ) provider = CellProfilerInvocationContractProviderFactory.provider_for_session( @@ -1125,7 +1118,6 @@ def test_cellprofiler_provider_rejects_under_specified_one_image_align() -> None ) from openhcs.core.context.processing_context import ProcessingContext from openhcs.core.pipeline.compilation_session import CompilationSession - from openhcs.core.pipeline.step_snapshot import StepSnapshot from openhcs.core.source_bindings import ( NamedSourceBinding, StepSourceBindingsConfig, @@ -1152,11 +1144,7 @@ def test_cellprofiler_provider_rejects_under_specified_one_image_align() -> None ), ), ) - snapshot = StepSnapshot( - index=0, - scope_id="align-cardinality::functionstep_0", - step=step, - ) + snapshot = step session = CompilationSession.from_context( context=ProcessingContext( step_plans={ @@ -1169,11 +1157,12 @@ def test_cellprofiler_provider_rejects_under_specified_one_image_align() -> None }, axis_id="A01", ), - steps=(step,), orchestrator=SimpleNamespace(pipeline_config=PipelineConfig()), global_config=GlobalPipelineConfig(), - step_state_map={0: object()}, - snapshots=(snapshot,), + pipeline=ResolvedPipelineDefinition( + steps=(snapshot,), + step_state_map={0: SimpleNamespace(scope_id="plate::functionstep_0")}, + ), ) with pytest.raises( @@ -1255,7 +1244,6 @@ def test_calculate_math_provider_keeps_object_identity_and_output_name_public() from openhcs.core.config import GlobalPipelineConfig, PipelineConfig from openhcs.core.context.processing_context import ProcessingContext from openhcs.core.pipeline.compilation_session import CompilationSession - from openhcs.core.pipeline.step_snapshot import StepSnapshot from openhcs.core.source_bindings import ( NamedSourceBinding, SourceProjectionRole, @@ -1303,14 +1291,7 @@ def test_calculate_math_provider_keeps_object_identity_and_output_name_public() name="CalculateMath", source_bindings=measurement_step.source_bindings, ) - snapshots = tuple( - StepSnapshot( - index=index, - scope_id=f"calculate-math-provider::functionstep_{index}", - step=current_step, - ) - for index, current_step in enumerate((measurement_step, step)) - ) + steps = (measurement_step, step) session = CompilationSession.from_context( context=ProcessingContext( step_plans={ @@ -1324,11 +1305,15 @@ def test_calculate_math_provider_keeps_object_identity_and_output_name_public() }, axis_id="A01", ), - steps=(measurement_step, step), orchestrator=SimpleNamespace(pipeline_config=PipelineConfig()), global_config=GlobalPipelineConfig(), - step_state_map={0: object(), 1: object()}, - snapshots=snapshots, + pipeline=ResolvedPipelineDefinition( + steps=steps, + step_state_map={ + 0: SimpleNamespace(scope_id="plate::functionstep_0"), + 1: SimpleNamespace(scope_id="plate::functionstep_1"), + }, + ), ) provider = CellProfilerInvocationContractProviderFactory.provider_for_session( @@ -1387,7 +1372,6 @@ def test_native_unnamed_main_flow_remains_a_canonical_contract_input() -> None: ) from openhcs.core.context.processing_context import ProcessingContext from openhcs.core.pipeline.compilation_session import CompilationSession - from openhcs.core.pipeline.step_snapshot import StepSnapshot from openhcs.core.steps.function_step import FunctionStep from openhcs.interop.cellprofiler.compile_time_contracts import ( CellProfilerInvocationContractProviderFactory, @@ -1402,12 +1386,6 @@ def session_for( FunctionStep(func=_native_image, name="NativeImage"), cellprofiler_step, ) - snapshots = tuple( - StepSnapshot( - index=index, scope_id=f"native-cursor::functionstep_{index}", step=step - ) - for index, step in enumerate(steps) - ) return ( CompilationSession.from_context( context=ProcessingContext( @@ -1422,11 +1400,12 @@ def session_for( }, axis_id="A01", ), - steps=steps, orchestrator=SimpleNamespace(pipeline_config=PipelineConfig()), global_config=GlobalPipelineConfig(), - step_state_map={index: object() for index in range(len(steps))}, - snapshots=snapshots, + pipeline=ResolvedPipelineDefinition( + steps=steps, + step_state_map={index: object() for index in range(len(steps))}, + ), ), steps, ) diff --git a/tests/unit/test_invocation_input_source_context_identity.py b/tests/unit/test_invocation_input_source_context_identity.py index 95c31656ce..7404681b68 100644 --- a/tests/unit/test_invocation_input_source_context_identity.py +++ b/tests/unit/test_invocation_input_source_context_identity.py @@ -98,7 +98,7 @@ def test_compiled_input_edges_own_exact_main_flow_membership() -> None: assert tuple(edge.spec for edge in edges) == (plate_template, combined_image) assert tuple(edge.storage_plan for edge in edges) == (None, None) - assert tuple(edge.consumes_main_flow for edge in edges) == (False, True) + assert tuple((edge.main_flow_projection is not None) for edge in edges) == (False, True) assert tuple(edge.main_flow_projection for edge in edges) == ( None, MainFlowInputProjection.COMPLETE_PAYLOAD, @@ -149,7 +149,7 @@ def threshold_like(image: np.ndarray) -> np.ndarray: current_image=source_payload, ).artifact_value(edge) - assert edge.consumes_main_flow is True + assert (edge.main_flow_projection is not None) is True assert edge.main_flow_projection is MainFlowInputProjection.COMPLETE_PAYLOAD assert request is source_payload assert image_payload_metadata(request).source_image_names == ("Hoechst",) @@ -235,7 +235,7 @@ def source_artifact_payload(_request, ref): request.artifact_value( replace( edges_by_ref[plate_template.ref()], - consumes_main_flow=True, + main_flow_projection=MainFlowInputProjection.DECLARED_SOURCE_IMAGE, ) ) @@ -260,7 +260,7 @@ def test_storage_backed_input_keeps_exact_runtime_authority() -> None: edge = next(edge for edge in edges if edge.spec == combined_image) assert edge.storage_plan is not None - assert edge.consumes_main_flow is False + assert (edge.main_flow_projection is not None) is False stored_payload = ImagePayloadMetadata( source_image_names=(combined_image.name,), diff --git a/tests/unit/test_loaded_pattern_group_ownership.py b/tests/unit/test_loaded_pattern_group_ownership.py new file mode 100644 index 0000000000..bc6a55ce28 --- /dev/null +++ b/tests/unit/test_loaded_pattern_group_ownership.py @@ -0,0 +1,521 @@ +"""Loaded cohorts retain original input facts while plans and call images remain live.""" + +from dataclasses import FrozenInstanceError, fields, replace +import inspect +import pickle +from types import SimpleNamespace + +import numpy as np +import pytest + +from openhcs.constants.constants import AllComponents, VariableComponents +from openhcs.core.compiled_step_plan import CompiledStepPlan +from openhcs.core.component_group_scope import ComponentGroupScope +from openhcs.core.context.processing_context import ProcessingContext +from openhcs.core.function_patterns import compile_function_pattern +from openhcs.core.runtime_image_values import ImagePayloadMetadata, image_payload_data, image_payload_metadata +from openhcs.core.source_bindings import CompiledSourceBindingPlan +from openhcs.core.source_image_provenance import SourceImageProvenancePlanes +from openhcs.core.steps import function_runtime +from openhcs.core.steps.function_runtime import ( + ComponentArtifactPlans, + FunctionCoreExecutor, + PatternGroupData, + PatternGroupExecutionRequest, + PatternGroupExecutionScope, + PatternGroupRuntime, + RuntimeProfileSink, +) +from openhcs.core.steps.function_output_manifest import NoStepOutputManifestMatch + + +def _identity(image): + return image + + +def _fixture(): + pattern = compile_function_pattern(_identity, {}, {}) + plan = CompiledStepPlan( + step_index=0, step_type="FunctionStep", step_name="Loaded", axis_id="A01", + step_scope_id="loaded-cohort", input_memory_type="numpy", output_memory_type="numpy", + execution_group_scope=ComponentGroupScope.dynamic(AllComponents.CHANNEL), + variable_components=(VariableComponents.SITE,), + source_binding_plan=CompiledSourceBindingPlan.empty(), + ) + context = ProcessingContext(axis_id="A01") + request = PatternGroupExecutionRequest( + context=context, execution_plan=plan, compiled_group=pattern.default_group, + component_value="1", pattern_group_info="A01_s{iii}_w1_z003_t002.tif", + component_index=7, component_count=99, + fixed_component_values=((AllComponents.Z_INDEX, "dispatch-value"),), + ) + paths = ["A01_s001_w1_z003_t002.tif", "A01_s002_w1_z003_t002.tif"] + payload = ImagePayloadMetadata( + source_image_provenance_planes=SourceImageProvenancePlanes.from_components( + paths=tuple(paths), + component_metadata=tuple( + {"well": "A01", "site": str(site), "channel": "1", "z_index": "3", "timepoint": "2"} + for site in (1, 2) + ), + ), + ).payload_with(np.arange(24, dtype=np.float32).reshape(2, 3, 4)) + return request, paths, payload + + +def test_complete_loaded_owner_has_one_frozen_ten_field_contract_and_pickle(): + request, paths, payload = _fixture() + loaded = PatternGroupData.from_loaded_group(request, paths, payload) + expected = ( + "context", "execution_plan", "compiled_group", "component_value", "fixed_component_values", + "artifacts", "runtime_plane_index", "runtime_plane_count", + "matching_files", "main_data_stack", + ) + assert PatternGroupData.__bases__ == (PatternGroupExecutionScope,) + assert tuple(item.name for item in fields(loaded)) == expected + assert set(inspect.signature(PatternGroupData).parameters) == set(expected) + assert all(item.kw_only for item in fields(loaded)) + assert not hasattr(loaded, "__dict__") + assert loaded.context is request.context + assert loaded.execution_plan is request.execution_plan + assert loaded.compiled_group is request.compiled_group + assert loaded.matching_files is paths + assert loaded.main_data_stack is payload + with pytest.raises(FrozenInstanceError): + loaded.runtime_plane_count = 0 + replaced = replace(loaded, component_value="2") + assert replaced.main_data_stack is payload + assert replaced.matching_files is paths + from openhcs.core.orchestrator.execution_result import RuntimeExecutionTransportSerialization + + RuntimeExecutionTransportSerialization.register() + restored = pickle.loads(pickle.dumps(loaded)) + assert type(restored) is PatternGroupData + assert restored.runtime_plane_index == 7 + assert restored.runtime_plane_count == 2 + assert restored.execution_plan.step_scope_id == "loaded-cohort" + assert restored.fixed_component_values == loaded.fixed_component_values + np.testing.assert_array_equal(image_payload_data(restored.main_data_stack), image_payload_data(payload)) + + +def test_initial_coordinates_stay_captured_while_plan_selectors_follow_mutation(): + request, paths, payload = _fixture() + loaded = PatternGroupData.from_loaded_group(request, paths, payload) + assert loaded.runtime_plane_count == 2 + assert loaded.fixed_component_values == ((AllComponents.Z_INDEX, "3"), (AllComponents.TIMEPOINT, "2")) + paths.append("later-mutation.tif") + image_payload_data(payload)[:] = -1 + assert loaded.runtime_plane_count == 2 + assert len(loaded.matching_files) == 3 + request.execution_plan.axis_id = "B02" + request.execution_plan.execution_group_scope = ComponentGroupScope.dynamic(AllComponents.SITE) + assert loaded.axis_scope.axis_id == "B02" + assert loaded.axis_component == "site" + assert loaded.fixed_component_values == ((AllComponents.Z_INDEX, "3"), (AllComponents.TIMEPOINT, "2")) + + +def test_chain_shares_cohort_but_advances_only_current_image_and_memory(monkeypatch): + request, paths, payload = _fixture() + invocation = request.compiled_group.invocations[0] + invocation = replace(invocation, contract=replace( + invocation.contract, metadata=replace( + invocation.contract.metadata, output_memory_type="next-memory", + ), + )) + group = replace(request.compiled_group, invocations=(invocation, invocation)) + request = replace(request, compiled_group=group) + loaded = PatternGroupData.from_loaded_group(request, paths, payload) + first_output = np.ones((2, 3, 4), dtype=np.float32) + second_output = np.full((2, 3, 4), 2, dtype=np.float32) + seen = [] + + def execute(executor, *, debug_sink=None): + assert debug_sink is None + seen.append((executor.group_data, executor.main_data_arg, executor.source_memory_type)) + if len(seen) == 1: + paths.append("during-call.tif") + image_payload_data(payload)[:] = -3 + return first_output + return second_output + + monkeypatch.setattr(FunctionCoreExecutor, "execute", execute) + monkeypatch.setattr(function_runtime, "debug_event_sink_from_context", lambda _context: SimpleNamespace(captures_invocation_events=lambda: False)) + assert PatternGroupRuntime.execute_chain(loaded) is second_output + assert seen[0][0] is loaded and seen[1][0] is loaded + assert seen[0][1] is payload and seen[1][1] is first_output + assert seen[0][2] == "numpy" and seen[1][2] == "next-memory" + assert loaded.main_data_stack is payload + assert loaded.runtime_plane_count == 2 + assert loaded.fixed_component_values == ((AllComponents.Z_INDEX, "3"), (AllComponents.TIMEPOINT, "2")) + + +def test_scope_admission_follows_load_profile_inside_execution_error_boundary(monkeypatch): + request, paths, payload = _fixture() + runtime = PatternGroupRuntime(request) + events = [] + failure = RuntimeError("cohort admission failed") + monkeypatch.setattr(runtime, "_load_input_stack", lambda: (events.append("load") or (paths, payload))) + monkeypatch.setattr(RuntimeProfileSink, "record", lambda label, *_args, **_kwargs: events.append(label)) + + def fail_capture(cls, observed_request, observed_paths, observed_payload): + assert observed_request is request + assert observed_paths is paths + assert observed_payload is payload + events.append("capture") + raise failure + + monkeypatch.setattr(PatternGroupData, "from_loaded_group", classmethod(fail_capture)) + with pytest.raises(ValueError, match="Failed to process pattern group") as exc: + runtime.run() + assert exc.value.__cause__ is failure + assert events == ["load", "pattern_load_stack", "capture"] + + +@pytest.mark.parametrize("failure", [RuntimeError("load failed"), NoStepOutputManifestMatch("stale")]) +def test_load_errors_and_stale_skip_precede_capture_and_execution_wrapping(monkeypatch, failure): + request, _paths, _payload = _fixture() + runtime = PatternGroupRuntime(request) + events = [] + + def failed_load(): + events.append("load") + raise failure + + monkeypatch.setattr(runtime, "_load_input_stack", failed_load) + monkeypatch.setattr(RuntimeProfileSink, "record", lambda *_args, **_kwargs: pytest.fail("failed load must not reach profile/capture")) + if isinstance(failure, NoStepOutputManifestMatch): + assert runtime.run() is None + else: + with pytest.raises(RuntimeError) as exc: + runtime.run() + assert exc.value is failure + assert events == ["load"] + + +def test_empty_chain_is_rejected_after_full_capture_and_load_profile(monkeypatch): + request, paths, payload = _fixture() + request = replace(request, compiled_group=replace(request.compiled_group, invocations=())) + runtime = PatternGroupRuntime(request) + labels = [] + monkeypatch.setattr(runtime, "_load_input_stack", lambda: (paths, payload)) + monkeypatch.setattr(RuntimeProfileSink, "record", lambda label, *_args, **_kwargs: labels.append(label)) + with pytest.raises(ValueError, match="has no invocations") as exc: + runtime.run() + assert isinstance(exc.value.__cause__, ValueError) + assert labels == ["pattern_load_stack"] + + +def test_adapter_request_projects_live_fields_and_preserves_current_payload_epoch(): + request, paths, initial = _fixture() + loaded = PatternGroupData.from_loaded_group(request, paths, initial) + current = np.ones((2, 3, 4), dtype=np.float32) + invocation = loaded.compiled_group.invocations[0] + executor = FunctionCoreExecutor( + loaded, invocation, ComponentArtifactPlans(inputs={}, outputs={}), "1", + function_runtime.RuntimePlaneProjection.stack(2), current, "numpy", + ) + adapter = executor.runtime_adapter_request(current) + assert adapter.context is loaded.context + assert adapter.callable_contract is invocation.contract + assert adapter.source_payload is current + assert adapter.source_payload is not loaded.main_data_stack + assert adapter.plane_projection is executor.plane_projection + assert adapter.source_load_plan is request.execution_plan.source_load_plan + assert adapter.variable_components == (VariableComponents.SITE,) + assert adapter.axis_scope.fixed_component_values == loaded.fixed_component_values + request.execution_plan.axis_id = "B02" + request.execution_plan.variable_components = (VariableComponents.Z_INDEX,) + updated = executor.runtime_adapter_request(current) + assert updated.axis_scope.axis_id == "B02" + assert updated.variable_components == (VariableComponents.Z_INDEX,) + + +def test_adapter_tuple_admission_precedes_output_map_validation(): + request, paths, initial = _fixture() + loaded = PatternGroupData.from_loaded_group(request, paths, initial) + invocation = loaded.compiled_group.invocations[0] + executor = FunctionCoreExecutor( + loaded, invocation, ComponentArtifactPlans(inputs={}, outputs={"invalid": object()}), "1", + function_runtime.RuntimePlaneProjection.stack(2), initial, "numpy", + ) + request.execution_plan.variable_components = None + with pytest.raises(TypeError, match="NoneType.*not iterable"): + executor.runtime_adapter_request(initial) + request.execution_plan.variable_components = () + with pytest.raises(TypeError, match="Runtime adapter output"): + executor.runtime_adapter_request(initial) + + +def test_component_artifact_admission_precedes_source_provenance_capture(monkeypatch): + request, paths, initial = _fixture() + request.execution_plan.artifact_inputs = {"invalid": object()} + monkeypatch.setattr(function_runtime, "image_payload_metadata", lambda _payload: pytest.fail("source projection must follow artifact-plan admission")) + with pytest.raises(TypeError, match="Component artifact input"): + PatternGroupData.from_loaded_group(request, paths, initial) + + +def _stored_primary_fixture(*, preserves_main_flow=False): + from openhcs.constants.constants import Backend + from openhcs.core.artifacts import ( + ArtifactInputPlan, ArtifactOutputPlan, ArtifactSpec, + ArtifactSpecCollection, GroupLineageSourceRelation, ImageArtifactType, SpecialArtifactType, + ) + from openhcs.core.component_set import ComponentSet + from openhcs.core.pipeline.function_contracts import artifact_inputs, artifact_outputs + from openhcs.core.pipeline.path_planner import PathPlanner, PathPlannerArtifactStage + from openhcs.core.runtime_adapters import runtime_adapter + from openhcs.core.runtime_artifact_values import RuntimeValue + from openhcs.core.runtime_plane_projection import RuntimePlaneAxis + from openhcs.core.component_group_scope import RuntimeExecutionAxisScope + + request, _, payload = _fixture() + source = ArtifactSpec.input("Canonical", ImageArtifactType) + output = ArtifactSpec.output( + "Processed", SpecialArtifactType if preserves_main_flow else ImageArtifactType, + relations=(GroupLineageSourceRelation(source=source.ref()),), + ) + + @artifact_inputs(source) + @artifact_outputs(output) + @runtime_adapter("runtime", lambda _request: object(), manages_artifact_inputs=True) + def consume(image, *, runtime): + return image + + output_plan = ArtifactOutputPlan( + name=output.name, path="/memory/processed", artifact_type=output.artifact_type, + relations=output.relations, + ) + input_plan = ArtifactInputPlan( + name=source.name, path="/memory/canonical", artifact_type=ImageArtifactType, + source_step_id=0, + ) + pattern = compile_function_pattern(consume, {}, {output_plan.ref(): output_plan}) + pattern = PathPlannerArtifactStage(PathPlanner.__new__(PathPlanner)).compile_invocation_input_edges( + pattern, + artifact_inputs={input_plan.ref(): input_plan}, + relation_source_scopes={}, + execution_group_scope=ComponentGroupScope.ungrouped(), + consumer_variable_components=ComponentSet((AllComponents.SITE,)), + main_flow_artifacts=ArtifactSpecCollection((source,)), + ) + request.execution_plan.step_index = 1 + request.execution_plan.execution_group_scope = ComponentGroupScope.ungrouped() + request.execution_plan.artifact_inputs = {input_plan.ref(): input_plan} + request.execution_plan.artifact_outputs = {output_plan.ref(): output_plan} + request.execution_plan.compiled_function_pattern = pattern + request = function_runtime.ArtifactPatternGroupExecutionRequest( + context=request.context, execution_plan=request.execution_plan, + compiled_group=pattern.default_group, pattern_group_info=input_plan.path, + component_index=7, component_count=99, + fixed_component_values=((AllComponents.Z_INDEX, "3"), (AllComponents.TIMEPOINT, "2")), + ) + payload = image_payload_metadata(payload).replace_fields( + plane_axis=RuntimePlaneAxis.RUNTIME_SLICE, + ).payload_with(image_payload_data(payload), np.ones((2, 3, 4), dtype=bool)) + value = RuntimeValue.from_spec( + source, payload, + execution_scope=RuntimeExecutionAxisScope.from_raw("A01", component=None, value=None, fixed_component_values=request.fixed_component_values), + ) + request.context.runtime_value_store.replace( + value, path=input_plan.path, backend=Backend.MEMORY.value, + ) + return request, value + + +def test_stored_primary_admission_owns_independent_buffer_and_live_primary_binding(monkeypatch): + from openhcs.constants.constants import Backend + from openhcs.core.runtime_image_values import image_payload_mask + from openhcs.interop.cellprofiler.runtime.artifact_binding import RuntimeInputBindingRequest + from tests.unit.cellprofiler_runtime_test_support import cellprofiler_runtime_adapter_for_test + + request, canonical = _stored_primary_fixture() + runtime = PatternGroupRuntime(request) + monkeypatch.setattr( + runtime, "source_workspace_projection_authority", + lambda: SimpleNamespace(projection_if_available=lambda: None), + ) + paths, admitted = request.load_input_stack(runtime) + assert paths == ["/memory/canonical"] + assert not np.shares_memory(image_payload_data(admitted), image_payload_data(canonical.data)) + assert not np.shares_memory(image_payload_mask(admitted), image_payload_mask(canonical.data)) + loaded = PatternGroupData.from_loaded_group(request, paths, admitted) + assert loaded.runtime_plane_count == 2 + assert loaded.runtime_plane_index == 7 + assert loaded.fixed_component_values == ((AllComponents.Z_INDEX, "3"), (AllComponents.TIMEPOINT, "2")) + replacement = replace(canonical, data=image_payload_metadata(canonical.data).payload_with( + np.full((2, 3, 4), 31, dtype=np.float32), np.zeros((2, 3, 4), dtype=bool), + )) + request.context.runtime_value_store.replace( + replacement, path=paths[0], backend=Backend.MEMORY.value, + ) + image_payload_data(admitted)[:] = 17 + image_payload_mask(admitted)[:] = False + invocation = request.compiled_group.invocations[0] + edge = invocation.artifact_input_edges[0] + adapter = cellprofiler_runtime_adapter_for_test( + runtime_value_store=request.context.runtime_value_store, + callable_contract=invocation.contract, + artifact_inputs={edge.key: edge}, axis_scope=request.axis_scope, + ) + bound = RuntimeInputBindingRequest(adapter=adapter, kwargs={}, current_image=admitted).artifact_value(edge) + assert bound is admitted + np.testing.assert_array_equal(image_payload_data(bound), 17) + np.testing.assert_array_equal(image_payload_data(replacement.data), 31) + _, next_admitted = request.load_input_stack(runtime) + np.testing.assert_array_equal(image_payload_data(next_admitted), 31) + assert not np.shares_memory(image_payload_data(next_admitted), image_payload_data(replacement.data)) + assert loaded.runtime_plane_count == 2 + + +def test_checkpoint_demand_follows_preserved_input_to_native_reader(): + from openhcs.constants.constants import Backend + from openhcs.core.step_dependencies import StepInputDependency + + request, _ = _stored_primary_fixture() + source = replace(request.execution_plan, step_index=0, step_scope_id="source", write_backend=Backend.MEMORY.value) + preserving_request, _ = _stored_primary_fixture(preserves_main_flow=True) + preserving_pattern = preserving_request.execution_plan.compiled_function_pattern + preserving = replace( + source, step_index=1, step_scope_id="preserving", compiled_function_pattern=preserving_pattern, + main_input_dependency=StepInputDependency.step_output(source_step_index=0, source_step_scope_id="source"), + ) + native = replace( + source, step_index=2, step_scope_id="native", compiled_function_pattern=compile_function_pattern(_identity, {}, {}), + main_input_dependency=StepInputDependency.step_output(source_step_index=1, source_step_scope_id="preserving"), + ) + plans = {0: source, 1: preserving, 2: native} + assert source.requires_main_flow_checkpoint(plans) + assert preserving.requires_main_flow_checkpoint(plans) + native.compiled_function_pattern = source.compiled_function_pattern + assert not source.requires_main_flow_checkpoint(plans) + source.streaming_configs = {"viewer": object()} + assert source.requires_main_flow_checkpoint(plans) + + +@pytest.mark.parametrize("pattern_kind", ("unknown", "missing", "malformed")) +def test_checkpoint_demand_preserves_dependent_group_admission(pattern_kind): + from openhcs.constants.constants import Backend + from openhcs.core.step_dependencies import StepInputDependency + + request, _ = _stored_primary_fixture() + source = replace(request.execution_plan, step_index=0, step_scope_id="source", write_backend=Backend.MEMORY.value) + consumer = replace( + source, step_index=1, step_scope_id="consumer", + compiled_function_pattern=( + None if pattern_kind == "unknown" else replace( + source.compiled_function_pattern, groups=(), + is_grouped=pattern_kind == "missing", + ) + ), + main_input_dependency=StepInputDependency.step_output(source_step_index=0, source_step_scope_id="source"), + ) + plans = {0: source, 1: consumer} + if pattern_kind == "malformed": + with pytest.raises(ValueError, match="no 'default' group"): + source.requires_main_flow_checkpoint(plans) + else: + assert source.requires_main_flow_checkpoint(plans) + consumer.main_input_dependency = StepInputDependency.step_output(source_step_index=99, source_step_scope_id="absent") + assert not source.requires_main_flow_checkpoint(plans) + assert source.requires_main_flow_checkpoint({}) + assert source.requires_main_flow_checkpoint({1: consumer}) + + +def test_checkpoint_demand_propagates_only_through_preserved_outputs(): + from openhcs.constants.constants import Backend + from openhcs.core.step_dependencies import StepInputDependency + + request, _ = _stored_primary_fixture() + source = replace(request.execution_plan, step_index=0, step_scope_id="source", write_backend=Backend.MEMORY.value) + consumer = replace( + source, step_index=1, step_scope_id="consumer", visualize=True, + main_input_dependency=StepInputDependency.step_output(source_step_index=0, source_step_scope_id="source"), + ) + plans = {0: source, 1: consumer} + assert consumer.requires_main_flow_checkpoint(plans) + assert not source.requires_main_flow_checkpoint(plans) + preserving, _ = _stored_primary_fixture(preserves_main_flow=True) + consumer.compiled_function_pattern = preserving.execution_plan.compiled_function_pattern + assert source.requires_main_flow_checkpoint(plans) + + +def test_checkpoint_demand_terminates_on_preserving_cycles_and_self_producers(): + from openhcs.constants.constants import Backend + from openhcs.core.step_dependencies import StepInputDependency + + request, _ = _stored_primary_fixture(preserves_main_flow=True) + first = replace( + request.execution_plan, step_index=1, step_scope_id="first", write_backend=Backend.MEMORY.value, + main_input_dependency=StepInputDependency.step_output(source_step_index=2, source_step_scope_id="second"), + ) + second = replace( + first, step_index=2, step_scope_id="second", + main_input_dependency=StepInputDependency.step_output(source_step_index=1, source_step_scope_id="first"), + ) + plans = {1: first, 2: second} + assert not first.requires_main_flow_checkpoint(plans) + assert not second.requires_main_flow_checkpoint(plans) + second.streaming_configs = {"viewer": object()} + assert first.requires_main_flow_checkpoint(plans) + assert second.requires_main_flow_checkpoint(plans) + first.main_input_dependency = StepInputDependency.step_output(source_step_index=1, source_step_scope_id="first") + assert not first.requires_main_flow_checkpoint({1: first}) + self_producer = replace( + first, step_index=0, step_scope_id="self", + main_input_dependency=StepInputDependency.step_output(source_step_index=0, source_step_scope_id="self"), + ) + assert self_producer.requires_main_flow_checkpoint({0: self_producer}) + + +def test_artifact_loaded_coordinates_keep_producer_authority_over_original_source(): + request, canonical = _stored_primary_fixture() + exact_coordinates = ( + (AllComponents.CHANNEL, "ProducedChannel"), + (AllComponents.Z_INDEX, "3"), + (AllComponents.TIMEPOINT, "2"), + ) + request = replace(request, fixed_component_values=exact_coordinates) + assert image_payload_metadata(canonical.data).source_provenance.with_common_scalar_identity_from_planes().source_component_metadata["channel"] == "1" + loaded = PatternGroupData.from_loaded_group( + request, ["/memory/canonical"], canonical.data, + ) + assert loaded.fixed_component_values == exact_coordinates + canonical.data.metadata.source_provenance = canonical.data.metadata.source_provenance.with_source_component_metadata({"channel": "9"}) + assert loaded.fixed_component_values == exact_coordinates + + +def test_conversion_and_sequential_filter_use_the_same_transport_admission(): + from pathlib import Path + from openhcs.constants.constants import Backend, SequentialComponents + from openhcs.core.compiled_step_plan import ( + InputConversionPlan, SequentialRuntimeFilter, SequentialRuntimeFilterPlan, + ) + + request, _ = _stored_primary_fixture() + plan = request.execution_plan + assert plan.stored_primary_input_edges_for_group(request.compiled_group, None) + plan.input_conversion = InputConversionPlan( + output_dir=Path("/memory/input"), backend=Backend.MEMORY.value, + uses_virtual_workspace=True, original_subdir="images", + ) + assert plan.stored_primary_input_edges_for_group(request.compiled_group, None) is None + plan.input_conversion = None + plan.sequential_filter_plan = SequentialRuntimeFilterPlan( + filters=(SequentialRuntimeFilter(SequentialComponents.TIMEPOINT, "2"),), + ) + assert plan.stored_primary_input_edges_for_group(request.compiled_group, None) is None + + +def test_same_step_primary_producer_is_not_queried_before_its_callable_runs(): + request, _ = _stored_primary_fixture() + plan = request.execution_plan + assert plan.stored_primary_input_edges_for_group(request.compiled_group, None) + invocation = request.compiled_group.invocations[0] + edge = invocation.artifact_input_edges[0] + later_edge = replace(edge, storage_plan=replace( + edge.storage_plan, source_step_id=plan.step_index, + source_step_scope_id=plan.step_scope_id, + )) + group = replace(request.compiled_group, invocations=( + invocation.with_artifact_input_edges((later_edge,)), + )) + assert plan.stored_primary_input_edges_for_group(group, None) is None diff --git a/tests/unit/test_materialization_batch_outcomes.py b/tests/unit/test_materialization_batch_outcomes.py new file mode 100644 index 0000000000..ddb21fc62b --- /dev/null +++ b/tests/unit/test_materialization_batch_outcomes.py @@ -0,0 +1,227 @@ +"""Actual batch outcomes, independent of subsequent logical-value rendering.""" + +from dataclasses import replace +from pathlib import Path +import pickle +from types import MappingProxyType + +import pytest +from polystore.disk import DiskStorageBackend +from polystore.filemanager import FileManager +from polystore.memory import MemoryStorageBackend + +from openhcs.core.context.processing_context import ProcessingContext +from openhcs.core.compiled_step_plan import CompiledStepPlan +from openhcs.core.debug import NoOpDebugExecutionPolicy +from openhcs.core.function_patterns import compile_function_pattern +from openhcs.core.orchestrator.compiled_plate_execution import ( + CompiledPlateExecutionExtras, + CompiledPlateExecutionResults, +) +from openhcs.core.orchestrator.execution_result import ( + ExecutionResult, + RuntimeContextObservation, + RuntimeExecutionObservation, + RuntimeObservationMode, +) +from openhcs.core.orchestrator.worker_execution import ( + _execute_axis_with_sequential_combinations, +) +from openhcs.core.orchestrator.worker_lanes import WorkerLaneExecutionContext +from openhcs.core.runtime_exports import RuntimeExportObservation +from openhcs.core.steps.abstract import StepExecutionObservation +from openhcs.core.steps.function_step import FunctionStep +from openhcs.processing.materialization import ( + CsvOptions, + JsonOptions, + MaterializationSpec, + SavedMaterializationOutputs, + prepare_materialization, +) +from openhcs.processing.materialization.core import _WRITERS_BY_OPTIONS + + +class CsvOnlyMemoryBackend(MemoryStorageBackend): + def accepts_payload(self, data, path): + return Path(path).suffix == ".csv" + + +def test_rendered_batch_reuses_exact_outputs_after_logical_payload_mutates( + tmp_path, monkeypatch +): + manager = FileManager({"disk": DiskStorageBackend()}) + rows = [{"Area": 42}] + batch = prepare_materialization( + MaterializationSpec(CsvOptions(), JsonOptions()), + rows, + str(tmp_path / "measurements"), + manager, + ("disk",), + ) + original_outputs = batch.outputs + rows[0]["Area"] = 999 + + def render_again(*_args): + pytest.fail( + "Saving a prepared batch must not render mutable logical input again" + ) + + for option_type in (CsvOptions, JsonOptions): + monkeypatch.setitem( + _WRITERS_BY_OPTIONS, + option_type, + replace(_WRITERS_BY_OPTIONS[option_type], write=render_again), + ) + outcome = batch.save() + + assert isinstance(outcome, SavedMaterializationOutputs) + assert outcome.outputs_for_backend("disk") == original_outputs + assert all( + left is right + for left, right in zip( + outcome.outputs_for_backend("disk"), original_outputs, strict=True + ) + ) + assert Path(batch.primary_path).read_text().splitlines() == ["Area", "42"] + assert Path(original_outputs[1].path).read_text().find("999") == -1 + + +def test_saved_outcomes_include_only_backend_accepted_outputs(tmp_path): + manager = FileManager({"memory": CsvOnlyMemoryBackend()}) + batch = prepare_materialization( + MaterializationSpec(CsvOptions(), JsonOptions()), + [{"Area": 42}], + str(tmp_path / "measurements"), + manager, + ("memory",), + ) + + outcome = batch.save() + + assert outcome.outputs_for_backend("memory") == (batch.outputs[0],) + assert outcome.outputs_for_backend("disk") == () + assert manager.exists(batch.outputs[0].path, "memory") + assert not manager.exists(batch.outputs[1].path, "memory") + + +def test_failed_save_does_not_return_a_successful_outcome(tmp_path, monkeypatch): + manager = FileManager({"disk": DiskStorageBackend()}) + batch = prepare_materialization( + MaterializationSpec(CsvOptions()), + [{"Area": 42}], + str(tmp_path / "measurements"), + manager, + ("disk",), + ) + + def failed_save(*_args, **_kwargs): + raise OSError("destination is unavailable") + + monkeypatch.setattr(manager, "save_batch", failed_save) + with pytest.raises(OSError, match="destination is unavailable"): + batch.save() + assert not Path(batch.primary_path).exists() + + +class EmittedOutputStep(FunctionStep): + def __init__(self, path): + super().__init__(lambda image: image) + self.path = path + + def process(self, context, step_index): + self.path.write_text("Area\n42\n") + return StepExecutionObservation(MappingProxyType({}), (self.path,)) + + +class FrozenWorkerContext(ProcessingContext): + def __init__(self): + super().__init__( + axis_id="A01", + filemanager=FileManager({"memory": MemoryStorageBackend()}), + step_plans={ + 0: CompiledStepPlan( + step_index=0, + step_name="Save", + step_type="FunctionStep", + axis_id="A01", + compiled_function_pattern=compile_function_pattern( + lambda image: image, {}, {} + ), + ) + }, + ) + self.freeze() + self.released = False + + def release_execution_image_cache(self): + super().release_execution_image_cache() + self.released = True + + +@pytest.mark.parametrize("mode", tuple(RuntimeObservationMode)) +def test_worker_exports_actual_step_outcomes_after_resource_release( + tmp_path, monkeypatch, mode +): + import openhcs.core.orchestrator.worker_execution as worker + + path = tmp_path / "actual.csv" + context = FrozenWorkerContext() + lane = WorkerLaneExecutionContext( + execution_id="execution", + plate_id="plate", + debug_execution_policy=NoOpDebugExecutionPolicy(), + worker_slot="worker-0", + worker_assignments={"worker-0": ("A01",)}, + ) + monkeypatch.setattr(worker, "emit", lambda **_kwargs: None) + + def forbidden_reconstruction(*_args, **_kwargs): + pytest.fail("Ordinary execution must consume actual step outcomes") + + monkeypatch.setattr( + worker, + "preview_reused_step_outputs", + forbidden_reconstruction, + ) + result = _execute_axis_with_sequential_combinations( + [EmittedOutputStep(path)], + [("A01", context)], + lane, + mode, + release_axis_resources=False, + ) + transported = pickle.loads(pickle.dumps(result)) + + assert context.released + assert transported.is_success() + assert transported.runtime_observation.contexts[0].runtime_export_paths == (path,) + assert transported.runtime_observation.contexts[0].records == () + assert RuntimeExportObservation.from_runtime_observations( + (transported.runtime_observation,) + ).table_outputs == (path,) + + +def test_parent_and_worker_exports_share_existing_observation_authority(tmp_path): + worker_path = tmp_path / "worker.csv" + plate_path = tmp_path / "plate.csv" + unrelated = tmp_path / "unrelated.csv" + for path in (worker_path, plate_path, unrelated): + path.write_text("Area\n42\n") + worker = RuntimeExecutionObservation( + contexts=(RuntimeContextObservation("A01", (), (worker_path,)),) + ) + parent = RuntimeExecutionObservation( + contexts=(RuntimeContextObservation("A01", (), (plate_path,)),) + ) + results = CompiledPlateExecutionResults( + {"A01": ExecutionResult.success("A01", runtime_observation=worker)}, + extras=CompiledPlateExecutionExtras( + viewer_states_by_port={}, runtime_observation=parent + ), + ) + exports = RuntimeExportObservation.from_runtime_observations( + results.runtime_observations + ) + + assert exports.output_files == (worker_path, plate_path) + assert unrelated not in exports.output_files diff --git a/tests/unit/test_materialization_core.py b/tests/unit/test_materialization_core.py index 39022ad340..3be3e5a87c 100644 --- a/tests/unit/test_materialization_core.py +++ b/tests/unit/test_materialization_core.py @@ -1,4 +1,5 @@ import json +from pathlib import Path from functools import partial from multiprocessing.shared_memory import SharedMemory from types import SimpleNamespace @@ -2431,3 +2432,149 @@ def test_roi_materialization_treats_non_spatial_label_payload_as_empty() -> None assert out == "/tmp/A01_Worms_step3_segmentation_summary.txt" assert "No ROIs extracted" in fm.load(out, "memory") + + +@pytest.mark.parametrize("intrinsic", (False, True)) +def test_declared_volume_save_preserves_pixels_and_exact_plane_selection( + tmp_path, intrinsic +): + from openhcs.core.artifacts import ImageArtifactType + from openhcs.processing.materialization.options import MaterializedFilenameIdentity + from openhcs.core.component_group_scope import RuntimeExecutionAxisScope + from openhcs.core.image_file_serialization import TiffImageFileFormat + from openhcs.core.runtime_image_values import ( + image_payload_data, image_payload_mask, image_payload_metadata, + ) + from openhcs.core.runtime_slice_projection import RuntimeSliceProjection + from openhcs.core.source_projection import SourceArtifactProjection, SourcePixelRef + from openhcs.core.source_spatial_domain import VolumeSourceSpatialDomain + from openhcs.core.source_workspace_projection import ( + VirtualWorkspaceImagePayloadProjection, + ) + from openhcs.core.virtual_workspace_metadata import ( + VirtualWorkspaceSourceProjectionEntries, + ) + from openhcs.processing.materialization import prepare_materialization + import tifffile + + pixels = np.arange(3 * 4 * 5, dtype=np.uint16).reshape(3, 4, 5) + mask = pixels % 3 != 0 + paths = tuple(f"/source/A01_s001_w2_z{z:03d}_t001.tif" for z in (1, 2, 3)) + components = tuple( + {"well": "A01", "site": 1, "channel": 2, "z_index": z, "timepoint": 1} + for z in (1, 2, 3) + ) + domain = ( + VolumeSourceSpatialDomain( + source_depth=3, source_shape_yx=(4, 5), origin_yx=(0, 0) + ) + if intrinsic + else SourceSpatialDomain(source_shape_yx=(4, 5), origin_yx=(0, 0)) + ) + metadata = ImagePayloadMetadata( + plane_axis=RuntimePlaneAxis.RUNTIME_SLICE, + source_spatial_domain=domain, + source_voxel_spacing=SourceVoxelSpacing((2.0, 1.0, 0.5)), + source_image_names=("DNA",), + source_component_metadata={ + "well": "A01", + "site": 1, + "channel": 2, + "timepoint": 1, + "extension": ".tif", + }, + source_image_provenance_planes=SourceImageProvenancePlanes.from_components( + paths=paths, + component_metadata=components, + ), + ) + payload = metadata.payload_with(pixels, mask) + manager = FileManager({"disk": DiskStorageBackend()}) + spec = MaterializationSpec(ImageFileOptions( + filename_suffix=".tif", + filename_identity=MaterializedFilenameIdentity.SOURCE_IDENTITY, + )) + batch = prepare_materialization( + spec, + payload, + str(tmp_path / "output"), + manager, + ("disk",), + context=_SourceSchemaProcessingContext(), + variable_components=(VariableComponents.Z_INDEX,), + artifact_filename_identity=SourceImageIdentity( + component_metadata={**components[0], "extension": ".tif"}, + ), + ) + batch.save() + assert len(batch.outputs) == (1 if intrinsic else 3) + if not intrinsic: + for index, output in enumerate(batch.outputs): + np.testing.assert_array_equal(tifffile.imread(output.path), pixels[index]) + return + + (output,) = batch.outputs + assert Path(output.path).name == "A01_s001_w2_z001_t001.tif" + assert image_payload_metadata(payload).source_component_metadata.get("z_index") is None + assert output.metadata.source_component_metadata.get("z_index") is None + assert output.metadata.source_provenance.source_plane_count == 3 + np.testing.assert_array_equal(tifffile.imread(output.path), pixels) + saved_metadata = TiffImageFileFormat().persisted_metadata( + Path(output.path), payload + ) + projection = SourceArtifactProjection( + address=SourceArtifactProjection.scalar_address_for_image_metadata( + saved_metadata + ), + ref=SourcePixelRef("disk", output.path), + source_alias="DNA", + artifact_kind=ImageArtifactType, + image_metadata=saved_metadata, + execution_scope=RuntimeExecutionAxisScope.from_raw( + "A01", + component="channel", + value="2", + fixed_component_values=( + (AllComponents.SITE, "1"), + (AllComponents.TIMEPOINT, "1"), + ), + ), + ) + assert projection.address is None + entries = VirtualWorkspaceSourceProjectionEntries.from_projection_paths( + ((projection, "images/volume.tif"),) + ) + document = {} + entries.merge_into_subdirectory(document) + decoded = VirtualWorkspaceSourceProjectionEntries.from_subdirectory( + json.loads(json.dumps(document)) + ) + restored = decoded.entries["images/volume.tif"] + assert restored.execution_scope == projection.execution_scope + assert isinstance( + restored.image_metadata.source_spatial_domain, VolumeSourceSpatialDomain + ) + assert restored.image_metadata.source_spatial_domain.source_depth == 3 + reloaded = VirtualWorkspaceImagePayloadProjection( + persisted_metadata=restored.image_metadata + ).apply(metadata.payload_with(tifffile.imread(output.path), mask.copy())) + for index in range(3): + physical_plane = SourcePixelRef( + "disk", output.path, source_axis_indices=(index,) + ).load( + {"disk": manager._get_backend("disk")}, + base_path=tmp_path, + ) + np.testing.assert_array_equal(physical_plane, pixels[index]) + plane = RuntimeSliceProjection.value_for_slice( + reloaded, + RuntimePlaneAxisValueProjection.preserve( + axis=RuntimePlaneAxis.RUNTIME_SLICE, axis_size=3 + ).selected_plane(index), + ) + np.testing.assert_array_equal(image_payload_data(plane), pixels[index]) + np.testing.assert_array_equal(image_payload_mask(plane), mask[index]) + assert plane.metadata.source_path == paths[index] + assert plane.metadata.source_component_metadata["z_index"] == index + 1 + assert type(plane.metadata.source_spatial_domain) is SourceSpatialDomain + assert plane.metadata.source_voxel_spacing == metadata.source_voxel_spacing diff --git a/tests/unit/test_materialization_filter_inheritance.py b/tests/unit/test_materialization_filter_inheritance.py index fb52726433..664dd1da25 100644 --- a/tests/unit/test_materialization_filter_inheritance.py +++ b/tests/unit/test_materialization_filter_inheritance.py @@ -43,7 +43,7 @@ def _resolved_checkpoint( plate_path=plate_path, pipeline_config=pipeline_config, get_component_keys=lambda _component: ["A01", "B02"], - create_context=lambda axis_id: SimpleNamespace( + create_context=lambda axis_id, *, resolved_config: SimpleNamespace( axis_id=axis_id, step_axis_filters={}, ), @@ -67,8 +67,8 @@ def _resolved_checkpoint( ) filters = PipelineCompiler._resolve_global_step_axis_filters( orchestrator, - resolved.snapshots, - resolved.step_state_map, + resolved, + pipeline_config_state.to_saved_resolved_object(), ) return orchestrator, scope_id, pipeline_config_state, resolved, filters @@ -81,8 +81,8 @@ def test_path_zero_keeps_inherited_step_checkpoint_independent(tmp_path) -> None ) try: - snapshot = resolved.snapshots[0] - checkpoint_config = snapshot.step.step_materialization_config + snapshot = resolved.steps[0] + checkpoint_config = snapshot.step_materialization_config assert checkpoint_config.well_filter == 0 assert filters[0].allows(checkpoint_config, "A01") assert not filters[0].allows(checkpoint_config, "B02") @@ -97,7 +97,7 @@ def test_path_zero_keeps_inherited_step_checkpoint_independent(tmp_path) -> None ) ) assert ( - materialization_stage.materialized_output_dir_for_step(snapshot) + materialization_stage.materialized_output_dir_for_step(snapshot, 0) == checkpoint_dir ) @@ -154,7 +154,7 @@ def test_explicit_checkpoint_filter_overrides_inherited_workload(tmp_path) -> No ) try: - checkpoint_config = resolved.snapshots[0].step.step_materialization_config + checkpoint_config = resolved.steps[0].step_materialization_config assert checkpoint_config.well_filter == "B02" assert not filters[0].allows(checkpoint_config, "A01") assert filters[0].allows(checkpoint_config, "B02") diff --git a/tests/unit/test_materialization_source_extension.py b/tests/unit/test_materialization_source_extension.py index 5fd4e2d79f..7130b502d2 100644 --- a/tests/unit/test_materialization_source_extension.py +++ b/tests/unit/test_materialization_source_extension.py @@ -25,8 +25,7 @@ VirtualWorkspaceSourceProjection, ) from openhcs.core.steps.function_output_identity import ( - FunctionOutputIdentityAuthority, - FunctionOutputPathAuthority, + FunctionOutputIdentity, ) from openhcs.microscopes.source_schema import SourceSchemaFilenameParser from openhcs.processing.materialization import ImageFileOptions, MaterializationSpec @@ -275,13 +274,10 @@ def test_real_source_schema_composition_to_named_output_and_image_materializer( # suffixes before the named main/checkpoint writer saw the source identity. composed = ImagePayloadMetadata.compose((payload,), mode=mode) scalar = composed.for_leading_source_plane(0) - identity = FunctionOutputIdentityAuthority.filename_identity_from_metadata( + identity = FunctionOutputIdentity.from_filename_metadata( parser, scalar ) - destination = FunctionOutputPathAuthority.filename_for_identity( - parser, - replace(identity, filename_qualifier="fixture_image"), - ) + destination = replace(identity, filename_qualifier="fixture_image").filename(parser) assert destination == f"{well}_s001_w1_z001_t001_fixture_image{extension}" assert destination.count("_s001_w1_z001_t001") == 1 assert identity.extension == extension diff --git a/tests/unit/test_measurement_image_alignment.py b/tests/unit/test_measurement_image_alignment.py index c45f956e8f..1260afabe1 100644 --- a/tests/unit/test_measurement_image_alignment.py +++ b/tests/unit/test_measurement_image_alignment.py @@ -9,9 +9,8 @@ ImageOutputBundle, ) from openhcs.core.measurement_image_alignment import ( + MeasurementImageLabelAlignmentRequest, MeasurementImageAlignmentSource, - MeasurementImageLabelAlignmentStrategy, - MeasurementLabelSourceAlignmentStrategy, PreparedMeasurementObjectLabels, ) from openhcs.core.measurement_image_alignment import ( @@ -105,9 +104,7 @@ def test_source_reference_requires_exact_shape_after_domain_selection() -> None: source = _MeasurementImageSource(np.ones((4, 5), dtype=np.float32)) with pytest.raises(ValueError, match="incompatible declared domains"): - MeasurementImageLabelAlignmentStrategy.align( - source.alignment_request(labels=np.ones((3, 5), dtype=np.int32)) - ) + source.alignment_request(labels=np.ones((3, 5), dtype=np.int32)).aligned().image @pytest.mark.parametrize( @@ -123,9 +120,7 @@ def test_source_reference_does_not_infer_singleton_or_color_projection( source = _MeasurementImageSource(image) with pytest.raises(ValueError, match="incompatible declared domains"): - MeasurementImageLabelAlignmentStrategy.align( - source.alignment_request(labels=np.ones((4, 5), dtype=np.int32)) - ) + source.alignment_request(labels=np.ones((4, 5), dtype=np.int32)).aligned().image def test_payload_scoped_labels_consume_declared_singleton_runtime_image_plane() -> None: @@ -142,9 +137,7 @@ def test_payload_scoped_labels_consume_declared_singleton_runtime_image_plane() ) source = _MeasurementImageSource(image) - aligned = MeasurementImageLabelAlignmentStrategy.align( - source.object_label_alignment_request(labels) - ) + aligned = source.object_label_alignment_request(labels).aligned().image assert isinstance(aligned, np.ndarray) assert aligned.shape == (4, 5) @@ -164,9 +157,7 @@ def test_payload_scoped_labels_preserve_declared_runtime_volume() -> None: ) source = _MeasurementImageSource(image) - aligned = MeasurementImageLabelAlignmentStrategy.align( - source.object_label_alignment_request(labels) - ) + aligned = source.object_label_alignment_request(labels).aligned().image assert aligned is image @@ -186,9 +177,7 @@ def test_payload_scoped_labels_reject_mismatched_declared_runtime_volume() -> No source = _MeasurementImageSource(image) with pytest.raises(ValueError, match="incompatible declared domains"): - MeasurementImageLabelAlignmentStrategy.align( - source.object_label_alignment_request(labels) - ) + source.object_label_alignment_request(labels).aligned().image def test_payload_scoped_labels_reject_non_runtime_image_plane_axis() -> None: @@ -206,9 +195,7 @@ def test_payload_scoped_labels_reject_non_runtime_image_plane_axis() -> None: source = _MeasurementImageSource(image) with pytest.raises(ValueError, match="incompatible declared domains"): - MeasurementImageLabelAlignmentStrategy.align( - source.object_label_alignment_request(labels) - ) + source.object_label_alignment_request(labels).aligned().image def test_object_reference_requires_nominal_label_payload() -> None: @@ -218,9 +205,7 @@ def test_object_reference_requires_nominal_label_payload() -> None: ) with pytest.raises(ValueError, match="requires an ObjectLabelValue"): - MeasurementImageLabelAlignmentStrategy.align( - source.alignment_request(labels=np.ones((4, 5), dtype=np.int32)) - ) + source.alignment_request(labels=np.ones((4, 5), dtype=np.int32)).aligned().image def test_object_reference_uses_declared_source_spatial_adapter() -> None: @@ -237,9 +222,7 @@ def test_object_reference_uses_declared_source_spatial_adapter() -> None: reference_domain=MeasurementImageReferenceDomain.OBJECT_LABELS, ) - aligned = MeasurementImageLabelAlignmentStrategy.align( - source.object_label_alignment_request(labels) - ) + aligned = source.object_label_alignment_request(labels).aligned().image np.testing.assert_array_equal(aligned, image[1:3, 1:3]) @@ -273,9 +256,7 @@ def test_object_reference_preserves_nominal_image_payload_context() -> None: reference_domain=MeasurementImageReferenceDomain.OBJECT_LABELS, ) - aligned = MeasurementImageLabelAlignmentStrategy.align( - source.object_label_alignment_request(labels) - ) + aligned = source.object_label_alignment_request(labels).aligned().image assert isinstance(aligned, ImageMetadataPayload) assert aligned.metadata.plane_axis is RuntimePlaneAxis.RUNTIME_SLICE @@ -472,9 +453,7 @@ def test_aligned_image_stack_requires_declared_runtime_slice_labels() -> None: source = _MeasurementImageSource(image) with pytest.raises(ValueError, match="declared plane-scoped runtime-slice axis"): - MeasurementImageLabelAlignmentStrategy.align( - source.alignment_request(labels=np.ones((4, 5), dtype=np.int32)) - ) + source.alignment_request(labels=np.ones((4, 5), dtype=np.int32)).aligned().image def test_singleton_aligned_image_stack_accepts_payload_scoped_labels() -> None: @@ -483,7 +462,7 @@ def test_singleton_aligned_image_stack_accepts_payload_scoped_labels() -> None: variant_data=ObjectLabelVariantData(labels=np.ones((4, 5), dtype=np.int32)) ) - aligned = MeasurementLabelSourceAlignmentStrategy.align( + aligned = MeasurementImageLabelAlignmentRequest.labels_for_image( image, labels, label_payload=labels, @@ -513,9 +492,7 @@ def test_aligned_image_stack_accepts_nominal_runtime_slice_payload() -> None: ) source = _MeasurementImageSource(image) - aligned = MeasurementImageLabelAlignmentStrategy.align( - source.object_label_alignment_request(labels) - ) + aligned = source.object_label_alignment_request(labels).aligned().image assert aligned is image @@ -553,9 +530,7 @@ def test_aligned_image_stack_preserves_sparse_runtime_slice_payload() -> None: ) source = _MeasurementImageSource(image) - aligned = MeasurementImageLabelAlignmentStrategy.align( - source.object_label_alignment_request(labels) - ) + aligned = source.object_label_alignment_request(labels).aligned().image assert aligned is image @@ -604,9 +579,7 @@ def test_named_image_output_bundle_broadcasts_one_label_domain() -> None: labels = np.ones((4, 5), dtype=np.int32) source = _MeasurementImageSource(image) - aligned = MeasurementImageLabelAlignmentStrategy.align( - source.alignment_request(labels=labels) - ) + aligned = source.alignment_request(labels=labels).aligned().image assert aligned is image @@ -625,11 +598,13 @@ def test_runtime_slice_aligned_values_require_matching_aligned_image() -> None: ) ) - assert MeasurementLabelSourceAlignmentStrategy.align(image, labels) is labels + assert ( + MeasurementImageLabelAlignmentRequest.labels_for_image(image, labels) is labels + ) mismatched = RuntimeSliceAlignedValues((labels.slices[0],)) with pytest.raises(ValueError, match="must match the aligned image count"): - MeasurementLabelSourceAlignmentStrategy.align(image, mismatched) + MeasurementImageLabelAlignmentRequest.labels_for_image(image, mismatched) def test_object_reference_replaces_unrelated_aligned_image_stack() -> None: @@ -661,6 +636,6 @@ def test_equal_label_planes_are_not_collapsed() -> None: plane = np.arange(20, dtype=np.int32).reshape(4, 5) labels = np.stack((plane, plane)) - aligned = MeasurementLabelSourceAlignmentStrategy.align(image, labels) + aligned = MeasurementImageLabelAlignmentRequest.labels_for_image(image, labels) assert aligned is labels diff --git a/tests/unit/test_measurement_lookup_dialect_performance.py b/tests/unit/test_measurement_lookup_dialect_performance.py index 1de36425ee..f6e11da79b 100644 --- a/tests/unit/test_measurement_lookup_dialect_performance.py +++ b/tests/unit/test_measurement_lookup_dialect_performance.py @@ -4,6 +4,8 @@ import math from openhcs.core.measurement_feature_queries import ( + ColumnarMeasurementTableSchema, + MeasurementAxisValueProjection, MeasurementFeatureQuery, MeasurementFeatureValueIndex, ) @@ -161,3 +163,205 @@ def test_columnar_lookup_distinguishes_source_object_absence_padding_and_nan() - explicit_nan_values = explicit_nan_indexes["Nuclei"].values_by_label assert set(explicit_nan_values) == {4} assert math.isnan(explicit_nan_values[4]) + + +def test_feature_batch_preserves_overlapping_axes_last_write_and_live_columns() -> None: + import numpy as np + from openhcs.core.runtime_measurements import MeasurementRowAxisField + from openhcs.core.measurement_row_materialization import MEASUREMENT_SPARSE_CELL + + ids = np.asarray([1, 1, 2, 3, 4], dtype=object) + first = np.asarray([5.0, 7.0, np.nan, MEASUREMENT_SPARSE_CELL, None], dtype=object) + table = MeasurementTable( + name="MutableCells", + subject=MeasurementSubject( + MeasurementScope.OBJECT, "Cells", id_field="cell_key" + ), + rows=MeasurementSparseColumnarRows( + columns={ + "cell_key": ids, + "slice_index": (None, 0, 1, 0, 1), + "first": first, + "second": (1.0, None, 8.0, 9.0, 10.0), + }, + fields=( + FieldSpec("cell_key", int), + FieldSpec("slice_index", int), + FieldSpec("first", float), + FieldSpec("second", float), + ), + ), + ) + schema = ColumnarMeasurementTableSchema.from_table(table) + queries = { + name: MeasurementFeatureQuery(name, object_name="Cells") + for name in ("first", "second") + } + objects = { + name: {"Cells": query.query_object_name} for name, query in queries.items() + } + masks = { + axis: MeasurementAxisValueProjection( + MeasurementRowAxisField.SLICE_INDEX, axis + ).mask(table.rows.column_values("slice_index")) + for axis in (0, 1) + } + + def project(): + return { + feature: { + axis: indexes["Cells"].values_by_label for axis, indexes in axes.items() + } + for feature, axes in schema.feature_value_indexes( + table, + queries, + objects, + index_type=MeasurementFeatureValueIndex, + row_masks=masks, + ) + } + + initial = project() + assert initial == { + "first": {0: {1: 7.0}, 1: {1: 5.0}}, + "second": {0: {1: 1.0, 3: 9.0}, 1: {1: 1.0, 2: 8.0, 4: 10.0}}, + } + ids[0] = 9 + first[0] = 15.0 + changed = project() + assert changed["first"] == {0: {9: 15.0, 1: 7.0}, 1: {9: 15.0}} + assert changed["second"][1] == {9: 1.0, 2: 8.0, 4: 10.0} + assert initial["first"][1] == {1: 5.0} + + +def test_feature_batch_keeps_alias_column_priority_and_feature_qualification() -> None: + import numpy as np + from openhcs.core.measurement_row_materialization import MEASUREMENT_SPARSE_CELL + + table = MeasurementTable( + name="SourceQualified", + subject=MeasurementSubject(MeasurementScope.OBJECT, "Nuclei"), + rows=MeasurementSparseColumnarRows( + columns={ + "object_label": (1, 2, 3, 3, 5), + "source_image_name": ("DNA", "DNA", "DNA", "DNA", "Memb"), + "mean-intensity": (None, np.nan, 3.0, MEASUREMENT_SPARSE_CELL, 5.0), + "mean intensity": (1.0, 2.0, 9.0, 4.0, 99.0), + }, + fields=( + FieldSpec("object_label", int), + FieldSpec("source_image_name", str), + FieldSpec("mean-intensity", float), + FieldSpec("mean intensity", float), + ), + ), + ) + queries = { + source: MeasurementFeatureQuery( + f"Intensity_MeanIntensity_{source}", + object_name="Nuclei", + dialect=_lookup_dialect(), + ) + for source in ("DNA", "Memb") + } + objects = { + source: {"Nuclei": query.query_object_name} for source, query in queries.items() + } + schema = ColumnarMeasurementTableSchema.from_table(table) + default = { + feature: axes[None]["Nuclei"].values_by_label + for feature, axes in schema.feature_value_indexes( + table, queries, objects, index_type=MeasurementFeatureValueIndex + ) + } + assert default == {"DNA": {1: 1.0, 2: 2.0, 3: 4.0}, "Memb": {5: 5.0}} + qualified = { + feature: axes[None]["Nuclei"].values_by_label + for feature, axes in schema.non_absent_feature_value_indexes( + table, + queries, + objects, + index_type=MeasurementFeatureValueIndex, + ) + } + assert qualified["DNA"][1] == 1.0 + assert np.isnan(qualified["DNA"][2]) + assert qualified["DNA"][3] == 4.0 + assert qualified["Memb"] == {5: 5.0} + + +def test_shared_rows_keep_table_subject_and_result_constructor_authorities() -> None: + import pytest + from openhcs.core.measurement_feature_queries import ( + ColumnarMeasurementTableSchema, + ) + + rows = MeasurementSparseColumnarRows( + columns={ + "object_name": ("Cells", "Nuclei"), + "object_label": [1, 2], + "cell_key": [1, 2], + "nucleus_key": (10, 20), + "area": (2.0, 3.0), + }, + fields=( + FieldSpec("object_name", str), + FieldSpec("object_label", int), + FieldSpec("cell_key", int), + FieldSpec("nucleus_key", int), + FieldSpec("area", float), + ), + ) + fixed = MeasurementTable( + name="Fixed", + rows=rows, + subject=MeasurementSubject( + MeasurementScope.OBJECT, "Cells", id_field="cell_key" + ), + ) + nuclei = MeasurementTable( + name="Nuclei", + rows=rows, + subject=MeasurementSubject( + MeasurementScope.OBJECT, "Nuclei", id_field="nucleus_key" + ), + ) + mixed = MeasurementTable( + name="Mixed", + rows=rows, + subject=MeasurementSubject( + MeasurementScope.ARTIFACT, "Mixed", id_field="cell_key" + ), + ) + first_schema = ColumnarMeasurementTableSchema.from_table(fixed) + first = (first_schema.object_names(fixed), first_schema.feature_names(fixed)) + second_schema = ColumnarMeasurementTableSchema.from_table(nuclei) + second = (second_schema.object_names(nuclei), second_schema.feature_names(nuclei)) + combined_schema = ColumnarMeasurementTableSchema.from_table(mixed) + combined = ( + combined_schema.object_names(mixed), + combined_schema.feature_names(mixed), + ) + assert first[0] == ("Cells",) + assert second[0] == ("Nuclei",) + assert combined[0] == ("Cells", "Nuclei") + assert "cell_key" not in first[1] and "nucleus_key" in first[1] + assert "nucleus_key" not in second[1] and "cell_key" in second[1] + + class PositiveLabelIndex(MeasurementFeatureValueIndex): + def __init__(self, values_by_label=None, positional_values=None): + super().__init__(values_by_label or {}, positional_values or []) + if any(label <= 0 for label in self.values_by_label): + raise ValueError("Positive label index requires positive labels") + + query = MeasurementFeatureQuery("area", object_name="Nuclei") + indexed = PositiveLabelIndex.from_columnar_table_by_object( + mixed, query, {"Nuclei": "Nuclei"} + ) + assert isinstance(indexed["Nuclei"], PositiveLabelIndex) + assert indexed["Nuclei"].values_by_label == {2: 3.0} + rows.columns["object_label"][1] = -2 + with pytest.raises(ValueError, match="requires positive labels"): + PositiveLabelIndex.from_columnar_table_by_object( + mixed, query, {"Nuclei": "Nuclei"} + ) diff --git a/tests/unit/test_measurement_row_materialization.py b/tests/unit/test_measurement_row_materialization.py index 3a3a2b054b..ed0cbd3606 100644 --- a/tests/unit/test_measurement_row_materialization.py +++ b/tests/unit/test_measurement_row_materialization.py @@ -133,9 +133,9 @@ def test_source_provenance_preserves_producer_image_name_and_fills_coordinates() ): rows = MeasurementProjectedColumnarRows( { - "slice_index": (0,), - "source_image_name": ("IllumActinAvg",), - "mean_intensity": (0.25,), + "slice_index": (1, 0, 1), + "source_image_name": ("IllumActinAvg",) * 3, + "mean_intensity": (0.5, 0.25, 0.75), }, fields=( FieldSpec("slice_index", int), @@ -146,14 +146,25 @@ def test_source_provenance_preserves_producer_image_name_and_fills_coordinates() provenance = SourceImageProvenance( source_image_names=("IllumActin",), source_image_provenance_planes=SourceImageProvenancePlanes.from_components( - paths=("/input/A01_s1_w2.tif",), - component_metadata=({"well": "A01", "site": "1", "channel": "2"},), + paths=("/input/A01_s1_w2.tif", "/input/A01_s2_w2.tif"), + component_metadata=( + {"well": "A01", "site": "1", "channel": "2"}, + {"well": "A01", "site": "2", "channel": "2"}, + ), ), ) projected = measurement_rows_with_source_provenance(rows, provenance) assert projected.row_mappings() == ( + { + "slice_index": 1, + "source_image_name": "IllumActinAvg", + "mean_intensity": 0.5, + "well": "A01", + "site": "2", + "channel": "2", + }, { "slice_index": 0, "source_image_name": "IllumActinAvg", @@ -162,6 +173,14 @@ def test_source_provenance_preserves_producer_image_name_and_fills_coordinates() "site": "1", "channel": "2", }, + { + "slice_index": 1, + "source_image_name": "IllumActinAvg", + "mean_intensity": 0.75, + "well": "A01", + "site": "2", + "channel": "2", + }, ) @@ -436,3 +455,86 @@ def test_sparse_rows_reject_columns_absent_from_declared_fields() -> None: ({"value": 1.0},), fields=(FieldSpec("other", float),), ) + + +def test_dataclass_column_admission_owns_snapshot_and_releases_source_rows() -> None: + import gc + import weakref + + from openhcs.core.runtime_tabular_values import measurement_row_mapping + + @dataclass + class MutableMeasurementRow: + object_label: int + samples: list[float] + + row = MutableMeasurementRow(1, [2.5]) + row_ref = weakref.ref(row) + rows = DataclassMeasurementColumnarRows((row,)) + admitted_samples = rows.column_values("samples")[0] + row.samples.append(7.5) + assert measurement_row_mapping(row)["samples"] == [2.5, 7.5] + assert admitted_samples == [2.5] + assert rows.row_mappings() == ({"object_label": 1, "samples": [2.5]},) + + del rows, row + gc.collect() + assert row_ref() is None + assert admitted_samples == [2.5] + + +def test_bounded_preview_is_live_but_explicit_column_admission_keeps_snapshot() -> None: + from openhcs.core.measurement_feature_queries import ( + ColumnarMeasurementTableSchema, + MeasurementFeatureQuery, + MeasurementFeatureValueIndex, + ) + from openhcs.core.progress.live_measurements import _columnar_row_preview + from openhcs.core.runtime_measurements import ( + MeasurementScope, + MeasurementSubject, + MeasurementTable, + ) + + first = MeasurementProjectedColumnarRows( + {"object_label": np.array([1]), "area": np.array([1.0])}, + fields=(FieldSpec("object_label", int), FieldSpec("area", float)), + ) + second = MeasurementProjectedColumnarRows( + {"object_label": np.array([2]), "other": np.array([2.0])}, + fields=(FieldSpec("object_label", int), FieldSpec("other", float)), + ) + rows = ConcatenatedColumnarRows((first, second)) + table = MeasurementTable( + name="Cells", + rows=rows, + subject=MeasurementSubject(MeasurementScope.OBJECT, "Cells"), + ) + assert "area" in rows.columns + assert "absent" not in rows.columns + preview = _columnar_row_preview(rows, 1, 2) + assert preview.rows == ({"object_label": 1, "area": 1.0},) + first.columns["area"][0] = 7.0 + query = MeasurementFeatureQuery("area", object_name="Cells") + + def current_index(): + return next( + ColumnarMeasurementTableSchema.from_table( + table + ).non_absent_feature_value_indexes( + table, + {"area": query}, + {"area": {"Cells": "Cells"}}, + index_type=MeasurementFeatureValueIndex, + ) + )[1][None]["Cells"] + + assert current_index().values_by_label == {1: 7.0} + whole_column = rows.column_values("area") + whole_column[1] = 9.0 + first.columns["area"][0] = 11.0 + assert current_index().values_by_label == {1: 7.0, 2: 9.0} + assert _columnar_row_preview(rows, 2, 2).rows == ( + {"object_label": 1, "area": 7.0}, + {"object_label": 2, "area": 9.0}, + ) diff --git a/tests/unit/test_measureobjectintensitydistribution.py b/tests/unit/test_measureobjectintensitydistribution.py index 926c93d25c..d4d8ec30bf 100644 --- a/tests/unit/test_measureobjectintensitydistribution.py +++ b/tests/unit/test_measureobjectintensitydistribution.py @@ -32,8 +32,8 @@ ) from openhcs.core.runtime_tabular_values import MeasurementObjectRowIdentity from openhcs.interop.cellprofiler.measurement_dialect import ( + CELLPROFILER_MEASUREMENT_DIALECT, CELLPROFILER_MEASUREMENT_LOOKUP_DIALECT, - cellprofiler_projected_measurement_feature_name, ) from openhcs.processing.backends.cellprofiler._backend import ( CellProfilerBackendProvider, @@ -387,7 +387,7 @@ def test_intensity_zernike_rows_own_native_feature_identity_and_axes(): ) assert native_feature_name == "RadialDistribution_ZernikeMagnitude_BF_image_2_0" assert ( - cellprofiler_projected_measurement_feature_name( + CELLPROFILER_MEASUREMENT_DIALECT.projected_feature_name( native_feature_name, (("n", 2), ("m", 0)), ) diff --git a/tests/unit/test_opaque_main_flow_image_domain.py b/tests/unit/test_opaque_main_flow_image_domain.py new file mode 100644 index 0000000000..7f02a14a48 --- /dev/null +++ b/tests/unit/test_opaque_main_flow_image_domain.py @@ -0,0 +1,441 @@ +"""Whole image domains survive the producer/cache/next-load handoff.""" + +from dataclasses import replace +from types import SimpleNamespace + +import numpy as np +import pytest + +from openhcs.constants.constants import MEMORY_TYPE_NUMPY +from openhcs.core.compiled_step_plan import CompiledStepPlan +from openhcs.core.component_group_scope import ComponentGroupScope +from openhcs.core.function_patterns import MainFlowInputProjection, compile_function_pattern +from openhcs.core.runtime_image_values import ( + ImagePayloadMetadata, + image_payload_data, + image_payload_mask, + image_payload_metadata, +) +from openhcs.core.runtime_plane_projection import RuntimePlaneAxis +from openhcs.core.runtime_slice_projection import RuntimeSliceProjection +from openhcs.core.source_spatial_domain import SourceSpatialDomain +from openhcs.core.steps.function_runtime import PatternGroupExecutionRequest, PatternGroupRuntime +from openhcs.core.aligned_image_payload import AlignedImageStack, ImageOutputBundle, AlignedImageSliceContext, ImagePayloadStackComposition +from openhcs.core.context.processing_context import ProcessingContext +from openhcs.core.steps.function_output_manifest import step_output_manifest, StepOutputManifestStore +from openhcs.core.source_bindings import CompiledSourceBindingPlan +from openhcs.core.step_dependencies import StepInputDependency +from openhcs.microscopes.source_schema import SourceSchemaFilenameParser +from openhcs.core.source_image_provenance import SourceImageProvenancePlanes + + +def _identity(image): + return image + + +def _runtime(): + pattern = compile_function_pattern(_identity, {}, {}) + runtime = object.__new__(PatternGroupRuntime) + runtime.request = SimpleNamespace( + compiled_group=pattern.default_group, + execution_plan=CompiledStepPlan( + step_index=0, + step_name="WholeImage", + step_type="FunctionStep", + axis_id="A01", + output_memory_type=MEMORY_TYPE_NUMPY, + input_memory_type=MEMORY_TYPE_NUMPY, + variable_components=(), + artifact_inputs={}, + artifact_outputs={}, + execution_group_scope=ComponentGroupScope.ungrouped(), + ), + component_key=None, + ) + return runtime + + +@pytest.mark.parametrize( + ("shape", "channel_axis"), + [((4, 5), None), ((4, 5, 3), -1), ((3, 4, 5), None), ((1, 4, 5), None)], + ids=("plane", "rgb", "volume", "one-z-volume"), +) +def test_opaque_whole_image_is_copied_without_a_new_execution_axis(shape, channel_axis): + pixels = np.arange(np.prod(shape), dtype=np.float32).reshape(shape) + mask_shape = shape[:2] if channel_axis is not None else shape + mask = np.ones(mask_shape, dtype=bool) + metadata = ImagePayloadMetadata( + source_path="/input/A01_s001_w1_z001_t001.tif", + source_component_metadata={"well": "A01", "site": "1", "channel": "1"}, + source_image_names=("WholeImage",), + source_channel_axis=channel_axis, + source_spatial_domain=SourceSpatialDomain( + origin_yx=(2, 3), source_shape_yx=(12, 13), + ), + ) + payload = metadata.payload_with(pixels, mask) + projected = _runtime()._project_output_slices( + payload, ["/input/A01_s001_w1_z001_t001.tif", "/input/A01_s001_w1_z002_t001.tif"], + ) + assert len(projected) == 1 + assert projected[0][0] is payload + cached = ImagePayloadStackComposition.copy_whole_image( + payload, memory_type=MEMORY_TYPE_NUMPY, device_id=None, + ) + assert image_payload_data(cached).shape == shape + assert image_payload_metadata(cached) == metadata + np.testing.assert_array_equal(image_payload_data(cached), pixels) + np.testing.assert_array_equal(image_payload_mask(cached), mask) + assert not np.shares_memory(image_payload_data(cached), pixels) + assert not np.shares_memory(image_payload_mask(cached), mask) + assert image_payload_metadata(cached) is not metadata + assert RuntimeSliceProjection.full_stack_value(cached) is cached + image_payload_data(cached).flat[0] = -100 + image_payload_mask(cached).flat[0] = False + assert pixels.flat[0] == 0 + assert mask.flat[0] + image_payload_metadata(cached).source_channel_axis = 0 + assert metadata.source_channel_axis == channel_axis + + +@pytest.mark.parametrize("count", [1, 3]) +def test_declared_runtime_axis_retains_its_exact_count(count): + pixels = np.arange(count * 4 * 5, dtype=np.float32).reshape(count, 4, 5) + payload = ImagePayloadMetadata(plane_axis=RuntimePlaneAxis.RUNTIME_SLICE).payload_with(pixels) + projected = _runtime()._project_output_slices(payload, ["source-1.tif", "source-2.tif"]) + assert len(projected) == count + assert all(image_payload_metadata(value).plane_axis is None for value, _context in projected) + assert image_payload_data(payload).shape == (count, 4, 5) + assert image_payload_metadata(payload).plane_axis is RuntimePlaneAxis.RUNTIME_SLICE + + +@pytest.mark.parametrize("named", [False, True]) +@pytest.mark.parametrize("axis", [None, RuntimePlaneAxis.RUNTIME_SLICE, RuntimePlaneAxis.SOURCE_BINDING]) +def test_nominal_alignment_owner_preserves_single_output_topology(named, axis): + shape = (3, 4, 5) if axis is None else (1, 4, 5) + payload = ImagePayloadMetadata(plane_axis=axis).payload_with(np.ones(shape, dtype=np.float32)) + context = AlignedImageSliceContext.main_flow("Image") + value = (ImageOutputBundle if named else AlignedImageStack)((payload,), (context,)) + projected = _runtime()._project_output_slices(value, ["source.tif"]) + stack_payload = value.copy_projected_output_stack( + projected, memory_type=MEMORY_TYPE_NUMPY, device_id=None, + ) + if named and axis is not RuntimePlaneAxis.RUNTIME_SLICE: + expected_shape, expected_axis = shape, axis + else: + expected_shape = (1, 4, 5) if axis is RuntimePlaneAxis.RUNTIME_SLICE else (1, *shape) + expected_axis = RuntimePlaneAxis.RUNTIME_SLICE + assert image_payload_data(stack_payload).shape == expected_shape + assert image_payload_metadata(stack_payload).plane_axis is expected_axis + + +@pytest.mark.parametrize("count", [1, 3]) +def test_raw_array_fallback_keeps_explicit_runtime_unstack_contract(count): + runtime = _runtime() + runtime.request.context = ProcessingContext(axis_id="A01") + runtime.request.context.microscope_handler = SimpleNamespace(parser=SourceSchemaFilenameParser()) + pixels = np.arange(count * 4 * 5, dtype=np.float32).reshape(count, 4, 5) + projected = runtime._project_output_slices(pixels, [f"source-{i}.tif" for i in range(count)]) + payloads = tuple(payload for payload, _context in projected) + cached = ImagePayloadStackComposition.with_saved_output_context( + pixels, payloads, [image_payload_metadata(payload) for payload in payloads], + single_output_plane_axis=RuntimePlaneAxis.RUNTIME_SLICE, + ) + assert image_payload_data(cached).shape == (count, 4, 5) + assert image_payload_metadata(cached).plane_axis is RuntimePlaneAxis.RUNTIME_SLICE + + +class _MemoryFiles: + def __init__(self): + self.values = {} + + def exists(self, path, backend): + return path in self.values or any(value_path.startswith(path.rstrip("/") + "/") for value_path in self.values) + + def ensure_directory(self, path, backend): + pass + + def save_batch(self, payloads, paths, backend): + self.values.update(zip(paths, payloads, strict=True)) + + def load_batch(self, paths, backend): + return [self.values[path] for path in paths] + + def delete(self, path, backend): + del self.values[path] + + +@pytest.mark.parametrize("cache_hit", [False, True]) +@pytest.mark.parametrize("axis", [None, RuntimePlaneAxis.RUNTIME_SLICE, RuntimePlaneAxis.SOURCE_BINDING]) +@pytest.mark.parametrize("shape", [(4, 5), (4, 5, 3), (3, 4, 5), (1, 4, 5)]) +def test_save_and_next_load_preserve_domain_and_independent_cache(tmp_path, monkeypatch, cache_hit, axis, shape, raw_named=False): + pixels = np.arange(np.prod(shape), dtype=np.float32).reshape(shape) + channel_axis = -1 if shape == (4, 5, 3) else None + if axis is not None: + pixels = pixels[None] + channel_axis = 3 if channel_axis is not None else None + mask = np.ones(pixels.shape[:-1] if channel_axis is not None else pixels.shape, dtype=bool) + path = "/input/A01_s001_w1_z001_t001.tif" + components = {"well": "A01", "site": "1", "channel": "1", "z_index": "1", "timepoint": "1"} + metadata = ImagePayloadMetadata( + source_path=path, source_component_metadata=components, source_image_names=("WholeImage",), + source_channel_axis=channel_axis, plane_axis=axis, + source_image_provenance_planes=( + SourceImageProvenancePlanes.from_components(paths=(path,), component_metadata=(components,)) + if axis is not None else SourceImageProvenancePlanes() + ), + ) + payload = pixels if raw_named else metadata.payload_with(pixels, mask) + if raw_named: + mask = None + producer = _runtime() + pattern = compile_function_pattern(_identity, {}, {}) + plan = replace(producer.request.execution_plan, output_dir=tmp_path, step_scope_id="whole-producer", compiled_function_pattern=pattern) + producer.request.execution_plan = plan + files = _MemoryFiles() + context = ProcessingContext(axis_id="A01", filemanager=files) + context.microscope_handler = SimpleNamespace(parser=SourceSchemaFilenameParser()) + producer.request.context = context + producer.pattern_repr = "whole" + output = ( + ImageOutputBundle((payload,), (AlignedImageSliceContext.main_flow("WholeImage"),)) + if axis is not None or raw_named else payload + ) + records = producer._save_outputs(output, [path]) + manifest = step_output_manifest(context) + manifest.record_outputs(plan, records) + assert records[0].main_flow_plane_axis is axis + physical = files.values[records[0].output_path] + assert np.shares_memory(image_payload_data(physical), pixels) + if not cache_hit: + context.runtime_image_stack_cache.clear() + consumer_plan = replace( + plan, step_index=1, step_scope_id="whole-consumer", input_dir=tmp_path, + main_input_dependency=StepInputDependency.step_output(source_step_index=0, source_step_scope_id=plan.step_scope_id), + ) + consumer = PatternGroupRuntime(PatternGroupExecutionRequest( + context=context, execution_plan=consumer_plan, compiled_group=pattern.default_group, + component_index=0, component_count=1, + pattern_group_info="A01_s001_w1_z{iii}_t001.tif", + )) + monkeypatch.setattr(consumer, "source_workspace_projection_authority", lambda: SimpleNamespace(projection_if_available=lambda: None)) + loaded = consumer._load_input_stack()[1] + assert image_payload_data(loaded).shape == pixels.shape + assert image_payload_metadata(loaded).plane_axis is axis + np.testing.assert_array_equal(image_payload_data(loaded), pixels) + np.testing.assert_array_equal(image_payload_mask(loaded), mask) + assert not np.shares_memory(image_payload_data(loaded), pixels) + if mask is not None: + assert not np.shares_memory(image_payload_mask(loaded), mask) + assert image_payload_metadata(loaded) is not image_payload_metadata(physical) + image_payload_metadata(loaded).source_provenance = image_payload_metadata(loaded).source_provenance.with_source_image_names(("Changed",)) + assert image_payload_metadata(physical).source_image_names == ("WholeImage",) + image_payload_data(loaded).flat[0] = -100 + if mask is not None: + image_payload_mask(loaded).flat[0] = False + assert mask.flat[0] + assert pixels.flat[0] == 0 + consumer._record_main_flow_passthrough([records[0].relative_output_path]) + (passed,) = manifest.produced_records_for(consumer_plan) + assert passed.main_flow_plane_axis is axis + assert passed.image_metadata is records[0].image_metadata + + +@pytest.mark.parametrize("runtime_count", [1, 3]) +def test_mixed_named_outputs_retain_each_original_axis_before_projection(runtime_count): + contexts = (AlignedImageSliceContext.main_flow("Planes"), AlignedImageSliceContext.main_flow("Volume")) + planes = ImagePayloadMetadata(plane_axis=RuntimePlaneAxis.RUNTIME_SLICE).payload_with(np.ones((runtime_count, 4, 5), dtype=np.float32)) + volume = ImagePayloadMetadata().payload_with(np.ones((4, 5) if runtime_count == 1 else (2, 4, 5), dtype=np.float32)) + bundle = ImageOutputBundle((planes, volume), contexts) + projected = _runtime()._project_output_slices(bundle, []) + assert bundle.copy_projected_output_stack( + projected, memory_type=MEMORY_TYPE_NUMPY, device_id=None, + ) is None + assert [bundle.plane_axis_for_output_context(context) for _payload, context in projected] == [RuntimePlaneAxis.RUNTIME_SLICE] * runtime_count + [None] + + +def test_passed_through_record_preserves_collapsed_and_filename_coordinates(tmp_path): + from openhcs.core.steps.function_output_manifest import ProducedOutputSemantics + from openhcs.core.steps.function_output_identity import FunctionOutputIdentity + plan = replace(_runtime().request.execution_plan, output_dir=tmp_path) + record = ProducedOutputSemantics.from_output( + plan, tmp_path / "A01_s001_w1_z001_t001.tif", + FunctionOutputIdentity(component_values={"well": "A01"}, filename_component_values={"well": "A01", "z_index": 1}, extension=".tif", source="test"), + main_flow_plane_axis=None, + ) + passed = record.passed_through(replace(plan, step_index=1, step_scope_id="next")) + assert passed.component_values == record.component_values + assert passed.filename_component_values == record.filename_component_values + assert passed.main_flow_plane_axis is None + + +def test_duplicate_physical_path_rejects_contradictory_whole_axis(tmp_path): + from openhcs.core.steps.function_output_manifest import ProducedOutputSemantics + from openhcs.core.steps.function_output_identity import FunctionOutputIdentity + plan = replace(_runtime().request.execution_plan, output_dir=tmp_path) + opaque = ProducedOutputSemantics.from_output( + plan, tmp_path / "A01_s001_w1_z001_t001.tif", + FunctionOutputIdentity(component_values={"well": "A01"}, extension=".tif", source="test"), + main_flow_plane_axis=None, + ) + with pytest.raises(ValueError, match="conflicting main-flow image axes"): + StepOutputManifestStore._unique_output_path_records((opaque, replace(opaque, main_flow_plane_axis=RuntimePlaneAxis.RUNTIME_SLICE))) + + +@pytest.mark.parametrize("cache_hit", [False, True]) +@pytest.mark.parametrize("shape", [(4, 5), (4, 5, 3), (3, 4, 5), (1, 4, 5)]) +def test_named_raw_image_actual_save_and_reload_retains_opaque_domain(tmp_path, monkeypatch, cache_hit, shape): + test_save_and_next_load_preserve_domain_and_independent_cache( + tmp_path, monkeypatch, cache_hit, None, shape, raw_named=True, + ) + + +def test_record_axis_survives_replace_and_pickle(tmp_path): + import pickle + from openhcs.core.steps.function_output_manifest import ProducedOutputSemantics + from openhcs.core.steps.function_output_identity import FunctionOutputIdentity + plan = replace(_runtime().request.execution_plan, output_dir=tmp_path) + for axis in (None, RuntimePlaneAxis.RUNTIME_SLICE, RuntimePlaneAxis.SOURCE_BINDING): + record = ProducedOutputSemantics.from_output( + plan, tmp_path / "A01_s001_w1_z001_t001.tif", + FunctionOutputIdentity(component_values={"well": "A01"}, extension=".tif", source="test"), + main_flow_plane_axis=axis, + ) + assert replace(record).main_flow_plane_axis is axis + restored = pickle.loads(pickle.dumps(record)) + assert restored == record + assert restored.main_flow_plane_axis is axis + + +def _selected_pattern(name): + from openhcs.core.artifacts import ArtifactSpec, ImageArtifactType + from openhcs.core.pipeline.function_contracts import artifact_inputs + from openhcs.core.function_patterns import InvocationArtifactInputEdgePlan, InvocationArtifactInputProjectionKey + spec = ArtifactSpec.input(name, ImageArtifactType) + + @artifact_inputs(spec) + def consume(image): + return image + + pattern = compile_function_pattern(consume, {}, {}) + invocation = pattern.default_group.invocations[0] + invocation = invocation.with_artifact_input_edges((InvocationArtifactInputEdgePlan( + key=InvocationArtifactInputProjectionKey(invocation_key=invocation.key, input_index=0), + spec=spec, storage_plan=None, projection=None, main_flow_projection=MainFlowInputProjection.DECLARED_SOURCE_IMAGE, + ),)) + return replace(pattern, groups=(replace(pattern.default_group, invocations=(invocation,)),)) + + +@pytest.mark.parametrize("cache_hit", [False, True]) +def test_saved_mixed_named_cohort_rejects_joint_load_and_preserves_selected_domains(tmp_path, monkeypatch, cache_hit): + from openhcs.core.artifacts import ImageArtifactType + source = "/input/A01_s001_w1_z001_t001.tif" + components = {"well": "A01", "site": "1", "channel": "1", "z_index": "1", "timepoint": "1"} + contexts = tuple(AlignedImageSliceContext.main_flow(name, artifact_kind=ImageArtifactType.value) for name in ("Planes", "Volume")) + scalar_metadata = ImagePayloadMetadata(source_path=source, source_component_metadata=components) + declared_metadata = scalar_metadata.replace_fields( + plane_axis=RuntimePlaneAxis.RUNTIME_SLICE, + source_image_provenance_planes=SourceImageProvenancePlanes.from_components(paths=(source,), component_metadata=(components,)), + ) + planes = declared_metadata.payload_with(np.arange(20, dtype=np.float32).reshape(1, 4, 5)) + opaque_pixels = np.arange(20, dtype=np.float32).reshape(4, 5) + 100 + opaque = scalar_metadata.payload_with(opaque_pixels) + producer = _runtime() + pattern = compile_function_pattern(_identity, {}, {}) + plan = replace(producer.request.execution_plan, output_dir=tmp_path, step_scope_id="mixed-producer", compiled_function_pattern=pattern) + producer.request.execution_plan = plan + files = _MemoryFiles() + context = ProcessingContext(axis_id="A01", filemanager=files) + context.microscope_handler = SimpleNamespace(parser=SourceSchemaFilenameParser()) + producer.request.context = context + producer.pattern_repr = "mixed" + + # A prior homogeneous producer caches the same physical paths. Mixed replacement + # must invalidate that cache rather than leave a false joint runtime domain. + old_bundle = ImageOutputBundle((planes, declared_metadata.payload_with(opaque_pixels[None])), contexts) + old_records = producer._save_outputs(old_bundle, [source, source]) + assert context.runtime_image_stack_cache.get(tuple(r.output_path for r in old_records), memory_type=MEMORY_TYPE_NUMPY) is not None + bundle = ImageOutputBundle((planes, opaque), contexts) + records = producer._save_outputs(bundle, [source, source]) + manifest = step_output_manifest(context) + manifest.record_outputs(plan, records) + assert tuple(r.output_path for r in records) == tuple(r.output_path for r in old_records) + assert [r.main_flow_plane_axis for r in records] == [RuntimePlaneAxis.RUNTIME_SLICE, None] + assert context.runtime_image_stack_cache.get(tuple(r.output_path for r in records), memory_type=MEMORY_TYPE_NUMPY) is None + + def consumer_for(compiled): + consumer_plan = replace(plan, step_index=1, step_scope_id="mixed-consumer", input_dir=tmp_path, + compiled_function_pattern=compiled, + main_input_dependency=StepInputDependency.step_output(source_step_index=0, source_step_scope_id=plan.step_scope_id)) + consumer = PatternGroupRuntime(SimpleNamespace(context=context, execution_plan=consumer_plan, + compiled_group=compiled.default_group, source_binding_plan=CompiledSourceBindingPlan.empty(), + component_key=None, pattern_group_info="A01_s001_w1_z{iii}_t001.tif")) + monkeypatch.setattr(consumer, "source_workspace_projection_authority", lambda: SimpleNamespace(projection_if_available=lambda: None)) + return consumer + + with pytest.raises(ValueError, match="different declared image axes"): + consumer_for(pattern)._load_input_stack() + for name, expected, axis in (("Planes", image_payload_data(planes), RuntimePlaneAxis.RUNTIME_SLICE), ("Volume", opaque_pixels, None)): + selected = consumer_for(_selected_pattern(name)) + actual = selected._load_input_stack()[1] + np.testing.assert_array_equal(image_payload_data(actual), expected) + assert image_payload_metadata(actual).plane_axis is axis + if not cache_hit: + context.runtime_image_stack_cache.clear() + else: + selected_path = next(r.output_path for r in records if r.producer_identity.output_key == name) + context.runtime_image_stack_cache.store((selected_path,), memory_type=MEMORY_TYPE_NUMPY, stack=actual) + repeated = selected._load_input_stack()[1] + np.testing.assert_array_equal(image_payload_data(repeated), expected) + assert image_payload_metadata(repeated).plane_axis is axis + + +def test_multiple_unprojected_named_binding_domains_fail_existing_bundle_grammar(): + contexts = tuple(AlignedImageSliceContext.main_flow(name) for name in ("First", "Second")) + payloads = tuple(ImagePayloadMetadata(plane_axis=RuntimePlaneAxis.SOURCE_BINDING).payload_with( + np.ones((1, 4, 5), dtype=np.float32)) for _ in contexts) + with pytest.raises(ValueError, match="plane axis to be projected"): + bundle = ImageOutputBundle(payloads, contexts) + bundle.copy_projected_output_stack(tuple(bundle.projected_output_slices()), memory_type=MEMORY_TYPE_NUMPY, device_id=None) + + +def test_opaque_named_bundle_uses_existing_same_slice_mask_composition(): + from openhcs.core.aligned_image_payload import ImagePayloadBundleContext + contexts = tuple(AlignedImageSliceContext.main_flow(name) for name in ("First", "Second")) + first_mask = np.ones((4, 5), dtype=bool) + second_mask = first_mask.copy() + second_mask[0, 0] = False + payloads = tuple(ImagePayloadMetadata(source_image_names=(name,)).payload_with( + np.ones((4, 5), dtype=np.float32) * i, mask) + for i, (name, mask) in enumerate(zip(("First", "Second"), (first_mask, second_mask), strict=True))) + bundle = ImageOutputBundle(payloads, contexts) + stack_payload = bundle.copy_projected_output_stack(tuple(bundle.projected_output_slices()), memory_type=MEMORY_TYPE_NUMPY, device_id=None) + expected = ImagePayloadBundleContext.from_payloads(payloads).compose() + assert image_payload_metadata(stack_payload).plane_axis is RuntimePlaneAxis.SOURCE_BINDING + np.testing.assert_array_equal(image_payload_data(stack_payload), image_payload_data(expected)) + np.testing.assert_array_equal(image_payload_mask(stack_payload), image_payload_mask(expected)) + + +def test_input_bundle_composition_retains_lazy_plan_device_resolution(tmp_path, monkeypatch): + from openhcs.core.steps.function_output_manifest import ProducedOutputSemantics + from openhcs.core.steps.function_output_identity import FunctionOutputIdentity + plan = replace(_runtime().request.execution_plan, output_dir=tmp_path) + records = tuple(ProducedOutputSemantics.from_output( + plan, tmp_path / f"A01_s001_w1_z001_t001_{name}.tif", + FunctionOutputIdentity(component_values={"well": "A01"}, extension=".tif", source="test"), + main_flow_plane_axis=None, + ) for name in ("First", "Second")) + payloads = tuple(ImagePayloadMetadata(source_image_names=(name,)).payload_with( + np.ones((4, 5), dtype=np.float32) * i) for i, name in enumerate(("First", "Second"))) + + def unexpected_device_resolution(self, memory_type): + raise AssertionError("BUNDLE composition must retain its own memory allocation authority") + + monkeypatch.setattr(CompiledStepPlan, "device_id_for", unexpected_device_resolution) + output = ImagePayloadStackComposition.from_loaded_images( + payloads, + producer_records=records, + execution_plan=plan, source_projection=None, workspace_source_lookups=(), + ) + assert image_payload_metadata(output).plane_axis is RuntimePlaneAxis.SOURCE_BINDING + np.testing.assert_array_equal(image_payload_data(output), np.stack([image_payload_data(p) for p in payloads])) diff --git a/tests/unit/test_openhcs_adapter.py b/tests/unit/test_openhcs_adapter.py index 383c8d8fbe..146640cc5c 100644 --- a/tests/unit/test_openhcs_adapter.py +++ b/tests/unit/test_openhcs_adapter.py @@ -42,6 +42,7 @@ VFSConfig, WellFilterConfig, ) +from openhcs.core.config_document import ConfigDocumentAuthority from openhcs.core.pipeline_document import PipelineDocumentAuthority from openhcs.core.pipeline_document_fields import PipelineDocumentField from openhcs.core.runtime_execution_validation import ( @@ -270,6 +271,11 @@ def __exit__(self, exc_type, exc, traceback): def disconnect(self): return None + def submit_prepared_pipeline(self, request): + if request.compile_control.compile_only: + return self.submit_compile(request) + return self.submit_pipeline(request) + def submit_compile(self, submission): compile_submission = submission.compile_request() self.submitted.append(compile_submission) @@ -283,13 +289,14 @@ def submit_compile(self, submission): def submit_pipeline(self, submission): self.submitted.append(submission) - assert submission.compile_artifact_id == "compile-1" + assert submission.compile_control.compile_artifact_id == "compile-1" return {"status": "accepted", "execution_id": "exec-1"} def wait_for_completion(self, execution_id, poll_interval=0.5): self.waits.append(execution_id) if execution_id == "compile-1": return { + "execution": self.poll_status(execution_id)["execution"], "status": "complete", "execution_id": execution_id, "results": {"well_count": 1, "wells": ["A01"]}, @@ -320,6 +327,7 @@ def wait_for_completion(self, execution_id, poll_interval=0.5): execution_id=execution_id, ).write(observation_path) return { + "execution": self.poll_status(execution_id)["execution"], "status": "complete", "execution_id": execution_id, "results": {"output_plate_root": str(tmp_path)}, @@ -334,6 +342,7 @@ def poll_status(self, execution_id): "plate_id": "/tmp/execution_plate", "client_address": None, "status": "complete", + "results_summary": {"output_plate_root": str(tmp_path)}, "start_time": 10.0 if execution_id == "compile-1" else 13.0, "end_time": 12.0 if execution_id == "compile-1" else 17.0, }, @@ -375,23 +384,25 @@ def poll_status(self, execution_id): ) == execution.results_summary ) - assert source == FakeZMQExecutionClient.submitted[0].pipeline_code() + assert source == FakeZMQExecutionClient.submitted[0].pipeline_code assert ( - FakeZMQExecutionClient.submitted[0].pipeline_document - is FakeZMQExecutionClient.submitted[1].pipeline_document + FakeZMQExecutionClient.submitted[0].pipeline_code + == FakeZMQExecutionClient.submitted[1].pipeline_code ) assert all( - submission.global_pipeline_config is global_config + submission.global_config_code == ConfigDocumentAuthority.render( + global_config, expected_config_type=GlobalPipelineConfig + ) for submission in FakeZMQExecutionClient.submitted ) assert [ - submission.compile_only for submission in FakeZMQExecutionClient.submitted + submission.compile_control.compile_only for submission in FakeZMQExecutionClient.submitted ] == [ True, False, ] assert [ - submission.compile_artifact_id + submission.compile_control.compile_artifact_id for submission in FakeZMQExecutionClient.submitted ] == [None, "compile-1"] assert FakeZMQExecutionClient.waits == ["compile-1", "exec-1"] diff --git a/tests/unit/test_openhcs_measured_run.py b/tests/unit/test_openhcs_measured_run.py index d01a215d92..aa4c2a140a 100644 --- a/tests/unit/test_openhcs_measured_run.py +++ b/tests/unit/test_openhcs_measured_run.py @@ -24,7 +24,7 @@ from openhcs.core.orchestrator.execution_result import ExecutionResult from openhcs.core.pipeline_document import PipelineDocumentAuthority from openhcs.runtime.zmq_application import OPENHCS_ENDPOINT_APPLICATION -from openhcs.runtime.zmq_execution_client import OpenHCSExecutionSubmission +from openhcs.runtime.zmq_execution_client import OpenHCSExecutionSubmission, ZMQExecutionRequestBuilder from openhcs.runtime.zmq_execution_observation import ZMQRuntimeExecutionOutcomeExport from openhcs.runtime.zmq_execution_signature import ( ZMQAuxiliaryExecutionParams, @@ -71,13 +71,18 @@ def __exit__(self, exc_type, exc, traceback): def disconnect(self): self.disconnect_count += 1 + def submit_prepared_pipeline(self, request): + if request.compile_control.compile_only: + return self.submit_compile(request) + return self.submit_pipeline(request) + def submit_compile(self, submitted): - assert submitted.pipeline_document is submission.pipeline_document + assert submitted.pipeline_code == submission.pipeline_code() return {"status": "accepted", "execution_id": "compile-1"} def submit_pipeline(self, submitted): - assert submitted.pipeline_document is submission.pipeline_document - assert submitted.compile_artifact_id == "compile-1" + assert submitted.pipeline_code == submission.pipeline_code() + assert submitted.compile_control.compile_artifact_id == "compile-1" assert ( ZMQAuxiliaryExecutionParams.from_transport( submitted.config_params @@ -90,6 +95,7 @@ def wait_for_completion(self, execution_id, poll_interval=0.5): if execution_id == "execute-1": observation_path.touch() return { + "execution": self.poll_status(execution_id)["execution"], "status": "complete", "execution_id": execution_id, "results": {"output_plate_root": str(tmp_path)}, @@ -219,6 +225,11 @@ def __init__(self) -> None: def owned_server_process_is_alive(self) -> bool: return True + def submit_prepared_pipeline(self, request): + if request.compile_control.compile_only: + return self.submit_compile(request) + return self.submit_pipeline(request) + def submit_compile(self, submission): self.run_number += 1 observer({"phase": "compile", "status": "started", "timestamp": 10.0}) @@ -228,7 +239,7 @@ def submit_compile(self, submission): } def submit_pipeline(self, submission): - assert submission.compile_artifact_id == f"compile-{self.run_number}" + assert submission.compile_control.compile_artifact_id == f"compile-{self.run_number}" observer({"phase": "axis_started", "timestamp": 11.0}) return { "status": "accepted", @@ -242,6 +253,7 @@ def wait_for_completion(self, execution_id, poll_interval=0.5): observer({"phase": "axis_completed", "timestamp": 12.0}) (tmp_path / f"run-{self.run_number - 1}" / "observation.pkl").touch() return { + "execution": self.poll_status(execution_id)["execution"], "status": "complete", "execution_id": execution_id, "results": {"output_plate_root": str(tmp_path)}, @@ -384,7 +396,7 @@ def test_shared_evidence_writer_never_overwrites_existing_artifact( with pytest.raises(FileExistsError, match="Measured run evidence already exists"): measured_run.retain_measured_openhcs_completion( - submission=submission, + request=ZMQExecutionRequestBuilder.from_task(submission), execution_id="execution-1", results_summary={}, endpoint_provenance=endpoint, @@ -486,7 +498,7 @@ def test_outcome_only_run_uses_the_shared_receipt_finalizer(tmp_path: Path) -> N with pytest.raises(ToolExecutionError, match="execution identity does not match"): measured_run.retain_measured_openhcs_completion( - submission=submission, + request=ZMQExecutionRequestBuilder.from_task(submission), execution_id="stale-job", results_summary={"well_count": 1}, endpoint_provenance=endpoint, @@ -499,7 +511,7 @@ def test_outcome_only_run_uses_the_shared_receipt_finalizer(tmp_path: Path) -> N with pytest.raises(ToolExecutionError, match="Expected 2 execution axes"): measured_run.retain_measured_openhcs_completion( - submission=submission, + request=ZMQExecutionRequestBuilder.from_task(submission), execution_id="execution-1", results_summary={"well_count": 1}, endpoint_provenance=endpoint, @@ -520,7 +532,7 @@ def test_outcome_only_run_uses_the_shared_receipt_finalizer(tmp_path: Path) -> N ).write(observation_path) with pytest.raises(ToolExecutionError, match="no completed axes"): measured_run.retain_measured_openhcs_completion( - submission=submission, + request=ZMQExecutionRequestBuilder.from_task(submission), execution_id="execution-1", results_summary={"well_count": 0}, endpoint_provenance=endpoint, @@ -543,7 +555,7 @@ def test_outcome_only_run_uses_the_shared_receipt_finalizer(tmp_path: Path) -> N ).write(observation_path) with pytest.raises(ToolExecutionError, match="lacks compiled axis membership"): measured_run.retain_measured_openhcs_completion( - submission=submission, + request=ZMQExecutionRequestBuilder.from_task(submission), execution_id="execution-1", results_summary={"well_count": 1}, endpoint_provenance=endpoint, @@ -562,7 +574,7 @@ def test_outcome_only_run_uses_the_shared_receipt_finalizer(tmp_path: Path) -> N ).write(observation_path) completion = measured_run.retain_measured_openhcs_completion( - submission=submission, + request=ZMQExecutionRequestBuilder.from_task(submission), execution_id="execution-1", results_summary={"well_count": 1}, endpoint_provenance=endpoint, @@ -595,7 +607,7 @@ def test_outcome_only_run_uses_the_shared_receipt_finalizer(tmp_path: Path) -> N receipt_path.unlink() config_path.unlink() recovered = measured_run.retain_measured_openhcs_completion( - submission=submission, + request=ZMQExecutionRequestBuilder.from_task(submission), execution_id="execution-1", results_summary={"well_count": 1}, endpoint_provenance=endpoint, @@ -610,7 +622,7 @@ def test_outcome_only_run_uses_the_shared_receipt_finalizer(tmp_path: Path) -> N assert MeasuredPipelineRunReceipt.read(receipt_path) == recovered.receipt with pytest.raises(FileExistsError, match="Measured run evidence already exists"): measured_run.retain_measured_openhcs_completion( - submission=submission, + request=ZMQExecutionRequestBuilder.from_task(submission), execution_id="execution-1", results_summary={"well_count": 1}, endpoint_provenance=endpoint, diff --git a/tests/unit/test_output_publication_ownership.py b/tests/unit/test_output_publication_ownership.py new file mode 100644 index 0000000000..a8984c7f24 --- /dev/null +++ b/tests/unit/test_output_publication_ownership.py @@ -0,0 +1,157 @@ +"""Real output publication keeps buffer preparation and commit effects ordered.""" + +from dataclasses import replace +from types import SimpleNamespace + +import numpy as np +import pytest +from polystore.filemanager import FileManager +from polystore.memory import MemoryStorageBackend + +from openhcs.core.aligned_image_payload import ( + AlignedImageSliceContext, + AlignedImageStack, + ImageOutputBundle, + ImagePayloadStackComposition, +) +from openhcs.core.compiled_step_plan import CompiledStepPlan +from openhcs.core.component_group_scope import ComponentGroupScope +from openhcs.core.context.processing_context import ProcessingContext +from openhcs.core.function_patterns import compile_function_pattern +from openhcs.core.runtime_image_values import ImagePayloadMetadata, image_payload_data +from openhcs.core.steps.function_output_manifest import step_output_manifest +from openhcs.core.steps.function_runtime import PatternGroupRuntime +from openhcs.microscopes.source_schema import SourceSchemaFilenameParser + + +SOURCE = "/source/A01_s001_w1_z001_t001.tif" + + +def _identity(image): + return image + + +def _runtime(tmp_path): + filemanager = FileManager({"memory": MemoryStorageBackend()}) + context = ProcessingContext(axis_id="A01", filemanager=filemanager) + context.microscope_handler = SimpleNamespace(parser=SourceSchemaFilenameParser()) + plan = CompiledStepPlan( + step_index=0, + step_name="OutputOwnership", + step_type="FunctionStep", + step_scope_id="output-ownership", + axis_id="A01", + input_memory_type="numpy", + output_memory_type="numpy", + output_dir=tmp_path, + variable_components=(), + artifact_inputs={}, + artifact_outputs={}, + execution_group_scope=ComponentGroupScope.ungrouped(), + ) + runtime = PatternGroupRuntime(SimpleNamespace( + context=context, + execution_plan=plan, + compiled_group=compile_function_pattern(_identity, {}, {}).default_group, + component_key=None, + pattern_group_info="A01_s001_w1_z001_t001.tif", + )) + payload = ImagePayloadMetadata( + source_path=SOURCE, + source_component_metadata={ + "well": "A01", "site": "1", "channel": "1", "z_index": "1", "timepoint": "1", + }, + ).payload_with(np.ones((4, 5), dtype=np.float32)) + return runtime, payload + + +def test_buffer_preparation_failure_precedes_any_vfs_publication(tmp_path, monkeypatch): + runtime, payload = _runtime(tmp_path) + files = runtime.request.context.filemanager + events = [] + + def fail_copy(*args, **kwargs): + events.append("copy") + raise ValueError("buffer allocation failed") + + def unexpected_exists(*args, **kwargs): + pytest.fail("output path access must follow independent buffer preparation") + + monkeypatch.setattr(ImagePayloadStackComposition, "copy_whole_image", staticmethod(fail_copy)) + monkeypatch.setattr(files, "exists", unexpected_exists) + with pytest.raises(ValueError, match="buffer allocation failed"): + runtime._save_outputs(payload, [SOURCE]) + assert events == ["copy"] + assert runtime.request.context.runtime_image_stack_cache.stacks == {} + + +def test_saved_metadata_failure_keeps_actual_commit_but_no_cache_or_manifest(tmp_path, monkeypatch): + runtime, payload = _runtime(tmp_path) + files = runtime.request.context.filemanager + path = str(tmp_path / "A01_s001_w1_z001_t001.tif") + + def fail_attachment(*args, **kwargs): + assert files.load(path, "memory") is args[1][0] + assert np.shares_memory(image_payload_data(args[1][0]), payload.data) + raise ValueError("saved context failed") + + monkeypatch.setattr(ImagePayloadStackComposition, "with_saved_output_context", staticmethod(fail_attachment)) + with pytest.raises(ValueError, match="saved context failed"): + runtime._save_outputs(payload, [SOURCE]) + assert np.shares_memory(image_payload_data(files.load(path, "memory")), payload.data) + assert runtime.request.context.runtime_image_stack_cache.stacks == {} + assert step_output_manifest(runtime.request.context).produced_records_for(runtime.request.execution_plan) == () + + +def test_duplicate_output_paths_leave_existing_memory_value_and_cache_intact(tmp_path): + runtime, payload = _runtime(tmp_path) + context = runtime.request.context + path = str(tmp_path / "A01_s001_w1_z001_t001.tif") + previous = np.full((4, 5), 9, dtype=np.float32) + context.filemanager.ensure_directory(str(tmp_path), "memory") + context.filemanager.save(previous, path, "memory") + context.runtime_image_stack_cache.store((path,), memory_type="numpy", stack=previous) + output = AlignedImageStack((payload, replace(payload))) + with pytest.raises(ValueError, match="duplicate output path"): + runtime._save_outputs(output, [SOURCE, SOURCE]) + assert context.filemanager.load(path, "memory") is previous + assert context.runtime_image_stack_cache.get((path,), memory_type="numpy") is previous + + +def test_original_named_owner_is_consulted_at_saved_metadata_epoch(tmp_path): + runtime, payload = _runtime(tmp_path) + files = runtime.request.context.filemanager + path = str(tmp_path / "A01_s001_w1_z001_t001_Named.tif") + calls = [] + + class EpochSensitiveBundle(ImageOutputBundle): + def plane_axis_for_output_context(self, context): + calls.append(files.exists(path, "memory")) + if calls[-1]: + raise ValueError("post-save domain rejected") + return super().plane_axis_for_output_context(context) + + output = EpochSensitiveBundle((payload,), (AlignedImageSliceContext.main_flow("Named"),)) + with pytest.raises(ValueError, match="post-save domain rejected"): + runtime._save_outputs(output, [SOURCE]) + assert calls == [False, True] + np.testing.assert_array_equal(image_payload_data(files.load(path, "memory")), payload.data) + assert runtime.request.context.runtime_image_stack_cache.stacks == {} + + +def test_anonymous_context_is_shared_by_record_and_post_save_axis_hooks(tmp_path): + runtime, payload = _runtime(tmp_path) + calls = [] + + class AnonymousStack(AlignedImageStack): + def plane_axis_for_output_context(self, context): + calls.append(context) + return super().plane_axis_for_output_context(context) + + output = AnonymousStack((payload,)) + (record,) = runtime._save_outputs(output, [SOURCE]) + assert calls[0] is None + assert len(calls) == 3 + assert calls[1].is_anonymous_main_flow + assert calls[2] is calls[1] + assert record.output_context == calls[1] diff --git a/tests/unit/test_path_planner_materialization.py b/tests/unit/test_path_planner_materialization.py index 53202a49b6..9545224acb 100644 --- a/tests/unit/test_path_planner_materialization.py +++ b/tests/unit/test_path_planner_materialization.py @@ -1,3 +1,4 @@ +from openhcs.core.pipeline.compilation_session import ResolvedPipelineDefinition from dataclasses import dataclass, replace from pathlib import Path from types import SimpleNamespace @@ -87,7 +88,7 @@ PathPlannerStepAssemblyStage, PathPlannerValidationStage, ) -from openhcs.core.pipeline.step_snapshot import StepSnapshot +from openhcs.core.steps.abstract import AbstractStep from openhcs.core.artifact_key_selection import AdapterRecordedArtifactOutputPolicy from openhcs.core.runtime_adapters import runtime_adapter from openhcs.core.runtime_object_labels import ObjectLabelValue @@ -101,7 +102,6 @@ SourceBindingOrigin, SourceBindingsConfig, SourceProjectionRole, - SourceBindingRuntimeContext, StepSourceBindingsConfig, ) from openhcs.core.step_dependencies import StepInputDependency @@ -111,7 +111,7 @@ from openhcs.core.steps.function_runtime import ( ComponentArtifactPlans, FunctionCoreExecutor, - FunctionRuntimeScope, + PatternGroupData, ) from openhcs.microscopes.microscope_interfaces import MetadataArtifactProvider from openhcs.microscopes.openhcs import OpenHCSMetadataHandler @@ -144,13 +144,14 @@ def _execute_compiled_metadata_pattern(compiled, input_plans=None, stored_output ), path=producer.path, backend="memory", ) - scope = FunctionRuntimeScope( + scope = PatternGroupData( + matching_files=["input.tif"], + main_data_stack=np.zeros((1, 3, 4), dtype=np.uint16), context=context, execution_plan=plan, compiled_group=compiled.default_group, component_value=None, artifacts=ComponentArtifactPlans.from_step_component(plan, None), - source_binding_context=SourceBindingRuntimeContext.empty(), runtime_plane_index=0, runtime_plane_count=1, ) @@ -159,7 +160,7 @@ def _execute_compiled_metadata_pattern(compiled, input_plans=None, stored_output result = FunctionCoreExecutor( main_data_arg=ImagePayloadMetadata().payload_with(source), source_memory_type=MEMORY_TYPE_NUMPY, - runtime_scope=scope, + group_data=scope, invocation=invocation, artifacts=scope.artifacts.select_for_invocation( invocation, execution_scope=plan.execution_group_scope, component_key=None @@ -191,16 +192,28 @@ def resolve(self, handler, plate_path): def _compile_metadata_pattern(planner, pattern): - snapshot = _snapshot(func=pattern) - declarations, pattern, _, _ = planner.artifacts.prepare_step_declarations(snapshot) + snapshot = _resolved_step(func=pattern) + declarations, pattern, _, _ = planner.artifacts.prepare_step_declarations( + snapshot, 3 + ) input_plans = planner.artifacts.process_artifact_inputs( - declarations, snapshot.index, PathPlannerGroupScope.ungrouped(), - EMPTY_SOURCE_BINDINGS, ComponentSet(), snapshot.step.name, + declarations, + 3, + PathPlannerGroupScope.ungrouped(), + EMPTY_SOURCE_BINDINGS, + ComponentSet(), + snapshot.name, execution_scope=FunctionStepExecutionScope.AXIS, ) compiled = planner.artifacts.build_step_compiled_function_pattern( - snapshot, True, planner.artifacts.inject_metadata(pattern, declarations.inputs), - input_plans, {}, {}, PathPlannerGroupScope.ungrouped(), + snapshot, + 3, + True, + planner.artifacts.inject_metadata(pattern, declarations.inputs), + input_plans, + {}, + {}, + PathPlannerGroupScope.ungrouped(), ) return compiled, input_plans @@ -278,10 +291,8 @@ def process(self, context, step_index: int) -> None: del context, step_index -def _snapshot( +def _resolved_step( *, - index: int = 3, - scope_id: str | None = None, name: str = "step", is_function_step: bool = True, func=None, @@ -291,7 +302,7 @@ def _snapshot( input_source: InputSource = InputSource.PREVIOUS_STEP, processing_config: ProcessingConfig | None = None, step_materialization_config=None, -) -> StepSnapshot: +) -> AbstractStep: if func is None: def passthrough(image): @@ -316,11 +327,7 @@ def passthrough(image): if is_function_step else _NonFunctionStep(**step_kwargs) ) - return StepSnapshot( - index=index, - scope_id=scope_id or f"plate::functionstep_{index}", - step=step, - ) + return step def test_metadata_satisfied_artifact_input_compiles_without_runtime_plan(): @@ -341,7 +348,7 @@ def metadata_consumer(image, grid_dimensions): ) planner.ctx.plate_path = planner.plate_path pattern = (metadata_consumer, {"grid_dimensions": None}) - snapshot = _snapshot( + snapshot = _resolved_step( func=pattern, source_bindings=StepSourceBindingsConfig( enabled=True, @@ -349,7 +356,7 @@ def metadata_consumer(image, grid_dimensions): ), ) declarations, pattern, _, contracts = planner.artifacts.prepare_step_declarations( - snapshot + snapshot, 3 ) execution_bindings = planner.artifacts.source_bindings_for_contracts( snapshot, @@ -367,16 +374,17 @@ def metadata_consumer(image, grid_dimensions): ) runtime_input_plans = planner.artifacts.process_artifact_inputs( declarations, - snapshot.index, + 3, PathPlannerGroupScope.ungrouped(), execution_bindings, ComponentSet(), - snapshot.step.name, + snapshot.name, execution_scope=FunctionStepExecutionScope.AXIS, ) compiled = planner.artifacts.build_step_compiled_function_pattern( snapshot, + 3, True, planner.artifacts.inject_metadata(pattern, declarations.inputs), runtime_input_plans, @@ -587,7 +595,7 @@ def export_measurements(*, artifact_batch: RuntimeArtifactBatch): planner.artifact_context, available_artifacts=ArtifactSpecCollection((measurements,)), ) - snapshot = _snapshot( + snapshot = _resolved_step( func=export_measurements, name="PlateExporter", source_bindings=StepSourceBindingsConfig( @@ -603,7 +611,7 @@ def export_measurements(*, artifact_batch: RuntimeArtifactBatch): pattern, callable_scope, contracts, - ) = planner.artifacts.prepare_step_declarations(snapshot) + ) = planner.artifacts.prepare_step_declarations(snapshot, 3) execution_bindings = planner.artifacts.source_bindings_for_contracts( snapshot, contracts, @@ -611,7 +619,7 @@ def export_measurements(*, artifact_batch: RuntimeArtifactBatch): ) maps = planner.artifacts.compile_plan_maps( snapshot, - snapshot.index, + 3, declarations, PathPlannerGroupScope.ungrouped(), callable_scope, @@ -619,6 +627,7 @@ def export_measurements(*, artifact_batch: RuntimeArtifactBatch): ) compiled = planner.artifacts.build_step_compiled_function_pattern( snapshot, + 3, True, pattern, maps.inputs, @@ -626,8 +635,8 @@ def export_measurements(*, artifact_batch: RuntimeArtifactBatch): maps.relation_source_scopes, maps.group_scope, ) - plan = planner.plans[snapshot.index] - plan.step_name = snapshot.step.name + plan = planner.plans[3] + plan.step_name = snapshot.name plan.func = pattern plan.main_input_dependency = StepInputDependency.no_main_flow() plan.artifact_inputs = maps.inputs @@ -760,7 +769,8 @@ def __call__(self, invocation, step_context): match="Conflicting compiled invocation output artifact sidecar role", ): planner.artifacts.build_step_compiled_function_pattern( - _snapshot(func=pattern), + _resolved_step(func=pattern), + 0, True, pattern, {}, @@ -789,10 +799,8 @@ def test_materialization_collision_updates_results_dir_and_config(): materialization_config=PathConfigStub(sub_dir="images"), ) } - snapshot = _snapshot( - index=3, - name="materialize", - step_materialization_config=PathConfigStub(sub_dir="images"), + snapshot = _resolved_step( + name="materialize", step_materialization_config=PathConfigStub(sub_dir="images") ) planner.paths = PathPlannerPathAuthority(planner) @@ -805,7 +813,7 @@ def test_materialization_collision_updates_results_dir_and_config(): "main flow", ) - assert snapshot.step.step_materialization_config.sub_dir == "images" + assert snapshot.step_materialization_config.sub_dir == "images" materialized_output = planner.plans[3].materialized_output assert materialized_output.output_dir == Path("/data/plate1_processed/images_step3") assert materialized_output.sub_dir == "images_step3" @@ -855,8 +863,7 @@ def test_same_name_typed_artifacts_compile_through_producer_and_consumer_plans() def produce_shared(): return None - producer_snapshot = _snapshot( - index=2, + producer_snapshot = _resolved_step( name="produce_shared", func=produce_shared, group_by=GroupBy.NONE, @@ -868,10 +875,10 @@ def produce_shared(): producer_pattern, producer_scope, _producer_contracts, - ) = planner.artifacts.prepare_step_declarations(producer_snapshot) + ) = planner.artifacts.prepare_step_declarations(producer_snapshot, 2) producer_maps = planner.artifacts.compile_plan_maps( producer_snapshot, - producer_snapshot.index, + 2, producer_declarations, PathPlannerGroupScope.ungrouped(), producer_scope, @@ -879,6 +886,7 @@ def produce_shared(): ) producer_compiled = planner.artifacts.build_step_compiled_function_pattern( producer_snapshot, + 2, True, producer_pattern, producer_maps.inputs, @@ -920,8 +928,7 @@ def consume_shared(image, shared_image, shared_labels): del shared_image, shared_labels return image - consumer_snapshot = _snapshot( - index=3, + consumer_snapshot = _resolved_step( name="consume_shared", func=consume_shared, group_by=GroupBy.NONE, @@ -932,10 +939,10 @@ def consume_shared(image, shared_image, shared_labels): consumer_pattern, consumer_scope, _consumer_contracts, - ) = planner.artifacts.prepare_step_declarations(consumer_snapshot) + ) = planner.artifacts.prepare_step_declarations(consumer_snapshot, 3) consumer_maps = planner.artifacts.compile_plan_maps( consumer_snapshot, - consumer_snapshot.index, + 3, consumer_declarations, PathPlannerGroupScope.ungrouped(), consumer_scope, @@ -943,6 +950,7 @@ def consume_shared(image, shared_image, shared_labels): ) consumer_compiled = planner.artifacts.build_step_compiled_function_pattern( consumer_snapshot, + 3, True, consumer_pattern, consumer_maps.inputs, @@ -1139,7 +1147,7 @@ def combine_sources(image, secondary=None): edges = next(compiled.iter_invocations()).artifact_input_edges assert tuple(edge.spec for edge in edges) == source_specs - assert tuple(edge.consumes_main_flow for edge in edges) == (True, False, False) + assert tuple((edge.main_flow_projection is not None) for edge in edges) == (True, False, False) assert edges[0].storage_plan is None assert edges[0].projection is None assert edges[1].storage_plan is stored_inputs.get(source_specs[1].ref()) @@ -1181,14 +1189,6 @@ def test_implicit_native_main_flow_provenance_drives_artifact_owned_scope(): processing_config=processing_config, ), ) - snapshots = tuple( - StepSnapshot( - index=index, - scope_id=f"implicit-main-flow::functionstep_{index}", - step=step, - ) - for index, step in enumerate(steps) - ) session = CompilationSession.from_context( context=ProcessingContext( step_plans={ @@ -1202,11 +1202,11 @@ def test_implicit_native_main_flow_provenance_drives_artifact_owned_scope(): }, axis_id="A01", ), - steps=steps, orchestrator=SimpleNamespace(pipeline_config=PipelineConfig()), global_config=GlobalPipelineConfig(), - step_state_map={index: object() for index in range(len(steps))}, - snapshots=snapshots, + pipeline=ResolvedPipelineDefinition( + steps=steps, step_state_map={index: object() for index in range(len(steps))} + ), ) provider = CellProfilerInvocationContractProviderFactory.provider_for_session( session @@ -1274,7 +1274,7 @@ def test_implicit_native_main_flow_provenance_drives_artifact_owned_scope(): assert planner.declared == {} execution_scope = planner.execution_groups.get_execution_groups( - snapshots[1], + steps[1], PathPlannerComponentScopes.empty(), contracts=(consumer_contract,), ) @@ -1309,7 +1309,7 @@ def test_implicit_native_main_flow_provenance_drives_artifact_owned_scope(): edge = next(compiled_consumer.iter_invocations()).artifact_input_edges[0] assert edge.spec == cursor assert edge.storage_plan is None - assert edge.consumes_main_flow + assert edge.main_flow_projection is not None def test_artifact_output_source_uses_compiled_plan_across_parameter_occurrences(): @@ -1573,10 +1573,8 @@ def identify(main_image, Stain1): producer_step_name="Align", ), ) - snapshot = _snapshot( - name="IdentifyPrimaryObjects", - func=identify, - source_bindings=source_bindings, + snapshot = _resolved_step( + name="IdentifyPrimaryObjects", func=identify, source_bindings=source_bindings ) declarations = extract_artifact_declarations(identify) execution_scope = planner.execution_groups.get_execution_groups( @@ -1599,6 +1597,7 @@ def identify(main_image, Stain1): ) compiled = planner.artifacts.build_step_compiled_function_pattern( snapshot, + 3, True, identify, maps.inputs, @@ -1962,7 +1961,7 @@ def test_declared_group_lineage_scopes_outputs_without_rewriting_execution(): ) maps = planner.artifacts.compile_plan_maps( - _snapshot(name="FilterObjects"), + _resolved_step(name="FilterObjects"), 3, declarations, PathPlannerGroupScope.from_raw(("2",), component=AllComponents.CHANNEL), @@ -2014,7 +2013,7 @@ def test_declared_group_lineage_uses_main_flow_scope_without_artifact_plan(): ) maps = planner.artifacts.compile_plan_maps( - _snapshot(name="MeasureColocalization"), + _resolved_step(name="MeasureColocalization"), 3, declarations, group_scope, @@ -2065,7 +2064,7 @@ def test_prior_main_flow_artifact_scopes_output_without_rewriting_execution(): ) maps = planner.artifacts.compile_plan_maps( - _snapshot(name="IdentifyPrimaryObjects"), + _resolved_step(name="IdentifyPrimaryObjects"), 3, declarations, PathPlannerGroupScope.from_raw( @@ -2107,7 +2106,7 @@ def test_dict_invocation_lineage_uses_its_non_plan_input_group_scope(): ) maps = planner.artifacts.compile_plan_maps( - _snapshot(name="IdentifyPrimaryObjects"), + _resolved_step(name="IdentifyPrimaryObjects"), 3, declarations, PathPlannerGroupScope.from_raw( @@ -2177,7 +2176,7 @@ def test_measurement_output_scope_compiles_exact_cross_group_consumer_edge(): ) maps = planner.artifacts.compile_plan_maps( - _snapshot(name="MeasureObjectIntensity"), + _resolved_step(name="MeasureObjectIntensity"), 2, declarations, PathPlannerGroupScope.from_raw( @@ -2212,7 +2211,7 @@ def filter_objects(main_image, MeasureObjectIntensity_3_measurements): DEFAULT_GROUP_KEY, 0, ) - consumer_snapshot = _snapshot( + consumer_snapshot = _resolved_step( name="FilterObjects", func=filter_objects, group_by=GroupBy.CHANNEL, @@ -2236,6 +2235,7 @@ def filter_objects(main_image, MeasureObjectIntensity_3_measurements): ) compiled = planner.artifacts.build_step_compiled_function_pattern( consumer_snapshot, + 3, True, filter_objects, consumer_maps.inputs, @@ -2313,7 +2313,7 @@ def test_artifact_managed_lineage_keeps_exact_named_inputs_in_one_invocation(): ) maps = planner.artifacts.compile_plan_maps( - _snapshot(name="MeasureObjectSizeShape"), + _resolved_step(name="MeasureObjectSizeShape"), 3, declarations, PathPlannerGroupScope.ungrouped(), @@ -2366,7 +2366,7 @@ def test_artifact_managed_single_source_output_retains_source_group_scope(): ) maps = planner.artifacts.compile_plan_maps( - _snapshot(name="IdentifyPrimaryObjects"), + _resolved_step(name="IdentifyPrimaryObjects"), 3, declarations, PathPlannerGroupScope.ungrouped(), @@ -2432,7 +2432,7 @@ def test_declared_group_lineage_unions_compatible_source_groups(): ) maps = planner.artifacts.compile_plan_maps( - _snapshot(name="Measure"), + _resolved_step(name="Measure"), 3, declarations, PathPlannerGroupScope.from_raw( @@ -2516,7 +2516,7 @@ def test_collected_lineage_outputs_use_relation_owned_group_scope(): ) maps = planner.artifacts.compile_plan_maps( - _snapshot( + _resolved_step( name="MeasureColocalization", group_by=GroupBy.SITE, variable_components=(VariableComponents.CHANNEL,), @@ -2590,7 +2590,7 @@ def test_output_lineage_uses_input_qualified_consumer_scope(): ) maps = planner.artifacts.compile_plan_maps( - _snapshot(name="Calculate"), + _resolved_step(name="Calculate"), 3, declarations, PathPlannerGroupScope.from_raw( @@ -2618,12 +2618,18 @@ def test_planner_derived_group_lineage_selects_exact_managed_invocation(): blue_measurements = ArtifactSpec.output( "Measurements", MeasurementsArtifactType, - relations=(GroupLineageSourceRelation(blue.ref()), ArtifactMeasurementSubjectRelation()), + relations=( + GroupLineageSourceRelation(blue.ref()), + ArtifactMeasurementSubjectRelation(), + ), ) green_measurements = ArtifactSpec.output( "Measurements", MeasurementsArtifactType, - relations=(GroupLineageSourceRelation(green.ref()), ArtifactMeasurementSubjectRelation()), + relations=( + GroupLineageSourceRelation(green.ref()), + ArtifactMeasurementSubjectRelation(), + ), ) @artifact_inputs(blue) @@ -2662,7 +2668,7 @@ def measure_green(image, *, runtime): ), ) planner = _artifact_planner_stub() - snapshot = _snapshot( + snapshot = _resolved_step( name="MeasureChannels", func=functions, source_bindings=source_bindings, @@ -2703,7 +2709,8 @@ def measure_green(image, *, runtime): channel: tuple( invocation.key.function_name for invocation in compiled.default_group.invocations - if invocation.output_plans_for_component(execution_scope, channel) is not None + if invocation.output_plans_for_component(execution_scope, channel) + is not None ) for channel in execution_scope.keys } == { @@ -2748,11 +2755,11 @@ def test_real_object_measurement_preserves_selected_labels_group_scope( if measurement_group == DEFAULT_GROUP_KEY else {measurement_group: [invocation_pattern]} ) - snapshot = _snapshot(name="MeasureCells", func=pattern) + snapshot = _resolved_step(name="MeasureCells", func=pattern) labels_input = ArtifactSpec.input("Cells", ObjectLabelsArtifactType) step_context = ArtifactDeclarationStepContext( - step_name=snapshot.step.name, - step_index=snapshot.index, + step_name=snapshot.name, + step_index=3, group_by=GroupBy.CHANNEL, available_artifacts=ArtifactSpecCollection((labels_input,)), available_artifact_producers=( @@ -2772,22 +2779,28 @@ def test_real_object_measurement_preserves_selected_labels_group_scope( (numbered_blocks,), _ = MeasureObjectSizeShapeModule.number_step_invocation_blocks( (blocks,), first_module_num=4 ) - contract, consumed_names = MeasureObjectSizeShapeModule.invocation_callable_contract( - invocation=authored, - numbered_module_blocks=numbered_blocks, - consumed_kwarg_names=consumed_names, - step_context=step_context, + contract, consumed_names = ( + MeasureObjectSizeShapeModule.invocation_callable_contract( + invocation=authored, + numbered_module_blocks=numbered_blocks, + consumed_kwarg_names=consumed_names, + step_context=step_context, + ) ) provider = CellProfilerInvocationContractProvider( - {(snapshot.index, authored.key): InvocationContractPlan(contract, consumed_names)} + {(3, authored.key): InvocationContractPlan(contract, consumed_names)} ) declarations = extract_artifact_declarations( pattern, invocation_contract_provider=provider, step_context=step_context, ) - (measurement,) = contract.artifact_outputs.of_artifact_type(MeasurementsArtifactType) - (object_input,) = contract.artifact_inputs.of_artifact_type(ObjectLabelsArtifactType) + (measurement,) = contract.artifact_outputs.of_artifact_type( + MeasurementsArtifactType + ) + (object_input,) = contract.artifact_inputs.of_artifact_type( + ObjectLabelsArtifactType + ) assert object_input.ref() == labels_input.ref() assert object_input.parameter_name == "labels" assert measurement.measurement_feature_owner is MeasureObjectSizeShapeModule @@ -2892,7 +2905,7 @@ def test_declared_group_lineage_cannot_rewrite_scalar_step_execution_scope(): ) maps = planner.artifacts.compile_plan_maps( - _snapshot(name="MaskImage"), + _resolved_step(name="MaskImage"), 3, declarations, PathPlannerGroupScope.from_raw(("1", "3"), component=AllComponents.CHANNEL), @@ -2981,7 +2994,7 @@ def test_artifact_output_storage_scope_is_independent_of_execution_scope(): ) maps = planner.artifacts.compile_plan_maps( - _snapshot(name="CalculateMath"), + _resolved_step(name="CalculateMath"), 3, declarations, PathPlannerGroupScope.from_raw(("3",), component=AllComponents.CHANNEL), @@ -3049,7 +3062,7 @@ def test_each_output_storage_scope_is_independent_of_execution_scope(): ) maps = planner.artifacts.compile_plan_maps( - _snapshot(name="invocation-scoped-output"), + _resolved_step(name="invocation-scoped-output"), 3, declarations, PathPlannerGroupScope.from_raw( @@ -3125,7 +3138,7 @@ def test_dict_pattern_output_groups_do_not_drive_scalar_scope_narrowing(): ) maps = planner.artifacts.compile_plan_maps( - _snapshot(name="dict_pattern"), + _resolved_step(name="dict_pattern"), 3, declarations, PathPlannerGroupScope.from_raw(("1", "3"), component=AllComponents.CHANNEL), @@ -3169,7 +3182,7 @@ def test_source_binding_component_identity_narrows_declared_output_lineage(): ) maps = planner.artifacts.compile_plan_maps( - _snapshot(name="Watershed", source_bindings=source_bindings), + _resolved_step(name="Watershed", source_bindings=source_bindings), 3, declarations, PathPlannerGroupScope.from_raw( @@ -3216,7 +3229,7 @@ def test_source_binding_identity_scopes_outputs_without_execution_fanout(): ) maps = planner.artifacts.compile_plan_maps( - _snapshot(name="Watershed", source_bindings=source_bindings), + _resolved_step(name="Watershed", source_bindings=source_bindings), 3, declarations, PathPlannerGroupScope.ungrouped(), @@ -3282,7 +3295,7 @@ def test_image_object_outputs_keep_declared_image_execution_group_scope(): ) maps = planner.artifacts.compile_plan_maps( - _snapshot(name="MeasureObjectIntensity"), + _resolved_step(name="MeasureObjectIntensity"), 3, declarations, PathPlannerGroupScope.from_raw( @@ -3335,7 +3348,7 @@ def test_group_lineage_source_resolves_prior_main_flow_output_without_store_inpu ) maps = planner.artifacts.compile_plan_maps( - _snapshot(name="FilterObjects"), + _resolved_step(name="FilterObjects"), 3, declarations, PathPlannerGroupScope.from_raw( @@ -3370,13 +3383,12 @@ def declared_artifact_owner(image): planner = _artifact_planner_stub() planner.declaration_provider = declarations_for_invocation - snapshot = _snapshot( + snapshot = _resolved_step( is_function_step=True, func=(identify, {"artifact_name": "cells"}), group_by=GroupBy.NONE, variable_components=(VariableComponents.SITE,), name="identify_cells", - index=2, source_bindings=EMPTY_SOURCE_BINDINGS, input_source=InputSource.PREVIOUS_STEP, ) @@ -3388,6 +3400,7 @@ def declared_artifact_owner(image): _contracts, ) = planner.artifacts.prepare_step_declarations( snapshot, + 2, ) assert execution_scope is FunctionStepExecutionScope.AXIS output_plan = ArtifactOutputPlan( @@ -3397,6 +3410,7 @@ def declared_artifact_owner(image): ) compiled = planner.artifacts.build_step_compiled_function_pattern( snapshot, + 2, True, func_pattern, {}, @@ -3427,13 +3441,12 @@ def filter_objects(image, *, runtime): return image planner = _artifact_planner_stub() - snapshot = _snapshot( + snapshot = _resolved_step( is_function_step=True, func=filter_objects, group_by=GroupBy.CHANNEL, variable_components=(VariableComponents.SITE,), name="FilterObjects", - index=2, source_bindings=EMPTY_SOURCE_BINDINGS, input_source=InputSource.PREVIOUS_STEP, ) @@ -3449,6 +3462,7 @@ def filter_objects(image, *, runtime): _declarations, _pattern, execution_scope, _contracts = ( planner.artifacts.prepare_step_declarations( snapshot, + 2, ) ) execution_groups = planner.execution_groups.get_execution_groups( @@ -3462,13 +3476,14 @@ def filter_objects(image, *, runtime): ) assert execution_scope is FunctionStepExecutionScope.AXIS - snapshot.step.func = { + snapshot.func = { "1": [filter_objects], "2": [filter_objects], } _declarations, _pattern, execution_scope, _contracts = ( planner.artifacts.prepare_step_declarations( snapshot, + 2, ) ) execution_groups = planner.execution_groups.get_execution_groups( @@ -3566,13 +3581,12 @@ def identify_primary_objects(image, *, runtime): ), ), ) - snapshot = _snapshot( + snapshot = _resolved_step( is_function_step=True, func=identify_primary_objects, group_by=GroupBy.CHANNEL, variable_components=(VariableComponents.SITE,), name="IdentifyPrimaryObjects", - index=2, source_bindings=EMPTY_SOURCE_BINDINGS, input_source=InputSource.PREVIOUS_STEP, ) @@ -3623,13 +3637,12 @@ def relate_objects(image, *, runtime): group_component=AllComponents.CHANNEL, ), ) - snapshot = _snapshot( + snapshot = _resolved_step( is_function_step=True, func=relate_objects, group_by=GroupBy.CHANNEL, variable_components=(VariableComponents.SITE,), name="RelateObjects", - index=2, source_bindings=EMPTY_SOURCE_BINDINGS, input_source=InputSource.PREVIOUS_STEP, ) @@ -3678,13 +3691,12 @@ def measure_object_size_shape(image, *, runtime): group_component=AllComponents.SITE, ), ) - snapshot = _snapshot( + snapshot = _resolved_step( is_function_step=True, func=measure_object_size_shape, group_by=GroupBy.CHANNEL, variable_components=(VariableComponents.SITE,), name="MeasureObjectSizeShape", - index=2, source_bindings=EMPTY_SOURCE_BINDINGS, input_source=InputSource.PREVIOUS_STEP, ) @@ -3711,7 +3723,7 @@ def measure_object_size_shape(image, *, runtime): def test_execution_groups_resolve_non_grouped_variable_component_conflicts(): planner = _artifact_planner_stub() - snapshot = _snapshot( + snapshot = _resolved_step( is_function_step=True, func=lambda image: image, group_by=GroupBy.CHANNEL, @@ -3733,7 +3745,7 @@ def test_non_dict_group_by_declares_dynamic_scope_without_plate_key_lookup(): "non-dict group_by must not request plate component keys" ) ) - source_snapshot = _snapshot( + source_snapshot = _resolved_step( is_function_step=True, func=lambda image: image, group_by=GroupBy.CHANNEL, @@ -3755,7 +3767,7 @@ def test_non_dict_group_by_declares_dynamic_scope_without_plate_key_lookup(): def test_non_dict_group_by_uses_dynamic_source_scope_for_pipeline_start(): planner = _artifact_planner_stub() - source_snapshot = _snapshot( + source_snapshot = _resolved_step( is_function_step=True, func=lambda image: image, group_by=GroupBy.CHANNEL, @@ -3777,7 +3789,7 @@ def test_non_dict_group_by_uses_dynamic_source_scope_for_pipeline_start(): def test_dict_pattern_group_by_declares_execution_group_component(): planner = _artifact_planner_stub() - snapshot = _snapshot( + snapshot = _resolved_step( is_function_step=True, func={ "1": lambda image: image, @@ -3802,7 +3814,7 @@ def test_dict_pattern_group_by_declares_execution_group_component(): def test_dict_pattern_rejects_group_by_none_execution_component(): planner = _artifact_planner_stub() - snapshot = _snapshot( + snapshot = _resolved_step( is_function_step=True, func={ "1": lambda image: image, @@ -3827,7 +3839,7 @@ def test_dict_pattern_rejects_group_by_none_execution_component(): def test_execution_groups_reject_grouped_group_by_axis_conflict(): planner = _artifact_planner_stub() - composite_snapshot = _snapshot( + composite_snapshot = _resolved_step( is_function_step=True, func={"1": lambda image: image}, group_by=GroupBy.CHANNEL, @@ -3856,7 +3868,7 @@ def test_non_dict_group_by_preserves_explicitly_collapsed_input_axis(): ), } ) - snapshot = _snapshot( + snapshot = _resolved_step( is_function_step=True, func=lambda image: image, group_by=GroupBy.CHANNEL, @@ -3912,7 +3924,7 @@ def measurement_only(image, *, runtime): VariableComponents.SITE: PathPlannerGroupScope.ungrouped(), } ) - snapshot = _snapshot( + snapshot = _resolved_step( is_function_step=True, variable_components=(VariableComponents.CHANNEL,), group_by=GroupBy.SITE, @@ -3963,7 +3975,7 @@ def image_output(image): VariableComponents.SITE: PathPlannerGroupScope.ungrouped(), } ) - snapshot = _snapshot( + snapshot = _resolved_step( is_function_step=True, variable_components=(VariableComponents.CHANNEL,), group_by=GroupBy.SITE, @@ -3997,7 +4009,7 @@ def test_non_dict_group_by_namespaces_artifact_outputs_with_dynamic_component(): ), ) ) - snapshot = _snapshot( + snapshot = _resolved_step( is_function_step=True, func=lambda image: image, group_by=GroupBy.CHANNEL, @@ -4026,7 +4038,7 @@ def test_non_dict_group_by_namespaces_artifact_outputs_with_dynamic_component(): def test_non_dict_group_by_uses_source_binding_identity_for_pipeline_start_scope(): planner = _artifact_planner_stub() - snapshot = _snapshot( + snapshot = _resolved_step( is_function_step=True, func=lambda image: image, group_by=GroupBy.CHANNEL, @@ -4099,12 +4111,14 @@ def save_declared_payload(image): component_identity=(ComponentSelector(AllComponents.CHANNEL, "3"),), ) ) - snapshot = _snapshot( + snapshot = _resolved_step( is_function_step=True, func=save_declared_payload, group_by=GroupBy.CHANNEL, variable_components=(VariableComponents.SITE,), - source_bindings=StepSourceBindingsConfig(enabled=True, bindings=tuple(bindings)), + source_bindings=StepSourceBindingsConfig( + enabled=True, bindings=tuple(bindings) + ), input_source=InputSource.PREVIOUS_STEP, ) @@ -4139,7 +4153,7 @@ def test_main_flow_source_anchor_restricts_execution_to_its_exact_channel(): ), ), ) - snapshot = _snapshot( + snapshot = _resolved_step( is_function_step=True, func=lambda image: image, group_by=GroupBy.CHANNEL, @@ -4226,7 +4240,7 @@ def measure(image, CropBlue): producer_step_name="Crop", ), ) - snapshot = _snapshot( + snapshot = _resolved_step( name="Measure", func=measure, group_by=GroupBy.SITE, @@ -4246,6 +4260,7 @@ def measure(image, CropBlue): ) compiled = planner.artifacts.build_step_compiled_function_pattern( snapshot, + 3, True, measure, maps.inputs, @@ -4302,9 +4317,8 @@ def test_execution_anchor_ignores_source_artifact_lineage(): ), ), ) - snapshot = _snapshot( - source_bindings=source_bindings, - input_source=InputSource.PIPELINE_START, + snapshot = _resolved_step( + source_bindings=source_bindings, input_source=InputSource.PIPELINE_START ) source_contract = CallableContract.from_callable(lambda image: image) source_contract = replace( @@ -4554,7 +4568,7 @@ def test_artifact_graph_output_groups_validates_exact_partial_map() -> None: def test_non_dict_group_by_ignores_source_binding_identity_for_other_components(): planner = _artifact_planner_stub() - snapshot = _snapshot( + snapshot = _resolved_step( is_function_step=True, func=lambda image: image, group_by=GroupBy.SITE, @@ -4593,13 +4607,12 @@ def test_compiled_group_by_preserves_dynamic_execution_scope(): planner.plans[3].group_by = GroupBy.CHANNEL planner.plans[3].variable_components = (VariableComponents.SITE,) planner.plans[3].func = lambda image: image - snapshot = _snapshot( + snapshot = _resolved_step( is_function_step=True, func=lambda image: image, group_by=GroupBy.CHANNEL, variable_components=(VariableComponents.SITE,), name="measure_after_channel_collapse", - scope_id="plate::functionstep_3", input_source=InputSource.PREVIOUS_STEP, ) artifact_maps = ArtifactPlanMaps( @@ -4899,7 +4912,7 @@ def consume(main_image, image): ) ) - snapshot = _snapshot( + snapshot = _resolved_step( name="consumer", func=consume, group_by=GroupBy.NONE, @@ -4915,6 +4928,7 @@ def consume(main_image, image): with pytest.raises(ValueError, match="no exact relation-owned selection"): planner.artifacts.build_step_compiled_function_pattern( snapshot, + 3, True, consume, maps.inputs, @@ -4957,7 +4971,7 @@ def consume(main_image, image): ) ) - snapshot = _snapshot( + snapshot = _resolved_step( name="consumer", func=consume, group_by=GroupBy.NONE, @@ -4975,6 +4989,7 @@ def consume(main_image, image): assert producer_scope.component is AllComponents.CHANNEL compiled = planner.artifacts.build_step_compiled_function_pattern( snapshot, + 3, True, consume, maps.inputs, @@ -5075,8 +5090,7 @@ def produce(image, source_value): enabled=True, bindings=(NamedSourceBinding(alias=alias),), ) - snapshot = _snapshot( - index=step_index, + snapshot = _resolved_step( name=f"produce_{output_name}", func=produce, source_bindings=source_bindings, @@ -5137,7 +5151,7 @@ def consume(image, Nuclei, PH3): del Nuclei, PH3 return image - snapshot = _snapshot(index=4, name="consume", func=consume) + snapshot = _resolved_step(name="consume", func=consume) declarations = planner.artifacts.namespace_grouped_outputs_for_runtime_consumers( consume, extract_artifact_declarations(consume), @@ -5735,8 +5749,8 @@ def test_main_input_dependency_uses_scope_identity_for_step_output_edges(): ), } snapshots_by_index = { - 0: _snapshot(scope_id="plate::functionstep_0"), - 1: _snapshot(scope_id="plate::functionstep_1"), + 0: _resolved_step(), + 1: _resolved_step(), } planner.session = SimpleNamespace( snapshot=lambda index: snapshots_by_index[index], @@ -5744,7 +5758,7 @@ def test_main_input_dependency_uses_scope_identity_for_step_output_edges(): planner.steps = PathPlannerStepAssemblyStage(planner) dependency = planner.steps.main_input_dependency( - _snapshot(is_function_step=False), + _resolved_step(is_function_step=False), 1, ) @@ -5796,7 +5810,7 @@ def test_main_input_dependency_uses_declared_artifact_producer_not_previous_step ) dependency = planner.steps.main_input_dependency( - _snapshot( + _resolved_step( input_source=InputSource.PREVIOUS_STEP, is_function_step=True, name="Identify", @@ -5877,12 +5891,12 @@ def measure(image, *, runtime): ), } planner.session = SimpleNamespace( - snapshot=lambda index: _snapshot(scope_id=f"plate::functionstep_{index}"), + snapshot=lambda index: _resolved_step(), ) planner.steps = PathPlannerStepAssemblyStage(planner) dependency = planner.steps.main_input_dependency( - _snapshot(is_function_step=False), + _resolved_step(is_function_step=False), 2, ) @@ -5902,7 +5916,7 @@ def test_main_input_dependency_preserves_pipeline_start_edges(): } planner.initial_input = Path("/data/plate1/images") planner.session = SimpleNamespace( - snapshot=lambda index: {1: _snapshot(scope_id="plate::functionstep_1")}[index], + snapshot=lambda index: {1: _resolved_step()}[index], ) planner.paths = SimpleNamespace( build_output_path=lambda *_args, **_kwargs: Path( @@ -5912,10 +5926,7 @@ def test_main_input_dependency_preserves_pipeline_start_edges(): planner.steps = PathPlannerStepAssemblyStage(planner) dependency = planner.steps.main_input_dependency( - _snapshot( - input_source=InputSource.PIPELINE_START, - is_function_step=False, - ), + _resolved_step(input_source=InputSource.PIPELINE_START, is_function_step=False), 1, ) diff --git a/tests/unit/test_persisted_image_metadata.py b/tests/unit/test_persisted_image_metadata.py index 7df244dfc0..07a1ca4606 100644 --- a/tests/unit/test_persisted_image_metadata.py +++ b/tests/unit/test_persisted_image_metadata.py @@ -33,7 +33,13 @@ SourceProjectionMetadataSerializer, ) from openhcs.core.source_spatial_domain import SourceSpatialDomain -from openhcs.core.virtual_workspace_metadata import FIELDS, AtomicMetadataWriter +from openhcs.core.virtual_workspace_metadata import ( + FIELDS, + AtomicMetadataWriter, + MetadataWriteError, + VirtualWorkspaceSourceProjectionEntries, +) +from openhcs.microscopes.source_schema import SourceSchemaFilenameParser from openhcs.serialization.json import to_jsonable @@ -167,17 +173,9 @@ def merge(well): writer.merge_source_projection_metadata( path, ".", - { - FIELDS.WORKSPACE_MAPPING: { - virtual_path: {"backend": "disk", "backend_address": virtual_path} - }, - FIELDS.SOURCE_METADATA: {virtual_path: {"well": well}}, - FIELDS.SOURCE_PROJECTION: [ - SourceProjectionMetadataSerializer(None)._source_projection_payload( - projection, virtual_path - ) - ], - }, + VirtualWorkspaceSourceProjectionEntries.from_projection_paths( + ((projection, virtual_path),) + ), ) with ThreadPoolExecutor(max_workers=4) as pool: @@ -189,6 +187,288 @@ def merge(well): assert len(subdir[FIELDS.SOURCE_METADATA]) == 4 +def calibrated_projection(well, path, pixel_size): + spacing = SourceVoxelSpacing((pixel_size, pixel_size)) + source_metadata = {} + spacing.merge_into(source_metadata, path=path) + return SourcePlaneProjection( + OpenHCSPlaneAddress.from_values(well, 1, 1, 1, 1), + SourcePixelRef("disk", path), + source_metadata=source_metadata, + image_metadata=metadata_fixture().replace_fields(source_voxel_spacing=spacing), + ) + + +def publish_projection_inventory(writer, path, projection_metadata, saved_paths): + writer.publish_source_projection_metadata( + path, + "images", + projection_metadata, + serializer=SourceProjectionMetadataSerializer(SourceSchemaFilenameParser()), + saved_image_paths=saved_paths, + microscope_handler_name="VirtualWorkspaceMicroscopeHandler", + source_filename_parser_name="SourceSchemaFilenameParser", + component_labels={}, + backend="disk", + is_main=True, + results_dir=None, + ) + + +@pytest.mark.parametrize( + "merge_method", ("merge_subdirectory_metadata", "merge_source_projection_metadata") +) +def test_atomic_projection_merge_refreshes_geometry_from_current_document( + tmp_path, merge_method +): + path = tmp_path / "openhcs_metadata.json" + writer = AtomicMetadataWriter() + serializer = SourceProjectionMetadataSerializer(SourceSchemaFilenameParser()) + first = calibrated_projection("A01", "images/first.tif", 0.5) + second = calibrated_projection("A02", "images/second.tif", 2.0) + first_fields = serializer.projection_fields(((first, "images/first.tif"),)) + writer.replace_subdirectory_metadata(path, "images", first_fields) + second_fields = serializer.projection_fields(((second, "images/second.tif"),)) + if merge_method == "merge_subdirectory_metadata": + # This API replaces the projection field with the authoritative new list. + writer.merge_subdirectory_metadata(path, {"images": second_fields}) + expected_pixel_size = 2.0 + else: + writer.merge_source_projection_metadata( + path, "images", + VirtualWorkspaceSourceProjectionEntries.from_projection_paths( + ((second, "images/second.tif"),) + ), + ) + expected_pixel_size = 1.0 # Conflicting calibration has no physical scalar. + subdir = json.loads(path.read_text())[FIELDS.SUBDIRECTORIES]["images"] + assert subdir[FIELDS.PIXEL_SIZE] == expected_pixel_size + + +def test_final_publication_prunes_geometry_and_preserves_other_directories(tmp_path): + path = tmp_path / "openhcs_metadata.json" + writer = AtomicMetadataWriter() + serializer = SourceProjectionMetadataSerializer(SourceSchemaFilenameParser()) + retained = calibrated_projection("A01", "images/retained.tif", 0.5) + deleted = calibrated_projection("A02", "images/deleted.tif", 2.0) + elsewhere = calibrated_projection("A03", "other/retained.tif", 0.5) + projection_paths = ( + (retained, "images/retained.tif"), + (deleted, "images/deleted.tif"), + (elsewhere, "other/retained.tif"), + ) + writer.merge_source_projection_metadata( + path, "images", + VirtualWorkspaceSourceProjectionEntries.from_projection_paths(projection_paths) + ) + before = json.loads(path.read_text())[FIELDS.SUBDIRECTORIES]["images"] + assert before[FIELDS.PIXEL_SIZE] == 1.0 + publish_projection_inventory(writer, path, None, ("images/retained.tif",)) + subdir = json.loads(path.read_text())[FIELDS.SUBDIRECTORIES]["images"] + assert subdir[FIELDS.PIXEL_SIZE] == 0.5 + assert subdir[FIELDS.IMAGE_FILES] == ["images/retained.tif"] + entries = VirtualWorkspaceSourceProjectionEntries.from_subdirectory(subdir).entries + assert set(entries) == {"images/retained.tif", "other/retained.tif"} + assert entries["images/retained.tif"].image_metadata == retained.image_metadata + assert entries["other/retained.tif"].image_metadata == elsewhere.image_metadata + # A failed final inventory cannot publish fields or prune existing records. + before_bytes = path.read_bytes() + with pytest.raises(MetadataWriteError, match="lack typed produced addresses"): + publish_projection_inventory(writer, path, None, ("images/unowned.tif",)) + assert path.read_bytes() == before_bytes + + +def test_concurrent_step_publication_retains_records_outside_partial_inventory( + tmp_path, +): + path = tmp_path / "openhcs_metadata.json" + writer = AtomicMetadataWriter() + serializer = SourceProjectionMetadataSerializer(SourceSchemaFilenameParser()) + paths = tuple(f"images/{well}.tif" for well in ("A01", "A02", "A03", "A04")) + + def publish(item): + index, image_path = item + projection = calibrated_projection(f"A0{index + 1}", image_path, 0.5) + publish_projection_inventory( + writer, + path, + VirtualWorkspaceSourceProjectionEntries.from_projection_paths( + ((projection, image_path),) + ), + (image_path,), + ) + + with ThreadPoolExecutor(max_workers=4) as pool: + list(pool.map(publish, enumerate(paths))) + subdir = json.loads(path.read_text())[FIELDS.SUBDIRECTORIES]["images"] + assert set(subdir[FIELDS.WORKSPACE_MAPPING]) == set(paths) + assert len(subdir[FIELDS.IMAGE_FILES]) == 1 # Most recent partial step inventory. + assert subdir[FIELDS.PIXEL_SIZE] == 0.5 + publish_projection_inventory(writer, path, None, paths) + subdir = json.loads(path.read_text())[FIELDS.SUBDIRECTORIES]["images"] + assert subdir[FIELDS.IMAGE_FILES] == list(paths) + assert len(subdir[FIELDS.SOURCE_PROJECTION]) == len(paths) + assert subdir["wells"] == {f"A0{index + 1}": None for index in range(4)} + + +@pytest.mark.parametrize("publish", (False, True)) +def test_typed_projection_update_admits_only_retained_wire_records( + tmp_path, monkeypatch, publish +): + path = tmp_path / "openhcs_metadata.json" + writer = AtomicMetadataWriter() + retained = calibrated_projection("A01", "images/retained.tif", 0.5) + replacement = calibrated_projection("A02", "images/replaced.tif", 0.5) + serializer = SourceProjectionMetadataSerializer(SourceSchemaFilenameParser()) + fields = serializer.projection_fields(((retained, "images/retained.tif"),)) + fields[FIELDS.SOURCE_PROJECTION].append( + {"virtual_path": "images/replaced.tif", "projection_role": "broken"} + ) + writer.replace_subdirectory_metadata(path, "images", fields) + updates = VirtualWorkspaceSourceProjectionEntries.from_projection_paths( + ((replacement, "images/replaced.tif"),) + ) + admitted_paths = [] + serialized_paths = [] + decode = VirtualWorkspaceSourceProjectionEntries._projection_record + encode = SourceProjectionMetadataSerializer._source_projection_payload + + def record(cls, wire): + admitted_paths.append(wire["virtual_path"]) + return decode(wire) + + def payload(cls, projection, virtual_path): + serialized_paths.append(virtual_path) + return encode(projection, virtual_path) + + monkeypatch.setattr( + VirtualWorkspaceSourceProjectionEntries, + "_projection_record", + classmethod(record), + ) + monkeypatch.setattr( + SourceProjectionMetadataSerializer, + "_source_projection_payload", + classmethod(payload), + ) + merged = updates.merged_with_subdirectory(fields) + assert merged.entries["images/replaced.tif"] is replacement + assert tuple(merged.entries) == ("images/retained.tif", "images/replaced.tif") + admitted_paths.clear() + if publish: + publish_projection_inventory( + writer, path, updates, ("images/retained.tif", "images/replaced.tif") + ) + else: + writer.merge_source_projection_metadata(path, "images", updates) + assert admitted_paths == ["images/retained.tif"] + assert serialized_paths == ["images/replaced.tif"] + subdir = json.loads(path.read_text())[FIELDS.SUBDIRECTORIES]["images"] + restored = VirtualWorkspaceSourceProjectionEntries.from_subdirectory(subdir) + assert ( + restored.entries["images/replaced.tif"].image_metadata + == replacement.image_metadata + ) + + +@pytest.mark.parametrize("publish", (False, True)) +def test_invalid_unreplaced_projection_aborts_typed_transaction(tmp_path, publish): + path = tmp_path / "openhcs_metadata.json" + writer = AtomicMetadataWriter() + writer.replace_subdirectory_metadata( + path, "images", + {FIELDS.SOURCE_PROJECTION: [{"virtual_path": "images/broken.tif"}]}, + ) + replacement = calibrated_projection("A02", "images/new.tif", 0.5) + updates = VirtualWorkspaceSourceProjectionEntries.from_projection_paths( + ((replacement, "images/new.tif"),) + ) + before = path.read_bytes() + with pytest.raises(MetadataWriteError, match="projection_role"): + if publish: + publish_projection_inventory(writer, path, updates, ("images/new.tif",)) + else: + writer.merge_source_projection_metadata(path, "images", updates) + assert path.read_bytes() == before + + +@pytest.mark.parametrize("publish", (False, True)) +def test_typed_transaction_retains_wire_fields_and_derives_workspace_views( + tmp_path, publish +): + path = tmp_path / "openhcs_metadata.json" + writer = AtomicMetadataWriter() + original = calibrated_projection("A01", "images/original.tif", 0.5) + fields = SourceProjectionMetadataSerializer.projection_fields( + ((original, "images/original.tif"),) + ) + fields[FIELDS.SOURCE_PROJECTION][0]["external_annotation"] = {"version": 7} + fields[FIELDS.SOURCE_METADATA]["images/original.tif"] = { + "manual_override": "obsolete" + } + fields[FIELDS.WORKSPACE_MAPPING]["legacy.tif"] = {"opaque": "mapping"} + fields[FIELDS.SOURCE_METADATA]["legacy.tif"] = {"opaque": "metadata"} + writer.replace_subdirectory_metadata(path, "images", fields) + new = calibrated_projection("A02", "images/new.tif", 0.5) + updates = VirtualWorkspaceSourceProjectionEntries.from_projection_paths( + ((new, "images/new.tif"),) + ) + if publish: + publish_projection_inventory( + writer, path, updates, ("images/original.tif", "images/new.tif") + ) + else: + writer.merge_source_projection_metadata(path, "images", updates) + subdir = json.loads(path.read_text())[FIELDS.SUBDIRECTORIES]["images"] + assert subdir[FIELDS.SOURCE_PROJECTION][0]["external_annotation"] == {"version": 7} + if publish: + assert "legacy.tif" not in subdir[FIELDS.WORKSPACE_MAPPING] + assert "legacy.tif" not in subdir[FIELDS.SOURCE_METADATA] + assert subdir[FIELDS.SOURCE_METADATA]["images/original.tif"]["well"] == "A01" + assert "manual_override" not in subdir[FIELDS.SOURCE_METADATA][ + "images/original.tif" + ] + assert "well" not in subdir[FIELDS.SOURCE_PROJECTION][0]["source_metadata"] + publish_projection_inventory( + writer, path, None, ("images/original.tif", "images/new.tif") + ) + reconciled = json.loads(path.read_text())[FIELDS.SUBDIRECTORIES]["images"] + assert reconciled[FIELDS.SOURCE_PROJECTION][0]["external_annotation"] == { + "version": 7 + } + else: + assert subdir[FIELDS.WORKSPACE_MAPPING]["legacy.tif"] == {"opaque": "mapping"} + assert subdir[FIELDS.SOURCE_METADATA]["legacy.tif"] == {"opaque": "metadata"} + assert subdir[FIELDS.SOURCE_METADATA]["images/original.tif"] == { + "manual_override": "obsolete" + } + + +def test_typed_transaction_normalizes_legacy_paths_and_rejects_collisions(): + original = calibrated_projection("A01", "7", 0.5) + fields = SourceProjectionMetadataSerializer.projection_fields(((original, "7"),)) + fields[FIELDS.SOURCE_PROJECTION][0]["virtual_path"] = 7 + updates = VirtualWorkspaceSourceProjectionEntries.from_projection_paths( + ((calibrated_projection("A02", "new.tif", 0.5), "new.tif"),) + ) + assert tuple(updates.merged_with_subdirectory(fields).entries) == ("7", "new.tif") + colliding = VirtualWorkspaceSourceProjectionEntries.from_projection_paths( + ((calibrated_projection("A02", "7", 0.5), "7"),) + ) + with pytest.raises(RuntimeError, match="duplicate path '7'"): + colliding.merged_with_subdirectory(fields) + + +@pytest.mark.parametrize("field", (FIELDS.WORKSPACE_MAPPING, FIELDS.SOURCE_METADATA)) +def test_typed_transaction_preserves_durable_mapping_validation(field): + projection = calibrated_projection("A01", "images/current.tif", 0.5) + updates = VirtualWorkspaceSourceProjectionEntries.from_projection_paths( + ((projection, "images/current.tif"),) + ) + with pytest.raises(TypeError, match="must be a mapping"): + updates.merged_with_subdirectory({field: None}) + + def test_metadata_codec_rejects_unknown_declarations(): with pytest.raises(ValueError, match="undeclared"): ImagePayloadMetadata.from_mapping({"imagined_tile_axis": 9}) @@ -226,11 +506,11 @@ def test_native_header_reload_preserves_declared_crop_and_alias(tmp_path, origin context = ImagePayloadSourceMetadataContext(SourceImageIdentity(str(path), {})) from openhcs.core.runtime_image_values import image_payload_metadata from openhcs.core.source_bindings import NamedSourceBinding - from openhcs.core.source_image_semantics import apply_source_binding_payload current = image_payload_metadata( - apply_source_binding_payload( - reloaded, NamedSourceBinding(alias="neurite"), context + NamedSourceBinding(alias="neurite").apply_loaded_payload( + reloaded, + context, ) ) assert current.source_dtype == "float32" @@ -248,7 +528,6 @@ def test_native_mosaic_replaces_incompatible_old_tile_domain_without_losing_sour ): from openhcs.core.runtime_image_values import image_payload_metadata from openhcs.core.source_bindings import NamedSourceBinding - from openhcs.core.source_image_semantics import apply_source_binding_payload metadata = metadata_fixture().replace_fields( source_spatial_domain=SourceSpatialDomain((0, 0), (4, 6)) @@ -261,9 +540,8 @@ def test_native_mosaic_replaces_incompatible_old_tile_domain_without_losing_sour image_format.read(path), image_format.persisted_metadata(path, payload) ) current = image_payload_metadata( - apply_source_binding_payload( + NamedSourceBinding(alias="neurite").apply_loaded_payload( reloaded, - NamedSourceBinding(alias="neurite"), ImagePayloadSourceMetadataContext(SourceImageIdentity(str(path), {})), ) ) @@ -361,7 +639,6 @@ def test_native_headerless_hwc_replay_retains_declared_channel_semantics( from openhcs.core.runtime_image_values import image_payload_metadata from openhcs.core.source_bindings import NamedSourceBinding - from openhcs.core.source_image_semantics import apply_source_binding_payload pixels = np.arange(60, dtype=np.uint8).reshape(4, 5, 3) metadata = metadata_fixture().replace_fields( @@ -397,9 +674,8 @@ def test_native_headerless_hwc_replay_retains_declared_channel_semantics( json.loads(json.dumps(to_jsonable(restored))) ) assert restored.source_channel_axis == -1 - bound = apply_source_binding_payload( + bound = NamedSourceBinding(alias="neurite").apply_loaded_payload( ImageMetadataPayload(loaded, restored), - NamedSourceBinding(alias="neurite"), context, ) current = image_payload_metadata(bound) diff --git a/tests/unit/test_persisted_roi_only_publication.py b/tests/unit/test_persisted_roi_only_publication.py new file mode 100644 index 0000000000..4ec049524a --- /dev/null +++ b/tests/unit/test_persisted_roi_only_publication.py @@ -0,0 +1,392 @@ +"""Saved-output publication only: synthetic bytes, no ROI or pixel decoding.""" + +from dataclasses import replace +from types import SimpleNamespace + +from polystore.disk import DiskStorageBackend +from polystore.filemanager import FileManager +from openhcs.core.context.processing_context import ProcessingContext +from openhcs.microscopes.source_schema import SourceSchemaFilenameParser +import json + +import pytest + +from openhcs.agent.dto.plate import PlateFileQueryRequest +from openhcs.agent.path_policy import AgentPathPolicy +from openhcs.agent.services.plate_inspection_service import ( + PlateInspectionFileManagerFactory, + PlateInspectionService, +) +from openhcs.constants.constants import Backend +from openhcs.core.artifacts import ArtifactOutputPlan, MetadataArtifactType +from openhcs.core.compiled_step_plan import ( + CompiledStepPlan, + RuntimeArtifactMaterializationPlan, +) +from openhcs.core.component_group_scope import RuntimeExecutionAxisScope +from openhcs.core.runtime_artifact_values import RuntimeValue +from openhcs.core.runtime_stores import RuntimeArtifactLocation, StoredRuntimeValue +from openhcs.core.steps.function_artifact_materialization import ( + MaterializedRuntimeArtifact, + RuntimeArtifactMaterialization, +) +from openhcs.core.steps.function_outputs import ( + OpenHCSMetadataWriter, + ProducedImageMetadataCapability, + RuntimeArtifactMetadataTarget, +) +from openhcs.core.virtual_workspace_metadata import METADATA_CONFIG, MetadataWriteError +from openhcs.processing.materialization.core import ( + MaterializationSpec, + _WRITERS_BY_OPTIONS, + prepare_materialization, +) +from openhcs.processing.materialization.options import FileBundleOptions + + +@pytest.fixture +def publication_context(tmp_path): + filemanager = FileManager({Backend.DISK.value: DiskStorageBackend()}) + context = ProcessingContext(filemanager=filemanager) + context.metadata_cache = {} + context.microscope_handler = SimpleNamespace( + parser=SourceSchemaFilenameParser(), microscope_type="openhcsdata" + ) + context.publication_audit = [] + return context + + +class PublicationAuditCapability: + """Independent audit capability extends, rather than replaces, publication.""" + + def write(self, context, *, produced_plan=None): + context.publication_audit.append(("before", self.sub_dir)) + super().write(context, produced_plan=produced_plan) + context.publication_audit.append(("after", self.sub_dir)) + + +def plan_for(plate): + return CompiledStepPlan( + step_index=0, + step_name="synthetic saved result", + step_type="FunctionStep", + axis_id="A01", + write_backend=Backend.MEMORY.value, + create_openhcs_metadata=True, + output_plate_root=str(plate), + analysis_results_dir=str(plate / "compiled_default"), + runtime_artifact_materialization=RuntimeArtifactMaterializationPlan( + persistent_enabled=True, + persistent_backend=Backend.DISK.value, + ), + ) + + +def save_archive_outcome(context, plate, destination, monkeypatch): + """Use the original declared bundle writer, batch and disk save boundary.""" + spec = MaterializationSpec(FileBundleOptions()) + payload = { + f"{destination}/independent-outline.roi.zip": b"synthetic admission only" + } + base_path = plate / "bundle" + batch = prepare_materialization( + spec, + payload, + str(base_path), + context.filemanager, + (Backend.DISK.value,), + ) + saved = batch.save() + (output,) = saved.outputs_for_backend(Backend.DISK.value) + assert output is batch.outputs[0] + # Source qualification must consume the original successful save, not render + # a mutable logical payload again or use planned names as proof of a save. + payload.clear() + + def forbidden_render(*args, **kwargs): + pytest.fail("Publication rendered the already-saved batch again") + + writer = _WRITERS_BY_OPTIONS[FileBundleOptions] + monkeypatch.setitem( + _WRITERS_BY_OPTIONS, FileBundleOptions, replace(writer, write=forbidden_render) + ) + artifact_plan = ArtifactOutputPlan( + name="synthetic archive bundle", + path="/memory/bundle.pkl", + artifact_type=MetadataArtifactType, + materialization=spec, + ) + value = RuntimeValue.from_output_plan( + artifact_plan, + {}, + execution_scope=RuntimeExecutionAxisScope(axis_id="A01"), + ) + record = StoredRuntimeValue( + key=value.key, + data=value.data, + materialization_source_metadata=value.materialization_source_metadata, + location=RuntimeArtifactLocation( + path=artifact_plan.path, backend=Backend.MEMORY.value + ), + ) + materialization = RuntimeArtifactMaterialization( + output_plan=artifact_plan, + spec=spec, + record=record, + data=payload, + base_path=base_path, + source_identity=None, + filename_source_identity=None, + ) + return ( + MaterializedRuntimeArtifact( + outputs_by_backend=saved.outputs_by_backend, + materialization=materialization, + ), + output, + ) + + +class ExistingDiskInspectionFactory(PlateInspectionFileManagerFactory): + """Original public service receives the same real disk manager as saving.""" + + def __init__(self, manager): + self.manager = manager + + def create(self): + return self.manager + + +@pytest.fixture(autouse=True) +def forbid_optional_backend_bootstrap(monkeypatch): + import polystore.base + + def forbidden_bootstrap(*args, **kwargs): + pytest.fail("Source-only qualification must not bootstrap optional backends") + + monkeypatch.setattr(polystore.base, "ensure_storage_registry", forbidden_bootstrap) + + +def result_paths(plate, context): + service = PlateInspectionService( + AgentPathPolicy.with_roots(readable_roots=(plate,), writable_roots=()), + filemanager_factory=ExistingDiskInspectionFactory(context.filemanager), + ) + result = service.query_files( + PlateFileQueryRequest.from_fields( + plate_path=str(plate), + microscope_type="openhcsdata", + kind="result", + include_previews=False, + ) + ) + assert result.errors == () + assert all(record.preview is None for record in result.records) + return tuple(record.full_path for record in result.records) + + +@pytest.mark.parametrize("destination", ("roi_only", "independent/nested/roi_only")) +def test_saved_roi_only_batch_publishes_and_reconciles_without_rendering( + tmp_path, + publication_context, + monkeypatch, + destination, +): + plate = tmp_path / "plate" + outcome, output = save_archive_outcome( + publication_context, plate, destination, monkeypatch + ) + plan = plan_for(plate) + targets = OpenHCSMetadataWriter.OutputTarget.for_execution( + publication_context, + plan, + artifact_materializations=(outcome,), + ) + assert tuple(target.output_dir for target in targets) == (plate / destination,) + OpenHCSMetadataWriter.write( + publication_context, plan, artifact_materializations=(outcome,) + ) + assert result_paths(plate, publication_context) == (output.path,) + published = json.loads(METADATA_CONFIG.metadata_path(plate).read_text()) + assert published["subdirectories"][destination]["image_files"] == [] + assert published["subdirectories"][destination]["source_projection"] == [] + # Final reconciliation has no runtime outcome/value to reconstruct. Its + # destination comes from the same durable declaration the reader admitted. + publication_context.step_plans = {0: plan} + owner = RuntimeArtifactMetadataTarget.from_plan(plan) + reconciled = tuple( + target.output_dir + for target in owner.reconciliation_targets(publication_context) + ) + assert plate / destination in reconciled + OpenHCSMetadataWriter.finalize_completed_plate({"A01": publication_context}) + assert result_paths(plate, publication_context) == (output.path,) + + +def test_shared_writer_accepts_result_only_but_not_unaddressed_images( + tmp_path, + publication_context, +): + plate = tmp_path / "plate" + directory = plate / "standalone_result" + directory.mkdir(parents=True) + roi = directory / "independent-outline.roi.zip" + roi.write_bytes(b"synthetic admission only") + target = RuntimeArtifactMetadataTarget.from_plan(plan_for(plate)).for_directory( + directory + ) + target.write(publication_context) + assert result_paths(plate, publication_context) == (str(roi),) + metadata_path = METADATA_CONFIG.metadata_path(plate) + before = metadata_path.read_bytes() + (directory / "unaddressed-image.tif").write_bytes(b"never decoded") + with pytest.raises( + MetadataWriteError, match="Saved images lack typed produced addresses" + ): + target.write(publication_context) + assert metadata_path.read_bytes() == before + + +def test_reconciliation_keeps_artifact_destination_without_results_field( + tmp_path, publication_context +): + from polystore.virtual_workspace import SourcePixelRef + + from openhcs.core.source_projection import ( + OpenHCSPlaneAddress, + SourceArtifactProjection, + SourceProjectionMetadataSerializer, + ) + from openhcs.microscopes.openhcs import OpenHCSMetadataHandler + + plate = tmp_path / "plate" + plate.mkdir() + projection = SourceArtifactProjection( + address=OpenHCSPlaneAddress.from_values( + well="A01", site="1", channel="2", z_index="1", timepoint="1" + ), + ref=SourcePixelRef(Backend.DISK.value, "physical/acquisition-source.tif"), + source_alias="Declared", + artifact_kind=MetadataArtifactType, + ) + fields = SourceProjectionMetadataSerializer( + SourceSchemaFilenameParser() + ).projection_fields(((projection, "nested/declared-result.tif"),)) + metadata_path = METADATA_CONFIG.metadata_path(plate) + metadata_path.write_text(json.dumps({"subdirectories": {"nested": fields}})) + before = metadata_path.read_bytes() + handler = OpenHCSMetadataHandler(publication_context.filemanager) + assert handler.analysis_result_directories(plate) == () + owner = RuntimeArtifactMetadataTarget.from_plan(plan_for(plate)) + assert plate / "nested" in tuple( + target.output_dir for target in owner.reconciliation_targets(publication_context) + ) + assert metadata_path.read_bytes() == before + + +@pytest.mark.parametrize("later_subdirectory", [False, True]) +def test_reconciliation_admits_all_projection_rows_before_workspace_fields( + tmp_path, publication_context, later_subdirectory +): + plate = tmp_path / "plate" + plate.mkdir() + invalid_row = { + "virtual_path": "images/unregistered.tif", + "projection_role": "unknown", + } + subdirectories = {"images": {"workspace_mapping": "invalid"}} + destination = "later" if later_subdirectory else "images" + subdirectories.setdefault(destination, {})["source_projection"] = [invalid_row] + metadata_path = METADATA_CONFIG.metadata_path(plate) + metadata_path.write_text(json.dumps({"subdirectories": subdirectories})) + before = metadata_path.read_bytes() + owner = RuntimeArtifactMetadataTarget.from_plan(plan_for(plate)) + with pytest.raises(RuntimeError, match="unknown projection_role"): + owner.reconciliation_targets(publication_context) + assert metadata_path.read_bytes() == before + + +def test_reconciliation_preserves_raw_json_error_and_missing_document_error( + tmp_path, publication_context +): + from polystore.exceptions import MetadataNotFoundError + + plate = tmp_path / "plate" + plate.mkdir() + metadata_path = METADATA_CONFIG.metadata_path(plate) + owner = RuntimeArtifactMetadataTarget.from_plan(plan_for(plate)) + with pytest.raises(MetadataNotFoundError): + owner.reconciliation_targets(publication_context) + metadata_path.write_text("{") + with pytest.raises(json.JSONDecodeError): + owner.reconciliation_targets(publication_context) + assert metadata_path.read_text() == "{" + + +def test_new_result_declaration_composes_cooperative_hooks_without_consumer_edits( + tmp_path, + publication_context, + monkeypatch, +): + plate = tmp_path / "plate" + destination = "new/declaration_only" + outcome, output = save_archive_outcome( + publication_context, plate, destination, monkeypatch + ) + registry = OpenHCSMetadataWriter.OutputTarget.__registry__ + original_declarations = dict(registry) + try: + + class IndependentSavedResultMetadataTarget( + PublicationAuditCapability, + ProducedImageMetadataCapability, + RuntimeArtifactMetadataTarget, + ): + declaration_key = None + + @classmethod + def from_plan(cls, plan): + return cls( + output_dir=plate / destination, + backend=Backend.DISK.value, + plate_root=str(plate), + sub_dir=destination, + results_dir=str(plate / destination), + ) + + plan = replace( + plan_for(plate), + runtime_artifact_materialization=RuntimeArtifactMaterializationPlan(), + ) + (target,) = OpenHCSMetadataWriter.OutputTarget.for_execution( + publication_context, + plan, + artifact_materializations=(outcome,), + ) + target.write(publication_context, produced_plan=plan) + assert publication_context.publication_audit == [ + ("before", destination), + ("after", destination), + ] + assert result_paths(plate, publication_context) == (output.path,) + finally: + registry.clear() + registry.update(original_declarations) + + +def test_files_without_successful_batch_outcomes_do_not_create_step_targets( + tmp_path, + publication_context, +): + plate = tmp_path / "plate" + directory = plate / "unclaimed" + directory.mkdir(parents=True) + (directory / "not_a_saved_outcome.roi.zip").write_bytes(b"synthetic admission only") + assert ( + OpenHCSMetadataWriter.OutputTarget.for_execution( + publication_context, + plan_for(plate), + artifact_materializations=(), + ) + == () + ) diff --git a/tests/unit/test_persisted_semantic_metadata.py b/tests/unit/test_persisted_semantic_metadata.py index 9dd251927c..6f9535c173 100644 --- a/tests/unit/test_persisted_semantic_metadata.py +++ b/tests/unit/test_persisted_semantic_metadata.py @@ -17,7 +17,6 @@ image_payload_metadata, ) from openhcs.core.source_binding_selection import SourcePatternResolutionContext -from openhcs.core.source_bindings import SourceBindingRuntimeContext from openhcs.core.source_image_provenance import ( SourceImageProvenance, SourceImageProvenancePlanes, @@ -94,14 +93,10 @@ def _resolve_persisted_nested_metadata_in_spawned_runtime( projection = VirtualWorkspaceSourceProjection.from_openhcs_metadata( Path("/plate"), document ) - runtime_context = SourceBindingRuntimeContext( - step_input_files=(VIRTUAL_PATH,), - step_input_source_paths={VIRTUAL_PATH: VIRTUAL_PATH}, - source_metadata_by_path=projection.source_metadata_by_path, - ) - selection_context = SourcePatternResolutionContext.from_runtime_context( + selection_context = SourcePatternResolutionContext.from_sources( parser=SourceSchemaFilenameParser(), - runtime_context=runtime_context, + source_paths_by_virtual_path={VIRTUAL_PATH: VIRTUAL_PATH}, + source_metadata_by_path=projection.source_metadata_by_path, ) metadata = selection_context.metadata_for_path(VIRTUAL_PATH) if metadata is None: diff --git a/tests/unit/test_pipeline_document.py b/tests/unit/test_pipeline_document.py index 4b58a23201..1760d52baa 100644 --- a/tests/unit/test_pipeline_document.py +++ b/tests/unit/test_pipeline_document.py @@ -158,3 +158,32 @@ def test_render_revalidates_direct_pipeline_document_instances() -> None: with pytest.raises(TypeError, match="PipelineConfig"): PipelineDocumentAuthority.render(invalid) + + +def test_pipeline_document_preserves_intrinsic_volume_source_declaration(): + import pickle + from openhcs.core.config import LazySourceBindingsConfig + from openhcs.core.source_bindings import ( + CompiledSourceBindingPlan, + StepSourceBindingsConfig, + ) + from openhcs.core.source_spatial_domain import VolumeSourceSpatialDomain + + domain = VolumeSourceSpatialDomain() + document = PipelineDocumentAuthority.from_values( + pipeline_config=PipelineConfig( + source_bindings_config=LazySourceBindingsConfig( + source_spatial_domain=domain + ) + ), + pipeline_steps=[], + ) + source = PipelineDocumentAuthority.render(document) + restored = PipelineDocumentAuthority.from_source(source) + assert ( + restored.pipeline_config.source_bindings_config.source_spatial_domain == domain + ) + plan = CompiledSourceBindingPlan.from_config( + StepSourceBindingsConfig(source_spatial_domain=domain) + ) + assert pickle.loads(pickle.dumps(plan)).source_spatial_domain == domain diff --git a/tests/unit/test_preparation_admission.py b/tests/unit/test_preparation_admission.py index 3ed203e53d..99c99a3a55 100644 --- a/tests/unit/test_preparation_admission.py +++ b/tests/unit/test_preparation_admission.py @@ -189,8 +189,10 @@ def prepare_selected(): ) dynamic_invocation = CompiledFunctionInvocation( key=FunctionInvocationKey("dynamic", "default", 1), - contract=CallableContract.from_callable(dynamic), + contract=CallableContract.from_prepared_callable(dynamic), ) + assert events == ["selected", "unselected", "dynamic"] + assert dynamic_invocation.contract.metadata.canonical_signature is not None group = CompiledFunctionGroup("default", (invocation, dynamic_invocation)) pattern = CompiledFunctionPattern(groups=(group,), is_grouped=False) context = SimpleNamespace(step_plans={0: SimpleNamespace(step_index=0, compiled_function_pattern=pattern)}) diff --git a/tests/unit/test_primary_image_carrier_compile_gate.py b/tests/unit/test_primary_image_carrier_compile_gate.py index 5056b6dd0c..c7da86749e 100644 --- a/tests/unit/test_primary_image_carrier_compile_gate.py +++ b/tests/unit/test_primary_image_carrier_compile_gate.py @@ -19,6 +19,7 @@ from openhcs.core.component_group_scope import ComponentGroupScope from openhcs.core.context.processing_context import ProcessingContext from openhcs.core.function_patterns import ( + MainFlowInputProjection, CompiledFunctionGroup, CompiledFunctionInvocation, CompiledFunctionPattern, @@ -74,7 +75,7 @@ def _compiled_pattern( ), storage_plan=None, projection=None, - consumes_main_flow=True, + main_flow_projection=MainFlowInputProjection.DECLARED_SOURCE_IMAGE, ), ) ) diff --git a/tests/unit/test_primary_object_diagnostics.py b/tests/unit/test_primary_object_diagnostics.py index 6c8f88cf27..735a8908e7 100644 --- a/tests/unit/test_primary_object_diagnostics.py +++ b/tests/unit/test_primary_object_diagnostics.py @@ -145,7 +145,7 @@ def test_diagnostic_contract_has_source_producer_stage_identity_not_new_objects( def test_ordinary_image_contextualization_preserves_unexecuted_masks(): from openhcs.core.artifacts import ArtifactOutputPlan - from openhcs.core.steps.function_runtime import FunctionOutputContextStrategy + source = _source() objects = _objects(source) @@ -164,7 +164,7 @@ def test_ordinary_image_contextualization_preserves_unexecuted_masks(): artifact_type=spec.artifact_type, sidecar_role=spec.sidecar_role, relations=spec.relations, ) - value = FunctionOutputContextStrategy.for_output_plan(plan).contextualize( + value = (ImageArtifactType if plan is None else plan.artifact_type).contextualize_output( source, plane, plan, None ) np.testing.assert_array_equal(value.mask, plane.mask) diff --git a/tests/unit/test_step_snapshot.py b/tests/unit/test_resolved_pipeline_definition.py similarity index 59% rename from tests/unit/test_step_snapshot.py rename to tests/unit/test_resolved_pipeline_definition.py index ddbf5ca4cb..acdf9a8983 100644 --- a/tests/unit/test_step_snapshot.py +++ b/tests/unit/test_resolved_pipeline_definition.py @@ -1,14 +1,9 @@ -from dataclasses import fields - +from openhcs.core.pipeline.compilation_session import ResolvedPipelineDefinition import pytest from openhcs.constants import VariableComponents from openhcs.constants.input_source import InputSource from openhcs.core.config import ProcessingConfig, StepMaterializationConfig -from openhcs.core.pipeline.step_snapshot import ( - StepSnapshot, - build_step_snapshots, -) from openhcs.core.source_bindings import ( ComponentSelector, NamedSourceBinding, @@ -27,10 +22,10 @@ def __init__(self, scope_id="plate::functionstep_0"): self.scope_id = scope_id def to_object(self): - raise AssertionError("StepSnapshot must not call ObjectState.to_object()") + raise AssertionError("Resolved pipeline must not call ObjectState.to_object()") -def test_step_snapshot_reads_semantics_from_resolved_step_without_object_conversion(): +def test_resolved_pipeline_reads_steps_without_object_conversion(): source_bindings = StepSourceBindingsConfig( bindings=( NamedSourceBinding( @@ -54,24 +49,20 @@ def test_step_snapshot_reads_semantics_from_resolved_step_without_object_convers ) state = StateStub() - snapshot = build_step_snapshots([step], {0: state})[0] - - assert [field.name for field in fields(StepSnapshot)] == [ - "index", - "scope_id", - "step", - ] - assert snapshot.scope_id == "plate::functionstep_0" - assert snapshot.step is step - assert snapshot.step.source_bindings is source_bindings - assert snapshot.step.processing_config.input_source is InputSource.PIPELINE_START - assert snapshot.step.processing_config.variable_components == [ + pipeline = ResolvedPipelineDefinition([step], {0: state}) + assert pipeline.steps[0] is step + assert pipeline.step_state_map[0] is state + assert pipeline.steps[0].source_bindings is source_bindings + assert ( + pipeline.steps[0].processing_config.input_source is InputSource.PIPELINE_START + ) + assert pipeline.steps[0].processing_config.variable_components == [ VariableComponents.SITE ] -def test_build_step_snapshots_requires_matching_objectstate(): +def test_resolved_pipeline_requires_matching_objectstate(): step = FunctionStep(func=_identity, name="missing") - with pytest.raises(ValueError, match="Missing ObjectState"): - build_step_snapshots([step], {}) + with pytest.raises(ValueError, match="missing ObjectState"): + ResolvedPipelineDefinition([step], {}) diff --git a/tests/unit/test_returned_output_abi.py b/tests/unit/test_returned_output_abi.py index a62970c746..7cac5c73e6 100644 --- a/tests/unit/test_returned_output_abi.py +++ b/tests/unit/test_returned_output_abi.py @@ -279,6 +279,6 @@ def process(_image: np.ndarray) -> tuple[ImageOutputBundle, np.ndarray]: records = context.runtime_value_store.find(name=spec.name, axis_id="A01") assert len(records) == 1 np.testing.assert_array_equal( - image_payload_data(records[0].value.data), + image_payload_data(records[0].data), expected, ) diff --git a/tests/unit/test_runtime_adapter_source_artifacts.py b/tests/unit/test_runtime_adapter_source_artifacts.py index 774ef3587f..af3d5ca2a0 100644 --- a/tests/unit/test_runtime_adapter_source_artifacts.py +++ b/tests/unit/test_runtime_adapter_source_artifacts.py @@ -2,6 +2,7 @@ from types import SimpleNamespace import numpy as np +import pytest from polystore.base import ensure_storage_registry, storage_registry from polystore.filemanager import FileManager from scipy.io import savemat @@ -12,7 +13,9 @@ from openhcs.core.component_group_scope import RuntimeExecutionAxisScope from openhcs.core.runtime_adapters import RuntimeAdapterRequest from openhcs.core.runtime_image_loading import ImagePayloadSourceMetadataContext -from openhcs.core.runtime_image_values import image_payload_data +from openhcs.core.runtime_image_values import image_payload_data, image_payload_metadata +from openhcs.core.runtime_source_binding_cache import RuntimeSourceBindingContextCache +from openhcs.core.source_binding_selection import SourcePatternResolutionContext from openhcs.core.runtime_object_labels import ObjectLabelSet from openhcs.core.source_binding_workspace import SourceBindingWorkspaceProjector from openhcs.core.source_bindings import ( @@ -20,7 +23,6 @@ NamedSourceBinding, SourceBindingMatchMethod, SourceBindingMatchPlan, - SourceBindingRuntimeContext, SourceBindingsConfig, SourceFilterClause, SourceFilterMatchType, @@ -30,7 +32,6 @@ StepSourceBindingsConfig, ) from openhcs.core.source_image_provenance import SourceImageIdentity -from openhcs.core.source_image_semantics import apply_source_binding_payload from openhcs.core.source_matching import SourceImageSetIdentityPolicy from openhcs.core.source_projection import SourcePlaneProjection from openhcs.core.source_workspace_projection import ( @@ -38,8 +39,8 @@ VirtualWorkspaceSourceProjectionAuthority, VirtualWorkspaceSourceProjectionCache, ) -from openhcs.interop.cellprofiler.runtime.artifact_binding import ( - RuntimeArtifactTypeStrategy, +from openhcs.interop.cellprofiler.runtime.output_recording import ( + CellProfilerOutputRecorder, ) from openhcs.microscopes import create_microscope_handler from openhcs.microscopes.openhcs import OpenHCSMicroscopeHandler @@ -53,6 +54,7 @@ def _filemanager() -> FileManager: def test_source_artifact_inputs_share_workspace_vfs_and_contract_resolution( tmp_path: Path, + monkeypatch: pytest.MonkeyPatch, ) -> None: source_root = tmp_path / "source" workspace_root = tmp_path / "workspace" @@ -140,6 +142,7 @@ def binding( filemanager=filemanager, microscope_handler=microscope_handler, runtime_source_workspace_projection_cache=projection_cache, + runtime_source_binding_context_cache=RuntimeSourceBindingContextCache(), source_image_set_identity_policy=SourceImageSetIdentityPolicy( frozenset((AllComponents.CHANNEL,)) ), @@ -173,9 +176,8 @@ def binding( Backend.VIRTUAL_WORKSPACE.value, ), ) - primary_payload = apply_source_binding_payload( + primary_payload = primary_binding.apply_loaded_payload( primary_payload, - primary_binding, ImagePayloadSourceMetadataContext( SourceImageIdentity( primary_virtual_path, @@ -186,13 +188,6 @@ def binding( primary_projection.ref.backend_address, ), ) - runtime_context = SourceBindingRuntimeContext( - step_input_source_paths={ - virtual_path: source_ref.backend_address - for virtual_path, source_ref in projection.source_refs_by_virtual_path.items() - }, - source_metadata_by_path=projection.source_metadata_by_path, - ) def request() -> RuntimeAdapterRequest: return RuntimeAdapterRequest( @@ -205,7 +200,6 @@ def request() -> RuntimeAdapterRequest: enabled=True, ), ), - source_binding_context=runtime_context, axis_scope=RuntimeExecutionAxisScope.from_raw( "A01", component=None, @@ -214,12 +208,11 @@ def request() -> RuntimeAdapterRequest: ) illumination_request = request() + illumination_payload = illumination_request.source_artifact_payload( + illumination_binding.input_spec().ref() + ) np.testing.assert_array_equal( - image_payload_data( - illumination_request.source_artifact_payload( - illumination_binding.input_spec().ref() - ) - ), + image_payload_data(illumination_payload), illumination[np.newaxis, ...], ) @@ -234,10 +227,44 @@ def request() -> RuntimeAdapterRequest: labels_request = request() labels_spec = labels_binding.input_spec() labels_payload = labels_request.source_artifact_payload(labels_spec.ref()) - label_set = RuntimeArtifactTypeStrategy.for_artifact_type( + label_set = CellProfilerOutputRecorder.for_artifact_type( ObjectLabelsArtifactType ).raw_runtime_input_value( spec=labels_spec, value=labels_payload ) assert isinstance(label_set, ObjectLabelSet) np.testing.assert_array_equal(label_set.labels, labels[np.newaxis, ...]) + + # Exercise the actual source adapter and VFS under the independent live + # selector route. Payload identity belongs to the unchanged typed source + # projection, not the selector's resolved metadata record representation. + with monkeypatch.context() as live_selector: + live_selector.setattr( + RuntimeSourceBindingContextCache, + "source_pattern_context", + lambda self, **kwargs: SourcePatternResolutionContext.from_projection( + **kwargs + ), + ) + live_illumination = request().source_artifact_payload( + illumination_binding.input_spec().ref() + ) + live_labels = request().source_artifact_payload(labels_spec.ref()) + for produced, live in ( + (illumination_payload, live_illumination), + (labels_payload, live_labels), + ): + np.testing.assert_array_equal( + image_payload_data(produced), image_payload_data(live) + ) + produced_metadata = image_payload_metadata(produced) + live_metadata = image_payload_metadata(live) + assert produced_metadata == live_metadata + assert ( + produced_metadata.source_provenance.source_identity.identity + == live_metadata.source_provenance.source_identity.identity + ) + assert ( + produced_metadata.source_provenance.represented_source_identities + == live_metadata.source_provenance.represented_source_identities + ) diff --git a/tests/unit/test_runtime_artifact_input_value_contract.py b/tests/unit/test_runtime_artifact_input_value_contract.py index a99da528e9..504dd7de60 100644 --- a/tests/unit/test_runtime_artifact_input_value_contract.py +++ b/tests/unit/test_runtime_artifact_input_value_contract.py @@ -9,14 +9,16 @@ image_payload_data, image_payload_metadata, ) -from openhcs.interop.cellprofiler.runtime.artifact_binding import RuntimeArtifactTypeStrategy +from openhcs.interop.cellprofiler.runtime.output_recording import ( + CellProfilerOutputRecorder, +) def test_integer_call_mutation_does_not_replace_post_call_source(): spec = ArtifactSpec.input("DNA", ImageArtifactType) pixels = np.arange(12, dtype=np.uint8).reshape(3, 4) source = ImagePayloadMetadata(source_image_names=("Original",)).payload_with(pixels) - strategy = RuntimeArtifactTypeStrategy.for_artifact_type(spec.artifact_type) + strategy = CellProfilerOutputRecorder.for_artifact_type(spec.artifact_type) raw = strategy.raw_runtime_input_value(spec, source) assert image_payload_data(raw) is pixels assert image_payload_metadata(raw) is not image_payload_metadata(source) @@ -37,7 +39,7 @@ def test_raw_source_derivation_preserves_live_nested_source_mapping(): source = ImagePayloadMetadata( source_component_metadata={"nested": {"selected": "before"}}, ).payload_with(np.zeros((2, 3), dtype=np.uint8)) - strategy = RuntimeArtifactTypeStrategy.for_artifact_type(spec.artifact_type) + strategy = CellProfilerOutputRecorder.for_artifact_type(spec.artifact_type) first = strategy.raw_runtime_input_value(spec, source) nested = image_payload_metadata(source).source_component_metadata["nested"] assert image_payload_metadata(first) is not image_payload_metadata(source) @@ -50,7 +52,7 @@ def test_raw_source_derivation_preserves_live_nested_source_mapping(): def test_measurement_type_errors_remain_at_value_consumption(): spec = ArtifactSpec.input("Intensity", MeasurementsArtifactType) - strategy = RuntimeArtifactTypeStrategy.for_artifact_type(spec.artifact_type) + strategy = CellProfilerOutputRecorder.for_artifact_type(spec.artifact_type) with pytest.raises(TypeError, match="Measurement artifact 'Intensity' requires a MeasurementTable, got object"): strategy.runtime_input_value(spec, object()) with pytest.raises(TypeError, match="Measurement artifact 'Intensity' requires a MeasurementTable, got object"): diff --git a/tests/unit/test_runtime_artifact_queries.py b/tests/unit/test_runtime_artifact_queries.py index 105607d76d..28806d60c9 100644 --- a/tests/unit/test_runtime_artifact_queries.py +++ b/tests/unit/test_runtime_artifact_queries.py @@ -2,6 +2,7 @@ from collections.abc import Mapping from dataclasses import dataclass +import weakref import pytest @@ -25,24 +26,22 @@ ) from openhcs.core.runtime_artifact_queries import ( RuntimeArtifactQueryContext, - MeasurementLabelSliceFeatureBatchQueryCache, MeasurementLabelSliceFeatureBatchQuery, MeasurementLabelSliceFeatureQuery, MeasurementTableAxisProjection, - MeasurementTableUnion, measurement_table_axis_values, measurement_row_mapping, runtime_measurement_tables_for_object, runtime_relationship, ) from openhcs.core.measurement_feature_queries import ( + ColumnarMeasurementTableSchema, MeasurementAxisValueProjection, MeasurementFeatureQuery, + RuntimeObjectLabelMeasurementQuery, + RuntimeObjectLabelMeasurementQueryCache, MeasurementFeatureValueIndex, - MeasurementObjectFeatureAxisBatchQueryCache, MeasurementObjectFeatureVectorBatchQuery, - MeasurementTableObjectFeatureSemantics, - MeasurementTableObjectFeatureSemanticsCache, matching_measurement_field, measurement_feature_candidates, ordered_measurement_feature_candidates, @@ -51,7 +50,6 @@ from openhcs.core.runtime_tabular_values import ( FieldSpec, MeasurementObjectRowIdentity, - MeasurementRowMappingCache, ) from openhcs.core.runtime_measurements import ( MeasurementRowAxisField, @@ -93,6 +91,71 @@ AXIS_ID = "A01" +@pytest.mark.parametrize("batched", (False, True)) +def test_opaque_feature_qualifier_projects_post_callback_object_identity(batched): + import numpy as np + + columns = { + "object_label": [1, 2, 3], + "updated_label": [7, 8, 9], + "value": [3.0, 4.0, MEASUREMENT_SPARSE_CELL], + } + table = MeasurementTable( + name="MutableIdentity", + rows=MeasurementSparseColumnarRows( + columns, + fields=( + FieldSpec("object_label", int), + FieldSpec("updated_label", int), + FieldSpec("value", float), + ), + ), + subject=MeasurementSubject(MeasurementScope.OBJECT, "Cells", "object_label"), + ) + qualified = [] + + def qualify(value): + qualified.append(value) + table.subject = MeasurementSubject( + MeasurementScope.OBJECT, "Cells", "updated_label" + ) + if len(qualified) % 2 == 0: + first_label = 10 if len(qualified) == 2 else 30 + columns["updated_label"] = [first_label, first_label + 10, 99] + return True + + query = MeasurementFeatureQuery("value", "Cells") + row_mask = np.asarray([True, False, False]) + if batched: + indexes = [ + axes[None]["Cells"] + for _, axes in ColumnarMeasurementTableSchema.from_table( + table + ).feature_value_indexes( + table, + {"first": query, "second": query}, + {"first": {"Cells": "Cells"}, "second": {"Cells": "Cells"}}, + index_type=MeasurementFeatureValueIndex, + row_masks={None: row_mask}, + measurement_value_qualifier=qualify, + ) + ] + else: + indexes = [ + MeasurementFeatureValueIndex.from_columnar_table_by_object( + table, + query, + {"Cells": "Cells"}, + row_mask=row_mask, + measurement_value_qualifier=qualify, + )["Cells"] + for _ in range(2) + ] + + assert qualified == [3.0, 4.0, 3.0, 4.0] + assert [index.values_by_label for index in indexes] == [{10: 3.0}, {30: 3.0}] + + @pytest.mark.parametrize( ("declaration_type", "field_name"), ( @@ -214,7 +277,6 @@ def test_runtime_measurement_query_matches_schema_and_row_object_subjects() -> N def test_measurement_row_mapping_accepts_slotted_dataclasses() -> None: - MeasurementRowMappingCache.process_cache().entries.clear() row = MeasurementRow(object_name="Nuclei", object_label=1) mapping = measurement_row_mapping(row) @@ -233,15 +295,24 @@ def test_measurement_row_mapping_accepts_slotted_dataclasses() -> None: } -def test_measurement_row_mapping_cache_reuses_dataclass_rows() -> None: - cache = MeasurementRowMappingCache.process_cache() - cache.entries.clear() - row = MeasurementRow(object_name="Nuclei", object_label=1) +def test_measurement_row_mapping_observes_current_dataclass_with_independent_values() -> ( + None +): + @dataclass(slots=True) + class MutableMeasurementRow: + object_name: str + values: list[float] + row = MutableMeasurementRow(object_name="Nuclei", values=[0.5]) first = measurement_row_mapping(row) + row.object_name = "Cells" + row.values[0] = 7.5 second = measurement_row_mapping(row) - assert first is second + assert first == {"object_name": "Nuclei", "values": [0.5]} + assert second == {"object_name": "Cells", "values": [7.5]} + second["values"][0] = 9.5 + assert row.values == [7.5] def test_projected_columnar_rows_preserve_none_values() -> None: @@ -636,9 +707,9 @@ def test_measurement_feature_query_uses_table_object_id_field() -> None: assert values.tolist() == [10.0, 20.0] -def test_measurement_table_semantics_cache_reuses_table_identity() -> None: - cache = MeasurementTableObjectFeatureSemanticsCache.process_cache() - cache.entries.clear() +def test_measurement_table_semantics_observes_current_row_and_subject_declarations() -> ( + None +): table = MeasurementTable( name="ObjectMeasurements", rows=MeasurementSparseColumnarRows.from_rows( @@ -655,12 +726,22 @@ def test_measurement_table_semantics_cache_reuses_table_identity() -> None: subject=MeasurementSubject(MeasurementScope.ARTIFACT, "ObjectMeasurements"), ) - first = MeasurementTableObjectFeatureSemantics.from_table(table) - second = MeasurementTableObjectFeatureSemantics.from_table(table) + first_schema = ColumnarMeasurementTableSchema.from_table(table) + first = (first_schema.object_names(table), first_schema.feature_names(table)) + table.rows = MeasurementSparseColumnarRows( + {**table.rows.columns, "object_name": ("Nuclei", "Nuclei")}, + fields=table.rows.fields, + ) + second_schema = ColumnarMeasurementTableSchema.from_table(table) + second = (second_schema.object_names(table), second_schema.feature_names(table)) + table.subject = MeasurementSubject(MeasurementScope.OBJECT, "SelectedObjects") + third_schema = ColumnarMeasurementTableSchema.from_table(table) + third = (third_schema.object_names(table), third_schema.feature_names(table)) - assert first is second - assert first.object_names == ("Cells",) - assert "area" in first.feature_names + assert first[0] == ("Cells",) + assert second[0] == ("Nuclei",) + assert third[0] == ("SelectedObjects",) + assert "area" in first[1] == second[1] == third[1] def test_measurement_feature_candidates_match_cellprofiler_compact_metric_names() -> ( @@ -960,42 +1041,23 @@ def test_batch_label_slice_measurement_lookup_scans_each_axis_once( monkeypatch: pytest.MonkeyPatch, ) -> None: np = pytest.importorskip("numpy") - MeasurementLabelSliceFeatureBatchQueryCache.process_cache().entries.clear() - MeasurementObjectFeatureAxisBatchQueryCache.process_cache().entries.clear() - table_scans: list[tuple[int, int | None, tuple[str, ...]]] = [] - original_table_value_indexes = ( - MeasurementObjectFeatureVectorBatchQuery.table_value_indexes - ) - - def counted_table_value_indexes( - query: MeasurementObjectFeatureVectorBatchQuery, - table: MeasurementTable, - table_query: MeasurementFeatureQuery, - table_object_names: tuple[str, ...], - query_objects_by_requested_object: Mapping[str, str | None], - *, - projection: MeasurementAxisValueProjection | None = None, - ) -> dict[str, MeasurementFeatureValueIndex]: + table_scans: list[tuple[int, tuple[int, ...], tuple[str, ...]]] = [] + original_feature_indexes = ColumnarMeasurementTableSchema.feature_value_indexes + + def counted_feature_indexes(schema, table, queries, objects_by_feature, **kwargs): table_scans.append( ( id(table), - None if projection is None else projection.value, - table_object_names, + tuple(kwargs["row_masks"]), + tuple(next(iter(objects_by_feature.values()))), ) ) - return original_table_value_indexes( - query, - table, - table_query, - table_object_names, - query_objects_by_requested_object, - projection=projection, + yield from original_feature_indexes( + schema, table, queries, objects_by_feature, **kwargs ) monkeypatch.setattr( - MeasurementObjectFeatureVectorBatchQuery, - "table_value_indexes", - counted_table_value_indexes, + ColumnarMeasurementTableSchema, "feature_value_indexes", counted_feature_indexes ) cell_labels = object_labels( np.array( @@ -1082,9 +1144,8 @@ def counted_table_value_indexes( [1.5], [1.9], ) - assert [(table_id, axis) for table_id, axis, _ in table_scans] == [ - (id(table), 0), - (id(table), 1), + assert [(table_id, axes) for table_id, axes, _ in table_scans] == [ + (id(table), (0, 1)), ] assert all( set(object_names) == {"Cells", "Nuclei"} for _, _, object_names in table_scans @@ -1158,10 +1219,8 @@ def test_label_slice_measurement_lookup_preserves_producer_runtime_slice_axis() assert tuple(value.tolist() for value in values) == ([0.25], [0.0]) -def test_axis_batch_cache_rebuilds_partial_object_axes() -> None: +def test_axis_batch_observes_current_values_across_complete_object_axes() -> None: np = pytest.importorskip("numpy") - cache = MeasurementObjectFeatureAxisBatchQueryCache.process_cache() - cache.entries.clear() table = MeasurementTable( name="IntensityMeasurements", rows=MeasurementProjectedColumnarRows( @@ -1194,17 +1253,11 @@ def test_axis_batch_cache_rebuilds_partial_object_axes() -> None: dialect=CELLPROFILER_MEASUREMENT_LOOKUP_DIALECT, ) table_map = {"Nuclei": (table,)} - cache.store_value( - batch_query.axis_cache_key(table_map, MeasurementRowAxisField.SLICE_INDEX), - ( - batch_query.table_owners(table_map), - { - 0: {"Nuclei": ({1: 1.0, 2: 2.0}, [])}, - 1: {}, - 2: {}, - }, - ), + initial = batch_query.value_indexes_by_axis( + table_map, MeasurementRowAxisField.SLICE_INDEX ) + assert initial[2]["Nuclei"][0] == {1: 5.0, 2: 6.0} + table.rows.columns["mean_intensity"] = (1.0, 2.0, 3.0, 4.0, 7.0, 8.0) labels = object_labels( np.array( ( @@ -1229,7 +1282,7 @@ def test_axis_batch_cache_rebuilds_partial_object_axes() -> None: assert tuple(value.tolist() for value in values) == ( [1.0, 2.0], [3.0, 4.0], - [5.0, 6.0], + [7.0, 8.0], ) @@ -1352,9 +1405,13 @@ def test_row_sequence_feature_semantics_ignore_stale_partition_fields() -> None: subject=MeasurementSubject(MeasurementScope.OBJECT, "Objects2"), ) - semantics = MeasurementTableObjectFeatureSemantics.from_table(table) + semantics_schema = ColumnarMeasurementTableSchema.from_table(table) + semantics = ( + semantics_schema.object_names(table), + semantics_schema.feature_names(table), + ) - assert "Children_Objects2_Count" not in semantics.feature_names + assert "Children_Objects2_Count" not in semantics[1] def test_measurement_table_axis_query_projects_sequence_rows() -> None: @@ -1386,9 +1443,9 @@ def test_measurement_table_axis_query_projects_sequence_rows() -> None: assert projected.rows.row_mappings() == ( {"slice_index": 1, "object_label": 1, "area": 20.0}, ) - assert MeasurementTableObjectFeatureSemantics.from_table( + assert ColumnarMeasurementTableSchema.from_table(table).feature_names( table - ).feature_names == frozenset({"area"}) + ) == frozenset({"area"}) def test_measurement_table_union_preserves_compatible_schema() -> None: @@ -1416,7 +1473,7 @@ def test_measurement_table_union_preserves_compatible_schema() -> None: subject=subject, ) - union = MeasurementTableUnion("CellMeasurements", (first, second)).as_table() + union = MeasurementTable.join("CellMeasurements", (first, second)) assert union.rows.fields == (FieldSpec("cell_id", int), FieldSpec("area", float)) assert union.subject.object_name == "Cells" @@ -1446,7 +1503,7 @@ def test_measurement_table_union_composes_ordered_source_provenance() -> None: for index, path in enumerate(paths, start=1) ) - union = MeasurementTableUnion("CellMeasurements", tables).as_table() + union = MeasurementTable.join("CellMeasurements", tables) assert union.rows.row_mappings() == ( {"cell_id": 1, "area": 10.0}, @@ -1504,19 +1561,17 @@ def test_measurement_table_union_bundles_sources_per_declared_runtime_slice() -> for channel in (1, 2) ) - metadata = MeasurementTableUnion("quality_metrics", tables).source_metadata() + provenance = MeasurementTable.joined_source_provenance("quality_metrics", tables) - assert metadata.source_provenance.source_plane_count == 2 + assert provenance.source_plane_count == 2 assert tuple( - metadata.source_provenance.for_source_plane(index).source_component_metadata[ - "site" - ] + provenance.for_source_plane(index).source_component_metadata["site"] for index in range(2) ) == ("1", "2") assert tuple( tuple( contributor.path - for contributor in metadata.source_provenance.for_source_plane( + for contributor in provenance.for_source_plane( index ).source_image_provenance_planes.contributors ) @@ -1526,6 +1581,31 @@ def test_measurement_table_union_bundles_sources_per_declared_runtime_slice() -> ("/plate/A01_s002_w1.tif", "/plate/A01_s002_w2.tif"), ) + # A later export reads the tables' current provenance, not the prior join epoch. + first = tables[0] + first.source_provenance = ( + first.source_provenance.with_source_image_provenance_planes( + SourceImageProvenancePlanes.from_components( + paths=("/changed/site-1.tif", "/changed/site-2.tif"), + component_metadata=( + {"well": "A01", "site": "1"}, + {"well": "A01", "site": "2"}, + ), + ) + ) + ) + current = MeasurementTable.joined_source_provenance("quality_metrics", tables) + assert ( + current.for_source_plane(0).source_image_provenance_planes.contributors[0].path + == "/changed/site-1.tif" + ) + assert ( + provenance.for_source_plane(0) + .source_image_provenance_planes.contributors[0] + .path + == "/plate/A01_s001_w1.tif" + ) + def test_measurement_table_union_accepts_axisless_payload_domain() -> None: table = MeasurementTable( @@ -1541,8 +1621,8 @@ def test_measurement_table_union_accepts_axisless_payload_domain() -> None: ) assert ( - MeasurementTableUnion("CellMeasurements", (table,)).row_axis_domain( - MeasurementRowAxisField.SLICE_INDEX + MeasurementTable.shared_row_axis_domain( + "CellMeasurements", (table,), MeasurementRowAxisField.SLICE_INDEX ) is None ) @@ -1568,11 +1648,8 @@ def test_measurement_table_union_preserves_payload_rows_in_axis_declaring_table( subject=MeasurementSubject(MeasurementScope.OBJECT, "Cells", "cell_id"), ) - assert MeasurementTableUnion( - "CellMeasurements", - (table,), - ).row_axis_domain( - MeasurementRowAxisField.SLICE_INDEX + assert MeasurementTable.shared_row_axis_domain( + "CellMeasurements", (table,), MeasurementRowAxisField.SLICE_INDEX ) == (0,) @@ -1607,8 +1684,8 @@ def test_measurement_table_union_rejects_mixed_slice_domains() -> None: ValueError, match="mixes declared and axisless 'slice_index' row domains", ): - MeasurementTableUnion("CellMeasurements", tables).row_axis_domain( - MeasurementRowAxisField.SLICE_INDEX + MeasurementTable.shared_row_axis_domain( + "CellMeasurements", tables, MeasurementRowAxisField.SLICE_INDEX ) @@ -1640,7 +1717,7 @@ def test_measurement_table_union_drops_incompatible_schema_facts() -> None: ValueError, match="require one exact nominal subject", ): - MeasurementTableUnion("MixedMeasurements", (first, second)).as_table() + MeasurementTable.join("MixedMeasurements", (first, second)) def test_measurement_table_axis_query_projects_table_sequences() -> None: @@ -1788,3 +1865,126 @@ def _record_native( path=f"/memory/{native_value.name}.pkl", backend="memory", ) + + +def test_batch_measurement_queries_release_owners_and_observe_store_replacement() -> ( + None +): + np = pytest.importorskip("numpy") + + def run_query_epoch(): + store = RuntimeValueStore() + pixels = { + name: np.ones((2, 32, 32), dtype=np.int32) for name in ("Cells", "Nuclei") + } + labels = { + name: object_labels(value, declared_object_id_domains=((1,), (1,))) + for name, value in pixels.items() + } + feature_values = np.asarray([0.5, 0.9, 1.5, 1.9]) + table = MeasurementTable( + name="MixedShapeMeasurements", + rows=MeasurementSparseColumnarRows( + { + "slice_index": np.asarray([0, 1, 0, 1]), + "object_name": np.asarray(["Cells", "Cells", "Nuclei", "Nuclei"]), + "object_label": np.ones(4, dtype=np.int32), + "FormFactor": feature_values, + }, + fields=( + FieldSpec("slice_index", int), + FieldSpec("object_name", str), + FieldSpec("object_label", int), + FieldSpec("FormFactor", float), + ), + ), + subject=MeasurementSubject( + MeasurementScope.ARTIFACT, "MixedShapeMeasurements" + ), + ) + plan = ArtifactOutputPlan( + name=table.name, + path="/memory/measurements", + artifact_type=MeasurementsArtifactType, + ) + store.record( + RuntimeValue.normalize(plan, table, axis_id=AXIS_ID), + path=plan.path, + backend="memory", + ) + query = MeasurementLabelSliceFeatureBatchQuery( + measurement_tables=(table,), + feature_name="AreaShape_FormFactor", + dialect=CELLPROFILER_MEASUREMENT_LOOKUP_DIALECT, + row_axis=MeasurementRowAxisField.SLICE_INDEX, + plane_projector=RuntimePlaneProjection.stack(2), + labels_by_object=labels, + ) + vectors = query.values_by_object() + assert vectors["Cells"][0].tolist() == [0.5] + owned_cache = store.query_cache(RuntimeObjectLabelMeasurementQueryCache) + owned_cache.store_value( + RuntimeObjectLabelMeasurementQuery( + axis_id=AXIS_ID, + group_key=None, + object_name="Cells", + feature_name="AreaShape_FormFactor", + label_domain=(1,), + label_plane_domains=((1,), (1,)), + ), + vectors["Cells"], + ) + feature_values[0] = 7.5 + store.replace( + RuntimeValue.normalize(plan, table, axis_id=AXIS_ID), + path=plan.path, + backend="memory", + ) + assert not owned_cache.entries + assert query.values_by_object()["Cells"][0].tolist() == [7.5] + references = tuple(weakref.ref(value) for value in pixels.values()) + ( + weakref.ref(feature_values), + ) + store.clear() + assert not owned_cache.entries + assert len(store) == 0 + return references + + assert all(reference() is None for reference in run_query_epoch()) + + +def test_declared_non_absent_query_observes_labels_after_each_scalar_conversion(): + labels = [1, 2] + conversions = [] + + class UpdatingNumericText(str): + def __float__(self): + conversions.append(self) + labels[:] = [10 * len(conversions), 20 * len(conversions)] + return float(str(self)) + + table = MeasurementTable( + name="MutableNumericCells", + rows=MeasurementSparseColumnarRows( + { + "object_label": labels, + "value": [UpdatingNumericText("3"), UpdatingNumericText("4")], + }, + fields=(FieldSpec("object_label", int), FieldSpec("value", float)), + ), + subject=MeasurementSubject(MeasurementScope.OBJECT, "Cells"), + ) + query = MeasurementFeatureQuery("value", "Cells") + indexes = [ + axes[None]["Cells"].values_by_label + for _, axes in ColumnarMeasurementTableSchema.from_table( + table + ).non_absent_feature_value_indexes( + table, + {"first": query, "second": query}, + {"first": {"Cells": "Cells"}, "second": {"Cells": "Cells"}}, + index_type=MeasurementFeatureValueIndex, + ) + ] + assert indexes == [{20: 3.0, 40: 4.0}, {40: 3.0, 80: 4.0}] + assert conversions == ["3", "4", "3", "4"] diff --git a/tests/unit/test_runtime_context_declaration.py b/tests/unit/test_runtime_context_declaration.py index 6bdfd2461c..2ac6962887 100644 --- a/tests/unit/test_runtime_context_declaration.py +++ b/tests/unit/test_runtime_context_declaration.py @@ -23,11 +23,10 @@ from openhcs.core.pipeline.function_contracts import runtime_context_parameter from openhcs.core.runtime_image_values import ImagePayloadMetadata from openhcs.core.runtime_plane_projection import RuntimePlaneProjection -from openhcs.core.source_bindings import SourceBindingRuntimeContext from openhcs.core.steps.function_runtime import ( ComponentArtifactPlans, FunctionCoreExecutor, - FunctionRuntimeScope, + PatternGroupData, ) from openhcs.processing.backends.cellprofiler.save_images import ( save_images, @@ -111,7 +110,7 @@ def process(image, *, context=None): return image prepare_processing_callable(process) - contract = CallableContract.from_callable(process) + contract = CallableContract.from_callable(process).with_prepared_signature() assert contract.runtime_context_parameter is None assert "context" not in contract.runtime_owned_parameter_names assert "context" not in parameter_exclusions(process) @@ -129,19 +128,20 @@ def test_runtime_binding_consumes_captured_selection(func, parameter): pattern = compile_function_pattern(func, {}, {}) context = ProcessingContext(axis_id="A01") artifacts = ComponentArtifactPlans(inputs={}, outputs={}) - scope = FunctionRuntimeScope( + scope = PatternGroupData( + matching_files=["input.tif"], + main_data_stack=np.zeros((1, 3, 4), dtype=np.uint16), context=context, execution_plan=CompiledStepPlan( step_index=0, step_name="Context", step_type="FunctionStep", axis_id="A01" ), compiled_group=pattern.default_group, artifacts=artifacts, - source_binding_context=SourceBindingRuntimeContext.empty(), runtime_plane_index=0, runtime_plane_count=1, ) executor = FunctionCoreExecutor( - runtime_scope=scope, + group_data=scope, invocation=next(pattern.iter_invocations()), artifacts=artifacts, group_key=None, diff --git a/tests/unit/test_runtime_equivalence.py b/tests/unit/test_runtime_equivalence.py index 9d6c4040f0..b00af0e456 100644 --- a/tests/unit/test_runtime_equivalence.py +++ b/tests/unit/test_runtime_equivalence.py @@ -8756,15 +8756,13 @@ def test_runtime_measurement_snapshot_preserves_plane_local_single_row_aggregate axis_id = f"A01_s00{site}" records_by_axis[axis_id] = ( StoredRuntimeValue( - RuntimeValue( - key=ArtifactKey( - name="Crop", - artifact_type=MeasurementsArtifactType, - scope=RuntimeExecutionAxisScope(axis_id=axis_id), - ), - data=table, + key=ArtifactKey( + name="Crop", + artifact_type=MeasurementsArtifactType, + scope=RuntimeExecutionAxisScope(axis_id=axis_id), ), - RuntimeArtifactLocation( + data=table, + location=RuntimeArtifactLocation( path=f"/memory/Crop_site{site}.pkl", backend="memory", ), @@ -10732,15 +10730,13 @@ def test_runtime_reference_artifact_equivalence_ignores_duplicate_measurement_ar ) records = tuple( StoredRuntimeValue( - RuntimeValue( - key=ArtifactKey( - name="MeasureTexture", - artifact_type=MeasurementsArtifactType, - scope=RuntimeExecutionAxisScope(axis_id="A01"), - ), - data=table, + key=ArtifactKey( + name="MeasureTexture", + artifact_type=MeasurementsArtifactType, + scope=RuntimeExecutionAxisScope(axis_id="A01"), ), - RuntimeArtifactLocation( + data=table, + location=RuntimeArtifactLocation( path=f"/memory/MeasureTexture_{index}.pkl", backend="memory", ), @@ -10792,15 +10788,13 @@ def test_runtime_reference_artifact_equivalence_ignores_duplicate_image_feature_ ) records = tuple( StoredRuntimeValue( - RuntimeValue( - key=ArtifactKey( - name=table.name, - artifact_type=MeasurementsArtifactType, - scope=RuntimeExecutionAxisScope(axis_id="A01"), - ), - data=table, + key=ArtifactKey( + name=table.name, + artifact_type=MeasurementsArtifactType, + scope=RuntimeExecutionAxisScope(axis_id="A01"), ), - RuntimeArtifactLocation( + data=table, + location=RuntimeArtifactLocation( path=f"/memory/{table.name}_{index}.pkl", backend="memory", ), @@ -10852,19 +10846,17 @@ def test_runtime_reference_artifact_equivalence_ignores_grouped_duplicate_image_ ) records = tuple( StoredRuntimeValue( - RuntimeValue( - key=ArtifactKey( - name=table.name, - artifact_type=MeasurementsArtifactType, - scope=RuntimeExecutionAxisScope( - axis_id="A01", - component=AllComponents.CHANNEL, - value=group_key, - ), + key=ArtifactKey( + name=table.name, + artifact_type=MeasurementsArtifactType, + scope=RuntimeExecutionAxisScope( + axis_id="A01", + component=AllComponents.CHANNEL, + value=group_key, ), - data=table, ), - RuntimeArtifactLocation( + data=table, + location=RuntimeArtifactLocation( path=f"/memory/{table.name}_{group_key}.pkl", backend="memory", ), @@ -10927,15 +10919,13 @@ def test_runtime_reference_artifact_equivalence_applies_tolerance_after_same_pat ) records = tuple( StoredRuntimeValue( - RuntimeValue( - key=ArtifactKey( - name=table.name, - artifact_type=MeasurementsArtifactType, - scope=RuntimeExecutionAxisScope(axis_id="A01"), - ), - data=table, + key=ArtifactKey( + name=table.name, + artifact_type=MeasurementsArtifactType, + scope=RuntimeExecutionAxisScope(axis_id="A01"), ), - RuntimeArtifactLocation( + data=table, + location=RuntimeArtifactLocation( path=f"/memory/{table.name}.pkl", backend="memory", ), @@ -11055,15 +11045,13 @@ def test_runtime_reference_artifact_equivalence_preserves_distinct_source_image_ ) observation_records.append( StoredRuntimeValue( - RuntimeValue( - key=ArtifactKey( - name=table.name, - artifact_type=MeasurementsArtifactType, - scope=RuntimeExecutionAxisScope(axis_id="A01"), - ), - data=table, + key=ArtifactKey( + name=table.name, + artifact_type=MeasurementsArtifactType, + scope=RuntimeExecutionAxisScope(axis_id="A01"), ), - RuntimeArtifactLocation( + data=table, + location=RuntimeArtifactLocation( path=f"/memory/{Path(source_path).stem}.pkl", backend="memory", ), @@ -11112,15 +11100,13 @@ def test_runtime_reference_artifact_equivalence_ignores_duplicate_aggregate_tabl records_by_axis = { axis: ( StoredRuntimeValue( - RuntimeValue( - key=ArtifactKey( - name="IdentifyPrimaryObjects", - artifact_type=MeasurementsArtifactType, - scope=RuntimeExecutionAxisScope(axis_id=axis), - ), - data=table, + key=ArtifactKey( + name="IdentifyPrimaryObjects", + artifact_type=MeasurementsArtifactType, + scope=RuntimeExecutionAxisScope(axis_id=axis), ), - RuntimeArtifactLocation( + data=table, + location=RuntimeArtifactLocation( path=f"/memory/IdentifyPrimaryObjects_{axis}.pkl", backend="memory", ), @@ -11154,42 +11140,40 @@ def test_runtime_reference_artifact_equivalence_ignores_group_replayed_image_tab ) records = tuple( StoredRuntimeValue( - RuntimeValue( - key=ArtifactKey( - name="CalculateMath", - artifact_type=MeasurementsArtifactType, - scope=RuntimeExecutionAxisScope( - axis_id="A01", - component=AllComponents.CHANNEL, - value=channel, - ), + key=ArtifactKey( + name="CalculateMath", + artifact_type=MeasurementsArtifactType, + scope=RuntimeExecutionAxisScope( + axis_id="A01", + component=AllComponents.CHANNEL, + value=channel, ), - data=MeasurementTable( - name="CalculateMath", - rows=MeasurementSparseColumnarRows.from_rows( - ( - { - "slice_index": 0, - "feature_name": "Math_Stain1Colocalized", - "result_value": 0.25, - }, - { - "slice_index": 1, - "feature_name": "Math_Stain1Colocalized", - "result_value": 0.75, - }, - ), - fields=( - FieldSpec("slice_index", int), - FieldSpec("feature_name", str), - FieldSpec("result_value", float), - ), + ), + data=MeasurementTable( + name="CalculateMath", + rows=MeasurementSparseColumnarRows.from_rows( + ( + { + "slice_index": 0, + "feature_name": "Math_Stain1Colocalized", + "result_value": 0.25, + }, + { + "slice_index": 1, + "feature_name": "Math_Stain1Colocalized", + "result_value": 0.75, + }, + ), + fields=( + FieldSpec("slice_index", int), + FieldSpec("feature_name", str), + FieldSpec("result_value", float), ), - source_path=f"/source/channel_{channel}.tif", - subject=MeasurementSubject(MeasurementScope.IMAGE, "Image"), ), + source_path=f"/source/channel_{channel}.tif", + subject=MeasurementSubject(MeasurementScope.IMAGE, "Image"), ), - RuntimeArtifactLocation( + location=RuntimeArtifactLocation( path=f"/memory/CalculateMath_{channel}.pkl", backend="memory", ), @@ -11222,37 +11206,35 @@ def test_runtime_reference_artifact_equivalence_preserves_local_group_image_rows ) records = tuple( StoredRuntimeValue( - RuntimeValue( - key=ArtifactKey( - name="CalculateMath", - artifact_type=MeasurementsArtifactType, - scope=RuntimeExecutionAxisScope( - axis_id="A01", - component=AllComponents.CHANNEL, - value=channel, - ), + key=ArtifactKey( + name="CalculateMath", + artifact_type=MeasurementsArtifactType, + scope=RuntimeExecutionAxisScope( + axis_id="A01", + component=AllComponents.CHANNEL, + value=channel, ), - data=MeasurementTable( - name="CalculateMath", - rows=MeasurementSparseColumnarRows.from_rows( - ( - { - "slice_index": 0, - "feature_name": "Math_Stain1Colocalized", - "result_value": 0.25, - }, - ), - fields=( - FieldSpec("slice_index", int), - FieldSpec("feature_name", str), - FieldSpec("result_value", float), - ), + ), + data=MeasurementTable( + name="CalculateMath", + rows=MeasurementSparseColumnarRows.from_rows( + ( + { + "slice_index": 0, + "feature_name": "Math_Stain1Colocalized", + "result_value": 0.25, + }, + ), + fields=( + FieldSpec("slice_index", int), + FieldSpec("feature_name", str), + FieldSpec("result_value", float), ), - source_path=f"/source/channel_{channel}.tif", - subject=MeasurementSubject(MeasurementScope.IMAGE, "Image"), ), + source_path=f"/source/channel_{channel}.tif", + subject=MeasurementSubject(MeasurementScope.IMAGE, "Image"), ), - RuntimeArtifactLocation( + location=RuntimeArtifactLocation( path=f"/memory/CalculateMath_{channel}.pkl", backend="memory", ), @@ -11303,15 +11285,13 @@ def test_runtime_reference_artifact_equivalence_preserves_same_value_wide_image_ { "A01": ( StoredRuntimeValue( - RuntimeValue( - key=ArtifactKey( - name="IdentifyPrimaryObjects", - artifact_type=MeasurementsArtifactType, - scope=RuntimeExecutionAxisScope(axis_id="A01"), - ), - data=table, + key=ArtifactKey( + name="IdentifyPrimaryObjects", + artifact_type=MeasurementsArtifactType, + scope=RuntimeExecutionAxisScope(axis_id="A01"), ), - RuntimeArtifactLocation( + data=table, + location=RuntimeArtifactLocation( path="/memory/IdentifyPrimaryObjects_A01.pkl", backend="memory", ), @@ -11385,15 +11365,13 @@ def test_runtime_reference_artifact_equivalence_ignores_duplicate_object_rows( ) records.append( StoredRuntimeValue( - RuntimeValue( - key=ArtifactKey( - name="MeasureTexture", - artifact_type=MeasurementsArtifactType, - scope=RuntimeExecutionAxisScope(axis_id="A01"), - ), - data=table, + key=ArtifactKey( + name="MeasureTexture", + artifact_type=MeasurementsArtifactType, + scope=RuntimeExecutionAxisScope(axis_id="A01"), ), - RuntimeArtifactLocation( + data=table, + location=RuntimeArtifactLocation( path=f"/memory/MeasureTexture_{index}.pkl", backend="memory", ), diff --git a/tests/unit/test_runtime_execution_validation.py b/tests/unit/test_runtime_execution_validation.py index 077d4a5e41..9906fed3bb 100644 --- a/tests/unit/test_runtime_execution_validation.py +++ b/tests/unit/test_runtime_execution_validation.py @@ -33,7 +33,11 @@ from openhcs.core.measurement_row_materialization import ( MeasurementSparseColumnarRows, ) -from openhcs.core.orchestrator.execution_result import ExecutionResult +from openhcs.core.orchestrator.execution_result import ( + ExecutionResult, + RuntimeContextObservation, + RuntimeExecutionObservation, +) from openhcs.core.pipeline.function_contracts import execution_scope from openhcs.core.runtime_artifact_values import ( ArtifactKey, @@ -120,7 +124,8 @@ def _streaming_context( def test_runtime_execution_validation_detects_missing_artifact_kind() -> None: observation = RuntimeArtifactExecutionObservation.from_contexts( - {"A01": ProcessingContext(axis_id="A01")} + {"A01": ProcessingContext(axis_id="A01")}, + runtime_observations=(), ) failures = runtime_artifact_execution_failures( @@ -186,7 +191,9 @@ def test_runtime_execution_observation_reads_context_stores() -> None: backend="memory", ) - observation = RuntimeArtifactExecutionObservation.from_contexts({"A01": context}) + observation = RuntimeArtifactExecutionObservation.from_contexts( + {"A01": context}, runtime_observations=() + ) assert observation.record_counts_by_axis["A01"][MeasurementsArtifactType] == 1 @@ -204,7 +211,9 @@ def test_runtime_execution_observation_ignores_uncontracted_files( context = ProcessingContext(axis_id="A01") - observation = RuntimeArtifactExecutionObservation.from_contexts({"A01": context}) + observation = RuntimeArtifactExecutionObservation.from_contexts( + {"A01": context}, runtime_observations=() + ) assert observation.exports.table_outputs == () assert observation.exports.image_outputs == () @@ -239,16 +248,23 @@ def test_zmq_observation_exports_exact_compiler_owned_artifacts( }, axis_id="A01", ) - monkeypatch.setattr( - "openhcs.core.steps.function_artifact_materialization." - "runtime_export_artifact_output_paths", - lambda _plan, _context: (contracted_output,), + runtime_observations = ( + RuntimeExecutionObservation( + contexts=( + RuntimeContextObservation( + context_key="A01", + records=(), + runtime_export_paths=(contracted_output,), + ), + ) + ), ) export = ZMQRuntimeExecutionObservationExport.from_execution( compiled_contexts={"A01": context}, execution_results={"A01": ExecutionResult.success("A01")}, output_roots=(tmp_path,), + runtime_observations=runtime_observations, ) assert export.expectation.artifact_kinds == frozenset((MeasurementsArtifactType,)) @@ -258,7 +274,9 @@ def test_zmq_observation_exports_exact_compiler_owned_artifacts( assert export.exports.output_files == (contracted_output,) assert unrelated_output not in export.exports.output_files assert ( - RuntimeExportObservation.from_execution_contexts({"A01": context}).output_files + RuntimeExportObservation.from_runtime_observations( + runtime_observations + ).output_files == export.exports.output_files ) @@ -514,22 +532,22 @@ def test_runtime_execution_observation_reads_plate_export_from_exact_owner( ) for axis_id, owns_output in (("A01", True), ("A02", False)) } - observed_axes: list[str] = [] - - def output_paths(plan, _context): - observed_axes.append(plan.axis_id) - return (contracted_output,) - - monkeypatch.setattr( - "openhcs.core.steps.function_artifact_materialization." - "runtime_export_artifact_output_paths", - output_paths, + runtime_observations = ( + RuntimeExecutionObservation( + contexts=( + RuntimeContextObservation( + context_key="A01", + records=(), + runtime_export_paths=(contracted_output,), + ), + ) + ), + ) + observation = RuntimeArtifactExecutionObservation.from_contexts( + contexts, runtime_observations=runtime_observations ) - - observation = RuntimeArtifactExecutionObservation.from_contexts(contexts) expectation = RuntimeArtifactExecutionExpectation.from_compiled_contexts(contexts) - assert observed_axes == ["A01"] assert observation.exports.table_outputs == (contracted_output,) assert expectation.artifact_kinds == frozenset((MeasurementsArtifactType,)) assert tuple( @@ -578,6 +596,7 @@ def test_zmq_observation_compresses_and_preserves_exact_runtime_records( compiled_contexts={"A01": context}, execution_results={"A01": ExecutionResult.success("A01")}, output_roots=(tmp_path,), + runtime_observations=(), ) path = tmp_path / "observation.pkl" diff --git a/tests/unit/test_runtime_exports.py b/tests/unit/test_runtime_exports.py index 3e14b1eb64..ba205b4974 100644 --- a/tests/unit/test_runtime_exports.py +++ b/tests/unit/test_runtime_exports.py @@ -176,12 +176,14 @@ def _stored_measurements_record( ), ) return StoredRuntimeValue( - value, - RuntimeArtifactLocation( - path=f"results/{axis_id}_Measurements_step1.csv", - backend="disk", - ), - ) + key=value.key, + data=value.data, + materialization_source_metadata=value.materialization_source_metadata, + location=RuntimeArtifactLocation( + path=f"results/{axis_id}_Measurements_step1.csv", + backend="disk", + ), + ) def _table_export_expectation() -> RuntimeExportExpectation: diff --git a/tests/unit/test_runtime_output_matching.py b/tests/unit/test_runtime_output_matching.py index 4b393dae95..bb5cf64e9a 100644 --- a/tests/unit/test_runtime_output_matching.py +++ b/tests/unit/test_runtime_output_matching.py @@ -21,6 +21,12 @@ FunctionStepExecutionScope, ) from openhcs.core.runtime_output_matching import RuntimeReturnedOutputMatcher +from openhcs.core.runtime_image_values import ImagePayloadMetadata, image_payload_data +from openhcs.core.runtime_plane_projection import ( + RuntimePlaneAxis, + RuntimePlaneAxisValueProjection, +) +from openhcs.core.runtime_slice_projection import RuntimeSliceProjectionDeclarationError from openhcs.core.function_patterns import ( CompiledFunctionInvocation, FunctionInvocationKey, @@ -59,6 +65,58 @@ def test_runtime_output_matcher_maps_canonical_and_trailing_slots() -> None: } +def test_matcher_contextualizes_declared_axis_before_resolving_complete_abi() -> None: + first = ArtifactSpec.output("First", ImageArtifactType) + second = ArtifactSpec.output("Second", ImageArtifactType) + measurements = ArtifactSpec.output("Measurements", MeasurementsArtifactType) + data = np.arange(24, dtype=np.float32).reshape((2, 3, 4)) + payload = ImagePayloadMetadata( + plane_axis=RuntimePlaneAxis.RUNTIME_SLICE + ).payload_with(data, None) + trailing = object() + contract = _contract(first, second, measurements) + matcher = RuntimeReturnedOutputMatcher(contract, (payload, trailing)) + projection = RuntimePlaneAxisValueProjection.preserve( + axis=RuntimePlaneAxis.RUNTIME_SLICE, + axis_size=2, + ) + + returned = matcher.contextualize_canonical_output(plane_projection=projection) + resolved = RuntimeReturnedOutputMatcher(contract, returned).resolve() + + assert returned[1] is trailing + assert resolved[measurements.ref()] is trailing + for index, spec in enumerate((first, second)): + selected = image_payload_data(resolved[spec.ref()]) + np.testing.assert_array_equal(selected, data[index]) + assert np.shares_memory(selected, data) + assert ( + RuntimeReturnedOutputMatcher(contract, returned).contextualize_canonical_output() + is returned + ) + + with pytest.raises(RuntimeSliceProjectionDeclarationError, match="without a compiled"): + matcher.contextualize_canonical_output() + with pytest.raises(RuntimeSliceProjectionDeclarationError, match="already selected"): + matcher.contextualize_canonical_output( + plane_projection=projection.selected_plane(0) + ) + with pytest.raises(ValueError, match="projection declares 3 value"): + matcher.contextualize_canonical_output( + plane_projection=RuntimePlaneAxisValueProjection.preserve( + axis=RuntimePlaneAxis.RUNTIME_SLICE, + axis_size=3, + ) + ) + with pytest.raises(RuntimeSliceProjectionDeclarationError, match="plane axis"): + matcher.contextualize_canonical_output( + plane_projection=RuntimePlaneAxisValueProjection.preserve( + axis=RuntimePlaneAxis.SOURCE_BINDING, + axis_size=2, + ) + ) + + def test_runtime_output_matcher_uses_exact_multi_canonical_contexts() -> None: first = ArtifactSpec.output("First", ImageArtifactType) second = ArtifactSpec.output("Second", ImageArtifactType) diff --git a/tests/unit/test_runtime_slice_projection.py b/tests/unit/test_runtime_slice_projection.py index 78aec1511f..a3cc39fdf8 100644 --- a/tests/unit/test_runtime_slice_projection.py +++ b/tests/unit/test_runtime_slice_projection.py @@ -1,4 +1,5 @@ from dataclasses import dataclass +import inspect from typing import Any, get_args, get_origin import numpy as np @@ -85,6 +86,8 @@ def _annotation_leaf_types(annotation: object) -> tuple[type, ...]: def test_cellprofiler_runtime_parameter_types_declare_slice_projection() -> None: missing: list[str] = [] for parameter_type in _subclasses(KeywordRuntimeParameter): + if inspect.isabstract(parameter_type): + continue if not parameter_type.__module__.startswith( ("openhcs.processing.backends.cellprofiler", "openhcs.interop.cellprofiler") ): diff --git a/tests/unit/test_runtime_source_resolution_snapshot.py b/tests/unit/test_runtime_source_resolution_snapshot.py new file mode 100644 index 0000000000..eaa1322d23 --- /dev/null +++ b/tests/unit/test_runtime_source_resolution_snapshot.py @@ -0,0 +1,328 @@ +"""Resolution lifetimes across generic source selectors and artifact adapters.""" + +import pickle +from types import MappingProxyType + +import pytest +from polystore.virtual_workspace import SourcePixelRef + +from openhcs.constants.constants import AllComponents +from openhcs.core.context.processing_context import ProcessingContext +from openhcs.core.runtime_source_binding_cache import RuntimeSourceBindingContextCache +from openhcs.core.source_binding_selection import ( + DeclaredSourceMetadataRecord, + SourceBindingMatchedImageSet, + SourcePatternResolutionContext, +) +from openhcs.core.source_bindings import ( + MetadataExtractionRule, + MetadataSource, +) +from openhcs.core.source_matching import SourceImageSetIdentityPolicy +from openhcs.core.source_metadata import ( + ORIGINAL_SOURCE_METADATA_FIELD, + ResolvedSourceMetadataRecord, +) +from openhcs.core.source_projection import OpenHCSPlaneAddress, SourcePlaneProjection +from openhcs.core.source_workspace_projection import VirtualWorkspaceSourceProjection +from openhcs.microscopes.microscope_interfaces import FilenameParseResult +from openhcs.microscopes.source_schema import SourceSchemaFilenameParser + +PATH = "A01_s001_w1_z001_t001.tif" + + +class CountingParser(SourceSchemaFilenameParser): + def __init__(self): + super().__init__() + self.calls = [] + + def parse_filename(self, path): + self.calls.append(path) + result = super().parse_filename(path) + if result is None or self.pattern_format is None: + return result + return FilenameParseResult( + tuple( + ( + component, + ( + int(self.pattern_format) + if component is AllComponents.SITE + else value + ), + ) + for component, value in result.declared_values() + ), + extension=result.extension, + ) + + +def projection(metadata): + return VirtualWorkspaceSourceProjection( + source_refs_by_virtual_path={PATH: SourcePixelRef("disk", "/source/image.tif")}, + source_metadata_by_path={PATH: metadata}, + ) + + +def snapshot(cache, source_projection, parser, rules=()): + return cache.source_pattern_context( + parser=parser, projection=source_projection, metadata_rules=rules + ) + + +def test_declared_record_resolves_live_parser_and_nested_metadata(): + nested = {"Plate": "before"} + record = DeclaredSourceMetadataRecord.from_mapping( + {ORIGINAL_SOURCE_METADATA_FIELD: nested, "site": 8} + ) + assert isinstance(record, DeclaredSourceMetadataRecord) + parser = CountingParser() + first = record.resolve(PATH, parser, ()) + nested["Plate"] = "after" + second = record.resolve(PATH, parser, ()) + assert first["site"] == second["site"] == 8 + assert first[ORIGINAL_SOURCE_METADATA_FIELD]["Plate"] == "before" + assert second[ORIGINAL_SOURCE_METADATA_FIELD]["Plate"] == "after" + assert parser.calls == [PATH, PATH] + + +def test_runtime_snapshot_owns_nested_metadata_and_unknown_fallback(): + nested = {"Plate": "before"} + source_projection = projection({ORIGINAL_SOURCE_METADATA_FIELD: nested}) + parser = CountingParser() + cache = RuntimeSourceBindingContextCache() + context = snapshot(cache, source_projection, parser) + calls = tuple(parser.calls) + nested["Plate"] = "after" + for _ in range(3): + metadata = context.metadata_for_path(PATH) + assert isinstance(metadata, ResolvedSourceMetadataRecord) + assert metadata[ORIGINAL_SOURCE_METADATA_FIELD]["Plate"] == "before" + assert tuple(parser.calls) == calls + with pytest.raises(TypeError): + metadata[ORIGINAL_SOURCE_METADATA_FIELD]["Plate"] = "invalid" + unknown = "A02_s001_w1_z001_t001.tif" + assert context.metadata_for_path(unknown)["well"] == "A02" + assert parser.calls[-1] == unknown + assert snapshot(cache, source_projection, parser) is context + entry = next(iter(cache.source_resolution_snapshots.values())) + assert entry.projection is source_projection + assert entry.context.parser is parser + + +def test_direct_projection_context_remains_live(): + nested = {"Plate": "before"} + parser = CountingParser() + context = SourcePatternResolutionContext.from_projection( + parser=parser, + projection=projection({ORIGINAL_SOURCE_METADATA_FIELD: nested}), + ) + assert ( + context.metadata_for_path(PATH)[ORIGINAL_SOURCE_METADATA_FIELD]["Plate"] + == "before" + ) + nested["Plate"] = "after" + assert ( + context.metadata_for_path(PATH)[ORIGINAL_SOURCE_METADATA_FIELD]["Plate"] + == "after" + ) + assert parser.calls == [PATH, PATH] + + +def test_snapshot_replacement_tracks_projection_parser_semantics_and_rules(): + cache = RuntimeSourceBindingContextCache() + parser = CountingParser() + source_projection = projection({}) + original = snapshot(cache, source_projection, parser) + parser.pattern_format = "9" + changed_parser = snapshot(cache, source_projection, parser) + assert changed_parser is not original + assert original.metadata_for_path(PATH)["site"] == 1 + assert changed_parser.metadata_for_path(PATH)["site"] == 9 + replaced_projection = snapshot(cache, projection({"site": 7}), parser) + assert replaced_projection.metadata_for_path(PATH)["site"] == 7 + replaced_parser = snapshot(cache, source_projection, CountingParser()) + assert replaced_parser is not original + assert replaced_parser.metadata_for_path(PATH)["site"] == 1 + rules = ( + MetadataExtractionRule( + source=MetadataSource.FILE_NAME, pattern=r"(?PA01)" + ), + ) + changed_rules = snapshot(cache, source_projection, parser, rules) + assert changed_rules is not changed_parser + assert ( + changed_rules.metadata_for_path(PATH)[ORIGINAL_SOURCE_METADATA_FIELD]["Plate"] + == "A01" + ) + + +def test_matched_set_preserves_resolved_record_behavior_and_precedence(): + parser = CountingParser() + context = snapshot( + RuntimeSourceBindingContextCache(), projection({"site": None}), parser + ) + matched = SourceBindingMatchedImageSet.from_plan( + bindings=(), + match_plan=None, + source_context=context, + identity_policy=SourceImageSetIdentityPolicy(), + ) + calls = tuple(parser.calls) + assert ( + matched.source_metadata_by_path[PATH] is context.source_metadata_by_path[PATH] + ) + assert matched.metadata_for_path(PATH)["site"] == 1 + assert tuple(parser.calls) == calls + + +def test_virtual_positions_remain_distinct_with_shared_physical_address(): + other = "A01_s002_w1_z001_t001.tif" + source_projection = VirtualWorkspaceSourceProjection( + source_refs_by_virtual_path={ + PATH: SourcePixelRef("disk", "/source/shared.tif"), + other: SourcePixelRef("disk", "/source/shared.tif"), + }, + source_metadata_by_path=MappingProxyType( + {PATH: {"site": 1}, other: {"site": 2}} + ), + ) + context = snapshot( + RuntimeSourceBindingContextCache(), source_projection, CountingParser() + ) + assert context.virtual_paths_for_source("/source/shared.tif") == (PATH, other) + assert context.metadata_for_path(PATH)["site"] == 1 + assert context.metadata_for_path(other)["site"] == 2 + + +def test_known_empty_record_remains_none_without_repeated_parsing(): + parser = CountingParser() + source_projection = VirtualWorkspaceSourceProjection( + source_refs_by_virtual_path={"opaque": SourcePixelRef("disk", "opaque")}, + source_metadata_by_path={}, + ) + context = snapshot(RuntimeSourceBindingContextCache(), source_projection, parser) + calls = tuple(parser.calls) + assert context.metadata_for_path("opaque") is None + assert context.metadata_for_path("opaque") is None + assert tuple(parser.calls) == calls + + +def test_snapshot_rejects_nested_values_outside_existing_metadata_grammar(): + with pytest.raises(TypeError, match="Source metadata scalar values"): + snapshot( + RuntimeSourceBindingContextCache(), + projection({"nested": {"unsupported": {"deep": 1}}}), + CountingParser(), + ) + + +def test_declared_and_resolved_records_preserve_family_value_identity(): + declared = DeclaredSourceMetadataRecord.from_mapping({"site": 1, "well": "A01"}) + resolved = ResolvedSourceMetadataRecord.from_mapping({"site": 1, "well": "A01"}) + assert declared == resolved + assert hash(declared) == hash(resolved) + assert hash(declared) == hash((declared.fields,)) + assert declared != DeclaredSourceMetadataRecord.from_mapping( + {"site": 2, "well": "A01"} + ) + nested = {ORIGINAL_SOURCE_METADATA_FIELD: {"Plate": "A"}} + with pytest.raises(TypeError): + hash(DeclaredSourceMetadataRecord.from_mapping(nested)) + with pytest.raises(TypeError): + hash(ResolvedSourceMetadataRecord.from_mapping(nested)) + + +def test_snapshot_owns_position_and_projection_map_views(): + original_ref = SourcePixelRef("disk", "/source/original.tif") + refs = {PATH: original_ref} + positions = { + PATH: SourcePlaneProjection( + address=OpenHCSPlaneAddress.from_values("A01", 1, 1, 1, 1), + ref=original_ref, + source_alias="original", + ) + } + original_projection = positions[PATH] + source_projection = VirtualWorkspaceSourceProjection( + source_refs_by_virtual_path=refs, + source_metadata_by_path={PATH: {}}, + source_projections_by_virtual_path=positions, + ) + context = snapshot( + RuntimeSourceBindingContextCache(), source_projection, CountingParser() + ) + refs[PATH] = SourcePixelRef("disk", "/source/replaced.tif") + positions.clear() + assert context.source_paths_by_virtual_path[PATH] == "/source/original.tif" + assert context.source_projections_by_virtual_path[PATH] is original_projection + with pytest.raises(TypeError): + context.source_projections_by_virtual_path[PATH] = original_projection + + +def test_resolved_direct_constructor_owns_deep_immutable_invariant(): + nested = {"Plate": "before"} + resolved = ResolvedSourceMetadataRecord(((ORIGINAL_SOURCE_METADATA_FIELD, nested),)) + nested["Plate"] = "after" + assert resolved[ORIGINAL_SOURCE_METADATA_FIELD]["Plate"] == "before" + with pytest.raises(TypeError): + resolved[ORIGINAL_SOURCE_METADATA_FIELD]["Plate"] = "invalid" + with pytest.raises(TypeError, match="Source metadata scalar values"): + ResolvedSourceMetadataRecord((("nested", {"unsupported": {"deep": 1}}),)) + + +@pytest.mark.parametrize("context_owned", (False, True)) +def test_warmed_cache_transport_reconstructs_all_derived_defaults(context_owned): + processing_context = ProcessingContext(axis_id="A01") + cache = ( + processing_context.runtime_source_binding_context_cache + if context_owned + else RuntimeSourceBindingContextCache() + ) + parser = CountingParser() + source_projection = projection({ORIGINAL_SOURCE_METADATA_FIELD: {"Plate": "A"}}) + context = snapshot(cache, source_projection, parser) + cache.normalized_source_metadata(source_projection.source_metadata_by_path) + assert cache.source_resolution_snapshots + assert cache.source_metadata_by_mapping_identity + restored_owner = pickle.loads( + pickle.dumps(processing_context if context_owned else cache) + ) + restored = ( + restored_owner.runtime_source_binding_context_cache + if context_owned + else restored_owner + ) + if context_owned: + assert restored_owner.axis_id == "A01" + assert restored == RuntimeSourceBindingContextCache() + rebuilt = snapshot(restored, source_projection, parser) + assert rebuilt is not context + assert rebuilt.metadata_for_path(PATH) == context.metadata_for_path(PATH) + + +def test_durable_workspace_mapping_still_runs_selector_parser_and_rule_fallbacks(): + from openhcs.core.source_metadata import DurableSourceMetadata, SourceMetadataRecord + + metadata = DurableSourceMetadata.from_mapping({"site": 8, "literal": "kept"}) + parser = CountingParser() + context = SourcePatternResolutionContext.from_sources( + parser=parser, + source_paths_by_virtual_path={PATH: "/source/image.tif"}, + source_metadata_by_path={PATH: metadata}, + metadata_rules=( + MetadataExtractionRule( + source=MetadataSource.FILE_NAME, pattern=r"(?PA01)" + ), + ), + ) + assert not isinstance(metadata, SourceMetadataRecord) + assert isinstance( + context.source_metadata_by_path[PATH], DeclaredSourceMetadataRecord + ) + resolved = context.metadata_for_path(PATH) + assert resolved["site"] == 8 + assert resolved["well"] == "A01" + assert resolved["literal"] == "kept" + assert resolved[ORIGINAL_SOURCE_METADATA_FIELD]["Plate"] == "A01" + assert parser.calls == [PATH] diff --git a/tests/unit/test_runtime_stack_cache_lifetime.py b/tests/unit/test_runtime_stack_cache_lifetime.py index 78470ea371..f735926289 100644 --- a/tests/unit/test_runtime_stack_cache_lifetime.py +++ b/tests/unit/test_runtime_stack_cache_lifetime.py @@ -38,7 +38,7 @@ def test_release_drops_all_cached_views_and_allows_reuse(context_owned: bool) -> assert all(cache.get(entry, memory_type="numpy") is None for entry in paths) replacement = np.zeros((1, 8, 8), dtype=np.uint16) cache.store(paths[0], memory_type="numpy", stack=replacement) - assert cache.get(paths[0], memory_type="numpy").stack is replacement + assert cache.get(paths[0], memory_type="numpy") is replacement def test_context_image_cache_release_preserves_runtime_artifacts_and_observations() -> ( diff --git a/tests/unit/test_runtime_value_store.py b/tests/unit/test_runtime_value_store.py index d5535ffb0b..d8c00482c5 100644 --- a/tests/unit/test_runtime_value_store.py +++ b/tests/unit/test_runtime_value_store.py @@ -215,7 +215,7 @@ def test_store_transport_excludes_derived_caches_and_retains_records(): assert restored.revision == store.revision assert len(restored) == len(store) == 1 assert ( - restored.observed_values[0].value.data.row_mappings() + restored.observed_values[0].data.row_mappings() == value.data.row_mappings() ) assert ( @@ -572,9 +572,12 @@ def test_runtime_artifact_query_from_dynamic_input_plan_matches_discovered_group ) assert isinstance(query.target, RuntimeArtifactDynamicComponentTarget) + value = _runtime_value(path="/memory/measurements_wDAPI.pkl") assert query.matches( StoredRuntimeValue( - value=_runtime_value(path="/memory/measurements_wDAPI.pkl"), + key=value.key, + data=value.data, + materialization_source_metadata=value.materialization_source_metadata, location=RuntimeArtifactLocation( path="/memory/measurements_wDAPI.pkl", backend="memory", @@ -818,7 +821,13 @@ def test_runtime_artifact_input_projection_transposes_producer_stack_axis() -> N None, ) store.record( - RuntimeValue.normalize(group_plan, payload, axis_id="A01"), + RuntimeValue.normalize_for_execution_scope( + group_plan, + payload, + execution_scope=RuntimeExecutionAxisScope.from_raw( + "A01", component=AllComponents.CHANNEL, value=channel, + ), + ), path=group_plan.path, backend="memory", ) @@ -848,6 +857,14 @@ def test_runtime_artifact_input_projection_transposes_producer_stack_axis() -> N backend="memory", ) + candidates = runtime_input.candidate_execution_scopes( + store, + ComponentGroupScope.dynamic(AllComponents.SITE), + variable_components=ComponentSet((AllComponents.CHANNEL,)), + ) + assert tuple(scope.value_text for scope in candidates) == ("1", "2", "3") + assert all(scope.fixed_component_values == () for scope in candidates) + payload = runtime_input.composed_value(runtime_input.records(store)) np.testing.assert_array_equal( @@ -861,6 +878,135 @@ def test_runtime_artifact_input_projection_transposes_producer_stack_axis() -> N ) +def test_artifact_candidate_scopes_preserve_projected_site_time_correlation() -> None: + path = "/memory/processed_pixels.pkl" + variables = (AllComponents.SITE, AllComponents.TIMEPOINT) + output_plan = ArtifactOutputPlan( + name="image", path=path, artifact_type=ImageArtifactType, + variable_components=variables, + ) + storage_plan = ArtifactInputPlan( + name="image", path=path, artifact_type=ImageArtifactType, + variable_components=variables, + ) + payload = ImagePayloadMetadata( + plane_axis=RuntimePlaneAxis.RUNTIME_SLICE, + source_image_provenance_planes=SourceImageProvenancePlanes.from_components( + paths=("/source/original_first.tif", "/source/original_second.tif"), + component_metadata=( + {"site": "1", "timepoint": "3"}, + {"site": "2", "timepoint": "4"}, + ), + ), + ).payload_with( + np.stack((np.full((2, 2), 17.0), np.full((2, 2), 29.0))), + np.asarray([[[True, False], [False, True]], [[False, True], [True, False]]]), + ) + store = RuntimeValueStore() + store.record(RuntimeValue.normalize(output_plan, payload, axis_id="A01"), + path=path, backend="memory") + edge = _runtime_input_edge( + storage_plan, + invocation_scope=ComponentGroupScope.dynamic(AllComponents.SITE), + producer_selection_scope=ComponentGroupScope.ungrouped(), + component_scopes=( + ComponentGroupScope.dynamic(AllComponents.SITE), + ComponentGroupScope.from_raw(("3",), component=AllComponents.TIMEPOINT), + ), + consumer_variable_components=(), + ) + runtime_input = RuntimeArtifactInput( + edge_plan=edge, backend="memory", + axis_scope=RuntimeExecutionAxisScope.from_raw("A01", component=None, value=None), + ) + candidates = runtime_input.candidate_execution_scopes( + store, ComponentGroupScope.dynamic(AllComponents.SITE), + variable_components=ComponentSet(), + ) + (coordinates,) = tuple(candidates) + assert coordinates.value_text == "1" + assert coordinates.fixed_component_values == ((AllComponents.TIMEPOINT, "3"),) + assert candidates[coordinates] == path + selected = replace(runtime_input, axis_scope=coordinates).resolve_value(store) + np.testing.assert_array_equal(image_payload_data(selected), np.full((2, 2), 17.0)) + np.testing.assert_array_equal(selected.mask, payload.mask[0]) + + +def test_artifact_candidate_scopes_keep_actual_producer_group_as_fixed_context() -> None: + path = "/memory/produced_pixels.pkl" + output_plan = ArtifactOutputPlan( + name="image", path=path, artifact_type=ImageArtifactType, + group_component=AllComponents.CHANNEL, group_keys=("1",), + ) + storage_plan = ArtifactInputPlan( + name="image", path=path, artifact_type=ImageArtifactType, + group_component=AllComponents.CHANNEL, group_keys=("1",), + ) + payload = ImagePayloadMetadata( + source_path="/source/old_filename_w9.tif", + source_component_metadata={"site": "2", "timepoint": "3", "channel": "1", "z_index": "1"}, + ).payload_with(np.full((2, 2), 17.0), None) + store = RuntimeValueStore() + record = store.record( + RuntimeValue.normalize_for_execution_scope( + output_plan, payload, + execution_scope=RuntimeExecutionAxisScope.from_raw( + "A01", component=AllComponents.CHANNEL, value="1", + fixed_component_values=((AllComponents.SITE, "2"), (AllComponents.TIMEPOINT, "3"), (AllComponents.Z_INDEX, "1")), + ), + ), + path=path, backend="memory", + ) + runtime_input = RuntimeArtifactInput( + edge_plan=_runtime_input_edge( + storage_plan, + invocation_scope=ComponentGroupScope.dynamic(AllComponents.SITE), + producer_selection_scope=storage_plan.producer_group_scope(), + component_scopes=(ComponentGroupScope.dynamic(AllComponents.SITE),), + consumer_variable_components=(), + ), + axis_scope=RuntimeExecutionAxisScope.from_raw("A01", component=None, value=None), + backend="memory", + ) + candidates = runtime_input.candidate_execution_scopes( + store, ComponentGroupScope.dynamic(AllComponents.SITE), + variable_components=ComponentSet(), + ) + (coordinates,) = tuple(candidates) + assert coordinates.value_text == "2" + assert dict(coordinates.fixed_component_values) == { + AllComponents.CHANNEL: "1", AllComponents.TIMEPOINT: "3", AllComponents.Z_INDEX: "1", + } + selected = replace(runtime_input, axis_scope=coordinates).records(store) + assert len(selected) == 1 + assert selected[0] is record + + second_payload = ImagePayloadMetadata( + source_path="/source/another_original.tif", + source_component_metadata={"site": "2", "timepoint": "3", "channel": "1", "z_index": "2"}, + ).payload_with(np.full((2, 2), 29.0), None) + second_record = store.record( + RuntimeValue.normalize_for_execution_scope( + output_plan, second_payload, + execution_scope=RuntimeExecutionAxisScope.from_raw( + "A01", component=AllComponents.CHANNEL, value="1", + fixed_component_values=((AllComponents.SITE, "2"), (AllComponents.TIMEPOINT, "3"), (AllComponents.Z_INDEX, "2")), + ), + ), + path=path, backend="memory", + ) + candidates = runtime_input.candidate_execution_scopes( + store, ComponentGroupScope.dynamic(AllComponents.SITE), + variable_components=ComponentSet(), + ) + assert len(candidates) == 2 + selected_records = tuple( + replace(runtime_input, axis_scope=scope).records(store) + for scope in candidates + ) + assert selected_records == ((record,), (second_record,)) + + def test_runtime_artifact_input_projection_ignores_scalar_pixel_contributors() -> None: path = "/memory/scalar_image.pkl" output_plan = ArtifactOutputPlan( @@ -1007,6 +1153,10 @@ def test_runtime_artifact_input_projection_collapses_excluded_singleton_axis() - backend="memory", ) + projected_values = runtime_input.projected_values(store) + assert all(type(value) is RuntimeValue for value in projected_values) + assert all(image_payload_data(value.data).shape == (2, 2) for value in projected_values) + assert all(image_payload_data(record.data).shape == (1, 2, 2) for record in store.values()) payload = runtime_input.resolve_value(store) assert image_payload_data(payload).shape == (2, 2, 2) @@ -1219,7 +1369,7 @@ def test_runtime_artifact_input_projection_keeps_equal_keys_component_typed(): assert len(records) == 1 assert records[0].key.scope.component is AllComponents.SITE - np.testing.assert_array_equal(records[0].value.data, np.full((2, 2), 1.0)) + np.testing.assert_array_equal(records[0].data, np.full((2, 2), 1.0)) def test_runtime_artifact_input_projection_uses_compiled_group_for_plane_scope(): @@ -1560,6 +1710,165 @@ def test_declared_paired_channel_label_input_matches_image_set_context(): assert runtime_input.resolve_value(store).name == "Nuclei" +def _grouped_label_input_with_distinct_consumer_channel(): + path = "/memory/Cells_channel_0.pkl" + storage_plan = ArtifactInputPlan( + name="Cells", + path=path, + artifact_type=ObjectLabelsArtifactType, + group_component=AllComponents.CHANNEL, + group_keys=("0",), + paths_by_group={"0": path}, + source_step_id=20, + ) + output_plan = ArtifactOutputPlan( + name=storage_plan.name, + path=path, + artifact_type=storage_plan.artifact_type, + group_component=storage_plan.group_component, + group_keys=storage_plan.group_keys, + paths_by_group=storage_plan.paths_by_group, + ).for_group("0") + value = RuntimeValue.normalize_for_execution_scope( + output_plan, + ObjectLabelSet( + name="Cells", + variant_data=ObjectLabelVariantData(labels=np.ones((2, 2), dtype=np.uint16)), + ), + execution_scope=RuntimeExecutionAxisScope.from_raw( + "W001", component=AllComponents.CHANNEL, value="0", + fixed_component_values=( + (AllComponents.SITE, "1"), (AllComponents.TIMEPOINT, "1"), + ), + ), + ) + store = RuntimeValueStore() + record = store.record(value, path=path, backend="memory") + runtime_input = RuntimeArtifactInput( + edge_plan=_runtime_input_edge( + storage_plan, + invocation_scope=ComponentGroupScope.ungrouped(), + producer_selection_scope=storage_plan.producer_group_scope(), + component_scopes=(), + consumer_variable_components=(AllComponents.Z_INDEX,), + ), + axis_scope=RuntimeExecutionAxisScope.from_raw( + "W001", component=None, value=None, + fixed_component_values=( + (AllComponents.SITE, "1"), (AllComponents.CHANNEL, "2"), + (AllComponents.TIMEPOINT, "1"), + ), + ), + backend="memory", + ) + return store, record, runtime_input + + +def test_exact_producer_group_does_not_constrain_consumer_source_channel(): + store, record, runtime_input = _grouped_label_input_with_distinct_consumer_channel() + + assert runtime_input.records(store) == (record,) + assert runtime_input.resolve_value(store) is record.data + candidates = runtime_input.candidate_execution_scopes( + store, ComponentGroupScope.ungrouped(), + variable_components=ComponentSet((AllComponents.Z_INDEX,)), + ) + (scope,) = candidates + # Discovery still owns the producer's semantic channel, rather than adopting + # a later consumer's independently selected source-image channel. + assert dict(scope.fixed_component_values) == { + AllComponents.SITE: "1", AllComponents.CHANNEL: "0", + AllComponents.TIMEPOINT: "1", + } + + +@pytest.mark.parametrize("component", [AllComponents.SITE, AllComponents.TIMEPOINT]) +def test_exact_producer_group_preserves_shared_fixed_context_constraints(component): + store, _record, runtime_input = _grouped_label_input_with_distinct_consumer_channel() + fixed_values = dict(runtime_input.axis_scope.fixed_component_values) + fixed_values[component] = "2" + wrong_context = replace( + runtime_input, + axis_scope=replace( + runtime_input.axis_scope, fixed_component_values=tuple(fixed_values.items()), + ), + ) + with pytest.raises(RuntimeError, match="Missing RuntimeValueStore record"): + wrong_context.records(store) + + +@pytest.mark.parametrize("mismatch", ["group", "well", "path", "fixed-z"]) +def test_exact_producer_group_rejects_other_producer_or_fixed_plane(mismatch): + _store, record, runtime_input = _grouped_label_input_with_distinct_consumer_channel() + scope = record.key.scope + path = record.location.path + if mismatch == "group": + scope = replace(scope, value="1") + elif mismatch == "well": + scope = replace(scope, axis_id="W002") + elif mismatch == "path": + path = "/memory/other/Cells_channel_0.pkl" + else: + scope = RuntimeExecutionAxisScope.from_raw( + scope.axis_id, component=scope.component, value=scope.value, + fixed_component_values=(*scope.fixed_component_values, (AllComponents.Z_INDEX, "2")), + ) + runtime_input = replace( + runtime_input, + axis_scope=RuntimeExecutionAxisScope.from_raw( + runtime_input.axis_scope.axis_id, + component=runtime_input.axis_scope.component, + value=runtime_input.axis_scope.value, + fixed_component_values=( + *runtime_input.axis_scope.fixed_component_values, + (AllComponents.Z_INDEX, "1"), + ), + ), + ) + store = RuntimeValueStore() + store.record( + replace(record, key=replace(record.key, scope=scope)), + path=path, backend=record.location.backend, + ) + with pytest.raises(RuntimeError, match="Missing RuntimeValueStore record"): + runtime_input.records(store) + + +def test_different_producer_group_axis_preserves_fixed_source_channel_constraint(): + _store, record, runtime_input = _grouped_label_input_with_distinct_consumer_channel() + # SITE is now the selected producer group. CHANNEL remains a genuine fixed + # image context and cannot use the selected-group exemption. + scope = RuntimeExecutionAxisScope.from_raw( + "W001", component=AllComponents.SITE, value="1", + fixed_component_values=( + (AllComponents.CHANNEL, "0"), (AllComponents.TIMEPOINT, "1"), + ), + ) + storage_plan = replace( + runtime_input.edge_plan.storage_plan, + group_component=AllComponents.SITE, group_keys=("1",), + paths_by_group={"1": record.location.path}, + ) + runtime_input = replace( + runtime_input, + edge_plan=replace( + runtime_input.edge_plan, + storage_plan=storage_plan, + projection=replace( + runtime_input.edge_plan.projection, + producer_selection_scope=storage_plan.producer_group_scope(), + ), + ), + ) + store = RuntimeValueStore() + store.record( + replace(record, key=replace(record.key, scope=scope)), + path=record.location.path, backend=record.location.backend, + ) + with pytest.raises(RuntimeError, match="Missing RuntimeValueStore record"): + runtime_input.records(store) + + def test_paired_channel_declaration_reaches_both_adapter_input_consumers(): store, record, runtime_input = _paired_channel_label_input() edge = runtime_input.edge_plan @@ -1598,7 +1907,7 @@ def consume_labels(image, labels): request = RuntimeInputBindingRequest( adapter=adapter, kwargs={}, current_image=np.zeros((2, 2)) ) - assert request.artifact_value(edge) is record.value.data + assert request.artifact_value(edge) is record.data @pytest.mark.parametrize("component", [AllComponents.SITE, AllComponents.Z_INDEX, AllComponents.TIMEPOINT]) @@ -1671,14 +1980,14 @@ def test_paired_channel_projection_rejects_a_different_producer_site_plane(): store, record, runtime_input = _paired_channel_label_input() edge = runtime_input.edge_plan payload = replace( - record.value.data, + record.data, source_image_provenance_planes=SourceImageProvenancePlanes.from_components( paths=("/source/site2_DNA.tif",), component_metadata=({"site": "2", "channel": "1"},), ), ) store.replace( - replace(record.value, data=payload), path=record.path, backend=record.backend + replace(record, data=payload), path=record.location.path, backend=record.location.backend ) projected_input = replace( runtime_input, @@ -1701,7 +2010,7 @@ def test_paired_channel_input_rejects_ambiguous_address_matched_contexts(): _other_store, other_record, _other_input = _paired_channel_label_input( producer_values=((AllComponents.CHANNEL, "3"),), ) - store.record(other_record.value, path=other_record.path, backend=other_record.backend) + store.record(other_record, path=other_record.location.path, backend=other_record.location.backend) with pytest.raises(RuntimeError, match="Ambiguous RuntimeValueStore records"): runtime_input.records(store) @@ -1795,8 +2104,12 @@ def test_exact_input_admits_no_shared_projected_context_constraints( ) store = RuntimeValueStore() record = store.record( - replace(original.value, key=replace(original.key, scope=producer_scope)), - path=original.path, backend=original.backend, + RuntimeValue( + key=replace(original.key, scope=producer_scope), + data=original.data, + materialization_source_metadata=original.materialization_source_metadata, + ), + path=original.location.path, backend=original.location.backend, ) source = NamedSourceBinding( alias="Reference", @@ -1951,12 +2264,14 @@ def test_runtime_value_store_merges_observed_records_from_worker_boundary(): def test_runtime_measurement_observation_axis_accepts_table_record_once(): value = _runtime_value() record = StoredRuntimeValue( - value=value, - location=RuntimeArtifactLocation( + key=value.key, + data=value.data, + materialization_source_metadata=value.materialization_source_metadata, + location=RuntimeArtifactLocation( path="/memory/measurements.pkl", backend="memory", ), - ) + ) axis = RuntimeMeasurementObservationAxis("A01") axis.accept_measurement_table(record) @@ -1964,7 +2279,7 @@ def test_runtime_measurement_observation_axis_accepts_table_record_once(): assert len(axis.measurement_tables) == 1 scoped_table = axis.measurement_tables[0] assert scoped_table.table is value.data - assert scoped_table.record_identity == record.path + assert scoped_table.record_identity == record.location.path assert scoped_table.execution_scope == record.key.scope @@ -1990,10 +2305,10 @@ def test_dynamic_input_query_distinguishes_compiled_paths_with_same_backend(): RuntimeArtifactQuery.from_input_plan( ArtifactInputPlan( name="measurements", - path=record.path, + path=record.location.path, artifact_type=MeasurementsArtifactType, group_component=AllComponents.CHANNEL, - paths_by_group={None: record.path, "DAPI": record.path}, + paths_by_group={None: record.location.path, "DAPI": record.location.path}, ), axis_id="A01", backend="memory", @@ -2058,7 +2373,7 @@ def test_dynamic_query_snapshots_address_mapping_without_mutating_source_plan(): assert store.find_matching(old_query) == (first,) paths["DAPI"] = "/second/measurements.pkl" assert plan.paths_by_group is paths - assert old_query.target.input_plan.paths_by_group["DAPI"] == first.path + assert old_query.target.input_plan.paths_by_group["DAPI"] == first.location.path assert hash(old_query) == old_hash assert old_query == same_query assert store.find_matching(old_query) == (first,) @@ -2128,10 +2443,10 @@ def test_store_transport_excludes_all_derived_lookup_caches(): query = RuntimeArtifactQuery.from_input_plan( ArtifactInputPlan( name="measurements", - path=record.path, + path=record.location.path, artifact_type=MeasurementsArtifactType, group_component=AllComponents.CHANNEL, - paths_by_group={"DAPI": record.path}, + paths_by_group={"DAPI": record.location.path}, ), axis_id="A01", backend="memory", @@ -2151,13 +2466,14 @@ def test_store_transport_excludes_all_derived_lookup_caches(): assert restored._query_caches == {} assert restored.values()[0].key == record.key assert restored.values()[0].location == record.location - assert restored.values()[0].value.data.row_mappings() == value.data.row_mappings() + assert restored.values()[0].data.row_mappings() == value.data.row_mappings() assert restored.find_matching(query) == (restored.values()[0],) assert restored.get(record.key) is restored.values()[1] assert restored.get(record.key).location == latest.location assert restored.observed_values == restored.values() assert restored.values()[0] is restored.observed_values[0] - assert restored.values()[0].value is restored.values()[1].value + assert restored.values()[0].data is restored.values()[1].data + assert restored.values()[0].key is restored.values()[1].key def test_unified_store_cache_keeps_both_query_domains_and_empty_results(): @@ -2168,7 +2484,7 @@ def test_unified_store_cache_keeps_both_query_domains_and_empty_results(): query = RuntimeArtifactQuery.from_input_plan( ArtifactInputPlan( name="measurements", - path=record.path, + path=record.location.path, artifact_type=MeasurementsArtifactType, group_component=AllComponents.CHANNEL, ), @@ -2204,7 +2520,7 @@ def test_unified_store_cache_eviction_recomputes_order_without_changing_record_a query = RuntimeArtifactQuery.from_output_plan( ArtifactOutputPlan( name="first", - path=first.path, + path=first.location.path, artifact_type=MeasurementsArtifactType, group_component=AllComponents.CHANNEL, group_keys=("DAPI",), @@ -2220,8 +2536,31 @@ def test_unified_store_cache_eviction_recomputes_order_without_changing_record_a assert recomputed == all_records assert recomputed is not all_records assert recomputed[0] is first and recomputed[1] is second - replacement = store.replace(first_value, path=first.path, backend="memory") + replacement = store.replace(first_value, path=first.location.path, backend="memory") assert cache.entries == {} assert store.find_matching(query)[0] is replacement assert store.find() == (replacement, second) assert store.find()[1] is second + + +def test_changed_stored_measurement_subject_requires_a_transient_value(): + value = _runtime_value() + store = RuntimeValueStore() + record = store.record(value, path="/memory/measurements.pkl", backend="memory") + plan = ArtifactOutputPlan( + name=value.name, artifact_type=value.artifact_type, + path="/memory/measurements.pkl", + ) + record.data.subject = MeasurementSubject(MeasurementScope.IMAGE, "NextImage") + + admitted = record.validated_for_output_plan(plan, axis_id="A01") + + assert type(admitted) is RuntimeValue + assert admitted.key.semantic_id == record.data.runtime_semantic_id + assert admitted.key != record.key + assert store.get(record.key) is record + assert record.location.path == "/memory/measurements.pkl" + assert admitted.data is record.data + assert type(StoredRuntimeValue.from_output_plan( + plan, admitted.data, execution_scope=record.key.scope, + )) is RuntimeValue diff --git a/tests/unit/test_runtime_values.py b/tests/unit/test_runtime_values.py index d89c1bde66..10fa5eb3f1 100644 --- a/tests/unit/test_runtime_values.py +++ b/tests/unit/test_runtime_values.py @@ -112,14 +112,14 @@ SourceImageIdentity, SourceImageProvenancePlanes, ) -from openhcs.core.source_image_semantics import apply_source_binding_payload from openhcs.core.source_metadata import ( + SOURCE_VOXEL_SPACING_FIELD, SOURCE_PLANE_COUNT_FIELD, SOURCE_PLANE_INDEX_FIELD, SourceVoxelSpacing, ) from openhcs.core.source_spatial_domain import SourceSpatialDomain -from openhcs.core.steps.function_runtime import ( +from openhcs.core.projected_image_output import ( DefaultImageOutputSourceContextStrategy, ) from openhcs.processing.backends.analysis.region_properties import ( @@ -2142,9 +2142,8 @@ def test_source_aligned_object_labels_replace_stale_plane_provenance() -> None: def test_source_image_loading_semantics_attaches_component_metadata() -> None: image = np.zeros((4, 5), dtype=np.uint16) - payload = apply_source_binding_payload( + payload = NamedSourceBinding(alias="DNA").apply_loaded_payload( image, - NamedSourceBinding(alias="DNA"), ImagePayloadSourceMetadataContext( SourceImageIdentity( "01_POS002_D.TIF", @@ -2301,13 +2300,12 @@ def test_declared_source_pixel_channel_axis_owns_source_spatial_domain() -> None ), ) - bound = apply_source_binding_payload( + bound = NamedSourceBinding( + alias="Color", + source_channel_axis=-1, + source_channel_counts=frozenset((3, 4)), + ).apply_loaded_payload( payload, - NamedSourceBinding( - alias="Color", - source_channel_axis=-1, - source_channel_counts=frozenset((3, 4)), - ), ImagePayloadSourceMetadataContext(SourceImageIdentity("color.tif")), ) @@ -2325,15 +2323,14 @@ def test_object_label_source_image_semantics_treats_rgb_image_as_label_plane() - ImagePayloadMetadata(source_channel_axis=-1), ) - payload = apply_source_binding_payload( + payload = NamedSourceBinding( + alias="Objects", + artifact_kind=ObjectLabelsArtifactType, + projection_role=SourceProjectionRole.SOURCE_ARTIFACT, + source_channel_axis=-1, + source_channel_counts=frozenset((3, 4)), + ).apply_loaded_payload( source, - NamedSourceBinding( - alias="Objects", - artifact_kind=ObjectLabelsArtifactType, - projection_role=SourceProjectionRole.SOURCE_ARTIFACT, - source_channel_axis=-1, - source_channel_counts=frozenset((3, 4)), - ), ImagePayloadSourceMetadataContext(SourceImageIdentity("objects.png")), ) @@ -2353,13 +2350,12 @@ def test_source_file_pixel_semantics_declare_ingestion_channel_axis( image = np.zeros((4, 5, 3), dtype=np.uint8) iio.imwrite(path, image) - payload = apply_source_binding_payload( + payload = NamedSourceBinding( + alias="Color", + source_channel_axis=-1, + source_channel_counts=frozenset((3, 4)), + ).apply_loaded_payload( iio.imread(path), - NamedSourceBinding( - alias="Color", - source_channel_axis=-1, - source_channel_counts=frozenset((3, 4)), - ), ImagePayloadSourceMetadataContext(SourceImageIdentity(str(path))), ) @@ -2394,13 +2390,12 @@ def test_source_file_pixel_semantics_allow_monochrome_without_declared_channel_a path = tmp_path / "source.png" iio.imwrite(path, np.zeros((4, 5), dtype=np.uint8)) - payload = apply_source_binding_payload( + payload = NamedSourceBinding( + alias="Color", + source_channel_axis=-1, + source_channel_counts=frozenset((3, 4)), + ).apply_loaded_payload( iio.imread(path), - NamedSourceBinding( - alias="Color", - source_channel_axis=-1, - source_channel_counts=frozenset((3, 4)), - ), ImagePayloadSourceMetadataContext(SourceImageIdentity(str(path))), ) @@ -3988,6 +3983,26 @@ def test_derived_image_payload_context_uses_source_provenance_atomically() -> No assert metadata.source_image_names == ("Grayscale",) +@pytest.mark.parametrize("invalid_owner", ("source", "output")) +def test_derived_image_context_admits_current_calibration_before_channel_axis( + invalid_owner, +): + source = ImagePayloadMetadata(source_path="/input/source.tif").payload_with( + np.zeros((4, 5), dtype=np.float32) + ) + output = ImagePayloadMetadata(source_path="/stale/output.tif").payload_with( + np.ones((4, 5), dtype=np.float32) + ) + metadata = image_payload_metadata(source if invalid_owner == "source" else output) + metadata.source_provenance.source_identity.component_metadata = { + SOURCE_VOXEL_SPACING_FIELD: "-1,1,1", + } + metadata.source_channel_axis = False + + with pytest.raises(ValueError, match="finite and positive"): + image_payload_metadata(source).derive_payload(source, output) + + def test_object_label_source_context_keeps_source_aligned_stack_planes() -> None: paths = tuple(f"/input/A01_s001_w1_z{index:03d}_t001.tif" for index in range(1, 61)) component_metadata = tuple( diff --git a/tests/unit/test_saved_source_label_plane_domain.py b/tests/unit/test_saved_source_label_plane_domain.py index ef87d36854..2e099bcff1 100644 --- a/tests/unit/test_saved_source_label_plane_domain.py +++ b/tests/unit/test_saved_source_label_plane_domain.py @@ -16,8 +16,8 @@ from openhcs.core.runtime_plane_projection import RuntimePlaneAxis, RuntimePlaneAxisValueProjection from openhcs.core.source_image_provenance import SourceImageProvenancePlanes from openhcs.core.source_metadata import SourceVoxelSpacing -from openhcs.interop.cellprofiler.runtime.artifact_binding import ( - RuntimeArtifactTypeStrategy, +from openhcs.interop.cellprofiler.runtime.output_recording import ( + CellProfilerOutputRecorder, ) from openhcs.interop.cellprofiler.runtime.function_contract_execution import CellProfilerFunctionContractExecutor from openhcs.processing.backends.cellprofiler.shape import MeasureObjectSizeShapeModule, measure_object_size_shape @@ -38,11 +38,39 @@ def _source(labels, *, axis=RuntimePlaneAxis.RUNTIME_SLICE, plane_count=None, sp def _saved_label_input(source): spec = ArtifactSpec.input("saved_labels", ObjectLabelsArtifactType, parameter_name="labels") - return RuntimeArtifactTypeStrategy.for_artifact_type(spec.artifact_type).runtime_input_value( + return CellProfilerOutputRecorder.for_artifact_type(spec.artifact_type).runtime_input_value( spec=spec, value=source ) +@pytest.mark.parametrize("axis", tuple(RuntimePlaneAxis)) +@pytest.mark.parametrize("plane_count", (1, 2)) +def test_explicit_object_projection_preserves_axis_without_acquisition_provenance( + axis, plane_count, +): + labels = np.ones((plane_count, 6, 7), dtype=np.int32) + source = ImagePayloadMetadata(plane_axis=axis).payload_with(labels) + projection = RuntimePlaneAxisValueProjection.preserve( + axis=axis, axis_size=plane_count, + ) + payload = SourceImageObjectLabelBuildRequest( + image=source, labels=labels, plane_projection=projection, + ).payload() + + assert payload.plane_axis is axis + assert payload.domain.declared_object_id_domains == ((1,),) * plane_count + assert payload.source_provenance == source.metadata.source_provenance + np.testing.assert_array_equal(payload.labels, labels) + other_axis = next(member for member in RuntimePlaneAxis if member is not axis) + with pytest.raises(ValueError, match="conflicts with the source-image axis"): + SourceImageObjectLabelBuildRequest( + image=source, labels=labels, + plane_projection=RuntimePlaneAxisValueProjection.preserve( + axis=other_axis, axis_size=plane_count, + ), + ).payload() + + @pytest.mark.parametrize("axis", tuple(RuntimePlaneAxis)) def test_original_artifact_admission_and_full_stack_shape_keep_2d_planes(axis): labels = np.zeros((2, 8, 9), dtype=np.int32) @@ -51,7 +79,7 @@ def test_original_artifact_admission_and_full_stack_shape_keep_2d_planes(axis): source = _source(labels, axis=axis) source_bytes = labels.tobytes() spec = ArtifactSpec.input("saved_labels", ObjectLabelsArtifactType, parameter_name="labels") - value = RuntimeArtifactTypeStrategy.for_artifact_type(spec.artifact_type).runtime_input_value( + value = CellProfilerOutputRecorder.for_artifact_type(spec.artifact_type).runtime_input_value( spec=spec, value=source ) assert value.domain.scope is ObjectLabelDomainScope.PLANE @@ -265,7 +293,9 @@ def test_explicit_plane_domain_still_requires_projection_and_rejects_global_coun @pytest.mark.parametrize("axis", tuple(RuntimePlaneAxis)) def test_generic_output_context_uses_execution_projection_not_image_storage_axis(axis): - from openhcs.core.steps.function_runtime import NumpyArrayObjectLabelOutputValueContextStrategy + from openhcs.core.projected_image_output import ( + NumpyArrayObjectLabelOutputValueContextStrategy, +) labels = np.zeros((2, 6, 7), dtype=np.int32) labels[0, 1:3, 2:4] = 29 diff --git a/tests/unit/test_selected_plane_stream_materialization.py b/tests/unit/test_selected_plane_stream_materialization.py index e10febdd45..77afa3fe8e 100644 --- a/tests/unit/test_selected_plane_stream_materialization.py +++ b/tests/unit/test_selected_plane_stream_materialization.py @@ -1,5 +1,7 @@ """Selected image declarations must materialize with their exact source identity.""" +from openhcs.core.artifacts import ImageArtifactType + from pathlib import Path from dataclasses import dataclass, fields, replace from multiprocessing.shared_memory import SharedMemory @@ -39,10 +41,7 @@ from openhcs.core.runtime_spatial_graph import SpatialGraph, SpatialGraphNode from openhcs.core.source_image_provenance import SourceImageProvenancePlanes from openhcs.core.source_metadata import SourceVoxelSpacing -from openhcs.core.steps.function_runtime import ( - ImageFunctionOutputContextStrategy, - FunctionOutputContextStrategy, -) + from openhcs.core.steps.function_artifact_materialization import ( PersistentArtifactMaterializationTargetPlan, materialize_artifact_outputs, @@ -97,7 +96,7 @@ def test_public_selected_checkpoint_materializes_and_streams_without_storage_axe source = _source_stack(axis) pixels = np.arange(56, dtype=np.uint16).reshape(1, 7, 8) selected = SelectedPlaneImageOutput(pixels, (1,)) - payload = ImageFunctionOutputContextStrategy().contextualize( + payload = ImageArtifactType.contextualize_output( source, selected, None, @@ -221,7 +220,7 @@ def with_data(self, data): selected = DeclaredCrop(np.arange(112).reshape(2, 7, 8)) calls.clear() - payload = ImageFunctionOutputContextStrategy().contextualize( + payload = ImageArtifactType.contextualize_output( _source_stack(RuntimePlaneAxis.SOURCE_BINDING), selected, None, @@ -255,7 +254,7 @@ def test_all_public_declared_outputs_persist_with_selected_qa_streams( cell = NeuriteOutgrowthCellResult( 1, 1, 0.0, 0, 0.0, 0.0, 0.0, 0, 0.0, 1.0, 0.0, False ) - selected = ImageFunctionOutputContextStrategy().contextualize( + selected = ImageArtifactType.contextualize_output( source, SelectedPlaneImageOutput((labels[1] > 0).astype(np.uint8)[None], (1,)), None, @@ -313,7 +312,7 @@ def test_all_public_declared_outputs_persist_with_selected_qa_streams( output_dir=tmp_path / "images", ) for output, value in zip(plans, values, strict=True): - value = FunctionOutputContextStrategy.for_output_plan(output).contextualize( + value = (ImageArtifactType if output is None else output.artifact_type).contextualize_output( source, value, output, diff --git a/tests/unit/test_source_binding_workspace.py b/tests/unit/test_source_binding_workspace.py index 32436c2527..94c7c0c6c5 100644 --- a/tests/unit/test_source_binding_workspace.py +++ b/tests/unit/test_source_binding_workspace.py @@ -12,7 +12,7 @@ from openhcs.core.source_binding_workspace import SourceBindingWorkspaceProjector from openhcs.core.runtime_tabular_values import FieldSpec from openhcs.core.source_metadata import ( - SourceMetadataRoleView, + SourceMetadataFields, SourceVoxelSpacing, SourceVoxelSpacingUnit, SOURCE_VOXEL_SPACING_FIELD, @@ -330,9 +330,7 @@ def test_source_binding_workspace_projector_assigns_selector_channels(tmp_path): } assert all("image_type" not in source for source in serialized_sources) filter_paths_by_alias = { - str(source["source_alias"]): SourceMetadataRoleView( - source - ).source_filter_paths() + str(source["source_alias"]): SourceMetadataFields.source_filter_paths(source) for source in serialized_sources } assert filter_paths_by_alias == { @@ -386,7 +384,7 @@ def test_source_binding_workspace_projects_semantic_identity_after_raw_selection assert projection.address.value_for(AllComponents.CHANNEL) == "MCP_DNA" original_metadata = dict( - SourceMetadataRoleView(projection.source_metadata).original_items() + SourceMetadataFields.original_items(projection.source_metadata) ) assert original_metadata[AllComponents.CHANNEL.value] == "1" @@ -609,7 +607,7 @@ def test_group_address_preserves_distinct_source_well_as_literal_metadata(tmp_pa source_metadata = next(iter(metadata[FIELDS.SOURCE_METADATA].values())) assert source_metadata["well"] == "Sequence1" - assert dict(SourceMetadataRoleView(source_metadata).original_items()) == { + assert dict(SourceMetadataFields.original_items(source_metadata)) == { "Well": "A01", "FrameNumber": "0000", "Run": "Sequence1", @@ -788,7 +786,7 @@ def test_order_source_sets_join_imported_metadata_across_aliases(tmp_path): assert {projection.source_alias for projection in projections} == {"DNA", "Actin"} for projection in projections: original = dict( - SourceMetadataRoleView(projection.source_metadata).original_items() + SourceMetadataFields.original_items(projection.source_metadata) ) assert original["Compound"] == "DMSO" assert original["Dose"] == "0" @@ -912,7 +910,7 @@ def test_metadata_source_sets_propagate_imported_metadata(tmp_path): assert len(projections) == 2 assert all( - dict(SourceMetadataRoleView(item.source_metadata).original_items())["Compound"] + dict(SourceMetadataFields.original_items(item.source_metadata))["Compound"] == "DrugA" for item in projections ) @@ -958,7 +956,7 @@ def test_imported_metadata_duplicate_join_uses_first_matching_row(tmp_path): assert metadata["Site"] == "1" assert metadata["Compound"] == "First" - original = dict(SourceMetadataRoleView(metadata).original_items()) + original = dict(SourceMetadataFields.original_items(metadata)) assert original["Site"] == "1" assert original["Plate"] == "20585" assert original["Well"] == "A01" @@ -1006,7 +1004,7 @@ def test_imported_metadata_later_stage_overrides_extracted_field(tmp_path): assert metadata["Plate"] == "plate_1" assert metadata["Dose"] == "0" assert projection.address.value_for(AllComponents.WELL) == "A01" - original = dict(SourceMetadataRoleView(metadata).original_items()) + original = dict(SourceMetadataFields.original_items(metadata)) assert original["Plate"] == "plate_1" assert original["Well"] == "A01" assert original["ChannelNumber"] == "2" @@ -1058,7 +1056,7 @@ def test_imported_metadata_coerces_join_and_payload_values_through_declared_type filemanager=_filemanager(), ) projection = projection_set.projections[0] - original = dict(SourceMetadataRoleView(projection.source_metadata).original_items()) + original = dict(SourceMetadataFields.original_items(projection.source_metadata)) assert original["Site"] == 5 assert original["Dose"] == 0.25 @@ -1072,7 +1070,7 @@ def test_imported_metadata_coerces_join_and_payload_values_through_declared_type pixel_size=1.0, ) serialized = next(iter(metadata[FIELDS.SOURCE_METADATA].values())) - serialized_original = dict(SourceMetadataRoleView(serialized).original_items()) + serialized_original = dict(SourceMetadataFields.original_items(serialized)) assert serialized_original["Dose"] == 0.25 assert serialized_original["Frame"] == 7 @@ -1161,7 +1159,7 @@ def test_imported_metadata_skips_source_sets_with_partial_join_identity(tmp_path ) assert "Compound" not in dict( - SourceMetadataRoleView(projection.source_metadata).original_items() + SourceMetadataFields.original_items(projection.source_metadata) ) @@ -1285,7 +1283,7 @@ def test_source_bindings_reinitialization_resolves_current_imported_metadata(tmp ) ) assert ( - dict(SourceMetadataRoleView(first_metadata).original_items())["Compound"] + dict(SourceMetadataFields.original_items(first_metadata))["Compound"] == "First" ) @@ -1300,7 +1298,7 @@ def test_source_bindings_reinitialization_resolves_current_imported_metadata(tmp assert metadata_path.read_bytes() != first_payload assert ( - dict(SourceMetadataRoleView(second_metadata).original_items())["Compound"] + dict(SourceMetadataFields.original_items(second_metadata))["Compound"] == "Second" ) diff --git a/tests/unit/test_source_bindings.py b/tests/unit/test_source_bindings.py index 34d6667e5a..5ea5a6c0c5 100644 --- a/tests/unit/test_source_bindings.py +++ b/tests/unit/test_source_bindings.py @@ -32,7 +32,6 @@ LazyStepSourceBindingsConfig, PipelineConfig, ) -from openhcs.core.pipeline.step_snapshot import StepSnapshot from openhcs.core.runtime_tabular_values import FieldSpec from openhcs.core.source_binding_selection import ( SourceBindingCandidateMatcher, @@ -57,7 +56,6 @@ SourceBindingMatchMethod, SourceBindingMatchPlan, SourceBindingOrigin, - SourceBindingRuntimeContext, SourceBindingsConfig, SourceFilterClause, SourceFilterMatchType, @@ -430,22 +428,16 @@ def test_step_source_bindings_inherit_plate_source_bindings_for_snapshot(): exclude_params=["func"], ) ObjectStateRegistry.register(step_state, _skip_snapshot=True) - snapshot = StepSnapshot( - index=0, - scope_id=step_state.scope_id, - step=step_state.to_saved_resolved_object(), - ) + snapshot = step_state.to_saved_resolved_object() finally: ObjectStateRegistry.clear() - assert snapshot.step.source_bindings.bindings == (binding,) - assert snapshot.step.source_bindings.source_stack_components == ( - AllComponents.Z_INDEX, - ) - assert snapshot.step.source_bindings.grouping_metadata_fields == ("Plate",) - assert snapshot.step.source_bindings.metadata_fields == metadata_fields + assert snapshot.source_bindings.bindings == (binding,) + assert snapshot.source_bindings.source_stack_components == (AllComponents.Z_INDEX,) + assert snapshot.source_bindings.grouping_metadata_fields == ("Plate",) + assert snapshot.source_bindings.metadata_fields == metadata_fields compiled = CompiledSourceBindingPlan.from_config( - snapshot.step.source_bindings, + snapshot.source_bindings, ) assert compiled.bindings == (binding,) assert compiled.source_stack_components == (AllComponents.Z_INDEX,) @@ -517,17 +509,13 @@ def test_enabled_step_source_bindings_compile_inherited_bindings(): exclude_params=["func"], ) ObjectStateRegistry.register(step_state, _skip_snapshot=True) - snapshot = StepSnapshot( - index=0, - scope_id=step_state.scope_id, - step=step_state.to_saved_resolved_object(), - ) + snapshot = step_state.to_saved_resolved_object() finally: ObjectStateRegistry.clear() - assert snapshot.step.source_bindings.bindings == (binding,) + assert snapshot.source_bindings.bindings == (binding,) assert CompiledSourceBindingPlan.from_config( - snapshot.step.source_bindings, + snapshot.source_bindings, ).bindings == (binding,) @@ -555,18 +543,14 @@ def test_pipeline_step_source_bindings_enabled_inherits_to_function_steps(): exclude_params=["func"], ) ObjectStateRegistry.register(step_state, _skip_snapshot=True) - snapshot = StepSnapshot( - index=0, - scope_id=step_state.scope_id, - step=step_state.to_saved_resolved_object(), - ) + snapshot = step_state.to_saved_resolved_object() finally: ObjectStateRegistry.clear() - assert snapshot.step.source_bindings.enabled is True - assert snapshot.step.source_bindings.bindings == (binding,) + assert snapshot.source_bindings.enabled is True + assert snapshot.source_bindings.bindings == (binding,) assert CompiledSourceBindingPlan.from_config( - snapshot.step.source_bindings, + snapshot.source_bindings, ).bindings == (binding,) @@ -724,6 +708,57 @@ def fake_create_microscope_handler(**kwargs): assert captured_kwargs["microscope_type"] == Microscope.OPENHCS.value +def test_admitted_request_config_survives_next_live_global_context( + tmp_path, monkeypatch, +): + from openhcs.core.orchestrator import orchestrator as orchestrator_module + from openhcs.core.orchestrator.orchestrator import PipelineOrchestrator + from openhcs.core.pipeline.compiler import AxisCompilationRequest + + authored = PipelineConfig(microscope=Microscope.OPENHCS) + ensure_global_config_context( + GlobalPipelineConfig, + GlobalPipelineConfig(num_workers=2, auto_add_output_plate_to_plate_manager=True), + ) + admitted = ObjectState(authored).to_saved_resolved_object() + ensure_global_config_context( + GlobalPipelineConfig, + GlobalPipelineConfig(num_workers=4, auto_add_output_plate_to_plate_manager=False), + ) + received = {} + monkeypatch.setattr( + orchestrator_module, "create_microscope_handler", + lambda **kwargs: received.update(kwargs) or SimpleNamespace(), + ) + orchestrator = PipelineOrchestrator( + tmp_path, pipeline_config=authored, resolved_config=admitted, + ) + orchestrator.initialize_microscope_handler(admitted) + assert received["source_bindings_config"] is admitted.source_bindings_config + assert received["microscope_type"] == Microscope.OPENHCS.value + assert orchestrator.get_effective_config().num_workers == 4 + + orchestrator._initialized = True + orchestrator.input_dir = tmp_path + request = AxisCompilationRequest( + orchestrator=orchestrator, + global_config=admitted, + pipeline=SimpleNamespace(), path_resolver=SimpleNamespace(), + global_step_axis_filters={}, enable_visualizer_override=False, + is_zmq_execution=True, + ) + context = request.context_for("A01") + assert context.auto_add_output_plate_to_plate_manager is True + assert context.tiff_config is admitted.tiff_config + + # The next authored request admits current global and local changes. + orchestrator.pipeline_config = PipelineConfig(microscope=Microscope.OPENHCS, num_workers=3) + next_request = orchestrator.get_effective_config() + assert next_request.num_workers == 3 + assert next_request.auto_add_output_plate_to_plate_manager is False + assert admitted.num_workers == 2 + + def test_source_bindings_expose_generic_resolution_requirements(): config = StepSourceBindingsConfig( bindings=( @@ -1119,6 +1154,73 @@ def test_narrow_step_binding_uses_exact_workspace_provenance_identity(): ) +@pytest.mark.parametrize("shared_source", [True, False]) +def test_source_binding_members_use_exact_source_identity_without_metadata_axes( + shared_source, +): + primary_path = "A01_s001_w2_z001_t001.tif" + object_path = "_source/SavedIPO/A01_s001_w2_z001_t001.tif" + source_path = "/a/saved.labels.tif" + object_source = source_path if shared_source else "/b/saved.labels.tif" + metadata = { + "well": "A01", + "site": "1", + "channel": "2", + "z_index": "1", + "timepoint": "1", + } + coordinates = tuple( + ComponentSelector(component, metadata[component.value]) + for component in AllComponents + ) + primary = NamedSourceBinding(alias="SavedImage", component_identity=coordinates) + objects = NamedSourceBinding( + alias="SavedIPO", + component_identity=coordinates, + artifact_kind=ObjectLabelsArtifactType, + projection_role=SourceProjectionRole.SOURCE_ARTIFACT, + ) + refs = { + primary_path: SourcePixelRef("disk", source_path), + object_path: SourcePixelRef("disk", object_source), + } + address = OpenHCSPlaneAddress.from_complete_source_metadata(metadata) + projection = VirtualWorkspaceSourceProjection( + source_refs_by_virtual_path=refs, + source_metadata_by_path={primary_path: metadata, object_path: metadata}, + source_projections_by_virtual_path={ + primary_path: SourcePlaneProjection( + address=address, ref=refs[primary_path], source_alias=primary.alias + ), + object_path: SourceArtifactProjection( + address=address, + ref=refs[object_path], + source_alias=objects.alias, + artifact_kind=ObjectLabelsArtifactType, + ), + }, + ) + policy = SourceImageSetIdentityPolicy.from_source_bindings( + SourceBindingsConfig(bindings=(primary, objects)) + ) + assert not policy.identity_components() + matched = SourceBindingMatchedImageSet.from_plan( + bindings=(primary, objects), + match_plan=SourceBindingMatchPlan(SourceBindingMatchMethod.ORDER), + source_context=SourcePatternResolutionContext.from_projection( + parser=SourceSchemaFilenameParser(), projection=projection + ), + identity_policy=policy, + ) + assert matched.members_for_binding( + objects, + anchor_provenance=SourceImageProvenance( + source_path=primary_path, source_component_metadata=metadata + ), + source_universe=(object_path,), + ) == ((object_path,) if shared_source else ()) + + def test_source_binding_members_load_one_store_for_multiple_matching_identities(): binding = NamedSourceBinding( alias="Membrane", @@ -1245,6 +1347,57 @@ def test_declared_positions_keep_store_planes_and_same_basename_sources_distinct ) == (positions[:2], (positions[1],), (positions[2],), ()) + +def test_source_binding_members_collapse_lookup_aliases_of_same_projection(): + relative = tuple(f"A01_s001_w1_z{z:03d}_t001.tif" for z in (0, 1)) + full = tuple(f"/workspace/{path}" for path in relative) + source_path = "/physical/source.tif" + binding = NamedSourceBinding(alias="OriginalPhysical") + projections = tuple( + SourcePlaneProjection( + address=OpenHCSPlaneAddress.from_values("A01", "1", "1", z, "1"), + ref=SourcePixelRef("disk", source_path), source_alias=binding.alias, + ) + for z in (0, 1) + ) + typed = { + spelling: projection + for path, loadable, projection in zip(relative, full, projections, strict=True) + for spelling in (path, loadable) + } + workspace = VirtualWorkspaceSourceProjection( + source_refs_by_virtual_path={path: projection.ref for path, projection in typed.items()}, + source_metadata_by_path={full[0]: {"channel": "9"}}, + source_projections_by_virtual_path=typed, + ) + context = SourcePatternResolutionContext.from_projection( + parser=SourceSchemaFilenameParser(), projection=workspace, + ) + matched = SourceBindingMatchedImageSet.from_plan( + bindings=(binding,), match_plan=None, source_context=context, + identity_policy=SourceImageSetIdentityPolicy(), + ) + candidates = (*typed, source_path) + assert matched.members_for_binding( + binding, + anchor_provenance=SourceImageProvenance(source_path, {"z_index": "0"}), + source_universe=candidates, + ) == (relative[0],) + assert matched.matching_candidates_for_source_identities( + (SourceImageIdentity(source_path), SourceImageIdentity(full[0]), + SourceImageIdentity(source_path, {"channel": "9"})), candidates, + ) == (relative, (relative[0],), (relative[0],)) + # A later declaration replacement is a new position even with equal fields. + typed[full[0]] = SourcePlaneProjection( + address=projections[0].address, ref=projections[0].ref, source_alias=binding.alias, + ) + with pytest.raises(ValueError, match="one exact declared source-set position"): + matched.members_for_binding( + binding, + anchor_provenance=SourceImageProvenance(source_path, {"z_index": "0"}), + source_universe=candidates, + ) + def test_source_binding_exact_position_projection_inherits_owning_context(): """Surface policy guard: declaration resolution is not reimplemented in leaves.""" assert ( @@ -1542,38 +1695,3 @@ def test_compiled_source_binding_plan_round_trips_through_pickle(): assert restored.metadata_rules == plan.metadata_rules assert restored.match_plan == plan.match_plan assert restored.binding_for_alias("OrigBlue") == plan.binding_for_alias("OrigBlue") - - -def test_source_binding_runtime_context_preserves_source_provenance_through_pickle(): - context = SourceBindingRuntimeContext( - step_input_files=("A01_s001_w1_z001_t001.tif",), - step_input_dir="/workspace", - step_input_source_paths={ - "A01_s001_w1_z001_t001.tif": "/real/source_C20_w1.tif", - }, - source_metadata_by_path={ - "A01_s001_w1_z001_t001.tif": { - "Compound": "DMSO", - ORIGINAL_SOURCE_METADATA_FIELD: { - "Plate": "PlateA", - "ChannelNumber": "1", - }, - }, - }, - pipeline_input_files=("/real/source_C20_w1.tif",), - pipeline_input_backend="disk", - ) - - restored = pickle.loads(pickle.dumps(context)) - - assert restored == context - assert dict(restored.step_input_source_paths) == { - "A01_s001_w1_z001_t001.tif": "/real/source_C20_w1.tif", - } - assert dict(restored.source_metadata_by_path["A01_s001_w1_z001_t001.tif"]) == { - "Compound": "DMSO", - ORIGINAL_SOURCE_METADATA_FIELD: { - "Plate": "PlateA", - "ChannelNumber": "1", - }, - } diff --git a/tests/unit/test_source_bound_matched_image_set_anchors.py b/tests/unit/test_source_bound_matched_image_set_anchors.py index f79d80899b..12f5e916f1 100644 --- a/tests/unit/test_source_bound_matched_image_set_anchors.py +++ b/tests/unit/test_source_bound_matched_image_set_anchors.py @@ -1,4 +1,6 @@ +from pathlib import Path from types import SimpleNamespace +from unittest.mock import Mock import pytest from polystore.virtual_workspace import SourcePixelRef @@ -23,6 +25,8 @@ execution_scope, ) from openhcs.core.source_binding_selection import SourcePatternResolutionContext +from openhcs.core.runtime_source_binding_cache import RuntimeSourceBindingContextCache +from openhcs.core.steps.function_output_manifest import _STEP_OUTPUT_MANIFESTS from openhcs.core.source_bindings import ( CompiledSourceBindingPlan, ComponentSelector, @@ -38,8 +42,7 @@ from openhcs.core.source_workspace_projection import VirtualWorkspaceSourceProjection from openhcs.core.step_dependencies import StepInputDependency from openhcs.core.steps.function_execution import ( - PatternGroups, - StepAnchorPatternFilter, + FunctionStepExecutor, ) from openhcs.microscopes.source_schema import SourceSchemaFilenameParser @@ -52,6 +55,28 @@ ) +def _anchor_executor( + *, plan, parser, output_manifest, source_workspace_projection_cache +): + executor = object.__new__(FunctionStepExecutor) + executor.plan = plan + executor.context = Mock( + plate_path=Path("."), + microscope_handler=SimpleNamespace( + parser=parser, + metadata_handler=SimpleNamespace( + source_workspace_metadata_document=lambda _path: None + ), + ), + filemanager=SimpleNamespace(exists=lambda *_args: False), + runtime_source_workspace_projection_cache=source_workspace_projection_cache, + runtime_source_binding_context_cache=RuntimeSourceBindingContextCache(), + ) + if output_manifest is not None: + _STEP_OUTPUT_MANIFESTS[executor.context] = output_manifest + return executor + + def test_artifact_only_group_declares_no_source_anchor_bindings() -> None: payload = ArtifactSpec.input( "payload", @@ -73,14 +98,13 @@ def consume(*, payload): ), ), ) - pattern_filter = StepAnchorPatternFilter( + pattern_filter = _anchor_executor( plan=SimpleNamespace( source_binding_plan=source_binding_plan, execution_group_scope=ComponentGroupScope.ungrouped(), ), parser=SourceSchemaFilenameParser(), output_manifest=None, - source_workspace_authority=None, source_workspace_projection_cache=None, ) @@ -129,7 +153,7 @@ def _filter_source_anchors( dimension_aliases: tuple[str, ...] | None = None, shared_output: bool = True, composed_image_set: bool = True, -) -> PatternGroups: +) -> dict: available_bindings = _source_bindings() aliases = tuple(binding.alias for binding in available_bindings) compiled_bindings = tuple( @@ -231,14 +255,10 @@ def measure_images(image): ), compiled_function_pattern=compiled_pattern, ) - patterns = PatternGroups( - { - channel: tuple( - f"A01_s{site:03d}_w{channel}_z001_t001.tif" for site in sites - ) - for _alias, channel in SOURCE_ALIASES - } - ) + patterns = { + channel: tuple(f"A01_s{site:03d}_w{channel}_z001_t001.tif" for site in sites) + for _alias, channel in SOURCE_ALIASES + } source_paths = { pattern: f"/source/{pattern}" for pattern_list in patterns.values() @@ -259,15 +279,14 @@ def measure_images(image): source_metadata_by_path=source_metadata, ) monkeypatch.setattr( - StepAnchorPatternFilter, + FunctionStepExecutor, "source_pattern_context", lambda _self: source_context, ) - pattern_filter = StepAnchorPatternFilter( + pattern_filter = _anchor_executor( plan=plan, parser=SourceSchemaFilenameParser(), output_manifest=None, - source_workspace_authority=None, source_workspace_projection_cache=None, ) return pattern_filter.source_bound_anchor_patterns(patterns) @@ -281,7 +300,7 @@ def test_all_loaded_contract_collapses_sibling_alias_groups_by_metadata( artifact_aliases=tuple(alias for alias, _channel in SOURCE_ALIASES), ) - assert filtered.groups == { + assert filtered == { "2": ("A01_s001_w2_z001_t001.tif",), "1": (), "5": (), @@ -299,7 +318,7 @@ def test_natural_callable_keeps_each_source_component_anchor( composed_image_set=False, ) - assert filtered.groups == { + assert filtered == { channel: (f"A01_s001_w{channel}_z001_t001.tif",) for _alias, channel in SOURCE_ALIASES } @@ -313,7 +332,7 @@ def test_selected_source_contract_keeps_only_its_exact_alias_anchor( artifact_aliases=("OrigHoechst",), ) - assert filtered.groups == { + assert filtered == { "1": ("A01_s001_w1_z001_t001.tif",), } @@ -327,7 +346,7 @@ def test_distinct_metadata_sets_each_keep_one_source_representative( sites=(1, 2), ) - assert filtered.groups == { + assert filtered == { "2": ( "A01_s001_w2_z001_t001.tif", "A01_s002_w2_z001_t001.tif", @@ -348,7 +367,7 @@ def test_independent_source_aligned_outputs_keep_each_execution_group( shared_output=False, ) - assert filtered.groups == { + assert filtered == { "2": ("A01_s001_w2_z001_t001.tif",), "1": ("A01_s001_w1_z001_t001.tif",), } @@ -408,13 +427,11 @@ def measure_hoechst(image): ), compiled_function_pattern=compiled_pattern, ) - patterns = PatternGroups( - { - "2": ("A01_s001_w2_z001_t001.tif",), - "1": ("A01_s001_w1_z001_t001.tif",), - "5": ("A01_s001_w5_z001_t001.tif",), - } - ) + patterns = { + "2": ("A01_s001_w2_z001_t001.tif",), + "1": ("A01_s001_w1_z001_t001.tif",), + "5": ("A01_s001_w5_z001_t001.tif",), + } source_context = SourcePatternResolutionContext.from_sources( parser=SourceSchemaFilenameParser(), source_paths_by_virtual_path={ @@ -429,21 +446,20 @@ def measure_hoechst(image): }, ) monkeypatch.setattr( - StepAnchorPatternFilter, + FunctionStepExecutor, "source_pattern_context", lambda _self: source_context, ) - pattern_filter = StepAnchorPatternFilter( + pattern_filter = _anchor_executor( plan=plan, parser=SourceSchemaFilenameParser(), output_manifest=None, - source_workspace_authority=None, source_workspace_projection_cache=None, ) filtered = pattern_filter.source_bound_anchor_patterns(patterns) - assert filtered.groups == { + assert filtered == { "2": ("A01_s001_w2_z001_t001.tif",), "1": ("A01_s001_w1_z001_t001.tif",), "5": (), @@ -510,28 +526,25 @@ def identify_bodies(image): ), ) monkeypatch.setattr( - StepAnchorPatternFilter, + FunctionStepExecutor, "source_pattern_context", lambda _self: source_context, ) - pattern_filter = StepAnchorPatternFilter( + pattern_filter = _anchor_executor( plan=plan, parser=SourceSchemaFilenameParser(), output_manifest=None, - source_workspace_authority=None, source_workspace_projection_cache=None, ) filtered = pattern_filter.source_bound_anchor_patterns( - PatternGroups( - { - "1": ("A01_s{iii}_w1_z001_t001.tif",), - "2": ("A01_s{iii}_w2_z001_t001.tif",), - } - ) + { + "1": ("A01_s{iii}_w1_z001_t001.tif",), + "2": ("A01_s{iii}_w2_z001_t001.tif",), + } ) - assert filtered.groups == { + assert filtered == { "2": ("A01_s{iii}_w2_z001_t001.tif",), } @@ -631,23 +644,20 @@ def align_source_set(image): ), ) monkeypatch.setattr( - StepAnchorPatternFilter, + FunctionStepExecutor, "source_pattern_context", lambda _self: source_context, ) - pattern_filter = StepAnchorPatternFilter( + pattern_filter = _anchor_executor( plan=plan, parser=SourceSchemaFilenameParser(), output_manifest=None, - source_workspace_authority=None, source_workspace_projection_cache=None, ) - patterns = PatternGroups( - { - "1": ("A01_s001_w{iii}_z001_t001.tif",), - "2": ("A01_s002_w{iii}_z001_t001.tif",), - } - ) + patterns = { + "1": ("A01_s001_w{iii}_z001_t001.tif",), + "2": ("A01_s002_w{iii}_z001_t001.tif",), + } assert pattern_filter.source_bound_anchor_patterns(patterns) == patterns @@ -683,7 +693,10 @@ def test_static_site_groups_do_not_cross_project_natural_source_set_templates( MeasurementsArtifactType, relations=( ArtifactMeasurementSubjectRelation(), - *(GroupLineageSourceRelation(source=spec.ref()) for spec in input_specs), + *( + GroupLineageSourceRelation(source=spec.ref()) + for spec in input_specs + ), ), ), ) @@ -759,22 +772,19 @@ def align_source_set(image): ), ) monkeypatch.setattr( - StepAnchorPatternFilter, + FunctionStepExecutor, "source_pattern_context", lambda _self: source_context, ) - pattern_filter = StepAnchorPatternFilter( + pattern_filter = _anchor_executor( plan=plan, parser=SourceSchemaFilenameParser(), output_manifest=None, - source_workspace_authority=None, source_workspace_projection_cache=None, ) - patterns = PatternGroups( - { - "1": ("A01_s001_w{iii}_z001_t001.tif",), - "2": ("A01_s002_w{iii}_z001_t001.tif",), - } - ) + patterns = { + "1": ("A01_s001_w{iii}_z001_t001.tif",), + "2": ("A01_s002_w{iii}_z001_t001.tif",), + } assert pattern_filter.source_bound_anchor_patterns(patterns) == patterns diff --git a/tests/unit/test_source_image_provenance.py b/tests/unit/test_source_image_provenance.py index eae9118787..7f65e326ea 100644 --- a/tests/unit/test_source_image_provenance.py +++ b/tests/unit/test_source_image_provenance.py @@ -67,6 +67,54 @@ def test_source_provenance_preserves_plane_positions_before_axis_deduplication() assert axis == (plane_identities[0],) +def test_plane_coordinate_reads_preserve_runtime_scope_and_scalar_fallback() -> None: + provenance = SourceImageProvenance( + source_path="/input/fallback.tif", + source_component_metadata={ + "well": "A01", "site": "99", "channel": "9", "timepoint": "3", + }, + source_image_provenance_planes=SourceImageProvenancePlanes(( + SourceImageProvenanceContributor( + SourceImageIdentity(component_metadata={"site": "88"}), + source_image_name="Ancestor", + ), + RuntimeSourceImageProvenancePlane( + SourceImageIdentity(component_metadata={"site": "1", "channel": "1"}), + contributors=(SourceImageProvenanceContributor( + SourceImageIdentity(component_metadata={"site": "77"}), + source_image_name="DNA", + ),), + ), + RuntimeSourceImageProvenancePlane( + SourceImageIdentity(component_metadata={"site": "2", "channel": "2"}), + ), + )), + ) + assert dict(provenance.component_metadata_for_plane(0)) == { + "well": "A01", "site": "1", "channel": "1", "timepoint": "3", + } + assert provenance.varying_plane_component_values(tuple(AllComponents)) == { + "site": ("1", "2"), "channel": ("1", "2"), + } + assert provenance.require_common_component_values( + (AllComponents.WELL, AllComponents.TIMEPOINT) + ) == ((AllComponents.WELL, "A01"), (AllComponents.TIMEPOINT, "3")) + with pytest.raises(ValueError, match="'site' is not fixed"): + provenance.require_common_component_values((AllComponents.SITE,)) + identities = provenance.image_set_plane_identities( + SourceImageSetIdentityPolicy(frozenset((AllComponents.CHANNEL,))) + ) + assert len(identities) == 2 + assert tuple(next(iter(value)).components for value in identities) == ( + (("site", "1"), ("timepoint", "3"), ("well", "A01")), + (("site", "2"), ("timepoint", "3"), ("well", "A01")), + ) + provenance.source_identity.component_metadata = {"well": "B02", "timepoint": "4"} + assert provenance.require_common_component_values( + (AllComponents.WELL, AllComponents.TIMEPOINT) + ) == ((AllComponents.WELL, "B02"), (AllComponents.TIMEPOINT, "4")) + + def test_source_provenance_axis_retains_distinct_image_sets() -> None: provenance = SourceImageProvenance( source_image_provenance_planes=SourceImageProvenancePlanes.from_components( diff --git a/tests/unit/test_source_image_provenance_hotpath.py b/tests/unit/test_source_image_provenance_hotpath.py index bf3e167d50..552cdadf8e 100644 --- a/tests/unit/test_source_image_provenance_hotpath.py +++ b/tests/unit/test_source_image_provenance_hotpath.py @@ -14,7 +14,7 @@ def test_empty_explicit_provenance_reuses_authoritative_value() -> None: ) fields = SourceImageProvenanceFields(source_provenance=retained) - fields.absorb_explicit_source_provenance(SourceImageProvenance()) + fields.absorb_explicit_source_provenance((None, None, None, ())) assert fields.source_provenance is retained @@ -30,7 +30,9 @@ def test_populated_explicit_provenance_preserves_merge_precedence() -> None: ) fields = SourceImageProvenanceFields(source_provenance=fallback) - fields.absorb_explicit_source_provenance(explicit) + fields.absorb_explicit_source_provenance( + (None, {"channel": "2"}, None, ("Explicit",)) + ) assert fields.source_provenance == SourceImageProvenance( source_path="/input/A01_s001_w1.tif", diff --git a/tests/unit/test_source_metadata_live_mutation.py b/tests/unit/test_source_metadata_live_mutation.py index 19cf5086cd..935fc63373 100644 --- a/tests/unit/test_source_metadata_live_mutation.py +++ b/tests/unit/test_source_metadata_live_mutation.py @@ -3,7 +3,7 @@ import pytest from openhcs.constants.constants import AllComponents -from openhcs.core.source_binding_selection import SourceMetadataRecord +from openhcs.core.source_binding_selection import DeclaredSourceMetadataRecord from openhcs.core.source_matching import ( ORIGINAL_SOURCE_METADATA_FIELD, semantic_source_metadata_value, @@ -31,7 +31,7 @@ def test_metadata_queries_observe_scalar_mutation(readonly_outer): @pytest.mark.parametrize( - "view", (dict, MappingProxyType, SourceMetadataRecord.from_mapping) + "view", (dict, MappingProxyType, DeclaredSourceMetadataRecord.from_mapping) ) def test_literal_queries_observe_nested_original_mutation(view): original = {"Well": "LiteralA"} diff --git a/tests/unit/test_source_metadata_owner.py b/tests/unit/test_source_metadata_owner.py new file mode 100644 index 0000000000..217278289d --- /dev/null +++ b/tests/unit/test_source_metadata_owner.py @@ -0,0 +1,672 @@ +"""Owned metadata lifetime and its production provenance consumers.""" + +import pickle +from collections.abc import Mapping, Sequence + +import cloudpickle +from types import MappingProxyType + +import numpy as np +import pytest +from polystore.virtual_workspace import SourcePixelRef + +from openhcs.constants.constants import AllComponents +from openhcs.core.artifacts import ImageArtifactType +from openhcs.core.runtime_image_values import ( + ImagePayloadMetadata, + image_payload_metadata, +) +from openhcs.core.source_binding_selection import DeclaredSourceMetadataRecord +from openhcs.core.source_bindings import ( + SOURCE_BINDING_ALIAS_METADATA_FIELD, +) +from openhcs.core.source_image_provenance import ( + SourceImageIdentity, + SourceImageProvenance, + SourceImageProvenancePlanes, + SourceImageProvenance, + SourceImageProvenancePlaneRecord, + SourcePlaneIndexedMetadata, + source_component_metadata_consensus, +) +from openhcs.core.source_matching import ( + source_component_metadata_items, + source_component_metadata_value, + source_component_metadata_values, + source_metadata_value, + with_source_component_metadata, +) +from openhcs.core.source_metadata import ( + ORIGINAL_SOURCE_METADATA_FIELD, + DurableSourceMetadata, + ResolvedSourceMetadataRecord, + SourceMetadataRecord, + SourceMetadataFields, + source_metadata_scalar, +) +from openhcs.core.source_projection import OpenHCSPlaneAddress, SourcePlaneProjection +from openhcs.core.steps.function_output_identity import FunctionOutputIdentity +from openhcs.core.source_workspace_projection import ( + VirtualWorkspaceImagePayloadProjection, + VirtualWorkspaceSourceProjection, +) +from openhcs.core.virtual_workspace_metadata import ( + VirtualWorkspaceSourceMetadataEntries, +) +from openhcs.serialization.json import to_jsonable + + +@pytest.mark.parametrize("owner", (ResolvedSourceMetadataRecord, DurableSourceMetadata)) +def test_owned_snapshot_detaches_nested_fields_and_preserves_record_contract(owner): + nested = {"Well": "literal"} + record = owner.from_mapping({"well": "A01", ORIGINAL_SOURCE_METADATA_FIELD: nested}) + nested["Well"] = "changed" + assert source_metadata_value(record, "Well") == "literal" + with pytest.raises(TypeError): + record[ORIGINAL_SOURCE_METADATA_FIELD]["Well"] = "changed" + with pytest.raises(TypeError): + hash(record) + declared = DeclaredSourceMetadataRecord.from_mapping( + {"well": "A01", ORIGINAL_SOURCE_METADATA_FIELD: {"Well": "literal"}} + ) + reversed_record = owner.from_mapping( + {ORIGINAL_SOURCE_METADATA_FIELD: {"Well": "literal"}, "well": "A01"} + ) + if isinstance(record, SourceMetadataRecord): + assert record == declared + assert record != reversed_record + else: + assert record != declared and declared != record + assert record == reversed_record + assert record == dict(declared) + + +def test_owned_lookup_keeps_first_duplicate_field_and_full_ordered_record(): + record = ResolvedSourceMetadataRecord((("well", "A01"), ("well", "A02"))) + assert record["well"] == "A01" + assert tuple(record.items()) == (("well", "A01"), ("well", "A01")) + assert record.fields == (("well", "A01"), ("well", "A02")) + assert dict(record) == {"well": "A01"} + assert record != ResolvedSourceMetadataRecord((("well", "A01"),)) + + +def test_runtime_birth_canonicalizes_but_durable_and_derived_values_keep_literal_spelling( + tmp_path, +): + spelling = str(tmp_path / "unused" / ".." / "image.tif") + durable = DurableSourceMetadata.from_mapping({"path": spelling}) + runtime = ResolvedSourceMetadataRecord.from_mapping(durable) + assert durable["path"] == spelling + assert runtime["path"] == str(tmp_path / "image.tif") + derived = SourceMetadataFields.with_fields(runtime, {"new_path": spelling}) + assert isinstance(derived, DurableSourceMetadata) + assert derived["path"] == str(tmp_path / "image.tif") + assert derived["new_path"] == spelling + projection = SourcePlaneProjection( + address=OpenHCSPlaneAddress.from_values( + well="A01", site="1", channel="1", z_index="1", timepoint="1" + ), + ref=SourcePixelRef("disk", "plane.tif"), + source_metadata=derived, + ) + assert projection.source_metadata["new_path"] == str(tmp_path / "image.tif") + + +def test_owned_scalar_identity_reuses_literal_metadata_but_not_mutable_carriers(): + fields = {"well": "A01", "channel": "1", "extension": ".tif"} + owner = DurableSourceMetadata.from_mapping(fields) + original = ImagePayloadMetadata( + source_provenance=SourceImageProvenance( + source_path="/input/source.tif", + source_component_metadata=owner, + source_image_names=("DNA",), + ) + ) + first = original.replace_fields() + second = original.with_source_context_from(original) + assert first.source_provenance is not original.source_provenance + assert ( + first.source_provenance.source_identity + is not original.source_provenance.source_identity + ) + assert first.source_component_metadata is owner + assert second.source_component_metadata is owner + assert ( + first.source_provenance.equality_identity + == original.source_provenance.equality_identity + ) + assert to_jsonable(first) == to_jsonable(original) + first.source_provenance.source_identity.path = "/changed.tif" + assert original.source_path == "/input/source.tif" + assert second.source_path == "/input/source.tif" + + +def test_workspace_alias_projection_and_artifact_naming_preserve_owned_metadata(): + source = VirtualWorkspaceSourceMetadataEntries.normalize_metadata_fields( + {"well": "A01", "channel": "1", SOURCE_BINDING_ALIAS_METADATA_FIELD: "DNA"} + ) + payload = ImagePayloadMetadata().payload_with(np.ones((2, 2), dtype=np.float32)) + projected = VirtualWorkspaceImagePayloadProjection( + source_metadata=source, source_alias="DNA" + ).apply(payload) + metadata = image_payload_metadata(projected) + assert isinstance(metadata.source_component_metadata, DurableSourceMetadata) + assert SOURCE_BINDING_ALIAS_METADATA_FIELD not in metadata.source_component_metadata + named = ImageArtifactType.normalize_runtime_payload("DerivedDNA", projected) + named_metadata = image_payload_metadata(named) + assert ( + named_metadata.source_component_metadata is metadata.source_component_metadata + ) + assert named_metadata.source_image_names == ("DerivedDNA",) + assert metadata.source_image_names == ("DNA",) + assert ( + named_metadata.source_provenance.source_image_provenance_planes.represented_source_image_names + == ("DNA",) + ) + + +def test_owned_updates_replace_aliases_and_keep_original_literals(): + owner = DurableSourceMetadata.from_mapping( + { + "channel": "1", + "ChannelNumber": "2", + ORIGINAL_SOURCE_METADATA_FIELD: {"ChannelNumber": "literal"}, + } + ) + updated = with_source_component_metadata(owner, AllComponents.CHANNEL, "3") + assert isinstance(updated, DurableSourceMetadata) + assert "ChannelNumber" not in updated + assert source_metadata_value(updated, "ChannelNumber") == "literal" + assert source_component_metadata_values(updated, AllComponents.CHANNEL) == ("3",) + assert owner["channel"] == "1" + + +@pytest.mark.parametrize("owner", (ResolvedSourceMetadataRecord, DurableSourceMetadata)) +def test_custom_scalar_remains_live_for_queries_and_new_fingerprints(owner): + class MutableInteger(int): + def __str__(self): + return self.tag + + def __repr__(self): + return self.tag + + value = MutableInteger(1) + value.tag = "before" + record = owner.from_mapping({"channel": value}) + first = SourceImageIdentity(component_metadata=record) + assert source_component_metadata_value(record, AllComponents.CHANNEL) == "before" + value.tag = "after" + assert source_component_metadata_value(record, AllComponents.CHANNEL) == "after" + assert SourceImageIdentity(component_metadata=record).identity != first.identity + assert first.identity[1] == (("channel", "before"),) + + +def test_lazy_role_errors_are_unchanged_by_owned_construction(): + record = DurableSourceMetadata.from_mapping( + { + "channel": "1", + "wellrow": "A", + "wellcolumn": "bad", + ORIGINAL_SOURCE_METADATA_FIELD: 7, + } + ) + assert source_component_metadata_value(record, AllComponents.CHANNEL) == "1" + with pytest.raises(ValueError): + source_component_metadata_value(record, AllComponents.WELL) + with pytest.raises(RuntimeError, match="must be a mapping"): + source_metadata_value(record, "channel") + with pytest.raises(RuntimeError, match="must be a mapping"): + source_component_metadata_values(record, AllComponents.CHANNEL) + + +@pytest.mark.parametrize("invalid", ([1], {"deep": {"unsupported": 1}}, object())) +def test_durable_metadata_keeps_existing_invalid_value_domain(invalid): + with pytest.raises(RuntimeError): + VirtualWorkspaceSourceMetadataEntries.normalize_metadata_fields( + {"field": invalid} + ) + + +def test_source_identity_mapping_equality_keeps_original_class_and_current_field_boundaries(): + owner = DurableSourceMetadata.from_mapping({"flag": True}) + identity = SourceImageIdentity("source.tif", owner) + raw = SourceImageIdentity("source.tif", MappingProxyType({"flag": True})) + assert identity == raw and raw == identity + assert identity != SourceImageIdentity("source.tif", {"flag": 1}) + assert SourceImageIdentity(component_metadata=None) != SourceImageIdentity( + component_metadata={} + ) + with pytest.raises(TypeError): + hash(identity) + + class Child(SourceImageIdentity): + pass + + assert identity.__eq__(Child("source.tif", owner)) is NotImplemented + + class ReportedIdentity: + @property + def __class__(self): + return SourceImageIdentity + + def __getattribute__(self, name): + if name in ("path", "component_metadata", "_identity"): + reads.append(name) + return getattr(raw, name) + return object.__getattribute__(self, name) + + reads = [] + assert identity.__eq__(ReportedIdentity()) is True + assert reads == ["path", "component_metadata", "_identity"] + + nested = {"literal": "before"} + left = SourceImageIdentity( + component_metadata={ORIGINAL_SOURCE_METADATA_FIELD: nested} + ) + right = SourceImageIdentity( + component_metadata={ORIGINAL_SOURCE_METADATA_FIELD: {"literal": "before"}} + ) + captured = left.identity + assert left == right + nested["literal"] = "after" + assert left != right and left.identity == captured + + +def test_nested_mapping_order_does_not_change_provenance_identity_or_wire_order(): + raw = {"well": "A01", ORIGINAL_SOURCE_METADATA_FIELD: {"site": "001", "channel": "1"}} + reordered = {ORIGINAL_SOURCE_METADATA_FIELD: {"channel": "1", "site": "001"}, "well": "A01"} + owned = DurableSourceMetadata.from_mapping(reordered) + before = to_jsonable(owned) + original = SourceImageProvenance(source_path="source.tif", source_component_metadata=raw) + for metadata in (reordered, owned): + candidate = SourceImageProvenance(source_path="source.tif", source_component_metadata=metadata) + assert candidate == original + assert candidate.equality_identity == original.equality_identity + assert SourceMetadataFields.provenance_identity_items(raw) == SourceMetadataFields.provenance_identity_items(owned) + assert to_jsonable(owned) == before + assert tuple(reordered) == (ORIGINAL_SOURCE_METADATA_FIELD, "well") + assert tuple(reordered[ORIGINAL_SOURCE_METADATA_FIELD]) == ("channel", "site") + reordered[ORIGINAL_SOURCE_METADATA_FIELD]["site"] = "002" + changed = SourceImageProvenance(source_path="source.tif", source_component_metadata=reordered) + assert changed.equality_identity != original.equality_identity + + +def test_canonical_metadata_identity_preserves_ordered_provenance_planes(): + paths = ("a.tif", "b.tif") + metadata = ({"site": "1"}, {"site": "2"}) + forward = SourceImageProvenancePlanes.from_components(paths=paths, component_metadata=metadata) + reverse = SourceImageProvenancePlanes.from_components( + paths=tuple(reversed(paths)), component_metadata=tuple(reversed(metadata)), + ) + assert SourceImageProvenance(source_image_provenance_planes=forward).equality_identity != SourceImageProvenance( + source_image_provenance_planes=reverse, + ).equality_identity + + +@pytest.mark.parametrize("serializer", (pickle, cloudpickle)) +def test_identity_transport_preserves_birth_fingerprint_after_current_metadata_changes(serializer): + from openhcs.core.orchestrator.execution_result import RuntimeExecutionTransportSerialization + + RuntimeExecutionTransportSerialization.register() + nested = {"site": "001", "channel": "1"} + identity = SourceImageIdentity("original.tif", {ORIGINAL_SOURCE_METADATA_FIELD: nested}) + birth = identity.identity + nested["site"] = "002" + identity.path = "current.tif" + restored = serializer.loads(serializer.dumps(identity)) + assert restored.path == "current.tif" + assert restored.component_metadata[ORIGINAL_SOURCE_METADATA_FIELD]["site"] == "002" + assert restored.identity == birth + assert SourceImageIdentity(restored.path, restored.component_metadata).identity != birth + + +def test_raw_composition_snapshots_once_before_consensus_reads(): + class ObservableMapping(Mapping): + def __init__(self, values): + self.values = values + self.key_reads = self.value_reads = 0 + + def __iter__(self): + self.key_reads += 1 + return iter(self.values) + + def __len__(self): + return len(self.values) + + def __getitem__(self, key): + self.value_reads += 1 + return self.values[key] + + raw = ObservableMapping({"well": "A01"}) + consensus = source_component_metadata_consensus((raw, raw)) + assert dict(consensus) == {"well": "A01"} + assert raw.key_reads == 2 and raw.value_reads == 2 + snapshot = SourceMetadataFields.composition_snapshot(raw) + raw.values["well"] = "A02" + assert snapshot["well"] == "A01" + assert source_component_metadata_consensus((raw, raw))["well"] == "A02" + + +@pytest.mark.parametrize("owner", (ResolvedSourceMetadataRecord, DurableSourceMetadata)) +@pytest.mark.parametrize("serializer", (pickle, cloudpickle)) +def test_owned_transport_stores_only_authoritative_fields_and_rebuilds_local_views( + owner, serializer +): + record = owner.from_mapping( + {"well": "A01", ORIGINAL_SOURCE_METADATA_FIELD: {"literal": "value"}} + ) + before = SourceImageIdentity(component_metadata=record).identity + assert source_metadata_value(record, "literal") == "value" + assert source_component_metadata_value(record, AllComponents.WELL) == "A01" + assert record._views + restored = serializer.loads(serializer.dumps(record)) + assert isinstance(restored, owner) + assert restored.fields == record.fields + assert not restored._views + assert restored.metadata_contents is not record.metadata_contents + assert to_jsonable(restored) == to_jsonable(record) + assert SourceImageIdentity(component_metadata=restored).identity == before + with pytest.raises(TypeError): + restored[ORIGINAL_SOURCE_METADATA_FIELD]["literal"] = "changed" + + +@pytest.mark.parametrize("owner", (ResolvedSourceMetadataRecord, DurableSourceMetadata)) +def test_transport_does_not_recanonicalize_stored_absolute_values_or_validate_unused_roles( + owner, tmp_path +): + directory = tmp_path / "original" + directory.mkdir() + spelling = str(directory / "image.tif") + record = owner.from_mapping({"path": spelling, ORIGINAL_SOURCE_METADATA_FIELD: 7}) + before = SourceImageIdentity(component_metadata=record).identity + directory.rmdir() + target = tmp_path / "replacement" + target.mkdir() + directory.symlink_to(target, target_is_directory=True) + assert str((directory / "image.tif").resolve()) != spelling + restored = pickle.loads(pickle.dumps(record)) + assert restored["path"] == spelling + assert SourceImageIdentity(component_metadata=restored).identity == before + with pytest.raises(RuntimeError, match="must be a mapping"): + source_metadata_value(restored, "unused") + + +def test_ordered_component_batch_matches_sequential_raw_updates(): + fields = { + "Well": "old", + "Site": "old", + "ChannelNumber": "old", + "ZIndex": "old", + "Timepoint": "old", + ORIGINAL_SOURCE_METADATA_FIELD: {"Well": "literal"}, + } + components = tuple( + (component, str(index)) for index, component in enumerate(AllComponents, 1) + ) + raw = dict(fields) + for component, value in components: + raw = with_source_component_metadata(raw, component, value) + record = DurableSourceMetadata.from_mapping(fields) + updated = SourceMetadataFields.with_fields(record, {}, components=components) + assert isinstance(updated, DurableSourceMetadata) + assert to_jsonable(updated) == to_jsonable(raw) + assert tuple(updated) == tuple(raw) + assert source_metadata_value(updated, "Well") == "literal" + + +@pytest.mark.parametrize("existing_extension", (False, True)) +def test_output_identity_batch_keeps_original_field_order_and_extension_precedence( + existing_extension, +): + fields = {"literal": "kept", "Well": "old"} + if existing_extension: + fields["extension"] = ".old" + identity = FunctionOutputIdentity( + component_values={"well": "A01", "channel": "1"}, + extension=".tif", + source="control", + ) + expected = dict(fields) + expected.update(identity.component_values) + for component, value in source_component_metadata_items(identity.component_values): + expected = with_source_component_metadata(expected, component, value) + expected["extension"] = ".tif" + actual = identity.component_metadata(DurableSourceMetadata.from_mapping(fields)) + assert tuple(actual.items()) == tuple(expected.items()) + assert to_jsonable(actual) == expected + + +def test_duplicate_record_keys_collapse_at_source_identity_mapping_boundary(): + record = ResolvedSourceMetadataRecord((("well", "A01"), ("well", "A02"))) + expected = SourceImageIdentity(component_metadata=dict(record)) + actual = SourceImageIdentity(component_metadata=record) + assert actual == expected + assert actual.identity == expected.identity + assert tuple(actual.component_metadata.items()) == (("well", "A01"),) + assert record.fields == (("well", "A01"), ("well", "A02")) + + +def test_stringified_key_collisions_keep_platform_map_last_value_at_owned_birth(): + fields = {1: "first", "1": "last"} + durable = VirtualWorkspaceSourceMetadataEntries.normalize_metadata_fields(fields) + assert tuple(durable.items()) == (("1", "last"),) + projection = SourcePlaneProjection( + address=OpenHCSPlaneAddress.from_values( + well="A01", site="1", channel="1", z_index="1", timepoint="1" + ), + ref=SourcePixelRef("disk", "plane.tif"), + source_metadata=fields, + ) + assert tuple(projection.source_metadata.items()) == (("1", "last"),) + declaration = DeclaredSourceMetadataRecord.from_mapping(fields) + assert declaration.fields == (("1", "first"), ("1", "last")) + assert declaration["1"] == "first" + + +@pytest.mark.parametrize( + "decoder", + ( + ResolvedSourceMetadataRecord.from_mapping, + DurableSourceMetadata.from_mapping, + VirtualWorkspaceSourceMetadataEntries.normalize_metadata_fields, + ), +) +def test_owned_map_birth_validates_overwritten_stringified_key_values(decoder): + with pytest.raises((TypeError, RuntimeError)): + decoder({1: [], "1": "valid"}) + + +def test_mapping_and_ordered_record_equality_namespaces_stay_separate(): + ordered = ResolvedSourceMetadataRecord.from_mapping({"well": "A01", "site": "1"}) + reordered = ResolvedSourceMetadataRecord.from_mapping({"site": "1", "well": "A01"}) + mapping = DurableSourceMetadata.from_mapping(ordered) + reordered_mapping = DurableSourceMetadata.from_mapping(reordered) + assert ordered != reordered + assert mapping == reordered_mapping + assert mapping == dict(ordered) and dict(ordered) == mapping + for record in ( + ordered, + reordered, + DeclaredSourceMetadataRecord.from_mapping(dict(ordered)), + ): + assert mapping != record and record != mapping + assert hash(ordered) == hash( + DeclaredSourceMetadataRecord.from_mapping(dict(ordered)) + ) + with pytest.raises(TypeError): + hash(mapping) + + +@pytest.mark.parametrize( + "factory", + ( + lambda metadata: VirtualWorkspaceSourceMetadataEntries({"plane.tif": metadata}), + lambda metadata: VirtualWorkspaceImagePayloadProjection( + source_metadata=metadata + ), + lambda metadata: VirtualWorkspaceSourceProjection({}, {"plane.tif": metadata}), + lambda metadata: SourceImageProvenancePlaneRecord(component_metadata=metadata), + lambda metadata: SourcePlaneIndexedMetadata(metadata, 0, 1), + lambda metadata: SourcePlaneProjection( + address=OpenHCSPlaneAddress.from_values( + well="A01", site="1", channel="1", z_index="1", timepoint="1" + ), + ref=SourcePixelRef("disk", "plane.tif"), + source_metadata=metadata, + ), + ), +) +def test_public_mapping_field_carriers_keep_content_equality(factory): + owner = DurableSourceMetadata.from_mapping({"well": "A01", "site": "1"}) + reordered = DurableSourceMetadata.from_mapping({"site": "1", "well": "A01"}) + raw = MappingProxyType({"well": "A01", "site": "1"}) + assert factory(owner) == factory(reordered) + assert factory(owner) == factory(raw) + assert factory(raw) == factory(owner) + with pytest.raises(TypeError): + hash(factory(owner)) + + +def test_durable_tuple_birth_uses_mapping_last_value_policy(): + metadata = DurableSourceMetadata((("well", "A01"), ("well", "A02"))) + assert metadata.fields == (("well", "A02"),) + assert metadata == {"well": "A02"} + assert ( + SourceImageIdentity(component_metadata=metadata).identity + == SourceImageIdentity(component_metadata={"well": "A02"}).identity + ) + + +def test_scalar_admission_preserves_primitives_subclasses_and_scalar_container_precedence(): + class Integer(int): + pass + + class Real(float): + pass + + class TextMapping(str, Mapping): + pass + + values = ( + None, + False, + True, + 0, + -3, + 1.25, + "literal", + Integer(7), + Real(2.5), + TextMapping("literal"), + ) + for value in values: + assert DurableSourceMetadata.normalized_scalar(value) is value + assert source_metadata_scalar(value) is value + assert isinstance(values[-1], Mapping) + assert isinstance(values[-1], Sequence) + + +def test_durable_scalar_admission_preserves_rejected_container_and_scalar_errors(): + class MappingSequence(Mapping, Sequence): + def __getitem__(self, key): + raise KeyError(key) + + def __iter__(self): + return iter(()) + + def __len__(self): + return 0 + + container_error = ( + "virtual_workspace source metadata supports scalar values and " + "one-level scalar mappings only." + ) + scalar_error = ( + "virtual_workspace source metadata scalar values must be strings, " + "numbers, booleans, or null." + ) + for value in ( + {}, + [], + (), + range(1), + b"bytes", + bytearray(b"bytes"), + MappingSequence(), + ): + with pytest.raises(RuntimeError) as caught: + DurableSourceMetadata.normalized_scalar(value) + assert str(caught.value) == container_error + for value in (set(), frozenset(), 1j, object()): + with pytest.raises(RuntimeError) as caught: + DurableSourceMetadata.normalized_scalar(value) + assert str(caught.value) == scalar_error + + +def test_scalar_admission_keeps_none_identity_and_reported_class_read_order(): + class ReportedClass: + def __init__(self, reports): + self.reports = reports + self.reads = [] + + @property + def __class__(self): + reported = self.reports[min(len(self.reads), len(self.reports) - 1)] + self.reads.append(reported) + return reported + + reported_none = ReportedClass((type(None),)) + with pytest.raises(RuntimeError) as caught: + DurableSourceMetadata.normalized_scalar(reported_none) + assert str(caught.value) == ( + "virtual_workspace source metadata scalar values must be strings, " + "numbers, booleans, or null." + ) + assert reported_none.reads == [type(None)] * 6 + + reported_none = ReportedClass((type(None),)) + with pytest.raises(TypeError, match="Source metadata scalar values must be"): + source_metadata_scalar(reported_none) + assert reported_none.reads == [type(None)] * 4 + + reported_integer = ReportedClass((object, int, object)) + assert DurableSourceMetadata.normalized_scalar(reported_integer) is reported_integer + assert reported_integer.reads == [object, int] + + for normalize in ( + source_metadata_scalar, + SourceMetadataFields.normalized_scalar, + ResolvedSourceMetadataRecord.normalized_scalar, + ): + reported_integer = ReportedClass((object, int, object)) + assert normalize(reported_integer) is reported_integer + assert reported_integer.reads == [object, int, object] + + # Scalar admission and string normalization are separate observations. + # A changing reported class must retain the previous normalization order. + reported_string = ReportedClass((str, object)) + assert normalize(reported_string) is reported_string + assert reported_string.reads == [str, object] + + reported_string = ReportedClass((str, object)) + assert DurableSourceMetadata.normalized_scalar(reported_string) is reported_string + assert reported_string.reads == [str] + + changing_class = ReportedClass( + (object, object, object, object, object, Sequence, str) + ) + with pytest.raises(RuntimeError) as caught: + DurableSourceMetadata.normalized_scalar(changing_class) + assert str(caught.value) == ( + "virtual_workspace source metadata scalar values must be strings, " + "numbers, booleans, or null." + ) + assert changing_class.reads == [ + object, + object, + object, + object, + object, + Sequence, + str, + ] diff --git a/tests/unit/test_source_projection.py b/tests/unit/test_source_projection.py index a2a590d50a..5871a9745f 100644 --- a/tests/unit/test_source_projection.py +++ b/tests/unit/test_source_projection.py @@ -11,7 +11,7 @@ from openhcs.core.source_bindings import SourceProjectionRole from openhcs.core.source_metadata import ( ORIGINAL_SOURCE_METADATA_FIELD, - SourceMetadataRoleView, + SourceMetadataFields, ) from openhcs.core.source_projection import ( OpenHCSPlaneAddress, @@ -269,7 +269,7 @@ def test_source_projection_preserves_provenance_owned_component_remaps( assert source_metadata[component.value] == address_value assert ( - dict(SourceMetadataRoleView(source_metadata).original_items())[component.value] + dict(SourceMetadataFields.original_items(source_metadata))[component.value] == source_value ) diff --git a/tests/unit/test_source_provenance_constructor_defaults.py b/tests/unit/test_source_provenance_constructor_defaults.py new file mode 100644 index 0000000000..f25eaa478c --- /dev/null +++ b/tests/unit/test_source_provenance_constructor_defaults.py @@ -0,0 +1,99 @@ +"""All source-metadata carriers decode authored aliases at the same boundary.""" + +from functools import partial + +import numpy as np +import pytest + +from openhcs.core.artifacts import ArtifactSpec, ObjectLabelsArtifactType +from openhcs.core.runtime_image_values import ImagePayloadMetadata +from openhcs.core.runtime_measurements import ( + MeasurementScope, + MeasurementSubject, + MeasurementTable, +) +from openhcs.core.runtime_object_labels import ( + ObjectLabelPayload, + ObjectLabelSet, + ObjectLabelVariantData, +) +from openhcs.core.runtime_relationships import ( + DirectedObjectRelationshipPayload, + ObjectRelationship, + ObjectRelationshipDeclaration, +) +from openhcs.core.runtime_spatial_graph import SpatialGraph +from openhcs.core.runtime_tabular_values import ColumnarRows +from openhcs.core.source_image_provenance import SourceImageProvenance + + +class EmptyRows(ColumnarRows): + columns = {} + fields = () + + +def _carriers(): + labels = ObjectLabelVariantData(labels=np.zeros((2, 3), dtype=np.int32)) + relationship = ObjectRelationshipDeclaration.parent_child( + source=ArtifactSpec.output("Cells", ObjectLabelsArtifactType).ref(), + target=ArtifactSpec.output("Nuclei", ObjectLabelsArtifactType).ref(), + producer_module_number=1, + ) + return ( + ImagePayloadMetadata, + partial(ObjectLabelPayload, variant_data=labels), + partial(ObjectLabelSet, name="Cells", variant_data=labels), + partial( + MeasurementTable, + name="Intensity", + rows=EmptyRows(), + subject=MeasurementSubject(MeasurementScope.IMAGE, "DNA"), + ), + partial(SpatialGraph, name="Graph", nodes=(), edges=()), + partial( + ObjectRelationship, + name="ParentChild", + declaration=relationship, + payload=DirectedObjectRelationshipPayload(source_ids=(), target_ids=()), + ), + ) + + +@pytest.mark.parametrize("construct", _carriers()) +def test_absent_aliases_do_not_create_empty_provenance(construct, monkeypatch): + supplied = SourceImageProvenance( + source_path="/tmp/source.tif", source_component_metadata={"well": "A01"} + ) + + def unexpected(cls, values): + pytest.fail("Absent source aliases must not allocate a decoded value.") + + monkeypatch.setattr( + SourceImageProvenance, "from_init_values", classmethod(unexpected) + ) + carrier = construct(source_provenance=supplied) + assert carrier.source_path == "/tmp/source.tif" + assert carrier.source_component_metadata["well"] == "A01" + assert carrier.source_provenance is not supplied + carrier.source_provenance.source_identity.path = "/tmp/changed.tif" + assert supplied.source_path == "/tmp/source.tif" + + +@pytest.mark.parametrize("construct", _carriers()) +def test_explicit_empty_metadata_and_aliases_still_decode(construct, monkeypatch): + calls = [] + original = SourceImageProvenance.from_init_values + + def observe(cls, values): + calls.append(values) + return original(values) + + monkeypatch.setattr(SourceImageProvenance, "from_init_values", classmethod(observe)) + empty = construct(source_component_metadata={}) + assert calls == [(None, {}, None, ())] + assert empty.source_component_metadata is not None + assert dict(empty.source_component_metadata) == {} + authored = construct(source_path="/tmp/authored.tif", source_image_names=("DNA",)) + assert authored.source_path == "/tmp/authored.tif" + assert authored.source_image_names == ("DNA",) + assert len(calls) == 2 diff --git a/tests/unit/test_source_spatial_domain.py b/tests/unit/test_source_spatial_domain.py index 269f5e6a09..f460fd08bd 100644 --- a/tests/unit/test_source_spatial_domain.py +++ b/tests/unit/test_source_spatial_domain.py @@ -1,4 +1,5 @@ import numpy as np +import pytest from openhcs.core.aligned_image_payload import ( ObjectLabelPayloadSourceSpatialDomainAdapter, @@ -16,6 +17,7 @@ from openhcs.core.runtime_sparse_labels import SparseIJVLabelRows from openhcs.core.source_spatial_domain import ( SourceSpatialDomain, + VolumeSourceSpatialDomain, SourceSpatialDomainAdapter, dense_array_in_source_spatial_domain, ) @@ -116,3 +118,34 @@ def test_sparse_object_label_projection_preserves_all_declared_variants(): dtype=np.int32, ), ) + + +@pytest.mark.parametrize("as_labels", (False, True)) +def test_xy_alignment_preserves_intrinsic_volume_owner(as_labels): + pixels = np.arange(3 * 6 * 7, dtype=np.int32).reshape(3, 6, 7) + mask = np.ones(pixels.shape, dtype=bool) + mask[:, 0, 0] = False + source = ImagePayloadMetadata( + source_spatial_domain=VolumeSourceSpatialDomain( + source_depth=3, origin_yx=(0, 0), source_shape_yx=(6, 7) + ), + ).payload_with(pixels, mask) + value = ( + SourceImageObjectLabelBuildRequest(image=source, labels=pixels).label_set(name="Objects") + if as_labels else source + ) + target = ImagePayloadMetadata( + source_spatial_domain=SourceSpatialDomain( + origin_yx=(1, 2), source_shape_yx=(6, 7) + ), + ).payload_with(np.zeros((3, 2, 3)), None) + result = SourceSpatialDomainAdapter.for_value(value).value_in_payload_domain( + SourceSpatialDomainAdapter.for_value(target) + ) + adapter = SourceSpatialDomainAdapter.for_value(result) + assert isinstance(adapter.domain, VolumeSourceSpatialDomain) + assert adapter.domain.source_depth == 3 + assert adapter.domain.origin_yx == (1, 2) + np.testing.assert_array_equal(adapter.array, pixels[:, 1:3, 2:5]) + if not as_labels: + np.testing.assert_array_equal(result.mask, mask[:, 1:3, 2:5]) diff --git a/tests/unit/test_spatial_graph_materialization.py b/tests/unit/test_spatial_graph_materialization.py index 0c0e70ef37..18aa93f233 100644 --- a/tests/unit/test_spatial_graph_materialization.py +++ b/tests/unit/test_spatial_graph_materialization.py @@ -1,3 +1,5 @@ + +from openhcs.core.artifacts import ImageArtifactType import numpy as np import pytest @@ -25,10 +27,7 @@ SpatialGraphEdge, SpatialGraphNode, ) -from openhcs.core.steps.function_runtime import ( - FunctionOutputContextStrategy, - SpatialGraphFunctionOutputContextStrategy, -) + from openhcs.core.source_image_provenance import SourceImageProvenancePlanes from openhcs.processing.materialization import ( BackendSaver, @@ -138,10 +137,9 @@ def test_spatial_graph_output_context_preserves_exact_source_identity() -> None: artifact_type=SpatialGraphArtifactType, ) - strategy = FunctionOutputContextStrategy.for_output_plan(output_plan) - contextualized = strategy.contextualize(source, graph, output_plan, None) + strategy = (ImageArtifactType if output_plan is None else output_plan.artifact_type) + contextualized = strategy.contextualize_output(source, graph, output_plan, None) - assert isinstance(strategy, SpatialGraphFunctionOutputContextStrategy) assert isinstance(contextualized, SpatialGraph) assert contextualized is not graph assert contextualized.source_path == "/tmp/A01_s002_w1_z001_t001.tif" @@ -172,9 +170,7 @@ def test_spatial_graph_output_context_projects_declared_source_plane() -> None: artifact_type=SpatialGraphArtifactType, ) - contextualized = FunctionOutputContextStrategy.for_output_plan( - output_plan - ).contextualize(source, graph, output_plan, None) + contextualized = (ImageArtifactType if output_plan is None else output_plan.artifact_type).contextualize_output(source, graph, output_plan, None) assert contextualized.source_path == "/tmp/smi312.tif" assert contextualized.source_component_metadata["channel"] == "4" diff --git a/tests/unit/test_volume_projection_fixture.py b/tests/unit/test_volume_projection_fixture.py index 418674246c..f3e2a58bbb 100644 --- a/tests/unit/test_volume_projection_fixture.py +++ b/tests/unit/test_volume_projection_fixture.py @@ -4,6 +4,8 @@ execution, saved CSV/ROI publication, an installed MCP journey, or biology. """ +from openhcs.core.artifacts import MeasurementsArtifactType, ObjectLabelsArtifactType + import importlib.util from pathlib import Path import sys @@ -19,7 +21,7 @@ from openhcs.core.source_image_provenance import SourceImageProvenancePlanes from openhcs.core.source_projection import OpenHCSPlaneAddress from openhcs.core.source_matching import source_component_metadata_value -from openhcs.core.steps.function_runtime import ImageFunctionOutputContextStrategy, MeasurementsFunctionOutputContextStrategy, ObjectLabelsFunctionOutputContextStrategy + spec = importlib.util.spec_from_file_location( @@ -62,7 +64,7 @@ def test_selected_then_full_stack_outputs_keep_exact_source_context(source_volum original_pixels = image_payload_data(source_volume) selected_indices = indices or (0, 1, 2) selection = fixture.select_volume_fixture_planes_v2(source_volume, indices) - projected = ImageFunctionOutputContextStrategy().contextualize( + projected = ImageArtifactType.contextualize_output( source_volume, selection, output_plan(fixture.SELECTED_VOLUME), RuntimePlaneAxisValueProjection(RuntimePlaneAxis.RUNTIME_SLICE, (), None, 3), ) @@ -79,13 +81,13 @@ def test_selected_then_full_stack_outputs_keep_exact_source_context(source_volum projection = RuntimePlaneAxisValueProjection(RuntimePlaneAxis.RUNTIME_SLICE, (), None, len(selected_indices)) for _ in range(2): image, labels, rows = fixture.inspect_volume_fixture_v2(projected) - contextual_image = ImageFunctionOutputContextStrategy().contextualize( + contextual_image = ImageArtifactType.contextualize_output( projected, image, output_plan(fixture.VOLUME_IMAGE), projection, ) - contextual_labels = ObjectLabelsFunctionOutputContextStrategy().contextualize( + contextual_labels = ObjectLabelsArtifactType.contextualize_output( projected, labels, output_plan(fixture.VOLUME_LABELS), projection, ) - contextual_rows = MeasurementsFunctionOutputContextStrategy().contextualize( + contextual_rows = MeasurementsArtifactType.contextualize_output( projected, rows, output_plan(fixture.VOLUME_ROWS), projection, ) np.testing.assert_array_equal(image_payload_data(contextual_image), expected) @@ -121,7 +123,7 @@ def test_empty_label_stack_keeps_schema_and_exact_plane_context(source_volume): empty = image_payload_metadata(source_volume).payload_with(np.zeros((3, 8, 9), dtype=np.uint16)) image, labels, rows = fixture.inspect_volume_fixture_v2(empty) projection = RuntimePlaneAxisValueProjection(RuntimePlaneAxis.RUNTIME_SLICE, (), None, 3) - contextual = ObjectLabelsFunctionOutputContextStrategy().contextualize( + contextual = ObjectLabelsArtifactType.contextualize_output( image, labels, output_plan(fixture.VOLUME_LABELS), projection, ) assert contextual.declared_plane_count() == 3 @@ -129,7 +131,7 @@ def test_empty_label_stack_keeps_schema_and_exact_plane_context(source_volume): contextual.validate_source_alignment(fixture.VOLUME_LABELS.name) assert len(rows) == 0 and rows.row_type is fixture.VolumeProjectionFixtureRow assert all(len(rows.column_values(field.name)) == 0 for field in rows.fields) - table = MeasurementsFunctionOutputContextStrategy().contextualize( + table = MeasurementsArtifactType.contextualize_output( image, rows, output_plan(fixture.VOLUME_ROWS), projection, ) assert len(table.rows) == 0 diff --git a/tests/unit/test_zmq_compilation.py b/tests/unit/test_zmq_compilation.py index f86a280c87..1f22cfffd5 100644 --- a/tests/unit/test_zmq_compilation.py +++ b/tests/unit/test_zmq_compilation.py @@ -106,6 +106,7 @@ def compile_pipelines( well_filter, is_zmq_execution, debug_execution_policy, + resolved_config, ) -> CompiledExecutionBundle: self.calls.append( { @@ -113,6 +114,7 @@ def compile_pipelines( "well_filter": well_filter, "is_zmq_execution": is_zmq_execution, "debug_execution_policy": debug_execution_policy, + "resolved_config": resolved_config, } ) time.sleep(0.03) @@ -184,6 +186,7 @@ def test_reused_compile_artifact_reads_step_names_from_compiled_plans() -> None: plate_id="/tmp/plate", pipeline_steps=[], orchestrator=None, + resolved_config=GlobalPipelineConfig(), wells=["A01"], compile_artifact_id="artifact-1", compilation_signature="signature", @@ -224,6 +227,7 @@ def test_compile_fresh_emits_heartbeat_during_long_compilation() -> None: plate_id="/tmp/plate", pipeline_steps=[_StrippedStepShell(), _StrippedStepShell()], orchestrator=orchestrator, + resolved_config=GlobalPipelineConfig(), wells=["A01"], compile_artifact_id=None, compilation_signature="signature", @@ -247,6 +251,7 @@ def test_compile_fresh_emits_heartbeat_during_long_compilation() -> None: "well_filter": ["A01"], "is_zmq_execution": True, "debug_execution_policy": "debug-policy", + "resolved_config": request.resolved_config, } ] assert progress_emitter.compiled_init_events == [ @@ -306,6 +311,7 @@ def test_rejected_reuse_preserves_artifact_for_a_valid_request(retain, invalid): plate_id="/plate", pipeline_steps=[], orchestrator=None, + resolved_config=GlobalPipelineConfig(), wells=["A01"], compile_artifact_id="artifact-1", compilation_signature="signature", diff --git a/tests/unit/test_zmq_compiled_pipeline_run.py b/tests/unit/test_zmq_compiled_pipeline_run.py index 476ccabb38..1572b6592d 100644 --- a/tests/unit/test_zmq_compiled_pipeline_run.py +++ b/tests/unit/test_zmq_compiled_pipeline_run.py @@ -3,6 +3,7 @@ from __future__ import annotations from contextlib import contextmanager +from dataclasses import replace from pathlib import Path import pytest @@ -13,6 +14,7 @@ from openhcs.runtime.zmq_execution_client import ( OpenHCSExecutionSubmission, ZMQExecutionClient, + ZMQExecutionRequestBuilder, ZMQPipelineRunPhase, run_compiled_pipeline, ) @@ -27,6 +29,11 @@ def __init__(self, *, compile_status="complete", execute_status="complete"): self.compile_submission = None self.execution_submission = None + def submit_prepared_pipeline(self, request): + if request.compile_control.compile_only: + return self.submit_compile(request) + return self.submit_pipeline(request) + def submit_compile(self, submission): self.events.append("submit_compile") self.compile_submission = submission @@ -47,6 +54,13 @@ def wait_for_completion(self, execution_id, poll_interval=0.5): else self.execute_status ), "execution_id": execution_id, + "execution": { + "execution_id": execution_id, + "plate_id": "/tmp/plate", + "status": self.compile_status if execution_id == "compile-1" else self.execute_status, + "start_time": 10.0, + "end_time": 12.0, + }, } @@ -83,7 +97,7 @@ def observe(phase): assert result.compile_artifact_id == "compile-1" assert result.execution_id == "execute-1" - assert result.completion_response["status"] == "complete" + assert result.execution_record.status == "complete" assert result.completion_observed_at > 0 assert client.events == [ "submit_compile", @@ -91,8 +105,8 @@ def observe(phase): "submit_execution", "wait:execute-1", ] - assert client.execution_submission.pipeline_document is submission.pipeline_document - assert client.execution_submission.compile_artifact_id == "compile-1" + assert client.execution_submission.pipeline_code == result.request.pipeline_code + assert client.execution_submission.compile_control.compile_artifact_id == "compile-1" assert observed_phases == [ (event, phase) for phase in ZMQPipelineRunPhase for event in ("start", "end") ] @@ -103,7 +117,7 @@ class ClientWithResults(FakeExecutionClient): def wait_for_completion(self, execution_id, poll_interval=0.5): response = super().wait_for_completion(execution_id, poll_interval) if execution_id == "execute-1": - response["results"] = {"output_plate_root": "/output/plate"} + response["execution"]["results_summary"] = {"output_plate_root": "/output/plate"} return response run = run_compiled_pipeline(ClientWithResults(), _submission()) @@ -117,7 +131,7 @@ class ClientWithLegacyResults(FakeExecutionClient): def wait_for_completion(self, execution_id, poll_interval=0.5): response = super().wait_for_completion(execution_id, poll_interval) if execution_id == "execute-1": - response["results_summary"] = {"output_plate_root": "/legacy/plate"} + response["execution"]["results_summary"] = {"output_plate_root": "/legacy/plate"} return response run = run_compiled_pipeline(ClientWithLegacyResults(), _submission()) @@ -213,3 +227,47 @@ def test_compiled_pipeline_run_does_not_report_failed_execution_as_complete(): run_compiled_pipeline(client, _submission()) assert client.events[-1] == "wait:execute-1" + + +def test_compiled_run_retains_its_admitted_wire_and_standalone_request_stays_fresh(monkeypatch): + submission = _submission() + rendered = [] + original_render = PipelineDocumentAuthority.render + + def render(document): + rendered.append(document) + return original_render(document) + + monkeypatch.setattr(PipelineDocumentAuthority, "render", render) + + class EditingClient(FakeExecutionClient): + def submit_compile(self, request): + response = super().submit_compile(request) + submission.pipeline_document = PipelineDocumentAuthority.from_values( + pipeline_config=PipelineConfig(num_workers=3), pipeline_steps=[] + ) + submission.global_pipeline_config = replace( + submission.global_pipeline_config, num_workers=3 + ) + return response + + client = EditingClient() + run = run_compiled_pipeline(client, submission) + + assert len(rendered) == 1 + assert run.request.pipeline_code == client.compile_submission.pipeline_code + assert run.request.global_config_code == client.compile_submission.global_config_code + fresh = ZMQExecutionRequestBuilder.from_task(submission) + assert fresh.pipeline_code != run.request.pipeline_code + assert fresh.global_config_code != run.request.global_config_code + + +def test_compiled_run_rejects_a_terminal_record_for_another_execution(): + class WrongRecordClient(FakeExecutionClient): + def wait_for_completion(self, execution_id, poll_interval=0.5): + response = super().wait_for_completion(execution_id, poll_interval) + response["execution"]["execution_id"] = "another-job" + return response + + with pytest.raises(RuntimeError, match="matching completed execution record"): + run_compiled_pipeline(WrongRecordClient(), _submission()) diff --git a/tests/unit/test_zmq_execution_server.py b/tests/unit/test_zmq_execution_server.py index 2cdb1197eb..d79efc92c3 100644 --- a/tests/unit/test_zmq_execution_server.py +++ b/tests/unit/test_zmq_execution_server.py @@ -1,3 +1,4 @@ +import json import sys from pathlib import Path from dataclasses import replace @@ -7,7 +8,7 @@ import pytest from objectstate import get_current_global_config from zmqruntime.execution import ExecutionServer -from zmqruntime.messages import ExecutionRecord, ExecutionStatus +from zmqruntime.messages import ExecutionRecord, ExecutionStatus, MessageFields import openhcs.runtime.zmq_execution_server as zmq_execution_server_module from openhcs.constants.constants import GroupBy @@ -17,6 +18,9 @@ ProcessingConfig, ) from openhcs.core.execution_state import ExecutionOutputPlateSummary +from openhcs.core.orchestrator.compiled_plate_execution import ( + CompiledPlateExecutionResults, +) from openhcs.core.orchestrator.execution_result import ( ExecutionResult, RuntimeContextObservation, @@ -193,20 +197,22 @@ def test_server_exports_outcomes_without_projecting_compiled_values( server._export_runtime_observation( request_context=request_context, compilation=compilation, - execution_results={ - "A01": ExecutionResult.success( - "A01", - runtime_observation=RuntimeExecutionObservation( - contexts=( - RuntimeContextObservation( - "context", - (), - runtime_export_paths=(declared_output,), - ), - ) - ), - ) - }, + execution_results=CompiledPlateExecutionResults( + { + "A01": ExecutionResult.success( + "A01", + runtime_observation=RuntimeExecutionObservation( + contexts=( + RuntimeContextObservation( + "context", + (), + runtime_export_paths=(declared_output,), + ), + ) + ), + ) + } + ), ) export = ZMQRuntimeExecutionOutcomeExport.read(export_path) @@ -384,42 +390,65 @@ def initialize_registry() -> None: assert context.pipeline_steps == [] -def test_zmq_server_forwards_parent_execution_progress_without_worker_claim() -> None: - server = object.__new__(ZMQExecutionServer) +def test_zmq_server_admits_all_progress_through_generic_terminal_watermark() -> None: + from zmqruntime.execution.progress_stream import ProgressStreamSubscriber + from openhcs.runtime.zmq_execution_client import ZMQExecutionClient + + server = ZMQExecutionServer() + record = ExecutionRecord("execution-1", "plate-1", None, ExecutionStatus.RUNNING.value) + server.active_executions[record.execution_id] = record server._worker_assignments_by_execution = { "execution-1": {"worker_0": ["A01", "B01"]} } - server.progress_queue = SimpleQueue() worker_queue = SimpleQueue() progress_context = ProgressExecutionContext( - execution_id="execution-1", - plate_id="plate-1", + execution_id=record.execution_id, + plate_id=record.plate_id, ) - worker_queue.put( - create_event( - ProgressEventPayload( - identity=progress_context.identity_for_event( - axis_id="", - step_name="ExportToDatabase", - ), - phase=ProgressPhase.RUNNING, - status=ProgressStatus.RUNNING, - completed=32, - total=33, - percent=(32 / 33) * 100.0, - ) - ).to_dict() + parent = create_event( + ProgressEventPayload( + identity=progress_context.identity_for_event( + axis_id="", step_name="ExportToDatabase", + ), + phase=ProgressPhase.RUNNING, + status=ProgressStatus.RUNNING, + completed=32, total=33, percent=(32 / 33) * 100.0, + ) ) + server._enqueue_progress(parent.to_dict()) + worker_queue.put(parent.to_dict()) + worker = replace( + parent, + identity=progress_context.identity_for_event( + axis_id="A01", step_name="ExportToDatabase", + ), + worker_slot="worker_0", + owned_wells=["A01", "B01"], + ) + worker_queue.put(worker.to_dict()) worker_queue.put(None) - server._forward_worker_progress(worker_queue) - event = ProgressEvent.from_dict(server.progress_queue.get()) + published = [server.progress_queue.get_nowait() for _ in range(3)] + received = [] + client = ZMQExecutionClient(progress_callback=received.append) + subscriber = ProgressStreamSubscriber(lambda: None, client._record_progress) + for payload in published: + assert subscriber._dispatch_message(json.dumps(payload)) + assert [payload[MessageFields.PROGRESS_SEQUENCE] for payload in received] == [1, 2, 3] + assert client.progress_observation(record.execution_id).sequence == 3 + assert record.to_dict()[MessageFields.PROGRESS_SEQUENCE] == 3 + assert record.progress_event == published[-1] + event = ProgressEvent.from_dict(published[1]) assert event.axis_id == "" assert event.worker_slot is None assert event.owned_wells is None assert event.worker_assignments == {"worker_0": ["A01", "B01"]} assert event.total_wells == ["A01", "B01"] + worker_event = ProgressEvent.from_dict(published[2]) + assert worker_event.axis_id == "A01" + assert worker_event.worker_slot == "worker_0" + assert worker_event.owned_wells == ["A01", "B01"] def test_zmq_server_records_the_compilation_output_plate_value_without_rebuilding_it() -> ( diff --git a/tests/unit/test_zmq_runtime_outcome_export.py b/tests/unit/test_zmq_runtime_outcome_export.py index f358c89ca1..041116b678 100644 --- a/tests/unit/test_zmq_runtime_outcome_export.py +++ b/tests/unit/test_zmq_runtime_outcome_export.py @@ -110,6 +110,7 @@ def test_value_export_rejects_an_uncompiled_execution_axis() -> None: compiled_contexts={}, execution_results={"A01": ExecutionResult.success("A01")}, output_roots=(), + runtime_observations=(), ) with pytest.raises(RuntimeError, match="execution outcomes have no compiled axis"): exported.require_valid_observation() @@ -167,6 +168,7 @@ def test_previous_runtime_export_versions_remain_readable(tmp_path: Path) -> Non execution_results={}, output_roots=(), execution_id="new-job", + runtime_observations=(), ), schema_version=6, execution_id=None, @@ -178,6 +180,7 @@ def test_previous_runtime_export_versions_remain_readable(tmp_path: Path) -> Non execution_results={}, output_roots=(), execution_id="other-job", + runtime_observations=(), ).write(observation_path) assert observation_path.read_bytes() == retained_bytes assert ( diff --git a/tests/unit/test_zmq_submission_timeout.py b/tests/unit/test_zmq_submission_timeout.py index 0b4c857c78..53dc24eaa3 100644 --- a/tests/unit/test_zmq_submission_timeout.py +++ b/tests/unit/test_zmq_submission_timeout.py @@ -66,7 +66,7 @@ def send_control_request(self, request, *, timeout_ms: int): client, ) - client._submit_submission(_Submission(), timeout_ms=15000) + client._submit_submission(lambda: client.serialize_task(_Submission().to_task()), timeout_ms=15000) assert [phase for phase, _timeout_ms in observed] == [ "progress", @@ -116,7 +116,7 @@ def connect( client.connect = MethodType(connect, client) try: - client._submit_submission(_Submission(), timeout_ms=15000) + client._submit_submission(lambda: client.serialize_task(_Submission().to_task()), timeout_ms=15000) except RuntimeError as error: assert str(error) == "Failed to connect to execution server" else: @@ -163,7 +163,7 @@ def send_control_request(self, request, *, timeout_ms: int): ExecutionSubmissionPreparationTimeoutError, match="no execute request was sent", ): - client._submit_submission(_Submission(), timeout_ms=10) + client._submit_submission(lambda: client.serialize_task(_Submission().to_task()), timeout_ms=10) assert observed == ["connect"]