firecode 1.5.1__tar.gz → 1.5.2__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 (115) hide show
  1. firecode-1.5.2/.ase/gui.py +1 -0
  2. firecode-1.5.2/.coveragerc +23 -0
  3. firecode-1.5.2/.github/workflows/test.yml +46 -0
  4. firecode-1.5.2/.gitignore +11 -0
  5. firecode-1.5.2/.pre-commit-config.yaml +43 -0
  6. {firecode-1.5.1 → firecode-1.5.2}/CHANGELOG.md +16 -10
  7. {firecode-1.5.1 → firecode-1.5.2}/PKG-INFO +23 -5
  8. firecode-1.5.2/README.md +52 -0
  9. {firecode-1.5.1 → firecode-1.5.2}/firecode/__main__.py +71 -29
  10. {firecode-1.5.1 → firecode-1.5.2}/firecode/algebra.py +15 -23
  11. {firecode-1.5.1 → firecode-1.5.2}/firecode/ase_manipulations.py +430 -503
  12. firecode-1.5.2/firecode/atropisomer_module.py +556 -0
  13. firecode-1.5.2/firecode/calculators/_ase_uma.py +48 -0
  14. {firecode-1.5.1 → firecode-1.5.2}/firecode/calculators/_orca.py +45 -49
  15. {firecode-1.5.1 → firecode-1.5.2}/firecode/calculators/_xtb.py +351 -353
  16. firecode-1.5.2/firecode/embedder.py +2988 -0
  17. firecode-1.5.2/firecode/embedder_options.py +583 -0
  18. {firecode-1.5.1 → firecode-1.5.2}/firecode/embeds.py +395 -314
  19. {firecode-1.5.1 → firecode-1.5.2}/firecode/errors.py +17 -31
  20. {firecode-1.5.1 → firecode-1.5.2}/firecode/graph_manipulations.py +40 -46
  21. {firecode-1.5.1 → firecode-1.5.2}/firecode/hypermolecule_class.py +140 -118
  22. firecode-1.5.2/firecode/mep_relaxer.py +218 -0
  23. firecode-1.5.2/firecode/modify_settings.py +198 -0
  24. firecode-1.5.2/firecode/multiembed.py +144 -0
  25. {firecode-1.5.1 → firecode-1.5.2}/firecode/numba_functions.py +64 -80
  26. firecode-1.5.2/firecode/operators.py +887 -0
  27. firecode-1.5.2/firecode/optimization_methods.py +817 -0
  28. firecode-1.5.2/firecode/parameters.py +49 -0
  29. firecode-1.5.2/firecode/pka.py +308 -0
  30. {firecode-1.5.1 → firecode-1.5.2}/firecode/profiler.py +1 -3
  31. {firecode-1.5.1 → firecode-1.5.2}/firecode/pt.py +7 -7
  32. firecode-1.5.2/firecode/quotes.py +10 -0
  33. {firecode-1.5.1 → firecode-1.5.2}/firecode/rdkit_tools.py +105 -100
  34. {firecode-1.5.1 → firecode-1.5.2}/firecode/reactive_atoms_classes.py +274 -237
  35. firecode-1.5.2/firecode/references.py +18 -0
  36. {firecode-1.5.1 → firecode-1.5.2}/firecode/settings.py +16 -16
  37. firecode-1.5.2/firecode/solvents.py +131 -0
  38. {firecode-1.5.1 → firecode-1.5.2}/firecode/standalone_optimizer.py +149 -134
  39. firecode-1.5.2/firecode/tests/conftest.py +11 -0
  40. firecode-1.5.2/firecode/tests/embed_multiembed/embed_multiembed.txt +4 -0
  41. firecode-1.5.2/firecode/tests/embed_trimolecular/HCOOH.xyz +7 -0
  42. firecode-1.5.2/firecode/tests/operator_mtd_search/dimer.xyz +12 -0
  43. firecode-1.5.2/firecode/tests/operator_mtd_search/operator_mtd_search.txt +2 -0
  44. firecode-1.5.2/firecode/tests/operator_rdkit_search/butane.xyz +16 -0
  45. firecode-1.5.2/firecode/tests/operator_rdkit_search/operator_rdkit_search.txt +2 -0
  46. firecode-1.5.2/firecode/tests/scan_linear/dimer.xyz +12 -0
  47. firecode-1.5.2/firecode/tests/scan_linear/scan_linear.txt +2 -0
  48. firecode-1.5.2/firecode/tests/test_suite.py +118 -0
  49. {firecode-1.5.1 → firecode-1.5.2}/firecode/torsion_module.py +358 -329
  50. {firecode-1.5.1 → firecode-1.5.2}/firecode/units.py +4 -4
  51. {firecode-1.5.1 → firecode-1.5.2}/firecode/utils.py +341 -194
  52. firecode-1.5.2/pixi.lock +6574 -0
  53. {firecode-1.5.1 → firecode-1.5.2}/pyproject.toml +56 -6
  54. firecode-1.5.1/.ase/gui.py +0 -1
  55. firecode-1.5.1/.gitignore +0 -153
  56. firecode-1.5.1/README.md +0 -34
  57. firecode-1.5.1/docs/conf.py +0 -65
  58. firecode-1.5.1/docs/examples.rst +0 -188
  59. firecode-1.5.1/docs/images/atropo.png +0 -0
  60. firecode-1.5.1/docs/images/complex_embed_cd.png +0 -0
  61. firecode-1.5.1/docs/images/embeds.svg +0 -449
  62. firecode-1.5.1/docs/images/intro_embed.PNG +0 -0
  63. firecode-1.5.1/docs/images/logo.png +0 -0
  64. firecode-1.5.1/docs/images/orbitals.png +0 -0
  65. firecode-1.5.1/docs/images/peptide.png +0 -0
  66. firecode-1.5.1/docs/images/peptide_chemdraw.png +0 -0
  67. firecode-1.5.1/docs/images/plot.svg +0 -1534
  68. firecode-1.5.1/docs/images/qz_firecode.gif +0 -0
  69. firecode-1.5.1/docs/images/trimolecular.png +0 -0
  70. firecode-1.5.1/docs/index.rst +0 -12
  71. firecode-1.5.1/docs/installation.rst +0 -85
  72. firecode-1.5.1/docs/introduction.rst +0 -93
  73. firecode-1.5.1/docs/license.rst +0 -551
  74. firecode-1.5.1/docs/operators_keywords.rst +0 -240
  75. firecode-1.5.1/docs/requirements.txt +0 -2
  76. firecode-1.5.1/docs/usage.rst +0 -165
  77. firecode-1.5.1/firecode/atropisomer_module.py +0 -504
  78. firecode-1.5.1/firecode/calculators/__init__.py +0 -29
  79. firecode-1.5.1/firecode/calculators/_ase_uma.py +0 -193
  80. firecode-1.5.1/firecode/calculators/dummy_ase_calc.py +0 -42
  81. firecode-1.5.1/firecode/concurrent_test.py +0 -119
  82. firecode-1.5.1/firecode/embedder.py +0 -2772
  83. firecode-1.5.1/firecode/embedder_options.py +0 -585
  84. firecode-1.5.1/firecode/mep_relaxer.py +0 -196
  85. firecode-1.5.1/firecode/modify_settings.py +0 -168
  86. firecode-1.5.1/firecode/multiembed.py +0 -150
  87. firecode-1.5.1/firecode/operators.py +0 -834
  88. firecode-1.5.1/firecode/optimization_methods.py +0 -782
  89. firecode-1.5.1/firecode/parameters.py +0 -84
  90. firecode-1.5.1/firecode/pka.py +0 -287
  91. firecode-1.5.1/firecode/quotes.py +0 -9
  92. firecode-1.5.1/firecode/references.py +0 -17
  93. firecode-1.5.1/firecode/solvents.py +0 -126
  94. firecode-1.5.1/firecode/tests.py +0 -160
  95. firecode-1.5.1/pixi.lock +0 -4205
  96. {firecode-1.5.1 → firecode-1.5.2}/.readthedocs.yaml +0 -0
  97. {firecode-1.5.1 → firecode-1.5.2}/LICENSE +0 -0
  98. {firecode-1.5.1 → firecode-1.5.2}/MANIFEST.in +0 -0
  99. {firecode-1.5.1 → firecode-1.5.2}/firecode/__init__.py +0 -0
  100. {firecode-1.5.1 → firecode-1.5.2}/firecode/quotes.json +0 -0
  101. {firecode-1.5.1 → firecode-1.5.2}/firecode/tests/C2H4.xyz +0 -0
  102. {firecode-1.5.1/firecode/tests/chelotropic → firecode-1.5.2/firecode/tests/embed_chelotropic}/C2H4.xyz +0 -0
  103. {firecode-1.5.1/firecode/tests/chelotropic → firecode-1.5.2/firecode/tests/embed_chelotropic}/HCOOOH.xyz +0 -0
  104. /firecode-1.5.1/firecode/tests/chelotropic/chelotropic.txt → /firecode-1.5.2/firecode/tests/embed_chelotropic/embed_chelotropic.txt +0 -0
  105. {firecode-1.5.1/firecode/tests/cyclical → firecode-1.5.2/firecode/tests/embed_cyclical}/C2H4.xyz +0 -0
  106. /firecode-1.5.1/firecode/tests/cyclical/cyclical.txt → /firecode-1.5.2/firecode/tests/embed_cyclical/embed_cyclical.txt +0 -0
  107. {firecode-1.5.1/firecode/tests/string → firecode-1.5.2/firecode/tests/embed_multiembed}/HCOOH.xyz +0 -0
  108. {firecode-1.5.1/firecode/tests/string → firecode-1.5.2/firecode/tests/embed_string}/CH3Cl.xyz +0 -0
  109. {firecode-1.5.1/firecode/tests/trimolecular → firecode-1.5.2/firecode/tests/embed_string}/HCOOH.xyz +0 -0
  110. /firecode-1.5.1/firecode/tests/string/string.txt → /firecode-1.5.2/firecode/tests/embed_string/embed_string.txt +0 -0
  111. {firecode-1.5.1/firecode/tests/trimolecular → firecode-1.5.2/firecode/tests/embed_trimolecular}/CH3Cl.xyz +0 -0
  112. /firecode-1.5.1/firecode/tests/trimolecular/trimolecular.txt → /firecode-1.5.2/firecode/tests/embed_trimolecular/embed_trimolecular.txt +0 -0
  113. {firecode-1.5.1/firecode/tests/dihedral → firecode-1.5.2/firecode/tests/scan_dihedral}/C2F2H4.xyz +0 -0
  114. /firecode-1.5.1/firecode/tests/dihedral/dihedral.txt → /firecode-1.5.2/firecode/tests/scan_dihedral/scan_dihedral.txt +0 -0
  115. {firecode-1.5.1 → firecode-1.5.2}/icon.ico +0 -0
