boltz2-python-client 0.5.0__tar.gz → 0.5.2.post1__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.
- boltz2_python_client-0.5.2.post1/CHANGELOG.md +215 -0
- {boltz2_python_client-0.5.0/boltz2_python_client.egg-info → boltz2_python_client-0.5.2.post1}/PKG-INFO +31 -6
- {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/README.md +30 -5
- {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/boltz2_client/__init__.py +1 -38
- {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/boltz2_client/cli/__init__.py +3 -0
- {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/boltz2_client/cli/info.py +7 -0
- {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/boltz2_client/cli/msa.py +15 -5
- {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/boltz2_client/cli/screen.py +11 -3
- {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/boltz2_client/client.py +4 -3
- {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/boltz2_client/multi_endpoint_client.py +177 -43
- {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/boltz2_client/virtual_screening.py +43 -19
- {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1/boltz2_python_client.egg-info}/PKG-INFO +31 -6
- {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/boltz2_python_client.egg-info/SOURCES.txt +2 -1
- {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/docs/multi_endpoint.md +35 -0
- boltz2_python_client-0.5.2.post1/tests/test_multi_endpoint_reliability.py +317 -0
- boltz2_python_client-0.5.0/CHANGELOG.md +0 -108
- {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/LICENSE +0 -0
- {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/MANIFEST.in +0 -0
- {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/boltz2_client/__main__.py +0 -0
- {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/boltz2_client/a3m/__init__.py +0 -0
- {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/boltz2_client/a3m/converter.py +0 -0
- {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/boltz2_client/a3m/pairing.py +0 -0
- {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/boltz2_client/a3m/parser.py +0 -0
- {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/boltz2_client/a3m_to_csv_converter.py +0 -0
- {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/boltz2_client/cli/predict.py +0 -0
- {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/boltz2_client/data/__init__.py +0 -0
- {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/boltz2_client/data/speclist.txt +0 -0
- {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/boltz2_client/exceptions.py +0 -0
- {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/boltz2_client/models.py +0 -0
- {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/boltz2_client/msa_search.py +0 -0
- {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/boltz2_client/utils.py +0 -0
- {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/boltz2_python_client.egg-info/dependency_links.txt +0 -0
- {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/boltz2_python_client.egg-info/entry_points.txt +0 -0
- {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/boltz2_python_client.egg-info/requires.txt +0 -0
- {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/boltz2_python_client.egg-info/top_level.txt +0 -0
- {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/docs/a3m_to_multimer_msa.md +0 -0
- {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/docs/affinity_prediction.md +0 -0
- {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/docs/async.md +0 -0
- {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/docs/covalent_complex.md +0 -0
- {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/docs/msa_search.md +0 -0
- {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/docs/parameters.md +0 -0
- {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/docs/virtual_screening.md +0 -0
- {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/docs/yaml.md +0 -0
- {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/examples/01_basic_protein_folding.py +0 -0
- {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/examples/02_protein_structure_prediction_with_msa.py +0 -0
- {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/examples/03_protein_ligand_complex.py +0 -0
- {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/examples/04_covalent_bonding.py +0 -0
- {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/examples/05_dna_protein_complex.py +0 -0
- {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/examples/06_yaml_configurations.py +0 -0
- {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/examples/07_advanced_parameters.py +0 -0
- {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/examples/08_affinity_prediction_simple.py +0 -0
- {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/examples/09_virtual_screening.py +0 -0
- {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/examples/10_msa_search_integration.py +0 -0
- {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/examples/11_msa_search_large_protein.py +0 -0
- {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/examples/12_msa_affinity_prediction.py +0 -0
- {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/examples/13_a3m_to_multimer_csv.py +0 -0
- {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/examples/README.md +0 -0
- {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/examples/barnase_barstar_with_msa.py +0 -0
- {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/examples/cdk4_msa_affinity_example.py +0 -0
- {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/examples/comprehensive_multi_endpoint_demo.py +0 -0
- {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/examples/data/cdk2_target.txt +0 -0
- {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/examples/data/cdk4_msa_affinity/cdk4_palbociclib_results.json +0 -0
- {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/examples/data/kinase_y7w_affinity.json +0 -0
- {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/examples/data/msa-kras-g12c_combined.a3m +0 -0
- {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/examples/data/multi_protein_complex.yaml +0 -0
- {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/examples/data/protein_ligand.yaml +0 -0
- {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/examples/data/sars_cov2_mpro_nirmatrelvir.yaml +0 -0
- {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/examples/data/test_msa_endpoint_curl.sh +0 -0
- {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/examples/msa_search_simple_demo.py +0 -0
- {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/examples/multi_endpoint_screening.py +0 -0
- {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/examples/notebooks/01_multimer_prediction.ipynb +0 -0
- {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/examples/notebooks/02_cdk4_msa_affinity_prediction.ipynb +0 -0
- {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/examples/notebooks/03_colabfold_a3m_to_multimer.ipynb +0 -0
- {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/examples/notebooks/boltz2_comprehensive_demo.ipynb +0 -0
- {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/examples/notebooks/boltz2_demo.ipynb +0 -0
- {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/examples/notebooks/boltz2_nim_DNA_Protein_Complex_example_py3Dmol.ipynb +0 -0
- {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/examples/notebooks/boltz2_nim_protein_ligand_covalent_complex_molstar_visualization.ipynb +0 -0
- {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/licenses/PyYAML-LICENSE +0 -0
- {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/licenses/README.md +0 -0
- {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/licenses/aiofiles-LICENSE +0 -0
- {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/licenses/aiohttp-LICENSE +0 -0
- {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/licenses/click-LICENSE +0 -0
- {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/licenses/httpx-LICENSE +0 -0
- {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/licenses/py3Dmol-LICENSE +0 -0
- {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/licenses/pydantic-LICENSE +0 -0
- {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/licenses/rich-LICENSE +0 -0
- {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/licenses/typing-extensions-LICENSE +0 -0
- {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/pyproject.toml +0 -0
- {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/setup.cfg +0 -0
- {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/tests/__init__.py +0 -0
- {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/tests/conftest.py +0 -0
- {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/tests/constants.py +0 -0
- {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/tests/test_a3m_to_csv_converter.py +0 -0
- {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/tests/test_basic.py +0 -0
- {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/tests/test_cli_multi_endpoint.py +0 -0
- {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/tests/test_comprehensive_stress.py +0 -0
- {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/tests/test_examples_syntax.py +0 -0
- {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/tests/test_integration_scenarios.py +0 -0
- {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/tests/test_live_endpoints.py +0 -0
- {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/tests/test_msa_search.py +0 -0
- {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/tests/test_multi_endpoint_functionality.py +0 -0
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
## [0.5.2.post1] - 2026-02-24
|
|
6
|
+
|
|
7
|
+
PEP 440 post-release patch on top of `0.5.2`. **No public API changes**;
|
|
8
|
+
fixes a long-standing packaging defect that has been present since
|
|
9
|
+
`0.5.0` (and was carried into `0.5.2` unchanged). Users on a clean
|
|
10
|
+
environment should upgrade to `0.5.2.post1`; users who already have
|
|
11
|
+
`pandas` installed will see no behavior difference.
|
|
12
|
+
|
|
13
|
+
### Fixed — packaging
|
|
14
|
+
- **`import boltz2_client` now works on a clean install.** Previously
|
|
15
|
+
`boltz2_client/virtual_screening.py` did `import pandas as pd` at
|
|
16
|
+
module top, but `pandas` is only declared in the `[dev]` extra (not a
|
|
17
|
+
runtime dependency), so any clean `pip install boltz2-python-client`
|
|
18
|
+
followed by `import boltz2_client` raised
|
|
19
|
+
`ModuleNotFoundError: No module named 'pandas'`. The pandas import is
|
|
20
|
+
now deferred into the four methods that actually need it
|
|
21
|
+
(`CompoundLibrary.from_csv`, `ScreeningResults.to_dataframe`,
|
|
22
|
+
`ScreeningResults.get_top_hits`,
|
|
23
|
+
`ScreeningResults.get_statistics_by_group`); calling any of those
|
|
24
|
+
methods still requires pandas, but importing the package, the CLI,
|
|
25
|
+
and every other code path no longer does. Callers who use the virtual
|
|
26
|
+
screening DataFrame helpers should install with
|
|
27
|
+
`pip install "boltz2-python-client[dev]"` or add `pandas` to their
|
|
28
|
+
own environment.
|
|
29
|
+
- A `from __future__ import annotations` was added to
|
|
30
|
+
`virtual_screening.py` so the `pd.DataFrame` return-type annotations
|
|
31
|
+
on those methods are evaluated lazily and do not require `pandas` at
|
|
32
|
+
import time. Static type checkers and IDEs continue to resolve the
|
|
33
|
+
annotations via a `TYPE_CHECKING` block.
|
|
34
|
+
|
|
35
|
+
## [0.5.2] - 2026-02-24
|
|
36
|
+
|
|
37
|
+
### Fixed — `MultiEndpointClient` reliability
|
|
38
|
+
- **No longer cascades into "All endpoints failed" after a single endpoint glitch.**
|
|
39
|
+
`failed_requests` is now reset on every successful call across all
|
|
40
|
+
`predict_*` methods (`predict`, `predict_sync`, `predict_protein_structure`,
|
|
41
|
+
`predict_protein_ligand_complex`, `predict_covalent_complex`,
|
|
42
|
+
`predict_dna_protein_complex`, `predict_with_advanced_parameters`,
|
|
43
|
+
`predict_from_yaml_config`, `predict_from_yaml_file`, and the
|
|
44
|
+
corresponding `*_sync` variants). Previously a recovered endpoint could
|
|
45
|
+
remain marked unhealthy indefinitely after three transient failures.
|
|
46
|
+
- **`_select_endpoint()` now honours the per-request `attempted_endpoints`
|
|
47
|
+
set.** The `LEAST_LOADED` and `RANDOM` strategies could otherwise re-pick
|
|
48
|
+
the same dead endpoint repeatedly inside a single dispatch loop, wasting
|
|
49
|
+
retries and (on `LEAST_LOADED`) starving healthy endpoints. Round-robin
|
|
50
|
+
also now skips already-attempted endpoints fairly without resetting the
|
|
51
|
+
global rotation counter.
|
|
52
|
+
- **`health_check_sync()` now normalises `HealthStatus` to a boolean.**
|
|
53
|
+
Previously it stored the entire `HealthStatus` object on
|
|
54
|
+
`EndpointStatus.is_healthy`, which is always truthy and broke the sync
|
|
55
|
+
recovery + status-table paths.
|
|
56
|
+
- **Background health-check loop runs an immediate probe at startup.**
|
|
57
|
+
Initial unreachability is now detected without waiting a full
|
|
58
|
+
`health_check_interval` (default 60 s).
|
|
59
|
+
- **Synchronous `__exit__` no longer crashes when no event loop is running.**
|
|
60
|
+
`with MultiEndpointClient(...)` is now safe in plain synchronous code.
|
|
61
|
+
|
|
62
|
+
### Fixed — CLI
|
|
63
|
+
- `boltz2 msa-search`, `boltz2 msa-predict`, and `boltz2 msa-ligand` now
|
|
64
|
+
exit with a non-zero status when the underlying call fails (previously
|
|
65
|
+
they printed the error and exited cleanly, masking failures in pipelines).
|
|
66
|
+
- `boltz2 screen` now reports a clear error if client initialization fails
|
|
67
|
+
or if `--pocket-residues` is malformed, instead of crashing with a stack
|
|
68
|
+
trace before the progress UI starts.
|
|
69
|
+
- Removed a redundant local `import json` inside
|
|
70
|
+
`boltz2 multimer-msa --save-all`; the module-level import is used.
|
|
71
|
+
|
|
72
|
+
### Fixed — virtual screening
|
|
73
|
+
- `VirtualScreening` no longer raises `IndexError` when a prediction
|
|
74
|
+
response comes back with empty `structures`, `confidence_scores`, or
|
|
75
|
+
affinity score lists; missing fields are reported as `None` and the
|
|
76
|
+
campaign continues.
|
|
77
|
+
|
|
78
|
+
### Fixed — async client
|
|
79
|
+
- `Boltz2Client._sagemaker_predict` now uses `asyncio.get_running_loop()`
|
|
80
|
+
instead of the deprecated `asyncio.get_event_loop()` (silences the
|
|
81
|
+
Python 3.10+ `DeprecationWarning` and avoids a future-version hard
|
|
82
|
+
error).
|
|
83
|
+
|
|
84
|
+
### Added
|
|
85
|
+
- **`boltz2 --version` / `boltz2 -V`** prints the installed package
|
|
86
|
+
version (previously the CLI had no version flag).
|
|
87
|
+
|
|
88
|
+
### Removed
|
|
89
|
+
- Dead `_HAS_VISUALIZATION` / `_HAS_ANALYSIS` optional-import scaffolding
|
|
90
|
+
in `boltz2_client/__init__.py` referencing modules that have never
|
|
91
|
+
shipped. The package public surface is unchanged: no name was ever
|
|
92
|
+
successfully exported from those blocks.
|
|
93
|
+
|
|
94
|
+
### Docs
|
|
95
|
+
- Updated the README tagline to accurately describe what ships in the
|
|
96
|
+
package (multi-endpoint load balancing + notebook examples that
|
|
97
|
+
visualize structures with `py3Dmol` and Molstar) instead of claiming a
|
|
98
|
+
non-existent "built-in 3D visualization" module.
|
|
99
|
+
|
|
100
|
+
### Tests
|
|
101
|
+
- Added `tests/test_multi_endpoint_reliability.py` with 11 regression
|
|
102
|
+
tests pinning each of the fixes above. Each test fails on 0.5.1 and
|
|
103
|
+
passes on 0.5.2; the full suite (excluding live-endpoint tests) is now
|
|
104
|
+
134 passing.
|
|
105
|
+
|
|
106
|
+
## [0.5.1] - 2026-04-07
|
|
107
|
+
|
|
108
|
+
### Fixed
|
|
109
|
+
- CLI `metadata` command now shows a clear error for SageMaker endpoints instead of a cryptic `NoneType` error
|
|
110
|
+
- SageMaker endpoint exception handling cleanup in CLI
|
|
111
|
+
|
|
112
|
+
## [0.5.0] - 2026-04-07
|
|
113
|
+
|
|
114
|
+
### Added
|
|
115
|
+
- AWS SageMaker endpoint support (`EndpointType.SAGEMAKER`, CLI `--endpoint-type sagemaker`, `--sagemaker-endpoint-name`, `--sagemaker-region`)
|
|
116
|
+
|
|
117
|
+
### Changed
|
|
118
|
+
- **PocketConstraint API** now uses `Contact` objects (binder + contacts)
|
|
119
|
+
- **Parameter ranges:** `recycling_steps` 1–10, `diffusion_samples` 1–25
|
|
120
|
+
- **`write_full_pde`** support for full predicted distance error matrix output
|
|
121
|
+
- **`Ligand.id`** is optional
|
|
122
|
+
- Compatibility updates for **Boltz-2 NIM v1.6.0**
|
|
123
|
+
|
|
124
|
+
### Fixed
|
|
125
|
+
- Comprehensive test suite fixes and live endpoint tests
|
|
126
|
+
|
|
127
|
+
## [0.4.0] - 2025-11-01
|
|
128
|
+
|
|
129
|
+
### Added
|
|
130
|
+
- A3M to multimer MSA conversion utilities, `multimer-msa` and `convert-msa` CLI commands
|
|
131
|
+
- Example script `13_a3m_to_multimer_csv.py` and guides (`docs/a3m_to_multimer_msa.md`)
|
|
132
|
+
- Multimer notebooks (`01_multimer_prediction.ipynb`, `03_colabfold_a3m_to_multimer.ipynb`) and related example scripts
|
|
133
|
+
- `08_affinity_prediction_simple.py` as the maintained affinity example (with `kinase_y7w_affinity.json`)
|
|
134
|
+
|
|
135
|
+
### Changed
|
|
136
|
+
- Multi-endpoint client default load-balancing strategy documented as **least-loaded**; expanded multi-endpoint coverage across prediction APIs
|
|
137
|
+
- README and guides updated for v1.5 NIM parameter limits (recycling/diffusion), PAE/PDE output, and PDB export
|
|
138
|
+
|
|
139
|
+
### Documentation
|
|
140
|
+
- Multi-endpoint virtual screening guide and examples (`comprehensive_multi_endpoint_demo.py`, `multi_endpoint_screening.py`)
|
|
141
|
+
|
|
142
|
+
## [0.3.0] - 2025-09-11
|
|
143
|
+
|
|
144
|
+
### Added
|
|
145
|
+
- **GPU-accelerated MSA Search NIM Integration**:
|
|
146
|
+
- New `MSASearchClient` for direct MSA Search NIM interaction
|
|
147
|
+
- `MSAFormatConverter` for A3M, FASTA, and Stockholm format support
|
|
148
|
+
- `MSASearchIntegration` for Boltz-2 workflow integration
|
|
149
|
+
- **New Client Methods**:
|
|
150
|
+
- `configure_msa_search()` - Configure MSA Search NIM endpoint
|
|
151
|
+
- `search_msa()` - Standalone MSA search
|
|
152
|
+
- `predict_with_msa_search()` - Integrated MSA + structure prediction
|
|
153
|
+
- `predict_ligand_with_msa_search()` - MSA + ligand + affinity prediction
|
|
154
|
+
- `batch_msa_search()` - Batch processing for multiple sequences
|
|
155
|
+
- **CLI Commands**:
|
|
156
|
+
- `boltz2 msa-search` - Search and save MSA alignments
|
|
157
|
+
- `boltz2 msa-predict` - Combined MSA search + structure prediction
|
|
158
|
+
- `boltz2 msa-ligand` - MSA-guided ligand affinity prediction
|
|
159
|
+
- `--msa-file` option for existing MSA files
|
|
160
|
+
- **Examples**:
|
|
161
|
+
- `10_msa_search_integration.py` - Comprehensive MSA integration demo
|
|
162
|
+
- `11_msa_search_large_protein.py` - Large protein optimization
|
|
163
|
+
- `12_msa_affinity_prediction.py` - MSA-guided affinity prediction
|
|
164
|
+
- **Documentation**:
|
|
165
|
+
- New MSA Search Guide with complete usage examples
|
|
166
|
+
- Updated Affinity Prediction Guide with MSA-guided section
|
|
167
|
+
- Enhanced README with MSA integration examples
|
|
168
|
+
|
|
169
|
+
### Fixed
|
|
170
|
+
- Parameter naming consistency: `max_hits` → `max_msa_sequences`, `e_value_threshold` → `e_value`
|
|
171
|
+
- MSA file handling in `predict_protein_structure()` method
|
|
172
|
+
- Documentation inconsistencies and outdated examples
|
|
173
|
+
|
|
174
|
+
### Improved
|
|
175
|
+
- Better error handling for MSA Search API responses
|
|
176
|
+
- Retry logic for MSA Search requests
|
|
177
|
+
- More comprehensive test coverage
|
|
178
|
+
|
|
179
|
+
## [0.2.1] - 2025-08-14
|
|
180
|
+
|
|
181
|
+
### Added
|
|
182
|
+
- Complete multi-endpoint support for ALL Boltz2 NIM functionalities:
|
|
183
|
+
- `predict_protein_structure()` with MSA support
|
|
184
|
+
- `predict_protein_ligand_complex()` with affinity prediction
|
|
185
|
+
- `predict_covalent_complex()`
|
|
186
|
+
- `predict_dna_protein_complex()`
|
|
187
|
+
- `predict_with_advanced_parameters()`
|
|
188
|
+
- `predict_from_yaml_config()` and `predict_from_yaml_file()`
|
|
189
|
+
- New `msa` parameter in `predict_protein_structure()` for direct MSA input
|
|
190
|
+
- Comprehensive demo notebook (`examples/boltz2_comprehensive_demo.ipynb`) with:
|
|
191
|
+
- Single and multi-endpoint examples
|
|
192
|
+
- Both Python API and CLI demonstrations
|
|
193
|
+
- Advanced features and visualization
|
|
194
|
+
- `AlignmentFormat` export in `__init__.py`
|
|
195
|
+
|
|
196
|
+
### Fixed
|
|
197
|
+
- MSA support now correctly uses nested dictionary format `{database: {format: AlignmentFileRecord}}`
|
|
198
|
+
- CLI multi-endpoint initialization (removed incorrect `is_async` parameter)
|
|
199
|
+
- Multi-endpoint client MSA parameter passing
|
|
200
|
+
- YAML configuration MSA format handling
|
|
201
|
+
|
|
202
|
+
### Changed
|
|
203
|
+
- Updated README.md examples (removed `is_async=True` from MultiEndpointClient)
|
|
204
|
+
- Improved error handling in multi-endpoint operations
|
|
205
|
+
- Better organization of test scripts into `test_scripts/` directory
|
|
206
|
+
|
|
207
|
+
### Documentation
|
|
208
|
+
- New comprehensive demo notebook with complete examples
|
|
209
|
+
- Updated all guides for consistency
|
|
210
|
+
- Added troubleshooting tips for multi-endpoint usage
|
|
211
|
+
|
|
212
|
+
## [0.2.0] - Previous release
|
|
213
|
+
- Initial multi-endpoint support for virtual screening
|
|
214
|
+
- Basic affinity prediction features
|
|
215
|
+
- Virtual screening capabilities
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.2
|
|
2
2
|
Name: boltz2-python-client
|
|
3
|
-
Version: 0.5.
|
|
3
|
+
Version: 0.5.2.post1
|
|
4
4
|
Summary: Python client for Boltz-2 protein structure prediction API with covalent complex and multi-endpoint support
|
|
5
5
|
Author-email: NVIDIA Corporation <bionemo-support@nvidia.com>
|
|
6
6
|
Maintainer-email: NVIDIA Corporation <bionemo-support@nvidia.com>
|
|
@@ -52,7 +52,7 @@ Copyright (c) 2025-2026, NVIDIA CORPORATION. All rights reserved.
|
|
|
52
52
|
[](https://www.python.org/downloads/)
|
|
53
53
|
[](https://opensource.org/licenses/MIT)
|
|
54
54
|
|
|
55
|
-
A comprehensive Python client for NVIDIA's Boltz-2 biomolecular structure prediction service. This package provides both synchronous and asynchronous interfaces, a rich CLI, and
|
|
55
|
+
A comprehensive Python client for NVIDIA's Boltz-2 biomolecular structure prediction service. This package provides both synchronous and asynchronous interfaces, a rich CLI, multi-endpoint load balancing, and notebook examples that visualize predicted structures with `py3Dmol` and Molstar.
|
|
56
56
|
|
|
57
57
|
## Features
|
|
58
58
|
|
|
@@ -167,18 +167,43 @@ client = Boltz2Client(
|
|
|
167
167
|
### AWS SageMaker Endpoint
|
|
168
168
|
|
|
169
169
|
```python
|
|
170
|
-
|
|
170
|
+
from boltz2_client import Boltz2SyncClient
|
|
171
|
+
|
|
172
|
+
# Requires: pip install "boltz2-python-client[sagemaker]"
|
|
173
|
+
# AWS credentials must be configured (e.g. via AWS_ACCESS_KEY_ID/AWS_SECRET_ACCESS_KEY
|
|
174
|
+
# environment variables, ~/.aws/credentials, or an IAM role)
|
|
175
|
+
|
|
176
|
+
client = Boltz2SyncClient(
|
|
171
177
|
endpoint_type="sagemaker",
|
|
172
178
|
sagemaker_endpoint_name="my-boltz2-endpoint",
|
|
173
179
|
sagemaker_region="us-east-1",
|
|
174
180
|
)
|
|
175
|
-
```
|
|
176
181
|
|
|
177
|
-
|
|
182
|
+
# Health check (calls describe_endpoint under the hood)
|
|
183
|
+
health = client.health_check()
|
|
184
|
+
print(f"Endpoint status: {health.status}")
|
|
185
|
+
|
|
186
|
+
# Predict protein structure — same API as local/hosted endpoints
|
|
187
|
+
result = client.predict_protein_structure(
|
|
188
|
+
sequence="MKTVRQERLKSIVRILERSKEPVSGAQLAEELSVSRQVIVQDIAYLRSLGYNIVATPRGYVLAGG",
|
|
189
|
+
recycling_steps=3,
|
|
190
|
+
sampling_steps=200,
|
|
191
|
+
)
|
|
192
|
+
print(f"Confidence: {result.confidence_scores[0]:.3f}")
|
|
193
|
+
|
|
194
|
+
# Protein-ligand with affinity prediction
|
|
195
|
+
result = client.predict_protein_ligand_complex(
|
|
196
|
+
protein_sequence="MKTVRQERLK...",
|
|
197
|
+
ligand_smiles="CC(=O)OC1=CC=CC=C1C(=O)O",
|
|
198
|
+
predict_affinity=True,
|
|
199
|
+
)
|
|
200
|
+
```
|
|
178
201
|
|
|
179
202
|
```bash
|
|
180
|
-
# CLI
|
|
203
|
+
# CLI — all commands work with SageMaker by adding the endpoint flags
|
|
181
204
|
boltz2 --endpoint-type sagemaker --sagemaker-endpoint-name my-boltz2-endpoint health
|
|
205
|
+
boltz2 --endpoint-type sagemaker --sagemaker-endpoint-name my-boltz2-endpoint \
|
|
206
|
+
protein "MKTVRQERLKSIVRILERSKEPVSGAQLAEELSVSRQVIVQDIAYLRSLGYNIVATPRGYVLAGG"
|
|
182
207
|
```
|
|
183
208
|
|
|
184
209
|
## Supported Prediction Types
|
|
@@ -6,7 +6,7 @@ Copyright (c) 2025-2026, NVIDIA CORPORATION. All rights reserved.
|
|
|
6
6
|
[](https://www.python.org/downloads/)
|
|
7
7
|
[](https://opensource.org/licenses/MIT)
|
|
8
8
|
|
|
9
|
-
A comprehensive Python client for NVIDIA's Boltz-2 biomolecular structure prediction service. This package provides both synchronous and asynchronous interfaces, a rich CLI, and
|
|
9
|
+
A comprehensive Python client for NVIDIA's Boltz-2 biomolecular structure prediction service. This package provides both synchronous and asynchronous interfaces, a rich CLI, multi-endpoint load balancing, and notebook examples that visualize predicted structures with `py3Dmol` and Molstar.
|
|
10
10
|
|
|
11
11
|
## Features
|
|
12
12
|
|
|
@@ -121,18 +121,43 @@ client = Boltz2Client(
|
|
|
121
121
|
### AWS SageMaker Endpoint
|
|
122
122
|
|
|
123
123
|
```python
|
|
124
|
-
|
|
124
|
+
from boltz2_client import Boltz2SyncClient
|
|
125
|
+
|
|
126
|
+
# Requires: pip install "boltz2-python-client[sagemaker]"
|
|
127
|
+
# AWS credentials must be configured (e.g. via AWS_ACCESS_KEY_ID/AWS_SECRET_ACCESS_KEY
|
|
128
|
+
# environment variables, ~/.aws/credentials, or an IAM role)
|
|
129
|
+
|
|
130
|
+
client = Boltz2SyncClient(
|
|
125
131
|
endpoint_type="sagemaker",
|
|
126
132
|
sagemaker_endpoint_name="my-boltz2-endpoint",
|
|
127
133
|
sagemaker_region="us-east-1",
|
|
128
134
|
)
|
|
129
|
-
```
|
|
130
135
|
|
|
131
|
-
|
|
136
|
+
# Health check (calls describe_endpoint under the hood)
|
|
137
|
+
health = client.health_check()
|
|
138
|
+
print(f"Endpoint status: {health.status}")
|
|
139
|
+
|
|
140
|
+
# Predict protein structure — same API as local/hosted endpoints
|
|
141
|
+
result = client.predict_protein_structure(
|
|
142
|
+
sequence="MKTVRQERLKSIVRILERSKEPVSGAQLAEELSVSRQVIVQDIAYLRSLGYNIVATPRGYVLAGG",
|
|
143
|
+
recycling_steps=3,
|
|
144
|
+
sampling_steps=200,
|
|
145
|
+
)
|
|
146
|
+
print(f"Confidence: {result.confidence_scores[0]:.3f}")
|
|
147
|
+
|
|
148
|
+
# Protein-ligand with affinity prediction
|
|
149
|
+
result = client.predict_protein_ligand_complex(
|
|
150
|
+
protein_sequence="MKTVRQERLK...",
|
|
151
|
+
ligand_smiles="CC(=O)OC1=CC=CC=C1C(=O)O",
|
|
152
|
+
predict_affinity=True,
|
|
153
|
+
)
|
|
154
|
+
```
|
|
132
155
|
|
|
133
156
|
```bash
|
|
134
|
-
# CLI
|
|
157
|
+
# CLI — all commands work with SageMaker by adding the endpoint flags
|
|
135
158
|
boltz2 --endpoint-type sagemaker --sagemaker-endpoint-name my-boltz2-endpoint health
|
|
159
|
+
boltz2 --endpoint-type sagemaker --sagemaker-endpoint-name my-boltz2-endpoint \
|
|
160
|
+
protein "MKTVRQERLKSIVRILERSKEPVSGAQLAEELSVSRQVIVQDIAYLRSLGYNIVATPRGYVLAGG"
|
|
136
161
|
```
|
|
137
162
|
|
|
138
163
|
## Supported Prediction Types
|
|
@@ -26,7 +26,7 @@ Example:
|
|
|
26
26
|
>>> print(f"Confidence: {result.confidence_scores[0]:.3f}")
|
|
27
27
|
"""
|
|
28
28
|
|
|
29
|
-
__version__ = "0.5.
|
|
29
|
+
__version__ = "0.5.2.post1"
|
|
30
30
|
__author__ = "NVIDIA Corporation"
|
|
31
31
|
__email__ = "bionemo-support@nvidia.com"
|
|
32
32
|
|
|
@@ -103,28 +103,6 @@ from .utils import (
|
|
|
103
103
|
convert_pdb_to_cif,
|
|
104
104
|
)
|
|
105
105
|
|
|
106
|
-
# Optional imports for visualization
|
|
107
|
-
try:
|
|
108
|
-
from .visualization import (
|
|
109
|
-
StructureVisualizer,
|
|
110
|
-
visualize_structure,
|
|
111
|
-
create_multi_view,
|
|
112
|
-
)
|
|
113
|
-
_HAS_VISUALIZATION = True
|
|
114
|
-
except ImportError:
|
|
115
|
-
_HAS_VISUALIZATION = False
|
|
116
|
-
|
|
117
|
-
# Optional imports for analysis
|
|
118
|
-
try:
|
|
119
|
-
from .analysis import (
|
|
120
|
-
StructureAnalyzer,
|
|
121
|
-
calculate_rmsd,
|
|
122
|
-
analyze_contacts,
|
|
123
|
-
)
|
|
124
|
-
_HAS_ANALYSIS = True
|
|
125
|
-
except ImportError:
|
|
126
|
-
_HAS_ANALYSIS = False
|
|
127
|
-
|
|
128
106
|
__all__ = [
|
|
129
107
|
# Core client classes
|
|
130
108
|
"Boltz2Client",
|
|
@@ -201,21 +179,6 @@ __all__ = [
|
|
|
201
179
|
"SPECIES_TO_TAXID",
|
|
202
180
|
]
|
|
203
181
|
|
|
204
|
-
# Add visualization exports if available
|
|
205
|
-
if _HAS_VISUALIZATION:
|
|
206
|
-
__all__.extend([
|
|
207
|
-
"StructureVisualizer",
|
|
208
|
-
"visualize_structure",
|
|
209
|
-
"create_multi_view",
|
|
210
|
-
])
|
|
211
|
-
|
|
212
|
-
# Add analysis exports if available
|
|
213
|
-
if _HAS_ANALYSIS:
|
|
214
|
-
__all__.extend([
|
|
215
|
-
"StructureAnalyzer",
|
|
216
|
-
"calculate_rmsd",
|
|
217
|
-
"analyze_contacts",
|
|
218
|
-
])
|
|
219
182
|
|
|
220
183
|
def get_version() -> str:
|
|
221
184
|
"""Get the current version of the package."""
|
{boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/boltz2_client/cli/__init__.py
RENAMED
|
@@ -22,6 +22,7 @@ from rich.table import Table
|
|
|
22
22
|
from rich.progress import Progress, SpinnerColumn, TextColumn, TimeElapsedColumn, BarColumn
|
|
23
23
|
import yaml as pyyaml
|
|
24
24
|
|
|
25
|
+
from .. import __version__ as _pkg_version
|
|
25
26
|
from ..client import Boltz2Client
|
|
26
27
|
from ..models import (
|
|
27
28
|
PredictionRequest, Polymer, Ligand, BondConstraint,
|
|
@@ -53,6 +54,8 @@ def print_warning(message: str):
|
|
|
53
54
|
|
|
54
55
|
|
|
55
56
|
@click.group()
|
|
57
|
+
@click.version_option(_pkg_version, "-V", "--version", prog_name="boltz2",
|
|
58
|
+
message="%(prog)s %(version)s")
|
|
56
59
|
@click.option('--base-url', default='http://localhost:8000', help='Service base URL (can be comma-separated for multiple endpoints)')
|
|
57
60
|
@click.option('--api-key', help='API key for NVIDIA hosted endpoints (or set NVIDIA_API_KEY env var)')
|
|
58
61
|
@click.option('--endpoint-type',
|
|
@@ -78,6 +78,11 @@ def metadata(ctx):
|
|
|
78
78
|
"""Get service metadata and model information."""
|
|
79
79
|
async def get_metadata():
|
|
80
80
|
try:
|
|
81
|
+
if ctx.obj.get('endpoint_type') == 'sagemaker':
|
|
82
|
+
print_error("Metadata endpoint is not available for SageMaker endpoints.")
|
|
83
|
+
print_error("Use 'boltz2 ... health' to check SageMaker endpoint status.")
|
|
84
|
+
raise click.Abort()
|
|
85
|
+
|
|
81
86
|
client = create_client(ctx)
|
|
82
87
|
|
|
83
88
|
with Progress(
|
|
@@ -108,6 +113,8 @@ def metadata(ctx):
|
|
|
108
113
|
|
|
109
114
|
console.print(table)
|
|
110
115
|
|
|
116
|
+
except click.Abort:
|
|
117
|
+
raise
|
|
111
118
|
except Exception as e:
|
|
112
119
|
print_error(f"Failed to get metadata: {e}")
|
|
113
120
|
raise click.Abort()
|
|
@@ -115,8 +115,12 @@ def msa_search_command(ctx, sequence: str, endpoint: str, databases: List[str],
|
|
|
115
115
|
|
|
116
116
|
except Exception as e:
|
|
117
117
|
print_error(f"MSA search failed: {e}")
|
|
118
|
+
raise
|
|
118
119
|
|
|
119
|
-
|
|
120
|
+
try:
|
|
121
|
+
asyncio.run(run_msa_search())
|
|
122
|
+
except Exception:
|
|
123
|
+
raise click.Abort()
|
|
120
124
|
|
|
121
125
|
|
|
122
126
|
@cli.command(name='msa-predict')
|
|
@@ -233,8 +237,12 @@ def msa_predict_command(ctx, sequence: str, endpoint: str, databases: List[str],
|
|
|
233
237
|
|
|
234
238
|
except Exception as e:
|
|
235
239
|
print_error(f"MSA prediction failed: {e}")
|
|
240
|
+
raise
|
|
236
241
|
|
|
237
|
-
|
|
242
|
+
try:
|
|
243
|
+
asyncio.run(run_msa_predict())
|
|
244
|
+
except Exception:
|
|
245
|
+
raise click.Abort()
|
|
238
246
|
|
|
239
247
|
|
|
240
248
|
@cli.command(name='msa-ligand')
|
|
@@ -380,8 +388,12 @@ def msa_ligand_command(ctx, protein_sequence: str, smiles: Optional[str], ccd: O
|
|
|
380
388
|
|
|
381
389
|
except Exception as e:
|
|
382
390
|
print_error(f"MSA-ligand prediction failed: {e}")
|
|
391
|
+
raise
|
|
383
392
|
|
|
384
|
-
|
|
393
|
+
try:
|
|
394
|
+
asyncio.run(run_msa_ligand())
|
|
395
|
+
except Exception:
|
|
396
|
+
raise click.Abort()
|
|
385
397
|
|
|
386
398
|
|
|
387
399
|
@cli.command(name='convert-msa')
|
|
@@ -779,8 +791,6 @@ def multimer_msa_command(ctx, a3m_files: Tuple[str, ...], chain_ids: str,
|
|
|
779
791
|
|
|
780
792
|
# Save all outputs if requested
|
|
781
793
|
if save_all:
|
|
782
|
-
import json
|
|
783
|
-
|
|
784
794
|
# Collect all scores and metrics
|
|
785
795
|
scores = {
|
|
786
796
|
'confidence_scores': response.confidence_scores,
|
|
@@ -44,11 +44,15 @@ def screen(ctx, target_sequence, compounds_file, target_name, output_dir, no_aff
|
|
|
44
44
|
boltz2 screen "MKTVRQERLK..." compounds.csv -o results/
|
|
45
45
|
boltz2 screen target.fasta library.json --pocket-residues "10,15,20,25"
|
|
46
46
|
"""
|
|
47
|
-
client = create_client(ctx)
|
|
48
|
-
|
|
49
47
|
# Import here to avoid circular imports
|
|
50
48
|
from ..virtual_screening import VirtualScreening, CompoundLibrary
|
|
51
49
|
|
|
50
|
+
try:
|
|
51
|
+
client = create_client(ctx)
|
|
52
|
+
except Exception as e:
|
|
53
|
+
print_error(f"Failed to initialize client: {e}")
|
|
54
|
+
raise click.Abort()
|
|
55
|
+
|
|
52
56
|
console.print(f"\n[bold cyan]🧬 Virtual Screening Campaign[/bold cyan]")
|
|
53
57
|
console.print(f"Target: {target_name}")
|
|
54
58
|
console.print(f"Compounds: {compounds_file}")
|
|
@@ -64,7 +68,11 @@ def screen(ctx, target_sequence, compounds_file, target_name, output_dir, no_aff
|
|
|
64
68
|
# Parse pocket residues
|
|
65
69
|
pocket_residues_list = None
|
|
66
70
|
if pocket_residues:
|
|
67
|
-
|
|
71
|
+
try:
|
|
72
|
+
pocket_residues_list = [int(x.strip()) for x in pocket_residues.split(',')]
|
|
73
|
+
except ValueError as e:
|
|
74
|
+
print_error(f"Invalid --pocket-residues value (expected comma-separated ints): {e}")
|
|
75
|
+
raise click.Abort()
|
|
68
76
|
console.print(f"Pocket constraint: {len(pocket_residues_list)} residues")
|
|
69
77
|
|
|
70
78
|
# Create screener
|
|
@@ -243,8 +243,6 @@ class Boltz2Client:
|
|
|
243
243
|
self, request_dict: dict, progress_callback: Optional[Callable] = None
|
|
244
244
|
) -> dict:
|
|
245
245
|
"""Invoke a SageMaker endpoint and return the parsed JSON response."""
|
|
246
|
-
import asyncio
|
|
247
|
-
|
|
248
246
|
def _invoke():
|
|
249
247
|
return self._sm_runtime.invoke_endpoint(
|
|
250
248
|
EndpointName=self._sm_endpoint_name,
|
|
@@ -256,7 +254,10 @@ class Boltz2Client:
|
|
|
256
254
|
if progress_callback:
|
|
257
255
|
progress_callback(f"Invoking SageMaker endpoint {self._sm_endpoint_name}...")
|
|
258
256
|
|
|
259
|
-
|
|
257
|
+
# Always run the blocking boto3 call in a worker thread. Use the
|
|
258
|
+
# currently running loop (asyncio.get_event_loop is deprecated for
|
|
259
|
+
# this purpose in Python 3.10+ and emits a DeprecationWarning).
|
|
260
|
+
loop = asyncio.get_running_loop()
|
|
260
261
|
response = await loop.run_in_executor(None, _invoke)
|
|
261
262
|
|
|
262
263
|
http_status = response["ResponseMetadata"]["HTTPStatusCode"]
|