2 Commits

Author SHA1 Message Date
04f9c9252a ... 2025-11-04 10:15:06 +01:00
c2d45917ce clean up d3_json 2025-10-31 09:38:41 +01:00
4 changed files with 62 additions and 10 deletions

View File

@ -1573,14 +1573,12 @@ class Pathway(EnviPathModel, AliasMixin, ScenarioMixin):
while len(queue): while len(queue):
current = queue.pop() current = queue.pop()
processed.add(current) processed.add(current)
nodes.append(current.d3_json()) nodes.append(current.d3_json())
for e in self.edges: for e in self.edges.filter(start_nodes=current).distinct():
if current in e.start_nodes.all(): for prod in e.end_nodes.all():
for prod in e.end_nodes.all(): if prod not in queue and prod not in processed:
if prod not in queue and prod not in processed: queue.append(prod)
queue.append(prod)
# We shouldn't lose or make up nodes... # We shouldn't lose or make up nodes...
assert len(nodes) == len(self.nodes) assert len(nodes) == len(self.nodes)

View File

@ -172,6 +172,7 @@ def predict(
except Exception as e: except Exception as e:
pw.kv.update({"status": "failed"}) pw.kv.update({"status": "failed"})
pw.kv.update(**{"error": str(e)})
pw.save() pw.save()
if JobLog.objects.filter(task_id=self.request.id).exists(): if JobLog.objects.filter(task_id=self.request.id).exists():

View File

@ -2,12 +2,13 @@ import logging
import re import re
from abc import ABC from abc import ABC
from collections import defaultdict from collections import defaultdict
from typing import List, Optional, Dict, TYPE_CHECKING from typing import List, Optional, Dict, TYPE_CHECKING, Union
from indigo import Indigo, IndigoException, IndigoObject from indigo import Indigo, IndigoException, IndigoObject
from indigo.renderer import IndigoRenderer from indigo.renderer import IndigoRenderer
from rdkit import Chem, rdBase from rdkit import Chem, rdBase
from rdkit.Chem import MACCSkeys, Descriptors from rdkit.Chem import MACCSkeys, Descriptors
from rdkit.Chem import rdchem
from rdkit.Chem import rdChemReactions from rdkit.Chem import rdChemReactions
from rdkit.Chem.Draw import rdMolDraw2D from rdkit.Chem.Draw import rdMolDraw2D
from rdkit.Chem.MolStandardize import rdMolStandardize from rdkit.Chem.MolStandardize import rdMolStandardize
@ -90,8 +91,15 @@ class FormatConverter(object):
return Chem.MolToSmiles(mol, canonical=canonical) return Chem.MolToSmiles(mol, canonical=canonical)
@staticmethod @staticmethod
def InChIKey(smiles): def InChIKey(mol_or_smiles: Union[rdchem.Mol | str]):
return Chem.MolToInchiKey(FormatConverter.from_smiles(smiles)) if isinstance(mol_or_smiles, str):
mol_or_smiles = mol_or_smiles.replace("~", "")
mol_or_smiles = FormatConverter.from_smiles(mol_or_smiles)
if mol_or_smiles is None:
return None
return Chem.MolToInchiKey(mol_or_smiles)
@staticmethod @staticmethod
def InChI(smiles): def InChI(smiles):
@ -288,7 +296,8 @@ class FormatConverter(object):
product = GetMolFrags(product, asMols=True) product = GetMolFrags(product, asMols=True)
for p in product: for p in product:
p = FormatConverter.standardize( p = FormatConverter.standardize(
Chem.MolToSmiles(p), remove_stereo=remove_stereo Chem.MolToSmiles(p).replace("~", ""),
remove_stereo=remove_stereo,
) )
prods.append(p) prods.append(p)

View File

@ -35,6 +35,7 @@ from epdb.models import (
RuleBasedRelativeReasoning, RuleBasedRelativeReasoning,
Scenario, Scenario,
SequentialRule, SequentialRule,
Setting,
SimpleAmbitRule, SimpleAmbitRule,
SimpleRDKitRule, SimpleRDKitRule,
SimpleRule, SimpleRule,
@ -1258,3 +1259,46 @@ class PathwayUtils:
res[edge.url] = rule_chain res[edge.url] = rule_chain
return res return res
def _find_intermediates(self, data_pathway, pred_pathway):
pass
def engineer(self, setting: "Setting"):
from epdb.logic import SPathway
# get a fresh copy
pw = Pathway.objects.get(id=self.pathway.pk)
root_nodes = [n.default_node_label.smiles for n in pw.root_nodes]
if len(root_nodes) != 1:
logger.warning(f"Pathway {pw.name} has {len(root_nodes)} root nodes")
return
spw = SPathway(root_nodes[0], None, setting)
level = 0
while not spw.done:
spw.predict_step(from_depth=level)
level += 1
# Generate Node / SMILES mapping
node_mapping = {}
from utilities.chem import FormatConverter
for node in pw.nodes:
for snode in spw.smiles_to_node.values():
data_smiles = node.default_node_label.smiles
pred_smiles = snode.smiles
data_key = FormatConverter.InChIKey(data_smiles.replace("~", ""))
pred_key = FormatConverter.InChIKey(pred_smiles.replace("~", ""))
if data_key == pred_key:
node_mapping[snode] = node
print(node_mapping)
return spw
pass