Skip to content
Draft
Show file tree
Hide file tree
Changes from 16 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
768118c
First version of added namespace search in get_by_label
francescalb Mar 14, 2025
bcafad0
Corrected namespace search
francescalb Mar 14, 2025
79acb31
Updated so that emmo-inferred is given emmo as prefix (as prev)
francescalb Mar 14, 2025
dd99912
Updated test_patch to new emmo
francescalb Mar 14, 2025
3390620
Updated graph to have default for emmorelations
francescalb Mar 14, 2025
d5a6ea5
test_load and test_save updated
francescalb Mar 14, 2025
00e8d9a
Updated excelparser-tests with emmo-1.0.0
francescalb Mar 14, 2025
3aadfee
Updated redirections_test
francescalb Mar 14, 2025
6782a73
Update documentation test.
francescalb Mar 14, 2025
652951a
Test_save updated
francescalb Mar 14, 2025
d5ab563
Update ontopy/ontology.py
francescalb Mar 14, 2025
04b46f9
Update ontopy/ontology.py
francescalb Mar 14, 2025
46926c6
Update ontopy/ontology.py
francescalb Mar 14, 2025
64d0f8d
Merge branch 'flb/emmo_1.0.0_released' into flb/get_by_label_w_namespace
francescalb Mar 14, 2025
0b96a02
pre-commit
francescalb Mar 14, 2025
172af04
Merge branch 'flb/emmo_1.0.0_released' into flb/get_by_label_w_namespace
francescalb Mar 14, 2025
5f4b4ec
just temporarily push
francescalb Mar 18, 2025
f106279
Added possibility of specifying iri in new_entity
francescalb Mar 20, 2025
861a348
pylint fixes and docs corrections
francescalb Mar 20, 2025
5d47dde
Merge branch 'flb/specifiy_iri_new_entity' into flb/get_by_label_w_na…
francescalb Mar 20, 2025
8a13a0d
Merge branch 'master' into flb/get_by_label_w_namespace
jesper-friis May 29, 2025
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
4 changes: 1 addition & 3 deletions examples/emmodoc/classes.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,11 +54,10 @@ branch of mereotopology.
%BRANCHDOC MathematicalModel
%BRANCHDOC MathematicalOperator
%BRANCHDOC Metrological
%BRANCHDOC PhysicalDimension rankdir=RL
%BRANCHDOC hasMetrologicalReference rankdir=RL
%BRANCHDOC PhysicalQuantity
%BRANCHDOC Number
%BRANCHDOC MeasurementUnit
%BRANCHDOC UTF8
%BRANCHDOC SIBaseUnit
%BRANCHDOC SISpecialUnit rankdir=RL
%BRANCHDOC PrefixedUnit
Expand All @@ -71,7 +70,6 @@ branch of mereotopology.
%BRANCHDOC Reductionistic
%BRANCHDOC Expression

%BRANCHDOC Physicalistic
%BRANCHDOC ElementaryParticle
#%BRANCHDOC Subatomic
%BRANCHDOC Matter
Expand Down
2 changes: 1 addition & 1 deletion examples/emmodoc/emmo.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,4 @@
%BRANCHFIG EMMORelation caption='The complete taxonomy of EMMO relations.' terminated=0 relations=all edgelabels=0

%HEADER "The taxonomy of EMMO classes" level=2
%BRANCHFIG EMMO caption='The almost complete taxonomy of EMMO classes. Only physical quantities and constants are left out.' terminated=0 relations=isA edgelabels=0 leaves=PhysicalDimension,BaseQuantity,DerivedQuantity,ExactConstant,MeasuredConstant,SIBaseUnit,SISpecialUnit,MetricPrefix,UTF8
%BRANCHFIG EMMO caption='The almost complete taxonomy of EMMO classes. Only physical quantities and constants are left out.' terminated=0 relations=isA edgelabels=0 leaves=hasMetrologicalReference,BaseQuantity,DerivedQuantity,ExactConstant,MeasuredConstant,SIBaseUnit,SISpecialUnit,MetricPrefix
3 changes: 2 additions & 1 deletion ontopy/excelparser.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import pandas as pd
import numpy as np
import pyparsing
import defusedxml.ElementTree as ET

