Skip to content

Commit

Permalink
refactored to be able to install package
Browse files Browse the repository at this point in the history
Signed-off-by: Marcel Müller <[email protected]>
  • Loading branch information
marcelmbn committed Oct 17, 2023
1 parent 03dd09a commit 56e41e1
Show file tree
Hide file tree
Showing 7 changed files with 164 additions and 45 deletions.
12 changes: 12 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
[build-system]
requires = ["setuptools"]
build-backend = "setuptools.build_meta"

[tool.mypy]
check_untyped_defs = true
disallow_any_generics = true
disallow_incomplete_defs = true
disallow_untyped_defs = true
warn_redundant_casts = true
warn_unreachable = true
warn_unused_ignores = true
41 changes: 41 additions & 0 deletions setup.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
[metadata]
name = getrandompcmol
version = attr: getrandompcmol.__version__.__version__
long_description = file: README.md
long_description_content_type = text/markdown
author = "Marcel Müller"
license = GPL-3.0
license_files = LICENSE
classifiers =
License :: OSI Approved :: GNU General Public License v3 (GPLv3)
Programming Language :: Python
Programming Language :: Python :: 3
Programming Language :: Python :: 3 :: Only
Programming Language :: Python :: 3.8
Programming Language :: Python :: 3.9
Programming Language :: Python :: 3.10
Programming Language :: Python :: 3.11
Topic :: Scientific/Engineering
Typing :: Typed

[options]
packages = find:
install_requires =
numpy
python_requires = >=3.8
include_package_data = True
package_dir =
=src

[options.packages.find]
where = src

[options.entry_points]
console_scripts =
getrandompcmol = getrandompcmol:console_entry_point

[options.extras_require]
dev =
black
pre-commit
pylint
4 changes: 4 additions & 0 deletions setup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
from setuptools import setup

if __name__ == "__main__":
setup()
10 changes: 10 additions & 0 deletions src/getrandompcmol/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
"""
GetRandomPCMol
=======
Dummy command line tool to square a number.
"""

from .__version__ import __version__
from .miscelleanous import chdir, create_directory
from .randommols import console_entry_point, main
5 changes: 5 additions & 0 deletions src/getrandompcmol/__version__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
"""
Module containing the version string.
"""

__version__ = "0.1.0"
46 changes: 46 additions & 0 deletions src/getrandompcmol/miscelleanous.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
"""
Miscelleanous functions that are used in the project.
"""

from __future__ import annotations

import os


def create_directory(name: str) -> bool:
"""
Creates a directory with the given name if it does not exist already.
"""
if not os.path.exists(name):
os.mkdir(name)
exist = False
else:
print(f"Directory {name} already exists.")
exist = True

# check if the new directory exists and raise an error and stop execution if not
try:
if not os.path.exists(name):
raise FileNotFoundError(f"Directory {name} does not exist.")
except FileNotFoundError as e:
print(f"Error: {e}")
raise SystemExit(1) from e
return exist


# define a function which goes back to the original working directory if it is called
def chdir(dirname: str) -> None:
"""
Change the active directory.
"""
try:
os.chdir(str(dirname))
# print("Current working directory: {0}".format(os.getcwd()))
except FileNotFoundError:
print(f"Directory: {dirname} does not exist")
except NotADirectoryError:
print(f"{dirname} is not a directory")
except PermissionError:
print(f"You do not have permissions to change to {dirname}")

return None
91 changes: 46 additions & 45 deletions randommols.py → src/getrandompcmol/randommols.py
Original file line number Diff line number Diff line change
@@ -1,31 +1,30 @@
#!/usr/bin/env python

"""
This script generates random molecules from PubChem and optimizes them with xTB.
"""
from __future__ import annotations

import argparse as ap
import os
import subprocess

from numpy.random import RandomState

from .miscelleanous import chdir, create_directory


def main(arguments):
def main(arguments: ap.Namespace) -> None:
"""
Main function of the script.
"""
# get number of compounds from command line
numcomp = arguments.numcomp

### GENERAL PARAMETERS ###
maxcid = 10000000
maxnumat = 50

class bcolors:
HEADER = "\033[95m"
OKBLUE = "\033[94m"
OKCYAN = "\033[96m"
OKGREEN = "\033[92m"
WARNING = "\033[93m"
FAIL = "\033[91m"
ENDC = "\033[0m"
BOLD = "\033[1m"
UNDERLINE = "\033[4m"

# set the seed
print(f"Generating random numbers between 1 and {maxcid:d} ...")
seed = RandomState(2009)
Expand All @@ -35,8 +34,8 @@ class bcolors:
pwd = os.getcwd()

