rowan-python 3.1.3__tar.gz → 3.1.4__tar.gz
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.
- {rowan_python-3.1.3 → rowan_python-3.1.4}/PKG-INFO +1 -1
- {rowan_python-3.1.3 → rowan_python-3.1.4}/docs/index.md +32 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/examples/batch_docking.py +1 -1
- {rowan_python-3.1.3 → rowan_python-3.1.4}/examples/boltz_paired_msa.py +2 -2
- {rowan_python-3.1.3 → rowan_python-3.1.4}/examples/boltz_single_msa.py +2 -2
- {rowan_python-3.1.3 → rowan_python-3.1.4}/examples/chai_paired_msa.py +2 -2
- {rowan_python-3.1.3 → rowan_python-3.1.4}/examples/chai_single_msa.py +2 -2
- {rowan_python-3.1.3 → rowan_python-3.1.4}/examples/colabfold_paired_msa.py +2 -2
- {rowan_python-3.1.3 → rowan_python-3.1.4}/examples/colabfold_single_msa.py +2 -2
- rowan_python-3.1.4/examples/docking.py +39 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/examples/docking_screen.py +5 -2
- {rowan_python-3.1.3 → rowan_python-3.1.4}/examples/pocket_detection.py +1 -1
- rowan_python-3.1.4/examples/resubmit_with_perturbations.py +39 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/examples/scan.py +7 -7
- {rowan_python-3.1.3 → rowan_python-3.1.4}/pyproject.toml +1 -1
- {rowan_python-3.1.3 → rowan_python-3.1.4}/rowan/__init__.py +6 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/rowan/calculation.py +16 -8
- {rowan_python-3.1.3 → rowan_python-3.1.4}/rowan/folder.py +120 -1
- {rowan_python-3.1.3 → rowan_python-3.1.4}/rowan/molecule.py +73 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/rowan/protein.py +92 -13
- {rowan_python-3.1.3 → rowan_python-3.1.4}/rowan/utils.py +21 -1
- {rowan_python-3.1.3 → rowan_python-3.1.4}/rowan/workflows/base.py +22 -3
- {rowan_python-3.1.3 → rowan_python-3.1.4}/rowan/workflows/basic_calculation.py +1 -1
- {rowan_python-3.1.3 → rowan_python-3.1.4}/rowan/workflows/docking.py +10 -7
- {rowan_python-3.1.3 → rowan_python-3.1.4}/rowan/workflows/fukui.py +2 -19
- {rowan_python-3.1.3 → rowan_python-3.1.4}/rowan/workflows/msa.py +15 -22
- {rowan_python-3.1.3 → rowan_python-3.1.4}/rowan/workflows/pka.py +2 -6
- {rowan_python-3.1.3 → rowan_python-3.1.4}/rowan/workflows/protein_md.py +22 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/skills/computational-chemistry-and-biology/SKILL.md +4 -2
- {rowan_python-3.1.3 → rowan_python-3.1.4}/skills/computational-chemistry-and-biology/reference/conformer_search.md +1 -1
- {rowan_python-3.1.3 → rowan_python-3.1.4}/skills/computational-chemistry-and-biology/reference/docking.md +14 -9
- rowan_python-3.1.4/skills/computational-chemistry-and-biology/reference/folders_and_projects.md +59 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/skills/computational-chemistry-and-biology/reference/msa.md +3 -3
- {rowan_python-3.1.3 → rowan_python-3.1.4}/skills/computational-chemistry-and-biology/reference/pose_analysis_md.md +6 -1
- {rowan_python-3.1.3 → rowan_python-3.1.4}/skills/computational-chemistry-and-biology/reference/protein_md.md +1 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/skills/computational-chemistry-and-biology/reference/protein_prep.md +2 -2
- {rowan_python-3.1.3 → rowan_python-3.1.4}/skills/computational-chemistry-and-biology/reference/scan.md +11 -11
- {rowan_python-3.1.3 → rowan_python-3.1.4}/.envrc +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/.github/workflows/build-and-deploy-docs.yml +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/.github/workflows/publish-skill.yml +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/.github/workflows/python-publish.yml +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/.github/workflows/test.yml +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/.gitignore +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/.pre-commit-config.yaml +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/AGENTS.md +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/CLAUDE.md +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/GEMINI.md +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/LICENSE +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/README.md +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/docs/images/deciduous-tree-favicon.png +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/docs/stylesheets/colors.css +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/examples/PROTAC_solubility.py +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/examples/admet.py +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/examples/analogue_docking.py +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/examples/aqueous_solubility.py +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/examples/basic_calculation.py +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/examples/basic_calculation_from_json.py +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/examples/basic_calculation_with_constraint.py +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/examples/basic_calculation_with_solvent.py +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/examples/bde.py +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/examples/cofolding_screen.py +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/examples/conformer_dependent_redox.py +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/examples/conformers.py +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/examples/conformers_screen.py +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/examples/data/1iep_receptorH.pdb +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/examples/data/Al_FCC.xyz +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/examples/data/citalopram_1iep.xyz +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/examples/data/ibuprofen_conformers.sdf +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/examples/data/tyk2_ligands.sdf +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/examples/data/tyk2_structure.pdb +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/examples/data/workflow_example.json +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/examples/dcd_download.py +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/examples/descriptors.py +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/examples/double_ended_ts_search.py +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/examples/electronic_properties.py +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/examples/estimate_workflow.py +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/examples/fukui_index.py +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/examples/hydrogen_bond_basicity.py +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/examples/interaction_energy_decomposition.py +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/examples/ion_mobility.py +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/examples/irc.py +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/examples/macropka.py +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/examples/membrane_permeability.py +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/examples/multistage_optimization.py +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/examples/nmr.py +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/examples/optimization.py +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/examples/pdb_download.py +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/examples/periodic_dft.py +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/examples/phenol_pka.py +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/examples/pka.py +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/examples/pose_analysis_md.py +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/examples/project_scoped_api_key.py +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/examples/protein_binder_design.py +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/examples/protein_cofolding.py +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/examples/protein_cofolding_with_constraints.py +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/examples/protein_cofolding_with_templates.py +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/examples/protein_md.py +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/examples/rbfe_graph.py +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/examples/rbfe_resubmit.py +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/examples/redox_potential.py +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/examples/relative_binding_free_energy_perturbation.py +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/examples/retrieve_workflow.py +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/examples/solvent_dependent_conformers.py +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/examples/spin_states.py +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/examples/strain.py +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/examples/tautomer.py +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/examples/template.py +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/examples/webhook.py +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/mkdocs.yml +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/pixi.lock +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/rowan/api_keys.py +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/rowan/config.py +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/rowan/constants.py +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/rowan/project.py +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/rowan/py.typed +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/rowan/types.py +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/rowan/user.py +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/rowan/workflows/__init__.py +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/rowan/workflows/admet.py +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/rowan/workflows/analogue_docking.py +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/rowan/workflows/batch_docking.py +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/rowan/workflows/bde.py +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/rowan/workflows/conformer_search.py +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/rowan/workflows/constants.py +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/rowan/workflows/descriptors.py +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/rowan/workflows/double_ended_ts_search.py +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/rowan/workflows/electronic_properties.py +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/rowan/workflows/hydrogen_bond_donor_acceptor_strength.py +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/rowan/workflows/interaction_energy_decomposition.py +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/rowan/workflows/ion_mobility.py +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/rowan/workflows/irc.py +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/rowan/workflows/macropka.py +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/rowan/workflows/membrane_permeability.py +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/rowan/workflows/multistage_optimization.py +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/rowan/workflows/nmr.py +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/rowan/workflows/pocket_detection.py +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/rowan/workflows/pose_analysis_md.py +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/rowan/workflows/protein_binder_design.py +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/rowan/workflows/protein_cofolding.py +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/rowan/workflows/rbfe_graph.py +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/rowan/workflows/redox_potential.py +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/rowan/workflows/relative_binding_free_energy_perturbation.py +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/rowan/workflows/scan.py +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/rowan/workflows/solubility.py +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/rowan/workflows/solvent_dependent_conformers.py +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/rowan/workflows/spin_states.py +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/rowan/workflows/strain.py +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/rowan/workflows/tautomer_search.py +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/skills/computational-chemistry-and-biology/reference/admet.md +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/skills/computational-chemistry-and-biology/reference/analogue_docking.md +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/skills/computational-chemistry-and-biology/reference/basic_calculation.md +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/skills/computational-chemistry-and-biology/reference/batch_docking.md +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/skills/computational-chemistry-and-biology/reference/bde.md +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/skills/computational-chemistry-and-biology/reference/descriptors.md +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/skills/computational-chemistry-and-biology/reference/double_ended_ts_search.md +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/skills/computational-chemistry-and-biology/reference/electronic_properties.md +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/skills/computational-chemistry-and-biology/reference/fukui.md +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/skills/computational-chemistry-and-biology/reference/hydrogen_bond_donor_acceptor_strength.md +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/skills/computational-chemistry-and-biology/reference/interaction_energy_decomposition.md +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/skills/computational-chemistry-and-biology/reference/ion_mobility.md +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/skills/computational-chemistry-and-biology/reference/irc.md +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/skills/computational-chemistry-and-biology/reference/macropka.md +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/skills/computational-chemistry-and-biology/reference/membrane_permeability.md +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/skills/computational-chemistry-and-biology/reference/multistage_optimization.md +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/skills/computational-chemistry-and-biology/reference/nmr.md +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/skills/computational-chemistry-and-biology/reference/pka.md +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/skills/computational-chemistry-and-biology/reference/pocket_detection.md +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/skills/computational-chemistry-and-biology/reference/protein_binder_design.md +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/skills/computational-chemistry-and-biology/reference/protein_cofolding.md +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/skills/computational-chemistry-and-biology/reference/rbfe_graph.md +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/skills/computational-chemistry-and-biology/reference/redox_potential.md +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/skills/computational-chemistry-and-biology/reference/relative_binding_free_energy_perturbation.md +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/skills/computational-chemistry-and-biology/reference/solubility.md +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/skills/computational-chemistry-and-biology/reference/solvent_dependent_conformers.md +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/skills/computational-chemistry-and-biology/reference/spin_states.md +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/skills/computational-chemistry-and-biology/reference/strain.md +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/skills/computational-chemistry-and-biology/reference/tautomer_search.md +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/skills/computational-chemistry-and-biology/reference/webhooks.md +0 -0
- {rowan_python-3.1.3 → rowan_python-3.1.4}/skills/computational-chemistry-and-biology/scripts/check_env.py +0 -0
|
@@ -23,6 +23,16 @@
|
|
|
23
23
|
- batch_submit_workflow
|
|
24
24
|
- batch_poll_status
|
|
25
25
|
|
|
26
|
+
::: rowan.calculation
|
|
27
|
+
handler: python
|
|
28
|
+
options:
|
|
29
|
+
show_source: false
|
|
30
|
+
show_root_heading: false
|
|
31
|
+
show_root_toc_entry: false
|
|
32
|
+
members_order: source
|
|
33
|
+
group_by_category: true
|
|
34
|
+
filters: ["!^_"]
|
|
35
|
+
|
|
26
36
|
## ADMET
|
|
27
37
|
::: rowan.workflows.admet
|
|
28
38
|
handler: python
|
|
@@ -254,6 +264,17 @@
|
|
|
254
264
|
group_by_category: true
|
|
255
265
|
filters: ["!^__"]
|
|
256
266
|
|
|
267
|
+
## Pocket Detection
|
|
268
|
+
::: rowan.workflows.pocket_detection
|
|
269
|
+
handler: python
|
|
270
|
+
options:
|
|
271
|
+
show_source: false
|
|
272
|
+
show_root_heading: false
|
|
273
|
+
show_root_toc_entry: false
|
|
274
|
+
members_order: source
|
|
275
|
+
group_by_category: true
|
|
276
|
+
filters: ["!^__"]
|
|
277
|
+
|
|
257
278
|
## Pose Analysis MD
|
|
258
279
|
::: rowan.workflows.pose_analysis_md
|
|
259
280
|
handler: python
|
|
@@ -397,6 +418,17 @@
|
|
|
397
418
|
group_by_category: true
|
|
398
419
|
filters: ["!^__"]
|
|
399
420
|
|
|
421
|
+
## API Keys
|
|
422
|
+
::: rowan.api_keys
|
|
423
|
+
handler: python
|
|
424
|
+
options:
|
|
425
|
+
show_source: false
|
|
426
|
+
show_root_heading: false
|
|
427
|
+
show_root_toc_entry: false
|
|
428
|
+
members_order: source
|
|
429
|
+
group_by_category: true
|
|
430
|
+
filters: ["!^__"]
|
|
431
|
+
|
|
400
432
|
## Folder Class and Functions
|
|
401
433
|
::: rowan.folder
|
|
402
434
|
handler: python
|
|
@@ -14,7 +14,7 @@ msa_workflow = rowan.submit_msa_workflow(
|
|
|
14
14
|
"VLSPADKTNVKAAWGKVGAHAGEYGAEALERMFLSFPTTKTYFPHFDLSHGSAQVKGHGKKVADALTNAVAHVDDMPNALSALSDLHAHKLRVDPVNFKLLSHCLLVTLAAHLPAEFTPAVHASLDKFLASVSTVLTSKYR",
|
|
15
15
|
"VHLTPEEKSAVTALWGKVNVDEVGGEALGRLLVVYPWTQRFFESFGDLSTPDAVMGNPKVKAHGKKVLGAFSDGLAHLDNLKGTFATLSELHCDKLHVDPENFRLLGNVLVCVLAHHFGKEFTPPVQAAYQKVVAGVANALAHKYH",
|
|
16
16
|
],
|
|
17
|
-
output_formats=[
|
|
17
|
+
output_formats=[rowan.MSAFormat.BOLTZ],
|
|
18
18
|
name="Boltz Paired MSA Example",
|
|
19
19
|
folder=folder,
|
|
20
20
|
)
|
|
@@ -23,7 +23,7 @@ print(f"View workflow privately at: https://labs.rowansci.com/msa/{msa_workflow.
|
|
|
23
23
|
|
|
24
24
|
msa_result = msa_workflow.result()
|
|
25
25
|
|
|
26
|
-
msa_result.download_files(
|
|
26
|
+
msa_result.download_files(rowan.MSAFormat.BOLTZ, path=msa_directory)
|
|
27
27
|
|
|
28
28
|
tar_path = next(msa_directory.glob("*.tar.gz"))
|
|
29
29
|
with tarfile.open(tar_path, "r") as tar_ref:
|
|
@@ -13,7 +13,7 @@ msa_workflow = rowan.submit_msa_workflow(
|
|
|
13
13
|
initial_protein_sequences=[
|
|
14
14
|
"HPETLVKVKDAEDQLGARVGYIELDLNSGKILESFRPEERFPMMSTFKVLLCGAVLSRIDAGQEQLGRRIHYSQNDLVEYSPVTEKHLTDGMTVRELCSAAITMSDNTAANLLLTTIGGPKELTAFLHNMGDHVTRLDRWEPELNEAIPNDERDTTMPVAMATTLRKLLTGELLTLASRQQLIDWMEADKVAGPLLRSALPAGWFIADKSGAGERGSRGIIAALGPDGKPSRIVVIYTTGSQATMDERNRQIAEIGASLIKHW"
|
|
15
15
|
],
|
|
16
|
-
output_formats=[
|
|
16
|
+
output_formats=[rowan.MSAFormat.BOLTZ],
|
|
17
17
|
name="Boltz MSA Example",
|
|
18
18
|
folder=folder,
|
|
19
19
|
)
|
|
@@ -22,7 +22,7 @@ print(f"View workflow privately at: https://labs.rowansci.com/msa/{msa_workflow.
|
|
|
22
22
|
|
|
23
23
|
msa_result = msa_workflow.result()
|
|
24
24
|
|
|
25
|
-
msa_result.download_files(
|
|
25
|
+
msa_result.download_files(rowan.MSAFormat.BOLTZ, path=msa_directory)
|
|
26
26
|
|
|
27
27
|
tar_path = next(msa_directory.glob("*.tar.gz"))
|
|
28
28
|
with tarfile.open(tar_path, "r") as tar_ref:
|
|
@@ -25,7 +25,7 @@ msa_workflow = rowan.submit_msa_workflow(
|
|
|
25
25
|
"VLSPADKTNVKAAWGKVGAHAGEYGAEALERMFLSFPTTKTYFPHFDLSHGSAQVKGHGKKVADALTNAVAHVDDMPNALSALSDLHAHKLRVDPVNFKLLSHCLLVTLAAHLPAEFTPAVHASLDKFLASVSTVLTSKYR",
|
|
26
26
|
"VHLTPEEKSAVTALWGKVNVDEVGGEALGRLLVVYPWTQRFFESFGDLSTPDAVMGNPKVKAHGKKVLGAFSDGLAHLDNLKGTFATLSELHCDKLHVDPENFRLLGNVLVCVLAHHFGKEFTPPVQAAYQKVVAGVANALAHKYH",
|
|
27
27
|
],
|
|
28
|
-
output_formats=[
|
|
28
|
+
output_formats=[rowan.MSAFormat.CHAI],
|
|
29
29
|
name="CHAI Paired MSA Example",
|
|
30
30
|
folder=folder,
|
|
31
31
|
)
|
|
@@ -34,7 +34,7 @@ print(f"View workflow privately at: https://labs.rowansci.com/msa/{msa_workflow.
|
|
|
34
34
|
|
|
35
35
|
msa_result = msa_workflow.result()
|
|
36
36
|
|
|
37
|
-
msa_result.download_files(
|
|
37
|
+
msa_result.download_files(rowan.MSAFormat.CHAI, path=msa_directory)
|
|
38
38
|
|
|
39
39
|
tar_path = next(msa_directory.glob("*.tar.gz"))
|
|
40
40
|
with tarfile.open(tar_path, "r") as tar_ref:
|
|
@@ -22,7 +22,7 @@ msa_workflow = rowan.submit_msa_workflow(
|
|
|
22
22
|
initial_protein_sequences=[
|
|
23
23
|
"HPETLVKVKDAEDQLGARVGYIELDLNSGKILESFRPEERFPMMSTFKVLLCGAVLSRIDAGQEQLGRRIHYSQNDLVEYSPVTEKHLTDGMTVRELCSAAITMSDNTAANLLLTTIGGPKELTAFLHNMGDHVTRLDRWEPELNEAIPNDERDTTMPVAMATTLRKLLTGELLTLASRQQLIDWMEADKVAGPLLRSALPAGWFIADKSGAGERGSRGIIAALGPDGKPSRIVVIYTTGSQATMDERNRQIAEIGASLIKHW"
|
|
24
24
|
],
|
|
25
|
-
output_formats=[
|
|
25
|
+
output_formats=[rowan.MSAFormat.CHAI],
|
|
26
26
|
name="CHAI MSA Example",
|
|
27
27
|
folder=folder,
|
|
28
28
|
)
|
|
@@ -31,7 +31,7 @@ print(f"View workflow privately at: https://labs.rowansci.com/msa/{msa_workflow.
|
|
|
31
31
|
|
|
32
32
|
msa_result = msa_workflow.result()
|
|
33
33
|
|
|
34
|
-
msa_result.download_files(
|
|
34
|
+
msa_result.download_files(rowan.MSAFormat.CHAI, path=msa_directory)
|
|
35
35
|
|
|
36
36
|
tar_path = next(msa_directory.glob("*.tar.gz"))
|
|
37
37
|
with tarfile.open(tar_path, "r") as tar_ref:
|
|
@@ -14,7 +14,7 @@ msa_workflow = rowan.submit_msa_workflow(
|
|
|
14
14
|
"VLSPADKTNVKAAWGKVGAHAGEYGAEALERMFLSFPTTKTYFPHFDLSHGSAQVKGHGKKVADALTNAVAHVDDMPNALSALSDLHAHKLRVDPVNFKLLSHCLLVTLAAHLPAEFTPAVHASLDKFLASVSTVLTSKYR",
|
|
15
15
|
"VHLTPEEKSAVTALWGKVNVDEVGGEALGRLLVVYPWTQRFFESFGDLSTPDAVMGNPKVKAHGKKVLGAFSDGLAHLDNLKGTFATLSELHCDKLHVDPENFRLLGNVLVCVLAHHFGKEFTPPVQAAYQKVVAGVANALAHKYH",
|
|
16
16
|
],
|
|
17
|
-
output_formats=[
|
|
17
|
+
output_formats=[rowan.MSAFormat.COLABFOLD],
|
|
18
18
|
name="Colabfold Paired MSA Example",
|
|
19
19
|
folder=folder,
|
|
20
20
|
)
|
|
@@ -23,7 +23,7 @@ print(f"View workflow privately at: https://labs.rowansci.com/msa/{msa_workflow.
|
|
|
23
23
|
|
|
24
24
|
msa_result = msa_workflow.result()
|
|
25
25
|
|
|
26
|
-
msa_result.download_files(
|
|
26
|
+
msa_result.download_files(rowan.MSAFormat.COLABFOLD, path=msa_directory)
|
|
27
27
|
|
|
28
28
|
tar_path = next(msa_directory.glob("*.tar.gz"))
|
|
29
29
|
with tarfile.open(tar_path, "r") as tar_ref:
|
|
@@ -13,7 +13,7 @@ msa_workflow = rowan.submit_msa_workflow(
|
|
|
13
13
|
initial_protein_sequences=[
|
|
14
14
|
"HPETLVKVKDAEDQLGARVGYIELDLNSGKILESFRPEERFPMMSTFKVLLCGAVLSRIDAGQEQLGRRIHYSQNDLVEYSPVTEKHLTDGMTVRELCSAAITMSDNTAANLLLTTIGGPKELTAFLHNMGDHVTRLDRWEPELNEAIPNDERDTTMPVAMATTLRKLLTGELLTLASRQQLIDWMEADKVAGPLLRSALPAGWFIADKSGAGERGSRGIIAALGPDGKPSRIVVIYTTGSQATMDERNRQIAEIGASLIKHW"
|
|
15
15
|
],
|
|
16
|
-
output_formats=[
|
|
16
|
+
output_formats=[rowan.MSAFormat.COLABFOLD],
|
|
17
17
|
name="Colabfold MSA Example",
|
|
18
18
|
folder=folder,
|
|
19
19
|
)
|
|
@@ -22,7 +22,7 @@ print(f"View workflow privately at: https://labs.rowansci.com/msa/{msa_workflow.
|
|
|
22
22
|
|
|
23
23
|
msa_result = msa_workflow.result()
|
|
24
24
|
|
|
25
|
-
msa_result.download_files(
|
|
25
|
+
msa_result.download_files(rowan.MSAFormat.COLABFOLD, path=msa_directory)
|
|
26
26
|
|
|
27
27
|
tar_path = next(msa_directory.glob("*.tar.gz"))
|
|
28
28
|
with tarfile.open(tar_path, "r") as tar_ref:
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import rowan
|
|
2
|
+
|
|
3
|
+
# Set your API key or use the ROWAN_API_KEY environment variable
|
|
4
|
+
# rowan.api_key = "rowan-sk..."
|
|
5
|
+
folder = rowan.get_folder("examples")
|
|
6
|
+
|
|
7
|
+
# Dasatinib — redocked into its own ABL1 co-crystal structure (PDB: 2GQG)
|
|
8
|
+
dasatinib = rowan.Molecule.from_smiles("Cc1nc(Nc2ncc(C(=O)Nc3c(C)cccc3Cl)s2)cc(N2CCN(CCO)CC2)n1")
|
|
9
|
+
|
|
10
|
+
protein = rowan.create_protein_from_pdb_id("2GQG")
|
|
11
|
+
if len(protein.chains) > 1:
|
|
12
|
+
protein = protein.select_chains([protein.chains[0]])
|
|
13
|
+
protein.prepare()
|
|
14
|
+
|
|
15
|
+
# Pocket is [[center_x, center_y, center_z], [size_x, size_y, size_z]] in Å.
|
|
16
|
+
# For a co-crystal structure, extract these from the bound ligand's position.
|
|
17
|
+
# Use rowan.submit_pocket_detection_workflow() when the binding site is unknown.
|
|
18
|
+
center = [44.59, 79.75, 39.59]
|
|
19
|
+
size = [24.15, 21.33, 19.88]
|
|
20
|
+
workflow = rowan.submit_docking_workflow(
|
|
21
|
+
protein,
|
|
22
|
+
pocket=[center, size],
|
|
23
|
+
initial_molecule=dasatinib,
|
|
24
|
+
name="dasatinib docking (2GQG redock)",
|
|
25
|
+
folder=folder,
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
print(f"View workflow privately at: https://labs.rowansci.com/docking/{workflow.uuid}")
|
|
29
|
+
|
|
30
|
+
result = workflow.result()
|
|
31
|
+
print(result)
|
|
32
|
+
|
|
33
|
+
for i, score in enumerate(result.scores):
|
|
34
|
+
print(f" Pose {i}: score={score.score:.3f} posebusters_valid={score.posebusters_valid}")
|
|
35
|
+
|
|
36
|
+
# Download the top-scoring protein–ligand complex as a PDB
|
|
37
|
+
complex_protein = result.get_complex(0)
|
|
38
|
+
complex_protein.download_pdb_file("dasatinib_2GQG_complex.pdb")
|
|
39
|
+
print("Saved dasatinib_2GQG_complex.pdb")
|
|
@@ -19,7 +19,7 @@ workflows = []
|
|
|
19
19
|
results = {}
|
|
20
20
|
|
|
21
21
|
protein = rowan.create_protein_from_pdb_id(
|
|
22
|
-
"
|
|
22
|
+
"1HCK", name="CDK2", project_uuid=rowan.default_project().uuid
|
|
23
23
|
)
|
|
24
24
|
|
|
25
25
|
protein.prepare()
|
|
@@ -43,11 +43,14 @@ lowest_conformer_energy = 0
|
|
|
43
43
|
for workflow, result in workflow_results:
|
|
44
44
|
for conformer_uuid in result.conformers:
|
|
45
45
|
energy = rowan.retrieve_calculation_molecules(conformer_uuid)[0]["energy"]
|
|
46
|
-
|
|
46
|
+
if energy is not None:
|
|
47
|
+
lowest_conformer_energy = min(lowest_conformer_energy, energy)
|
|
47
48
|
|
|
48
49
|
sorted_scores = sorted(result.scores, key=lambda s: s.score)
|
|
49
50
|
for score in sorted_scores:
|
|
50
51
|
pose_energy = rowan.retrieve_calculation_molecules(score.pose)[0]["energy"]
|
|
52
|
+
if pose_energy is None:
|
|
53
|
+
continue
|
|
51
54
|
strain = (pose_energy - lowest_conformer_energy) * HARTREE_TO_KCALMOL
|
|
52
55
|
if score.posebusters_valid and strain < 4:
|
|
53
56
|
results[workflow.name] = score
|
|
@@ -5,7 +5,7 @@ import rowan
|
|
|
5
5
|
folder = rowan.get_folder("examples")
|
|
6
6
|
|
|
7
7
|
protein = rowan.create_protein_from_pdb_id(
|
|
8
|
-
"
|
|
8
|
+
"1OTP", name="thymidine phosphorylase", project_uuid=rowan.default_project().uuid
|
|
9
9
|
)
|
|
10
10
|
|
|
11
11
|
protein.prepare()
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Resubmit a completed workflow with a perturbed structure.
|
|
3
|
+
|
|
4
|
+
Two strategies: random noise to break symmetry, or displacement along a
|
|
5
|
+
vibrational mode to follow a reaction coordinate or escape a stuck geometry.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import rowan
|
|
9
|
+
|
|
10
|
+
# Set your API key or use the ROWAN_API_KEY environment variable
|
|
11
|
+
# rowan.api_key = "rowan-sk..."
|
|
12
|
+
folder = rowan.get_folder("examples")
|
|
13
|
+
|
|
14
|
+
# --- Option 1: random noise ---
|
|
15
|
+
wf = rowan.retrieve_workflow("your-workflow-uuid")
|
|
16
|
+
mol = wf.result().molecule
|
|
17
|
+
|
|
18
|
+
perturbed_mol = mol.perturb()
|
|
19
|
+
resubmit = rowan.submit_multistage_optimization_workflow(
|
|
20
|
+
initial_molecule=perturbed_mol,
|
|
21
|
+
name="cyclobutane opt - perturbed resubmit",
|
|
22
|
+
folder=folder,
|
|
23
|
+
)
|
|
24
|
+
print(f"https://labs.rowansci.com/multistage-opt/{resubmit.uuid}")
|
|
25
|
+
|
|
26
|
+
# --- Option 2: displace along a vibrational mode ---
|
|
27
|
+
# Requires a prior frequency calculation. Imaginary modes have negative frequency.
|
|
28
|
+
ts_wf = rowan.retrieve_workflow("your-ts-freq-workflow-uuid")
|
|
29
|
+
ts_mol = ts_wf.result().molecule
|
|
30
|
+
|
|
31
|
+
imaginary_mode = next(m for m in ts_mol.vibrational_modes if m.frequency < 0)
|
|
32
|
+
|
|
33
|
+
displaced_mol = ts_mol.displace_along_mode(mode=imaginary_mode, displacement=0.3)
|
|
34
|
+
resubmit = rowan.submit_multistage_optimization_workflow(
|
|
35
|
+
initial_molecule=displaced_mol,
|
|
36
|
+
name="TS resubmit - displaced along imaginary mode",
|
|
37
|
+
folder=folder,
|
|
38
|
+
)
|
|
39
|
+
print(f"https://labs.rowansci.com/multistage-opt/{resubmit.uuid}")
|
|
@@ -13,13 +13,13 @@ folder = rowan.get_folder("examples")
|
|
|
13
13
|
workflow = rowan.submit_scan_workflow(
|
|
14
14
|
initial_molecule=rowan.Molecule.from_smiles("O"),
|
|
15
15
|
name="Water Angle scan",
|
|
16
|
-
scan_settings=
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
16
|
+
scan_settings=rowan.ScanSettings(
|
|
17
|
+
type="angle",
|
|
18
|
+
atoms=[2, 1, 3], # 1-indexed
|
|
19
|
+
start=100,
|
|
20
|
+
stop=110,
|
|
21
|
+
num=5,
|
|
22
|
+
),
|
|
23
23
|
calculation_method="GFN2-xTB",
|
|
24
24
|
calculation_engine="xtb",
|
|
25
25
|
folder=folder,
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
from . import constants
|
|
3
3
|
from stjames import (
|
|
4
4
|
Atom,
|
|
5
|
+
BindingPoseContact,
|
|
6
|
+
ConformerGenSettings,
|
|
5
7
|
Constraint,
|
|
6
8
|
ConstraintType,
|
|
7
9
|
ConformerClusteringSettings,
|
|
@@ -14,15 +16,19 @@ from stjames import (
|
|
|
14
16
|
KMeansClusteringSettings,
|
|
15
17
|
Method,
|
|
16
18
|
Mode,
|
|
19
|
+
MSAFormat,
|
|
17
20
|
MultiStageOptSettings,
|
|
18
21
|
OpenConfSettings,
|
|
19
22
|
OptimizationSettings,
|
|
20
23
|
PBCDFTSettings,
|
|
21
24
|
PeriodicCell,
|
|
25
|
+
ProteinSequence,
|
|
26
|
+
ScanSettings,
|
|
22
27
|
Settings,
|
|
23
28
|
Solvent,
|
|
24
29
|
SolventSettings,
|
|
25
30
|
Task,
|
|
31
|
+
VibrationalMode,
|
|
26
32
|
)
|
|
27
33
|
from stjames.workflows.relative_binding_free_energy_perturbation import RBFEGraph, RBFEGraphEdge
|
|
28
34
|
from stjames.excited_state_settings import TDDFTSettings
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
from typing import Self
|
|
4
4
|
|
|
5
|
+
import httpx
|
|
5
6
|
import stjames
|
|
6
7
|
from pydantic import BaseModel, ConfigDict, Field
|
|
7
8
|
|
|
@@ -62,10 +63,13 @@ class Calculation(BaseModel):
|
|
|
62
63
|
:param in_place: If True, update this instance in-place. If False, return new instance.
|
|
63
64
|
:returns: Updated Calculation object.
|
|
64
65
|
"""
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
66
|
+
try:
|
|
67
|
+
with api_client() as client:
|
|
68
|
+
response = client.get(f"/calculation/{self.uuid}/stjames")
|
|
69
|
+
response.raise_for_status()
|
|
70
|
+
data = response.json()
|
|
71
|
+
except httpx.TimeoutException as e:
|
|
72
|
+
raise TimeoutError(f"Timed out fetching calculation {self.uuid}.") from e
|
|
69
73
|
|
|
70
74
|
molecules = _parse_molecules(data.get("molecules", []))
|
|
71
75
|
|
|
@@ -94,11 +98,15 @@ def retrieve_calculation(uuid: str) -> Calculation:
|
|
|
94
98
|
:param uuid: UUID of the calculation to retrieve.
|
|
95
99
|
:returns: Calculation object with the fetched data.
|
|
96
100
|
:raises requests.HTTPError: If the API request fails.
|
|
101
|
+
:raises TimeoutError: If the response times out.
|
|
97
102
|
"""
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
103
|
+
try:
|
|
104
|
+
with api_client() as client:
|
|
105
|
+
response = client.get(f"/calculation/{uuid}/stjames")
|
|
106
|
+
response.raise_for_status()
|
|
107
|
+
data = response.json()
|
|
108
|
+
except httpx.TimeoutException as e:
|
|
109
|
+
raise TimeoutError(f"Timed out fetching calculation {uuid}.") from e
|
|
102
110
|
|
|
103
111
|
molecules = _parse_molecules(data.get("molecules", []))
|
|
104
112
|
|
|
@@ -1,11 +1,16 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
1
3
|
from datetime import datetime
|
|
2
|
-
from typing import Any, Self
|
|
4
|
+
from typing import TYPE_CHECKING, Any, Self
|
|
3
5
|
|
|
4
6
|
from pydantic import BaseModel
|
|
5
7
|
|
|
6
8
|
from .project import default_project, retrieve_project
|
|
7
9
|
from .utils import api_client, get_project_uuid
|
|
8
10
|
|
|
11
|
+
if TYPE_CHECKING:
|
|
12
|
+
from .workflows.base import Workflow
|
|
13
|
+
|
|
9
14
|
|
|
10
15
|
class Folder(BaseModel):
|
|
11
16
|
"""
|
|
@@ -121,6 +126,77 @@ class Folder(BaseModel):
|
|
|
121
126
|
"""
|
|
122
127
|
print_folder_tree(self.uuid, max_depth, show_uuids)
|
|
123
128
|
|
|
129
|
+
def children(self, size: int = 100) -> list[Folder]:
|
|
130
|
+
"""
|
|
131
|
+
List all child folders directly inside this folder.
|
|
132
|
+
|
|
133
|
+
:param size: Maximum number of child folders to return.
|
|
134
|
+
:returns: List of child Folder objects.
|
|
135
|
+
:raises HTTPError: If the API request fails.
|
|
136
|
+
"""
|
|
137
|
+
return list_folders(parent_uuid=self.uuid, size=size)
|
|
138
|
+
|
|
139
|
+
def workflows(self, size: int = 100) -> list[Workflow]:
|
|
140
|
+
"""
|
|
141
|
+
List all workflows directly inside this folder.
|
|
142
|
+
|
|
143
|
+
:param size: Maximum number of workflows to return.
|
|
144
|
+
:returns: List of Workflow objects.
|
|
145
|
+
:raises HTTPError: If the API request fails.
|
|
146
|
+
"""
|
|
147
|
+
from .workflows.base import list_workflows
|
|
148
|
+
|
|
149
|
+
return list_workflows(parent_uuid=self.uuid, size=size)
|
|
150
|
+
|
|
151
|
+
def contents(self, size: int = 100) -> list[Folder | Workflow]:
|
|
152
|
+
"""
|
|
153
|
+
List everything directly inside this folder, both child folders and workflows.
|
|
154
|
+
|
|
155
|
+
Folders come first, followed by workflows. For a single type, use :func:`children`
|
|
156
|
+
or :func:`workflows`.
|
|
157
|
+
|
|
158
|
+
:param size: Maximum number of items of each type to return.
|
|
159
|
+
:returns: List of Folder and Workflow objects.
|
|
160
|
+
:raises HTTPError: If the API request fails.
|
|
161
|
+
"""
|
|
162
|
+
return [*self.children(size=size), *self.workflows(size=size)]
|
|
163
|
+
|
|
164
|
+
def parent(self) -> Folder | None:
|
|
165
|
+
"""
|
|
166
|
+
Retrieve the parent folder, or None if this is a root folder.
|
|
167
|
+
|
|
168
|
+
:returns: Parent Folder, or None if there is no parent.
|
|
169
|
+
:raises HTTPError: If the API request fails.
|
|
170
|
+
"""
|
|
171
|
+
if self.parent_uuid is None:
|
|
172
|
+
return None
|
|
173
|
+
return retrieve_folder(self.parent_uuid)
|
|
174
|
+
|
|
175
|
+
def __truediv__(self, name: str) -> Folder:
|
|
176
|
+
"""
|
|
177
|
+
Traverse into a child folder by name using the ``/`` operator.
|
|
178
|
+
|
|
179
|
+
Example::
|
|
180
|
+
|
|
181
|
+
root = rowan.root_folder()
|
|
182
|
+
subfolder = root / "CDK2" / "docking"
|
|
183
|
+
|
|
184
|
+
:param name: Exact name of the child folder to navigate into.
|
|
185
|
+
:returns: Child Folder with the given name.
|
|
186
|
+
:raises ValueError: If no child with that name exists, or if multiple children share
|
|
187
|
+
the same name (use :func:`children` and select by UUID to disambiguate).
|
|
188
|
+
"""
|
|
189
|
+
matches = [f for f in self.children(size=200) if f.name == name]
|
|
190
|
+
if not matches:
|
|
191
|
+
raise ValueError(f"No child folder named {name!r} in {self.name!r} ({self.uuid})")
|
|
192
|
+
if len(matches) > 1:
|
|
193
|
+
uuids = ", ".join(f.uuid for f in matches)
|
|
194
|
+
raise ValueError(
|
|
195
|
+
f"Multiple child folders named {name!r} in {self.name!r} ({self.uuid}). "
|
|
196
|
+
f"Use retrieve_folder() with one of these UUIDs to disambiguate: {uuids}"
|
|
197
|
+
)
|
|
198
|
+
return matches[0]
|
|
199
|
+
|
|
124
200
|
|
|
125
201
|
def retrieve_folder(uuid: str) -> Folder:
|
|
126
202
|
"""
|
|
@@ -147,6 +223,9 @@ def list_folders(
|
|
|
147
223
|
"""
|
|
148
224
|
Retrieve a list of folders based on the specified criteria.
|
|
149
225
|
|
|
226
|
+
If no ``parent_uuid`` is given and a project is active (via :func:`set_project` or
|
|
227
|
+
``rowan.project_uuid``), lists folders rooted at that project's root folder.
|
|
228
|
+
|
|
150
229
|
:param parent_uuid: UUID of the parent folder to filter by.
|
|
151
230
|
:param name_contains: Substring to search for in folder names.
|
|
152
231
|
:param public: Filter folders by their public status.
|
|
@@ -156,6 +235,11 @@ def list_folders(
|
|
|
156
235
|
:returns: List of Folder objects that match the search criteria.
|
|
157
236
|
:raises requests.HTTPError: if the request to the API fails.
|
|
158
237
|
"""
|
|
238
|
+
if parent_uuid is None:
|
|
239
|
+
if project_uuid := get_project_uuid():
|
|
240
|
+
parent_uuid = retrieve_project(project_uuid).root_folder_uuid
|
|
241
|
+
else:
|
|
242
|
+
parent_uuid = default_project().root_folder_uuid
|
|
159
243
|
|
|
160
244
|
params: dict[str, Any] = {
|
|
161
245
|
"page": page,
|
|
@@ -189,6 +273,9 @@ def create_folder(
|
|
|
189
273
|
"""
|
|
190
274
|
Create a new folder.
|
|
191
275
|
|
|
276
|
+
If no ``parent_uuid`` is given and a project is active (via :func:`set_project` or
|
|
277
|
+
``rowan.project_uuid``), the folder is created inside that project's root folder.
|
|
278
|
+
|
|
192
279
|
:param name: Name of the folder.
|
|
193
280
|
:param parent_uuid: UUID of the parent folder.
|
|
194
281
|
:param notes: Description of the folder.
|
|
@@ -196,6 +283,12 @@ def create_folder(
|
|
|
196
283
|
:param public: Whether the folder is public.
|
|
197
284
|
:returns: Newly created folder.
|
|
198
285
|
"""
|
|
286
|
+
if parent_uuid is None:
|
|
287
|
+
if project_uuid := get_project_uuid():
|
|
288
|
+
parent_uuid = retrieve_project(project_uuid).root_folder_uuid
|
|
289
|
+
else:
|
|
290
|
+
parent_uuid = default_project().root_folder_uuid
|
|
291
|
+
|
|
199
292
|
data = {
|
|
200
293
|
"name": name,
|
|
201
294
|
"parent_uuid": parent_uuid,
|
|
@@ -210,6 +303,32 @@ def create_folder(
|
|
|
210
303
|
return Folder(**folder_data)
|
|
211
304
|
|
|
212
305
|
|
|
306
|
+
def root_folder() -> Folder:
|
|
307
|
+
"""
|
|
308
|
+
Get the root folder of the active project.
|
|
309
|
+
|
|
310
|
+
The root folder is the top of the folder tree you navigate and store workflows in. Use the
|
|
311
|
+
active project set via :func:`set_project` (or ``rowan.project_uuid``), falling back to the
|
|
312
|
+
default project.
|
|
313
|
+
|
|
314
|
+
Example::
|
|
315
|
+
|
|
316
|
+
root = rowan.root_folder()
|
|
317
|
+
for child in root.children():
|
|
318
|
+
print(child.name)
|
|
319
|
+
batch = root / "CDK2" / "docking"
|
|
320
|
+
|
|
321
|
+
:returns: Root Folder of the active or default project.
|
|
322
|
+
:raises HTTPError: If the API request fails.
|
|
323
|
+
"""
|
|
324
|
+
if project_uuid := get_project_uuid():
|
|
325
|
+
root_uuid = retrieve_project(project_uuid).root_folder_uuid
|
|
326
|
+
else:
|
|
327
|
+
root_uuid = default_project().root_folder_uuid
|
|
328
|
+
assert root_uuid is not None
|
|
329
|
+
return retrieve_folder(root_uuid)
|
|
330
|
+
|
|
331
|
+
|
|
213
332
|
def get_folder(path: str, create: bool = True) -> Folder:
|
|
214
333
|
"""
|
|
215
334
|
Get a folder by name or nested path within the default project.
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
"""Molecule class for representing molecular structures and computed properties."""
|
|
2
2
|
|
|
3
|
+
import math
|
|
4
|
+
import random
|
|
3
5
|
from pathlib import Path
|
|
4
6
|
from typing import Any, Self
|
|
5
7
|
|
|
@@ -272,6 +274,77 @@ class Molecule(BaseModel):
|
|
|
272
274
|
"""
|
|
273
275
|
return self._stjames.dihedral(i, j, k, l, degrees=degrees)
|
|
274
276
|
|
|
277
|
+
def perturb(self, stddev: float = 0.005) -> "Molecule":
|
|
278
|
+
"""
|
|
279
|
+
Return a copy with random Gaussian noise added to each atom position.
|
|
280
|
+
|
|
281
|
+
Useful for breaking symmetry before resubmitting an optimization (e.g. when
|
|
282
|
+
a calculation is stuck in a saddle point or converges to an unwanted geometry).
|
|
283
|
+
|
|
284
|
+
:param stddev: standard deviation of the Gaussian displacement (Angstroms)
|
|
285
|
+
:returns: new Molecule with perturbed coordinates
|
|
286
|
+
"""
|
|
287
|
+
|
|
288
|
+
def _gauss() -> float:
|
|
289
|
+
u1 = random.random()
|
|
290
|
+
u2 = random.random()
|
|
291
|
+
return math.sqrt(-2.0 * math.log(u1)) * math.cos(2.0 * math.pi * u2) * stddev
|
|
292
|
+
|
|
293
|
+
new_atoms = [
|
|
294
|
+
stjames.Atom(
|
|
295
|
+
atomic_number=atom.atomic_number,
|
|
296
|
+
position=(
|
|
297
|
+
atom.position[0] + _gauss(),
|
|
298
|
+
atom.position[1] + _gauss(),
|
|
299
|
+
atom.position[2] + _gauss(),
|
|
300
|
+
),
|
|
301
|
+
mass=atom.mass,
|
|
302
|
+
)
|
|
303
|
+
for atom in self._stjames.atoms
|
|
304
|
+
]
|
|
305
|
+
new_mol = self._stjames.model_copy(update={"atoms": new_atoms})
|
|
306
|
+
return Molecule(_stjames=new_mol)
|
|
307
|
+
|
|
308
|
+
def displace_along_mode(self, mode: stjames.VibrationalMode, displacement: float) -> "Molecule":
|
|
309
|
+
"""
|
|
310
|
+
Return a copy with atom positions displaced along a vibrational normal mode.
|
|
311
|
+
|
|
312
|
+
Requires a prior frequency calculation. For a transition state, the imaginary
|
|
313
|
+
mode has a negative frequency and points toward the reactant or product.
|
|
314
|
+
|
|
315
|
+
:param mode: vibrational mode to displace along, from ``vibrational_modes``
|
|
316
|
+
:param displacement: displacement distance along the normalized mode (Angstroms)
|
|
317
|
+
:returns: new Molecule with displaced coordinates
|
|
318
|
+
:raises ValueError: if the mode has no displacements or zero-norm displacements
|
|
319
|
+
"""
|
|
320
|
+
raw = mode.displacements
|
|
321
|
+
if not raw:
|
|
322
|
+
raise ValueError(
|
|
323
|
+
"Vibrational mode has no displacements. "
|
|
324
|
+
"Rerun the calculation with frequencies=True to displace along a mode."
|
|
325
|
+
)
|
|
326
|
+
norm = math.sqrt(sum(x**2 + y**2 + z**2 for x, y, z in raw))
|
|
327
|
+
if norm == 0:
|
|
328
|
+
raise ValueError(
|
|
329
|
+
"Vibrational mode has zero-norm displacements. "
|
|
330
|
+
"This indicates malformed frequency output, try displacing along a different mode."
|
|
331
|
+
)
|
|
332
|
+
|
|
333
|
+
new_atoms = [
|
|
334
|
+
stjames.Atom(
|
|
335
|
+
atomic_number=atom.atomic_number,
|
|
336
|
+
position=(
|
|
337
|
+
atom.position[0] + (dx / norm) * displacement,
|
|
338
|
+
atom.position[1] + (dy / norm) * displacement,
|
|
339
|
+
atom.position[2] + (dz / norm) * displacement,
|
|
340
|
+
),
|
|
341
|
+
mass=atom.mass,
|
|
342
|
+
)
|
|
343
|
+
for atom, (dx, dy, dz) in zip(self._stjames.atoms, raw, strict=True)
|
|
344
|
+
]
|
|
345
|
+
new_mol = self._stjames.model_copy(update={"atoms": new_atoms})
|
|
346
|
+
return Molecule(_stjames=new_mol)
|
|
347
|
+
|
|
275
348
|
|
|
276
349
|
def load_named_ligands(path: Path | str) -> dict[str, Molecule]:
|
|
277
350
|
"""
|