diff --git a/docs/conf.py b/docs/conf.py index ff15a4fb..af5831c3 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -13,16 +13,16 @@ import os import sys -sys.path.insert(0, os.path.abspath('../')) +sys.path.insert(0, os.path.abspath("../")) # -- Project information ----------------------------------------------------- -project = 'sssom-py' -copyright = '2021, Chris Mungall; Nicolas Matentzoglu; Harshad Hegde' -author = 'Chris Mungall; Nicolas Matentzoglu; Harshad Hegde' +project = "sssom-py" +copyright = "2021, Chris Mungall; Nicolas Matentzoglu; Harshad Hegde" +author = "Chris Mungall; Nicolas Matentzoglu; Harshad Hegde" # The full version, including alpha/beta/rc tags -release = '0.3.6-dev' +release = "0.3.6-dev" # -- General configuration --------------------------------------------------- @@ -30,15 +30,15 @@ # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. extensions = [ - 'sphinx.ext.autodoc', - 'sphinx.ext.githubpages', - 'sphinx_rtd_theme', - 'sphinx_click', - 'sphinx.ext.napoleon', - 'sphinx.ext.viewcode', - 'sphinx.ext.todo', - 'sphinx.ext.coverage', - 'recommonmark' + "sphinx.ext.autodoc", + "sphinx.ext.githubpages", + "sphinx_rtd_theme", + "sphinx_click", + "sphinx.ext.napoleon", + "sphinx.ext.viewcode", + "sphinx.ext.todo", + "sphinx.ext.coverage", + "recommonmark", ] # Napoleon settings @@ -55,24 +55,24 @@ napoleon_use_rtype = True # Add any paths that contain templates here, relative to this directory. -templates_path = ['_templates'] +templates_path = ["_templates"] # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. # This pattern also affects html_static_path and html_extra_path. -exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store', 'setup.cfg'] +exclude_patterns = ["_build", "Thumbs.db", ".DS_Store", "setup.cfg"] # -- Options for HTML output ------------------------------------------------- # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. # -html_theme = 'sphinx_rtd_theme' +html_theme = "sphinx_rtd_theme" # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ['_static'] +html_static_path = ["_static"] html_theme_options = { "use_edit_page_button": True, @@ -84,5 +84,5 @@ "github_repo": "sssom-py", "github_version": "master/docs/", "display_github": True, # Add 'Edit on Github' link instead of 'View page source' - "conf_py_path": "/master/docs/", # Path in the checkout to the docs root + "conf_py_path": "/master/docs/", # Path in the checkout to the docs root } diff --git a/sssom/constants.py b/sssom/constants.py index 4d1283db..16dcccc6 100644 --- a/sssom/constants.py +++ b/sssom/constants.py @@ -19,17 +19,25 @@ # SCHEMA_VIEW = package_schemaview("sssom_schema") -OWL_EQUIV_CLASS = "http://www.w3.org/2002/07/owl#equivalentClass" +OWL_EQUIV_CLASS_URI = "http://www.w3.org/2002/07/owl#equivalentClass" RDFS_SUBCLASS_OF_URI = "http://www.w3.org/2000/01/rdf-schema#subClassOf" +RDF_TYPE_URI = "http://www.w3.org/1999/02/22-rdf-syntax-ns#type" +SSSOM_SUPERCLASS_OF_URI = "http://w3id.org/sssom/superClassOf" +SKOS_EXACT_MATCH_URI = "http://www.w3.org/2004/02/skos/core#exactMatch" +SKOS_CLOSE_MATCH_URI = "http://www.w3.org/2004/02/skos/core#closeMatch" +SKOS_BROAD_MATCH_URI = "http://www.w3.org/2004/02/skos/core#broadMatch" +SKOS_NARROW_MATCH_URI = "http://www.w3.org/2004/02/skos/core#narrowMatch" +OBO_HAS_DB_XREF_URI = "http://www.geneontology.org/formats/oboInOwl#hasDbXref" +SKOS_RELATED_MATCH_URI = "http://www.w3.org/2004/02/skos/core#relatedMatch" DEFAULT_MAPPING_PROPERTIES = [ - "http://www.geneontology.org/formats/oboInOwl#hasDbXref", - "http://www.w3.org/2004/02/skos/core#exactMatch", - "http://www.w3.org/2004/02/skos/core#broadMatch", - "http://www.w3.org/2004/02/skos/core#closeMatch", - "http://www.w3.org/2004/02/skos/core#narrowMatch", - "http://www.w3.org/2004/02/skos/core#relatedMatch", - OWL_EQUIV_CLASS, + SKOS_EXACT_MATCH_URI, + SKOS_CLOSE_MATCH_URI, + SKOS_BROAD_MATCH_URI, + SKOS_NARROW_MATCH_URI, + OBO_HAS_DB_XREF_URI, + SKOS_RELATED_MATCH_URI, + OWL_EQUIV_CLASS_URI, ] UNKNOWN_IRI = "http://w3id.org/sssom/unknown_prefix/" @@ -125,6 +133,7 @@ CROSS_SPECIES_NARROW_MATCH = "semapv:crossSpeciesNarrowMatch" CROSS_SPECIES_BROAD_MATCH = "semapv:crossSpeciesBroadMatch" RDF_SEE_ALSO = "rdfs:seeAlso" +RDF_TYPE = "rdf:type" SSSOM_SUPERCLASS_OF = "sssom:superClassOf" PREDICATE_LIST = [ diff --git a/sssom/parsers.py b/sssom/parsers.py index 10b90d65..0576376a 100644 --- a/sssom/parsers.py +++ b/sssom/parsers.py @@ -34,9 +34,17 @@ OBJECT_LABEL, OBJECT_SOURCE, OBJECT_SOURCE_ID, - OWL_EQUIV_CLASS, + OWL_EQUIV_CLASS_URI, PREDICATE_ID, + RDF_TYPE, + RDF_TYPE_URI, RDFS_SUBCLASS_OF, + SKOS_BROAD_MATCH, + SKOS_BROAD_MATCH_URI, + SKOS_EXACT_MATCH, + SKOS_EXACT_MATCH_URI, + SKOS_NARROW_MATCH, + SKOS_NARROW_MATCH_URI, SUBJECT_ID, SUBJECT_LABEL, SUBJECT_SOURCE, @@ -667,7 +675,7 @@ def from_obographs( mdict[PREDICATE_ID] = curie_from_uri(predicate_id, prefix_map) mdict[MAPPING_JUSTIFICATION] = MAPPING_JUSTIFICATION_UNSPECIFIED mlist.append(Mapping(**mdict)) - if "equivalentNodesSets" in g and OWL_EQUIV_CLASS in mapping_predicates: + if "equivalentNodesSets" in g and OWL_EQUIV_CLASS_URI in mapping_predicates: for equivalents in g["equivalentNodesSets"]: if "nodeIds" in equivalents: for ec1 in equivalents["nodeIds"]: @@ -677,7 +685,7 @@ def from_obographs( mdict[SUBJECT_ID] = curie_from_uri(ec1, prefix_map) mdict[OBJECT_ID] = curie_from_uri(ec2, prefix_map) mdict[PREDICATE_ID] = curie_from_uri( - OWL_EQUIV_CLASS, prefix_map + OWL_EQUIV_CLASS_URI, prefix_map ) mdict[ MAPPING_JUSTIFICATION @@ -817,8 +825,27 @@ def _cell_element_values( mdict[CONFIDENCE] = child.firstChild.nodeValue elif child.nodeName == "relation": relation = child.firstChild.nodeValue - if (relation == "=") and (OWL_EQUIV_CLASS in mapping_predicates): - mdict[PREDICATE_ID] = "owl:equivalentClass" + if (relation == "=") and ( + SKOS_EXACT_MATCH_URI in mapping_predicates + ): + mdict[PREDICATE_ID] = SKOS_EXACT_MATCH + elif (relation == "<") and ( + SKOS_BROAD_MATCH_URI in mapping_predicates + ): + mdict[PREDICATE_ID] = SKOS_BROAD_MATCH + elif (relation == ">") and ( + SKOS_NARROW_MATCH_URI in mapping_predicates + ): + mdict[PREDICATE_ID] = SKOS_NARROW_MATCH + # elif (relation == "%") and (SOMETHING in mapping_predicates) + # # Incompatible. + # pass + # elif (relation == "HasInstance") and (SOMETHING in mapping_predicates): + # pass + elif (relation == "InstanceOf") and ( + RDF_TYPE_URI in mapping_predicates + ): + mdict[PREDICATE_ID] = RDF_TYPE else: logging.warning(f"{relation} not a recognised relation type.") else: diff --git a/sssom/util.py b/sssom/util.py index 8396f972..b417d0ec 100644 --- a/sssom/util.py +++ b/sssom/util.py @@ -1440,7 +1440,7 @@ def get_all_prefixes(msdf: MappingSetDataFrame) -> list: # print( # f"Slot '{slot}' has an incorrect value: {msdf.metadata[slot]}" # ) - raise ValidationError( + logging.warning( f"Slot '{slot}' has an incorrect value: {msdf.metadata[slot]}" ) prefix_list.append(get_prefix_from_curie(msdf.metadata[slot])) diff --git a/sssom/validators.py b/sssom/validators.py index 3e1cf90b..d84d0a96 100644 --- a/sssom/validators.py +++ b/sssom/validators.py @@ -83,7 +83,7 @@ def check_all_prefixes_in_curie_map(msdf: MappingSetDataFrame) -> None: missing_prefixes = [] for pref in prefixes: - if pref not in list(msdf.prefix_map.keys()): + if pref != "" and pref not in list(msdf.prefix_map.keys()): missing_prefixes.append(pref) if missing_prefixes: raise ValidationError( diff --git a/tests/data/oaei-ordo-hp.yaml b/tests/data/oaei-ordo-hp.yaml new file mode 100644 index 00000000..49e68b62 --- /dev/null +++ b/tests/data/oaei-ordo-hp.yaml @@ -0,0 +1,2 @@ +license: "https://w3id.org/sssom/license/unspecified" +mapping_set_id: "https://w3id.org/sssom/sssompy/tests/oeai-ordo-hp" \ No newline at end of file diff --git a/tests/test_cli.py b/tests/test_cli.py index c6feddb7..1fd38e71 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -47,9 +47,11 @@ def test_cli_single_input(self): # Initially returned 2 tsv and 1 rdf. The RDF failed test test_cases = get_all_test_cases() for test in test_cases: - self.run_convert(runner, test) - if test.inputformat == "tsv": + if test.inputformat == "alignment-api-xml": + self.run_parse(runner, test) + elif test.inputformat == "tsv": # These test only run on TSV inputs + self.run_convert(runner, test) self.run_validate(runner, test) self.run_parse(runner, test) @@ -123,7 +125,7 @@ def run_parse(self, runner: CliRunner, test_case: SSSOMTestCase) -> Result: ] if test_case.metadata_file: params.append("--metadata") - params.append(test_case.metadata_file) + params.append(data_dir / test_case.metadata_file) result = runner.invoke(parse, params) self.run_successful(result, test_case) diff --git a/tests/test_config.yaml b/tests/test_config.yaml index 63506e6a..21b333b5 100644 --- a/tests/test_config.yaml +++ b/tests/test_config.yaml @@ -38,18 +38,20 @@ tests: # HP: "http://purl.obolibrary.org/obo/HP_" # ORDO: "http://www.orpha.net/ORDO/Orphanet_" # oboInOwl: "http://www.geneontology.org/formats/oboInOwl#" - # - filename: "oaei-ordo-hp.rdf" - # inputformat: "alignment-api-xml" - # ct_json_elements: 1293 - # ct_data_frame_rows: 646 - # ct_graph_queries_owl: - # query_count_equivalent_classes: 646 - # ct_graph_queries_rdf: - # query_count_equivalent_classes: 646 - # curie_map: - # HP: "http://purl.obolibrary.org/obo/HP_" - # ORDO: "http://www.orpha.net/ORDO/Orphanet_" - # oboInOwl: "http://www.geneontology.org/formats/oboInOwl#" + - filename: "oaei-ordo-hp.rdf" + inputformat: "alignment-api-xml" + multiple_input: False + ct_json_elements: 7 + ct_data_frame_rows: 646 + ct_graph_queries_owl: + query_count_equivalent_classes: 0 + ct_graph_queries_rdf: + query_count_equivalent_classes: 0 + curie_map: + HP: "http://purl.obolibrary.org/obo/HP_" + ORDO: "http://www.orpha.net/ORDO/Orphanet_" + oboInOwl: "http://www.geneontology.org/formats/oboInOwl#" + metadata_file: "oaei-ordo-hp.yaml" queries: query_count_equivalent_classes: > SELECT DISTINCT ?e1 ?e2 WHERE { diff --git a/tests/test_conversion.py b/tests/test_conversion.py index 76b69955..3a2920ad 100644 --- a/tests/test_conversion.py +++ b/tests/test_conversion.py @@ -6,6 +6,7 @@ import unittest from typing import Dict +import yaml from rdflib import Graph from sssom.parsers import get_parsing_function, to_mapping_set_document @@ -23,6 +24,7 @@ write_table, ) +from .constants import data_dir from .test_data import SSSOMTestCase, get_all_test_cases @@ -36,7 +38,12 @@ def test_conversion(self): for test in test_cases: with self.subTest(test=test.id): read_func = get_parsing_function(test.inputformat, test.filepath) - msdf = read_func(test.filepath, prefix_map=test.prefix_map) + if test.metadata_file: + with open(data_dir / test.metadata_file, "r") as f: + meta = yaml.safe_load(f) + else: + meta = None + msdf = read_func(test.filepath, prefix_map=test.prefix_map, meta=meta) mdoc = to_mapping_set_document(msdf) logging.info(f"Testing {test.filepath}") self.assertEqual(