Skip to content

feat(secondary-pharma): public get_poses with verified receptor, project-scoped from_last_run (DDOS-8005) - #646

Merged
ASinanSaglam merged 8 commits into
mainfrom
feat/DDOS-8005-get-poses-receptor-and-630-followups
Sep 30, 2026
Merged

ASinanSaglam merged 8 commits into
mainfrom
feat/DDOS-8005-get-poses-receptor-and-630-followups

Conversation

@ASinanSaglam

Copy link
Copy Markdown
Contributor

Summary

  • Project scoping (shared, affects every tool): Execution.from_last_run() now passes project_id=client.project_id, like list(). Unset client project stays org-wide. Lookups by id or compute_job_id stay unscoped. (project_id on Executions.list/search dates from DDOS-5704: feat: ability to list executions by project id #540.)
  • quiet= removed from Execution.from_id/from_last_run/list and _from_dto_maybe_quiet (review of feat(drug-discovery): add SecondaryPharmacology SDK class (DDOS-7332) #630, Remove "CLI" #3/I think we should generalize the description further -- "Command line tool and Python client for working ..." #5).
  • ProteinPrep: deleted the list / from_last_run overrides (vestigial since Migrate ProteinPrep to deeporigin.protein-prep v10 #639 removed the dual-tool-key logic). from_id untouched. Expect conflicts in protein_prep.py with in-flight ProteinPrep work.
  • DDOS-8005: SecondaryPharmacology.get_poses() is public. It downloads each distinct panel receptor once, verifies structure_sha256 (one re-download on mismatch), and sets pose.props["receptor_local_path"]. Rows with no receptor_file_path return poses without a receptor. Paths outside protected/ or containing .., % or NUL are rejected before any download.
  • show_panel_pose() is public. Pick the pose by ligand (ligand_id, or a Ligand, matched on SMILES when it has no id) and by uniprot_id or gene_name.
  • panel_version (the immutable manifest volume_key) is stamped from result rows. Gap checks and get_panel(panel_version=...) read that panel's members.json, so a later panel change can't cause false gaps. Rows naming several versions raise.
  • Review of feat(drug-discovery): add SecondaryPharmacology SDK class (DDOS-7332) #630: plot() de-duplicated (output identical to main across six cases); plot_heatmap(value_label=...) replaces the hardcoded "RMSD" hover label; docstrings condensed; "kinase panel" wording → "off-target panel" / "secondary-pharmacology panel"; self_test guard on docking get_results(); _backfill_ligand_ids no longer overwrites API ids.
  • Docs, notebook samples (get_poses, show_panel_pose) and CONTEXT.md glossary entries (Project scope, Panel, Panel pose).

Jira: https://deeporigin.atlassian.net/browse/DDOS-8005

Test plan

  • uv run pytest --env local -q -p no:cacheprovider → 1503 passed, 34 skipped, 4 xpassed
  • uv run pytest --env local -q -p no:cacheprovider tests/test_notebooks.py -k secondary → 1 passed
  • interrogate -c pyproject.toml -f 100 --omit-covered-files . → 100%
  • uvx ruff@0.14.7 format --check . → clean
  • Scoping tests are discovery-based over every Execution subclass, for project_id set and None; each new guard was mutation-checked
  • Receptor download and show_panel_pose visually confirmed in a notebook on dev

🤖 Generated with Claude Code

@sg-s sg-s left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

@ASinanSaglam approving, but please resolve conflicts and merge

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot review overview

🟡 Changes recommended

URL path validation misses query and fragment delimiters, and documentation overpromises receptor availability for legacy rows.

Review effort: Balanced
Findings: 1 Medium severity · 2 Low severity

Open (3)
What changed in this PR

Adds project-scoped execution discovery and public, receptor-aware Secondary Pharmacology pose APIs.

Changes:

  • Scopes execution listing and latest-run lookup by project.
  • Adds verified receptor downloads, panel-version tracking, and pose visualization.
  • Updates tests, mock-server fixtures, plots, and documentation.
File Description
src/​drug_discovery/​execution.py Adds project scoping and removes quiet.
src/​drug_discovery/​protein_prep.py Removes redundant execution lookup overrides.
src/​drug_discovery/​secondary_pharma.py Adds public pose APIs and panel-version handling.
src/​plots.py Makes heatmap value labels configurable.
tests/​test_executions.py Tests project-scoped execution discovery.
tests/​test_secondary_pharma.py Tests poses, receptors, panels, and scoping.
tests/​test_plots.py Tests configurable hover labels.
tests/​conftest.py Isolates download caches during tests.
tests/​mock_server/​server.py Seeds panel catalogs and structure files.
tests/​mock_server/​routers/​tools.py Updates mock panel metadata.
docs/​notebooks/​clean/​secondary-pharma.ipynb Demonstrates pose download and visualization.
docs/​dd/​tools/​secondary-pharma.md Documents new Secondary Pharmacology APIs.
docs/​dd/​ref/​secondary_pharma.md Updates API terminology.
docs/​dd/​tools/​proteinprep.md Updates execution-reconnection guidance.
docs/​dd/​tools/​overview.md Documents project-scoped history methods.
docs/​dd/​tools/​docking.md Clarifies latest-run project scope.
CONTEXT.md Defines project, panel, and panel-pose terminology.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread src/drug_discovery/secondary_pharma.py
Comment thread docs/dd/tools/secondary-pharma.md Outdated
Comment thread docs/notebooks/clean/secondary-pharma.ipynb Outdated
ASinanSaglam and others added 8 commits September 30, 2026 14:08
plot_heatmap hardcoded 'RMSD' in the hover text; add value_label (default
'RMSD') so binding-energy and pose-score heatmaps label themselves.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…_panel_pose, project-scoped from_last_run (DDOS-8005)

- get_poses() is public: downloads each pose's panel receptor once,
  verifies structure_sha256, sets props['receptor_local_path']; rows
  without a receptor_file_path yield poses without one; paths outside
  protected/ or containing '..', '%' or NUL are rejected before any download
- panel_version (immutable volume_key) is stamped from result rows;
  gap checks and get_panel(panel_version=...) read that panel's members.json
- show_panel_pose() is public; matches a ligand without an id by SMILES
- Execution.from_last_run() passes project_id=client.project_id like list()
- remove the quiet= flag and _from_dto_maybe_quiet
- delete ProteinPrep list/from_last_run overrides (vestigial after #639)
- de-duplicate SecondaryPharmacology.plot(); condense docstrings
- tests: discovery-based scoping checks over every Execution subclass,
  project_id=None cases, mock panel catalog/receptor, isolated HOME fixture

Addresses the post-merge review of #630.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…ct scoping (DDOS-8005)

- user guide, API ref and notebook samples for get_poses / show_panel_pose
- 'in your current project' scoping wording in tools overview and docking
- drop stale ProteinPrep 'either routed tool' wording
- CONTEXT.md: Project scope, Panel, Panel pose; 'off-target panel' wording

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…se (DDOS-8005)

- ligand= works for a ligand synced in a live run; a reloaded run needs a
  ligand from job.ligands or a ligand_id from get_results()
- drop language_info.version from the notebook so nb-clean (check) passes

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…ow_panel_pose lookup (DDOS-8005)

- compare structure_sha256 case-insensitively; inline the digest check into
  _fetch_verified_receptor and delete _verify_panel_receptor_digest
- fold ligand-id/SMILES resolution into _panel_pose_row; errors now point to
  ligand_id when a SMILES matches nothing or several ligands
- inline the receptor-path check into show_panel_pose
- write cached panel files with write_bytes (receptor and catalog reads already
  re-fetch on a bad digest or unreadable JSON)
- clear panel_version when update_from_dto assigns a new execution id

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…on, clearer from_last_run error (DDOS-8005)

- restore temp-file + os.replace for cached panel files so an interrupted or
  concurrent download never leaves or exposes a partial file
- panel_version must be a single name ([A-Za-z0-9_-][A-Za-z0-9._-]*)
- from_last_run 'No executions found' error names the project_id; docs note
  that runs started with no project are not listed once a project is selected
- remove the deeporigin.__file__ debug cell from the secondary-pharma notebook
- fix stale mock comment about who seeds the pose SDF

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…hint, receptor docs (DDOS-8005)

- _validate_panel_file_path refuses '?' and '#' like '%': the path builds both a request URL and a local cache path. Two cases added to test_secondary_pharma_get_poses_rejects_unsafe_receptor_path.
- _panel_pose_row: nested conditional and hint branching moved to _panel_pose_lookup_hint (same strings; Sonar S3358, S3776).
- docs/notebook: receptor_local_path is set only for rows with receptor_file_path; older rows return the pose without it (Copilot review).

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
… gone (DDOS-8005)

ABFE.from_id (added in #647) called Execution._from_dto_maybe_quiet(..., quiet=False), which this PR removes with quiet=. quiet=False ran from_dto() unchanged, so the call becomes cls.from_dto(dto, client=client).

test_abfe_from_id_hydrates_from_fetched_dto fails with AttributeError on the old call (no test reached it before).

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@ASinanSaglam
ASinanSaglam force-pushed the feat/DDOS-8005-get-poses-receptor-and-630-followups branch from a04e5b9 to e4e980d Compare September 30, 2026 18:19
@ASinanSaglam
ASinanSaglam merged commit feeaf3c into main Sep 30, 2026
11 checks passed
@ASinanSaglam
ASinanSaglam deleted the feat/DDOS-8005-get-poses-receptor-and-630-followups branch September 30, 2026 18:43

This branch was successfully deployed

1 active deployment
docs — e4e980dd Deployed Sep 30, 2026 by ASinanSaglam via build-docs #829
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants