Skip to content

Add BuildCompiler.plating: generate PUDU/Opentrons plating protocol from transformation results#49

Merged
Gonza10V merged 1 commit into
platingfrom
codex/add-buildcompiler.plating-method
Apr 28, 2026
Merged

Add BuildCompiler.plating: generate PUDU/Opentrons plating protocol from transformation results#49
Gonza10V merged 1 commit into
platingfrom
codex/add-buildcompiler.plating-method

Conversation

@Gonza10V
Copy link
Copy Markdown
Contributor

Motivation

  • Provide a public BuildCompiler.plating(...) entry point to map transformation outputs into a PUDU-compatible plating protocol and simulate it with Opentrons tooling.
  • Accept multiple transformation output shapes (thermocycler wells, strain mapping, or raw well map) and normalize them into PUDU's bacterium_locations format for downstream protocol generation.

Description

  • Added BuildCompiler.plating(...) which: normalizes transformation_results, writes plating_input.json containing plating_data and advanced_params, generates a self-contained run_plating.py that from pudu.plating import Plating and calls Plating(plating_data=PLATING_DATA, json_params=ADVANCED_PARAMS), invokes the simulation helper, and returns paths for plating_json, protocol_script, and simulation_zip.
  • Added helpers in src/buildcompiler/robotutils.py: load_json_or_dict, normalize_plating_data, write_plating_protocol_script, and run_opentrons_script_to_zip (creates a temp working dir, runs opentrons_simulate, captures stdout/stderr/returncode, and zips protocol+JSON+logs).
  • Normalization accepts {'bacterium_locations': {...}}, {'strain_locations': {...}}, {'thermocycler_wells': {...}}, or a raw well map like {'A1': 'strain_1'} and returns {'bacterium_locations': {...}}.
  • Updated imports and JSON/filesystem usage in BuildCompiler and added an optional automation dependency pudupy under [project.optional-dependencies] in pyproject.toml.
  • Documentation: added a minimal example usage to README.md demonstrating input shape, advanced_params, and calling compiler.plating(...).

Testing

  • Ran unit tests for the new plating behavior with python -m unittest tests/test_plating.py, which executed 7 tests and completed successfully (all tests passed).
  • Simulated Opentrons execution behavior by monkeypatching subprocess.run in tests to validate run_opentrons_script_to_zip writes simulate_stdout.txt, simulate_stderr.txt, and simulate_returncode.txt into the zip (test passed).
  • Ran static checks with ruff on modified files and received no issues.
  • The tests do not require a physical OT-2; actual opentrons_simulate invocation is exercised in production usage but is mocked in unit tests.

Codex Task

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: d2fede0d3f

ℹ️ 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".

Comment on lines +315 to +316
f"PLATING_DATA = {json.dumps(plating_data, indent=4)}\n\n"
f"ADVANCED_PARAMS = {json.dumps(advanced_params, indent=4)}\n\n"
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Serialize script constants as Python literals

write_plating_protocol_script embeds plating_data/advanced_params into a Python file using json.dumps, which emits JSON tokens like true, false, and null. Those are not Python literals, so when users pass booleans or None in advanced_params (a common config case), the generated run_plating.py crashes with NameError during module evaluation under opentrons_simulate.

Useful? React with 👍 / 👎.

Comment on lines +265 to +269
candidate = Path(value)
else:
raise ValueError("Expected a dict, JSON string, or path to a JSON file.")

if candidate.exists():
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Parse JSON strings before probing filesystem paths

load_json_or_dict treats every string as a path first and calls Path.exists() before json.loads; for large but valid JSON strings (e.g., many well mappings), this can raise OSError: [Errno 36] File name too long and abort parsing. The function should attempt JSON parsing (or catch OSError and fall back) so valid JSON string input does not fail based on filename limits.

Useful? React with 👍 / 👎.

@Gonza10V Gonza10V merged commit bb85f2d into plating Apr 28, 2026
0 of 4 checks passed
@Gonza10V Gonza10V deleted the codex/add-buildcompiler.plating-method branch April 28, 2026 03:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant