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
18 changes: 13 additions & 5 deletions hippo/designdb/components/compound.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
ReactantModel,
ReactionModel,
ScaffoldModel,
TargetModel,
)
from django.db.models import Exists, OuterRef
from IPython.display import display
Expand Down Expand Up @@ -376,17 +377,24 @@ def add_stock(
return quote
return quote.pk

def get_tags(self) -> list[str]:
"""Get the tags assigned to this compound"""
return list(self._instance.tags.values_list('compound_tag_name', flat=True))
def get_tags(self, target: TargetModel | None = None) -> list[str]:
"""Get the tags assigned to this compound

def add_tag(self, tag: str) -> None:
:param target: Optionally restrict to tags assigned under this
:class:`.TargetModel`, defaults to ``None`` (tags across all targets)
"""
junctions = CompoundTagJunctionModel.objects.filter(compound=self._instance)
if target is not None:
junctions = junctions.filter(target=target)
return list(junctions.values_list('compound_tag__compound_tag_name', flat=True))

def add_tag(self, tag: str, *, target: TargetModel) -> None:
"""Add a tag to this compound"""

assert isinstance(tag, str)
tag_obj, _ = CompoundTagModel.objects.get_or_create(compound_tag_name=tag)
CompoundTagJunctionModel.objects.get_or_create(
compound=self._instance, compound_tag=tag_obj
compound=self._instance, compound_tag=tag_obj, target=target
)
self._tags = None # invalidate cache

Expand Down
14 changes: 12 additions & 2 deletions hippo/designdb/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -641,12 +641,17 @@ class Meta(BaseModel.Meta):


class CompoundTagJunctionModel(BaseModel):
pk = models.CompositePrimaryKey('compound_id', 'compound_tag_id')
pk = models.CompositePrimaryKey('compound_id', 'compound_tag_id', 'target_id')
compound = models.ForeignKey(
CompoundModel,
on_delete=models.CASCADE,
db_column='compound_id',
)
target = models.ForeignKey(
TargetModel,
on_delete=models.CASCADE,
db_column='target_id',
)
compound_tag = models.ForeignKey(
CompoundTagModel,
on_delete=models.CASCADE,
Expand Down Expand Up @@ -691,12 +696,17 @@ class Meta(BaseModel.Meta):


class CompoundEnumerationMethodJunctionModel(BaseModel):
pk = models.CompositePrimaryKey('compound_id', 'enumeration_method_id')
pk = models.CompositePrimaryKey('compound_id', 'enumeration_method_id', 'target_id')
compound = models.ForeignKey(
CompoundModel,
on_delete=models.CASCADE,
db_column='compound_id',
)
target = models.ForeignKey(
TargetModel,
on_delete=models.CASCADE,
db_column='target_id',
)
enumeration_method = models.ForeignKey(
EnumerationMethodModel,
on_delete=models.CASCADE,
Expand Down
29 changes: 25 additions & 4 deletions hippo/designdb/services/ingestion.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@
import pandas as pd
from designdb.components.compound import Ingredient
from designdb.models import (
CompoundEnumerationMethodJunctionModel,
CompoundModel,
CompoundTagJunctionModel,
EnumerationMethodModel,
PoseMethodModel,
PoseModel,
Expand Down Expand Up @@ -371,7 +373,12 @@ def ingest_filesystem(
smiles=smiles,
# inchikey=sane_inchikey,
)
compound.tags.add(*compound_tags)
for compound_tag in compound_tags:
CompoundTagJunctionModel.objects.get_or_create(
compound=compound,
compound_tag=compound_tag,
target=target,
)
if compound_created:
result.compounds_created += 1

Expand Down Expand Up @@ -514,9 +521,18 @@ def ingest_sdf(
# smiles=sane_smiles,
# inchikey=sane_inchikey,
)
compound.tags.add(*compound_tags)
for compound_tag in compound_tags:
CompoundTagJunctionModel.objects.get_or_create(
compound=compound,
compound_tag=compound_tag,
target=target,
)
if enumeration_method_obj is not None:
compound.enumeration_methods.add(enumeration_method_obj)
CompoundEnumerationMethodJunctionModel.objects.get_or_create(
compound=compound,
enumeration_method=enumeration_method_obj,
target=target,
)
if compound_created:
result.compounds_created += 1

Expand Down Expand Up @@ -1080,7 +1096,12 @@ def ingest_syndirella_elabs(
products = CompoundModel.objects.filter(pk__in=product_ids)
product_tags = CompoundTagService.tags_from_list(product_tag_list)
for compound in products:
compound.tags.add(*product_tags)
for compound_tag in product_tags:
CompoundTagJunctionModel.objects.get_or_create(
compound=compound,
compound_tag=compound_tag,
target=target,
)

# bulk register scaffold relationships

Expand Down
28 changes: 22 additions & 6 deletions hippo/designdb/sets/compound.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
ReactionModel,
RouteModel,
ScaffoldModel,
TargetModel,
)
from django.db.models import Count, Exists, OuterRef, Q, QuerySet
from django.db.models.query import ModelIterable
Expand Down Expand Up @@ -1287,6 +1288,8 @@ def write_CAR_csv(
def add_tag(
self,
tag: str,
*,
target: TargetModel,
) -> None:
"""Add this tag to every member of the set"""

Expand All @@ -1296,7 +1299,9 @@ def add_tag(

CompoundTagJunctionModel.objects.bulk_create(
[
CompoundTagJunctionModel(compound=compound, compound_tag=compound_tag)
CompoundTagJunctionModel(
compound=compound, compound_tag=compound_tag, target=target
)
for compound in self._queryset
],
ignore_conflicts=True,
Expand Down Expand Up @@ -1503,14 +1508,25 @@ def inchikeys(self) -> list[str]:
"""Returns the inchikeys of compounds in this set"""
return list(self._queryset.values_list('compound_inchikey', flat=True))

def get_tags(self, target: TargetModel | None = None) -> set[str]:
"""Returns the set of unique tags present in this compound set

:param target: Optionally restrict to tags assigned under this
:class:`.TargetModel`, defaults to ``None`` (tags across all targets)
"""
junctions = CompoundTagJunctionModel.objects.filter(compound_id__in=self.ids)
if target is not None:
junctions = junctions.filter(target=target)
return set(
junctions.values_list(
'compound_tag__compound_tag_name', flat=True
).distinct()
)

@property
def tags(self) -> set[str]:
"""Returns the set of unique tags present in this compound set"""
return set(
CompoundTagJunctionModel.objects.filter(compound_id__in=self.ids)
.values_list('compound_tag__compound_tag_name', flat=True)
.distinct()
)
return self.get_tags()

@property
def num_poses(self) -> int:
Expand Down
6 changes: 4 additions & 2 deletions images/xchem-designdb/init-db/01_schema.sql
Original file line number Diff line number Diff line change
Expand Up @@ -206,10 +206,11 @@ CREATE TABLE IF NOT EXISTS designdb.compound_tags (
-- New table
CREATE TABLE IF NOT EXISTS designdb.has_compound_tags (
compound_id BIGINT NOT NULL REFERENCES designdb.compounds (id) ON DELETE CASCADE,
target_id BIGINT NOT NULL REFERENCES designdb.targets (id) ON DELETE CASCADE,
compound_tag_id BIGINT NOT NULL REFERENCES designdb.compound_tags (id) ON DELETE CASCADE,
created_on TIMESTAMPTZ DEFAULT now(),
updated_on TIMESTAMPTZ DEFAULT now(),
PRIMARY KEY (compound_id, compound_tag_id)
PRIMARY KEY (compound_id, compound_tag_id, target_id)
);

-- New table
Expand All @@ -229,10 +230,11 @@ CREATE TABLE IF NOT EXISTS designdb.enumeration_methods (
-- New table
CREATE TABLE IF NOT EXISTS designdb.has_enumeration_methods (
compound_id BIGINT NOT NULL REFERENCES designdb.compounds (id) ON DELETE CASCADE,
target_id BIGINT NOT NULL REFERENCES designdb.targets (id) ON DELETE CASCADE,
enumeration_method_id BIGINT NOT NULL REFERENCES designdb.enumeration_methods (id) ON DELETE CASCADE,
created_on TIMESTAMPTZ DEFAULT now(),
updated_on TIMESTAMPTZ DEFAULT now(),
PRIMARY KEY (compound_id, enumeration_method_id)
PRIMARY KEY (compound_id, enumeration_method_id, target_id)
);

-- New table
Expand Down
2 changes: 1 addition & 1 deletion uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading