AMDockVS 0.1.0__py3-none-any.whl

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 (269) hide show
  1. amdockvs/__init__.py +67 -0
  2. amdockvs/__main__.py +5 -0
  3. amdockvs/app.py +181 -0
  4. amdockvs/binding_sites/__init__.py +22 -0
  5. amdockvs/binding_sites/api.py +444 -0
  6. amdockvs/binding_sites/boxes.py +180 -0
  7. amdockvs/binding_sites/cavity.py +247 -0
  8. amdockvs/binding_sites/from_structure.py +54 -0
  9. amdockvs/binding_sites/jobs.py +246 -0
  10. amdockvs/binding_sites/p2rank.py +465 -0
  11. amdockvs/binding_sites/repository.py +32 -0
  12. amdockvs/binding_sites/scopes.py +15 -0
  13. amdockvs/chemistry/__init__.py +54 -0
  14. amdockvs/chemistry/alignment.py +52 -0
  15. amdockvs/chemistry/api.py +575 -0
  16. amdockvs/chemistry/conformers.py +50 -0
  17. amdockvs/chemistry/descriptors.py +123 -0
  18. amdockvs/chemistry/filtering.py +403 -0
  19. amdockvs/chemistry/fingerprints.py +72 -0
  20. amdockvs/chemistry/jobs.py +519 -0
  21. amdockvs/chemistry/pipeline.py +146 -0
  22. amdockvs/chemistry/protonation.py +178 -0
  23. amdockvs/chemistry/repository.py +189 -0
  24. amdockvs/chemistry/rmsd.py +39 -0
  25. amdockvs/chemistry/service.py +472 -0
  26. amdockvs/chemistry/shards.py +110 -0
  27. amdockvs/chemistry/standardization.py +96 -0
  28. amdockvs/chemistry/state.py +31 -0
  29. amdockvs/chemistry/tools/__init__.py +23 -0
  30. amdockvs/chemistry/tools/esmfold.py +221 -0
  31. amdockvs/chemistry/tools/ligands.py +219 -0
  32. amdockvs/chemistry/tools/receptors.py +176 -0
  33. amdockvs/complexes/__init__.py +3 -0
  34. amdockvs/complexes/api.py +155 -0
  35. amdockvs/core/__init__.py +4 -0
  36. amdockvs/core/config.toml +45 -0
  37. amdockvs/core/configuration.py +416 -0
  38. amdockvs/core/constants.py +121 -0
  39. amdockvs/core/normalize.py +59 -0
  40. amdockvs/core/paths.py +257 -0
  41. amdockvs/core/user_env.py +50 -0
  42. amdockvs/core/vocab.py +204 -0
  43. amdockvs/core/worker_io.py +86 -0
  44. amdockvs/data/hetero_codes.json +8 -0
  45. amdockvs/diversity/__init__.py +24 -0
  46. amdockvs/diversity/api.py +647 -0
  47. amdockvs/diversity/clustering.py +613 -0
  48. amdockvs/diversity/jobs.py +333 -0
  49. amdockvs/docking/__init__.py +138 -0
  50. amdockvs/docking/api.py +1472 -0
  51. amdockvs/docking/engines/__init__.py +6 -0
  52. amdockvs/docking/engines/autodock4.py +309 -0
  53. amdockvs/docking/engines/gnina.py +337 -0
  54. amdockvs/docking/engines/programs.py +294 -0
  55. amdockvs/docking/engines/registry.py +102 -0
  56. amdockvs/docking/engines/vina.py +720 -0
  57. amdockvs/docking/jobs.py +797 -0
  58. amdockvs/docking/pairs.py +241 -0
  59. amdockvs/docking/planning.py +120 -0
  60. amdockvs/docking/preparation/__init__.py +5 -0
  61. amdockvs/docking/preparation/entities.py +165 -0
  62. amdockvs/docking/preparation/jobs.py +447 -0
  63. amdockvs/docking/preparation/meeko.py +236 -0
  64. amdockvs/docking/preparation/profiles.py +69 -0
  65. amdockvs/docking/preparation/shards.py +258 -0
  66. amdockvs/docking/preparation/state.py +137 -0
  67. amdockvs/docking/protocols.py +80 -0
  68. amdockvs/docking/readiness.py +291 -0
  69. amdockvs/docking/repository.py +620 -0
  70. amdockvs/docking/residues.py +107 -0
  71. amdockvs/docking/results/__init__.py +5 -0
  72. amdockvs/docking/results/dataset.py +402 -0
  73. amdockvs/docking/results/diagram.py +398 -0
  74. amdockvs/docking/results/interactions.py +186 -0
  75. amdockvs/docking/results/jobs.py +284 -0
  76. amdockvs/docking/results/metrics.py +127 -0
  77. amdockvs/docking/results/redocking.py +123 -0
  78. amdockvs/docking/results/repository.py +810 -0
  79. amdockvs/docking/results/rmsd.py +115 -0
  80. amdockvs/docking/results/tables.py +264 -0
  81. amdockvs/docking/shard_jobs.py +935 -0
  82. amdockvs/docking/submission.py +102 -0
  83. amdockvs/integrations/__init__.py +6 -0
  84. amdockvs/integrations/api.py +48 -0
  85. amdockvs/integrations/contracts.py +28 -0
  86. amdockvs/integrations/envs.py +155 -0
  87. amdockvs/integrations/pkasso.py +50 -0
  88. amdockvs/integrations/registry.py +190 -0
  89. amdockvs/io/__init__.py +39 -0
  90. amdockvs/io/_common.py +37 -0
  91. amdockvs/io/api.py +366 -0
  92. amdockvs/io/ccd_bonds.py +180 -0
  93. amdockvs/io/formats.py +394 -0
  94. amdockvs/io/import_stats.py +88 -0
  95. amdockvs/io/jobs.py +446 -0
  96. amdockvs/io/loaders.py +137 -0
  97. amdockvs/io/parsers/__init__.py +17 -0
  98. amdockvs/io/parsers/readers.py +390 -0
  99. amdockvs/io/payloads.py +341 -0
  100. amdockvs/io/properties.py +57 -0
  101. amdockvs/io/receptor_preview.py +967 -0
  102. amdockvs/io/rows.py +232 -0
  103. amdockvs/io/shards.py +334 -0
  104. amdockvs/io/transformers/__init__.py +13 -0
  105. amdockvs/io/transformers/materializers.py +439 -0
  106. amdockvs/io/transformers/rows.py +283 -0
  107. amdockvs/io/transformers/sdf.py +130 -0
  108. amdockvs/io/transformers/sequences.py +48 -0
  109. amdockvs/io/transformers/smiles.py +155 -0
  110. amdockvs/io/transformers/structures.py +405 -0
  111. amdockvs/manifest.py +30 -0
  112. amdockvs/models/__init__.py +84 -0
  113. amdockvs/models/base.py +13 -0
  114. amdockvs/models/clustering.py +154 -0
  115. amdockvs/models/complexes.py +53 -0
  116. amdockvs/models/descriptors.py +80 -0
  117. amdockvs/models/docking.py +325 -0
  118. amdockvs/models/molecules.py +363 -0
  119. amdockvs/models/qsar.py +149 -0
  120. amdockvs/models/screening.py +212 -0
  121. amdockvs/models/sets.py +84 -0
  122. amdockvs/molecules/__init__.py +8 -0
  123. amdockvs/molecules/api.py +548 -0
  124. amdockvs/molecules/filtering.py +154 -0
  125. amdockvs/molecules/fragments.py +367 -0
  126. amdockvs/molecules/repository.py +108 -0
  127. amdockvs/molecules/scopes.py +49 -0
  128. amdockvs/molecules/storage.py +473 -0
  129. amdockvs/project/__init__.py +1 -0
  130. amdockvs/project/deletion.py +129 -0
  131. amdockvs/project/sets.py +277 -0
  132. amdockvs/project/summaries.py +236 -0
  133. amdockvs/qsar/__init__.py +31 -0
  134. amdockvs/qsar/api.py +1429 -0
  135. amdockvs/qsar/jobs.py +195 -0
  136. amdockvs/qsar/modeling.py +462 -0
  137. amdockvs/runtime.py +582 -0
  138. amdockvs/screening/__init__.py +12 -0
  139. amdockvs/screening/campaign.py +241 -0
  140. amdockvs/screening/filters.py +114 -0
  141. amdockvs/screening/materialize.py +289 -0
  142. amdockvs/shards.py +35 -0
  143. amdockvs/ui/__init__.py +9 -0
  144. amdockvs/ui/app_widget/__init__.py +0 -0
  145. amdockvs/ui/app_widget/widget.py +21 -0
  146. amdockvs/ui/catalog/__init__.py +50 -0
  147. amdockvs/ui/catalog/activity.py +294 -0
  148. amdockvs/ui/catalog/binding_sites.py +91 -0
  149. amdockvs/ui/catalog/common.py +515 -0
  150. amdockvs/ui/catalog/complexes.py +87 -0
  151. amdockvs/ui/catalog/deletion.py +56 -0
  152. amdockvs/ui/catalog/details.py +380 -0
  153. amdockvs/ui/catalog/domain_views.py +57 -0
  154. amdockvs/ui/catalog/ligands.py +169 -0
  155. amdockvs/ui/catalog/molecules.py +178 -0
  156. amdockvs/ui/catalog/receptors.py +926 -0
  157. amdockvs/ui/catalog/results.py +937 -0
  158. amdockvs/ui/catalog/shards.py +92 -0
  159. amdockvs/ui/common/__init__.py +4 -0
  160. amdockvs/ui/common/async_query.py +199 -0
  161. amdockvs/ui/common/drop_area.py +116 -0
  162. amdockvs/ui/common/job_follower.py +113 -0
  163. amdockvs/ui/common/theme.py +62 -0
  164. amdockvs/ui/common/widgets.py +86 -0
  165. amdockvs/ui/main_window.py +596 -0
  166. amdockvs/ui/monitor/__init__.py +3 -0
  167. amdockvs/ui/monitor/monitor.py +24 -0
  168. amdockvs/ui/registry.py +124 -0
  169. amdockvs/ui/resources/__init__.py +1 -0
  170. amdockvs/ui/resources/icons/__init__.py +47 -0
  171. amdockvs/ui/resources/icons/activity.svg +1 -0
  172. amdockvs/ui/resources/icons/bell.svg +1 -0
  173. amdockvs/ui/resources/icons/binding_site.svg +53 -0
  174. amdockvs/ui/resources/icons/build.svg +1 -0
  175. amdockvs/ui/resources/icons/catalog.svg +1 -0
  176. amdockvs/ui/resources/icons/cloud.svg +1 -0
  177. amdockvs/ui/resources/icons/columns.svg +1 -0
  178. amdockvs/ui/resources/icons/complexes.svg +1 -0
  179. amdockvs/ui/resources/icons/cpu.svg +1 -0
  180. amdockvs/ui/resources/icons/details.svg +1 -0
  181. amdockvs/ui/resources/icons/diversity.svg +53 -0
  182. amdockvs/ui/resources/icons/doc.svg +1 -0
  183. amdockvs/ui/resources/icons/docking.svg +67 -0
  184. amdockvs/ui/resources/icons/docking_results.svg +60 -0
  185. amdockvs/ui/resources/icons/file-plus.svg +1 -0
  186. amdockvs/ui/resources/icons/filter.svg +1 -0
  187. amdockvs/ui/resources/icons/help.svg +1 -0
  188. amdockvs/ui/resources/icons/info.svg +1 -0
  189. amdockvs/ui/resources/icons/ligands.svg +78 -0
  190. amdockvs/ui/resources/icons/logo.png +0 -0
  191. amdockvs/ui/resources/icons/logo.svg +4 -0
  192. amdockvs/ui/resources/icons/menu.svg +1 -0
  193. amdockvs/ui/resources/icons/models.svg +1 -0
  194. amdockvs/ui/resources/icons/mol_tools.svg +1 -0
  195. amdockvs/ui/resources/icons/offtarget.svg +61 -0
  196. amdockvs/ui/resources/icons/predictions.svg +1 -0
  197. amdockvs/ui/resources/icons/pymol.svg +1 -0
  198. amdockvs/ui/resources/icons/qsar.svg +67 -0
  199. amdockvs/ui/resources/icons/receptor.svg +40 -0
  200. amdockvs/ui/resources/icons/redocking.svg +58 -0
  201. amdockvs/ui/resources/icons/reset.svg +1 -0
  202. amdockvs/ui/resources/icons/search.svg +1 -0
  203. amdockvs/ui/resources/icons/settings.svg +1 -0
  204. amdockvs/ui/resources/icons/shredder.svg +1 -0
  205. amdockvs/ui/resources/icons/sort-asc.svg +1 -0
  206. amdockvs/ui/resources/icons/sort-desc.svg +1 -0
  207. amdockvs/ui/resources/icons/sort.svg +1 -0
  208. amdockvs/ui/resources/icons/style.svg +1 -0
  209. amdockvs/ui/resources/icons/target.svg +1 -0
  210. amdockvs/ui/resources/icons/text-input.svg +1 -0
  211. amdockvs/ui/resources/icons/theme.svg +1 -0
  212. amdockvs/ui/resources/icons/themed.py +324 -0
  213. amdockvs/ui/resources/icons/trash.svg +1 -0
  214. amdockvs/ui/resources/icons/workflow.svg +1 -0
  215. amdockvs/ui/resources/icons/x.svg +1 -0
  216. amdockvs/ui/resources/images/__init__.py +0 -0
  217. amdockvs/ui/shell/__init__.py +0 -0
  218. amdockvs/ui/shell/auxiliary_panel.py +227 -0
  219. amdockvs/ui/shell/job_feedback.py +376 -0
  220. amdockvs/ui/shell/main_content.py +223 -0
  221. amdockvs/ui/shell/notifications.py +148 -0
  222. amdockvs/ui/shell/project_summary.py +112 -0
  223. amdockvs/ui/shell/projects.py +159 -0
  224. amdockvs/ui/shell/settings_tools.py +178 -0
  225. amdockvs/ui/shell/splash.py +320 -0
  226. amdockvs/ui/shell/statusbar.py +183 -0
  227. amdockvs/ui/shell/tool_coordinator.py +101 -0
  228. amdockvs/ui/shell/view_coordinator.py +266 -0
  229. amdockvs/ui/tools/__init__.py +0 -0
  230. amdockvs/ui/tools/binding_sites/__init__.py +23 -0
  231. amdockvs/ui/tools/binding_sites/box.py +992 -0
  232. amdockvs/ui/tools/binding_sites/detection.py +790 -0
  233. amdockvs/ui/tools/binding_sites/flexible_residues.py +229 -0
  234. amdockvs/ui/tools/docking/__init__.py +22 -0
  235. amdockvs/ui/tools/docking/diagram_dock.py +102 -0
  236. amdockvs/ui/tools/docking/offtarget.py +448 -0
  237. amdockvs/ui/tools/docking/preparation_panel.py +711 -0
  238. amdockvs/ui/tools/docking/protocol_editor.py +661 -0
  239. amdockvs/ui/tools/docking/redocking.py +356 -0
  240. amdockvs/ui/tools/docking/redocking_charts.py +198 -0
  241. amdockvs/ui/tools/docking/results_pivot.py +432 -0
  242. amdockvs/ui/tools/docking/run_panel.py +1064 -0
  243. amdockvs/ui/tools/docking/scope_panel.py +146 -0
  244. amdockvs/ui/tools/docking/studio.py +319 -0
  245. amdockvs/ui/tools/import_workspace.py +616 -0
  246. amdockvs/ui/tools/molecules/__init__.py +19 -0
  247. amdockvs/ui/tools/molecules/build.py +809 -0
  248. amdockvs/ui/tools/molecules/diversity.py +867 -0
  249. amdockvs/ui/tools/molecules/filter.py +898 -0
  250. amdockvs/ui/tools/pymol_ribbon.py +911 -0
  251. amdockvs/ui/tools/qsar/__init__.py +0 -0
  252. amdockvs/ui/tools/qsar/activities.py +216 -0
  253. amdockvs/ui/tools/qsar/chart.py +399 -0
  254. amdockvs/ui/tools/qsar/panels.py +828 -0
  255. amdockvs/ui/tools/workflow_panel.py +795 -0
  256. amdockvs/ui/viewers/__init__.py +0 -0
  257. amdockvs/ui/viewers/molecular_viewer.py +574 -0
  258. amdockvs/ui/visualization/__init__.py +0 -0
  259. amdockvs/ui/visualization/chart_controller.py +168 -0
  260. amdockvs/workflows/__init__.py +1 -0
  261. amdockvs/workflows/orchestrator.py +513 -0
  262. amdockvs/workflows/rules.py +141 -0
  263. amdockvs/workflows/steps.py +224 -0
  264. amdockvs-0.1.0.dist-info/METADATA +205 -0
  265. amdockvs-0.1.0.dist-info/RECORD +269 -0
  266. amdockvs-0.1.0.dist-info/WHEEL +5 -0
  267. amdockvs-0.1.0.dist-info/entry_points.txt +2 -0
  268. amdockvs-0.1.0.dist-info/licenses/LICENSE +21 -0
  269. amdockvs-0.1.0.dist-info/top_level.txt +1 -0
amdockvs/__init__.py ADDED
@@ -0,0 +1,67 @@
1
+ from importlib import import_module
2
+
3
+ _LAZY_EXPORTS = {
4
+ "manifest": ("amdockvs.manifest", "manifest"),
5
+ "MoleculeScope": ("amdockvs.molecules.api", "MoleculeScope"),
6
+ "AMDOCKVS_APP_ID": ("amdockvs.runtime", "AMDOCKVS_APP_ID"),
7
+ "AMDOCKVS_APP_NAME": ("amdockvs.runtime", "AMDOCKVS_APP_NAME"),
8
+ "AMDOCKVS_DEFAULT_PROJECT_DIRS": ("amdockvs.runtime", "AMDOCKVS_DEFAULT_PROJECT_DIRS"),
9
+ "AMDOCKVS_PROJECT_RESOURCES": ("amdockvs.runtime", "AMDOCKVS_PROJECT_RESOURCES"),
10
+ "AMDOCKVS_SCOPE_ID": ("amdockvs.runtime", "AMDOCKVS_SCOPE_ID"),
11
+ "AMDockVSRuntime": ("amdockvs.runtime", "AMDockVSRuntime"),
12
+ "ComplexRef": ("amdockvs.project.sets", "ComplexRef"),
13
+ "ComplexSetRef": ("amdockvs.project.sets", "ComplexSetRef"),
14
+ "MoleculeSetRef": ("amdockvs.project.sets", "MoleculeSetRef"),
15
+ "QSARDatasetRef": ("amdockvs.project.sets", "QSARDatasetRef"),
16
+ "QSARModelRef": ("amdockvs.project.sets", "QSARModelRef"),
17
+ "DescriptorSummary": ("amdockvs.project.summaries", "DescriptorSummary"),
18
+ "DockingHitSummary": ("amdockvs.project.summaries", "DockingHitSummary"),
19
+ "DockingResultsStatsSummary": ("amdockvs.project.summaries", "DockingResultsStatsSummary"),
20
+ "DockingResultSummary": ("amdockvs.project.summaries", "DockingResultSummary"),
21
+ "JobStatus": ("amdockvs.project.summaries", "JobStatus"),
22
+ "LigandSummary": ("amdockvs.project.summaries", "LigandSummary"),
23
+ "LigandTableStatsSummary": ("amdockvs.project.summaries", "LigandTableStatsSummary"),
24
+ "ProjectSummary": ("amdockvs.project.summaries", "ProjectSummary"),
25
+ "ReceptorDockingSummary": ("amdockvs.project.summaries", "ReceptorDockingSummary"),
26
+ "ReceptorSummary": ("amdockvs.project.summaries", "ReceptorSummary"),
27
+ "ReceptorTableStatsSummary": ("amdockvs.project.summaries", "ReceptorTableStatsSummary"),
28
+ "ScreeningSummary": ("amdockvs.project.summaries", "ScreeningSummary"),
29
+ }
30
+
31
+
32
+ def __getattr__(name: str):
33
+ target = _LAZY_EXPORTS.get(name)
34
+ if target is None:
35
+ raise AttributeError(name)
36
+ module_name, attr_name = target
37
+ value = getattr(import_module(module_name), attr_name)
38
+ globals()[name] = value
39
+ return value
40
+
41
+ __all__ = [
42
+ "AMDOCKVS_APP_ID",
43
+ "AMDOCKVS_APP_NAME",
44
+ "AMDOCKVS_DEFAULT_PROJECT_DIRS",
45
+ "AMDOCKVS_PROJECT_RESOURCES",
46
+ "AMDOCKVS_SCOPE_ID",
47
+ "AMDockVSRuntime",
48
+ "ComplexRef",
49
+ "ComplexSetRef",
50
+ "DescriptorSummary",
51
+ "DockingHitSummary",
52
+ "DockingResultsStatsSummary",
53
+ "DockingResultSummary",
54
+ "JobStatus",
55
+ "LigandSummary",
56
+ "LigandTableStatsSummary",
57
+ "MoleculeScope",
58
+ "MoleculeSetRef",
59
+ "ProjectSummary",
60
+ "QSARDatasetRef",
61
+ "QSARModelRef",
62
+ "ReceptorDockingSummary",
63
+ "ReceptorSummary",
64
+ "ReceptorTableStatsSummary",
65
+ "ScreeningSummary",
66
+ "manifest",
67
+ ]
amdockvs/__main__.py ADDED
@@ -0,0 +1,5 @@
1
+ from amdockvs.app import main
2
+
3
+
4
+ if __name__ == "__main__":
5
+ raise SystemExit(main())
amdockvs/app.py ADDED
@@ -0,0 +1,181 @@
1
+ from __future__ import annotations
2
+
3
+ import argparse
4
+ import os
5
+ from pathlib import Path
6
+ from typing import TYPE_CHECKING, Sequence
7
+
8
+ if TYPE_CHECKING:
9
+ # Kept out of module import time: pulling in the runtime (MolSuite, executors) here would
10
+ # delay the splash by ~2s. It's imported inside main() only after the splash is on screen.
11
+ from amdockvs.runtime import AMDockVSRuntime
12
+
13
+
14
+ def _splash_disabled() -> bool:
15
+ return (
16
+ os.environ.get("QT_QPA_PLATFORM", "").strip().lower() == "offscreen"
17
+ or os.environ.get("AMDOCK_DISABLE_SPLASH", "").strip().lower() in {"1", "true", "yes", "on"}
18
+ )
19
+
20
+
21
+ def build_arg_parser() -> argparse.ArgumentParser:
22
+ parser = argparse.ArgumentParser(prog="amdockvs")
23
+ parser.add_argument("-pi", "--project-id", help="UUID of the project to open at start-up.")
24
+ parser.add_argument("-pp", "--project-path", help="Path of the project to open at start-up.")
25
+ return parser
26
+
27
+
28
+ FREEZE_LOG = "/tmp/amdock_stacks.log"
29
+
30
+
31
+ def install_freeze_watchdog(qt_app, *, stall_seconds: float = 10.0):
32
+ """Dump every thread's Python stack to :data:`FREEZE_LOG` while the GUI thread is stuck.
33
+
34
+ A frozen window can't be inspected from outside here (``ptrace_scope=1`` blocks py-spy
35
+ and gdb), so the app reports itself: a 500 ms timer pats a heartbeat, and a plain
36
+ daemon thread dumps the stacks whenever that heartbeat goes stale. ``kill -USR1 <pid>``
37
+ forces a dump too. Returns the timer -- Qt drops timers that nobody holds.
38
+ """
39
+ import faulthandler
40
+ import signal
41
+ import threading
42
+ import time
43
+
44
+ from PySide6.QtCore import QTimer
45
+
46
+ log = open(FREEZE_LOG, "a", buffering=1) # noqa: SIM115 - lives as long as the app
47
+ faulthandler.register(signal.SIGUSR1, file=log, all_threads=True)
48
+ beat = [time.monotonic()]
49
+ timer = QTimer(qt_app)
50
+ timer.setInterval(500)
51
+ timer.timeout.connect(lambda: beat.__setitem__(0, time.monotonic()))
52
+ timer.start()
53
+
54
+ def watch() -> None:
55
+ while True:
56
+ time.sleep(2.0)
57
+ stalled = time.monotonic() - beat[0]
58
+ if stalled < stall_seconds:
59
+ continue
60
+ print(f"\n=== GUI thread stalled {stalled:.0f}s at {time.strftime('%H:%M:%S')} ===", file=log)
61
+ faulthandler.dump_traceback(file=log, all_threads=True)
62
+ beat[0] = time.monotonic() # one dump per stall window, not per poll
63
+
64
+ threading.Thread(target=watch, name="freeze-watchdog", daemon=True).start()
65
+ return timer
66
+
67
+
68
+ def _open_startup_project(runtime: AMDockVSRuntime, *, project_id: str | None, project_path: str | None) -> None:
69
+ if project_id and project_path:
70
+ raise ValueError("Use --project-id or --project-path, not both.")
71
+ if project_id:
72
+ runtime.open_project(project_id)
73
+ return
74
+ if not project_path:
75
+ return
76
+ path = Path(project_path).expanduser().resolve()
77
+ project = runtime.molsuite.find_project(folder=path)
78
+ if project is None:
79
+ raise ValueError(f"No AMDockVS project is registered at: {path}")
80
+ runtime.open_project(project.id)
81
+
82
+
83
+ def main(argv: Sequence[str] | None = None) -> int:
84
+ import time
85
+ start = time.time()
86
+ parser = build_arg_parser()
87
+ args = parser.parse_args(list(argv) if argv is not None else None)
88
+
89
+ # Native file dialogs: our conda Qt ships the theme plugins but leaves QT_QPA_PLATFORMTHEME
90
+ # unset, so Qt loads no platform theme and falls back to its own (non-native) dialog. Route
91
+ # dialogs through the xdg-desktop-portal (D-Bus to the running GTK portal) — the gtk3 plugin
92
+ # can't be linked here (conda libpangoft2 vs harfbuzz symbol clash), but the portal needs
93
+ # none of that. Overridable, and skipped for offscreen tests. Must precede QApplication().
94
+ if not os.environ.get("QT_QPA_PLATFORMTHEME") and \
95
+ os.environ.get("QT_QPA_PLATFORM", "").strip().lower() != "offscreen":
96
+ os.environ["QT_QPA_PLATFORMTHEME"] = "xdgdesktopportal"
97
+
98
+ from PySide6.QtCore import QCoreApplication, Qt
99
+ from PySide6.QtWidgets import QApplication
100
+
101
+ qt_app = QApplication.instance()
102
+ owns_app = qt_app is None
103
+ if qt_app is None:
104
+ # PyMOL is rendered by a QOpenGLWidget. Moving a dock between this main
105
+ # window and a native top-level window otherwise destroys that widget's
106
+ # OpenGL context while PyMOL still owns resources created in it. The next
107
+ # pymol.draw() can then abort the whole process in native code. Qt must be
108
+ # told to preserve/share GUI OpenGL contexts before QApplication exists.
109
+ QCoreApplication.setAttribute(
110
+ Qt.ApplicationAttribute.AA_ShareOpenGLContexts,
111
+ True,
112
+ )
113
+ qt_app = QApplication(["amdockvs"])
114
+
115
+ watchdog = install_freeze_watchdog(qt_app) # noqa: F841 - the timer must outlive this scope
116
+
117
+ from ms_components.theme import apply_theme
118
+ from ms_components.wheel import install_shift_hscroll, uninstall_shift_hscroll
119
+
120
+ from amdockvs.ui.common.theme import saved_base_font_pt, saved_theme_name
121
+ from amdockvs.ui.resources.icons.themed import shutdown_themed_icons
122
+ apply_theme(saved_theme_name(), qt_app,
123
+ base_font_pt=saved_base_font_pt()) # ribbon recolor follows in main_window; live switch via Theme menu
124
+ install_shift_hscroll(qt_app) # Shift+wheel = horizontal, as in the browser/GTK
125
+
126
+ print("Creating splash…", time.time() - start)
127
+ splash = None
128
+ if not _splash_disabled():
129
+ from amdockvs.ui.shell.splash import create_splash
130
+ print("Creating splash 2…", time.time() - start)
131
+ splash = create_splash()
132
+
133
+ if splash is not None:
134
+ splash.status("Starting engine…")
135
+ print("Starting engine WITHOUT IMPORTS...", time.time() - start)
136
+
137
+ from amdockvs.runtime import AMDockVSRuntime
138
+ print("Starting engine...", time.time() - start)
139
+ runtime = AMDockVSRuntime()
140
+ startup_error: Exception | None = None
141
+ try:
142
+ if splash is not None:
143
+ splash.status("Opening project…")
144
+ try:
145
+ _open_startup_project(
146
+ runtime,
147
+ project_id=args.project_id,
148
+ project_path=args.project_path,
149
+ )
150
+ except Exception as exc:
151
+ startup_error = exc
152
+
153
+ if splash is not None:
154
+ splash.status("Loading interface…")
155
+ from amdockvs.ui.main_window import AMDockVSMainWindow
156
+
157
+ window = AMDockVSMainWindow(runtime=runtime)
158
+ window.showMaximized()
159
+ # Bring the window to front and let it paint NOW, so it sits maximized behind the
160
+ # (always-on-top) splash — PyCharm-style — instead of only appearing when the splash closes.
161
+ window.raise_()
162
+ window.activateWindow()
163
+ print("Loading interface...", time.time() - start)
164
+ if splash is not None:
165
+ qt_app.processEvents()
166
+ splash.raise_()
167
+ splash.finish(window)
168
+ print('splash finished', time.time() - start)
169
+ if startup_error is not None:
170
+ from PySide6.QtWidgets import QMessageBox
171
+
172
+ QMessageBox.warning(window, "Open Project", f"Could not open the startup project:\n{startup_error}")
173
+ return qt_app.exec()
174
+ finally:
175
+ try:
176
+ uninstall_shift_hscroll(qt_app)
177
+ shutdown_themed_icons(qt_app)
178
+ finally:
179
+ runtime.shutdown()
180
+ if owns_app:
181
+ qt_app.quit()
@@ -0,0 +1,22 @@
1
+ """Binding sites: manual boxes, reference ligands, import-time components and P2Rank."""
2
+
3
+ from amdockvs.binding_sites.api import BindingSiteAPI
4
+ from amdockvs.binding_sites.scopes import BindingSiteScope
5
+ from amdockvs.binding_sites.jobs import P2RankPredictionParams, p2rank_prediction_job
6
+ from amdockvs.binding_sites.p2rank import (
7
+ P2RANK_VERSION,
8
+ P2RankInstallation,
9
+ ensure_p2rank,
10
+ p2rank_status,
11
+ )
12
+
13
+ __all__ = [
14
+ "P2RANK_VERSION",
15
+ "P2RankInstallation",
16
+ "P2RankPredictionParams",
17
+ "BindingSiteAPI",
18
+ "BindingSiteScope",
19
+ "ensure_p2rank",
20
+ "p2rank_prediction_job",
21
+ "p2rank_status",
22
+ ]