Skip to content

Commit

Permalink
libmoleculargraph instruction
Browse files Browse the repository at this point in the history
  • Loading branch information
mojaie committed Jan 10, 2024
1 parent e2a605d commit 7202944
Show file tree
Hide file tree
Showing 3 changed files with 173 additions and 76 deletions.
51 changes: 34 additions & 17 deletions build/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,37 @@ libmoleculargraph

A library builder for calling some functions of MolecularGraph.jl from external applications. See [PackageCompiler.jl](https://github.com/JuliaLang/PackageCompiler.jl) for details.

### tested environment

```
julia> versioninfo()
Julia Version 1.8.2
Commit 36034abf260 (2022-09-29 15:21 UTC)
Platform Info:
OS: macOS (x86_64-apple-darwin21.4.0)
CPU: 4 × Intel(R) Core(TM) i5-8210Y CPU @ 1.60GHz
WORD_SIZE: 64
LIBM: libopenlibm
LLVM: libLLVM-13.0.1 (ORCJIT, skylake)
Threads: 1 on 4 virtual cores
```

- ./scripts/test_lib.py worked with Python 3.10.0
- did not work with Julia version 1.7.3 due to a link error.

### Dockerfile (recommended)

- See `./docker-example`
- A test script `../scripts/python_test.py` worked with Python 3.10.0


### Other platforms

Building in environments shown below and other platforms are not supported.


#### For Intel Mac

- Building MacOS binary has some potential issues.
- Run `make` to build binary and then `sudo make link` to copy them to `/usr/local`
- Testing environment:

```
julia> versioninfo()
Julia Version 1.10.0
Commit 3120989f39b (2023-12-25 18:01 UTC)
Build Info:
Official https://julialang.org/ release
Platform Info:
OS: macOS (x86_64-apple-darwin22.4.0)
CPU: 4 × Intel(R) Core(TM) i5-8210Y CPU @ 1.60GHz
WORD_SIZE: 64
LIBM: libopenlibm
LLVM: libLLVM-15.0.7 (ORCJIT, skylake)
Threads: 1 on 4 virtual cores
```

- did not work with Julia version 1.7.3 (and below) due to a link error.
139 changes: 139 additions & 0 deletions scripts/python_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
from ctypes import CDLL, RTLD_GLOBAL, POINTER, cast, c_char_p, c_ubyte, c_double, c_int, c_uint
import json
from pathlib import Path
import platform


def jl_init():
dlext = "dylib" if platform.system() == "Darwin" else "so"
libdir = Path("/usr/local/lib")
jl = CDLL(libdir / f"libmoleculargraph.{dlext}", RTLD_GLOBAL)
jl.jl_init_with_image(bytes(libdir), f"libmoleculargraph.{dlext}".encode())
return jl


def jl_exit(jl):
jl.jl_atexit_hook(0)


def smiles_to_mol(jl, smiles: str) -> bytes:
jl.smilestomol.argtypes = [c_char_p]
jl.smilestomol.restype = c_char_p
return jl.smilestomol(smiles.encode(), r"{}".encode())


def smarts_to_mol(jl, smarts: str) -> bytes:
jl.smartstomol.argtypes = [c_char_p]
jl.smartstomol.restype = c_char_p
return jl.smartstomol(smarts.encode())


def sdf_to_mol(jl, sdf: str) -> bytes:
# sdf: SDFile string (open as f -> f.read())
jl.sdftomol.argtypes = [c_char_p]
jl.sdftomol.restype = c_char_p
return jl.sdftomol(sdf.encode(), r"{}".encode())


def vertex_count(jl, mol: bytes) -> int:
# mol: json.dumps(mol_dict).encode()
jl.vertex_count.argtypes = [c_char_p]
jl.vertex_count.restype = c_int
return jl.vertex_count(mol)


def edge_count(jl, mol: bytes) -> int:
# mol: json.dumps(mol_dict).encode()
jl.edge_count.argtypes = [c_char_p]
jl.edge_count.restype = c_int
return jl.edge_count(mol)


def inchikey(jl, mol: bytes) -> str:
# mol: json.dumps(mol_dict).encode()
jl.inchikey.argtypes = [c_char_p]
jl.inchikey.restype = c_char_p
return jl.inchikey(mol).decode("utf-8")


def standard_weight(jl, mol: bytes) -> float:
# mol: json.dumps(mol_dict).encode()
jl.standard_weight.argtypes = [c_char_p]
jl.standard_weight.restype = c_double
return jl.standard_weight(mol)


def mol_to_svg(jl, mol: bytes) -> str:
# mol: json.dumps(mol_dict).encode()
jl.drawsvg.argtypes = [c_char_p]
jl.drawsvg.restype = c_char_p
return jl.drawsvg(mol).decode("utf-8")


def sdf_to_svg(jl, sdf: str) -> str:
mol = sdf_to_mol(jl, sdf)
return mol_to_svg(jl, mol)


def smiles_to_svg(jl, smiles: str) -> str:
mol = smiles_to_mol(jl, smiles)
return mol_to_svg(jl, mol)


def mol_to_png(jl, mol: bytes, width: int, height: int) -> bytes:
# mol: json.dumps(mol_dict).encode()
buf = (c_ubyte * 200_000).from_buffer(bytearray(200_000)) # 200 kB buffer, tentative
jl.drawpng.argtypes = [c_ubyte * 200_000, c_char_p, c_uint, c_uint]
jl.drawpng.restype = c_int
size = jl.drawpng(buf, mol, c_uint(width), c_uint(height))
return bytes(buf[:size])


def sdf_to_png(jl, sdf: str, width: int, height: int) -> bytes:
mol = sdf_to_mol(jl, sdf)
return mol_to_png(jl, mol, width, height)


def smiles_to_png(jl, smiles: str, width: int, height: int) -> bytes:
mol = smiles_to_mol(jl, smiles)
return mol_to_png(jl, mol, width, height)


def has_exact_match(jl, mol1: bytes, mol2: bytes, options: bytes) -> bool:
# mol1, mol2, options: json.dumps(dict).encode()
jl.has_exact_match.argtypes = [c_char_p, c_char_p, c_char_p]
jl.has_exact_match.restype = c_int
return jl.has_exact_match(mol1, mol2, options)


def has_substruct_match(jl, mol1: bytes, mol2: bytes, options: bytes) -> bool:
# mol1, mol2, options: json.dumps(dict).encode()
jl.has_substruct_match.argtypes = [c_char_p, c_char_p, c_char_p]
jl.has_substruct_match.restype = c_int
return jl.has_substruct_match(mol1, mol2, options)


def tdmcis_size(jl, mol1: bytes, mol2: bytes, options: bytes) -> int:
# mol1, mol2, options: json.dumps(dict).encode()
jl.tdmcis_size.argtypes = [c_char_p, c_char_p, c_char_p]
jl.tdmcis_size.restype = c_int
return jl.tdmcis_size(mol1, mol2, options)


def tdmces_size(jl, mol1: bytes, mol2: bytes, options: bytes) -> int:
# mol1, mol2, options: json.dumps(dict).encode()
jl.tdmces_size.argtypes = [c_char_p, c_char_p, c_char_p]
jl.tdmces_size.restype = c_int
return jl.tdmces_size(mol1, mol2, options)


if __name__ == "__main__":
jl = jl_init()
mol1 = smiles_to_mol(jl, "CC(=O)OC1=CC=CC=C1C(=O)O")
mol2 = smiles_to_mol(jl, "OC1=CC=CC=C1C(=O)O")
print(standard_weight(jl, mol1))
print(inchikey(jl, mol1))
print(has_substruct_match(jl, mol1, mol2, json.dumps({}).encode()))
print(tdmces_size(jl, mol1, mol2, json.dumps({}).encode()))
print(mol_to_svg(jl, mol1))
jl_exit(jl)
59 changes: 0 additions & 59 deletions scripts/test_lib.py

This file was deleted.

0 comments on commit 7202944

Please sign in to comment.