class AnnotationScore(Resource): annotation_scorer = AnnotationScorer(get_owlsim_api()) @api.expect(sufficiency_input) @api.marshal_with(sufficiency_output) def post(self): """ Get annotation score """ data = request.json phenotypes = [ feature['id'] for feature in data['features'] if feature['isPresent'] is True ] absent_phenotypes = [ feature['id'] for feature in data['features'] if feature['isPresent'] is False ] return AnnotationScore.annotation_scorer.get_annotation_sufficiency( profile=phenotypes, negated_classes=absent_phenotypes) @api.expect(score_get) @api.marshal_with(sufficiency_output) def get(self): """ Get annotation score """ input_args = score_get.parse_args() return AnnotationScore.annotation_scorer.get_annotation_sufficiency( profile=input_args['id'], negated_classes=input_args['absent_id'])
def setup_class(self): patch('ontobio.sim.api.owlsim2.get_owlsim_stats', return_value=(None, None)).start() self.ic_store = OwlSim2Api() self.annot_scorer = AnnotationScorer(self.ic_store) self.ic_store.statistics = IcStatistic(mean_mean_ic=6.82480, mean_sum_ic=120.89767, mean_cls=15.47425, max_max_ic=16.16108, max_sum_ic=6746.96160, individual_count=65309, mean_max_ic=9.51535) self.ic_store.category_statistics = { 'ear feature': IcStatistic( mean_mean_ic=7.55126, mean_sum_ic=26.60304, mean_cls=3.40207, max_max_ic=16.15508, max_sum_ic=613.22168, individual_count=6004, mean_max_ic=8.48152, descendants=['pointy ears', 'large ears', 'small ears']), 'skin feature': IcStatistic(mean_mean_ic=7.55126, mean_sum_ic=26.60304, mean_cls=3.40207, max_max_ic=16.15508, max_sum_ic=613.22168, individual_count=6004, mean_max_ic=8.48152, descendants=[ 'blue skin', 'orange skin', 'increased pigmentation' ]), } self.mock_ic_values = { 'pointy ears': 12.0021, 'large ears': 8.2345, 'small ears': 8.1536, 'blue skin': 10.12593, 'orange skin': 15.1592, 'increased pigmentation': 5.5926 } self.negation_weight = .23 self.category_weight = .33
from flask_restplus import Resource from flask import request from ontobio.sim.annotation_scorer import AnnotationScorer from ontobio.sim.api.owlsim2 import OwlSim2Api from biolink.api.restplus import api from biolink.datamodel.sim_serializers import sufficiency_input, sufficiency_output annotation_scorer = AnnotationScorer(OwlSim2Api()) score_get = api.parser() score_get.add_argument('id', action='append', help='Phenotype identifier (eg HP:0004935)') score_get.add_argument('absent_id', default=[], action='append', help='absent phenotype (eg HP:0002828)') class AnnotationScore(Resource): @api.expect(sufficiency_input) @api.marshal_with(sufficiency_output) def post(self): """ Get annotation score """ data = request.json phenotypes = [ feature['id'] for feature in data['features'] if feature['isPresent'] is True ]
class TestAnnotationSufficiency(): """ Unit tests for AnnotationScorer Mock data based on star trek example https://www.slideshare.net/mhaendel/patientled-deep-phenotyping-using-a- layfriendly-version-of-the-human-phenotype-ontology-90800501/5 """ @classmethod def setup_class(self): patch('ontobio.sim.api.owlsim2.get_owlsim_stats', return_value=(None, None)).start() self.ic_store = OwlSim2Api() self.annot_scorer = AnnotationScorer(self.ic_store) self.ic_store.statistics = IcStatistic(mean_mean_ic=6.82480, mean_sum_ic=120.89767, mean_cls=15.47425, max_max_ic=16.16108, max_sum_ic=6746.96160, individual_count=65309, mean_max_ic=9.51535) self.ic_store.category_statistics = { 'ear feature': IcStatistic( mean_mean_ic=7.55126, mean_sum_ic=26.60304, mean_cls=3.40207, max_max_ic=16.15508, max_sum_ic=613.22168, individual_count=6004, mean_max_ic=8.48152, descendants=['pointy ears', 'large ears', 'small ears']), 'skin feature': IcStatistic(mean_mean_ic=7.55126, mean_sum_ic=26.60304, mean_cls=3.40207, max_max_ic=16.15508, max_sum_ic=613.22168, individual_count=6004, mean_max_ic=8.48152, descendants=[ 'blue skin', 'orange skin', 'increased pigmentation' ]), } self.mock_ic_values = { 'pointy ears': 12.0021, 'large ears': 8.2345, 'small ears': 8.1536, 'blue skin': 10.12593, 'orange skin': 15.1592, 'increased pigmentation': 5.5926 } self.negation_weight = .23 self.category_weight = .33 @classmethod def teardown_class(self): self.annot_scorer = None self.ic_store = None def test_get_simple_score(self): """ Test ontobio.sim.sim_engine.InformationContentStore._get_simple_score no negation """ classes = ['blue skin', 'pointy ears'] negated_classes = [] simple_score = self.annot_scorer._get_simple_score( classes, negated_classes, self.ic_store.statistics.mean_mean_ic, self.ic_store.statistics.mean_max_ic, self.ic_store.statistics.mean_sum_ic, self.negation_weight, self.mock_ic_values) assert simple_score == 0.7276770236073753 def test_get_simple_score_w_negation(self): """ Test ontobio.sim.sim_engine.InformationContentStore._get_simple_score with negation """ classes = ['blue skin', 'pointy ears'] negated_classes = ['large ears', 'increased pigmentation'] simple_score = self.annot_scorer._get_simple_score( classes, negated_classes, self.ic_store.statistics.mean_mean_ic, self.ic_store.statistics.mean_max_ic, self.ic_store.statistics.mean_sum_ic, self.negation_weight, self.mock_ic_values) assert simple_score == 0.7364454115065521 def test_get_cat_score(self): """ Test ontobio.sim.sim_engine.InformationContentStore._get_categorical_score no negation """ classes = ['blue skin', 'pointy ears'] negated_classes = [] categories = ['ear feature', 'skin feature'] categorical_score = self.annot_scorer._get_categorical_score( classes, negated_classes, categories, self.negation_weight, self.mock_ic_values) assert categorical_score == 0.7002519289078384 def test_get_cat_score_w_negation(self): """ Test ontobio.sim.sim_engine.InformationContentStore._get_categorical_score with negation """ classes = ['blue skin', 'pointy ears'] negated_classes = ['large ears', 'increased pigmentation'] categories = ['ear feature', 'skin feature'] categorical_score = self.annot_scorer._get_categorical_score( classes, negated_classes, categories, self.negation_weight, self.mock_ic_values) assert categorical_score == 0.7201759238096741 def test_get_scaled_score(self): """ Test ontobio.sim.sim_engine.InformationContentStore._get_scaled_score """ simple_score = 0.73 categorical_score = 0.82 scaled_score = self.annot_scorer._get_scaled_score( simple_score, categorical_score, self.category_weight) assert scaled_score == 0.75233082706766907
class TestOwlSimIntegration(): """ Hodgepodge of integration tests for ontobio and owlsim2 to assist in development """ @classmethod def setup_class(self): self.owlsim2_api = OwlSim2Api() self.annot_scorer = AnnotationScorer(self.owlsim2_api) self.pheno_sim = PhenoSimEngine(self.owlsim2_api) @classmethod def teardown_class(self): self.annot_scorer = None self.pheno_sim = None self.owlsim2_api = None def test_stat_type(self): """ Test stat type """ assert isinstance(self.owlsim2_api.statistics, IcStatistic) def test_fetch_stats(self): """ Test that we're getting stats back and they're the correct type """ assert isinstance(self.owlsim2_api.statistics.mean_mean_ic, float) assert isinstance(self.owlsim2_api.statistics.individual_count, int) def test_fetch_ic(self): """ Fetch two classes that are parent-child and test that the child has a higher IC than the parent :return: """ classes = ['HP:0000739', 'HP:0000740'] ic_dict = self.owlsim2_api.get_profile_ic(classes) assert isinstance(ic_dict['HP:0000740'], float) assert ic_dict['HP:0000740'] > ic_dict['HP:0000739'] def test_get_annotation_suff(self): classes = ['HP:0000739', 'HP:0000740'] negated_classes = [] annot_suff = self.annot_scorer.get_annotation_sufficiency( classes, negated_classes) assert 0 < annot_suff.simple_score < 1 assert 0 < annot_suff.scaled_score < 1 assert 0 < annot_suff.categorical_score < 1 def test_sim_search(self): classes = ['HP:0000739', 'HP:0000740'] search_results = self.pheno_sim.search(classes) assert search_results.matches[0].rank == 1 assert 0 < search_results.matches[0].score < 100 assert search_results.matches[0].type in [ 'gene', 'phenotype', 'disease' ] assert search_results.matches[0].taxon.id is not None assert len(search_results.matches[0].pairwise_match) > 0 assert search_results.matches[0].pairwise_match[0].lcs.IC > 0 def test_sim_compare(self): """ Comparison where a disease is the reference """ classes_a = ['MONDO:0008199'] classes_b = [['HP:0002367', 'HP:0031466', 'HP:0007123']] compare_results = self.pheno_sim.compare(classes_a, classes_b) assert compare_results.query.reference.id == "MONDO:0008199" assert compare_results.query.reference.type == "disease" assert compare_results.query.reference.taxon.id == "NCBITaxon:9606" assert compare_results.matches[0].pairwise_match[ 0].match.id in classes_b[0] assert compare_results.matches[0].score > 0 def test_sim_compare_ind(self): """ Comparison where a disease is the query """ classes_a = ['HP:0002367', 'HP:0031466', 'HP:0007123'] classes_b = [['MONDO:0008199']] compare_results = self.pheno_sim.compare(classes_a, classes_b) assert compare_results.matches[0].id == "MONDO:0008199" assert compare_results.matches[0].type == "disease" assert compare_results.matches[0].taxon.id == "NCBITaxon:9606" assert compare_results.matches[0].score > 0 def test_sim_compare_multiple(self): """ Comparison against multiple profiles """ classes_a = ['HP:0002367', 'HP:0031466', 'HP:0007123'] classes_b = [['HP:0000716', 'HP:0011307'], ['HP:0001004']] compare_results = self.pheno_sim.compare(classes_a, classes_b) assert compare_results.query.target_ids[1][0].id == 'HP:0001004'
def setup_class(self): self.owlsim2_api = OwlSim2Api() self.annot_scorer = AnnotationScorer(self.owlsim2_api) self.pheno_sim = PhenoSimEngine(self.owlsim2_api)