import ontopy
from ontopy import get_ontology
Expand Down Expand Up @@ -521,7 +522,7 @@ def get_metadata_from_dataframe( # pylint: disable=too-many-locals,too-many-bra
try:
cat = read_catalog(location.rsplit("/", 1)[0])
catalog.update(cat)
except ReadCatalogError:
except (ReadCatalogError, ET.ParseError): # Issue 840
warnings.warn(f"Catalog for {imported} not found.")
locations.add(location)
# set defined prefix
Expand Down
3 changes: 3 additions & 0 deletions ontopy/graph.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,9 @@
"hasOutput": {"color": "darkviolet", "style": "dotted"},
"hasInput": {"color": "darkviolet"},
"hasTemporaryParticipant": {"color": "darkviolet", "style": "dashed"},
"refersTo": {"color": "cyan", "style": "dotted"},
"hasReferent": {"color": "cyan"},
"providesInterpretation": {"color": "pink", "style": "dashed"},
},
"inverse": {"arrowhead": "inv"},
"default_dataprop": {"color": "green", "constraint": "false"},
Expand Down
172 changes: 109 additions & 63 deletions ontopy/ontology.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,18 +110,13 @@ def get_ontology(
base_iri = base_iri.as_uri() if isinstance(base_iri, Path) else base_iri

if base_iri == "emmo":
base_iri = (
"http://emmo-repo.github.io/versions/1.0.0-beta4/emmo.ttl"
)
base_iri = "https://w3id.org/emmo/"
elif base_iri == "emmo-inferred":
base_iri = (
"https://emmo-repo.github.io/versions/1.0.0-beta4/"
"emmo-inferred.ttl"
)
base_iri = "https://w3id.org/emmo/inferred"
elif base_iri == "emmo-development":
base_iri = (
"https://emmo-repo.github.io/versions/1.0.0-beta5/"
"emmo-inferred.ttl"
"https://raw.githubusercontent.com/emmo-repo/EMMO/"
"refs/heads/dev/emmo.ttl"
)

if base_iri in self.ontologies:
Expand Down Expand Up @@ -317,33 +312,42 @@ def get_by_label(
*,
label_annotations: str = None,
prefix: str = None,
namespace: str = None,
imported: bool = True,
colon_in_label: bool = None,
):
"""Returns entity with label annotation `label`.

Arguments:
label: label so search for.
May be written as 'label' or 'prefix:label'.
get_by_label('prefix:label') ==
get_by_label('label', prefix='prefix').
label_annotations: a sequence of label annotation names to look up.
Defaults to the `label_annotations` property.
prefix: if provided, it should be the last component of
the base iri of an ontology (with trailing slash (/) or hash
(#) stripped off). The search for a matching label will be
limited to this namespace.
imported: Whether to also look for `label` in imported ontologies.
colon_in_label: Whether to accept colon (:) in a label or name-part
of IRI. Defaults to the `colon_in_label` property of `self`.
Setting this true cannot be combined with `prefix`.
label: label so search for.
May be written as 'label' or 'prefix:label'
get_by_label('prefix:label') is equivalent to
searching for both
get_by_label('label', prefix='prefix') and
get_by_label('label', namespace='prefix')
label_annotations: a sequence of label annotation names to look up.
Defaults to the `label_annotations` property.
prefix: if provided, it should be the last component of
the base iri of an ontology (with trailing slash (/) or hash
(#) stripped off). The search for a matching label will be
limited to this ontology. `prefix` is ignored if `namespace`
is provided.
namespace: if provided, it should be the namespace of the entity.
It can be provided either as the whole namespace or only as the
last 'word' in the namespace, i.e. what is defined as the
namespace.name. `namespace` takes precedence over `prefix`.
imported: Whether to also look for `label` in imported ontologies.
colon_in_label: Whether to accept colon (:) in a label or name-part
of IRI. Defaults to the `colon_in_label` property of `self`.
Setting this true cannot be combined with `prefix`.

If several entities have the same label, only the one which is
found first is returned.Use get_by_label_all() to get all matches.

Note, if different prefixes are provided in the label and via
the `prefix` argument a warning will be issued and the
`prefix` argument will take precedence.
Note, if namespace is provided directly in the first argument as
'namespace:label' it will be used as namespace and
any value given to the `namespace` argument will be
ignored.

A NoSuchLabelError is raised if `label` cannot be found.
"""
Expand All @@ -358,23 +362,34 @@ def get_by_label(

if colon_in_label is None:
colon_in_label = self._colon_in_label
if colon_in_label:
if prefix:
raise ValueError(
"`prefix` cannot be combined with `colon_in_label`"
if colon_in_label and prefix:
raise ValueError(
"`prefix` cannot be combined with `colon_in_label`"
)

splitlabel = label.split(":", 1)
if len(splitlabel) == 2 and not splitlabel[1].startswith("//"):
label = splitlabel[1]
if namespace and namespace != splitlabel[0]:
warnings.warn(
f"Namespace given both as argument ({namespace}) "
f"and in label as ({splitlabel[0]}). "
"Namespace given in argument is ignored. "
)
else:
splitlabel = label.split(":", 1)
if len(splitlabel) == 2 and not splitlabel[1].startswith("//"):
label = splitlabel[1]
if prefix and prefix != splitlabel[0]:
warnings.warn(
f"Prefix given both as argument ({prefix}) "
f"and in label ({splitlabel[0]}). "
"Prefix given in argument takes precedence. "
)
if not prefix:
prefix = splitlabel[0]
namespace = splitlabel[0]

if namespace:
entityset = self.get_by_label_all(
label,
label_annotations=label_annotations,
namespace=namespace,
)
if len(entityset) == 1:
return entityset.pop()
raise NoSuchLabelError(
f"No label annotations matches for '{label}' "
f"with prefix '{prefix}'."
)

if prefix:
entityset = self.get_by_label_all(
Expand All @@ -384,11 +399,6 @@ def get_by_label(
)
if len(entityset) == 1:
return entityset.pop()
if len(entityset) > 1:
raise AmbiguousLabelError(
f"Several entities have the same label '{label}' "
f"with prefix '{prefix}'."
)
raise NoSuchLabelError(
f"No label annotations matches for '{label}' "
f"with prefix '{prefix}'."
Expand Down Expand Up @@ -430,24 +440,30 @@ def get_by_label_all(
label,
label_annotations=None,
prefix=None,
namespace=None,
exact_match=False,
) -> "Set[Optional[owlready2.entity.EntityClass]]":
"""Returns set of entities with label annotation `label`.

Arguments:
label: label so search for.
May be written as 'label' or 'prefix:label'. Wildcard matching
using glob pattern is also supported if `exact_match` is set to
false.
label_annotations: a sequence of label annotation names to look up.
Defaults to the `label_annotations` property.
prefix: if provided, it should be the last component of
the base iri of an ontology (with trailing slash (/) or hash
(#) stripped off). The search for a matching label will be
limited to this namespace.
exact_match: Do not treat "*" and brackets as special characters
when matching. May be useful if your ontology has labels
containing such labels.
label: label so search for.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks like an extra indentation

May be written as 'label' or 'prefix:label'. Wildcard matching
using glob pattern is also supported if `exact_match` is set to
false.
label_annotations: a sequence of label annotation names to look up.
Defaults to the `label_annotations` property.
prefix: if provided, it should be the last component of
the base iri of an ontology (with trailing slash (/) or hash
(#) stripped off). The search for a matching label will be
limited to this ontology. `prefix` is ignored if `namespace`
is provided.
namespace: if provided, it should be the namespace of the entity.
It can be provided either as the whole namespace or only as the
last 'word' in the namespace, i.e. what is defined as the
namespace.name. `namespace` takes precedence over `prefix`.
exact_match: Do not treat "*" and brackets as special characters
when matching. May be useful if your ontology has labels
containing such labels.

Returns:
Set of all matching entities or an empty set if no matches
Expand Down Expand Up @@ -501,13 +517,27 @@ def get_by_label_all(
entities.update(
ent for ent in self.get_entities() if ent.name in matches
)
if namespace:
print("in namespace", namespace)
print("entities", entities)
for ent in entities:
print("ent.namespace", ent.namespace)
print("ent.namespace.name", ent.namespace.name)
print("namespace", namespace)
print(namespace in [ent.namespace.name, ent.namespace.base_iri])
return set(
ent
for ent in entities
if namespace in [ent.namespace.name, ent.namespace._base_iri]
)

if prefix:
return set(
ent
for ent in entities
if ent.namespace.ontology.prefix == prefix
)

return entities

def _to_storids(self, sequence, create_if_missing=False):
Expand Down Expand Up @@ -564,23 +594,40 @@ def remove_label_annotation(self, iri):

def set_common_prefix(
self,
iri_base: str = "http://emmo.info/emmo",
iri_base: str = "https://w3id.org/emmo/inferred",
prefix: str = "emmo",
visited: "Optional[Set]" = None,
) -> None:
"""Set a common prefix for all imported ontologies
with the same first part of the base_iri.

Note that this function might give unintended results.
I.e. if `https://w3id.org/emmo` is given as iri_base
all imported domain ontologies adhering to the
emmo standard for base_iri will be given the same
prefix as well as emmo itself.

The default is to set the prefix to emmo only for emmo-inferred.

Args:
iri_base: The start of the base_iri to look for. Defaults to
the emmo base_iri http://emmo.info/emmo
the emmo base_iri https://w3id.org/emmo/inferred
prefix: the desired prefix. Defaults to emmo.
visited: Ontologies to skip. Only intended for internal use.
"""
if visited is None:
visited = set()
if self.base_iri.startswith(iri_base):
self.prefix = prefix

# If importing emmo-inferred set prefix to emmo
if (
iri_base == "https://w3id.org/emmo/inferred"
and self.prefix == "inferred"
and prefix == "emmo"
and self.base_iri == "https://w3id.org/emmo#"
):
self.prefix = prefix
for onto in self.imported_ontologies:
if not onto in visited:
visited.add(onto)
Expand Down Expand Up @@ -1331,7 +1378,6 @@ def properties(self, imported=False):
)
for s in self._get_obj_triples_po_s(rdf_type, rdf_property):
if not s < 0:
# print(s, self._unabbreviate(s))
generator.append(self._unabbreviate(s))
# generator.append(self[self._unabbreviate(s)])
# generator.append(self.world._get_by_storid(s))
Expand Down
3 changes: 1 addition & 2 deletions tests/ontopy_tests/test_graph.py
Original file line number Diff line number Diff line change
Expand Up @@ -223,8 +223,7 @@ def test_emmo_graphs(emmo: "Ontology", tmpdir: "Path") -> None:
emmo.Index,
emmo.Subjective,
emmo.NominalProperty,
emmo.ConventionalQuantitativeProperty,
emmo.ModelledQuantitativeProperty,
emmo.ConventionalProperty,
emmo.Theorization,
emmo.Experiment,
emmo.Theory,
Expand Down
Loading
Loading