# run PubGrep for each value and set up a list with successful downloads
comp = []
molname = []
comp: list[int] = []
molname: list[str] = []
for i in values:
print(f"\nDownloading CID {i:7d} ...")
try:
Expand Down Expand Up @@ -82,30 +81,21 @@ class bcolors:
else:
print(" " * 3 + f"Downloaded {i:7d} successfully after xTB conversion.")

try:
os.chdir(str(pwd) + "/pubchem_compounds/" + str(i))
# print("Current working directory: {0}".format(os.getcwd()))
except FileNotFoundError:
print(f"Directory: /pubchem_compounds/{i} does not exist")
except NotADirectoryError:
print(f"/pubchem_compounds/{i} is not a directory")
except PermissionError:
print(f"You do not have permissions to change to /pubchem_compounds/{i}")

# print the first entry of the fourth line compund of interest in sdf format
with open(f"{i}.sdf", encoding="UTF-8") as f:
lines = f.readlines()
nat = int(lines[3].split()[0])
print(" " * 3 + f"# of atoms: {nat:8d}")
if int(nat) > maxnumat:
print(
f"""{bcolors.WARNING}Number of
atoms in {i}.sdf is larger than {maxnumat} -
skipping CID {i:7d}{bcolors.ENDC}"""
f"{bcolors.WARNING}Number of \
atoms in {i}.sdf is larger than {maxnumat} -\
skipping CID {i:7d}{bcolors.ENDC}"
)
odir(pwd)
continue

direxists = create_directory(str(i))
chdir(str(i))
try:
pgout = subprocess.run(
["xtb", f"{i}.sdf", "--opt"],
Expand All @@ -117,7 +107,7 @@ class bcolors:
f.write(pgout.stdout.decode("utf-8"))
except subprocess.TimeoutExpired as exc:
print(" " * 3 + f"Process timed out.\n{exc}")
odir(pwd)
chdir(pwd)
continue
except subprocess.CalledProcessError as exc:
print(
Expand All @@ -131,7 +121,7 @@ class bcolors:
f"{bcolors.WARNING}xTB optimization failed - skipping CID %7d{bcolors.ENDC}"
% i
)
odir(pwd)
chdir(pwd)
continue

# load fourth entry of a line with ":: total charge" of xtb.out into a variable
Expand All @@ -155,7 +145,7 @@ class bcolors:
)
except subprocess.TimeoutExpired as exc:
print(" " * 3 + f"Process timed out.\n{exc}")
odir(pwd)
chdir(pwd)
continue
except subprocess.CalledProcessError as exc:
print(" " * 3 + "Status : FAIL", exc.returncode, exc.output)
Expand All @@ -166,10 +156,10 @@ class bcolors:
f"{bcolors.WARNING}mctc-convert failed - skipping CID %7d{bcolors.ENDC}"
% i
)
odir(pwd)
chdir(pwd)
continue

odir(pwd)
chdir(pwd)

# grep the name of the molecule from found.results (first entry in first line)
with open("found.results", encoding="UTF-8") as f:
Expand All @@ -178,8 +168,8 @@ class bcolors:
print(" " * 3 + f"Compound name: {molname[-1]:s}")

print(
f"""{bcolors.OKGREEN}Structure of
%7d successfully generated and optimized.{bcolors.ENDC}"""
f"{bcolors.OKGREEN}Structure of\
%7d successfully generated and optimized.{bcolors.ENDC}"
% i
)
comp.append(i)
Expand All @@ -198,18 +188,24 @@ class bcolors:
os.remove("found.results")


# define a function which goes back to the original working directory if it is called
def odir(pwdorg):
try:
os.chdir(str(pwdorg))
# print("Current working directory: {0}".format(os.getcwd()))
except FileNotFoundError:
print("Directory does not exist")
except NotADirectoryError:
print(f"{pwdorg} is not a directory")
class bcolors:
"""
Class for colorizing the output.
"""

HEADER = "\033[95m"
OKBLUE = "\033[94m"
OKCYAN = "\033[96m"
OKGREEN = "\033[92m"
WARNING = "\033[93m"
FAIL = "\033[91m"
ENDC = "\033[0m"
BOLD = "\033[1m"
UNDERLINE = "\033[4m"

if __name__ == "__main__":

def console_entry_point() -> int:
# parse arguments
parser = ap.ArgumentParser(description="Generate random molecules from PubChem")
parser.add_argument(
"-n",
Expand All @@ -221,3 +217,8 @@ def odir(pwdorg):
)
args = parser.parse_args()
main(args)
return 0


if __name__ == "__main__":
console_entry_point()

0 comments on commit 56e41e1

Please sign in to comment.