File size: 3,158 Bytes
4dcbafd
 
 
c79e342
 
 
7d2c47b
 
 
 
 
c79e342
7d2c47b
 
c79e342
e929cfd
 
7d2c47b
c79e342
7d2c47b
c79e342
 
 
 
 
7d2c47b
c79e342
 
7d2c47b
c79e342
 
7d2c47b
 
 
 
 
 
 
de0174a
 
 
7d2c47b
 
 
 
b5a6be3
7d2c47b
 
 
 
 
 
c79e342
 
 
7d2c47b
 
 
 
 
 
 
 
 
c79e342
 
15286d7
ba09262
15286d7
 
c79e342
 
 
7d2c47b
 
c79e342
 
 
 
7d2c47b
f259716
c79e342
 
 
 
42b8875
 
 
c79e342
42b8875
c79e342
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
---
license: cc-by-nc-4.0
---

# BioXMol — molecular encoder

A graph neural network that turns a SMILES string into a fixed-length embedding.
It was trained with soft contrastive learning to align molecular structure with
biological readouts (Cell Painting morphology from JUMP-CP and L1000 transcriptomics),
so the embeddings carry biological signal useful for tasks like drug-induced liver
injury (DILI) prediction. This repo ships the molecule encoder only — you provide SMILES.

This is a custom GNN, **not** a `transformers` model, so `AutoModel.from_pretrained`
does not work. Use the block below; it depends only on `torch` and `rdkit`.

![BioXMol overview](overview.png)

## How to use

Install:

```bash
pip install torch rdkit safetensors huggingface_hub numpy
```

Copy this whole block and run it — it downloads everything it needs from this repo:

```python
import os, sys, torch
from huggingface_hub import hf_hub_download
from safetensors.torch import load_file

REPO = "arslanmasood/BioXMol"

# 1. download the code + weights from this repo
for f in ["modeling_bioxmol.py", "featurizer.py"]:
    code_dir = os.path.dirname(hf_hub_download(REPO, f))
sys.path.insert(0, code_dir)
from modeling_bioxmol import GatedGraphNeuralNetwork
from featurizer import smiles2graph

# 2. load the encoder
model = GatedGraphNeuralNetwork(n_edge=1, in_dim=75, n_conv=6, fc_dims=[1024, 128])
model.load_state_dict(load_file(hf_hub_download(REPO, "bioxmol_soft_seed0.safetensors")))
model.eval()

# 3. encode a list of SMILES -> embeddings
@torch.no_grad()
def encode(smiles_list, layer="first_fc"):
    graphs = [smiles2graph(s) for s in smiles_list]
    n = max(nf.shape[0] for _, nf in graphs)            # pad to the largest molecule
    A, F, M = [], [], []
    for adj, nf in graphs:
        adj = torch.as_tensor(adj, dtype=torch.float)
        nf = torch.as_tensor(nf, dtype=torch.float)
        a = torch.zeros(n, n);           a[:adj.shape[0], :adj.shape[1]] = adj
        f = torch.zeros(n, nf.shape[1]); f[:nf.shape[0]] = nf
        m = torch.zeros(n, 1);           m[:nf.shape[0]] = 1.0   # 1 = real atom
        A.append(a); F.append(f); M.append(m)
    return model.embed(torch.stack(A), torch.stack(F), torch.stack(M), layer=layer)

# example
emb = encode(["CCO", "CC(=O)Oc1ccccc1C(=O)O"])
print(emb.shape)   # torch.Size([2, 1024])
```

`layer` can be 
- `"GNN"` (75-d),
- `"first_fc"` (1024-d, the default and recommended),
- `"second_fc"` (128-d).

## Training data

Pretrained on JUMP-CP (Cell Painting) and LINCS L1000 (transcriptomics); evaluated on
DILIRank 2.0. Each dataset has its own terms — check them before redistributing
derived artifacts.

## License

CC-BY-NC-4.0 (attribution, non-commercial). The training code inherits GPLv3 from the
upstream framework and is distributed separately.

## Citation

```bibtex
@misc{masood2026bioxmol,
  title  = {Unifying Disjoint Phenotypic Contexts: A Multimodal Soft Contrastive Approach to Identify DILI Activity Cliffs},
  author = {Masood, Muhammad Arslan and Cui, Tianyu and Heinonen, Markus and Kaski, Samuel},
  year   = {2026},
  doi    = {10.21203/rs.3.rs-9875956/v1}
}
```