Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions training/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,14 @@
from fastapi.responses import HTMLResponse
from pydantic import BaseModel
from rdkit import Chem
from rdkit.Chem import AllChem, DataStructs
from rdkit.Chem import DataStructs, rdFingerprintGenerator

import predict as P # reuse the unified flavor read

app = FastAPI(title="Flavor Workbench (demo)")

_FPS, _SMI, _KNOWN = [], [], []
_MORGAN = rdFingerprintGenerator.GetMorganGenerator(radius=2, fpSize=2048)


def _build_index():
Expand All @@ -48,7 +49,7 @@ def _build_index():
mol = Chem.MolFromSmiles(r["smiles"])
if mol is None:
continue
_FPS.append(AllChem.GetMorganFingerprintAsBitVect(mol, 2, nBits=2048))
_FPS.append(_MORGAN.GetFingerprint(mol))
_SMI.append(r["smiles"])
_KNOWN.append([t for t in basic if r[t] == 1])
print(f"substitution index built: {len(_FPS)} molecules")
Expand Down Expand Up @@ -92,7 +93,7 @@ def api_neighbors(q: Query):
if not smi or not _FPS:
return {"neighbors": []}
mol = Chem.MolFromSmiles(smi)
fp = AllChem.GetMorganFingerprintAsBitVect(mol, 2, nBits=2048)
fp = _MORGAN.GetFingerprint(mol)
sims = DataStructs.BulkTanimotoSimilarity(fp, _FPS)
self_smi = Chem.MolToSmiles(mol)
ranked = sorted(range(len(sims)), key=lambda i: sims[i], reverse=True)
Expand Down
5 changes: 3 additions & 2 deletions training/predict.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,10 @@
import joblib
import numpy as np
from rdkit import Chem
from rdkit.Chem import AllChem, Crippen, DataStructs, Descriptors, rdMolDescriptors
from rdkit.Chem import Crippen, DataStructs, Descriptors, rdFingerprintGenerator, rdMolDescriptors

FP_BITS, FP_RADIUS = 2048, 2
_MORGAN = rdFingerprintGenerator.GetMorganGenerator(radius=FP_RADIUS, fpSize=FP_BITS)
TASTE = Path("taste_models")

ACID_SMARTS = {
Expand Down Expand Up @@ -234,7 +235,7 @@ def _measured(mol):


def _fp(mol):
bv = AllChem.GetMorganFingerprintAsBitVect(mol, FP_RADIUS, nBits=FP_BITS)
bv = _MORGAN.GetFingerprint(mol)
arr = np.zeros((FP_BITS,), dtype=np.int8)
DataStructs.ConvertToNumpyArray(bv, arr)
return arr.reshape(1, -1)
Expand Down
5 changes: 3 additions & 2 deletions training/train_taste.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
import numpy as np
import pandas as pd
from rdkit import Chem
from rdkit.Chem import AllChem, DataStructs
from rdkit.Chem import DataStructs, rdFingerprintGenerator
from sklearn.ensemble import RandomForestClassifier, RandomForestRegressor
from sklearn.model_selection import train_test_split
from sklearn.metrics import roc_auc_score, r2_score
Expand All @@ -31,6 +31,7 @@
# handled in predict.py and never trained — regardless of how much data accrues.
RULE_TASTES = {"sour", "salty"}
FP_BITS, FP_RADIUS = 2048, 2
_MORGAN = rdFingerprintGenerator.GetMorganGenerator(radius=FP_RADIUS, fpSize=FP_BITS)
# Below this, a taste is too thin for an HONEST head, so it's skipped and
# handled by rule/flag instead. It's not a hard exclusion: add more data (more
# sources) and the taste crosses the line and trains itself on the next run.
Expand All @@ -55,7 +56,7 @@ def fp(smiles):
mol = Chem.MolFromSmiles(smiles)
if mol is None:
return None
bv = AllChem.GetMorganFingerprintAsBitVect(mol, FP_RADIUS, nBits=FP_BITS)
bv = _MORGAN.GetFingerprint(mol)
arr = np.zeros((FP_BITS,), dtype=np.int8)
DataStructs.ConvertToNumpyArray(bv, arr)
return arr
Expand Down
Loading