@@ -0,0 +1 @@
1
+ gui_default_settings["show_bonds"] = True
@@ -0,0 +1,23 @@
1
+ [run]
2
+ source = prism_pruner
3
+ omit = prism_pruner/__main__.py
4
+
5
+ [report]
6
+ exclude_lines =
7
+ # Have to re-enable the standard pragma
8
+ pragma: no cover
9
+
10
+ # Don't complain about missing debug-only code:
11
+ def __repr__
12
+ if self\.debug
13
+
14
+ # Don't complain if tests don't hit defensive assertion code:
15
+ raise AssertionError
16
+ raise NotImplementedError
17
+
18
+ # Don't complain if non-runnable code isn't run:
19
+ if 0:
20
+ if __name__ == .__main__.:
21
+
22
+ # Don't complain if an ellipsis isn't run (typically in an abstractmethod):
23
+ ^\s*\.\.\.
@@ -0,0 +1,46 @@
1
+ name: Test
2
+
3
+ on:
4
+ pull_request: {}
5
+ push:
6
+ branches:
7
+ - main
8
+ - feature/**
9
+
10
+ jobs:
11
+ test:
12
+ strategy:
13
+ matrix:
14
+ python-version: ['3.12']
15
+ os: [ubuntu-latest]
16
+
17
+ name: Python ${{ matrix.os }} ${{ matrix.python-version }}
18
+ runs-on: ${{ matrix.os }}
19
+
20
+ steps:
21
+ - uses: actions/checkout@v5
22
+
23
+ # - uses: actions/setup-python@v6
24
+ # with:
25
+ # python-version: ${{ matrix.python-version }}
26
+
27
+ - uses: prefix-dev/setup-pixi@v0.9.4
28
+ with:
29
+ pixi-version: v0.63.2
30
+ cache: true
31
+ environments: dev
32
+ # locked: false
33
+ locked: true
34
+
35
+ - run: pixi install -e dev --locked
36
+ # - run: pixi run fmt
37
+ # - run: pixi run lint
38
+ # - run: pixi run types
39
+ - run: pixi run -e dev test_cov
40
+
41
+ - name: Upload Coverage to Codecov
42
+ uses: codecov/codecov-action@v4
43
+ with:
44
+ files: ./coverage.xml
45
+ env:
46
+ CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
@@ -0,0 +1,11 @@
1
+ __pycache__/
2
+ build/
3
+ site/
4
+ .vscode/
5
+ .mypy_cache/
6
+ firecode.egg-info/
7
+ docs/
8
+
9
+ firecode/calculators/uma-s-1p1.pt
10
+ coverage.xml
11
+ .coverage
@@ -0,0 +1,43 @@
1
+ exclude: '.pixi/'
2
+ repos:
3
+ - repo: https://github.com/pre-commit/pre-commit-hooks
4
+ rev: v5.0.0 # this is optional, use `pre-commit autoupdate` to get the latest rev!
5
+ hooks:
6
+ - id: check-yaml
7
+ - id: check-toml
8
+ - id: end-of-file-fixer
9
+ - id: trailing-whitespace
10
+
11
+ - repo: local
12
+ hooks:
13
+ - id: ruff
14
+ name: ruff-format
15
+ stages: [pre-commit, pre-push]
16
+ language: system
17
+ entry: pixi run fmt
18
+ types: [python]
19
+ pass_filenames: false
20
+
21
+ - id: ruff
22
+ name: ruff-check
23
+ stages: [pre-commit, pre-push]
24
+ language: system
25
+ entry: pixi run lint
26
+ types: [python]
27
+ pass_filenames: false
28
+
29
+ # - id: Mypy
30
+ # name: mypy
31
+ # stages: [pre-commit, pre-push]
32
+ # language: system
33
+ # entry: pixi run types
34
+ # types: [python]
35
+ # pass_filenames: false
36
+
37
+ - id: pytest
38
+ name: pytest
39
+ stages: [pre-commit, pre-push]
40
+ language: system
41
+ entry: pixi run test
42
+ types: [python]
43
+ pass_filenames: false
@@ -4,14 +4,20 @@
4
4
  <!-- - ... mep_relax> BETA
5
5
  - ... IMAGES kw, also implement it for neb>-->
6
6
  <!-- FINALSPLEVEL keyword? -->
7
+ <!-- add documentation: SCRAMBLECHECK kw, fsm>, neb>, rdkit_search>, standalone optimizer-->
7
8
 
8
- ## FIRECODE 1.5.0 🔥 (WIP)
9
- - Implemented an interface to [ML-FSM](https://github.com/thegomeslab/ML-FSM/tree/main).
10
- - Removed openbabel dependency.
9
+ ## FIRECODE 1.5.2 🔥 (WIP)
10
+ - Broken up installation into dedicated modules: minimal (`firecode`) and MLIPs (`firecode[aimnet2]`, `firecode[uma]`, `firecode[full]`)
11
+ - Updated tests infrastructure and added CodeCov CI.
12
+
13
+ ## FIRECODE 1.5.1 🔥 (February 17 2026)
11
14
  - Imports bugfixes.
12
15
  - Restructured setup to use [Pixi](https://pixi.prefix.dev/latest/).
13
- - Removed SMILES to 3D conversion.
14
- <!-- add documentation: SCRAMBLECHECK kw, fsm>, neb>, rdkit_search>-->
16
+ - Removed openbabel dependency.
17
+ - Removed SMILES to 3D conversion with Openbabel.
18
+ - Implemented an interface to [ML-FSM](https://github.com/thegomeslab/ML-FSM/tree/main) with the "fsm>" operator.
19
+ - Added the "rdkit_search>" operator (ETKDGv3).
20
+ - Updated the AIMNET2 interface, which now relies exclusively on the "aimnet[ase]" library (see [repository](https://github.com/isayevlab/aimnetcentral)).
15
21
 
16
22
  ## FIRECODE 1.4.0 🔥 (January 25 2026) - Big cleanup and reorganization!
17
23
  - Similarity pruning is now done via the standalone [PRISM](https://github.com/ntampellini/prism_pruner) library.
@@ -24,7 +30,7 @@
24
30
  ## FIRECODE 1.3.0 🔥 (December 15 2025)
25
31
  - Added [UMA](https://fair-chem.github.io/core/uma.html) as a calculator with Meta MLIPs, via ASE and the fairchem-core library. The model path needs to be specified in the settings.py file.
26
32
  - Polished the neb> and scan> operators to work in sequence (neb> scan> start.xyz i1 i2).
27
- - Added standalone structure optimizer, called with "python -m firecode -o mol.xyz".
33
+ - Added standalone structure optimizer, called with "firecode -o mol.xyz".
28
34
  - Corrected behavior of fixed constraints with no specified distance, which before would relax. Now they are kept fixed at the initial distance.
29
35
  - Moved tests to their own folders.
30
36
  <!-- - Added free energy calculation via ASE vibrational analysis. -->
@@ -67,7 +73,7 @@
67
73
  - Informative suggestions: keywords that are not understood can generate suggestion of known keywords to use instead.
68
74
  - Removed rmsd library dependency for local numba numpy implementation.
69
75
  - Increased similarity_refining thresholds for the maximum number of structures to be compared: 1E5 for RMSD and MOI, 1E4 for rotationally corrected RMSD. Added printouts in log if we skip a pruning stage because the ensemble is too large.
70
- - Fixed a bug in _get_rotation_mask that would rotate the wrong part of the molecule (spotted because prune_by_rmsd_rot_corr would not reject some molecules that it should have)
76
+ - Fixed a bug in _get_rotation_mask that would rotate the wrong part of the molecule (spotted because prune_by_rmsd_rot_corr would not reject some molecules that it should have)
71
77
  - Added a debug messages printout function for the Pruner class, which by default is set to embedder.debuglog
72
78
  - Added support for AIMNET2 Pytorch models, including GPU support, with the package aimnet2-firecode. If a solvent is specified, the ALPB ΔGsolv (XTB) is added to the vacuum SP EE.
73
79
  - Removed support for the THREADS keyword and command line setting, as the number of workers in every multithreaded parallelism is now automated.
@@ -97,10 +103,10 @@
97
103
  - Various small bugfixes/graphic restyling
98
104
  - Stuctures are optimized at embedder.options.theory_level before running the mtd_search> operator, and a FatalError is raised if they scramble during this process. This increases the robustness of the workflow by avoiding changes in the molecular graph if the input structure is bad.
99
105
  - Added a warning printout system to the Embedder class, via logging and appending strings to the embedder.warnings list.
100
- - Added a saturation and compenetration check for input molecules, that warns about potential bad geometries.
106
+ - Added a saturation and compenetration check for input molecules, that warns about potential bad geometries.
101
107
 
102
108
  ## 0.4.10 (February 24, 2024)
103
- - Reduced/summarized printouts for loose to tight optimization steps.
109
+ - Reduced/summarized printouts for loose to tight optimization steps.
104
110
  <!-- - Removed call to compenetration_refining() on input ensemble: it is usually already pruned for compenetration for embed runs, and other ensembles (for example from "refine> mtd>" runs coming from CREST) benefit from relaxing eventual clashes that are present. -->
105
111
 
106
112
  ## 0.4.9 (February 22, 2024)
@@ -338,4 +344,4 @@
338
344
  - If pivots decrease during a bend, an exception is raised. Future versions might have a different behavior in this scenario.
339
345
 
340
346
  ## 0.0.1 (August 10, 2021)
341
- - First release
347
+ - First release
@@ -1,11 +1,11 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: firecode
3
- Version: 1.5.1
3
+ Version: 1.5.2
4
4
  Summary: FIRECODE: Filtering Refiner and Embedder for Conformationally Dense Ensembles
5
5
  Author-email: Nicolò Tampellini <nicolo.tampellini@yale.edu>
6
6
  License-Expression: LGPL-3.0-or-later
7
7
  License-File: LICENSE
8
- Requires-Python: <3.13,>=3.10
8
+ Requires-Python: <3.13,>=3.12
9
9
  Requires-Dist: ase
10
10
  Requires-Dist: inquirerpy
11
11
  Requires-Dist: matplotlib
@@ -33,9 +33,11 @@ Description-Content-Type: text/markdown
33
33
 
34
34
  [![License: GNU LGPL v3](https://img.shields.io/github/license/ntampellini/firecode)](https://opensource.org/licenses/LGPL-3.0)
35
35
  ![Python Version](https://img.shields.io/badge/Python-3.12-blue)
36
+ [![Powered by: Pixi](https://img.shields.io/badge/Powered_by-Pixi-facc15)](https://pixi.sh)
36
37
  ![Size](https://img.shields.io/github/languages/code-size/ntampellini/firecode)
37
38
  ![Lines](https://sloc.xyz/github/ntampellini/firecode/)
38
39
  [![CodeFactor Grade](https://img.shields.io/codefactor/grade/github/ntampellini/firecode)](https://www.codefactor.io/repository/github/ntampellini/firecode)
40
+ [![codecov](https://codecov.io/gh/ntampellini/FIRECODE/graph/badge.svg?token=D9TM6S33D8)](https://codecov.io/gh/ntampellini/FIRECODE)
39
41
 
40
42
  [![PyPI](https://img.shields.io/pypi/v/firecode)](https://pypi.org/project/firecode/)
41
43
  [![Wheel](https://img.shields.io/pypi/wheel/firecode)](https://pypi.org/project/firecode/)
@@ -53,10 +55,26 @@ Description-Content-Type: text/markdown
53
55
 
54
56
  </p>
55
57
 
56
- *FIRECODE is the expanded successor of [TSCoDe](https://github.com/ntampellini/TSCoDe).*
58
+ FIRECODE is a computational chemistry workflow driver for the generation, optimization and refinement of conformational ensembles, also implementing some transition state ultilities.
57
59
 
58
- FIRECODE is a computational chemistry toolbox for the generation, optimization and refinement of conformational ensembles. It features many flexible and highly customizable workflow utilities including conformer generation (via [CREST](https://github.com/crest-lab/crest) or FIRECODE), constrained ensemble optimization through popular calculators like [XTB](https://github.com/grimme-lab/xtb), [ORCA](https://www.orcasoftware.de/tutorials_orca/), [GAUSSIAN](https://gaussian.com/) and Pytorch Neural Network models via [ASE](https://github.com/rosswhitfield/ase) ([AIMNET2](https://github.com/isayevlab/AIMNet2)). It implements a series of conformational pruning routines based on inertia tensors, RMSD, symmetry-corrected RMSD, and more. It can also assemble non-covalent adducts from conformational ensembles (embedding) for fast and automated generation and evaluation of ground and transtition state-like structures. CPU and GPU multithreading is implemented throughout the codebase and linear algebra-intensive modules are compiled at runtime via [Numba](https://github.com/numba/numba).
60
+ It implements flexible and customizable workflows for conformer generation (via [CREST](https://github.com/crest-lab/crest), [RDKit](https://github.com/rdkit/rdkit)), double-ended TS search ([NEB](https://ase-lib.org/ase/neb.html) via [ASE](https://github.com/rosswhitfield/ase), [ML-FSM](https://github.com/thegomeslab/ML-FSM)), and (constrained) ensemble optimization through popular calculators like [XTB](https://github.com/grimme-lab/xtb), [TBLITE](https://github.com/tblite/tblite), [ORCA](https://www.orcasoftware.de/tutorials_orca/), and Pytorch Neural Network models ([AIMNET2](https://github.com/isayevlab/AIMNet2), [UMA](https://huggingface.co/facebook/UMA)) via [ASE](https://github.com/rosswhitfield/ase).
59
61
 
62
+ Conformational pruning is performed with the now standalone [PRISM Pruner](https://github.com/ntampellini/prism_pruner).
63
+
64
+ As a legacy feature from [TSCoDe](https://github.com/ntampellini/TSCoDe), FIRECODE can also assemble non-covalent adducts from conformational ensembles (embedding) programmatically.
65
+
66
+ ## Installation
67
+
68
+ The package is distributed via `pip`, and the use of [`uv`](https://docs.astral.sh/uv/) is highly recommended. The default installation is minimalistic, and torch/GPU support requires dedicated installs:
69
+
70
+ ```python
71
+ uv pip install firecode # XTB, TBLITE, ORCA
72
+ uv pip install firecode[aimnet2] # + AIMNET2
73
+ uv pip install firecode[uma] # + UMA/OMOL
74
+ uv pip install firecode[full] # + AIMNET2, UMA/OMOL
75
+ ```
76
+
77
+ More installation details in the documentation.
60
78
 
61
79
  ## Documentation
62
- Documentation on how to install and use the program can be found on [readthedocs](https://firecode.readthedocs.io/en/latest/index.html).
80
+ Additional documentation on how to install and use the program can be found on [readthedocs](https://firecode.readthedocs.io/en/latest/index.html).
@@ -0,0 +1,52 @@
1
+
2
+ # FIRECODE - Filtering Refiner and Embedder for Conformationally Dense Ensembles
3
+
4
+ <div align="center">
5
+
6
+ [![License: GNU LGPL v3](https://img.shields.io/github/license/ntampellini/firecode)](https://opensource.org/licenses/LGPL-3.0)
7
+ ![Python Version](https://img.shields.io/badge/Python-3.12-blue)
8
+ [![Powered by: Pixi](https://img.shields.io/badge/Powered_by-Pixi-facc15)](https://pixi.sh)
9
+ ![Size](https://img.shields.io/github/languages/code-size/ntampellini/firecode)
10
+ ![Lines](https://sloc.xyz/github/ntampellini/firecode/)
11
+ [![CodeFactor Grade](https://img.shields.io/codefactor/grade/github/ntampellini/firecode)](https://www.codefactor.io/repository/github/ntampellini/firecode)
12
+ [![codecov](https://codecov.io/gh/ntampellini/FIRECODE/graph/badge.svg?token=D9TM6S33D8)](https://codecov.io/gh/ntampellini/FIRECODE)
13
+
14
+ [![PyPI](https://img.shields.io/pypi/v/firecode)](https://pypi.org/project/firecode/)
15
+ [![Wheel](https://img.shields.io/pypi/wheel/firecode)](https://pypi.org/project/firecode/)
16
+ [![Documentation Status](https://readthedocs.org/projects/firecode/badge/?version=latest)](https://firecode.readthedocs.io/en/latest/?badge=latest)
17
+ ![PyPI - Downloads](https://img.shields.io/pypi/dm/firecode)
18
+ [![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/charliermarsh/ruff/main/assets/badge/v1.json)](https://github.com/charliermarsh/ruff)
19
+
20
+ ![Twitter](https://img.shields.io/twitter/url?url=https%3A%2F%2Ftwitter.com%2Fntampellini_&label=%40ntampellini_&link=https%3A%2F%2Ftwitter.com%2Fntampellini_)
21
+
22
+ </div>
23
+
24
+ <p align="center">
25
+
26
+ <img src="docs/images/logo.png" alt="FIRECODE logo" class="center" width="500"/>
27
+
28
+ </p>
29
+
30
+ FIRECODE is a computational chemistry workflow driver for the generation, optimization and refinement of conformational ensembles, also implementing some transition state ultilities.
31
+
32
+ It implements flexible and customizable workflows for conformer generation (via [CREST](https://github.com/crest-lab/crest), [RDKit](https://github.com/rdkit/rdkit)), double-ended TS search ([NEB](https://ase-lib.org/ase/neb.html) via [ASE](https://github.com/rosswhitfield/ase), [ML-FSM](https://github.com/thegomeslab/ML-FSM)), and (constrained) ensemble optimization through popular calculators like [XTB](https://github.com/grimme-lab/xtb), [TBLITE](https://github.com/tblite/tblite), [ORCA](https://www.orcasoftware.de/tutorials_orca/), and Pytorch Neural Network models ([AIMNET2](https://github.com/isayevlab/AIMNet2), [UMA](https://huggingface.co/facebook/UMA)) via [ASE](https://github.com/rosswhitfield/ase).
33
+
34
+ Conformational pruning is performed with the now standalone [PRISM Pruner](https://github.com/ntampellini/prism_pruner).
35
+
36
+ As a legacy feature from [TSCoDe](https://github.com/ntampellini/TSCoDe), FIRECODE can also assemble non-covalent adducts from conformational ensembles (embedding) programmatically.
37
+
38
+ ## Installation
39
+
40
+ The package is distributed via `pip`, and the use of [`uv`](https://docs.astral.sh/uv/) is highly recommended. The default installation is minimalistic, and torch/GPU support requires dedicated installs:
41
+
42
+ ```python
43
+ uv pip install firecode # XTB, TBLITE, ORCA
44
+ uv pip install firecode[aimnet2] # + AIMNET2
45
+ uv pip install firecode[uma] # + UMA/OMOL
46
+ uv pip install firecode[full] # + AIMNET2, UMA/OMOL
47
+ ```
48
+
49
+ More installation details in the documentation.
50
+
51
+ ## Documentation
52
+ Additional documentation on how to install and use the program can be found on [readthedocs](https://firecode.readthedocs.io/en/latest/index.html).
@@ -1,7 +1,5 @@
1
1
  # coding=utf-8
2
- '''
3
-
4
- FIRECODE: Filtering Refiner and Embedder for Conformationally Dense Ensembles
2
+ """FIRECODE: Filtering Refiner and Embedder for Conformationally Dense Ensembles
5
3
  Copyright (C) 2021-2026 Nicolò Tampellini
6
4
 
7
5
  This program is free software: you can redistribute it and/or modify
@@ -18,23 +16,23 @@ https://github.com/ntampellini/firecode
18
16
 
19
17
  Nicolo' Tampellini - nicolo.tampellini@yale.edu
20
18
 
21
- '''
19
+ """
20
+
22
21
  import argparse
23
22
  import os
24
23
  import sys
24
+
25
25
  from rich.traceback import install
26
+
26
27
  install(show_locals=True)
27
28
 
28
- __version__ = '1.5.0'
29
29
 
30
30
  def main():
31
-
32
-
33
- usage = '''\n\n 🔥 python -m firecode [-h] [-s] [-t] input.txt [-n NAME] [-p]
31
+ usage = """\n\n 🔥 python -m firecode [-h] [-s] [-t] input.txt [-n NAME] [-p]
34
32
  🔥 python -m firecode -cl "refine> mtd> mol.xyz"
35
33
  🔥 python -m firecode -c
36
34
  🔥 python -m firecode -o mol.xyz
37
-
35
+
38
36
  positional arguments:
39
37
  inpufile.txt Input filename, can be any text file.
40
38
 
@@ -48,46 +46,88 @@ def main():
48
46
  -p, --profile Profile the run through cProfiler.
49
47
  -o, --optimize FILE Run a standalone structure optimization tool.
50
48
 
51
- '''
49
+ """
52
50
 
53
51
  parser = argparse.ArgumentParser(usage=usage)
54
- parser.add_argument("-s", "--setup", help="Guided setup of the calculation settings.", action="store_true")
55
- parser.add_argument("-t", "--test", help="Perform some tests to check the software setup.", action="store_true")
56
- parser.add_argument("-cl", "--command_line", help="Read instructions from the command line instead of from an input file.", action="store")
57
- parser.add_argument("inputfile", help="Input filename, can be any text file.", action='store', nargs='?', default=None)
58
- parser.add_argument("-n", "--name", help="Specify a custom name for the run.", action='store', required=False)
59
- parser.add_argument("-c", "--cite", help="Print the appropriate document links for citation purposes.", action='store_true', required=False)
60
- parser.add_argument("-p", "--profile", help="Profile the run through cProfiler.", action='store_true', required=False)
61
- parser.add_argument("-o", "--optimize", help="Run a standalone structure optimization tool.", action='store', required=False, nargs='+')
52
+ parser.add_argument(
53
+ "-s", "--setup", help="Guided setup of the calculation settings.", action="store_true"
54
+ )
55
+ parser.add_argument(
56
+ "-t", "--test", help="Perform some tests to check the software setup.", action="store_true"
57
+ )
58
+ parser.add_argument(
59
+ "-cl",
60
+ "--command_line",
61
+ help="Read instructions from the command line instead of from an input file.",
62
+ action="store",
63
+ )
64
+ parser.add_argument(
65
+ "inputfile",
66
+ help="Input filename, can be any text file.",
67
+ action="store",
68
+ nargs="?",
69
+ default=None,
70
+ )
71
+ parser.add_argument(
72
+ "-n", "--name", help="Specify a custom name for the run.", action="store", required=False
73
+ )
74
+ parser.add_argument(
75
+ "-c",
76
+ "--cite",
77
+ help="Print the appropriate document links for citation purposes.",
78
+ action="store_true",
79
+ required=False,
80
+ )
81
+ parser.add_argument(
82
+ "-p",
83
+ "--profile",
84
+ help="Profile the run through cProfiler.",
85
+ action="store_true",
86
+ required=False,
87
+ )
88
+ parser.add_argument(
89
+ "-o",
90
+ "--optimize",
91
+ help="Run a standalone structure optimization tool.",
92
+ action="store",
93
+ required=False,
94
+ nargs="+",
95
+ )
62
96
 
63
97
  args = parser.parse_args()
64
98
 
65
- if (not (args.test or args.setup or args.command_line or args.optimize)) and args.inputfile is None:
99
+ if (
100
+ not (args.test or args.setup or args.command_line or args.optimize)
101
+ ) and args.inputfile is None:
66
102
  parser.error("One of the following arguments are required: inputfile, -t, -s, -o.\n")
67
103
 
68
104
  if args.setup:
69
105
  from firecode.modify_settings import run_setup
106
+
70
107
  run_setup()
71
- sys.exit()
108
+ sys.exit(0)
72
109
 
73
110
  if args.cite:
74
- print('No citation link is available for FIRECODE yet. You can link to the code on https://www.github.com/ntampellini/firecode')
75
- sys.exit()
111
+ print(
112
+ "No citation link is available for FIRECODE yet. You can link to the code on https://www.github.com/ntampellini/firecode"
113
+ )
114
+ sys.exit(0)
76
115
 
77
116
  if args.test:
78
117
  from firecode.tests import run_tests
118
+
79
119
  run_tests()
80
- sys.exit()
120
+ sys.exit(0)
81
121
 
82
122
  if args.optimize:
83
123
  from firecode.standalone_optimizer import main
124
+
84
125
  main(args.optimize)
85
- sys.exit()
126
+ sys.exit(0)
86
127
 
87
128
  if args.command_line:
88
-
89
- filename = 'input_firecode.txt'
90
- with open(filename, 'w') as f:
129
+ filename = "input_firecode.txt"
130
+ with open(filename, "w") as f:
91
131
  f.write(args.command_line)
92
132
 
93
133
  args.inputfile = filename
@@ -98,8 +138,9 @@ def main():
98
138
 
99
139
  if args.profile:
100
140
  from firecode.profiler import profiled_wrapper
141
+
101
142
  profiled_wrapper(filename, args.name)
102
- sys.exit()
143
+ sys.exit(0)
103
144
 
104
145
  embedder = Embedder(filename, stamp=args.name)
105
146
  # initialize embedder from input file
@@ -107,5 +148,6 @@ def main():
107
148
  embedder.run()
108
149
  # run the program
109
150
 
151
+
110
152
  if __name__ == "__main__":
111
- main()
153
+ main()
@@ -1,6 +1,4 @@
1
- '''
2
-
3
- FIRECODE: Filtering Refiner and Embedder for Conformationally Dense Ensembles
1
+ """FIRECODE: Filtering Refiner and Embedder for Conformationally Dense Ensembles
4
2
  Copyright (C) 2021-2026 Nicolò Tampellini
5
3
 
6
4
  This program is free software: you can redistribute it and/or modify
@@ -13,7 +11,8 @@ but WITHOUT ANY WARRANTY; without even the implied warranty of
13
11
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
12
  GNU General Public License for more details.
15
13
 
16
- '''
14
+ """
15
+
17
16
  import numpy as np
18
17
  from prism_pruner.algebra import normalize
19
18
 
@@ -21,10 +20,8 @@ norm_of = np.linalg.norm
21
20
 
22
21
 
23
22
  def point_angle(p1, p2, p3):
24
- '''
25
- Returns the planar angle between three points in space, in degrees.
26
- '''
27
- return np.arccos(np.clip(normalize(p1 - p2) @ normalize(p3 - p2), -1.0, 1.0))*180/np.pi
23
+ """Returns the planar angle between three points in space, in degrees."""
24
+ return np.arccos(np.clip(normalize(p1 - p2) @ normalize(p3 - p2), -1.0, 1.0)) * 180 / np.pi
28
25
 
29
26
 
30
27
  def kronecker_delta(i, j) -> int:
@@ -34,20 +31,18 @@ def kronecker_delta(i, j) -> int:
34
31
 
35
32
 
36
33
  def align_vec_pair(ref, tgt):
37
- '''
38
- ref, tgt: iterables of two 3D vectors each
39
-
34
+ """ref, tgt: iterables of two 3D vectors each
35
+
40
36
  return: rotation matrix that when applied to tgt,
41
37
  optimally aligns it to ref
42
- '''
43
-
44
- B = np.zeros((3,3))
38
+ """
39
+ B = np.zeros((3, 3))
45
40
  for i in range(3):
46
41
  for k in range(3):
47
42
  tot = 0
48
43
  for j in range(2):
49
- tot += ref[j][i]*tgt[j][k]
50
- B[i,k] = tot
44
+ tot += ref[j][i] * tgt[j][k]
45
+ B[i, k] = tot
51
46
 
52
47
  u, s, vh = np.linalg.svd(B)
53
48
 
@@ -62,7 +57,7 @@ def align_vec_pair(ref, tgt):
62
57
  def cart_prod_idx(sizes: np.ndarray):
63
58
  """Generates ids tuples for a cartesian product"""
64
59
  assert len(sizes) >= 2
65
- tuples_count = np.prod(sizes)
60
+ tuples_count = np.prod(sizes)
66
61
  tuples = np.zeros((tuples_count, len(sizes)), dtype=np.int32)
67
62
  tuple_idx = 0
68
63
  # stores the current combination
@@ -91,9 +86,7 @@ def cart_prod_idx(sizes: np.ndarray):
91
86
 
92
87
 
93
88
  def vector_cartesian_product(x, y):
94
- '''
95
- Cartesian product, but with vectors instead of indices
96
- '''
89
+ """Cartesian product, but with vectors instead of indices"""
97
90
  indices = cart_prod_idx(np.asarray((x.shape[0], y.shape[0]), dtype=np.int32))
98
91
  dim = x.shape[-1] if len(x.shape) > 1 else 1
99
92
  new_arr = np.zeros((*indices.shape, dim), dtype=x.dtype)
@@ -104,11 +97,10 @@ def vector_cartesian_product(x, y):
104
97
 
105
98
 
106
99
  def transform_coords(coords, rot, pos):
107
- '''
108
- Returns the rotated and tranlated
100
+ """Returns the rotated and tranlated
109
101
  coordinates. Slightly faster than
110
102
  Numpy, uses memory-contiguous arrays.
111
- '''
103
+ """
112
104
  t = np.transpose(coords)
113
105
  m = rot @ t
114
106
  f = np.transpose(m)