Skip to content

Commit

Permalink
Merge pull request #245 from bento-platform/develop
Browse files Browse the repository at this point in the history
Version 2.2.0
  • Loading branch information
zxenia authored Jul 22, 2021
2 parents 2374c2b + c31b92d commit b89a4b8
Show file tree
Hide file tree
Showing 5 changed files with 159 additions and 7 deletions.
4 changes: 4 additions & 0 deletions chord_metadata_service/chord/tests/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
"TEST_SEARCH_QUERY_4",
"TEST_SEARCH_QUERY_5",
"TEST_SEARCH_QUERY_6",
"TEST_SEARCH_QUERY_7",
"TEST_SEARCH_QUERY_8",
"TEST_FHIR_SEARCH_QUERY",
]

Expand Down Expand Up @@ -243,4 +245,6 @@ def valid_phenotypic_feature(biosample=None, phenopacket=None):
TEST_SEARCH_QUERY_5 = ["#ico", ["#resolve", "phenotypic_features", "[item]", "type", "label"], "proptosis"]
TEST_SEARCH_QUERY_6 = ["#ico", ["#resolve", "biosamples", "[item]", "sampled_tissue", "label"],
"URINARY BLADDER"]
TEST_SEARCH_QUERY_7 = ["#eq", ["#resolve", "experiment_results", "[item]", "file_format"], "VCF"]
TEST_SEARCH_QUERY_8 = ["#ico", ["#resolve", "experiment_type"], "chromatin"]
TEST_FHIR_SEARCH_QUERY = {"query": {"match": {"gender": "FEMALE"}}}
64 changes: 63 additions & 1 deletion chord_metadata_service/chord/tests/test_api_search.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,17 @@
from rest_framework.test import APITestCase

from chord_metadata_service.patients.models import Individual
from chord_metadata_service.phenopackets.models import Biosample, MetaData, Phenopacket, Procedure, PhenotypicFeature
from chord_metadata_service.experiments.models import Experiment, ExperimentResult, Instrument
from chord_metadata_service.phenopackets.tests.constants import (
VALID_PROCEDURE_1,
valid_biosample_1,
valid_biosample_2,
VALID_META_DATA_1,
)
from chord_metadata_service.phenopackets.models import Biosample, MetaData, Phenopacket, Procedure, PhenotypicFeature
from chord_metadata_service.experiments.tests.constants import (
valid_experiment, valid_experiment_result, valid_instrument
)

from chord_metadata_service.chord.tests.es_mocks import SEARCH_SUCCESS
from .constants import (
Expand All @@ -29,6 +33,8 @@
TEST_SEARCH_QUERY_4,
TEST_SEARCH_QUERY_5,
TEST_SEARCH_QUERY_6,
TEST_SEARCH_QUERY_7,
TEST_SEARCH_QUERY_8,
TEST_FHIR_SEARCH_QUERY,
)
from ..models import Project, Dataset, TableOwnership, Table
Expand Down Expand Up @@ -153,6 +159,18 @@ def setUp(self) -> None:
**valid_phenotypic_feature(phenopacket=self.phenopacket)
)

# table for experiments metadata
to_exp = TableOwnership.objects.create(table_id=uuid.uuid4(), service_id=uuid.uuid4(),
service_artifact="experiments", dataset=self.dataset)
self.t_exp = Table.objects.create(ownership_record=to_exp, name="Table 2", data_type=DATA_TYPE_EXPERIMENT)

# add Experiments metadata and link to self.biosample_1
self.instrument = Instrument.objects.create(**valid_instrument())
self.experiment_result = ExperimentResult.objects.create(**valid_experiment_result())
self.experiment = Experiment.objects.create(**valid_experiment(
biosample=self.biosample_1, instrument=self.instrument, table=self.t_exp))
self.experiment.experiment_results.set([self.experiment_result])

def test_common_search_1(self):
# No body
r = self.client.post(reverse("search"))
Expand Down Expand Up @@ -330,6 +348,50 @@ def test_private_table_search_9(self):
self.assertEqual(len(c["results"]), 1)
self.assertEqual(len(c["results"][0]["biosamples"]), 2)

def test_private_search_10_experiment(self):
# Valid search with result
r = self.client.post(reverse("private-search"), data=json.dumps({
"data_type": DATA_TYPE_EXPERIMENT,
"query": TEST_SEARCH_QUERY_7
}), content_type="application/json")
self.assertEqual(r.status_code, status.HTTP_200_OK)
c = r.json()
self.assertIn(str(self.t_exp.identifier), c["results"])
self.assertEqual(c["results"][str(self.t_exp.identifier)]["data_type"], DATA_TYPE_EXPERIMENT)
self.assertEqual(self.experiment.id, c["results"][str(self.t_exp.identifier)]["matches"][0]["id"])
self.assertEqual(len(c["results"][str(self.t_exp.identifier)]["matches"]), 1)
self.assertEqual(c["results"][str(self.t_exp.identifier)]["matches"][0]["id"], "experiment:1")
self.assertEqual(c["results"][str(self.t_exp.identifier)]["matches"][0]["study_type"],
"Whole genome Sequencing")
self.assertEqual(c["results"][str(self.t_exp.identifier)]["matches"][0]["molecule"], "total RNA")
self.assertEqual(len(c["results"][str(self.t_exp.identifier)]["matches"][0]["experiment_results"]), 1)
self.assertEqual(
c["results"][str(self.t_exp.identifier)]["matches"][0]["experiment_results"][0]["file_format"], "VCF"
)
self.assertEqual(c["results"][str(self.t_exp.identifier)]["matches"][0]["instrument"]["identifier"],
"instrument:01")
self.assertEqual(c["results"][str(self.t_exp.identifier)]["matches"][0]["instrument"]["platform"],
"Illumina")
self.assertEqual(c["results"][str(self.t_exp.identifier)]["matches"][0]["instrument"]["model"],
"Illumina HiSeq 4000")
self.assertEqual(c["results"][str(self.t_exp.identifier)]["matches"][0]["instrument"]["extra_properties"],
{"date": "2021-06-21"})

def test_private_search_11_experiment(self):
# Valid search with result, case-insensitive search for experiment_type
r = self.client.post(reverse("private-search"), data=json.dumps({
"data_type": DATA_TYPE_EXPERIMENT,
"query": TEST_SEARCH_QUERY_8
}), content_type="application/json")
self.assertEqual(r.status_code, status.HTTP_200_OK)
c = r.json()
self.assertIn(str(self.t_exp.identifier), c["results"])
self.assertEqual(c["results"][str(self.t_exp.identifier)]["data_type"], DATA_TYPE_EXPERIMENT)
self.assertEqual(c["results"][str(self.t_exp.identifier)]["matches"][0]["experiment_type"],
"Chromatin Accessibility")

# TODO table search fr experiments

@patch('chord_metadata_service.chord.views_search.es')
def test_fhir_search(self, mocked_es):
mocked_es.search.return_value = SEARCH_SUCCESS
Expand Down
91 changes: 88 additions & 3 deletions chord_metadata_service/experiments/search_schemas.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,63 @@
search_optional_eq,
search_optional_str,
tag_schema_with_search_properties,
merge_schema_dictionaries
)
from chord_metadata_service.restapi.search_schemas import ONTOLOGY_SEARCH_SCHEMA


__all__ = ["EXPERIMENT_SEARCH_SCHEMA"]

EXPERIMENT_RESULT_SEARCH_SCHEMA = tag_schema_with_search_properties(schemas.EXPERIMENT_RESULT_SCHEMA, {
"properties": {
"identifier": {
"search": search_optional_eq(0)
},
"description": {
"search": search_optional_str(1)
},
"filename": {
"search": search_optional_str(2)
},
"file_format": {
"search": search_optional_eq(3)
},
"data_output_type": {
"search": search_optional_eq(4)
},
"usage": {
"search": search_optional_str(5)
},
},
"search": {
"database": {
"primary_key": models.ExperimentResult._meta.pk.column,
"relation": models.ExperimentResult._meta.db_table,
}
}
})

INSTRUMENT_SEARCH_SCHEMA = tag_schema_with_search_properties(schemas.INSTRUMENT_SCHEMA, {
"properties": {
"identifier": {
"search": search_optional_eq(0)
},
"platform": {
"search": search_optional_str(1)
},
"description": {
"search": search_optional_str(2)
},
"model": {
"search": search_optional_str(3)
},
},
"search": {
"database": {
"primary_key": models.Instrument._meta.pk.column,
"relation": models.Instrument._meta.db_table,
}
}
})

EXPERIMENT_SEARCH_SCHEMA = tag_schema_with_search_properties(schemas.EXPERIMENT_SCHEMA, {
"properties": {
Expand Down Expand Up @@ -41,9 +92,11 @@
"library_strategy": {
"search": search_optional_str(7),
},
# TODO: other_fields: ?
"biosample": {
"search": search_optional_eq(8, queryable="internal"),
"search": merge_schema_dictionaries(
search_optional_eq(8),
{"database": {"field": models.Experiment._meta.get_field("biosample").column}}
)
},
"extraction_protocol": {
"search": search_optional_str(9),
Expand All @@ -60,6 +113,38 @@
"library_layout": {
"search": search_optional_str(13),
},
# query example: ["#ico", ["#resolve", "instrument", "model"], "Illumina"]
"instrument": merge_schema_dictionaries(
INSTRUMENT_SEARCH_SCHEMA,
{"search": {"database": {
"relationship": {
"type": "MANY_TO_ONE",
"foreign_key": models.Experiment._meta.get_field("instrument").column
}
}}}),
# query example: ["#ico", ["#resolve", "experiment_results", "[item]", "description"], "VCF file"]
"experiment_results": {
"items": merge_schema_dictionaries(
EXPERIMENT_RESULT_SEARCH_SCHEMA,
{"search": {"database": {
"relationship": {
"type": "MANY_TO_ONE",
"foreign_key": "experimentresult_id" # TODO: No hard-code, from M2M
}
}}}
),
"search": {
"database": {
"relation": models.Experiment._meta.get_field(
"experiment_results").remote_field.through._meta.db_table,
"relationship": {
"type": "ONE_TO_MANY",
"parent_foreign_key": "experiment_id", # TODO: No hard-code
"parent_primary_key": models.Experiment._meta.pk.column
}
}
}
},
},
"search": {
"database": {
Expand Down
5 changes: 3 additions & 2 deletions chord_metadata_service/experiments/tests/constants.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
def valid_experiment(biosample, instrument=None):
def valid_experiment(biosample, instrument=None, table=None):
return {
"id": "experiment:1",
"study_type": "Whole genome Sequencing",
Expand All @@ -15,7 +15,8 @@ def valid_experiment(biosample, instrument=None):
"qc_flags": ["flag 1", "flag 2"],
"extra_properties": {"some_field": "value"},
"biosample": biosample,
"instrument": instrument
"instrument": instrument,
"table": table
}


Expand Down
2 changes: 1 addition & 1 deletion chord_metadata_service/package.cfg
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
[package]
name = katsu
version = 2.1.2
version = 2.2.0
authors = Ksenia Zaytseva, David Lougheed, Simon Chénard, Romain Grégoire

0 comments on commit b89a4b8

Please sign in to comment.