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.
Files changed (101) hide show
  1. boltz2_python_client-0.5.2.post1/CHANGELOG.md +215 -0
  2. {boltz2_python_client-0.5.0/boltz2_python_client.egg-info → boltz2_python_client-0.5.2.post1}/PKG-INFO +31 -6
  3. {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/README.md +30 -5
  4. {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/boltz2_client/__init__.py +1 -38
  5. {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/boltz2_client/cli/__init__.py +3 -0
  6. {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/boltz2_client/cli/info.py +7 -0
  7. {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/boltz2_client/cli/msa.py +15 -5
  8. {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/boltz2_client/cli/screen.py +11 -3
  9. {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/boltz2_client/client.py +4 -3
  10. {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/boltz2_client/multi_endpoint_client.py +177 -43
  11. {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/boltz2_client/virtual_screening.py +43 -19
  12. {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1/boltz2_python_client.egg-info}/PKG-INFO +31 -6
  13. {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/boltz2_python_client.egg-info/SOURCES.txt +2 -1
  14. {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/docs/multi_endpoint.md +35 -0
  15. boltz2_python_client-0.5.2.post1/tests/test_multi_endpoint_reliability.py +317 -0
  16. boltz2_python_client-0.5.0/CHANGELOG.md +0 -108
  17. {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/LICENSE +0 -0
  18. {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/MANIFEST.in +0 -0
  19. {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/boltz2_client/__main__.py +0 -0
  20. {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/boltz2_client/a3m/__init__.py +0 -0
  21. {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/boltz2_client/a3m/converter.py +0 -0
  22. {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/boltz2_client/a3m/pairing.py +0 -0
  23. {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/boltz2_client/a3m/parser.py +0 -0
  24. {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/boltz2_client/a3m_to_csv_converter.py +0 -0
  25. {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/boltz2_client/cli/predict.py +0 -0
  26. {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/boltz2_client/data/__init__.py +0 -0
  27. {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/boltz2_client/data/speclist.txt +0 -0
  28. {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/boltz2_client/exceptions.py +0 -0
  29. {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/boltz2_client/models.py +0 -0
  30. {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/boltz2_client/msa_search.py +0 -0
  31. {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/boltz2_client/utils.py +0 -0
  32. {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/boltz2_python_client.egg-info/dependency_links.txt +0 -0
  33. {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/boltz2_python_client.egg-info/entry_points.txt +0 -0
  34. {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/boltz2_python_client.egg-info/requires.txt +0 -0
  35. {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/boltz2_python_client.egg-info/top_level.txt +0 -0
  36. {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/docs/a3m_to_multimer_msa.md +0 -0
  37. {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/docs/affinity_prediction.md +0 -0
  38. {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/docs/async.md +0 -0
  39. {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/docs/covalent_complex.md +0 -0
  40. {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/docs/msa_search.md +0 -0
  41. {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/docs/parameters.md +0 -0
  42. {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/docs/virtual_screening.md +0 -0
  43. {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/docs/yaml.md +0 -0
  44. {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/examples/01_basic_protein_folding.py +0 -0
  45. {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/examples/02_protein_structure_prediction_with_msa.py +0 -0
  46. {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/examples/03_protein_ligand_complex.py +0 -0
  47. {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/examples/04_covalent_bonding.py +0 -0
  48. {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/examples/05_dna_protein_complex.py +0 -0
  49. {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/examples/06_yaml_configurations.py +0 -0
  50. {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/examples/07_advanced_parameters.py +0 -0
  51. {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/examples/08_affinity_prediction_simple.py +0 -0
  52. {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/examples/09_virtual_screening.py +0 -0
  53. {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/examples/10_msa_search_integration.py +0 -0
  54. {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/examples/11_msa_search_large_protein.py +0 -0
  55. {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/examples/12_msa_affinity_prediction.py +0 -0
  56. {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/examples/13_a3m_to_multimer_csv.py +0 -0
  57. {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/examples/README.md +0 -0
  58. {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/examples/barnase_barstar_with_msa.py +0 -0
  59. {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/examples/cdk4_msa_affinity_example.py +0 -0
  60. {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/examples/comprehensive_multi_endpoint_demo.py +0 -0
  61. {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/examples/data/cdk2_target.txt +0 -0
  62. {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/examples/data/cdk4_msa_affinity/cdk4_palbociclib_results.json +0 -0
  63. {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/examples/data/kinase_y7w_affinity.json +0 -0
  64. {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/examples/data/msa-kras-g12c_combined.a3m +0 -0
  65. {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/examples/data/multi_protein_complex.yaml +0 -0
  66. {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/examples/data/protein_ligand.yaml +0 -0
  67. {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/examples/data/sars_cov2_mpro_nirmatrelvir.yaml +0 -0
  68. {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/examples/data/test_msa_endpoint_curl.sh +0 -0
  69. {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/examples/msa_search_simple_demo.py +0 -0
  70. {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/examples/multi_endpoint_screening.py +0 -0
  71. {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/examples/notebooks/01_multimer_prediction.ipynb +0 -0
  72. {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/examples/notebooks/02_cdk4_msa_affinity_prediction.ipynb +0 -0
  73. {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/examples/notebooks/03_colabfold_a3m_to_multimer.ipynb +0 -0
  74. {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/examples/notebooks/boltz2_comprehensive_demo.ipynb +0 -0
  75. {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/examples/notebooks/boltz2_demo.ipynb +0 -0
  76. {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
  77. {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
  78. {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/licenses/PyYAML-LICENSE +0 -0
  79. {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/licenses/README.md +0 -0
  80. {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/licenses/aiofiles-LICENSE +0 -0
  81. {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/licenses/aiohttp-LICENSE +0 -0
  82. {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/licenses/click-LICENSE +0 -0
  83. {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/licenses/httpx-LICENSE +0 -0
  84. {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/licenses/py3Dmol-LICENSE +0 -0
  85. {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/licenses/pydantic-LICENSE +0 -0
  86. {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/licenses/rich-LICENSE +0 -0
  87. {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/licenses/typing-extensions-LICENSE +0 -0
  88. {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/pyproject.toml +0 -0
  89. {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/setup.cfg +0 -0
  90. {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/tests/__init__.py +0 -0
  91. {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/tests/conftest.py +0 -0
  92. {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/tests/constants.py +0 -0
  93. {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/tests/test_a3m_to_csv_converter.py +0 -0
  94. {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/tests/test_basic.py +0 -0
  95. {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/tests/test_cli_multi_endpoint.py +0 -0
  96. {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/tests/test_comprehensive_stress.py +0 -0
  97. {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/tests/test_examples_syntax.py +0 -0
  98. {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/tests/test_integration_scenarios.py +0 -0
  99. {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/tests/test_live_endpoints.py +0 -0
  100. {boltz2_python_client-0.5.0 → boltz2_python_client-0.5.2.post1}/tests/test_msa_search.py +0 -0
  101. {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.0
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
  [![Python 3.8+](https://img.shields.io/badge/python-3.8+-blue.svg)](https://www.python.org/downloads/)
53
53
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](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 built-in 3D visualization capabilities.
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
- client = Boltz2Client(
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
- Requires `pip install "boltz2-python-client[sagemaker]"` and AWS credentials.
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
  [![Python 3.8+](https://img.shields.io/badge/python-3.8+-blue.svg)](https://www.python.org/downloads/)
7
7
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](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 built-in 3D visualization capabilities.
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
- client = Boltz2Client(
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
- Requires `pip install "boltz2-python-client[sagemaker]"` and AWS credentials.
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.0"
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."""
@@ -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
- asyncio.run(run_msa_search())
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
- asyncio.run(run_msa_predict())
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
- asyncio.run(run_msa_ligand())
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
- pocket_residues_list = [int(x.strip()) for x in pocket_residues.split(',')]
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
- loop = asyncio.get_event_loop()
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"]