Implement BuildCompiler.plating with SBOL provenance, protocol artifacts, and robot helpers#50
Conversation
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 6bce1f03ef
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| for idx, well in enumerate(sorted(payload["strain_locations"]), start=1): | ||
| impl_uri = payload["strain_locations"][well] |
There was a problem hiding this comment.
Preserve well order numerically when normalizing location maps
Sorting well keys as plain strings reorders 96-well coordinates incorrectly (for example, A10 is processed before A2). Since plating() then assigns destination wells by normalized list order, this can silently remap strains to the wrong plate positions in generated plate maps/protocols whenever strain_locations (and similarly bacterium_locations) includes columns 10–12.
Useful? React with 👍 / 👎.
| proc = subprocess.run( | ||
| ["opentrons_simulate", str(tmp_script)], | ||
| capture_output=True, | ||
| text=True, | ||
| cwd=tmpdir, |
There was a problem hiding this comment.
Raise when opentrons simulation exits with failure
The simulation subprocess return code is captured but never checked, so failed opentrons_simulate runs still produce a ZIP artifact and are reported as successful by plating() (no exception is raised, so no skip log is emitted). This can mark invalid automated protocols as if they were successfully simulated, which is misleading in CI or production build workflows.
Useful? React with 👍 / 👎.
Motivation
transformation(...)output (or simplified plating inputs) and produces a single solid 96-well plate with SBOL provenance and protocol artifacts.Description
BuildCompiler.plating(...)which normalizes inputs, enforces a 96-sample capacity, places strains in deterministic row-major wells (A1→H12), and returns a structured plating result dict.Activity,Usageentries (one per transformed strain), a protocol-modeAgent, aPlan, and anAssociationlinking activity↔agent↔plan; platedImplementations are created and annotated where possible.src/buildcompiler/robotutils.py:load_json_or_dict,normalize_plating_input,generate_96_well_positions,write_plate_map_json,write_plate_map_csv,write_manual_plating_protocol,write_plating_protocol_script, andrun_opentrons_script_to_zip.PLATING_ACTIVITY_ROLEinsrc/buildcompiler/constants.pyand best-effort SBOLInventory integration (optional import) with an internal fallback so plating still works if SBOLInventory is not installed.pyproject.tomlto add an optionalautomationdependency group (pudupy,opentrons, andSBOLInventorywithpython_version >= '3.10') to avoid forcing a global Python version bump.tests/test_plating.pycovering normalization, well mapping/capacity, SBOL provenance, manual protocol artifacts, automated script content (ensuringjson_params=), and simulation packaging using a mocked subprocess.Testing
pytest -q tests/test_plating.py tests/test_buildcompiler_transformation.pyand all tests passed (7 passed).def run(protocol: protocol_api.ProtocolContext):, importsprotocol_api, and usesPlating(..., json_params=ADVANCED_PARAMS)(notadvanced_params=) via tests.SBOLInventoryin the environment for integration testing but network/git access failed (GitHub clone returned a 403), so SBOLInventory support is implemented as optional and gracefully falls back when unavailable.Codex Task