Skip to content

Commit 844c0f4

Browse files
authored
fix: add identified_objects to _models.py (#2015)
* fix: add identified_objects to _models.py * add tests for identifiedobject _models.py
1 parent 8f8fedd commit 844c0f4

File tree

5 files changed

+139
-0
lines changed

5 files changed

+139
-0
lines changed

client/python/cryoet_data_portal/src/cryoet_data_portal/_codegen.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@
6969
"Frame": "Frame",
7070
"FrameAcquisitionFile": "FrameAcquisitionFile",
7171
"GainFile": "GainFile",
72+
"IdentifiedObject": "IdentifiedObject",
7273
"PerSectionAlignmentParameters": "PerSectionAlignmentParameters",
7374
"PerSectionParameters": "PerSectionParameters",
7475
"Run": "Run",

client/python/cryoet_data_portal/src/cryoet_data_portal/_models.py

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1195,6 +1195,64 @@ def get_by_id(cls, client: Client, id: int):
11951195
)
11961196

11971197

1198+
class IdentifiedObject(Model):
1199+
"""An ontology term/ID or accession code, state and description associated with a Run, describing cellular components that were visually identified, but not labeled, in a tomogram associated with the Run
1200+
1201+
Attributes:
1202+
id (int): Numeric identifier (May change!)
1203+
run (Run): The run this identified object is a part of
1204+
run_id (int): None
1205+
object_id (str): Gene Ontology Cellular Component identifier or UniProtKB accession for the identified object.
1206+
object_name (str): Name of the identified object (e.g. ribosome, nuclear pore complex, actin filament, membrane)
1207+
object_description (str): A textual description of the identified object, can be a longer description to include additional information not covered by the IdentifiedObject object name and state.
1208+
object_state (str): Molecule state of the identified object (e.g. open, closed)
1209+
"""
1210+
1211+
_gql_type: str = "IdentifiedObject"
1212+
_gql_root_field: str = "identifiedObjects"
1213+
1214+
id: int = IntField()
1215+
run: Run = ItemRelationship("Run", "run_id", "id")
1216+
run_id: int = IntField()
1217+
object_id: str = StringField()
1218+
object_name: str = StringField()
1219+
object_description: str = StringField()
1220+
object_state: str = StringField()
1221+
1222+
@classmethod
1223+
def find(
1224+
cls,
1225+
client: Client,
1226+
query_filters: Optional[Iterable[GQLExpression]] = None,
1227+
):
1228+
"""
1229+
Examples:
1230+
>>> identified_objects = IdentifiedObject.find(client, query_filters=[IdentifiedObject.run.name == "TS_026"])
1231+
1232+
Get all results for this type:
1233+
1234+
>>> identified_objects = IdentifiedObject.find(client)
1235+
"""
1236+
return super(IdentifiedObject, cls).find(client, query_filters)
1237+
1238+
find.__func__.__doc__ = Model.find.__func__.__doc__ + find.__func__.__doc__
1239+
1240+
@classmethod
1241+
def get_by_id(cls, client: Client, id: int):
1242+
"""
1243+
Examples:
1244+
Get an IdentifiedObject by ID:
1245+
1246+
>>> identified_object = IdentifiedObject.get_by_id(client, 10000)
1247+
>>> print(identified_object.id)
1248+
"""
1249+
return super(IdentifiedObject, cls).get_by_id(client, id)
1250+
1251+
get_by_id.__func__.__doc__ = (
1252+
Model.get_by_id.__func__.__doc__ + get_by_id.__func__.__doc__
1253+
)
1254+
1255+
11981256
class PerSectionAlignmentParameters(Model):
11991257
"""Map alignment parameters to tilt series frames
12001258
@@ -1339,6 +1397,7 @@ class Run(Model):
13391397
dataset_id (int): None
13401398
frames (List[Frame]): The frames of this run
13411399
gain_files (List[GainFile]): The gain files of this run
1400+
identified_objects (List[IdentifiedObject]): The identified objects of this run
13421401
frame_acquisition_files (List[FrameAcquisitionFile]): The frame acquisition files of this run
13431402
per_section_parameters (List[PerSectionParameters]): The per section parameters of this run
13441403
tiltseries (List[TiltSeries]): The tilt series of this run
@@ -1359,6 +1418,11 @@ class Run(Model):
13591418
dataset_id: int = IntField()
13601419
frames: List[Frame] = ListRelationship("Frame", "id", "run_id")
13611420
gain_files: List[GainFile] = ListRelationship("GainFile", "id", "run_id")
1421+
identified_objects: List[IdentifiedObject] = ListRelationship(
1422+
"IdentifiedObject",
1423+
"id",
1424+
"run_id",
1425+
)
13621426
frame_acquisition_files: List[FrameAcquisitionFile] = ListRelationship(
13631427
"FrameAcquisitionFile",
13641428
"id",
@@ -1951,6 +2015,7 @@ def download_everything(self, dest_path: Optional[str] = None):
19512015
Frame.setup()
19522016
FrameAcquisitionFile.setup()
19532017
GainFile.setup()
2018+
IdentifiedObject.setup()
19542019
PerSectionAlignmentParameters.setup()
19552020
PerSectionParameters.setup()
19562021
Run.setup()

client/python/cryoet_data_portal/tests/test_filters.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import pytest
22

33
from cryoet_data_portal import Run, Tomogram
4+
from cryoet_data_portal._models import IdentifiedObject
45

56

67
def test_basic_filters(client) -> None:
@@ -38,3 +39,38 @@ def test_filter_on_object_raises_exceptions(client) -> None:
3839
Run.find(client, [Run.annotations == 20001])
3940
with pytest.raises(Exception, match=match):
4041
Run.find(client, [Run.dataset == 20001])
42+
43+
44+
def test_identified_object_find(client) -> None:
45+
all_objects = IdentifiedObject.find(client)
46+
assert len(all_objects) == 3
47+
48+
ribosomes = IdentifiedObject.find(
49+
client,
50+
[IdentifiedObject.object_name == "ribosome"],
51+
)
52+
assert len(ribosomes) == 2
53+
for obj in ribosomes:
54+
assert obj.object_name == "ribosome"
55+
56+
go_objects = IdentifiedObject.find(
57+
client,
58+
[IdentifiedObject.object_id == "GO:0005739"],
59+
)
60+
assert len(go_objects) == 1
61+
assert go_objects[0].object_name == "mitochondrion"
62+
63+
64+
def test_identified_object_find_with_run_filter(client) -> None:
65+
run1_objects = IdentifiedObject.find(
66+
client,
67+
[IdentifiedObject.run.name == "RUN1"],
68+
)
69+
assert len(run1_objects) == 2
70+
71+
run2_objects = IdentifiedObject.find(
72+
client,
73+
[IdentifiedObject.run.name == "RUN2"],
74+
)
75+
assert len(run2_objects) == 1
76+
assert run2_objects[0].object_name == "ribosome"
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,18 @@
11
from cryoet_data_portal import Dataset
22
from cryoet_data_portal._client import Client
3+
from cryoet_data_portal._models import IdentifiedObject
34

45

56
def test_get_by_id(client: Client) -> None:
67
dataset = Dataset.get_by_id(client, 20001)
78
assert dataset.id == 20001
9+
10+
11+
def test_identified_object_get_by_id(client: Client) -> None:
12+
identified_object = IdentifiedObject.get_by_id(client, 30001)
13+
assert identified_object.id == 30001
14+
assert identified_object.object_id == "GO:0005840"
15+
assert identified_object.object_name == "ribosome"
16+
assert identified_object.object_description == "A large ribonucleoprotein complex"
17+
assert identified_object.object_state == "assembled"
18+
assert identified_object.run_id is not None

client/python/cryoet_data_portal/tests/test_infra/seed_db.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
from test_infra.factories.dataset_funding import DatasetFundingFactory
1717
from test_infra.factories.deposition import DepositionFactory
1818
from test_infra.factories.deposition_author import DepositionAuthorFactory
19+
from test_infra.factories.identified_object import IdentifiedObjectFactory
1920
from test_infra.factories.run import RunFactory
2021
from test_infra.factories.tiltseries import TiltseriesFactory
2122
from test_infra.factories.tomogram import TomogramFactory
@@ -489,6 +490,31 @@ def use_factoryboy() -> None:
489490
TomogramAuthorFactory.create(tomogram=tomo4, author_list_order=1)
490491
TomogramAuthorFactory.create(tomogram=tomo4, author_list_order=2)
491492

493+
IdentifiedObjectFactory.create(
494+
id=30001,
495+
run=r1,
496+
object_id="GO:0005840",
497+
object_name="ribosome",
498+
object_description="A large ribonucleoprotein complex",
499+
object_state="assembled",
500+
)
501+
IdentifiedObjectFactory.create(
502+
id=30002,
503+
run=r1,
504+
object_id="GO:0005739",
505+
object_name="mitochondrion",
506+
object_description="A semiautonomous organelle",
507+
object_state=None,
508+
)
509+
IdentifiedObjectFactory.create(
510+
id=30003,
511+
run=r2,
512+
object_id="GO:0005840",
513+
object_name="ribosome",
514+
object_description="A large ribonucleoprotein complex",
515+
object_state="assembled",
516+
)
517+
492518
FileFactory.update_file_ids()
493519

494520
session.commit()

0 commit comments

Comments
 (0)