Metadata-Version: 2.4
Name: mordred-ojmb
Version: 1.3.1
Summary: molecular descriptor calculator
Author-email: Hirotomo Moriwaki <philopon.dependence@gmail.com>
Maintainer-email: "Olivier J. M. Béquignon" <olivier.bequignon.maintainer@gmail.com>
License-Expression: BSD-3-Clause
Project-URL: Homepage, https://github.com/OlivierBeq/mordred
Keywords: QSAR,cheminformatics,molecular descriptors,toxicoinformatics
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Science/Research
Classifier: Topic :: Scientific/Engineering :: Chemistry
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Requires-Python: >=3.11
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: numpy>=2.0.0
Requires-Dist: networkx>=3.0
Requires-Dist: numba>=0.60
Requires-Dist: packaging
Requires-Dist: pandas>=2.1.0
Requires-Dist: rdkit
Requires-Dist: tqdm
Provides-Extra: test
Requires-Dist: pytest; extra == "test"
Requires-Dist: pytest-cov; extra == "test"
Requires-Dist: pyyaml; extra == "test"
Dynamic: license-file

# 🧬 mordred

<!-- Badges -->
<div align="center">

[![PyPI version](https://img.shields.io/pypi/v/mordred-ojmb.svg)](https://pypi.org/project/mordred-ojmb/)
[![Supported Python versions](https://img.shields.io/pypi/pyversions/mordred-ojmb.svg)](https://pypi.org/project/mordred-ojmb/)
[![License: BSD-3-Clause](https://img.shields.io/badge/License-BSD--3--Clause-yellow.svg)](https://opensource.org/licenses/BSD-3-Clause)
[![Tests](https://github.com/OlivierBeq/mordred/actions/workflows/tests.yml/badge.svg)](https://github.com/OlivierBeq/mordred/actions/workflows/tests.yml)
[![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)
[![codecov](https://codecov.io/gh/OlivierBeq/mordred/graph/badge.svg)](https://codecov.io/gh/OlivierBeq/mordred)
[![DOI](https://img.shields.io/badge/doi-10.1186%2Fs13321--018--0258--y-blue.svg)](https://doi.org/10.1186/s13321-018-0258-y)
<br>
![Windows](https://img.shields.io/badge/Windows-0078D6?style=for-the-badge&logo=windows&logoColor=white)
![Linux](https://img.shields.io/badge/Linux-FCC624?style=for-the-badge&logo=linux&logoColor=black)
![macOS](https://img.shields.io/badge/macOS-000000?style=for-the-badge&logo=apple&logoColor=white)

</div>

A comprehensive, pure-Python molecular descriptor calculator built directly on [RDKit](https://www.rdkit.org/) — no external binaries, no JVM, nothing to install by hand beyond RDKit itself. Mordred computes molecular descriptors straight from an `rdkit.Chem.Mol` and hands results back as plain values or a ready-to-use pandas `DataFrame`.

## ✨ Features

- 🧬 **1826 descriptors** — 1613 2D and 213 3D descriptors covering constitutional, topological, geometrical, electronic, and other descriptor classes, computed directly through RDKit.
- ⚡ **Fast & multiprocessing-ready** — `Calculator.map`/`Calculator.pandas` spread work across CPU cores out of the box; hot numeric kernels (SASA, subgraph enumeration, atomic-ID trees, ...) are JIT-compiled with numba.
- 🧩 **Composable** — descriptors are plain Python classes; build new ones out of existing ones with ordinary arithmetic (`descriptor_a + descriptor_b`, `descriptor_a * 2`, ...).
- 📊 **pandas-native output** — `Calculator.pandas()` returns a tidy `DataFrame`, one row per molecule, with missing/undefined values handled for you.
- 🧯 **Never silently misaligned** — descriptors that fail to compute for a given molecule (missing 3D coordinates, disconnected fragments, zero-division, ...) come back as explicit, inspectable errors, never dropped without a trace.
- 💾 **JSON-serializable** — save and reload the exact descriptor set behind a calculation with `Calculator.to_json`/`Calculator.from_json`, for fully reproducible pipelines.
- 🖥️ **Command-line interface** — compute descriptors for `.smi`/`.sdf`/`.mol` files straight from the shell, no Python required.

## ✍️ Copyright and Citation Notice

This repository is [Olivier J. M. Béquignon](https://github.com/OlivierBeq)'s actively maintained fork of the original [`mordred-descriptor/mordred`](https://github.com/mordred-descriptor/mordred) by Hirotomo Moriwaki et al., modernized for current Python and dependency versions (Python 3.11+, NumPy 2.x, current RDKit/pandas/networkx), with additional bug fixes and performance work. Olivier J. M. Béquignon is **not** the original author of mordred.

### Citing

If you use mordred in your research, please cite the original publication:

> Moriwaki H, Tian Y-S, Kawashita N, Takagi T (2018) Mordred: a molecular descriptor calculator. *Journal of Cheminformatics* 10:4.
> [DOI: 10.1186/s13321-018-0258-y](https://doi.org/10.1186/s13321-018-0258-y)

## 📦 Installation

```bash
pip install mordred-ojmb
```

Or from source:

```bash
git clone https://github.com/OlivierBeq/mordred.git
pip install ./mordred
```

## 🛠️ Requirements

- Python 3.11+
- [RDKit](https://www.rdkit.org/docs/Install.html)

## 💡 Usage

### Calculating descriptors

```python
from rdkit import Chem
from mordred import Calculator, descriptors

# a calculator with every registered descriptor, 2D only
calc = Calculator(descriptors, ignore_3D=True)
print(len(calc.descriptors))  # 1613

# calculate for a single molecule
mol = Chem.MolFromSmiles("c1ccccc1")
result = calc(mol)
print(result["SLogP"])

# calculate for multiple molecules, as a pandas DataFrame
mols = [Chem.MolFromSmiles(smi) for smi in ["c1ccccc1Cl", "c1ccccc1O", "c1ccccc1N"]]
df = calc.pandas(mols)
print(df["SLogP"])
```

### Selecting descriptor sets

Register individual descriptor modules — or individual descriptor classes/instances — instead of the full set:

```python
from mordred import Calculator
from mordred import AtomCount, BondCount

calc = Calculator()
calc.register(AtomCount)
calc.register(BondCount)
```

### 3D descriptors

By default, `ignore_3D=False`, so 3D descriptors are included whenever the calculator is built from the full `descriptors` module — but they return missing values for any molecule without 3D coordinates. Embed a conformer first if you want them calculated:

```python
from rdkit import Chem
from rdkit.Chem import AllChem
from mordred import Calculator, descriptors

mol = Chem.MolFromSmiles("c1ccccc1")
mol = Chem.AddHs(mol)
AllChem.EmbedMolecule(mol)

calc = Calculator(descriptors, ignore_3D=False)
result = calc(mol)
print(result["GeomDiameter"])
```

### Descriptor arithmetic

Descriptors are ordinary Python objects and compose with `+`, `-`, `*`, `/`, and more:

```python
from rdkit import Chem
from mordred import ABCIndex, Chi

benzene = Chem.MolFromSmiles("c1ccccc1")

abci = ABCIndex.ABCIndex()
chi_p2 = Chi.Chi(type="path", order=2)

abci_x_chi_p2 = abci * chi_p2
print(abci_x_chi_p2, abci_x_chi_p2(benzene))
```

### JSON serialization

Save the exact descriptor set behind a calculation, and reload it later for a fully reproducible pipeline:

```python
import json
from mordred import Calculator, descriptors

calc = Calculator(descriptors)
serialized = json.dumps(calc.to_json())

calc2 = Calculator.from_json(json.loads(serialized))
assert calc.descriptors == calc2.descriptors
```

### Command line

```bash
python -m mordred molecules.smi -o descriptors.csv
```

Accepts `.smi`, `.sdf`, and `.mol` input (auto-detected from the extension, or set explicitly with `-t`); run `python -m mordred -h` for the full option list.

## 📄 License

This project is licensed under the BSD-3-Clause License - see the [LICENSE](LICENSE) file for details. Original work Copyright (c) 2015-2017, Hirotomo Moriwaki.

## 📚 API Documentation

```python
Calculator(descs=None, version=None, ignore_3D=False, config=None)
```

The main entry point: a registry of descriptors bound to computation logic.

#### Parameters

- ***descs  : Descriptor-like, optional***
  Descriptors to register on construction — anything accepted by `register` below.
- ***version  : str, optional***
  Mordred version to register descriptor presets for; defaults to the installed version.
- ***ignore_3D  : bool***
  Skip descriptors that require 3D coordinates.
- ***config  : dict, optional***
  Global configuration dictionary, shared by all registered descriptors.

#### Attributes

- ***descriptors  : tuple[Descriptor, ...]***
  All currently registered descriptors, in registration order. Settable and deletable.

#### Methods

- ***register(desc, version=None, ignore_3D=False)***
  Register a descriptor, descriptor class, module, or any iterable of the above. A descriptor
  class is expanded via its `.preset()` method (e.g. `AtomCount` registers one instance per
  atom type); a module registers every descriptor-like object it exposes.
- ***\_\_call\_\_(mol, id=-1)*** → `Result`
  Calculate every registered descriptor for a single `rdkit.Chem.Mol`. `id` selects the
  conformer used for 3D descriptors. Returns a `Result`, a dict-and-sequence-like mapping from
  descriptor to value (or to an `Error` if that descriptor failed for this molecule).
- ***map(mols, nproc=None, quiet=False, id=-1, \*\*kwargs)*** → `Iterator[Result]`
  Calculate over an iterable of molecules, optionally in parallel (`nproc` processes; defaults
  to all available CPU cores). `kwargs` are forwarded to the `tqdm` progress bar.
- ***pandas(mols, conf_id=-1, decimals=3, fill_na=0, nproc=None, quiet=False, dtype=np.float32, \*\*kwargs)*** → `pd.DataFrame`
  Calculate over an iterable of molecules and return a tidy `DataFrame`, one row per molecule,
  with missing/undefined/absurdly-large values replaced by `fill_na` and results rounded to
  `decimals` places.
- ***to_json()*** → `list[dict]`
  Serialize the registered descriptor set to a JSON-compatible structure.
- ***Calculator.from_json(obj)*** *(classmethod)* → `Calculator`
  Build a `Calculator` back from the output of `to_json`.

________________

```python
Descriptor
```

Base class for every descriptor family (`AtomCount`, `Chi`, `SLogP`, ...). Concrete descriptors
are plain Python objects: instantiate them directly (`Chi.Chi(type="path", order=2)`), or call
`SomeDescriptor.preset(version)` to get every parametrization mordred registers by default for
that family. Descriptor instances are directly callable on a single molecule
(`descriptor(mol)`), comparable/hashable, and composable with standard arithmetic operators.

#### Notable attributes

- ***explicit_hydrogens  : bool***
  Whether this descriptor needs explicit hydrogens on the input molecule.
- ***require_3D  : bool***
  Whether this descriptor needs 3D coordinates.
- ***description()*** → `str`
  Human-readable description of this specific descriptor instance.

________________

```python
Result
```

A dict-and-sequence-like mapping from descriptor to value (or `Error`), returned by
`Calculator.__call__`/`map`. Index by descriptor name (`result["SLogP"]`), by position, or
iterate with `.items()`/`.keys()`/`.values()`.

#### Methods

- ***fill_missing(value=nan)*** → `Result`
  Replace missing/errored values with `value`.
- ***drop_missing()*** → `Result`
  Drop missing/errored values entirely.
