High-Performance Pharmaceutical Polymorph Analysis — C++ core, Python API
A C++17 engine (Python bindings via pybind11) for pharmaceutical polymorph analysis: CIF parsing, crystallographic descriptors (cell volume, density, Kitaigorodskii packing coefficient), hydrogen-bond geometry, and anhydrous vs hydrate comparison (Kabsch RMSD overlay) — with R comparative statistics and a SQL metadata catalogue.
Inspired by Sallum, Siqueira, Aguiar, Duarte, Sales, Lobo, Hernandes, Camargo, Napolitano — "Comparative structural analysis of anhydrous and monohydrated polymorphs of diclofenac diethylammonium", Computational and Theoretical Chemistry 1238:114751, Elsevier (2024).
⚠️ Research & educational use only. Not a medical device. Ships illustrative, synthetic CIFs; the real structures (CCDC 150469 / 163917) are referenced, not redistributed. See DISCLAIMER.md.
- C++ core (
cpp/): CIF parser, descriptor engine, Kabsch RMSD — Eigen-backed - pybind11 module
crystalhealth._core; idiomatic Python API on top - Dual backend: uses the compiled core when available, else a pure-Python reference
with identical results (
crystalhealth.backend_name()) - Catch2 unit tests + Google Benchmark suite; cibuildwheel multi-OS wheels
- R comparative statistics (MADP, Pearson, paired t-test) à la the source paper
- SQLite/PostgreSQL metadata catalogue
CIF ─► [C++ core: cif_parser → CrystalStructure → descriptors/RMSD] ─pybind11─►
Python API (load_cif, compare) ─► pandas / SQL catalogue / R statistics
See docs/science.md for the formulae and references.
Option A — Python API (compiles the C++ core):
git clone https://github.com/S01110011/crystalhealth-engine && cd crystalhealth-engine
pip install ".[dev]" # needs CMake + a C++17 compiler
python -c "import crystalhealth as ch; print('backend:', ch.backend_name())"
pytest -qOption B — no compiler? It still works (pure-Python reference backend):
pip install numpy pandas pytest
PYTHONPATH=python pytest -q
PYTHONPATH=python python scripts/batch_descriptors.py data/cifC++ tests & benchmarks:
make cpp-test # Catch2 via CMake + CTest
make bench # Google BenchmarkCompare the two polymorphs:
import crystalhealth as ch
anh = ch.load_cif("data/cif/ddea.cif")
hyd = ch.load_cif("data/cif/ddea_h2o.cif")
print(ch.compare(anh, hyd).as_dict())
# -> hydrate has larger cell volume & lower density (see paper)R comparative statistics:
make descriptors && make stats| Gate | Tool |
|---|---|
| C++ tests | Catch2 + CTest (Linux/macOS/Windows in CI) |
| Benchmarks | Google Benchmark |
| Python | pytest (backend-agnostic) |
| Lint | ruff (Python), /W4 -Wall -Wextra (C++) |
| Packaging | scikit-build-core + cibuildwheel |
Illustrative/synthetic CIFs only. Real depositions are CCDC-licensed and must be obtained from the CCDC (codes 150469, 163917) — see data/cif/README.md. Public CIFs: Crystallography Open Database (COD).
See CONTRIBUTING.md, SECURITY.md, LICENSE.