@galaxyproject/orbit 0.0.0 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +123 -0
- package/LICENSE +21 -0
- package/README.md +760 -5
- package/bin/legacy-mcp-config.js +363 -0
- package/bin/orbit.js +810 -0
- package/bin/pi-extension-path.d.ts +4 -0
- package/bin/pi-extension-path.js +44 -0
- package/bin/provider-auth.d.ts +22 -0
- package/bin/provider-auth.js +77 -0
- package/bin/thinking-pref.js +38 -0
- package/bin/update-check.d.ts +15 -0
- package/bin/update-check.js +137 -0
- package/extensions/cli-update/index.ts +32 -0
- package/extensions/orbit/activity-hooks.ts +141 -0
- package/extensions/orbit/activity.ts +116 -0
- package/extensions/orbit/agent-dir.ts +11 -0
- package/extensions/orbit/auto-resume.ts +352 -0
- package/extensions/orbit/config.ts +3 -0
- package/extensions/orbit/confusables.ts +1 -0
- package/extensions/orbit/context.ts +957 -0
- package/extensions/orbit/dashboard-commands.ts +191 -0
- package/extensions/orbit/dashboard-store.ts +473 -0
- package/extensions/orbit/dashboard-tools.ts +1185 -0
- package/extensions/orbit/empty-completion.ts +99 -0
- package/extensions/orbit/evidence-gate.ts +1276 -0
- package/extensions/orbit/evidence-override-command.ts +294 -0
- package/extensions/orbit/exec-guard/bash-risk.ts +1408 -0
- package/extensions/orbit/exec-guard/gate.ts +181 -0
- package/extensions/orbit/exec-guard/guardian-config.ts +54 -0
- package/extensions/orbit/exec-guard/index.ts +1 -0
- package/extensions/orbit/exec-guard/model-tier.ts +36 -0
- package/extensions/orbit/exec-guard/path-jail.ts +54 -0
- package/extensions/orbit/exec-guard/policy.ts +342 -0
- package/extensions/orbit/exec-guard/runtime-state.ts +15 -0
- package/extensions/orbit/exec-guard/sensitive-read.ts +525 -0
- package/extensions/orbit/exec-guard/types.ts +42 -0
- package/extensions/orbit/execution-commands.ts +134 -0
- package/extensions/orbit/feedback-command.ts +81 -0
- package/extensions/orbit/feedback.ts +96 -0
- package/extensions/orbit/galaxy-api.test.ts +122 -0
- package/extensions/orbit/galaxy-api.ts +606 -0
- package/extensions/orbit/galaxy-artifact-link-guidance.ts +5 -0
- package/extensions/orbit/galaxy-destructive-gate.ts +113 -0
- package/extensions/orbit/galaxy-enrich.ts +1108 -0
- package/extensions/orbit/galaxy-failure.ts +101 -0
- package/extensions/orbit/galaxy-fixture.ts +126 -0
- package/extensions/orbit/galaxy-history-guard.ts +233 -0
- package/extensions/orbit/galaxy-job-block.ts +347 -0
- package/extensions/orbit/galaxy-job-ops.ts +288 -0
- package/extensions/orbit/galaxy-live-source.ts +929 -0
- package/extensions/orbit/galaxy-markdown-adapter.ts +248 -0
- package/extensions/orbit/galaxy-op-policy.ts +332 -0
- package/extensions/orbit/galaxy-ops-tools.ts +326 -0
- package/extensions/orbit/galaxy-output-store.ts +80 -0
- package/extensions/orbit/galaxy-output.ts +346 -0
- package/extensions/orbit/galaxy-page-binding.ts +222 -0
- package/extensions/orbit/galaxy-page-markdown-guidance.ts +15 -0
- package/extensions/orbit/galaxy-page-ops.ts +159 -0
- package/extensions/orbit/galaxy-page-sync.test.ts +417 -0
- package/extensions/orbit/galaxy-page-sync.ts +318 -0
- package/extensions/orbit/galaxy-pages-api.ts +203 -0
- package/extensions/orbit/galaxy-pages-sync.ts +409 -0
- package/extensions/orbit/galaxy-poll-guard.ts +189 -0
- package/extensions/orbit/galaxy-poller.ts +706 -0
- package/extensions/orbit/galaxy-provenance.ts +623 -0
- package/extensions/orbit/galaxy-reconcile.ts +956 -0
- package/extensions/orbit/galaxy-recovery.ts +176 -0
- package/extensions/orbit/galaxy-repeat-guard.ts +55 -0
- package/extensions/orbit/galaxy-submission-capture.ts +707 -0
- package/extensions/orbit/galaxy-submission.ts +502 -0
- package/extensions/orbit/galaxy-tool-source.ts +78 -0
- package/extensions/orbit/galaxy-tool-wrap.ts +234 -0
- package/extensions/orbit/galaxy-udt-block.ts +127 -0
- package/extensions/orbit/galaxy-upload-tus.ts +334 -0
- package/extensions/orbit/galaxy-upload.ts +300 -0
- package/extensions/orbit/galaxy-version-capture.ts +65 -0
- package/extensions/orbit/git.ts +173 -0
- package/extensions/orbit/harness-block-fields.ts +597 -0
- package/extensions/orbit/index.ts +593 -0
- package/extensions/orbit/init-gate.ts +284 -0
- package/extensions/orbit/instructions-command.ts +136 -0
- package/extensions/orbit/invocation-failure-hint.ts +57 -0
- package/extensions/orbit/iwc-plan-check.ts +94 -0
- package/extensions/orbit/lesson-command.ts +303 -0
- package/extensions/orbit/lesson-hint.ts +245 -0
- package/extensions/orbit/lesson-nudge.ts +106 -0
- package/extensions/orbit/lessons/compose.ts +177 -0
- package/extensions/orbit/lessons/counters.ts +120 -0
- package/extensions/orbit/lessons/enabled.ts +116 -0
- package/extensions/orbit/lessons/matcher.ts +346 -0
- package/extensions/orbit/lessons/paths.ts +286 -0
- package/extensions/orbit/lessons/pi-event-contract.ts +105 -0
- package/extensions/orbit/lessons/propose-replay.ts +103 -0
- package/extensions/orbit/lessons/propose-tool.ts +222 -0
- package/extensions/orbit/lessons/propose.ts +502 -0
- package/extensions/orbit/lessons/replay.ts +89 -0
- package/extensions/orbit/lessons/reproduction-index.ts +83 -0
- package/extensions/orbit/lessons/search-tool.ts +99 -0
- package/extensions/orbit/lessons/search.ts +136 -0
- package/extensions/orbit/lessons/store.ts +415 -0
- package/extensions/orbit/lessons/text.ts +36 -0
- package/extensions/orbit/lessons/types.ts +69 -0
- package/extensions/orbit/lessons/user-dir.ts +24 -0
- package/extensions/orbit/lessons/user-lesson.ts +88 -0
- package/extensions/orbit/lessons/wrapper.ts +61 -0
- package/extensions/orbit/lessons-command.ts +147 -0
- package/extensions/orbit/local-exec.ts +39 -0
- package/extensions/orbit/mcp-output.ts +179 -0
- package/extensions/orbit/mcp-servers.test.ts +24 -0
- package/extensions/orbit/mcp-servers.ts +25 -0
- package/extensions/orbit/model-script.ts +351 -0
- package/extensions/orbit/notebook-anchors.ts +342 -0
- package/extensions/orbit/notebook-writer.ts +863 -0
- package/extensions/orbit/observation-allowlists.ts +1109 -0
- package/extensions/orbit/observation-replay.ts +148 -0
- package/extensions/orbit/observation-triggers.ts +563 -0
- package/extensions/orbit/observation-ui.ts +175 -0
- package/extensions/orbit/observations-command.ts +421 -0
- package/extensions/orbit/observations-config.ts +200 -0
- package/extensions/orbit/observations.ts +1381 -0
- package/extensions/orbit/profiles.ts +270 -0
- package/extensions/orbit/progress-updates.ts +95 -0
- package/extensions/orbit/proposal-commands.ts +882 -0
- package/extensions/orbit/provenance-fs-file.ts +59 -0
- package/extensions/orbit/provenance-fs.ts +32 -0
- package/extensions/orbit/provenance-memory-fs.ts +59 -0
- package/extensions/orbit/record-store-file.ts +177 -0
- package/extensions/orbit/record-store-page.ts +77 -0
- package/extensions/orbit/record-store-seam.ts +47 -0
- package/extensions/orbit/record-store.ts +149 -0
- package/extensions/orbit/registry-carrier.ts +107 -0
- package/extensions/orbit/registry-eligibility.ts +95 -0
- package/extensions/orbit/registry-evaluation.ts +403 -0
- package/extensions/orbit/registry-evaluator.ts +519 -0
- package/extensions/orbit/registry-import.ts +91 -0
- package/extensions/orbit/registry-lock.ts +221 -0
- package/extensions/orbit/registry-memory-fs.ts +42 -0
- package/extensions/orbit/registry-page-carrier.ts +103 -0
- package/extensions/orbit/registry-proposal.ts +1348 -0
- package/extensions/orbit/registry-runtime.ts +234 -0
- package/extensions/orbit/registry-schema.ts +735 -0
- package/extensions/orbit/registry-submitter.ts +59 -0
- package/extensions/orbit/registry-templates.ts +346 -0
- package/extensions/orbit/registry.ts +476 -0
- package/extensions/orbit/sandbox/index.ts +120 -0
- package/extensions/orbit/sandbox/sandbox-bash.ts +93 -0
- package/extensions/orbit/sandbox/sandbox-config.ts +87 -0
- package/extensions/orbit/sandbox/sandbox-init-message.ts +28 -0
- package/extensions/orbit/secret-redaction.ts +247 -0
- package/extensions/orbit/session-index/cwd.ts +18 -0
- package/extensions/orbit/session-index/db.ts +56 -0
- package/extensions/orbit/session-index/indexer.ts +154 -0
- package/extensions/orbit/session-index/is-enabled.ts +17 -0
- package/extensions/orbit/session-index/parse.ts +254 -0
- package/extensions/orbit/session-index/query.ts +209 -0
- package/extensions/orbit/session-index/schema.ts +72 -0
- package/extensions/orbit/session-index/tools.ts +152 -0
- package/extensions/orbit/session-lifecycle.ts +321 -0
- package/extensions/orbit/skill-triggers.ts +159 -0
- package/extensions/orbit/skills-command.ts +48 -0
- package/extensions/orbit/skills-discovery.ts +435 -0
- package/extensions/orbit/skills.ts +84 -0
- package/extensions/orbit/sra-import-gate.ts +77 -0
- package/extensions/orbit/state.ts +265 -0
- package/extensions/orbit/submission-replay.ts +147 -0
- package/extensions/orbit/sync-command.ts +157 -0
- package/extensions/orbit/teams/critic-parser.ts +93 -0
- package/extensions/orbit/teams/dispatcher.ts +210 -0
- package/extensions/orbit/teams/is-enabled.ts +22 -0
- package/extensions/orbit/teams/tool.ts +187 -0
- package/extensions/orbit/teams/types.ts +57 -0
- package/extensions/orbit/teams/validate.ts +42 -0
- package/extensions/orbit/tester-id-command.ts +133 -0
- package/extensions/orbit/tools-sync.ts +279 -0
- package/extensions/orbit/tools.ts +1300 -0
- package/extensions/orbit/types.ts +41 -0
- package/extensions/orbit/ui-bridge.ts +55 -0
- package/extensions/orbit/ulid.ts +60 -0
- package/extensions/orbit/user-instructions.ts +388 -0
- package/extensions/orbit/vendor/skills/_catalog.json +68 -0
- package/extensions/orbit/vendor/skills/_manifest.json +1106 -0
- package/extensions/orbit/vendor/skills/advance-galaxy-draft-step/SKILL.md +112 -0
- package/extensions/orbit/vendor/skills/advance-galaxy-draft-step/_provenance.json +218 -0
- package/extensions/orbit/vendor/skills/advance-galaxy-draft-step/_required_tools.json +33 -0
- package/extensions/orbit/vendor/skills/advance-galaxy-draft-step/_verify.json +4 -0
- package/extensions/orbit/vendor/skills/advance-galaxy-draft-step/references/cli/add.json +50 -0
- package/extensions/orbit/vendor/skills/advance-galaxy-draft-step/references/cli/draft-extract.json +51 -0
- package/extensions/orbit/vendor/skills/advance-galaxy-draft-step/references/cli/draft-next-step.json +42 -0
- package/extensions/orbit/vendor/skills/advance-galaxy-draft-step/references/cli/draft-validate.json +140 -0
- package/extensions/orbit/vendor/skills/advance-galaxy-draft-step/references/cli/list.json +32 -0
- package/extensions/orbit/vendor/skills/advance-galaxy-draft-step/references/notes/galaxy-tool-job-failure-reference.md +137 -0
- package/extensions/orbit/vendor/skills/advance-galaxy-draft-step/references/notes/open-requirements-ledger.md +173 -0
- package/extensions/orbit/vendor/skills/advance-galaxy-draft-step/references/schemas/galaxy-tool-summary.schema.json +175 -0
- package/extensions/orbit/vendor/skills/advance-galaxy-draft-step/references/schemas/galaxy-workflow-draft.schema.json +2727 -0
- package/extensions/orbit/vendor/skills/apply-galaxy-workflow-changeset/SKILL.md +82 -0
- package/extensions/orbit/vendor/skills/apply-galaxy-workflow-changeset/_provenance.json +133 -0
- package/extensions/orbit/vendor/skills/apply-galaxy-workflow-changeset/_required_tools.json +16 -0
- package/extensions/orbit/vendor/skills/apply-galaxy-workflow-changeset/_verify.json +4 -0
- package/extensions/orbit/vendor/skills/apply-galaxy-workflow-changeset/references/cli/draft-validate.json +140 -0
- package/extensions/orbit/vendor/skills/apply-galaxy-workflow-changeset/references/notes/galaxy-workflow-draft-format.md +135 -0
- package/extensions/orbit/vendor/skills/apply-galaxy-workflow-changeset/references/notes/open-requirements-ledger.md +173 -0
- package/extensions/orbit/vendor/skills/apply-galaxy-workflow-changeset/references/schemas/galaxy-workflow-draft.schema.json +2727 -0
- package/extensions/orbit/vendor/skills/changeset-to-galaxy-test-plan/SKILL.md +84 -0
- package/extensions/orbit/vendor/skills/changeset-to-galaxy-test-plan/_provenance.json +166 -0
- package/extensions/orbit/vendor/skills/changeset-to-galaxy-test-plan/_verify.json +29 -0
- package/extensions/orbit/vendor/skills/changeset-to-galaxy-test-plan/references/notes/galaxy-workflow-testability-design.md +136 -0
- package/extensions/orbit/vendor/skills/changeset-to-galaxy-test-plan/references/notes/iwc-shortcuts-anti-patterns.md +357 -0
- package/extensions/orbit/vendor/skills/changeset-to-galaxy-test-plan/references/notes/iwc-test-data-conventions.md +308 -0
- package/extensions/orbit/vendor/skills/changeset-to-galaxy-test-plan/references/notes/planemo-asserts-idioms.md +246 -0
- package/extensions/orbit/vendor/skills/changeset-to-galaxy-test-plan/references/notes/planemo-workflow-test-architecture.md +151 -0
- package/extensions/orbit/vendor/skills/changeset-to-galaxy-test-plan/references/schemas/galaxy-workflow-test-plan.schema.json +552 -0
- package/extensions/orbit/vendor/skills/changeset-to-galaxy-test-plan/references/schemas/summary-galaxy-workflow.schema.json +687 -0
- package/extensions/orbit/vendor/skills/changeset-to-galaxy-test-plan/references/schemas/tests-format.schema.json +7328 -0
- package/extensions/orbit/vendor/skills/compare-against-iwc-exemplar/SKILL.md +127 -0
- package/extensions/orbit/vendor/skills/compare-against-iwc-exemplar/_provenance.json +198 -0
- package/extensions/orbit/vendor/skills/compare-against-iwc-exemplar/_required_tools.json +16 -0
- package/extensions/orbit/vendor/skills/compare-against-iwc-exemplar/_verify.json +4 -0
- package/extensions/orbit/vendor/skills/compare-against-iwc-exemplar/references/cli/convert.json +123 -0
- package/extensions/orbit/vendor/skills/compare-against-iwc-exemplar/references/notes/galaxy-data-flow-draft-contract.md +129 -0
- package/extensions/orbit/vendor/skills/compare-against-iwc-exemplar/references/notes/iwc-shortcuts-anti-patterns.md +357 -0
- package/extensions/orbit/vendor/skills/compare-against-iwc-exemplar/references/notes/iwc-test-data-conventions.md +308 -0
- package/extensions/orbit/vendor/skills/compare-against-iwc-exemplar/references/notes/open-requirements-ledger.md +173 -0
- package/extensions/orbit/vendor/skills/debug-galaxy-workflow-output/SKILL.md +73 -0
- package/extensions/orbit/vendor/skills/debug-galaxy-workflow-output/_provenance.json +160 -0
- package/extensions/orbit/vendor/skills/debug-galaxy-workflow-output/_verify.json +4 -0
- package/extensions/orbit/vendor/skills/debug-galaxy-workflow-output/references/notes/galaxy-collection-semantics.md +43 -0
- package/extensions/orbit/vendor/skills/debug-galaxy-workflow-output/references/notes/galaxy-collection-semantics.yml +1250 -0
- package/extensions/orbit/vendor/skills/debug-galaxy-workflow-output/references/notes/galaxy-tool-job-failure-reference.md +137 -0
- package/extensions/orbit/vendor/skills/debug-galaxy-workflow-output/references/notes/galaxy-workflow-invocation-failure-reference.md +138 -0
- package/extensions/orbit/vendor/skills/debug-galaxy-workflow-output/references/notes/iwc-shortcuts-anti-patterns.md +357 -0
- package/extensions/orbit/vendor/skills/debug-galaxy-workflow-output/references/notes/nextflow-operators-to-galaxy-collection-recipes.md +98 -0
- package/extensions/orbit/vendor/skills/debug-galaxy-workflow-output/references/notes/planemo-asserts-idioms.md +246 -0
- package/extensions/orbit/vendor/skills/debug-galaxy-workflow-output/references/notes/planemo-workflow-test-architecture.md +151 -0
- package/extensions/orbit/vendor/skills/discover-shed-tool/SKILL.md +174 -0
- package/extensions/orbit/vendor/skills/discover-shed-tool/_provenance.json +130 -0
- package/extensions/orbit/vendor/skills/discover-shed-tool/_required_tools.json +18 -0
- package/extensions/orbit/vendor/skills/discover-shed-tool/_verify.json +17 -0
- package/extensions/orbit/vendor/skills/discover-shed-tool/references/cli/tool-revisions.json +48 -0
- package/extensions/orbit/vendor/skills/discover-shed-tool/references/cli/tool-search.json +95 -0
- package/extensions/orbit/vendor/skills/discover-shed-tool/references/cli/tool-versions.json +39 -0
- package/extensions/orbit/vendor/skills/discover-shed-tool/references/notes/component-tool-shed-search.md +230 -0
- package/extensions/orbit/vendor/skills/discover-shed-tool/references/schemas/galaxy-tool-discovery.schema.json +231 -0
- package/extensions/orbit/vendor/skills/implement-galaxy-workflow-test/SKILL.md +93 -0
- package/extensions/orbit/vendor/skills/implement-galaxy-workflow-test/_provenance.json +201 -0
- package/extensions/orbit/vendor/skills/implement-galaxy-workflow-test/_required_tools.json +28 -0
- package/extensions/orbit/vendor/skills/implement-galaxy-workflow-test/_verify.json +17 -0
- package/extensions/orbit/vendor/skills/implement-galaxy-workflow-test/references/cli/planemo.md +44 -0
- package/extensions/orbit/vendor/skills/implement-galaxy-workflow-test/references/cli/validate-tests.json +40 -0
- package/extensions/orbit/vendor/skills/implement-galaxy-workflow-test/references/notes/galaxy-workflow-testability-design.md +136 -0
- package/extensions/orbit/vendor/skills/implement-galaxy-workflow-test/references/notes/iwc-shortcuts-anti-patterns.md +357 -0
- package/extensions/orbit/vendor/skills/implement-galaxy-workflow-test/references/notes/iwc-test-data-conventions.md +308 -0
- package/extensions/orbit/vendor/skills/implement-galaxy-workflow-test/references/notes/planemo-asserts-idioms.md +246 -0
- package/extensions/orbit/vendor/skills/implement-galaxy-workflow-test/references/notes/planemo-workflow-test-architecture.md +151 -0
- package/extensions/orbit/vendor/skills/implement-galaxy-workflow-test/references/schemas/galaxy-workflow-test-plan.schema.json +552 -0
- package/extensions/orbit/vendor/skills/implement-galaxy-workflow-test/references/schemas/tests-format.schema.json +7328 -0
- package/extensions/orbit/vendor/skills/interview-to-galaxy-workflow-changeset/SKILL.md +81 -0
- package/extensions/orbit/vendor/skills/interview-to-galaxy-workflow-changeset/_provenance.json +93 -0
- package/extensions/orbit/vendor/skills/interview-to-galaxy-workflow-changeset/_verify.json +17 -0
- package/extensions/orbit/vendor/skills/interview-to-galaxy-workflow-changeset/references/notes/open-requirements-ledger.md +173 -0
- package/extensions/orbit/vendor/skills/interview-to-galaxy-workflow-changeset/references/schemas/summary-galaxy-workflow.schema.json +687 -0
- package/extensions/orbit/vendor/skills/pipeline-update-interview-to-galaxy/SKILL.md +81 -0
- package/extensions/orbit/vendor/skills/pipeline-update-interview-to-galaxy/_assembly.json +23 -0
- package/extensions/orbit/vendor/skills/run-workflow-test/SKILL.md +79 -0
- package/extensions/orbit/vendor/skills/run-workflow-test/_provenance.json +125 -0
- package/extensions/orbit/vendor/skills/run-workflow-test/_required_tools.json +28 -0
- package/extensions/orbit/vendor/skills/run-workflow-test/_verify.json +4 -0
- package/extensions/orbit/vendor/skills/run-workflow-test/references/cli/planemo.md +44 -0
- package/extensions/orbit/vendor/skills/run-workflow-test/references/cli/validate-tests.json +40 -0
- package/extensions/orbit/vendor/skills/run-workflow-test/references/notes/galaxy-workflow-invocation-failure-reference.md +138 -0
- package/extensions/orbit/vendor/skills/run-workflow-test/references/notes/planemo-asserts-idioms.md +246 -0
- package/extensions/orbit/vendor/skills/run-workflow-test/references/notes/planemo-workflow-test-architecture.md +151 -0
- package/extensions/orbit/vendor/skills/run-workflow-test/references/schemas/tests-format.schema.json +7328 -0
- package/extensions/orbit/vendor/skills/skills/LICENSE +21 -0
- package/extensions/orbit/vendor/skills/skills/collection-manipulation/README.md +39 -0
- package/extensions/orbit/vendor/skills/skills/collection-manipulation/SKILL.md +892 -0
- package/extensions/orbit/vendor/skills/skills/collection-manipulation/references/api-patterns.md +927 -0
- package/extensions/orbit/vendor/skills/skills/collection-manipulation/references/apply-rules.md +1482 -0
- package/extensions/orbit/vendor/skills/skills/collection-manipulation/references/test-patterns.md +996 -0
- package/extensions/orbit/vendor/skills/skills/collection-manipulation/references/tools.md +609 -0
- package/extensions/orbit/vendor/skills/skills/galaxy-data-libraries/SKILL.md +170 -0
- package/extensions/orbit/vendor/skills/skills/galaxy-integration/README.md +162 -0
- package/extensions/orbit/vendor/skills/skills/galaxy-integration/SKILL.md +99 -0
- package/extensions/orbit/vendor/skills/skills/galaxy-integration/examples/README.md +119 -0
- package/extensions/orbit/vendor/skills/skills/galaxy-integration/examples/tool-checking.md +419 -0
- package/extensions/orbit/vendor/skills/skills/galaxy-integration/examples/workflow-testing.md +617 -0
- package/extensions/orbit/vendor/skills/skills/galaxy-integration/galaxy-integration.md +614 -0
- package/extensions/orbit/vendor/skills/skills/galaxy-integration/jupyterlite/SKILL.md +144 -0
- package/extensions/orbit/vendor/skills/skills/galaxy-integration/jupyterlite/examples/average_col3.ipynb +68 -0
- package/extensions/orbit/vendor/skills/skills/galaxy-integration/jupyterlite/examples/extract_sample_metadata.ipynb +190 -0
- package/extensions/orbit/vendor/skills/skills/galaxy-integration/jupyterlite/examples/variant_annotation.ipynb +816 -0
- package/extensions/orbit/vendor/skills/skills/galaxy-integration/jupyterlite/examples/vcp_variant_map.ipynb +443 -0
- package/extensions/orbit/vendor/skills/skills/galaxy-integration/scripts/README.md +165 -0
- package/extensions/orbit/vendor/skills/skills/galaxy-integration/scripts/galaxy_tool_checker.py +521 -0
- package/extensions/orbit/vendor/skills/skills/galaxy-mcp-reference/SKILL.md +128 -0
- package/extensions/orbit/vendor/skills/skills/galaxy-mcp-reference/gotchas.md +135 -0
- package/extensions/orbit/vendor/skills/skills/galaxy-mcp-reference/history-access.md +132 -0
- package/extensions/orbit/vendor/skills/skills/reproduciblify/SKILL.md +146 -0
- package/extensions/orbit/vendor/skills/skills/reproduciblify/references/directives.yml +496 -0
- package/extensions/orbit/vendor/skills/skills/udt-authoring/SKILL.md +245 -0
- package/extensions/orbit/vendor/skills/skills/udt-authoring/examples/01-minimal-echo.yml +27 -0
- package/extensions/orbit/vendor/skills/skills/udt-authoring/examples/02-single-data-in-out.yml +27 -0
- package/extensions/orbit/vendor/skills/skills/udt-authoring/examples/03-multiple-data-js.yml +28 -0
- package/extensions/orbit/vendor/skills/skills/udt-authoring/examples/04-select-integer-boolean.yml +41 -0
- package/extensions/orbit/vendor/skills/skills/udt-authoring/examples/05-resource-requirements.yml +25 -0
- package/extensions/orbit/vendor/skills/skills/udt-authoring/examples/06-biocontainer-tool.yml +38 -0
- package/extensions/orbit/vendor/skills/skills/udt-authoring/examples/07-inline-python-script.yml +56 -0
- package/extensions/orbit/vendor/skills/skills/udt-authoring/examples/08-configfile-script.yml +74 -0
- package/extensions/orbit/vendor/skills/skills/udt-authoring/references/common-mistakes.md +76 -0
- package/extensions/orbit/vendor/skills/skills/udt-authoring/references/schema-reference.md +155 -0
- package/extensions/orbit/vendor/skills/skills/udt-authoring/references/templating.md +196 -0
- package/extensions/orbit/vendor/skills/skills/udt-authoring/scripts/validate.py +109 -0
- package/extensions/orbit/vendor/skills/skills/workflow-reports/README.md +71 -0
- package/extensions/orbit/vendor/skills/skills/workflow-reports/SKILL.md +190 -0
- package/extensions/orbit/vendor/skills/skills/workflow-reports/examples/histology-staining.md +145 -0
- package/extensions/orbit/vendor/skills/skills/workflow-reports/examples/tissue-microarray-analysis.md +176 -0
- package/extensions/orbit/vendor/skills/skills/workflow-reports/references/directives.md +415 -0
- package/extensions/orbit/vendor/skills/summarize-galaxy-workflow/SKILL.md +98 -0
- package/extensions/orbit/vendor/skills/summarize-galaxy-workflow/_provenance.json +93 -0
- package/extensions/orbit/vendor/skills/summarize-galaxy-workflow/_required_tools.json +28 -0
- package/extensions/orbit/vendor/skills/summarize-galaxy-workflow/_verify.json +17 -0
- package/extensions/orbit/vendor/skills/summarize-galaxy-workflow/references/cli/convert.json +123 -0
- package/extensions/orbit/vendor/skills/summarize-galaxy-workflow/references/cli/foundry.md +25 -0
- package/extensions/orbit/vendor/skills/summarize-galaxy-workflow/references/cli/validate.json +142 -0
- package/extensions/orbit/vendor/skills/summarize-galaxy-workflow/references/schemas/summary-galaxy-workflow.schema.json +687 -0
- package/extensions/orbit/vendor/skills/validate-galaxy-workflow/SKILL.md +74 -0
- package/extensions/orbit/vendor/skills/validate-galaxy-workflow/_provenance.json +71 -0
- package/extensions/orbit/vendor/skills/validate-galaxy-workflow/_required_tools.json +16 -0
- package/extensions/orbit/vendor/skills/validate-galaxy-workflow/_verify.json +4 -0
- package/extensions/orbit/vendor/skills/validate-galaxy-workflow/references/cli/validate.json +142 -0
- package/extensions/orbit/vendor/skills/validate-galaxy-workflow/references/notes/galaxy-workflow-invocation-failure-reference.md +138 -0
- package/extensions/orbit/vendor/skills/validate-galaxy-workflow/references/notes/galaxy-workflow-testability-design.md +136 -0
- package/extensions/orbit/vendor-skills.ts +283 -0
- package/extensions/orbit/workspace-state-dir.ts +46 -0
- package/extensions/orbit-handoff/index.ts +73 -0
- package/extensions/orbit-handoff/orbit-launcher.ts +142 -0
- package/extensions/whats-new/index.ts +98 -0
- package/lessons/LICENSE +17 -0
- package/lessons/README.md +117 -0
- package/lessons/SCHEMA.md +187 -0
- package/lessons/build-snapshot.mjs +311 -0
- package/lessons/data/downloaded-file-is-not-what-its-extension-says.md +61 -0
- package/lessons/galaxy-api/403-history-is-a-hard-stop.md +57 -0
- package/lessons/galaxy-api/collection-into-single-dataset-input.md +61 -0
- package/lessons/galaxy-api/connectedvalue-in-command-line.md +62 -0
- package/lessons/galaxy-api/hid-is-not-an-id.md +59 -0
- package/lessons/galaxy-api/invoke-workflow-inputs-not-params.md +60 -0
- package/lessons/galaxy-api/repeat-param-pipe-keys.md +63 -0
- package/lessons/galaxy-api/run-tool-returns-on-submit.md +61 -0
- package/lessons/galaxy-tools/reference-index-not-on-server.md +62 -0
- package/lessons/log.md +42 -0
- package/lessons/reproduction/input-population-mismatch.md +59 -0
- package/lessons/reproduction/methods-text-vs-executed-parameters.md +62 -0
- package/lessons/snapshot.json +1004 -0
- package/lessons/stats/de-contrast-direction-and-sample-labels.md +63 -0
- package/lessons/stats/na-coerced-to-zero-in-filters.md +59 -0
- package/lessons/validate.mjs +1219 -0
- package/package.json +103 -5
- package/shared/agent-prompt.d.ts +8 -0
- package/shared/agent-prompt.js +15 -0
- package/shared/approval-prompt.d.ts +4 -0
- package/shared/approval-prompt.js +61 -0
- package/shared/brain-env.d.ts +14 -0
- package/shared/brain-env.js +108 -0
- package/shared/brain-exit.d.ts +20 -0
- package/shared/brain-exit.js +149 -0
- package/shared/capability-profile.d.ts +16 -0
- package/shared/capability-profile.js +75 -0
- package/shared/config-source.d.ts +13 -0
- package/shared/config-source.js +17 -0
- package/shared/confusables.d.ts +3 -0
- package/shared/confusables.js +93 -0
- package/shared/custom-provider.d.ts +45 -0
- package/shared/custom-provider.js +169 -0
- package/shared/dashboard-contract.d.ts +123 -0
- package/shared/dashboard-contract.js +560 -0
- package/shared/dashboard-layout-store.d.ts +44 -0
- package/shared/dashboard-layout-store.js +281 -0
- package/shared/feedback-contract.d.ts +61 -0
- package/shared/feedback-contract.js +146 -0
- package/shared/galaxy-artifact-links.d.ts +30 -0
- package/shared/galaxy-artifact-links.js +166 -0
- package/shared/galaxy-credentials.d.ts +26 -0
- package/shared/galaxy-credentials.js +71 -0
- package/shared/galaxy-destructive.d.ts +21 -0
- package/shared/galaxy-destructive.js +269 -0
- package/shared/galaxy-guidance.d.ts +2 -0
- package/shared/galaxy-guidance.js +53 -0
- package/shared/galaxy-live-contract.d.ts +92 -0
- package/shared/galaxy-live-contract.js +180 -0
- package/shared/galaxy-page-cells.d.ts +2 -0
- package/shared/galaxy-page-cells.js +22 -0
- package/shared/galaxy-tool-family.d.ts +5 -0
- package/shared/galaxy-tool-family.js +27 -0
- package/shared/galaxy-url.d.ts +1 -0
- package/shared/galaxy-url.js +48 -0
- package/shared/gtn.d.ts +31 -0
- package/shared/gtn.js +253 -0
- package/shared/handled-prompt.d.ts +3 -0
- package/shared/handled-prompt.js +26 -0
- package/shared/known-provider.d.ts +11 -0
- package/shared/known-provider.js +89 -0
- package/shared/lesson-hint-marker.d.ts +7 -0
- package/shared/lesson-hint-marker.js +32 -0
- package/shared/lesson-rules.d.ts +150 -0
- package/shared/lesson-rules.js +203 -0
- package/shared/malformed-object-ids.d.ts +1 -0
- package/shared/malformed-object-ids.js +37 -0
- package/shared/markdown-sections.d.ts +10 -0
- package/shared/markdown-sections.js +118 -0
- package/shared/notebook-fences.d.ts +12 -0
- package/shared/notebook-fences.js +53 -0
- package/shared/observation-contract.d.ts +91 -0
- package/shared/observation-contract.js +544 -0
- package/shared/orbit-config.d.ts +226 -0
- package/shared/orbit-config.js +189 -0
- package/shared/orbit-env.d.ts +13 -0
- package/shared/orbit-env.js +124 -0
- package/shared/orbit-shell-contract.d.ts +74 -0
- package/shared/orbit-shell-contract.js +30 -0
- package/shared/page-content-hash.d.ts +1 -0
- package/shared/page-content-hash.js +13 -0
- package/shared/pi-default-model.d.ts +7 -0
- package/shared/pi-default-model.js +41 -0
- package/shared/prompt-blocks.d.ts +87 -0
- package/shared/prompt-blocks.js +898 -0
- package/shared/provider-auth-caps.d.ts +22 -0
- package/shared/provider-auth-caps.js +57 -0
- package/shared/random.d.ts +2 -0
- package/shared/random.js +15 -0
- package/shared/record-excerpt.d.ts +4 -0
- package/shared/record-excerpt.js +16 -0
- package/shared/redirect-guard.d.ts +36 -0
- package/shared/redirect-guard.js +235 -0
- package/shared/skills-pin.d.ts +8 -0
- package/shared/skills-pin.js +9 -0
- package/shared/skills-router.d.ts +17 -0
- package/shared/skills-router.js +63 -0
- package/shared/sra-import.d.ts +34 -0
- package/shared/sra-import.js +206 -0
- package/shared/state-dir.d.ts +21 -0
- package/shared/state-dir.js +240 -0
- package/shared/team-dispatch-contract.d.ts +28 -0
- package/shared/team-dispatch-contract.js +1 -0
- package/shared/truncate-middle.d.ts +11 -0
- package/shared/truncate-middle.js +68 -0
- package/shared/version-compare.d.ts +10 -0
- package/shared/version-compare.js +74 -0
- package/shared/whats-new.d.ts +31 -0
- package/shared/whats-new.js +83 -0
- package/shared/wsl.d.ts +10 -0
- package/shared/wsl.js +24 -0
|
@@ -0,0 +1,816 @@
|
|
|
1
|
+
{
|
|
2
|
+
"cells": [
|
|
3
|
+
{
|
|
4
|
+
"cell_type": "markdown",
|
|
5
|
+
"metadata": {},
|
|
6
|
+
"source": "# Variant Annotation: Synonymous vs Nonsynonymous\n\n## What This Notebook Does\n\nThis notebook takes a list of genetic variants (mutations) and determines whether each variant:\n- **Changes the protein** (nonsynonymous) - potentially affects function\n- **Does NOT change the protein** (synonymous) - silent mutation\n- **Is outside genes** (intergenic) - not in a protein-coding region\n\n## Background: How DNA Encodes Proteins\n\n```\nDNA: ATG GCT TAC ... (read in groups of 3 bases called \"codons\")\n ↓ ↓ ↓\nProtein: Met Ala Tyr ... (each codon = 1 amino acid)\n```\n\nBecause the genetic code is **redundant** (multiple codons can encode the same amino acid),\nsome mutations don't change the protein:\n\n- `GCT` → Alanine\n- `GCC` → Alanine (same amino acid! This would be a **synonymous** mutation)\n- `GCT` → `GAT` → Aspartic acid (different amino acid = **nonsynonymous**)\n\n## Inputs\n\n1. **GenBank file** (dataset #13372): Contains the reference genome with gene annotations\n2. **Variant table** (dataset #13437): List of mutations found in samples"
|
|
7
|
+
},
|
|
8
|
+
{
|
|
9
|
+
"cell_type": "markdown",
|
|
10
|
+
"metadata": {},
|
|
11
|
+
"source": "---\n## Step 1: Import Libraries\n\nWe need a few Python libraries:\n- `gxy`: Galaxy-specific library to download/upload files\n- `pandas`: For working with tables (like Excel but in Python)\n- `Bio` (Biopython): For reading GenBank files and translating DNA\n- `altair`: For creating interactive visualizations"
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
"cell_type": "code",
|
|
15
|
+
"execution_count": null,
|
|
16
|
+
"metadata": {},
|
|
17
|
+
"outputs": [],
|
|
18
|
+
"source": "# Galaxy integration - lets us download datasets from the history\nimport gxy\n\n# Pandas - work with data tables\nimport pandas as pd\n\n# Biopython - parse GenBank files and translate DNA to protein\nfrom Bio import SeqIO\nfrom Bio.Data import CodonTable\n\n# Altair - create interactive charts\nimport altair as alt\nalt.data_transformers.disable_max_rows() # Allow large datasets\n\n# Suppress Altair/narwhals compatibility warnings (harmless but noisy)\nimport warnings\nwarnings.filterwarnings('ignore', message='.*narwhals.*')\n\nprint(\"Libraries loaded successfully!\")"
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
"cell_type": "code",
|
|
22
|
+
"execution_count": null,
|
|
23
|
+
"metadata": {},
|
|
24
|
+
"outputs": [],
|
|
25
|
+
"source": "# Define which Galaxy datasets to use\n# These numbers correspond to the dataset IDs in your Galaxy history\n\nGENBANK_DATASET = 13372 # GenBank annotation file (contains gene locations)\nVARIANTS_DATASET = 13437 # Variant table (list of mutations)"
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
"cell_type": "markdown",
|
|
29
|
+
"metadata": {},
|
|
30
|
+
"source": [
|
|
31
|
+
"---\n",
|
|
32
|
+
"## Step 2: Download Data from Galaxy\n",
|
|
33
|
+
"\n",
|
|
34
|
+
"The `gxy.get()` function downloads a dataset from your Galaxy history to this notebook's environment."
|
|
35
|
+
]
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
"cell_type": "code",
|
|
39
|
+
"execution_count": null,
|
|
40
|
+
"metadata": {},
|
|
41
|
+
"outputs": [],
|
|
42
|
+
"source": "# Download the GenBank annotation file\ngenbank_path = await gxy.get(GENBANK_DATASET)\nprint(f\"Downloaded GenBank file to: {genbank_path}\")"
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
"cell_type": "code",
|
|
46
|
+
"execution_count": null,
|
|
47
|
+
"metadata": {},
|
|
48
|
+
"outputs": [],
|
|
49
|
+
"source": "# Download the variant table\nvariants_path = await gxy.get(VARIANTS_DATASET)\nprint(f\"Downloaded variants file to: {variants_path}\")"
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
"cell_type": "markdown",
|
|
53
|
+
"metadata": {},
|
|
54
|
+
"source": [
|
|
55
|
+
"---\n",
|
|
56
|
+
"## Step 3: Parse the GenBank File\n",
|
|
57
|
+
"\n",
|
|
58
|
+
"### What is a GenBank file?\n",
|
|
59
|
+
"\n",
|
|
60
|
+
"A GenBank file contains:\n",
|
|
61
|
+
"1. The full genome sequence (DNA)\n",
|
|
62
|
+
"2. Annotations showing where genes are located\n",
|
|
63
|
+
"\n",
|
|
64
|
+
"Each gene has a \"CDS\" (Coding Sequence) feature that tells us:\n",
|
|
65
|
+
"- Start and end positions on the genome\n",
|
|
66
|
+
"- Gene name and protein product\n",
|
|
67
|
+
"- Which strand (+ or -) it's on"
|
|
68
|
+
]
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
"cell_type": "code",
|
|
72
|
+
"execution_count": null,
|
|
73
|
+
"metadata": {},
|
|
74
|
+
"outputs": [],
|
|
75
|
+
"source": [
|
|
76
|
+
"# Load the GenBank file\n",
|
|
77
|
+
"record = SeqIO.read(genbank_path, \"genbank\")\n",
|
|
78
|
+
"\n",
|
|
79
|
+
"print(f\"Genome ID: {record.id}\")\n",
|
|
80
|
+
"print(f\"Genome length: {len(record.seq):,} bases\")\n",
|
|
81
|
+
"print(f\"Description: {record.description}\")"
|
|
82
|
+
]
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
"cell_type": "code",
|
|
86
|
+
"execution_count": null,
|
|
87
|
+
"metadata": {},
|
|
88
|
+
"outputs": [],
|
|
89
|
+
"source": [
|
|
90
|
+
"# Find all CDS (protein-coding) features\n",
|
|
91
|
+
"# These are the genes we'll use for annotation\n",
|
|
92
|
+
"\n",
|
|
93
|
+
"cds_features = [f for f in record.features if f.type == \"CDS\"]\n",
|
|
94
|
+
"\n",
|
|
95
|
+
"print(f\"Found {len(cds_features)} protein-coding genes (CDS features)\")\n",
|
|
96
|
+
"print(\"\\nFirst few genes:\")\n",
|
|
97
|
+
"for i, feat in enumerate(cds_features[:5]):\n",
|
|
98
|
+
" # Get gene name from the 'gene' or 'locus_tag' field\n",
|
|
99
|
+
" gene_name = feat.qualifiers.get(\"gene\", feat.qualifiers.get(\"locus_tag\", [\"unknown\"]))[0]\n",
|
|
100
|
+
" product = feat.qualifiers.get(\"product\", [\"unknown\"])[0]\n",
|
|
101
|
+
" print(f\" {i+1}. {gene_name}: {product}\")"
|
|
102
|
+
]
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
"cell_type": "markdown",
|
|
106
|
+
"metadata": {},
|
|
107
|
+
"source": [
|
|
108
|
+
"---\n",
|
|
109
|
+
"## Step 4: Build a Lookup Table for Every Position in Every Gene\n",
|
|
110
|
+
"\n",
|
|
111
|
+
"To annotate variants, we need to know for EVERY position in the genome:\n",
|
|
112
|
+
"- Is it inside a gene?\n",
|
|
113
|
+
"- If yes, which codon does it belong to?\n",
|
|
114
|
+
"- What amino acid does that codon encode?\n",
|
|
115
|
+
"\n",
|
|
116
|
+
"We'll build a table where each row represents one nucleotide position.\n",
|
|
117
|
+
"\n",
|
|
118
|
+
"### Understanding Codon Position\n",
|
|
119
|
+
"\n",
|
|
120
|
+
"Each codon has 3 bases. The position within the codon matters:\n",
|
|
121
|
+
"\n",
|
|
122
|
+
"```\n",
|
|
123
|
+
"Codon: A T G\n",
|
|
124
|
+
"Position: 1 2 3\n",
|
|
125
|
+
" ↑ ↑\n",
|
|
126
|
+
" | └── 3rd position: often \"wobble\" - mutations here are often synonymous\n",
|
|
127
|
+
" └────────── 1st position: mutations here usually change the amino acid\n",
|
|
128
|
+
"```"
|
|
129
|
+
]
|
|
130
|
+
},
|
|
131
|
+
{
|
|
132
|
+
"cell_type": "code",
|
|
133
|
+
"execution_count": null,
|
|
134
|
+
"metadata": {},
|
|
135
|
+
"outputs": [],
|
|
136
|
+
"source": [
|
|
137
|
+
"def get_gene_info(feature):\n",
|
|
138
|
+
" \"\"\"\n",
|
|
139
|
+
" Extract useful information from a CDS feature.\n",
|
|
140
|
+
" \n",
|
|
141
|
+
" Returns a dictionary with gene name, product, and translation settings.\n",
|
|
142
|
+
" \"\"\"\n",
|
|
143
|
+
" q = feature.qualifiers\n",
|
|
144
|
+
" \n",
|
|
145
|
+
" return {\n",
|
|
146
|
+
" # Gene name - try 'gene' first, fall back to 'locus_tag'\n",
|
|
147
|
+
" \"gene\": (q.get(\"gene\") or q.get(\"locus_tag\") or [\"\"])[0],\n",
|
|
148
|
+
" \n",
|
|
149
|
+
" # Protein product description\n",
|
|
150
|
+
" \"product\": (q.get(\"product\") or [\"\"])[0],\n",
|
|
151
|
+
" \n",
|
|
152
|
+
" # Codon start - which base of the first codon is the start\n",
|
|
153
|
+
" # Usually 1, but can be 2 or 3 for partial genes\n",
|
|
154
|
+
" \"codon_start\": int((q.get(\"codon_start\") or [\"1\"])[0]),\n",
|
|
155
|
+
" \n",
|
|
156
|
+
" # Translation table - which genetic code to use\n",
|
|
157
|
+
" # 1 = standard, 11 = bacterial/plastid, etc.\n",
|
|
158
|
+
" \"transl_table\": int((q.get(\"transl_table\") or [\"1\"])[0]),\n",
|
|
159
|
+
" }\n",
|
|
160
|
+
"\n",
|
|
161
|
+
"# Test on the first gene\n",
|
|
162
|
+
"test_info = get_gene_info(cds_features[0])\n",
|
|
163
|
+
"print(\"Example gene info:\")\n",
|
|
164
|
+
"for key, value in test_info.items():\n",
|
|
165
|
+
" print(f\" {key}: {value}\")"
|
|
166
|
+
]
|
|
167
|
+
},
|
|
168
|
+
{
|
|
169
|
+
"cell_type": "code",
|
|
170
|
+
"execution_count": null,
|
|
171
|
+
"metadata": {},
|
|
172
|
+
"outputs": [],
|
|
173
|
+
"source": [
|
|
174
|
+
"def codon_to_amino_acid(codon, transl_table=1):\n",
|
|
175
|
+
" \"\"\"\n",
|
|
176
|
+
" Translate a 3-letter DNA codon to its amino acid.\n",
|
|
177
|
+
" \n",
|
|
178
|
+
" Examples:\n",
|
|
179
|
+
" 'ATG' -> 'M' (Methionine, start codon)\n",
|
|
180
|
+
" 'TAA' -> '*' (Stop codon)\n",
|
|
181
|
+
" 'GCT' -> 'A' (Alanine)\n",
|
|
182
|
+
" \"\"\"\n",
|
|
183
|
+
" # Get the correct codon table (standard = 1, bacterial = 11, etc.)\n",
|
|
184
|
+
" table = CodonTable.unambiguous_dna_by_id.get(transl_table, \n",
|
|
185
|
+
" CodonTable.unambiguous_dna_by_id[1])\n",
|
|
186
|
+
" \n",
|
|
187
|
+
" codon = codon.upper()\n",
|
|
188
|
+
" \n",
|
|
189
|
+
" # Check if it's a stop codon\n",
|
|
190
|
+
" if codon in table.stop_codons:\n",
|
|
191
|
+
" return \"*\"\n",
|
|
192
|
+
" \n",
|
|
193
|
+
" # Look up the amino acid\n",
|
|
194
|
+
" return table.forward_table.get(codon, \"?\") # \"?\" if unknown\n",
|
|
195
|
+
"\n",
|
|
196
|
+
"# Test the function\n",
|
|
197
|
+
"print(\"Testing codon translation:\")\n",
|
|
198
|
+
"test_codons = [\"ATG\", \"GCT\", \"GCC\", \"TAA\", \"TGA\"]\n",
|
|
199
|
+
"for codon in test_codons:\n",
|
|
200
|
+
" aa = codon_to_amino_acid(codon)\n",
|
|
201
|
+
" print(f\" {codon} -> {aa}\")"
|
|
202
|
+
]
|
|
203
|
+
},
|
|
204
|
+
{
|
|
205
|
+
"cell_type": "code",
|
|
206
|
+
"execution_count": null,
|
|
207
|
+
"metadata": {},
|
|
208
|
+
"outputs": [],
|
|
209
|
+
"source": [
|
|
210
|
+
"def build_cds_lookup_table(record):\n",
|
|
211
|
+
" \"\"\"\n",
|
|
212
|
+
" Build a table with one row per nucleotide for all CDS features.\n",
|
|
213
|
+
" \n",
|
|
214
|
+
" For each nucleotide, we record:\n",
|
|
215
|
+
" - genome_pos: position on the genome (1-based)\n",
|
|
216
|
+
" - gene: gene name\n",
|
|
217
|
+
" - product: protein product\n",
|
|
218
|
+
" - base: the nucleotide (A, T, G, or C)\n",
|
|
219
|
+
" - codon: the 3-letter codon this base belongs to\n",
|
|
220
|
+
" - codon_pos: position within the codon (1, 2, or 3)\n",
|
|
221
|
+
" - aa: the amino acid the codon encodes\n",
|
|
222
|
+
" \"\"\"\n",
|
|
223
|
+
" rows = [] # Will hold all our data\n",
|
|
224
|
+
" \n",
|
|
225
|
+
" # Process each CDS feature (gene)\n",
|
|
226
|
+
" for feature in record.features:\n",
|
|
227
|
+
" if feature.type != \"CDS\":\n",
|
|
228
|
+
" continue\n",
|
|
229
|
+
" \n",
|
|
230
|
+
" # Get gene information\n",
|
|
231
|
+
" info = get_gene_info(feature)\n",
|
|
232
|
+
" \n",
|
|
233
|
+
" # Extract the CDS sequence (handles strand automatically)\n",
|
|
234
|
+
" cds_seq = str(feature.extract(record.seq))\n",
|
|
235
|
+
" \n",
|
|
236
|
+
" # Get the genomic positions for each base in the CDS\n",
|
|
237
|
+
" # This handles + and - strand genes correctly\n",
|
|
238
|
+
" strand = feature.location.strand or 1\n",
|
|
239
|
+
" \n",
|
|
240
|
+
" # Build list of genome positions in transcription order\n",
|
|
241
|
+
" genome_positions = []\n",
|
|
242
|
+
" for part in feature.location.parts:\n",
|
|
243
|
+
" start, end = int(part.start), int(part.end)\n",
|
|
244
|
+
" if strand >= 0:\n",
|
|
245
|
+
" # Forward strand: positions go 5' to 3'\n",
|
|
246
|
+
" positions = list(range(start + 1, end + 1)) # +1 for 1-based\n",
|
|
247
|
+
" else:\n",
|
|
248
|
+
" # Reverse strand: positions go 3' to 5' (reverse order)\n",
|
|
249
|
+
" positions = list(range(end, start, -1)) # Already 1-based\n",
|
|
250
|
+
" genome_positions.extend(positions)\n",
|
|
251
|
+
" \n",
|
|
252
|
+
" # Handle codon_start (frame offset)\n",
|
|
253
|
+
" frame_offset = info[\"codon_start\"] - 1\n",
|
|
254
|
+
" \n",
|
|
255
|
+
" # Process each nucleotide\n",
|
|
256
|
+
" n = len(cds_seq)\n",
|
|
257
|
+
" for i in range(n):\n",
|
|
258
|
+
" base = cds_seq[i]\n",
|
|
259
|
+
" \n",
|
|
260
|
+
" # Calculate codon information\n",
|
|
261
|
+
" in_frame = i + frame_offset\n",
|
|
262
|
+
" codon_pos = (in_frame % 3) + 1 # 1, 2, or 3\n",
|
|
263
|
+
" codon_number = (in_frame // 3) + 1\n",
|
|
264
|
+
" \n",
|
|
265
|
+
" # Get the full codon (3 bases)\n",
|
|
266
|
+
" codon_start_idx = in_frame - (in_frame % 3) - frame_offset\n",
|
|
267
|
+
" if codon_start_idx >= 0 and codon_start_idx + 2 < n:\n",
|
|
268
|
+
" codon = cds_seq[codon_start_idx:codon_start_idx + 3]\n",
|
|
269
|
+
" aa = codon_to_amino_acid(codon, info[\"transl_table\"])\n",
|
|
270
|
+
" else:\n",
|
|
271
|
+
" codon = \"NNN\" # Incomplete codon\n",
|
|
272
|
+
" aa = \"?\"\n",
|
|
273
|
+
" \n",
|
|
274
|
+
" # Add row to our table\n",
|
|
275
|
+
" rows.append({\n",
|
|
276
|
+
" \"genome_pos\": genome_positions[i],\n",
|
|
277
|
+
" \"gene\": info[\"gene\"],\n",
|
|
278
|
+
" \"product\": info[\"product\"],\n",
|
|
279
|
+
" \"base\": base,\n",
|
|
280
|
+
" \"codon\": codon,\n",
|
|
281
|
+
" \"codon_pos\": codon_pos,\n",
|
|
282
|
+
" \"codon_number\": codon_number,\n",
|
|
283
|
+
" \"aa\": aa,\n",
|
|
284
|
+
" })\n",
|
|
285
|
+
" \n",
|
|
286
|
+
" # Convert to DataFrame and sort by position\n",
|
|
287
|
+
" df = pd.DataFrame(rows)\n",
|
|
288
|
+
" df = df.sort_values([\"gene\", \"product\", \"genome_pos\"])\n",
|
|
289
|
+
" df = df.reset_index(drop=True)\n",
|
|
290
|
+
" \n",
|
|
291
|
+
" return df\n",
|
|
292
|
+
"\n",
|
|
293
|
+
"print(\"Building CDS lookup table (this may take a moment)...\")\n",
|
|
294
|
+
"cds_table = build_cds_lookup_table(record)\n",
|
|
295
|
+
"print(f\"Done! Table has {len(cds_table):,} rows\")"
|
|
296
|
+
]
|
|
297
|
+
},
|
|
298
|
+
{
|
|
299
|
+
"cell_type": "code",
|
|
300
|
+
"execution_count": null,
|
|
301
|
+
"metadata": {},
|
|
302
|
+
"outputs": [],
|
|
303
|
+
"source": [
|
|
304
|
+
"# Let's look at the CDS table we built\n",
|
|
305
|
+
"print(\"CDS lookup table summary:\")\n",
|
|
306
|
+
"print(f\" Total nucleotide positions: {len(cds_table):,}\")\n",
|
|
307
|
+
"print(f\" Unique genes: {cds_table['gene'].nunique()}\")\n",
|
|
308
|
+
"print(f\" Unique products: {cds_table['product'].nunique()}\")\n",
|
|
309
|
+
"\n",
|
|
310
|
+
"print(\"\\nFirst 15 rows (showing start of first gene):\")\n",
|
|
311
|
+
"cds_table.head(15)"
|
|
312
|
+
]
|
|
313
|
+
},
|
|
314
|
+
{
|
|
315
|
+
"cell_type": "markdown",
|
|
316
|
+
"metadata": {},
|
|
317
|
+
"source": [
|
|
318
|
+
"---\n",
|
|
319
|
+
"## Step 5: Load the Variant Table\n",
|
|
320
|
+
"\n",
|
|
321
|
+
"The variant table contains mutations found in the samples. Each row is one variant with:\n",
|
|
322
|
+
"- Position on the genome\n",
|
|
323
|
+
"- Reference allele (what the genome has)\n",
|
|
324
|
+
"- Alternate allele (what the mutation is)\n",
|
|
325
|
+
"- Frequency information"
|
|
326
|
+
]
|
|
327
|
+
},
|
|
328
|
+
{
|
|
329
|
+
"cell_type": "code",
|
|
330
|
+
"execution_count": null,
|
|
331
|
+
"metadata": {},
|
|
332
|
+
"outputs": [],
|
|
333
|
+
"source": [
|
|
334
|
+
"# Load the variant table\n",
|
|
335
|
+
"# This file has no header, so we specify column names\n",
|
|
336
|
+
"variants = pd.read_csv(\n",
|
|
337
|
+
" variants_path,\n",
|
|
338
|
+
" sep=\"\\t\", # Tab-separated\n",
|
|
339
|
+
" header=None, # No header row\n",
|
|
340
|
+
" names=[\"var_id\", \"samples\", \"af_min\", \"af_mean\", \"af_max\", \"REF\", \"ALT\"]\n",
|
|
341
|
+
")\n",
|
|
342
|
+
"\n",
|
|
343
|
+
"print(f\"Loaded {len(variants)} variants\")\n",
|
|
344
|
+
"print(\"\\nColumn descriptions:\")\n",
|
|
345
|
+
"print(\" var_id: Unique identifier (includes position)\")\n",
|
|
346
|
+
"print(\" samples: Number of samples with this variant\")\n",
|
|
347
|
+
"print(\" af_min/mean/max: Allele frequency statistics\")\n",
|
|
348
|
+
"print(\" REF: Reference allele\")\n",
|
|
349
|
+
"print(\" ALT: Alternate allele (the mutation)\")\n",
|
|
350
|
+
"\n",
|
|
351
|
+
"variants.head()"
|
|
352
|
+
]
|
|
353
|
+
},
|
|
354
|
+
{
|
|
355
|
+
"cell_type": "code",
|
|
356
|
+
"execution_count": null,
|
|
357
|
+
"metadata": {},
|
|
358
|
+
"outputs": [],
|
|
359
|
+
"source": [
|
|
360
|
+
"# Extract the position number from the var_id column\n",
|
|
361
|
+
"# The var_id looks like \"10044GA\" - the number is the position\n",
|
|
362
|
+
"\n",
|
|
363
|
+
"variants[\"POS\"] = variants[\"var_id\"].str.extract(r\"^(\\d+)\").astype(int)\n",
|
|
364
|
+
"\n",
|
|
365
|
+
"print(\"Added POS column:\")\n",
|
|
366
|
+
"print(f\" Position range: {variants['POS'].min()} to {variants['POS'].max()}\")\n",
|
|
367
|
+
"variants[[\"var_id\", \"POS\", \"REF\", \"ALT\"]].head()"
|
|
368
|
+
]
|
|
369
|
+
},
|
|
370
|
+
{
|
|
371
|
+
"cell_type": "markdown",
|
|
372
|
+
"metadata": {},
|
|
373
|
+
"source": [
|
|
374
|
+
"---\n",
|
|
375
|
+
"## Step 6: Annotate Variants\n",
|
|
376
|
+
"\n",
|
|
377
|
+
"Now we'll combine the variants with our CDS lookup table to determine the effect of each mutation.\n",
|
|
378
|
+
"\n",
|
|
379
|
+
"### The Process\n",
|
|
380
|
+
"\n",
|
|
381
|
+
"For each variant:\n",
|
|
382
|
+
"1. Look up the position in the CDS table\n",
|
|
383
|
+
"2. If not found → it's **intergenic** (not in a gene)\n",
|
|
384
|
+
"3. If found:\n",
|
|
385
|
+
" - Get the original codon and amino acid\n",
|
|
386
|
+
" - Create the mutated codon (swap the variant base)\n",
|
|
387
|
+
" - Translate the mutated codon\n",
|
|
388
|
+
" - If same amino acid → **synonymous**\n",
|
|
389
|
+
" - If different → **nonsynonymous**"
|
|
390
|
+
]
|
|
391
|
+
},
|
|
392
|
+
{
|
|
393
|
+
"cell_type": "code",
|
|
394
|
+
"execution_count": null,
|
|
395
|
+
"metadata": {},
|
|
396
|
+
"outputs": [],
|
|
397
|
+
"source": [
|
|
398
|
+
"# Helper function: get the complement of a DNA base\n",
|
|
399
|
+
"# This is needed for genes on the reverse strand\n",
|
|
400
|
+
"\n",
|
|
401
|
+
"COMPLEMENT = {\"A\": \"T\", \"T\": \"A\", \"G\": \"C\", \"C\": \"G\",\n",
|
|
402
|
+
" \"a\": \"t\", \"t\": \"a\", \"g\": \"c\", \"c\": \"g\"}\n",
|
|
403
|
+
"\n",
|
|
404
|
+
"def complement(base):\n",
|
|
405
|
+
" \"\"\"Return the complement of a DNA base (A↔T, G↔C).\"\"\"\n",
|
|
406
|
+
" return COMPLEMENT.get(base, base)\n",
|
|
407
|
+
"\n",
|
|
408
|
+
"print(\"Testing complement:\")\n",
|
|
409
|
+
"for b in [\"A\", \"T\", \"G\", \"C\"]:\n",
|
|
410
|
+
" print(f\" {b} -> {complement(b)}\")"
|
|
411
|
+
]
|
|
412
|
+
},
|
|
413
|
+
{
|
|
414
|
+
"cell_type": "code",
|
|
415
|
+
"execution_count": null,
|
|
416
|
+
"metadata": {},
|
|
417
|
+
"outputs": [],
|
|
418
|
+
"source": [
|
|
419
|
+
"def annotate_variants_with_effects(variants_df, cds_df):\n",
|
|
420
|
+
" \"\"\"\n",
|
|
421
|
+
" Annotate each variant with its effect on the protein.\n",
|
|
422
|
+
" \n",
|
|
423
|
+
" Returns a new DataFrame with additional columns:\n",
|
|
424
|
+
" - strand: '+' or '-' (which strand the gene is on)\n",
|
|
425
|
+
" - new_codon: the codon after the mutation\n",
|
|
426
|
+
" - new_aa: the amino acid after the mutation\n",
|
|
427
|
+
" - effect: 'synonymous', 'nonsynonymous', or 'intergenic'\n",
|
|
428
|
+
" \"\"\"\n",
|
|
429
|
+
" \n",
|
|
430
|
+
" # Merge variants with CDS table based on position\n",
|
|
431
|
+
" # This gives us the codon/amino acid context for each variant\n",
|
|
432
|
+
" merged = variants_df.merge(\n",
|
|
433
|
+
" cds_df,\n",
|
|
434
|
+
" left_on=\"POS\",\n",
|
|
435
|
+
" right_on=\"genome_pos\",\n",
|
|
436
|
+
" how=\"left\" # Keep all variants, even if not in a gene\n",
|
|
437
|
+
" )\n",
|
|
438
|
+
" \n",
|
|
439
|
+
" # Lists to store our results\n",
|
|
440
|
+
" strands = []\n",
|
|
441
|
+
" new_codons = []\n",
|
|
442
|
+
" new_aas = []\n",
|
|
443
|
+
" effects = []\n",
|
|
444
|
+
" \n",
|
|
445
|
+
" # Process each row\n",
|
|
446
|
+
" for idx, row in merged.iterrows():\n",
|
|
447
|
+
" \n",
|
|
448
|
+
" # Check if this position is in a gene\n",
|
|
449
|
+
" if pd.isna(row.get(\"codon\")):\n",
|
|
450
|
+
" # Not in a gene\n",
|
|
451
|
+
" strands.append(None)\n",
|
|
452
|
+
" new_codons.append(None)\n",
|
|
453
|
+
" new_aas.append(None)\n",
|
|
454
|
+
" effects.append(\"intergenic\")\n",
|
|
455
|
+
" continue\n",
|
|
456
|
+
" \n",
|
|
457
|
+
" # Get the values we need\n",
|
|
458
|
+
" ref_base = str(row[\"REF\"]).upper()\n",
|
|
459
|
+
" alt_base = str(row[\"ALT\"]).upper()\n",
|
|
460
|
+
" cds_base = str(row[\"base\"]).upper() # Base in the CDS (may be complemented)\n",
|
|
461
|
+
" codon = str(row[\"codon\"]).upper()\n",
|
|
462
|
+
" codon_pos = int(row[\"codon_pos\"]) # 1, 2, or 3\n",
|
|
463
|
+
" old_aa = str(row[\"aa\"])\n",
|
|
464
|
+
" \n",
|
|
465
|
+
" # Determine strand by comparing ref_base to cds_base\n",
|
|
466
|
+
" if ref_base == cds_base:\n",
|
|
467
|
+
" # Same base = forward strand\n",
|
|
468
|
+
" strand = \"+\"\n",
|
|
469
|
+
" coding_alt = alt_base\n",
|
|
470
|
+
" elif complement(ref_base) == cds_base:\n",
|
|
471
|
+
" # Complement = reverse strand\n",
|
|
472
|
+
" strand = \"-\"\n",
|
|
473
|
+
" coding_alt = complement(alt_base)\n",
|
|
474
|
+
" else:\n",
|
|
475
|
+
" # Mismatch - something's wrong\n",
|
|
476
|
+
" strands.append(\"?\")\n",
|
|
477
|
+
" new_codons.append(None)\n",
|
|
478
|
+
" new_aas.append(None)\n",
|
|
479
|
+
" effects.append(\"unknown\")\n",
|
|
480
|
+
" continue\n",
|
|
481
|
+
" \n",
|
|
482
|
+
" strands.append(strand)\n",
|
|
483
|
+
" \n",
|
|
484
|
+
" # Create the mutated codon\n",
|
|
485
|
+
" # Replace the base at codon_pos with the new base\n",
|
|
486
|
+
" codon_list = list(codon)\n",
|
|
487
|
+
" codon_list[codon_pos - 1] = coding_alt # -1 because codon_pos is 1-based\n",
|
|
488
|
+
" new_codon = \"\".join(codon_list)\n",
|
|
489
|
+
" new_codons.append(new_codon)\n",
|
|
490
|
+
" \n",
|
|
491
|
+
" # Translate the new codon\n",
|
|
492
|
+
" new_aa = codon_to_amino_acid(new_codon)\n",
|
|
493
|
+
" new_aas.append(new_aa)\n",
|
|
494
|
+
" \n",
|
|
495
|
+
" # Determine the effect\n",
|
|
496
|
+
" if old_aa == \"?\" or new_aa == \"?\":\n",
|
|
497
|
+
" effects.append(\"unknown\")\n",
|
|
498
|
+
" elif new_aa == old_aa:\n",
|
|
499
|
+
" effects.append(\"synonymous\")\n",
|
|
500
|
+
" else:\n",
|
|
501
|
+
" effects.append(\"nonsynonymous\")\n",
|
|
502
|
+
" \n",
|
|
503
|
+
" # Add our results to the DataFrame\n",
|
|
504
|
+
" merged[\"strand\"] = strands\n",
|
|
505
|
+
" merged[\"new_codon\"] = new_codons\n",
|
|
506
|
+
" merged[\"new_aa\"] = new_aas\n",
|
|
507
|
+
" merged[\"effect\"] = effects\n",
|
|
508
|
+
" \n",
|
|
509
|
+
" return merged\n",
|
|
510
|
+
"\n",
|
|
511
|
+
"print(\"Annotating variants (this may take a moment)...\")\n",
|
|
512
|
+
"annotated = annotate_variants_with_effects(variants, cds_table)\n",
|
|
513
|
+
"print(f\"Done! Annotated {len(annotated)} rows\")\n",
|
|
514
|
+
"print(\"\\n(Note: Some variants appear multiple times if they affect overlapping genes)\")"
|
|
515
|
+
]
|
|
516
|
+
},
|
|
517
|
+
{
|
|
518
|
+
"cell_type": "markdown",
|
|
519
|
+
"metadata": {},
|
|
520
|
+
"source": [
|
|
521
|
+
"---\n",
|
|
522
|
+
"## Step 7: View Results\n",
|
|
523
|
+
"\n",
|
|
524
|
+
"Let's see what we found!"
|
|
525
|
+
]
|
|
526
|
+
},
|
|
527
|
+
{
|
|
528
|
+
"cell_type": "code",
|
|
529
|
+
"execution_count": null,
|
|
530
|
+
"metadata": {},
|
|
531
|
+
"outputs": [],
|
|
532
|
+
"source": [
|
|
533
|
+
"# Summary of effects\n",
|
|
534
|
+
"print(\"=\" * 50)\n",
|
|
535
|
+
"print(\"VARIANT EFFECT SUMMARY\")\n",
|
|
536
|
+
"print(\"=\" * 50)\n",
|
|
537
|
+
"print(annotated[\"effect\"].value_counts())\n",
|
|
538
|
+
"print(\"\\n\")\n",
|
|
539
|
+
"\n",
|
|
540
|
+
"# Calculate percentages\n",
|
|
541
|
+
"total = len(annotated)\n",
|
|
542
|
+
"for effect in [\"nonsynonymous\", \"synonymous\", \"intergenic\"]:\n",
|
|
543
|
+
" count = (annotated[\"effect\"] == effect).sum()\n",
|
|
544
|
+
" pct = 100 * count / total\n",
|
|
545
|
+
" print(f\" {effect}: {count} ({pct:.1f}%)\")"
|
|
546
|
+
]
|
|
547
|
+
},
|
|
548
|
+
{
|
|
549
|
+
"cell_type": "code",
|
|
550
|
+
"execution_count": null,
|
|
551
|
+
"metadata": {},
|
|
552
|
+
"outputs": [],
|
|
553
|
+
"source": [
|
|
554
|
+
"# View the annotated variants\n",
|
|
555
|
+
"# Select the most important columns for display\n",
|
|
556
|
+
"\n",
|
|
557
|
+
"display_columns = [\n",
|
|
558
|
+
" \"var_id\", # Variant ID\n",
|
|
559
|
+
" \"POS\", # Genome position\n",
|
|
560
|
+
" \"REF\", # Reference allele\n",
|
|
561
|
+
" \"ALT\", # Alternate allele\n",
|
|
562
|
+
" \"gene\", # Gene name\n",
|
|
563
|
+
" \"product\", # Protein product\n",
|
|
564
|
+
" \"codon\", # Original codon\n",
|
|
565
|
+
" \"new_codon\", # Mutated codon\n",
|
|
566
|
+
" \"aa\", # Original amino acid\n",
|
|
567
|
+
" \"new_aa\", # New amino acid\n",
|
|
568
|
+
" \"effect\", # Effect type\n",
|
|
569
|
+
" \"samples\", # Number of samples\n",
|
|
570
|
+
" \"af_mean\" # Mean allele frequency\n",
|
|
571
|
+
"]\n",
|
|
572
|
+
"\n",
|
|
573
|
+
"print(\"First 20 annotated variants:\")\n",
|
|
574
|
+
"annotated[display_columns].head(20)"
|
|
575
|
+
]
|
|
576
|
+
},
|
|
577
|
+
{
|
|
578
|
+
"cell_type": "code",
|
|
579
|
+
"execution_count": null,
|
|
580
|
+
"metadata": {},
|
|
581
|
+
"outputs": [],
|
|
582
|
+
"source": [
|
|
583
|
+
"# Summary by gene\n",
|
|
584
|
+
"print(\"Effect counts by gene:\")\n",
|
|
585
|
+
"gene_summary = annotated.pivot_table(\n",
|
|
586
|
+
" index=\"gene\",\n",
|
|
587
|
+
" columns=\"effect\",\n",
|
|
588
|
+
" values=\"var_id\",\n",
|
|
589
|
+
" aggfunc=\"nunique\", # Count unique variants\n",
|
|
590
|
+
" fill_value=0\n",
|
|
591
|
+
")\n",
|
|
592
|
+
"gene_summary"
|
|
593
|
+
]
|
|
594
|
+
},
|
|
595
|
+
{
|
|
596
|
+
"cell_type": "markdown",
|
|
597
|
+
"metadata": {},
|
|
598
|
+
"source": [
|
|
599
|
+
"---\n",
|
|
600
|
+
"## Step 8: Visualization\n",
|
|
601
|
+
"\n",
|
|
602
|
+
"We'll create two charts:\n",
|
|
603
|
+
"1. **Variant track**: Shows where variants are located and their effects\n",
|
|
604
|
+
"2. **Amino acid heatmap**: Shows the amino acid context across genes\n",
|
|
605
|
+
"\n",
|
|
606
|
+
"Both charts share the same X-axis (genome position), so you can zoom in on one and both will update."
|
|
607
|
+
]
|
|
608
|
+
},
|
|
609
|
+
{
|
|
610
|
+
"cell_type": "code",
|
|
611
|
+
"execution_count": null,
|
|
612
|
+
"metadata": {},
|
|
613
|
+
"outputs": [],
|
|
614
|
+
"source": [
|
|
615
|
+
"# Prepare data for visualization\n",
|
|
616
|
+
"\n",
|
|
617
|
+
"# For the heatmap: add a label column for amino acids\n",
|
|
618
|
+
"cds_vis = cds_table.copy()\n",
|
|
619
|
+
"cds_vis[\"aa_label\"] = cds_vis[\"aa\"].replace({\"*\": \"Stop\", \"?\": \"Unknown\"})\n",
|
|
620
|
+
"\n",
|
|
621
|
+
"# Get the order of products (genes) by their position on the genome\n",
|
|
622
|
+
"product_order = (\n",
|
|
623
|
+
" cds_vis.groupby(\"product\")[\"genome_pos\"]\n",
|
|
624
|
+
" .min()\n",
|
|
625
|
+
" .sort_values()\n",
|
|
626
|
+
" .index.tolist()\n",
|
|
627
|
+
")\n",
|
|
628
|
+
"\n",
|
|
629
|
+
"print(f\"Products (genes) in order: {len(product_order)}\")"
|
|
630
|
+
]
|
|
631
|
+
},
|
|
632
|
+
{
|
|
633
|
+
"cell_type": "code",
|
|
634
|
+
"execution_count": null,
|
|
635
|
+
"metadata": {},
|
|
636
|
+
"outputs": [],
|
|
637
|
+
"source": [
|
|
638
|
+
"# Create the amino acid heatmap\n",
|
|
639
|
+
"# Each rectangle represents one nucleotide, colored by amino acid\n",
|
|
640
|
+
"\n",
|
|
641
|
+
"# Add columns for rectangle coordinates\n",
|
|
642
|
+
"cds_vis[\"x2\"] = cds_vis[\"genome_pos\"] + 1 # End of rectangle\n",
|
|
643
|
+
"\n",
|
|
644
|
+
"heatmap = alt.Chart(cds_vis).mark_rect().encode(\n",
|
|
645
|
+
" # X-axis: genome position\n",
|
|
646
|
+
" x=alt.X(\"genome_pos:Q\", title=\"Genome position\"),\n",
|
|
647
|
+
" x2=\"x2:Q\",\n",
|
|
648
|
+
" \n",
|
|
649
|
+
" # Y-axis: gene product\n",
|
|
650
|
+
" y=alt.Y(\"product:N\", sort=product_order, title=\"Gene\"),\n",
|
|
651
|
+
" \n",
|
|
652
|
+
" # Color by amino acid\n",
|
|
653
|
+
" color=alt.Color(\"aa_label:N\", title=\"Amino acid\"),\n",
|
|
654
|
+
" \n",
|
|
655
|
+
" # Tooltip shows details on hover\n",
|
|
656
|
+
" tooltip=[\"gene\", \"product\", \"genome_pos\", \"codon\", \"aa_label\", \"base\"]\n",
|
|
657
|
+
").properties(\n",
|
|
658
|
+
" width=900,\n",
|
|
659
|
+
" height=max(140, 18 * len(product_order)),\n",
|
|
660
|
+
" title=\"Amino acid context by position\"\n",
|
|
661
|
+
")\n",
|
|
662
|
+
"\n",
|
|
663
|
+
"print(\"Heatmap created!\")"
|
|
664
|
+
]
|
|
665
|
+
},
|
|
666
|
+
{
|
|
667
|
+
"cell_type": "code",
|
|
668
|
+
"execution_count": null,
|
|
669
|
+
"metadata": {},
|
|
670
|
+
"outputs": [],
|
|
671
|
+
"source": [
|
|
672
|
+
"# Create the variant track\n",
|
|
673
|
+
"# Shows variants as tick marks, colored by effect\n",
|
|
674
|
+
"\n",
|
|
675
|
+
"# Filter to only coding variants (synonymous or nonsynonymous)\n",
|
|
676
|
+
"coding_variants = annotated[\n",
|
|
677
|
+
" annotated[\"effect\"].isin([\"synonymous\", \"nonsynonymous\"])\n",
|
|
678
|
+
"].copy()\n",
|
|
679
|
+
"\n",
|
|
680
|
+
"# Calculate allele frequency range for sizing\n",
|
|
681
|
+
"coding_variants[\"af_range\"] = coding_variants[\"af_max\"] - coding_variants[\"af_min\"]\n",
|
|
682
|
+
"\n",
|
|
683
|
+
"# Get product order for these variants\n",
|
|
684
|
+
"var_product_order = (\n",
|
|
685
|
+
" coding_variants.groupby(\"product\")[\"POS\"]\n",
|
|
686
|
+
" .min()\n",
|
|
687
|
+
" .sort_values()\n",
|
|
688
|
+
" .index.tolist()\n",
|
|
689
|
+
")\n",
|
|
690
|
+
"\n",
|
|
691
|
+
"variant_track = alt.Chart(coding_variants).mark_tick(thickness=4).encode(\n",
|
|
692
|
+
" # X-axis: genome position\n",
|
|
693
|
+
" x=alt.X(\"POS:Q\", title=\"Genome position\"),\n",
|
|
694
|
+
" \n",
|
|
695
|
+
" # Y-axis: gene product\n",
|
|
696
|
+
" y=alt.Y(\"product:N\", sort=var_product_order, title=\"Gene\"),\n",
|
|
697
|
+
" \n",
|
|
698
|
+
" # Color: green for synonymous, red for nonsynonymous\n",
|
|
699
|
+
" color=alt.Color(\n",
|
|
700
|
+
" \"effect:N\",\n",
|
|
701
|
+
" title=\"Effect\",\n",
|
|
702
|
+
" scale=alt.Scale(\n",
|
|
703
|
+
" domain=[\"synonymous\", \"nonsynonymous\"],\n",
|
|
704
|
+
" range=[\"#2ca02c\", \"#d62728\"] # Green, Red\n",
|
|
705
|
+
" )\n",
|
|
706
|
+
" ),\n",
|
|
707
|
+
" \n",
|
|
708
|
+
" # Size: based on allele frequency range\n",
|
|
709
|
+
" size=alt.Size(\"af_range:Q\", title=\"AF range\"),\n",
|
|
710
|
+
" \n",
|
|
711
|
+
" # Opacity: based on number of samples\n",
|
|
712
|
+
" opacity=alt.Opacity(\"samples:Q\", title=\"Samples\"),\n",
|
|
713
|
+
" \n",
|
|
714
|
+
" # Tooltip shows details on hover\n",
|
|
715
|
+
" tooltip=[\n",
|
|
716
|
+
" \"var_id\", \"POS\", \"REF\", \"ALT\",\n",
|
|
717
|
+
" \"gene\", \"product\", \"effect\",\n",
|
|
718
|
+
" \"codon\", \"new_codon\", \"aa\", \"new_aa\",\n",
|
|
719
|
+
" \"samples\", \"af_mean\"\n",
|
|
720
|
+
" ]\n",
|
|
721
|
+
").properties(\n",
|
|
722
|
+
" width=900,\n",
|
|
723
|
+
" height=max(120, 16 * len(var_product_order)),\n",
|
|
724
|
+
" title=\"Variants by position (green=synonymous, red=nonsynonymous)\"\n",
|
|
725
|
+
")\n",
|
|
726
|
+
"\n",
|
|
727
|
+
"print(\"Variant track created!\")"
|
|
728
|
+
]
|
|
729
|
+
},
|
|
730
|
+
{
|
|
731
|
+
"cell_type": "code",
|
|
732
|
+
"execution_count": null,
|
|
733
|
+
"metadata": {},
|
|
734
|
+
"outputs": [],
|
|
735
|
+
"source": [
|
|
736
|
+
"# Combine both charts with shared X-axis zooming\n",
|
|
737
|
+
"# Click and drag on either chart to zoom - both will update!\n",
|
|
738
|
+
"\n",
|
|
739
|
+
"# Create a selection for X-axis zooming\n",
|
|
740
|
+
"zoom = alt.selection_interval(bind=\"scales\", encodings=[\"x\"])\n",
|
|
741
|
+
"\n",
|
|
742
|
+
"# Stack the charts vertically\n",
|
|
743
|
+
"combined_chart = alt.vconcat(\n",
|
|
744
|
+
" variant_track, # Variants on top\n",
|
|
745
|
+
" heatmap, # Amino acids below\n",
|
|
746
|
+
" spacing=10 # Gap between charts\n",
|
|
747
|
+
").resolve_scale(\n",
|
|
748
|
+
" x=\"shared\", # Share the X-axis between charts\n",
|
|
749
|
+
" color=\"independent\" # Keep colors separate\n",
|
|
750
|
+
").add_params(\n",
|
|
751
|
+
" zoom # Add zooming capability\n",
|
|
752
|
+
")\n",
|
|
753
|
+
"\n",
|
|
754
|
+
"print(\"Combined chart ready!\")\n",
|
|
755
|
+
"print(\"Tip: Click and drag on the chart to zoom in. Double-click to reset.\")\n",
|
|
756
|
+
"\n",
|
|
757
|
+
"combined_chart"
|
|
758
|
+
]
|
|
759
|
+
},
|
|
760
|
+
{
|
|
761
|
+
"cell_type": "markdown",
|
|
762
|
+
"metadata": {},
|
|
763
|
+
"source": [
|
|
764
|
+
"---\n",
|
|
765
|
+
"## Step 9: Save Results (Optional)\n",
|
|
766
|
+
"\n",
|
|
767
|
+
"Uncomment the cells below to save the annotated variants back to your Galaxy history."
|
|
768
|
+
]
|
|
769
|
+
},
|
|
770
|
+
{
|
|
771
|
+
"cell_type": "code",
|
|
772
|
+
"execution_count": null,
|
|
773
|
+
"metadata": {},
|
|
774
|
+
"outputs": [],
|
|
775
|
+
"source": [
|
|
776
|
+
"# Uncomment to save the annotated variants as a tabular file in Galaxy\n",
|
|
777
|
+
"\n",
|
|
778
|
+
"# annotated.to_csv(\"annotated_variants.tsv\", sep=\"\\t\", index=False)\n",
|
|
779
|
+
"# await gxy.put(\"annotated_variants.tsv\", output=\"Annotated Variants\", ext=\"tabular\")\n",
|
|
780
|
+
"# print(\"Saved annotated variants to Galaxy history!\")"
|
|
781
|
+
]
|
|
782
|
+
},
|
|
783
|
+
{
|
|
784
|
+
"cell_type": "markdown",
|
|
785
|
+
"metadata": {},
|
|
786
|
+
"source": [
|
|
787
|
+
"---\n",
|
|
788
|
+
"## Summary\n",
|
|
789
|
+
"\n",
|
|
790
|
+
"This notebook:\n",
|
|
791
|
+
"1. Downloaded GenBank annotation and variant data from Galaxy\n",
|
|
792
|
+
"2. Built a lookup table mapping every nucleotide to its codon and amino acid\n",
|
|
793
|
+
"3. Annotated each variant with its effect (synonymous, nonsynonymous, or intergenic)\n",
|
|
794
|
+
"4. Created an interactive visualization showing variant positions and effects\n",
|
|
795
|
+
"\n",
|
|
796
|
+
"**Key findings:**\n",
|
|
797
|
+
"- Most variants are nonsynonymous (change the protein)\n",
|
|
798
|
+
"- Synonymous variants are less common (\"silent\" mutations)\n",
|
|
799
|
+
"- The visualization lets you explore which genes have the most variants"
|
|
800
|
+
]
|
|
801
|
+
}
|
|
802
|
+
],
|
|
803
|
+
"metadata": {
|
|
804
|
+
"kernelspec": {
|
|
805
|
+
"display_name": "Python 3",
|
|
806
|
+
"language": "python",
|
|
807
|
+
"name": "python3"
|
|
808
|
+
},
|
|
809
|
+
"language_info": {
|
|
810
|
+
"name": "python",
|
|
811
|
+
"version": "3.10.0"
|
|
812
|
+
}
|
|
813
|
+
},
|
|
814
|
+
"nbformat": 4,
|
|
815
|
+
"nbformat_minor": 4
|
|
816
|
+
}
|