-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* update rc_split * format package * prepare release * Add subpackage SynChem * fix bug version * update readme * fix typos * build doc * fix format * fix format
- Loading branch information
1 parent
69ebdba
commit 155f869
Showing
25 changed files
with
1,838 additions
and
15 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
name: Build documentation for GitHub Pages | ||
|
||
on: | ||
push: | ||
branches: | ||
- main | ||
|
||
workflow_dispatch: # Enable manual action trigger | ||
|
||
env: | ||
PYTHONPATH: . | ||
|
||
jobs: | ||
build_documentation_for_github_pages: | ||
runs-on: ubuntu-latest | ||
steps: | ||
- uses: actions/checkout@v3 | ||
with: | ||
fetch-depth: 0 | ||
- uses: actions/setup-python@v4 | ||
with: | ||
python-version: '3.11' | ||
cache: 'pip' # caching pip dependencies | ||
- run: pip install -r requirements.txt | ||
- run: pip install sphinx sphinx-rtd-theme | ||
- run: python3 -m sphinx ./doc docs | ||
- name: publish doc | ||
shell: bash | ||
run: | | ||
git config user.name "GitHub Action" | ||
git config user.email "[email protected]" | ||
git add -f docs/ | ||
git commit -m "Doc build" | ||
git push origin `git subtree split --prefix docs/ main`:gh-pages --force |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
# Minimal makefile for Sphinx documentation | ||
# | ||
|
||
# You can set these variables from the command line, and also | ||
# from the environment for the first two. | ||
SPHINXOPTS ?= | ||
SPHINXBUILD ?= sphinx-build | ||
SOURCEDIR = source | ||
BUILDDIR = build | ||
|
||
# Put it first so that "make" without argument is like "make help". | ||
help: | ||
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) | ||
|
||
.PHONY: help Makefile | ||
|
||
# Catch-all target: route all unknown targets to Sphinx using the new | ||
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). | ||
%: Makefile | ||
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,9 +2,9 @@ | |
|
||
**Utils for Synthesis Planning** | ||
|
||
SynUtils is a collection of tools designed to support the planning and execution of chemical synthesis. This repository provides computational resources and utilities aimed at enhancing the efficiency and accuracy of synthesis planning through the use of advanced algorithms and AI-driven models. | ||
SynUtils is a collection of tools designed to support the planning and execution of chemical synthesis. | ||
|
||
![SynUtils](Docs/Figure/synutils.png) | ||
![SynUtils](https://raw.githubusercontent.com/TieuLongPhan/SynUtils/main/Docs/Figure/synutils.png) | ||
|
||
Our tools are tailored to assist researchers and chemists in navigating complex chemical reactions and synthesis pathways, leveraging the power of modern computational chemistry. Whether you're designing novel compounds or optimizing existing processes, SynUtils aims to provide the critical tools you need. | ||
|
||
|
@@ -29,18 +29,21 @@ For more details on each utility within the repository, please refer to the docu | |
conda activate synutils-env | ||
``` | ||
|
||
3. **Cloning and Installing SynUtils:** | ||
Clone the SynUtils repository from GitHub and install it: | ||
3. **Install from PyPi:** | ||
The easiest way to use SynTemp is by installing the PyPI package | ||
[synutility](https://pypi.org/project/synutility/). | ||
|
||
```bash | ||
git clone https://github.com/TieuLongPhan/SynUtils.git | ||
cd SynUtils | ||
pip install -r requirements.txt | ||
pip install black flake8 pytest # black for formating, flake8 for checking format, pytest for testing | ||
``` | ||
pip install synutility | ||
``` | ||
Optional if you want to install full version | ||
``` | ||
pip install synutility[all] | ||
``` | ||
|
||
## For contributors | ||
|
||
## Setting Up Your Development Environment | ||
We're welcoming new contributors to build this project better. Please not hesitate to inquire me via [email][[email protected]]. | ||
|
||
Before you start, ensure your local development environment is set up correctly. Pull the latest version of the `main` branch to start with the most recent stable code. | ||
|
||
|
@@ -97,4 +100,19 @@ git pull | |
3. **Create a Pull Request**: | ||
Open a pull request from your feature branch to the `stagging` branch. Ensure the pull request description clearly describes the changes and any additional context necessary for review. | ||
|
||
## Important Notes | ||
## Contributing | ||
- [Tieu-Long Phan](https://tieulongphan.github.io/) | ||
- [Phuoc-Chung Nguyen Van](https://github.com/phuocchung123) | ||
|
||
## Deployment timeline | ||
|
||
We plan to update new version quarterly. | ||
|
||
|
||
## License | ||
|
||
This project is licensed under MIT License - see the [License](LICENSE) file for details. | ||
|
||
## Acknowledgments | ||
|
||
This project has received funding from the European Unions Horizon Europe Doctoral Network programme under the Marie-Skłodowska-Curie grant agreement No 101072930 ([TACsy](https://tacsy.eu/) -- Training Alliance for Computational) |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
import unittest | ||
from synutility.SynChem.Reaction.balance_check import BalanceReactionCheck | ||
|
||
|
||
class TestBalanceReactionCheck(unittest.TestCase): | ||
|
||
def test_parse_input_string(self): | ||
input_data = "C>>O" | ||
expected_output = [{"reactions": "C>>O"}] | ||
result = BalanceReactionCheck.parse_input(input_data) | ||
self.assertEqual(result, expected_output) | ||
|
||
def test_parse_input_list_of_strings(self): | ||
input_data = ["C>>O", "[HH]+O=O>>O"] | ||
expected_output = [{"reactions": "C>>O"}, {"reactions": "[HH]+O=O>>O"}] | ||
result = BalanceReactionCheck.parse_input(input_data) | ||
self.assertEqual(result, expected_output) | ||
|
||
def test_parse_input_list_of_dicts(self): | ||
input_data = [{"reactions": "C>>O"}, {"reactions": "[HH]+O=O>>O"}] | ||
expected_output = [{"reactions": "C>>O"}, {"reactions": "[HH]+O=O>>O"}] | ||
result = BalanceReactionCheck.parse_input(input_data) | ||
self.assertEqual(result, expected_output) | ||
|
||
def test_parse_input_mixed_list(self): | ||
input_data = ["C>>O", {"reactions": "[HH]+O=O>>O"}] | ||
expected_output = [{"reactions": "C>>O"}, {"reactions": "[HH]+O=O>>O"}] | ||
result = BalanceReactionCheck.parse_input(input_data) | ||
self.assertEqual(result, expected_output) | ||
|
||
def test_parse_input_invalid_type(self): | ||
input_data = 123 # Not a string or list | ||
with self.assertRaises(ValueError): | ||
BalanceReactionCheck.parse_input(input_data) | ||
|
||
def test_parse_reaction(self): | ||
reaction_smiles = "C+C>>O+O" | ||
expected_output = ("C+C", "O+O") | ||
result = BalanceReactionCheck.parse_reaction(reaction_smiles) | ||
self.assertEqual(result, expected_output) | ||
|
||
def test_parse_reaction_single(self): | ||
reaction_smiles = "CC>>OO" | ||
expected_output = ("CC", "OO") | ||
result = BalanceReactionCheck.parse_reaction(reaction_smiles) | ||
self.assertEqual(result, expected_output) | ||
|
||
def test_single_smiles_balanced(self): | ||
"""Test a single balanced reaction in SMILES format.""" | ||
smiles = ( | ||
"Clc1cnc2nc1Nc1ccc(OCCC3CCNCC3)c(c1)CCc1cncc(c1)N2.O=C=NCc1ccco1" | ||
+ ">>O=C(NCc1ccco1)N1CCC(CCOc2ccc3cc2CCc2cncc(c2)Nc2ncc(Cl)c(n2)N3)CC1" | ||
) | ||
checker = BalanceReactionCheck() | ||
balanced = checker.rsmi_balance_check(smiles) | ||
self.assertTrue(balanced) | ||
|
||
def test_single_smiles_unbalanced(self): | ||
"""Test a single unbalanced reaction in SMILES format.""" | ||
smiles = "CC(=O)O.CCO>>CC(=O)OCC" | ||
checker = BalanceReactionCheck() | ||
balanced = checker.rsmi_balance_check(smiles) | ||
self.assertFalse(balanced) | ||
|
||
def test_list_of_dicts_mixed(self): | ||
"""Test a list of dictionaries with mixed balanced and unbalanced reactions.""" | ||
reactions = [ | ||
{ | ||
"R-id": "test_1", | ||
"reactions": ( | ||
"Clc1cnc2nc1Nc1ccc(OCCC3CCNCC3)c(c1)CCc1cncc(c1)N2.O=C=NCc1ccco1" | ||
+ ">>O=C(NCc1ccco1)N1CCC(CCOc2ccc3cc2CCc2cncc(c2)Nc2ncc(Cl)c(n2)N3)CC1" | ||
), | ||
}, | ||
{"R-id": "test_2", "reactions": "CC(=O)O.CCO>>CC(=O)OCC"}, | ||
] | ||
checker = BalanceReactionCheck() | ||
balanced, unbalanced = checker.dicts_balance_check( | ||
reactions, rsmi_column="reactions" | ||
) | ||
self.assertEqual(len(balanced), 1) | ||
self.assertEqual(len(unbalanced), 1) | ||
self.assertEqual(balanced[0]["R-id"], "test_1") | ||
self.assertEqual(unbalanced[0]["R-id"], "test_2") | ||
|
||
def test_valid_smiles_single_molecule(self): | ||
""" | ||
Test that the function returns the correct molecular formula for a valid SMILES string. | ||
""" | ||
smiles = "CCO" # Ethanol | ||
expected_formula = "C2H6O" | ||
result = BalanceReactionCheck().get_combined_molecular_formula(smiles) | ||
self.assertEqual( | ||
result, expected_formula, "Molecular formula for ethanol should be C2H6O." | ||
) | ||
|
||
def test_valid_smiles_complex_molecule(self): | ||
""" | ||
Test that the function returns the correct molecular formula for a more complex molecule. | ||
""" | ||
smiles = "CC(C)C(=O)O" # Isobutyric acid | ||
expected_formula = "C4H8O2" | ||
result = BalanceReactionCheck().get_combined_molecular_formula(smiles) | ||
self.assertEqual( | ||
result, | ||
expected_formula, | ||
"Molecular formula for isobutyric acid should be C4H8O2.", | ||
) | ||
|
||
def test_invalid_smiles(self): | ||
""" | ||
Test that the function returns an empty string when an invalid SMILES string is provided. | ||
""" | ||
invalid_smiles = "INVALID" | ||
result = BalanceReactionCheck().get_combined_molecular_formula(invalid_smiles) | ||
self.assertEqual(result, "", "Invalid SMILES should return an empty string.") | ||
|
||
|
||
if __name__ == "__main__": | ||
unittest.main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
import unittest | ||
from synutility.SynChem.Reaction.deionize import ( | ||
Deionize, | ||
) | ||
|
||
|
||
class TestDeionize(unittest.TestCase): | ||
|
||
def test_uncharge_anion(self): | ||
smiles = "[OH-]" | ||
uncharged_smiles = Deionize.uncharge_anion(smiles) | ||
self.assertEqual(uncharged_smiles, "O") | ||
|
||
def test_uncharge_cation(self): | ||
smiles = "[NH4+]" | ||
uncharged_smiles = Deionize.uncharge_cation(smiles) | ||
self.assertEqual( | ||
uncharged_smiles, "[NH4]" | ||
) # can uncharge to [NH4] but will not pass through | ||
|
||
def test_ammonia_hydroxide_standardize(self): | ||
reaction_smiles = "[NH4+].[OH-]>>N.O" | ||
standardized_smiles = Deionize.ammonia_hydroxide_standardize(reaction_smiles) | ||
self.assertTrue("N.O" in standardized_smiles or "O.N" in standardized_smiles) | ||
|
||
def test_not_uncharge_smiles(self): | ||
charge_smiles = "[NH4+].[OH-]" | ||
uncharged_smiles = Deionize.uncharge_smiles(charge_smiles) | ||
self.assertTrue("N" in uncharged_smiles and "O" in uncharged_smiles) | ||
self.assertTrue( | ||
uncharged_smiles in ["[NH4+].[OH-]", "[OH-].[NH4+]"] | ||
) # can not uncharge amonium | ||
|
||
def test_uncharge_smiles(self): | ||
charge_smiles = "[Na+].[OH-]" | ||
uncharged_smiles = Deionize.uncharge_smiles(charge_smiles) | ||
self.assertEqual(uncharged_smiles, "O[Na]") # can not uncharge amonium | ||
|
||
def test_apply_uncharge_smiles_to_reactions(self): | ||
reactions = [{"reactants": "[NH4+].[OH-]", "products": "N.O"}] | ||
uncharged_reactions = Deionize.apply_uncharge_smiles_to_reactions( | ||
reactions, Deionize.uncharge_smiles | ||
) | ||
for reaction in uncharged_reactions: | ||
self.assertTrue( | ||
"N" in reaction["new_reactants"] and "O" in reaction["new_reactants"] | ||
) | ||
self.assertTrue(reaction["success"]) | ||
|
||
|
||
if __name__ == "__main__": | ||
unittest.main() |
Oops, something went wrong.