From a79b8d2bd0cfebc83a5b4b7381d6c40ddb92be8b Mon Sep 17 00:00:00 2001
From: Kevin Schaper
Date: Fri, 3 Nov 2023 13:16:42 -0700
Subject: [PATCH 1/9] Added MappingResults & MappingInterface
---
backend/src/monarch_py/datamodels/model.py | 203 +++++++++++++-----
backend/src/monarch_py/datamodels/model.yaml | 6 +
.../interfaces/mapping_interface.py | 15 ++
frontend/src/api/model.ts | 17 +-
4 files changed, 190 insertions(+), 51 deletions(-)
create mode 100644 backend/src/monarch_py/interfaces/mapping_interface.py
diff --git a/backend/src/monarch_py/datamodels/model.py b/backend/src/monarch_py/datamodels/model.py
index ce8d75fcc..84b20d4b4 100644
--- a/backend/src/monarch_py/datamodels/model.py
+++ b/backend/src/monarch_py/datamodels/model.py
@@ -48,13 +48,19 @@ class Association(ConfiguredBaseModel):
category: Optional[str] = Field(None)
subject: str = Field(...)
original_subject: Optional[str] = Field(None)
- subject_namespace: Optional[str] = Field(None, description="""The namespace/prefix of the subject entity""")
- subject_category: Optional[str] = Field(None, description="""The category of the subject entity""")
+ subject_namespace: Optional[str] = Field(
+ None, description="""The namespace/prefix of the subject entity"""
+ )
+ subject_category: Optional[str] = Field(
+ None, description="""The category of the subject entity"""
+ )
subject_closure: Optional[List[str]] = Field(
default_factory=list,
description="""Field containing subject id and the ids of all of it's ancestors""",
)
- subject_label: Optional[str] = Field(None, description="""The name of the subject entity""")
+ subject_label: Optional[str] = Field(
+ None, description="""The name of the subject entity"""
+ )
subject_closure_label: Optional[List[str]] = Field(
default_factory=list,
description="""Field containing subject name and the names of all of it's ancestors""",
@@ -64,13 +70,19 @@ class Association(ConfiguredBaseModel):
predicate: str = Field(...)
object: str = Field(...)
original_object: Optional[str] = Field(None)
- object_namespace: Optional[str] = Field(None, description="""The namespace/prefix of the object entity""")
- object_category: Optional[str] = Field(None, description="""The category of the object entity""")
+ object_namespace: Optional[str] = Field(
+ None, description="""The namespace/prefix of the object entity"""
+ )
+ object_category: Optional[str] = Field(
+ None, description="""The category of the object entity"""
+ )
object_closure: Optional[List[str]] = Field(
default_factory=list,
description="""Field containing object id and the ids of all of it's ancestors""",
)
- object_label: Optional[str] = Field(None, description="""The name of the object entity""")
+ object_label: Optional[str] = Field(
+ None, description="""The name of the object entity"""
+ )
object_closure_label: Optional[List[str]] = Field(
default_factory=list,
description="""Field containing object name and the names of all of it's ancestors""",
@@ -109,11 +121,15 @@ class Association(ConfiguredBaseModel):
onset_qualifier: Optional[str] = Field(None)
sex_qualifier: Optional[str] = Field(None)
stage_qualifier: Optional[str] = Field(None)
- qualifiers_label: Optional[str] = Field(None, description="""The name of the frequency_qualifier entity""")
+ qualifiers_label: Optional[str] = Field(
+ None, description="""The name of the frequency_qualifier entity"""
+ )
qualifiers_namespace: Optional[str] = Field(
None, description="""The namespace/prefix of the frequency_qualifier entity"""
)
- qualifiers_category: Optional[str] = Field(None, description="""The category of the frequency_qualifier entity""")
+ qualifiers_category: Optional[str] = Field(
+ None, description="""The category of the frequency_qualifier entity"""
+ )
qualifiers_closure: Optional[List[str]] = Field(
default_factory=list,
description="""Field containing frequency_qualifier id and the ids of all of it's ancestors""",
@@ -122,7 +138,9 @@ class Association(ConfiguredBaseModel):
default_factory=list,
description="""Field containing frequency_qualifier name and the names of all of it's ancestors""",
)
- frequency_qualifier_label: Optional[str] = Field(None, description="""The name of the frequency_qualifier entity""")
+ frequency_qualifier_label: Optional[str] = Field(
+ None, description="""The name of the frequency_qualifier entity"""
+ )
frequency_qualifier_namespace: Optional[str] = Field(
None, description="""The namespace/prefix of the frequency_qualifier entity"""
)
@@ -137,11 +155,15 @@ class Association(ConfiguredBaseModel):
default_factory=list,
description="""Field containing frequency_qualifier name and the names of all of it's ancestors""",
)
- onset_qualifier_label: Optional[str] = Field(None, description="""The name of the onset_qualifier entity""")
+ onset_qualifier_label: Optional[str] = Field(
+ None, description="""The name of the onset_qualifier entity"""
+ )
onset_qualifier_namespace: Optional[str] = Field(
None, description="""The namespace/prefix of the onset_qualifier entity"""
)
- onset_qualifier_category: Optional[str] = Field(None, description="""The category of the onset_qualifier entity""")
+ onset_qualifier_category: Optional[str] = Field(
+ None, description="""The category of the onset_qualifier entity"""
+ )
onset_qualifier_closure: Optional[List[str]] = Field(
default_factory=list,
description="""Field containing onset_qualifier id and the ids of all of it's ancestors""",
@@ -150,11 +172,15 @@ class Association(ConfiguredBaseModel):
default_factory=list,
description="""Field containing onset_qualifier name and the names of all of it's ancestors""",
)
- sex_qualifier_label: Optional[str] = Field(None, description="""The name of the sex_qualifier entity""")
+ sex_qualifier_label: Optional[str] = Field(
+ None, description="""The name of the sex_qualifier entity"""
+ )
sex_qualifier_namespace: Optional[str] = Field(
None, description="""The namespace/prefix of the sex_qualifier entity"""
)
- sex_qualifier_category: Optional[str] = Field(None, description="""The category of the sex_qualifier entity""")
+ sex_qualifier_category: Optional[str] = Field(
+ None, description="""The category of the sex_qualifier entity"""
+ )
sex_qualifier_closure: Optional[List[str]] = Field(
default_factory=list,
description="""Field containing sex_qualifier id and the ids of all of it's ancestors""",
@@ -163,11 +189,15 @@ class Association(ConfiguredBaseModel):
default_factory=list,
description="""Field containing sex_qualifier name and the names of all of it's ancestors""",
)
- stage_qualifier_label: Optional[str] = Field(None, description="""The name of the stage_qualifier entity""")
+ stage_qualifier_label: Optional[str] = Field(
+ None, description="""The name of the stage_qualifier entity"""
+ )
stage_qualifier_namespace: Optional[str] = Field(
None, description="""The namespace/prefix of the stage_qualifier entity"""
)
- stage_qualifier_category: Optional[str] = Field(None, description="""The category of the stage_qualifier entity""")
+ stage_qualifier_category: Optional[str] = Field(
+ None, description="""The category of the stage_qualifier entity"""
+ )
stage_qualifier_closure: Optional[List[str]] = Field(
default_factory=list,
description="""Field containing stage_qualifier id and the ids of all of it's ancestors""",
@@ -225,13 +255,19 @@ class DirectionalAssociation(Association):
category: Optional[str] = Field(None)
subject: str = Field(...)
original_subject: Optional[str] = Field(None)
- subject_namespace: Optional[str] = Field(None, description="""The namespace/prefix of the subject entity""")
- subject_category: Optional[str] = Field(None, description="""The category of the subject entity""")
+ subject_namespace: Optional[str] = Field(
+ None, description="""The namespace/prefix of the subject entity"""
+ )
+ subject_category: Optional[str] = Field(
+ None, description="""The category of the subject entity"""
+ )
subject_closure: Optional[List[str]] = Field(
default_factory=list,
description="""Field containing subject id and the ids of all of it's ancestors""",
)
- subject_label: Optional[str] = Field(None, description="""The name of the subject entity""")
+ subject_label: Optional[str] = Field(
+ None, description="""The name of the subject entity"""
+ )
subject_closure_label: Optional[List[str]] = Field(
default_factory=list,
description="""Field containing subject name and the names of all of it's ancestors""",
@@ -241,13 +277,19 @@ class DirectionalAssociation(Association):
predicate: str = Field(...)
object: str = Field(...)
original_object: Optional[str] = Field(None)
- object_namespace: Optional[str] = Field(None, description="""The namespace/prefix of the object entity""")
- object_category: Optional[str] = Field(None, description="""The category of the object entity""")
+ object_namespace: Optional[str] = Field(
+ None, description="""The namespace/prefix of the object entity"""
+ )
+ object_category: Optional[str] = Field(
+ None, description="""The category of the object entity"""
+ )
object_closure: Optional[List[str]] = Field(
default_factory=list,
description="""Field containing object id and the ids of all of it's ancestors""",
)
- object_label: Optional[str] = Field(None, description="""The name of the object entity""")
+ object_label: Optional[str] = Field(
+ None, description="""The name of the object entity"""
+ )
object_closure_label: Optional[List[str]] = Field(
default_factory=list,
description="""Field containing object name and the names of all of it's ancestors""",
@@ -286,11 +328,15 @@ class DirectionalAssociation(Association):
onset_qualifier: Optional[str] = Field(None)
sex_qualifier: Optional[str] = Field(None)
stage_qualifier: Optional[str] = Field(None)
- qualifiers_label: Optional[str] = Field(None, description="""The name of the frequency_qualifier entity""")
+ qualifiers_label: Optional[str] = Field(
+ None, description="""The name of the frequency_qualifier entity"""
+ )
qualifiers_namespace: Optional[str] = Field(
None, description="""The namespace/prefix of the frequency_qualifier entity"""
)
- qualifiers_category: Optional[str] = Field(None, description="""The category of the frequency_qualifier entity""")
+ qualifiers_category: Optional[str] = Field(
+ None, description="""The category of the frequency_qualifier entity"""
+ )
qualifiers_closure: Optional[List[str]] = Field(
default_factory=list,
description="""Field containing frequency_qualifier id and the ids of all of it's ancestors""",
@@ -299,7 +345,9 @@ class DirectionalAssociation(Association):
default_factory=list,
description="""Field containing frequency_qualifier name and the names of all of it's ancestors""",
)
- frequency_qualifier_label: Optional[str] = Field(None, description="""The name of the frequency_qualifier entity""")
+ frequency_qualifier_label: Optional[str] = Field(
+ None, description="""The name of the frequency_qualifier entity"""
+ )
frequency_qualifier_namespace: Optional[str] = Field(
None, description="""The namespace/prefix of the frequency_qualifier entity"""
)
@@ -314,11 +362,15 @@ class DirectionalAssociation(Association):
default_factory=list,
description="""Field containing frequency_qualifier name and the names of all of it's ancestors""",
)
- onset_qualifier_label: Optional[str] = Field(None, description="""The name of the onset_qualifier entity""")
+ onset_qualifier_label: Optional[str] = Field(
+ None, description="""The name of the onset_qualifier entity"""
+ )
onset_qualifier_namespace: Optional[str] = Field(
None, description="""The namespace/prefix of the onset_qualifier entity"""
)
- onset_qualifier_category: Optional[str] = Field(None, description="""The category of the onset_qualifier entity""")
+ onset_qualifier_category: Optional[str] = Field(
+ None, description="""The category of the onset_qualifier entity"""
+ )
onset_qualifier_closure: Optional[List[str]] = Field(
default_factory=list,
description="""Field containing onset_qualifier id and the ids of all of it's ancestors""",
@@ -327,11 +379,15 @@ class DirectionalAssociation(Association):
default_factory=list,
description="""Field containing onset_qualifier name and the names of all of it's ancestors""",
)
- sex_qualifier_label: Optional[str] = Field(None, description="""The name of the sex_qualifier entity""")
+ sex_qualifier_label: Optional[str] = Field(
+ None, description="""The name of the sex_qualifier entity"""
+ )
sex_qualifier_namespace: Optional[str] = Field(
None, description="""The namespace/prefix of the sex_qualifier entity"""
)
- sex_qualifier_category: Optional[str] = Field(None, description="""The category of the sex_qualifier entity""")
+ sex_qualifier_category: Optional[str] = Field(
+ None, description="""The category of the sex_qualifier entity"""
+ )
sex_qualifier_closure: Optional[List[str]] = Field(
default_factory=list,
description="""Field containing sex_qualifier id and the ids of all of it's ancestors""",
@@ -340,11 +396,15 @@ class DirectionalAssociation(Association):
default_factory=list,
description="""Field containing sex_qualifier name and the names of all of it's ancestors""",
)
- stage_qualifier_label: Optional[str] = Field(None, description="""The name of the stage_qualifier entity""")
+ stage_qualifier_label: Optional[str] = Field(
+ None, description="""The name of the stage_qualifier entity"""
+ )
stage_qualifier_namespace: Optional[str] = Field(
None, description="""The namespace/prefix of the stage_qualifier entity"""
)
- stage_qualifier_category: Optional[str] = Field(None, description="""The category of the stage_qualifier entity""")
+ stage_qualifier_category: Optional[str] = Field(
+ None, description="""The category of the stage_qualifier entity"""
+ )
stage_qualifier_closure: Optional[List[str]] = Field(
default_factory=list,
description="""Field containing stage_qualifier id and the ids of all of it's ancestors""",
@@ -372,11 +432,15 @@ class Entity(ConfiguredBaseModel):
id: str = Field(...)
category: Optional[str] = Field(None)
name: Optional[str] = Field(None)
- full_name: Optional[str] = Field(None, description="""The long form name of an entity""")
+ full_name: Optional[str] = Field(
+ None, description="""The long form name of an entity"""
+ )
description: Optional[str] = Field(None)
xref: Optional[List[str]] = Field(default_factory=list)
provided_by: Optional[str] = Field(None)
- in_taxon: Optional[str] = Field(None, description="""The biolink taxon that the entity is in the closure of.""")
+ in_taxon: Optional[str] = Field(
+ None, description="""The biolink taxon that the entity is in the closure of."""
+ )
in_taxon_label: Optional[str] = Field(
None,
description="""The label of the biolink taxon that the entity is in the closure of.""",
@@ -430,10 +494,14 @@ class Mapping(ConfiguredBaseModel):
"""
subject_id: str = Field(...)
- subject_label: Optional[str] = Field(None, description="""The name of the subject entity""")
+ subject_label: Optional[str] = Field(
+ None, description="""The name of the subject entity"""
+ )
predicate_id: str = Field(...)
object_id: str = Field(...)
- object_label: Optional[str] = Field(None, description="""The name of the object entity""")
+ object_label: Optional[str] = Field(
+ None, description="""The name of the object entity"""
+ )
mapping_justification: Optional[str] = Field(None)
@@ -442,7 +510,9 @@ class Node(Entity):
UI container class extending Entity with additional information
"""
- in_taxon: Optional[str] = Field(None, description="""The biolink taxon that the entity is in the closure of.""")
+ in_taxon: Optional[str] = Field(
+ None, description="""The biolink taxon that the entity is in the closure of."""
+ )
in_taxon_label: Optional[str] = Field(
None,
description="""The label of the biolink taxon that the entity is in the closure of.""",
@@ -468,7 +538,9 @@ class Node(Entity):
id: str = Field(...)
category: Optional[str] = Field(None)
name: Optional[str] = Field(None)
- full_name: Optional[str] = Field(None, description="""The long form name of an entity""")
+ full_name: Optional[str] = Field(
+ None, description="""The long form name of an entity"""
+ )
description: Optional[str] = Field(None)
xref: Optional[List[str]] = Field(default_factory=list)
provided_by: Optional[str] = Field(None)
@@ -538,11 +610,23 @@ class EntityResults(Results):
total: int = Field(..., description="""total number of items matching a query""")
+class MappingResults(Results):
+ """
+ SSSOM Mappings returned as a results collection
+ """
+
+ limit: int = Field(..., description="""number of items to return in a response""")
+ offset: int = Field(..., description="""offset into the total number of items""")
+ total: int = Field(..., description="""total number of items matching a query""")
+
+
class MultiEntityAssociationResults(Results):
id: str = Field(...)
name: Optional[str] = Field(None)
- associated_categories: List[CategoryGroupedAssociationResults] = Field(default_factory=list)
+ associated_categories: List[CategoryGroupedAssociationResults] = Field(
+ default_factory=list
+ )
limit: int = Field(..., description="""number of items to return in a response""")
offset: int = Field(..., description="""offset into the total number of items""")
total: int = Field(..., description="""total number of items matching a query""")
@@ -550,16 +634,22 @@ class MultiEntityAssociationResults(Results):
class SearchResult(Entity):
- highlight: Optional[str] = Field(None, description="""matching text snippet containing html tags""")
+ highlight: Optional[str] = Field(
+ None, description="""matching text snippet containing html tags"""
+ )
score: Optional[float] = Field(None)
id: str = Field(...)
category: str = Field(...)
name: str = Field(...)
- full_name: Optional[str] = Field(None, description="""The long form name of an entity""")
+ full_name: Optional[str] = Field(
+ None, description="""The long form name of an entity"""
+ )
description: Optional[str] = Field(None)
xref: Optional[List[str]] = Field(default_factory=list)
provided_by: Optional[str] = Field(None)
- in_taxon: Optional[str] = Field(None, description="""The biolink taxon that the entity is in the closure of.""")
+ in_taxon: Optional[str] = Field(
+ None, description="""The biolink taxon that the entity is in the closure of."""
+ )
in_taxon_label: Optional[str] = Field(
None,
description="""The label of the biolink taxon that the entity is in the closure of.""",
@@ -602,20 +692,36 @@ class TermPairwiseSimilarity(PairwiseSimilarity):
"""
subject_id: str = Field(...)
- subject_label: Optional[str] = Field(None, description="""The name of the subject entity""")
- subject_source: Optional[str] = Field(None, description="""the source for the first entity""")
+ subject_label: Optional[str] = Field(
+ None, description="""The name of the subject entity"""
+ )
+ subject_source: Optional[str] = Field(
+ None, description="""the source for the first entity"""
+ )
object_id: str = Field(...)
- object_label: Optional[str] = Field(None, description="""The name of the object entity""")
- object_source: Optional[str] = Field(None, description="""the source for the second entity""")
+ object_label: Optional[str] = Field(
+ None, description="""The name of the object entity"""
+ )
+ object_source: Optional[str] = Field(
+ None, description="""the source for the second entity"""
+ )
ancestor_id: Optional[str] = Field(
None,
description="""the most recent common ancestor of the two compared entities. If there are multiple MRCAs then the most informative one is selected""",
)
- ancestor_label: Optional[str] = Field(None, description="""the name or label of the ancestor concept""")
+ ancestor_label: Optional[str] = Field(
+ None, description="""the name or label of the ancestor concept"""
+ )
ancestor_source: Optional[str] = Field(None)
- object_information_content: Optional[float] = Field(None, description="""The IC of the object""")
- subject_information_content: Optional[float] = Field(None, description="""The IC of the subject""")
- ancestor_information_content: Optional[float] = Field(None, description="""The IC of the object""")
+ object_information_content: Optional[float] = Field(
+ None, description="""The IC of the object"""
+ )
+ subject_information_content: Optional[float] = Field(
+ None, description="""The IC of the subject"""
+ )
+ ancestor_information_content: Optional[float] = Field(
+ None, description="""The IC of the object"""
+ )
jaccard_similarity: Optional[float] = Field(
None,
description="""The number of concepts in the intersection divided by the number in the union""",
@@ -684,6 +790,7 @@ class BestMatch(ConfiguredBaseModel):
AssociationTableResults.update_forward_refs()
CategoryGroupedAssociationResults.update_forward_refs()
EntityResults.update_forward_refs()
+MappingResults.update_forward_refs()
MultiEntityAssociationResults.update_forward_refs()
SearchResult.update_forward_refs()
SearchResults.update_forward_refs()
diff --git a/backend/src/monarch_py/datamodels/model.yaml b/backend/src/monarch_py/datamodels/model.yaml
index b28bfaebe..b7bc4323d 100644
--- a/backend/src/monarch_py/datamodels/model.yaml
+++ b/backend/src/monarch_py/datamodels/model.yaml
@@ -210,6 +210,12 @@ classes:
- object_id
- object_label
- mapping_justification
+ MappingResults:
+ description: SSSOM Mappings returned as a results collection
+ is_a: Results
+ slot_usage:
+ items:
+ range: Mapping
MultiEntityAssociationResults:
is_a: Results
slots:
diff --git a/backend/src/monarch_py/interfaces/mapping_interface.py b/backend/src/monarch_py/interfaces/mapping_interface.py
new file mode 100644
index 000000000..d33b93337
--- /dev/null
+++ b/backend/src/monarch_py/interfaces/mapping_interface.py
@@ -0,0 +1,15 @@
+from abc import ABC
+from typing import List
+
+from monarch_py.datamodels.model import MappingResults
+
+class MappingInterface(ABC):
+
+ def get_mappings(self,
+ entity_id: List[str] = None,
+ subject_id: List[str] = None,
+ predicate_id: List[str] = None,
+ object_id: List[str] = None,
+ mapping_justification: List[str] = None,
+ ) -> MappingResults:
+ raise NotImplementedError
diff --git a/frontend/src/api/model.ts b/frontend/src/api/model.ts
index 34b656aeb..d6d59466f 100644
--- a/frontend/src/api/model.ts
+++ b/frontend/src/api/model.ts
@@ -376,6 +376,17 @@ export interface Mapping {
object_label?: string,
mapping_justification?: string,
};
+/**
+ * SSSOM Mappings returned as a results collection
+ */
+export interface MappingResults extends Results {
+ /** number of items to return in a response */
+ limit: number,
+ /** offset into the total number of items */
+ offset: number,
+ /** total number of items matching a query */
+ total: number,
+};
export interface MultiEntityAssociationResults extends Results {
id: string,
@@ -502,12 +513,12 @@ export interface TermPairwiseSimilarity extends PairwiseSimilarity {
/** The IC of the object */
ancestor_information_content?: string,
/** The number of concepts in the intersection divided by the number in the union */
- jaccard_similarity?: number,
+ jaccard_similarity?: string,
/** the dot product of two node embeddings divided by the product of their lengths */
cosine_similarity?: number,
- dice_similarity?: number,
+ dice_similarity?: string,
/** the geometric mean of the jaccard similarity and the information content */
- phenodigm_score?: number,
+ phenodigm_score?: string,
};
/**
* A simple pairwise similarity between two sets of concepts/terms
From 40dd3f136e3caaaea9cfbd0e7780fc9f0faea525 Mon Sep 17 00:00:00 2001
From: Kevin Schaper
Date: Mon, 6 Nov 2023 13:19:03 -0800
Subject: [PATCH 2/9] Added MappingResults & MappingInterface
---
backend/src/monarch_py/interfaces/mapping_interface.py | 1 +
1 file changed, 1 insertion(+)
diff --git a/backend/src/monarch_py/interfaces/mapping_interface.py b/backend/src/monarch_py/interfaces/mapping_interface.py
index d33b93337..18f147750 100644
--- a/backend/src/monarch_py/interfaces/mapping_interface.py
+++ b/backend/src/monarch_py/interfaces/mapping_interface.py
@@ -3,6 +3,7 @@
from monarch_py.datamodels.model import MappingResults
+
class MappingInterface(ABC):
def get_mappings(self,
From 0f97e16d77a819f3e846026309cb18ee4ad49ddf Mon Sep 17 00:00:00 2001
From: Kevin Schaper
Date: Mon, 6 Nov 2023 15:35:17 -0800
Subject: [PATCH 3/9] Added solr querying & parsing for sssom api endpoint
---
backend/src/monarch_py/datamodels/model.py | 192 +++++-------------
backend/src/monarch_py/datamodels/solr.py | 1 +
.../solr/solr_implementation.py | 18 ++
.../implementations/solr/solr_parsers.py | 15 ++
.../implementations/solr/solr_query_utils.py | 23 +++
.../interfaces/mapping_interface.py | 24 ++-
6 files changed, 122 insertions(+), 151 deletions(-)
diff --git a/backend/src/monarch_py/datamodels/model.py b/backend/src/monarch_py/datamodels/model.py
index 84b20d4b4..2d1df70be 100644
--- a/backend/src/monarch_py/datamodels/model.py
+++ b/backend/src/monarch_py/datamodels/model.py
@@ -48,19 +48,13 @@ class Association(ConfiguredBaseModel):
category: Optional[str] = Field(None)
subject: str = Field(...)
original_subject: Optional[str] = Field(None)
- subject_namespace: Optional[str] = Field(
- None, description="""The namespace/prefix of the subject entity"""
- )
- subject_category: Optional[str] = Field(
- None, description="""The category of the subject entity"""
- )
+ subject_namespace: Optional[str] = Field(None, description="""The namespace/prefix of the subject entity""")
+ subject_category: Optional[str] = Field(None, description="""The category of the subject entity""")
subject_closure: Optional[List[str]] = Field(
default_factory=list,
description="""Field containing subject id and the ids of all of it's ancestors""",
)
- subject_label: Optional[str] = Field(
- None, description="""The name of the subject entity"""
- )
+ subject_label: Optional[str] = Field(None, description="""The name of the subject entity""")
subject_closure_label: Optional[List[str]] = Field(
default_factory=list,
description="""Field containing subject name and the names of all of it's ancestors""",
@@ -70,19 +64,13 @@ class Association(ConfiguredBaseModel):
predicate: str = Field(...)
object: str = Field(...)
original_object: Optional[str] = Field(None)
- object_namespace: Optional[str] = Field(
- None, description="""The namespace/prefix of the object entity"""
- )
- object_category: Optional[str] = Field(
- None, description="""The category of the object entity"""
- )
+ object_namespace: Optional[str] = Field(None, description="""The namespace/prefix of the object entity""")
+ object_category: Optional[str] = Field(None, description="""The category of the object entity""")
object_closure: Optional[List[str]] = Field(
default_factory=list,
description="""Field containing object id and the ids of all of it's ancestors""",
)
- object_label: Optional[str] = Field(
- None, description="""The name of the object entity"""
- )
+ object_label: Optional[str] = Field(None, description="""The name of the object entity""")
object_closure_label: Optional[List[str]] = Field(
default_factory=list,
description="""Field containing object name and the names of all of it's ancestors""",
@@ -121,15 +109,11 @@ class Association(ConfiguredBaseModel):
onset_qualifier: Optional[str] = Field(None)
sex_qualifier: Optional[str] = Field(None)
stage_qualifier: Optional[str] = Field(None)
- qualifiers_label: Optional[str] = Field(
- None, description="""The name of the frequency_qualifier entity"""
- )
+ qualifiers_label: Optional[str] = Field(None, description="""The name of the frequency_qualifier entity""")
qualifiers_namespace: Optional[str] = Field(
None, description="""The namespace/prefix of the frequency_qualifier entity"""
)
- qualifiers_category: Optional[str] = Field(
- None, description="""The category of the frequency_qualifier entity"""
- )
+ qualifiers_category: Optional[str] = Field(None, description="""The category of the frequency_qualifier entity""")
qualifiers_closure: Optional[List[str]] = Field(
default_factory=list,
description="""Field containing frequency_qualifier id and the ids of all of it's ancestors""",
@@ -138,9 +122,7 @@ class Association(ConfiguredBaseModel):
default_factory=list,
description="""Field containing frequency_qualifier name and the names of all of it's ancestors""",
)
- frequency_qualifier_label: Optional[str] = Field(
- None, description="""The name of the frequency_qualifier entity"""
- )
+ frequency_qualifier_label: Optional[str] = Field(None, description="""The name of the frequency_qualifier entity""")
frequency_qualifier_namespace: Optional[str] = Field(
None, description="""The namespace/prefix of the frequency_qualifier entity"""
)
@@ -155,15 +137,11 @@ class Association(ConfiguredBaseModel):
default_factory=list,
description="""Field containing frequency_qualifier name and the names of all of it's ancestors""",
)
- onset_qualifier_label: Optional[str] = Field(
- None, description="""The name of the onset_qualifier entity"""
- )
+ onset_qualifier_label: Optional[str] = Field(None, description="""The name of the onset_qualifier entity""")
onset_qualifier_namespace: Optional[str] = Field(
None, description="""The namespace/prefix of the onset_qualifier entity"""
)
- onset_qualifier_category: Optional[str] = Field(
- None, description="""The category of the onset_qualifier entity"""
- )
+ onset_qualifier_category: Optional[str] = Field(None, description="""The category of the onset_qualifier entity""")
onset_qualifier_closure: Optional[List[str]] = Field(
default_factory=list,
description="""Field containing onset_qualifier id and the ids of all of it's ancestors""",
@@ -172,15 +150,11 @@ class Association(ConfiguredBaseModel):
default_factory=list,
description="""Field containing onset_qualifier name and the names of all of it's ancestors""",
)
- sex_qualifier_label: Optional[str] = Field(
- None, description="""The name of the sex_qualifier entity"""
- )
+ sex_qualifier_label: Optional[str] = Field(None, description="""The name of the sex_qualifier entity""")
sex_qualifier_namespace: Optional[str] = Field(
None, description="""The namespace/prefix of the sex_qualifier entity"""
)
- sex_qualifier_category: Optional[str] = Field(
- None, description="""The category of the sex_qualifier entity"""
- )
+ sex_qualifier_category: Optional[str] = Field(None, description="""The category of the sex_qualifier entity""")
sex_qualifier_closure: Optional[List[str]] = Field(
default_factory=list,
description="""Field containing sex_qualifier id and the ids of all of it's ancestors""",
@@ -189,15 +163,11 @@ class Association(ConfiguredBaseModel):
default_factory=list,
description="""Field containing sex_qualifier name and the names of all of it's ancestors""",
)
- stage_qualifier_label: Optional[str] = Field(
- None, description="""The name of the stage_qualifier entity"""
- )
+ stage_qualifier_label: Optional[str] = Field(None, description="""The name of the stage_qualifier entity""")
stage_qualifier_namespace: Optional[str] = Field(
None, description="""The namespace/prefix of the stage_qualifier entity"""
)
- stage_qualifier_category: Optional[str] = Field(
- None, description="""The category of the stage_qualifier entity"""
- )
+ stage_qualifier_category: Optional[str] = Field(None, description="""The category of the stage_qualifier entity""")
stage_qualifier_closure: Optional[List[str]] = Field(
default_factory=list,
description="""Field containing stage_qualifier id and the ids of all of it's ancestors""",
@@ -255,19 +225,13 @@ class DirectionalAssociation(Association):
category: Optional[str] = Field(None)
subject: str = Field(...)
original_subject: Optional[str] = Field(None)
- subject_namespace: Optional[str] = Field(
- None, description="""The namespace/prefix of the subject entity"""
- )
- subject_category: Optional[str] = Field(
- None, description="""The category of the subject entity"""
- )
+ subject_namespace: Optional[str] = Field(None, description="""The namespace/prefix of the subject entity""")
+ subject_category: Optional[str] = Field(None, description="""The category of the subject entity""")
subject_closure: Optional[List[str]] = Field(
default_factory=list,
description="""Field containing subject id and the ids of all of it's ancestors""",
)
- subject_label: Optional[str] = Field(
- None, description="""The name of the subject entity"""
- )
+ subject_label: Optional[str] = Field(None, description="""The name of the subject entity""")
subject_closure_label: Optional[List[str]] = Field(
default_factory=list,
description="""Field containing subject name and the names of all of it's ancestors""",
@@ -277,19 +241,13 @@ class DirectionalAssociation(Association):
predicate: str = Field(...)
object: str = Field(...)
original_object: Optional[str] = Field(None)
- object_namespace: Optional[str] = Field(
- None, description="""The namespace/prefix of the object entity"""
- )
- object_category: Optional[str] = Field(
- None, description="""The category of the object entity"""
- )
+ object_namespace: Optional[str] = Field(None, description="""The namespace/prefix of the object entity""")
+ object_category: Optional[str] = Field(None, description="""The category of the object entity""")
object_closure: Optional[List[str]] = Field(
default_factory=list,
description="""Field containing object id and the ids of all of it's ancestors""",
)
- object_label: Optional[str] = Field(
- None, description="""The name of the object entity"""
- )
+ object_label: Optional[str] = Field(None, description="""The name of the object entity""")
object_closure_label: Optional[List[str]] = Field(
default_factory=list,
description="""Field containing object name and the names of all of it's ancestors""",
@@ -328,15 +286,11 @@ class DirectionalAssociation(Association):
onset_qualifier: Optional[str] = Field(None)
sex_qualifier: Optional[str] = Field(None)
stage_qualifier: Optional[str] = Field(None)
- qualifiers_label: Optional[str] = Field(
- None, description="""The name of the frequency_qualifier entity"""
- )
+ qualifiers_label: Optional[str] = Field(None, description="""The name of the frequency_qualifier entity""")
qualifiers_namespace: Optional[str] = Field(
None, description="""The namespace/prefix of the frequency_qualifier entity"""
)
- qualifiers_category: Optional[str] = Field(
- None, description="""The category of the frequency_qualifier entity"""
- )
+ qualifiers_category: Optional[str] = Field(None, description="""The category of the frequency_qualifier entity""")
qualifiers_closure: Optional[List[str]] = Field(
default_factory=list,
description="""Field containing frequency_qualifier id and the ids of all of it's ancestors""",
@@ -345,9 +299,7 @@ class DirectionalAssociation(Association):
default_factory=list,
description="""Field containing frequency_qualifier name and the names of all of it's ancestors""",
)
- frequency_qualifier_label: Optional[str] = Field(
- None, description="""The name of the frequency_qualifier entity"""
- )
+ frequency_qualifier_label: Optional[str] = Field(None, description="""The name of the frequency_qualifier entity""")
frequency_qualifier_namespace: Optional[str] = Field(
None, description="""The namespace/prefix of the frequency_qualifier entity"""
)
@@ -362,15 +314,11 @@ class DirectionalAssociation(Association):
default_factory=list,
description="""Field containing frequency_qualifier name and the names of all of it's ancestors""",
)
- onset_qualifier_label: Optional[str] = Field(
- None, description="""The name of the onset_qualifier entity"""
- )
+ onset_qualifier_label: Optional[str] = Field(None, description="""The name of the onset_qualifier entity""")
onset_qualifier_namespace: Optional[str] = Field(
None, description="""The namespace/prefix of the onset_qualifier entity"""
)
- onset_qualifier_category: Optional[str] = Field(
- None, description="""The category of the onset_qualifier entity"""
- )
+ onset_qualifier_category: Optional[str] = Field(None, description="""The category of the onset_qualifier entity""")
onset_qualifier_closure: Optional[List[str]] = Field(
default_factory=list,
description="""Field containing onset_qualifier id and the ids of all of it's ancestors""",
@@ -379,15 +327,11 @@ class DirectionalAssociation(Association):
default_factory=list,
description="""Field containing onset_qualifier name and the names of all of it's ancestors""",
)
- sex_qualifier_label: Optional[str] = Field(
- None, description="""The name of the sex_qualifier entity"""
- )
+ sex_qualifier_label: Optional[str] = Field(None, description="""The name of the sex_qualifier entity""")
sex_qualifier_namespace: Optional[str] = Field(
None, description="""The namespace/prefix of the sex_qualifier entity"""
)
- sex_qualifier_category: Optional[str] = Field(
- None, description="""The category of the sex_qualifier entity"""
- )
+ sex_qualifier_category: Optional[str] = Field(None, description="""The category of the sex_qualifier entity""")
sex_qualifier_closure: Optional[List[str]] = Field(
default_factory=list,
description="""Field containing sex_qualifier id and the ids of all of it's ancestors""",
@@ -396,15 +340,11 @@ class DirectionalAssociation(Association):
default_factory=list,
description="""Field containing sex_qualifier name and the names of all of it's ancestors""",
)
- stage_qualifier_label: Optional[str] = Field(
- None, description="""The name of the stage_qualifier entity"""
- )
+ stage_qualifier_label: Optional[str] = Field(None, description="""The name of the stage_qualifier entity""")
stage_qualifier_namespace: Optional[str] = Field(
None, description="""The namespace/prefix of the stage_qualifier entity"""
)
- stage_qualifier_category: Optional[str] = Field(
- None, description="""The category of the stage_qualifier entity"""
- )
+ stage_qualifier_category: Optional[str] = Field(None, description="""The category of the stage_qualifier entity""")
stage_qualifier_closure: Optional[List[str]] = Field(
default_factory=list,
description="""Field containing stage_qualifier id and the ids of all of it's ancestors""",
@@ -432,15 +372,11 @@ class Entity(ConfiguredBaseModel):
id: str = Field(...)
category: Optional[str] = Field(None)
name: Optional[str] = Field(None)
- full_name: Optional[str] = Field(
- None, description="""The long form name of an entity"""
- )
+ full_name: Optional[str] = Field(None, description="""The long form name of an entity""")
description: Optional[str] = Field(None)
xref: Optional[List[str]] = Field(default_factory=list)
provided_by: Optional[str] = Field(None)
- in_taxon: Optional[str] = Field(
- None, description="""The biolink taxon that the entity is in the closure of."""
- )
+ in_taxon: Optional[str] = Field(None, description="""The biolink taxon that the entity is in the closure of.""")
in_taxon_label: Optional[str] = Field(
None,
description="""The label of the biolink taxon that the entity is in the closure of.""",
@@ -494,14 +430,10 @@ class Mapping(ConfiguredBaseModel):
"""
subject_id: str = Field(...)
- subject_label: Optional[str] = Field(
- None, description="""The name of the subject entity"""
- )
+ subject_label: Optional[str] = Field(None, description="""The name of the subject entity""")
predicate_id: str = Field(...)
object_id: str = Field(...)
- object_label: Optional[str] = Field(
- None, description="""The name of the object entity"""
- )
+ object_label: Optional[str] = Field(None, description="""The name of the object entity""")
mapping_justification: Optional[str] = Field(None)
@@ -510,9 +442,7 @@ class Node(Entity):
UI container class extending Entity with additional information
"""
- in_taxon: Optional[str] = Field(
- None, description="""The biolink taxon that the entity is in the closure of."""
- )
+ in_taxon: Optional[str] = Field(None, description="""The biolink taxon that the entity is in the closure of.""")
in_taxon_label: Optional[str] = Field(
None,
description="""The label of the biolink taxon that the entity is in the closure of.""",
@@ -538,9 +468,7 @@ class Node(Entity):
id: str = Field(...)
category: Optional[str] = Field(None)
name: Optional[str] = Field(None)
- full_name: Optional[str] = Field(
- None, description="""The long form name of an entity"""
- )
+ full_name: Optional[str] = Field(None, description="""The long form name of an entity""")
description: Optional[str] = Field(None)
xref: Optional[List[str]] = Field(default_factory=list)
provided_by: Optional[str] = Field(None)
@@ -624,9 +552,7 @@ class MultiEntityAssociationResults(Results):
id: str = Field(...)
name: Optional[str] = Field(None)
- associated_categories: List[CategoryGroupedAssociationResults] = Field(
- default_factory=list
- )
+ associated_categories: List[CategoryGroupedAssociationResults] = Field(default_factory=list)
limit: int = Field(..., description="""number of items to return in a response""")
offset: int = Field(..., description="""offset into the total number of items""")
total: int = Field(..., description="""total number of items matching a query""")
@@ -634,22 +560,16 @@ class MultiEntityAssociationResults(Results):
class SearchResult(Entity):
- highlight: Optional[str] = Field(
- None, description="""matching text snippet containing html tags"""
- )
+ highlight: Optional[str] = Field(None, description="""matching text snippet containing html tags""")
score: Optional[float] = Field(None)
id: str = Field(...)
category: str = Field(...)
name: str = Field(...)
- full_name: Optional[str] = Field(
- None, description="""The long form name of an entity"""
- )
+ full_name: Optional[str] = Field(None, description="""The long form name of an entity""")
description: Optional[str] = Field(None)
xref: Optional[List[str]] = Field(default_factory=list)
provided_by: Optional[str] = Field(None)
- in_taxon: Optional[str] = Field(
- None, description="""The biolink taxon that the entity is in the closure of."""
- )
+ in_taxon: Optional[str] = Field(None, description="""The biolink taxon that the entity is in the closure of.""")
in_taxon_label: Optional[str] = Field(
None,
description="""The label of the biolink taxon that the entity is in the closure of.""",
@@ -692,36 +612,20 @@ class TermPairwiseSimilarity(PairwiseSimilarity):
"""
subject_id: str = Field(...)
- subject_label: Optional[str] = Field(
- None, description="""The name of the subject entity"""
- )
- subject_source: Optional[str] = Field(
- None, description="""the source for the first entity"""
- )
+ subject_label: Optional[str] = Field(None, description="""The name of the subject entity""")
+ subject_source: Optional[str] = Field(None, description="""the source for the first entity""")
object_id: str = Field(...)
- object_label: Optional[str] = Field(
- None, description="""The name of the object entity"""
- )
- object_source: Optional[str] = Field(
- None, description="""the source for the second entity"""
- )
+ object_label: Optional[str] = Field(None, description="""The name of the object entity""")
+ object_source: Optional[str] = Field(None, description="""the source for the second entity""")
ancestor_id: Optional[str] = Field(
None,
description="""the most recent common ancestor of the two compared entities. If there are multiple MRCAs then the most informative one is selected""",
)
- ancestor_label: Optional[str] = Field(
- None, description="""the name or label of the ancestor concept"""
- )
+ ancestor_label: Optional[str] = Field(None, description="""the name or label of the ancestor concept""")
ancestor_source: Optional[str] = Field(None)
- object_information_content: Optional[float] = Field(
- None, description="""The IC of the object"""
- )
- subject_information_content: Optional[float] = Field(
- None, description="""The IC of the subject"""
- )
- ancestor_information_content: Optional[float] = Field(
- None, description="""The IC of the object"""
- )
+ object_information_content: Optional[float] = Field(None, description="""The IC of the object""")
+ subject_information_content: Optional[float] = Field(None, description="""The IC of the subject""")
+ ancestor_information_content: Optional[float] = Field(None, description="""The IC of the object""")
jaccard_similarity: Optional[float] = Field(
None,
description="""The number of concepts in the intersection divided by the number in the union""",
diff --git a/backend/src/monarch_py/datamodels/solr.py b/backend/src/monarch_py/datamodels/solr.py
index 196b2ed1d..c89d923ea 100644
--- a/backend/src/monarch_py/datamodels/solr.py
+++ b/backend/src/monarch_py/datamodels/solr.py
@@ -9,6 +9,7 @@
class core(Enum):
ENTITY = "entity"
ASSOCIATION = "association"
+ SSSOM = "sssom"
class HistoPhenoKeys(Enum):
diff --git a/backend/src/monarch_py/implementations/solr/solr_implementation.py b/backend/src/monarch_py/implementations/solr/solr_implementation.py
index 2a78c5e49..a4c895ba7 100644
--- a/backend/src/monarch_py/implementations/solr/solr_implementation.py
+++ b/backend/src/monarch_py/implementations/solr/solr_implementation.py
@@ -34,6 +34,7 @@
build_association_table_query,
build_autocomplete_query,
build_histopheno_query,
+ build_mapping_query,
build_multi_entity_association_query,
build_search_query,
)
@@ -418,3 +419,20 @@ def get_association_table(
solr = SolrService(base_url=self.base_url, core=core.ASSOCIATION)
query_result = solr.query(query)
return parse_association_table(query_result, entity, offset, limit)
+
+ def get_mappings(
+ self,
+ entity_id: List[str] = None,
+ subject_id: List[str] = None,
+ predicate_id: List[str] = None,
+ object_id: List[str] = None,
+ mapping_justification: List[str] = None,
+ ) -> MappingResults:
+ solr = SolrService(base_url=self.base_url, core=core.SSSOM)
+ query = build_mapping_query(
+ entity_id=entity_id,
+ subject_id=subject_id,
+ predicate_id=predicate_id,
+ object_id=object_id,
+ mapping_justification=mapping_justification,
+ )
diff --git a/backend/src/monarch_py/implementations/solr/solr_parsers.py b/backend/src/monarch_py/implementations/solr/solr_parsers.py
index 5c79e230d..3700e7239 100644
--- a/backend/src/monarch_py/implementations/solr/solr_parsers.py
+++ b/backend/src/monarch_py/implementations/solr/solr_parsers.py
@@ -16,6 +16,8 @@
FacetValue,
HistoBin,
HistoPheno,
+ Mapping,
+ MappingResults,
SearchResult,
SearchResults,
)
@@ -168,6 +170,19 @@ def parse_autocomplete(query_result: SolrQueryResult) -> SearchResults:
return SearchResults(limit=10, offset=0, total=total, items=items)
+def parse_mapping(query_result: SolrQueryResult, offset: int, limit: int) -> MappingResults:
+ total = query_result.response.num_found
+ items = []
+ for doc in query_result.response.docs:
+ try:
+ result = Mapping(**doc)
+ items.append(result)
+ except ValidationError:
+ logger.error(f"Validation error for {doc}")
+ raise
+ return MappingResults(limit=limit, offset=offset, total=total, items=items)
+
+
##################
# Parser Helpers #
##################
diff --git a/backend/src/monarch_py/implementations/solr/solr_query_utils.py b/backend/src/monarch_py/implementations/solr/solr_query_utils.py
index 3556c5a75..f38a835b0 100644
--- a/backend/src/monarch_py/implementations/solr/solr_query_utils.py
+++ b/backend/src/monarch_py/implementations/solr/solr_query_utils.py
@@ -174,6 +174,29 @@ def build_autocomplete_query(q: str) -> SolrQuery:
return query
+def build_mapping_query(
+ entity_id: List[str] = None,
+ subject_id: List[str] = None,
+ predicate_id: List[str] = None,
+ object_id: List[str] = None,
+ mapping_justification: List[str] = None,
+ offset: int = 0,
+ limit: int = 20,
+) -> SolrQuery:
+ query = SolrQuery(start=offset, rows=limit)
+ if entity_id:
+ query.add_filter_query(" OR ".join([f'subject_id:"{escape(e)}" OR object_id:"{escape(e)}"' for e in entity_id]))
+ if subject_id:
+ query.add_filter_query(" OR ".join([f'subject_id:"{escape(e)}"' for e in subject_id]))
+ if predicate_id:
+ query.add_filter_query(" OR ".join([f'predicate_id:"{escape(e)}"' for e in predicate_id]))
+ if object_id:
+ query.add_filter_query(" OR ".join([f'object_id:"{escape(e)}"' for e in object_id]))
+ if mapping_justification:
+ query.add_filter_query(" OR ".join([f'mapping_justification:"{escape(e)}"' for e in mapping_justification]))
+ return query
+
+
### Search helper functions ###
diff --git a/backend/src/monarch_py/interfaces/mapping_interface.py b/backend/src/monarch_py/interfaces/mapping_interface.py
index 18f147750..f5664f118 100644
--- a/backend/src/monarch_py/interfaces/mapping_interface.py
+++ b/backend/src/monarch_py/interfaces/mapping_interface.py
@@ -5,12 +5,22 @@
class MappingInterface(ABC):
+ def get_mappings(
+ self,
+ entity_id: List[str] = None,
+ subject_id: List[str] = None,
+ predicate_id: List[str] = None,
+ object_id: List[str] = None,
+ mapping_justification: List[str] = None,
+ ) -> MappingResults:
+ """
+ Get SSSOM Mappings based on the provided constraints
- def get_mappings(self,
- entity_id: List[str] = None,
- subject_id: List[str] = None,
- predicate_id: List[str] = None,
- object_id: List[str] = None,
- mapping_justification: List[str] = None,
- ) -> MappingResults:
+ Args:
+ entity_id: Filter to only mappings matching the specified entity IDs. Defaults to None.
+ subject_id: Filter to only mappings matching the specified subject IDs. Defaults to None.
+ predicate_id: Filter to only mappings matching the specified predicate IDs. Defaults to None.
+ object_id: Filter to only mappings matching the specified object IDs. Defaults to None.
+ mapping_justification: Filter to only mappings matching the specified mapping justifications. Defaults to None.
+ """
raise NotImplementedError
From 9f55969c584d1597130583e2bba47b113eb23802 Mon Sep 17 00:00:00 2001
From: glass-ships
Date: Wed, 8 Nov 2023 10:29:39 -0700
Subject: [PATCH 4/9] finish implementation, cli, and api endpoint
---
backend/poetry.lock | 298 +++++++++---------
backend/src/monarch_py/api/search.py | 21 ++
backend/src/monarch_py/cli.py | 22 ++
backend/src/monarch_py/datamodels/model.py | 7 +-
backend/src/monarch_py/datamodels/model.yaml | 3 +
.../solr/solr_implementation.py | 23 +-
.../implementations/solr/solr_parsers.py | 2 +-
backend/src/monarch_py/solr_cli.py | 74 +++--
frontend/src/api/model.ts | 4 +
9 files changed, 275 insertions(+), 179 deletions(-)
diff --git a/backend/poetry.lock b/backend/poetry.lock
index 2db550422..e3aea9619 100644
--- a/backend/poetry.lock
+++ b/backend/poetry.lock
@@ -1233,13 +1233,13 @@ testing = ["flufl.flake8", "importlib-resources (>=1.3)", "packaging", "pyfakefs
[[package]]
name = "importlib-resources"
-version = "6.1.0"
+version = "6.1.1"
description = "Read resources from Python packages"
optional = false
python-versions = ">=3.8"
files = [
- {file = "importlib_resources-6.1.0-py3-none-any.whl", hash = "sha256:aa50258bbfa56d4e33fbd8aa3ef48ded10d1735f11532b8df95388cc6bdb7e83"},
- {file = "importlib_resources-6.1.0.tar.gz", hash = "sha256:9d48dcccc213325e810fd723e7fbb45ccb39f6cf5c31f00cf2b965f5f10f3cb9"},
+ {file = "importlib_resources-6.1.1-py3-none-any.whl", hash = "sha256:e8bf90d8213b486f428c9c39714b920041cb02c184686a3dee24905aaa8105d6"},
+ {file = "importlib_resources-6.1.1.tar.gz", hash = "sha256:3893a00122eafde6894c59914446a512f728a0c1a45f9bb9b63721b6bacf0b4a"},
]
[package.dependencies]
@@ -1318,12 +1318,12 @@ i18n = ["Babel (>=2.7)"]
[[package]]
name = "jsbeautifier"
-version = "1.14.9"
+version = "1.14.11"
description = "JavaScript unobfuscator and beautifier."
optional = false
python-versions = "*"
files = [
- {file = "jsbeautifier-1.14.9.tar.gz", hash = "sha256:c738ebc36b47bd94e4ca6dd17a9004c3cc74edad582ca1d60e0e5d5945a63cb9"},
+ {file = "jsbeautifier-1.14.11.tar.gz", hash = "sha256:6b632581ea60dd1c133cd25a48ad187b4b91f526623c4b0fb5443ef805250505"},
]
[package.dependencies]
@@ -1503,13 +1503,13 @@ regex = ["regex"]
[[package]]
name = "linkml"
-version = "1.6.1"
+version = "1.6.2"
description = "Linked Open Data Modeling Language"
optional = false
python-versions = ">=3.8,<4.0"
files = [
- {file = "linkml-1.6.1-py3-none-any.whl", hash = "sha256:7501cb9c7b2c13ca78fc7121ae8b5457fb5771138714da31cc11f971062070ee"},
- {file = "linkml-1.6.1.tar.gz", hash = "sha256:65f73cf29a77518972238e71e91e012c081cf2e43d71d8965ca414c78c11e08e"},
+ {file = "linkml-1.6.2-py3-none-any.whl", hash = "sha256:0e11b085ada080e0ebe9eee469ad55970b0cc333e7c39be956740dbc3a9e50b0"},
+ {file = "linkml-1.6.2.tar.gz", hash = "sha256:b1560a67de8c7de074c8be2ef5b810425f058e0874076e49c17a2dc4112f9da2"},
]
[package.dependencies]
@@ -1527,7 +1527,7 @@ openpyxl = "*"
parse = "*"
prefixcommons = ">=0.1.7"
prefixmaps = ">=0.1.3"
-pydantic = "*"
+pydantic = ">=1.0.0,<3.0.0"
pyjsg = ">=0.11.6"
pyshex = ">=0.7.20"
pyshexc = ">=0.8.3"
@@ -1575,13 +1575,13 @@ pydantic = "*"
[[package]]
name = "linkml-runtime"
-version = "1.6.0"
+version = "1.6.1"
description = "Runtime environment for LinkML, the Linked open data modeling language"
optional = false
python-versions = ">=3.7.6,<4.0.0"
files = [
- {file = "linkml_runtime-1.6.0-py3-none-any.whl", hash = "sha256:1b6b698f8cf23d63ff833ae0be8055b2e945e1c0ef06a1ed6db359247194a2eb"},
- {file = "linkml_runtime-1.6.0.tar.gz", hash = "sha256:a06df7431a9b929afe242598800d99cec83bb31cbdc1f5d2d70e6b26c67dc337"},
+ {file = "linkml_runtime-1.6.1-py3-none-any.whl", hash = "sha256:b598bf3fd2a5e354a662d34143193b0d7e092066affbf803053e1316acf75b2c"},
+ {file = "linkml_runtime-1.6.1.tar.gz", hash = "sha256:3036b8f4284e45df15733227eebef9c4216bcaff6d92c8fb09422e6026bf3152"},
]
[package.dependencies]
@@ -1935,13 +1935,13 @@ mkdocs = ">=1.1"
[[package]]
name = "mkdocs-material"
-version = "9.4.7"
+version = "9.4.8"
description = "Documentation that simply works"
optional = false
python-versions = ">=3.8"
files = [
- {file = "mkdocs_material-9.4.7-py3-none-any.whl", hash = "sha256:4d698d52bb6a6a3c452ab854481c4cdb68453a0420956a6aee2de55fe15fe610"},
- {file = "mkdocs_material-9.4.7.tar.gz", hash = "sha256:e704e001c9ef17291e1d3462c202425217601653e18f68f85d28eff4690e662b"},
+ {file = "mkdocs_material-9.4.8-py3-none-any.whl", hash = "sha256:8b20f6851bddeef37dced903893cd176cf13a21a482e97705a103c45f06ce9b9"},
+ {file = "mkdocs_material-9.4.8.tar.gz", hash = "sha256:f0c101453e8bc12b040e8b64ca39a405d950d8402609b1378cc2b98976e74b5f"},
]
[package.dependencies]
@@ -2792,13 +2792,13 @@ solrcloud = ["kazoo (>=2.5.0)"]
[[package]]
name = "pystow"
-version = "0.5.0"
+version = "0.5.2"
description = "Easily pick a place to store data for your python package."
optional = false
python-versions = ">=3.7"
files = [
- {file = "pystow-0.5.0-py3-none-any.whl", hash = "sha256:816a9da33cd8a3f8fbda577c3d2957cfc99d1fa3ea45032dbfa087b9a21b630f"},
- {file = "pystow-0.5.0.tar.gz", hash = "sha256:490e9ecbe4f947c72f63297f43f6584323c9ca2f2d48d47f2a22a815dc552bb4"},
+ {file = "pystow-0.5.2-py3-none-any.whl", hash = "sha256:c0faeb0fc854ede714be7949555f4d55ce40d8fd57f0ae1ff75e86158792299a"},
+ {file = "pystow-0.5.2.tar.gz", hash = "sha256:d05d233299d61b50f53c7de220d990ec4c58e3a54d195d8449f0302563eb6de6"},
]
[package.dependencies]
@@ -3280,121 +3280,121 @@ jupyter = ["ipywidgets (>=7.5.1,<9)"]
[[package]]
name = "rpds-py"
-version = "0.10.6"
+version = "0.12.0"
description = "Python bindings to Rust's persistent data structures (rpds)"
optional = false
python-versions = ">=3.8"
files = [
- {file = "rpds_py-0.10.6-cp310-cp310-macosx_10_7_x86_64.whl", hash = "sha256:6bdc11f9623870d75692cc33c59804b5a18d7b8a4b79ef0b00b773a27397d1f6"},
- {file = "rpds_py-0.10.6-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:26857f0f44f0e791f4a266595a7a09d21f6b589580ee0585f330aaccccb836e3"},
- {file = "rpds_py-0.10.6-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d7f5e15c953ace2e8dde9824bdab4bec50adb91a5663df08d7d994240ae6fa31"},
- {file = "rpds_py-0.10.6-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:61fa268da6e2e1cd350739bb61011121fa550aa2545762e3dc02ea177ee4de35"},
- {file = "rpds_py-0.10.6-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c48f3fbc3e92c7dd6681a258d22f23adc2eb183c8cb1557d2fcc5a024e80b094"},
- {file = "rpds_py-0.10.6-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c0503c5b681566e8b722fe8c4c47cce5c7a51f6935d5c7012c4aefe952a35eed"},
- {file = "rpds_py-0.10.6-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:734c41f9f57cc28658d98270d3436dba65bed0cfc730d115b290e970150c540d"},
- {file = "rpds_py-0.10.6-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a5d7ed104d158c0042a6a73799cf0eb576dfd5fc1ace9c47996e52320c37cb7c"},
- {file = "rpds_py-0.10.6-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:e3df0bc35e746cce42579826b89579d13fd27c3d5319a6afca9893a9b784ff1b"},
- {file = "rpds_py-0.10.6-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:73e0a78a9b843b8c2128028864901f55190401ba38aae685350cf69b98d9f7c9"},
- {file = "rpds_py-0.10.6-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:5ed505ec6305abd2c2c9586a7b04fbd4baf42d4d684a9c12ec6110deefe2a063"},
- {file = "rpds_py-0.10.6-cp310-none-win32.whl", hash = "sha256:d97dd44683802000277bbf142fd9f6b271746b4846d0acaf0cefa6b2eaf2a7ad"},
- {file = "rpds_py-0.10.6-cp310-none-win_amd64.whl", hash = "sha256:b455492cab07107bfe8711e20cd920cc96003e0da3c1f91297235b1603d2aca7"},
- {file = "rpds_py-0.10.6-cp311-cp311-macosx_10_7_x86_64.whl", hash = "sha256:e8cdd52744f680346ff8c1ecdad5f4d11117e1724d4f4e1874f3a67598821069"},
- {file = "rpds_py-0.10.6-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:66414dafe4326bca200e165c2e789976cab2587ec71beb80f59f4796b786a238"},
- {file = "rpds_py-0.10.6-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cc435d059f926fdc5b05822b1be4ff2a3a040f3ae0a7bbbe672babb468944722"},
- {file = "rpds_py-0.10.6-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8e7f2219cb72474571974d29a191714d822e58be1eb171f229732bc6fdedf0ac"},
- {file = "rpds_py-0.10.6-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3953c6926a63f8ea5514644b7afb42659b505ece4183fdaaa8f61d978754349e"},
- {file = "rpds_py-0.10.6-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2bb2e4826be25e72013916eecd3d30f66fd076110de09f0e750163b416500721"},
- {file = "rpds_py-0.10.6-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7bf347b495b197992efc81a7408e9a83b931b2f056728529956a4d0858608b80"},
- {file = "rpds_py-0.10.6-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:102eac53bb0bf0f9a275b438e6cf6904904908562a1463a6fc3323cf47d7a532"},
- {file = "rpds_py-0.10.6-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:40f93086eef235623aa14dbddef1b9fb4b22b99454cb39a8d2e04c994fb9868c"},
- {file = "rpds_py-0.10.6-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:e22260a4741a0e7a206e175232867b48a16e0401ef5bce3c67ca5b9705879066"},
- {file = "rpds_py-0.10.6-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f4e56860a5af16a0fcfa070a0a20c42fbb2012eed1eb5ceeddcc7f8079214281"},
- {file = "rpds_py-0.10.6-cp311-none-win32.whl", hash = "sha256:0774a46b38e70fdde0c6ded8d6d73115a7c39d7839a164cc833f170bbf539116"},
- {file = "rpds_py-0.10.6-cp311-none-win_amd64.whl", hash = "sha256:4a5ee600477b918ab345209eddafde9f91c0acd931f3776369585a1c55b04c57"},
- {file = "rpds_py-0.10.6-cp312-cp312-macosx_10_7_x86_64.whl", hash = "sha256:5ee97c683eaface61d38ec9a489e353d36444cdebb128a27fe486a291647aff6"},
- {file = "rpds_py-0.10.6-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0713631d6e2d6c316c2f7b9320a34f44abb644fc487b77161d1724d883662e31"},
- {file = "rpds_py-0.10.6-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b5a53f5998b4bbff1cb2e967e66ab2addc67326a274567697379dd1e326bded7"},
- {file = "rpds_py-0.10.6-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:6a555ae3d2e61118a9d3e549737bb4a56ff0cec88a22bd1dfcad5b4e04759175"},
- {file = "rpds_py-0.10.6-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:945eb4b6bb8144909b203a88a35e0a03d22b57aefb06c9b26c6e16d72e5eb0f0"},
- {file = "rpds_py-0.10.6-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:52c215eb46307c25f9fd2771cac8135d14b11a92ae48d17968eda5aa9aaf5071"},
- {file = "rpds_py-0.10.6-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c1b3cd23d905589cb205710b3988fc8f46d4a198cf12862887b09d7aaa6bf9b9"},
- {file = "rpds_py-0.10.6-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:64ccc28683666672d7c166ed465c09cee36e306c156e787acef3c0c62f90da5a"},
- {file = "rpds_py-0.10.6-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:516a611a2de12fbea70c78271e558f725c660ce38e0006f75139ba337d56b1f6"},
- {file = "rpds_py-0.10.6-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:9ff93d3aedef11f9c4540cf347f8bb135dd9323a2fc705633d83210d464c579d"},
- {file = "rpds_py-0.10.6-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:d858532212f0650be12b6042ff4378dc2efbb7792a286bee4489eaa7ba010586"},
- {file = "rpds_py-0.10.6-cp312-none-win32.whl", hash = "sha256:3c4eff26eddac49d52697a98ea01b0246e44ca82ab09354e94aae8823e8bda02"},
- {file = "rpds_py-0.10.6-cp312-none-win_amd64.whl", hash = "sha256:150eec465dbc9cbca943c8e557a21afdcf9bab8aaabf386c44b794c2f94143d2"},
- {file = "rpds_py-0.10.6-cp38-cp38-macosx_10_7_x86_64.whl", hash = "sha256:cf693eb4a08eccc1a1b636e4392322582db2a47470d52e824b25eca7a3977b53"},
- {file = "rpds_py-0.10.6-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:4134aa2342f9b2ab6c33d5c172e40f9ef802c61bb9ca30d21782f6e035ed0043"},
- {file = "rpds_py-0.10.6-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e782379c2028a3611285a795b89b99a52722946d19fc06f002f8b53e3ea26ea9"},
- {file = "rpds_py-0.10.6-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2f6da6d842195fddc1cd34c3da8a40f6e99e4a113918faa5e60bf132f917c247"},
- {file = "rpds_py-0.10.6-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b4a9fe992887ac68256c930a2011255bae0bf5ec837475bc6f7edd7c8dfa254e"},
- {file = "rpds_py-0.10.6-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b788276a3c114e9f51e257f2a6f544c32c02dab4aa7a5816b96444e3f9ffc336"},
- {file = "rpds_py-0.10.6-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:caa1afc70a02645809c744eefb7d6ee8fef7e2fad170ffdeacca267fd2674f13"},
- {file = "rpds_py-0.10.6-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:bddd4f91eede9ca5275e70479ed3656e76c8cdaaa1b354e544cbcf94c6fc8ac4"},
- {file = "rpds_py-0.10.6-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:775049dfa63fb58293990fc59473e659fcafd953bba1d00fc5f0631a8fd61977"},
- {file = "rpds_py-0.10.6-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:c6c45a2d2b68c51fe3d9352733fe048291e483376c94f7723458cfd7b473136b"},
- {file = "rpds_py-0.10.6-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:0699ab6b8c98df998c3eacf51a3b25864ca93dab157abe358af46dc95ecd9801"},
- {file = "rpds_py-0.10.6-cp38-none-win32.whl", hash = "sha256:ebdab79f42c5961682654b851f3f0fc68e6cc7cd8727c2ac4ffff955154123c1"},
- {file = "rpds_py-0.10.6-cp38-none-win_amd64.whl", hash = "sha256:24656dc36f866c33856baa3ab309da0b6a60f37d25d14be916bd3e79d9f3afcf"},
- {file = "rpds_py-0.10.6-cp39-cp39-macosx_10_7_x86_64.whl", hash = "sha256:0898173249141ee99ffcd45e3829abe7bcee47d941af7434ccbf97717df020e5"},
- {file = "rpds_py-0.10.6-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:9e9184fa6c52a74a5521e3e87badbf9692549c0fcced47443585876fcc47e469"},
- {file = "rpds_py-0.10.6-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5752b761902cd15073a527b51de76bbae63d938dc7c5c4ad1e7d8df10e765138"},
- {file = "rpds_py-0.10.6-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:99a57006b4ec39dbfb3ed67e5b27192792ffb0553206a107e4aadb39c5004cd5"},
- {file = "rpds_py-0.10.6-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:09586f51a215d17efdb3a5f090d7cbf1633b7f3708f60a044757a5d48a83b393"},
- {file = "rpds_py-0.10.6-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e225a6a14ecf44499aadea165299092ab0cba918bb9ccd9304eab1138844490b"},
- {file = "rpds_py-0.10.6-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b2039f8d545f20c4e52713eea51a275e62153ee96c8035a32b2abb772b6fc9e5"},
- {file = "rpds_py-0.10.6-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:34ad87a831940521d462ac11f1774edf867c34172010f5390b2f06b85dcc6014"},
- {file = "rpds_py-0.10.6-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:dcdc88b6b01015da066da3fb76545e8bb9a6880a5ebf89e0f0b2e3ca557b3ab7"},
- {file = "rpds_py-0.10.6-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:25860ed5c4e7f5e10c496ea78af46ae8d8468e0be745bd233bab9ca99bfd2647"},
- {file = "rpds_py-0.10.6-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:7854a207ef77319ec457c1eb79c361b48807d252d94348305db4f4b62f40f7f3"},
- {file = "rpds_py-0.10.6-cp39-none-win32.whl", hash = "sha256:e6fcc026a3f27c1282c7ed24b7fcac82cdd70a0e84cc848c0841a3ab1e3dea2d"},
- {file = "rpds_py-0.10.6-cp39-none-win_amd64.whl", hash = "sha256:e98c4c07ee4c4b3acf787e91b27688409d918212dfd34c872201273fdd5a0e18"},
- {file = "rpds_py-0.10.6-pp310-pypy310_pp73-macosx_10_7_x86_64.whl", hash = "sha256:68fe9199184c18d997d2e4293b34327c0009a78599ce703e15cd9a0f47349bba"},
- {file = "rpds_py-0.10.6-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:3339eca941568ed52d9ad0f1b8eb9fe0958fa245381747cecf2e9a78a5539c42"},
- {file = "rpds_py-0.10.6-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a360cfd0881d36c6dc271992ce1eda65dba5e9368575663de993eeb4523d895f"},
- {file = "rpds_py-0.10.6-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:031f76fc87644a234883b51145e43985aa2d0c19b063e91d44379cd2786144f8"},
- {file = "rpds_py-0.10.6-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1f36a9d751f86455dc5278517e8b65580eeee37d61606183897f122c9e51cef3"},
- {file = "rpds_py-0.10.6-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:052a832078943d2b2627aea0d19381f607fe331cc0eb5df01991268253af8417"},
- {file = "rpds_py-0.10.6-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:023574366002bf1bd751ebaf3e580aef4a468b3d3c216d2f3f7e16fdabd885ed"},
- {file = "rpds_py-0.10.6-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:defa2c0c68734f4a82028c26bcc85e6b92cced99866af118cd6a89b734ad8e0d"},
- {file = "rpds_py-0.10.6-pp310-pypy310_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:879fb24304ead6b62dbe5034e7b644b71def53c70e19363f3c3be2705c17a3b4"},
- {file = "rpds_py-0.10.6-pp310-pypy310_pp73-musllinux_1_2_i686.whl", hash = "sha256:53c43e10d398e365da2d4cc0bcaf0854b79b4c50ee9689652cdc72948e86f487"},
- {file = "rpds_py-0.10.6-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:3777cc9dea0e6c464e4b24760664bd8831738cc582c1d8aacf1c3f546bef3f65"},
- {file = "rpds_py-0.10.6-pp38-pypy38_pp73-macosx_10_7_x86_64.whl", hash = "sha256:40578a6469e5d1df71b006936ce95804edb5df47b520c69cf5af264d462f2cbb"},
- {file = "rpds_py-0.10.6-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:cf71343646756a072b85f228d35b1d7407da1669a3de3cf47f8bbafe0c8183a4"},
- {file = "rpds_py-0.10.6-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:10f32b53f424fc75ff7b713b2edb286fdbfc94bf16317890260a81c2c00385dc"},
- {file = "rpds_py-0.10.6-pp38-pypy38_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:81de24a1c51cfb32e1fbf018ab0bdbc79c04c035986526f76c33e3f9e0f3356c"},
- {file = "rpds_py-0.10.6-pp38-pypy38_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ac17044876e64a8ea20ab132080ddc73b895b4abe9976e263b0e30ee5be7b9c2"},
- {file = "rpds_py-0.10.6-pp38-pypy38_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5e8a78bd4879bff82daef48c14d5d4057f6856149094848c3ed0ecaf49f5aec2"},
- {file = "rpds_py-0.10.6-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:78ca33811e1d95cac8c2e49cb86c0fb71f4d8409d8cbea0cb495b6dbddb30a55"},
- {file = "rpds_py-0.10.6-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c63c3ef43f0b3fb00571cff6c3967cc261c0ebd14a0a134a12e83bdb8f49f21f"},
- {file = "rpds_py-0.10.6-pp38-pypy38_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:7fde6d0e00b2fd0dbbb40c0eeec463ef147819f23725eda58105ba9ca48744f4"},
- {file = "rpds_py-0.10.6-pp38-pypy38_pp73-musllinux_1_2_i686.whl", hash = "sha256:79edd779cfc46b2e15b0830eecd8b4b93f1a96649bcb502453df471a54ce7977"},
- {file = "rpds_py-0.10.6-pp38-pypy38_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:9164ec8010327ab9af931d7ccd12ab8d8b5dc2f4c6a16cbdd9d087861eaaefa1"},
- {file = "rpds_py-0.10.6-pp39-pypy39_pp73-macosx_10_7_x86_64.whl", hash = "sha256:d29ddefeab1791e3c751e0189d5f4b3dbc0bbe033b06e9c333dca1f99e1d523e"},
- {file = "rpds_py-0.10.6-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:30adb75ecd7c2a52f5e76af50644b3e0b5ba036321c390b8e7ec1bb2a16dd43c"},
- {file = "rpds_py-0.10.6-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dd609fafdcdde6e67a139898196698af37438b035b25ad63704fd9097d9a3482"},
- {file = "rpds_py-0.10.6-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:6eef672de005736a6efd565577101277db6057f65640a813de6c2707dc69f396"},
- {file = "rpds_py-0.10.6-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6cf4393c7b41abbf07c88eb83e8af5013606b1cdb7f6bc96b1b3536b53a574b8"},
- {file = "rpds_py-0.10.6-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ad857f42831e5b8d41a32437f88d86ead6c191455a3499c4b6d15e007936d4cf"},
- {file = "rpds_py-0.10.6-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1d7360573f1e046cb3b0dceeb8864025aa78d98be4bb69f067ec1c40a9e2d9df"},
- {file = "rpds_py-0.10.6-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d08f63561c8a695afec4975fae445245386d645e3e446e6f260e81663bfd2e38"},
- {file = "rpds_py-0.10.6-pp39-pypy39_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:f0f17f2ce0f3529177a5fff5525204fad7b43dd437d017dd0317f2746773443d"},
- {file = "rpds_py-0.10.6-pp39-pypy39_pp73-musllinux_1_2_i686.whl", hash = "sha256:442626328600bde1d09dc3bb00434f5374948838ce75c41a52152615689f9403"},
- {file = "rpds_py-0.10.6-pp39-pypy39_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:e9616f5bd2595f7f4a04b67039d890348ab826e943a9bfdbe4938d0eba606971"},
- {file = "rpds_py-0.10.6.tar.gz", hash = "sha256:4ce5a708d65a8dbf3748d2474b580d606b1b9f91b5c6ab2a316e0b0cf7a4ba50"},
+ {file = "rpds_py-0.12.0-cp310-cp310-macosx_10_7_x86_64.whl", hash = "sha256:c694bee70ece3b232df4678448fdda245fd3b1bb4ba481fb6cd20e13bb784c46"},
+ {file = "rpds_py-0.12.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:30e5ce9f501fb1f970e4a59098028cf20676dee64fc496d55c33e04bbbee097d"},
+ {file = "rpds_py-0.12.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d72a4315514e5a0b9837a086cb433b004eea630afb0cc129de76d77654a9606f"},
+ {file = "rpds_py-0.12.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:eebaf8c76c39604d52852366249ab807fe6f7a3ffb0dd5484b9944917244cdbe"},
+ {file = "rpds_py-0.12.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a239303acb0315091d54c7ff36712dba24554993b9a93941cf301391d8a997ee"},
+ {file = "rpds_py-0.12.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ced40cdbb6dd47a032725a038896cceae9ce267d340f59508b23537f05455431"},
+ {file = "rpds_py-0.12.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3c8c0226c71bd0ce9892eaf6afa77ae8f43a3d9313124a03df0b389c01f832de"},
+ {file = "rpds_py-0.12.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b8e11715178f3608874508f08e990d3771e0b8c66c73eb4e183038d600a9b274"},
+ {file = "rpds_py-0.12.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:5210a0018c7e09c75fa788648617ebba861ae242944111d3079034e14498223f"},
+ {file = "rpds_py-0.12.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:171d9a159f1b2f42a42a64a985e4ba46fc7268c78299272ceba970743a67ee50"},
+ {file = "rpds_py-0.12.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:57ec6baec231bb19bb5fd5fc7bae21231860a1605174b11585660236627e390e"},
+ {file = "rpds_py-0.12.0-cp310-none-win32.whl", hash = "sha256:7188ddc1a8887194f984fa4110d5a3d5b9b5cd35f6bafdff1b649049cbc0ce29"},
+ {file = "rpds_py-0.12.0-cp310-none-win_amd64.whl", hash = "sha256:1e04581c6117ad9479b6cfae313e212fe0dfa226ac727755f0d539cd54792963"},
+ {file = "rpds_py-0.12.0-cp311-cp311-macosx_10_7_x86_64.whl", hash = "sha256:0a38612d07a36138507d69646c470aedbfe2b75b43a4643f7bd8e51e52779624"},
+ {file = "rpds_py-0.12.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f12d69d568f5647ec503b64932874dade5a20255736c89936bf690951a5e79f5"},
+ {file = "rpds_py-0.12.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4f8a1d990dc198a6c68ec3d9a637ba1ce489b38cbfb65440a27901afbc5df575"},
+ {file = "rpds_py-0.12.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8c567c664fc2f44130a20edac73e0a867f8e012bf7370276f15c6adc3586c37c"},
+ {file = "rpds_py-0.12.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0e9e976e0dbed4f51c56db10831c9623d0fd67aac02853fe5476262e5a22acb7"},
+ {file = "rpds_py-0.12.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:efddca2d02254a52078c35cadad34762adbae3ff01c6b0c7787b59d038b63e0d"},
+ {file = "rpds_py-0.12.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d9e7f29c00577aff6b318681e730a519b235af292732a149337f6aaa4d1c5e31"},
+ {file = "rpds_py-0.12.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:389c0e38358fdc4e38e9995e7291269a3aead7acfcf8942010ee7bc5baee091c"},
+ {file = "rpds_py-0.12.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:33ab498f9ac30598b6406e2be1b45fd231195b83d948ebd4bd77f337cb6a2bff"},
+ {file = "rpds_py-0.12.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:d56b1cd606ba4cedd64bb43479d56580e147c6ef3f5d1c5e64203a1adab784a2"},
+ {file = "rpds_py-0.12.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1fa73ed22c40a1bec98d7c93b5659cd35abcfa5a0a95ce876b91adbda170537c"},
+ {file = "rpds_py-0.12.0-cp311-none-win32.whl", hash = "sha256:dbc25baa6abb205766fb8606f8263b02c3503a55957fcb4576a6bb0a59d37d10"},
+ {file = "rpds_py-0.12.0-cp311-none-win_amd64.whl", hash = "sha256:c6b52b7028b547866c2413f614ee306c2d4eafdd444b1ff656bf3295bf1484aa"},
+ {file = "rpds_py-0.12.0-cp312-cp312-macosx_10_7_x86_64.whl", hash = "sha256:9620650c364c01ed5b497dcae7c3d4b948daeae6e1883ae185fef1c927b6b534"},
+ {file = "rpds_py-0.12.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2124f9e645a94ab7c853bc0a3644e0ca8ffbe5bb2d72db49aef8f9ec1c285733"},
+ {file = "rpds_py-0.12.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:281c8b219d4f4b3581b918b816764098d04964915b2f272d1476654143801aa2"},
+ {file = "rpds_py-0.12.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:27ccc93c7457ef890b0dd31564d2a05e1aca330623c942b7e818e9e7c2669ee4"},
+ {file = "rpds_py-0.12.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d1c562a9bb72244fa767d1c1ab55ca1d92dd5f7c4d77878fee5483a22ffac808"},
+ {file = "rpds_py-0.12.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e57919c32ee295a2fca458bb73e4b20b05c115627f96f95a10f9f5acbd61172d"},
+ {file = "rpds_py-0.12.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fa35ad36440aaf1ac8332b4a4a433d4acd28f1613f0d480995f5cfd3580e90b7"},
+ {file = "rpds_py-0.12.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e6aea5c0eb5b0faf52c7b5c4a47c8bb64437173be97227c819ffa31801fa4e34"},
+ {file = "rpds_py-0.12.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:81cf9d306c04df1b45971c13167dc3bad625808aa01281d55f3cf852dde0e206"},
+ {file = "rpds_py-0.12.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:08e6e7ff286254016b945e1ab632ee843e43d45e40683b66dd12b73791366dd1"},
+ {file = "rpds_py-0.12.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:4d0a675a7acbbc16179188d8c6d0afb8628604fc1241faf41007255957335a0b"},
+ {file = "rpds_py-0.12.0-cp312-none-win32.whl", hash = "sha256:b2287c09482949e0ca0c0eb68b2aca6cf57f8af8c6dfd29dcd3bc45f17b57978"},
+ {file = "rpds_py-0.12.0-cp312-none-win_amd64.whl", hash = "sha256:8015835494b21aa7abd3b43fdea0614ee35ef6b03db7ecba9beb58eadf01c24f"},
+ {file = "rpds_py-0.12.0-cp38-cp38-macosx_10_7_x86_64.whl", hash = "sha256:6174d6ad6b58a6bcf67afbbf1723420a53d06c4b89f4c50763d6fa0a6ac9afd2"},
+ {file = "rpds_py-0.12.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:a689e1ded7137552bea36305a7a16ad2b40be511740b80748d3140614993db98"},
+ {file = "rpds_py-0.12.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f45321224144c25a62052035ce96cbcf264667bcb0d81823b1bbc22c4addd194"},
+ {file = "rpds_py-0.12.0-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:aa32205358a76bf578854bf31698a86dc8b2cb591fd1d79a833283f4a403f04b"},
+ {file = "rpds_py-0.12.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:91bd2b7cf0f4d252eec8b7046fa6a43cee17e8acdfc00eaa8b3dbf2f9a59d061"},
+ {file = "rpds_py-0.12.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3acadbab8b59f63b87b518e09c4c64b142e7286b9ca7a208107d6f9f4c393c5c"},
+ {file = "rpds_py-0.12.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:429349a510da82c85431f0f3e66212d83efe9fd2850f50f339341b6532c62fe4"},
+ {file = "rpds_py-0.12.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:05942656cb2cb4989cd50ced52df16be94d344eae5097e8583966a1d27da73a5"},
+ {file = "rpds_py-0.12.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:0c5441b7626c29dbd54a3f6f3713ec8e956b009f419ffdaaa3c80eaf98ddb523"},
+ {file = "rpds_py-0.12.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:b6b0e17d39d21698185097652c611f9cf30f7c56ccec189789920e3e7f1cee56"},
+ {file = "rpds_py-0.12.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:3b7a64d43e2a1fa2dd46b678e00cabd9a49ebb123b339ce799204c44a593ae1c"},
+ {file = "rpds_py-0.12.0-cp38-none-win32.whl", hash = "sha256:e5bbe011a2cea9060fef1bb3d668a2fd8432b8888e6d92e74c9c794d3c101595"},
+ {file = "rpds_py-0.12.0-cp38-none-win_amd64.whl", hash = "sha256:bec29b801b4adbf388314c0d050e851d53762ab424af22657021ce4b6eb41543"},
+ {file = "rpds_py-0.12.0-cp39-cp39-macosx_10_7_x86_64.whl", hash = "sha256:1096ca0bf2d3426cbe79d4ccc91dc5aaa73629b08ea2d8467375fad8447ce11a"},
+ {file = "rpds_py-0.12.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:48aa98987d54a46e13e6954880056c204700c65616af4395d1f0639eba11764b"},
+ {file = "rpds_py-0.12.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7979d90ee2190d000129598c2b0c82f13053dba432b94e45e68253b09bb1f0f6"},
+ {file = "rpds_py-0.12.0-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:88857060b690a57d2ea8569bca58758143c8faa4639fb17d745ce60ff84c867e"},
+ {file = "rpds_py-0.12.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4eb74d44776b0fb0782560ea84d986dffec8ddd94947f383eba2284b0f32e35e"},
+ {file = "rpds_py-0.12.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f62581d7e884dd01ee1707b7c21148f61f2febb7de092ae2f108743fcbef5985"},
+ {file = "rpds_py-0.12.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6f5dcb658d597410bb7c967c1d24eaf9377b0d621358cbe9d2ff804e5dd12e81"},
+ {file = "rpds_py-0.12.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9bf9acce44e967a5103fcd820fc7580c7b0ab8583eec4e2051aec560f7b31a63"},
+ {file = "rpds_py-0.12.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:240687b5be0f91fbde4936a329c9b7589d9259742766f74de575e1b2046575e4"},
+ {file = "rpds_py-0.12.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:25740fb56e8bd37692ed380e15ec734be44d7c71974d8993f452b4527814601e"},
+ {file = "rpds_py-0.12.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:a54917b7e9cd3a67e429a630e237a90b096e0ba18897bfb99ee8bd1068a5fea0"},
+ {file = "rpds_py-0.12.0-cp39-none-win32.whl", hash = "sha256:b92aafcfab3d41580d54aca35a8057341f1cfc7c9af9e8bdfc652f83a20ced31"},
+ {file = "rpds_py-0.12.0-cp39-none-win_amd64.whl", hash = "sha256:cd316dbcc74c76266ba94eb021b0cc090b97cca122f50bd7a845f587ff4bf03f"},
+ {file = "rpds_py-0.12.0-pp310-pypy310_pp73-macosx_10_7_x86_64.whl", hash = "sha256:0853da3d5e9bc6a07b2486054a410b7b03f34046c123c6561b535bb48cc509e1"},
+ {file = "rpds_py-0.12.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:cb41ad20064e18a900dd427d7cf41cfaec83bcd1184001f3d91a1f76b3fcea4e"},
+ {file = "rpds_py-0.12.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b710bf7e7ae61957d5c4026b486be593ed3ec3dca3e5be15e0f6d8cf5d0a4990"},
+ {file = "rpds_py-0.12.0-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a952ae3eb460c6712388ac2ec706d24b0e651b9396d90c9a9e0a69eb27737fdc"},
+ {file = "rpds_py-0.12.0-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0bedd91ae1dd142a4dc15970ed2c729ff6c73f33a40fa84ed0cdbf55de87c777"},
+ {file = "rpds_py-0.12.0-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:761531076df51309075133a6bc1db02d98ec7f66e22b064b1d513bc909f29743"},
+ {file = "rpds_py-0.12.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a2baa6be130e8a00b6cbb9f18a33611ec150b4537f8563bddadb54c1b74b8193"},
+ {file = "rpds_py-0.12.0-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f05450fa1cd7c525c0b9d1a7916e595d3041ac0afbed2ff6926e5afb6a781b7f"},
+ {file = "rpds_py-0.12.0-pp310-pypy310_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:81c4d1a3a564775c44732b94135d06e33417e829ff25226c164664f4a1046213"},
+ {file = "rpds_py-0.12.0-pp310-pypy310_pp73-musllinux_1_2_i686.whl", hash = "sha256:e888be685fa42d8b8a3d3911d5604d14db87538aa7d0b29b1a7ea80d354c732d"},
+ {file = "rpds_py-0.12.0-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:6f8d7fe73d1816eeb5378409adc658f9525ecbfaf9e1ede1e2d67a338b0c7348"},
+ {file = "rpds_py-0.12.0-pp38-pypy38_pp73-macosx_10_7_x86_64.whl", hash = "sha256:0831d3ecdea22e4559cc1793f22e77067c9d8c451d55ae6a75bf1d116a8e7f42"},
+ {file = "rpds_py-0.12.0-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:513ccbf7420c30e283c25c82d5a8f439d625a838d3ba69e79a110c260c46813f"},
+ {file = "rpds_py-0.12.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:301bd744a1adaa2f6a5e06c98f1ac2b6f8dc31a5c23b838f862d65e32fca0d4b"},
+ {file = "rpds_py-0.12.0-pp38-pypy38_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f8832a4f83d4782a8f5a7b831c47e8ffe164e43c2c148c8160ed9a6d630bc02a"},
+ {file = "rpds_py-0.12.0-pp38-pypy38_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4b2416ed743ec5debcf61e1242e012652a4348de14ecc7df3512da072b074440"},
+ {file = "rpds_py-0.12.0-pp38-pypy38_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:35585a8cb5917161f42c2104567bb83a1d96194095fc54a543113ed5df9fa436"},
+ {file = "rpds_py-0.12.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d389ff1e95b6e46ebedccf7fd1fadd10559add595ac6a7c2ea730268325f832c"},
+ {file = "rpds_py-0.12.0-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9b007c2444705a2dc4a525964fd4dd28c3320b19b3410da6517cab28716f27d3"},
+ {file = "rpds_py-0.12.0-pp38-pypy38_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:188912b22b6c8225f4c4ffa020a2baa6ad8fabb3c141a12dbe6edbb34e7f1425"},
+ {file = "rpds_py-0.12.0-pp38-pypy38_pp73-musllinux_1_2_i686.whl", hash = "sha256:1b4cf9ab9a0ae0cb122685209806d3f1dcb63b9fccdf1424fb42a129dc8c2faa"},
+ {file = "rpds_py-0.12.0-pp38-pypy38_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:2d34a5450a402b00d20aeb7632489ffa2556ca7b26f4a63c35f6fccae1977427"},
+ {file = "rpds_py-0.12.0-pp39-pypy39_pp73-macosx_10_7_x86_64.whl", hash = "sha256:466030a42724780794dea71eb32db83cc51214d66ab3fb3156edd88b9c8f0d78"},
+ {file = "rpds_py-0.12.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:68172622a5a57deb079a2c78511c40f91193548e8ab342c31e8cb0764d362459"},
+ {file = "rpds_py-0.12.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:54cdfcda59251b9c2f87a05d038c2ae02121219a04d4a1e6fc345794295bdc07"},
+ {file = "rpds_py-0.12.0-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:6b75b912a0baa033350367a8a07a8b2d44fd5b90c890bfbd063a8a5f945f644b"},
+ {file = "rpds_py-0.12.0-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:47aeceb4363851d17f63069318ba5721ae695d9da55d599b4d6fb31508595278"},
+ {file = "rpds_py-0.12.0-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0525847f83f506aa1e28eb2057b696fe38217e12931c8b1b02198cfe6975e142"},
+ {file = "rpds_py-0.12.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:efbe0b5e0fd078ed7b005faa0170da4f72666360f66f0bb2d7f73526ecfd99f9"},
+ {file = "rpds_py-0.12.0-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:0fadfdda275c838cba5102c7f90a20f2abd7727bf8f4a2b654a5b617529c5c18"},
+ {file = "rpds_py-0.12.0-pp39-pypy39_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:56dd500411d03c5e9927a1eb55621e906837a83b02350a9dc401247d0353717c"},
+ {file = "rpds_py-0.12.0-pp39-pypy39_pp73-musllinux_1_2_i686.whl", hash = "sha256:6915fc9fa6b3ec3569566832e1bb03bd801c12cea030200e68663b9a87974e76"},
+ {file = "rpds_py-0.12.0-pp39-pypy39_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:5f1519b080d8ce0a814f17ad9fb49fb3a1d4d7ce5891f5c85fc38631ca3a8dc4"},
+ {file = "rpds_py-0.12.0.tar.gz", hash = "sha256:7036316cc26b93e401cedd781a579be606dad174829e6ad9e9c5a0da6e036f80"},
]
[[package]]
name = "ruamel-yaml"
-version = "0.18.4"
+version = "0.18.5"
description = "ruamel.yaml is a YAML parser/emitter that supports roundtrip preservation of comments, seq/map flow style, and map key order"
optional = false
-python-versions = ">=3"
+python-versions = ">=3.7"
files = [
- {file = "ruamel.yaml-0.18.4-py3-none-any.whl", hash = "sha256:ca864776af7b0cbcbb223c38707a440bfabea926ba5b4163b2ef4991aae8f8c1"},
- {file = "ruamel.yaml-0.18.4.tar.gz", hash = "sha256:a2778930d2573358f7c43f26e4bd5715015dccebf53c9943ed611200c1e2adcd"},
+ {file = "ruamel.yaml-0.18.5-py3-none-any.whl", hash = "sha256:a013ac02f99a69cdd6277d9664689eb1acba07069f912823177c5eced21a6ada"},
+ {file = "ruamel.yaml-0.18.5.tar.gz", hash = "sha256:61917e3a35a569c1133a8f772e1226961bf5a1198bea7e23f06a0841dea1ab0e"},
]
[package.dependencies]
@@ -3445,28 +3445,28 @@ files = [
[[package]]
name = "ruff"
-version = "0.1.3"
-description = "An extremely fast Python linter, written in Rust."
+version = "0.1.4"
+description = "An extremely fast Python linter and code formatter, written in Rust."
optional = false
python-versions = ">=3.7"
files = [
- {file = "ruff-0.1.3-py3-none-macosx_10_7_x86_64.whl", hash = "sha256:b46d43d51f7061652eeadb426a9e3caa1e0002470229ab2fc19de8a7b0766901"},
- {file = "ruff-0.1.3-py3-none-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:b8afeb9abd26b4029c72adc9921b8363374f4e7edb78385ffaa80278313a15f9"},
- {file = "ruff-0.1.3-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ca3cf365bf32e9ba7e6db3f48a4d3e2c446cd19ebee04f05338bc3910114528b"},
- {file = "ruff-0.1.3-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:4874c165f96c14a00590dcc727a04dca0cfd110334c24b039458c06cf78a672e"},
- {file = "ruff-0.1.3-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eec2dd31eed114e48ea42dbffc443e9b7221976554a504767ceaee3dd38edeb8"},
- {file = "ruff-0.1.3-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:dc3ec4edb3b73f21b4aa51337e16674c752f1d76a4a543af56d7d04e97769613"},
- {file = "ruff-0.1.3-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2e3de9ed2e39160800281848ff4670e1698037ca039bda7b9274f849258d26ce"},
- {file = "ruff-0.1.3-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1c595193881922cc0556a90f3af99b1c5681f0c552e7a2a189956141d8666fe8"},
- {file = "ruff-0.1.3-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0f75e670d529aa2288cd00fc0e9b9287603d95e1536d7a7e0cafe00f75e0dd9d"},
- {file = "ruff-0.1.3-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:76dd49f6cd945d82d9d4a9a6622c54a994689d8d7b22fa1322983389b4892e20"},
- {file = "ruff-0.1.3-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:918b454bc4f8874a616f0d725590277c42949431ceb303950e87fef7a7d94cb3"},
- {file = "ruff-0.1.3-py3-none-musllinux_1_2_i686.whl", hash = "sha256:d8859605e729cd5e53aa38275568dbbdb4fe882d2ea2714c5453b678dca83784"},
- {file = "ruff-0.1.3-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:0b6c55f5ef8d9dd05b230bb6ab80bc4381ecb60ae56db0330f660ea240cb0d4a"},
- {file = "ruff-0.1.3-py3-none-win32.whl", hash = "sha256:3e7afcbdcfbe3399c34e0f6370c30f6e529193c731b885316c5a09c9e4317eef"},
- {file = "ruff-0.1.3-py3-none-win_amd64.whl", hash = "sha256:7a18df6638cec4a5bd75350639b2bb2a2366e01222825562c7346674bdceb7ea"},
- {file = "ruff-0.1.3-py3-none-win_arm64.whl", hash = "sha256:12fd53696c83a194a2db7f9a46337ce06445fb9aa7d25ea6f293cf75b21aca9f"},
- {file = "ruff-0.1.3.tar.gz", hash = "sha256:3ba6145369a151401d5db79f0a47d50e470384d0d89d0d6f7fab0b589ad07c34"},
+ {file = "ruff-0.1.4-py3-none-macosx_10_7_x86_64.whl", hash = "sha256:864958706b669cce31d629902175138ad8a069d99ca53514611521f532d91495"},
+ {file = "ruff-0.1.4-py3-none-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:9fdd61883bb34317c788af87f4cd75dfee3a73f5ded714b77ba928e418d6e39e"},
+ {file = "ruff-0.1.4-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b4eaca8c9cc39aa7f0f0d7b8fe24ecb51232d1bb620fc4441a61161be4a17539"},
+ {file = "ruff-0.1.4-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a9a1301dc43cbf633fb603242bccd0aaa34834750a14a4c1817e2e5c8d60de17"},
+ {file = "ruff-0.1.4-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:78e8db8ab6f100f02e28b3d713270c857d370b8d61871d5c7d1702ae411df683"},
+ {file = "ruff-0.1.4-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:80fea754eaae06335784b8ea053d6eb8e9aac75359ebddd6fee0858e87c8d510"},
+ {file = "ruff-0.1.4-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6bc02a480d4bfffd163a723698da15d1a9aec2fced4c06f2a753f87f4ce6969c"},
+ {file = "ruff-0.1.4-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9862811b403063765b03e716dac0fda8fdbe78b675cd947ed5873506448acea4"},
+ {file = "ruff-0.1.4-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:58826efb8b3efbb59bb306f4b19640b7e366967a31c049d49311d9eb3a4c60cb"},
+ {file = "ruff-0.1.4-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:fdfd453fc91d9d86d6aaa33b1bafa69d114cf7421057868f0b79104079d3e66e"},
+ {file = "ruff-0.1.4-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:e8791482d508bd0b36c76481ad3117987301b86072158bdb69d796503e1c84a8"},
+ {file = "ruff-0.1.4-py3-none-musllinux_1_2_i686.whl", hash = "sha256:01206e361021426e3c1b7fba06ddcb20dbc5037d64f6841e5f2b21084dc51800"},
+ {file = "ruff-0.1.4-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:645591a613a42cb7e5c2b667cbefd3877b21e0252b59272ba7212c3d35a5819f"},
+ {file = "ruff-0.1.4-py3-none-win32.whl", hash = "sha256:99908ca2b3b85bffe7e1414275d004917d1e0dfc99d497ccd2ecd19ad115fd0d"},
+ {file = "ruff-0.1.4-py3-none-win_amd64.whl", hash = "sha256:1dfd6bf8f6ad0a4ac99333f437e0ec168989adc5d837ecd38ddb2cc4a2e3db8a"},
+ {file = "ruff-0.1.4-py3-none-win_arm64.whl", hash = "sha256:d98ae9ebf56444e18a3e3652b3383204748f73e247dea6caaf8b52d37e6b32da"},
+ {file = "ruff-0.1.4.tar.gz", hash = "sha256:21520ecca4cc555162068d87c747b8f95e1e95f8ecfcbbe59e8dd00710586315"},
]
[[package]]
@@ -3537,13 +3537,13 @@ test = ["asv", "gmpy2", "mpmath", "pytest", "pytest-cov", "pytest-xdist", "sciki
[[package]]
name = "selenium"
-version = "4.15.1"
+version = "4.15.2"
description = ""
optional = false
python-versions = ">=3.8"
files = [
- {file = "selenium-4.15.1-py3-none-any.whl", hash = "sha256:e3a4ebdcc3eed27eec69f8000d798923dbf4897c97cc6441eb88a1386809170d"},
- {file = "selenium-4.15.1.tar.gz", hash = "sha256:8f0436b5949f1d4aa742f3dff0d748b955c371be92db8b6b008bf9c9ca227de7"},
+ {file = "selenium-4.15.2-py3-none-any.whl", hash = "sha256:9e82cd1ac647fb73cf0d4a6e280284102aaa3c9d94f0fa6e6cc4b5db6a30afbf"},
+ {file = "selenium-4.15.2.tar.gz", hash = "sha256:22eab5a1724c73d51b240a69ca702997b717eee4ba1f6065bf5d6b44dba01d48"},
]
[package.dependencies]
@@ -4147,13 +4147,13 @@ telegram = ["requests"]
[[package]]
name = "trio"
-version = "0.22.2"
+version = "0.23.1"
description = "A friendly Python library for async concurrency and I/O"
optional = false
-python-versions = ">=3.7"
+python-versions = ">=3.8"
files = [
- {file = "trio-0.22.2-py3-none-any.whl", hash = "sha256:f43da357620e5872b3d940a2e3589aa251fd3f881b65a608d742e00809b1ec38"},
- {file = "trio-0.22.2.tar.gz", hash = "sha256:3887cf18c8bcc894433420305468388dac76932e9668afa1c49aa3806b6accb3"},
+ {file = "trio-0.23.1-py3-none-any.whl", hash = "sha256:bb4abb3f4af23f96679e7c8cdabb8b234520f2498550d2cf63ebfd95f2ce27fe"},
+ {file = "trio-0.23.1.tar.gz", hash = "sha256:16f89f7dcc8f7b9dcdec1fcd863e0c039af6d0f9a22f8dfd56f75d75ec73fd48"},
]
[package.dependencies]
@@ -4162,7 +4162,7 @@ cffi = {version = ">=1.14", markers = "os_name == \"nt\" and implementation_name
exceptiongroup = {version = ">=1.0.0rc9", markers = "python_version < \"3.11\""}
idna = "*"
outcome = "*"
-sniffio = "*"
+sniffio = ">=1.3.0"
sortedcontainers = "*"
[[package]]
diff --git a/backend/src/monarch_py/api/search.py b/backend/src/monarch_py/api/search.py
index b7bf8d256..afbda3f46 100644
--- a/backend/src/monarch_py/api/search.py
+++ b/backend/src/monarch_py/api/search.py
@@ -62,3 +62,24 @@ async def autocomplete(
"""
response = solr().autocomplete(q=q)
return response
+
+
+@router.get("/mappings")
+async def mappings(
+ entity_id: Union[List[str], None] = Query(default=None),
+ subject_id: Union[List[str], None] = Query(default=None),
+ predicate_id: Union[List[str], None] = Query(default=None),
+ object_id: Union[List[str], None] = Query(default=None),
+ mapping_justification: Union[List[str], None] = Query(default=None),
+ pagination: PaginationParams = Depends(),
+):
+ response = solr().get_mappings(
+ entity_id=entity_id,
+ subject_id=subject_id,
+ predicate_id=predicate_id,
+ object_id=object_id,
+ mapping_justification=mapping_justification,
+ offset=pagination.offset,
+ limit=pagination.limit,
+ )
+ return response
diff --git a/backend/src/monarch_py/cli.py b/backend/src/monarch_py/cli.py
index 9b1c0c41d..40ba69e15 100644
--- a/backend/src/monarch_py/cli.py
+++ b/backend/src/monarch_py/cli.py
@@ -307,5 +307,27 @@ def multi_entity_associations(
solr_cli.multi_entity_associations(**locals())
+@app.command("mappings")
+def mappings(
+ entity_id: List[str] = typer.Option(None, "--entity-id", "-e", help="entity ID to get mappings for"),
+ subject_id: List[str] = typer.Option(None, "--subject-id", "-s", help="subject ID to get mappings for"),
+ predicate_id: List[str] = typer.Option(None, "--predicate-id", "-p", help="predicate ID to get mappings for"),
+ object_id: List[str] = typer.Option(None, "--object-id", "-o", help="object ID to get mappings for"),
+ mapping_justification: List[str] = typer.Option(
+ None, "--mapping-justification", "-m", help="mapping justification to get mappings for"
+ ),
+ offset: int = typer.Option(0, "--offset", help="The offset of the first mapping to be retrieved"),
+ limit: int = typer.Option(20, "--limit", "-l", help="The number of mappings to return"),
+ fmt: str = typer.Option(
+ "json",
+ "--format",
+ "-f",
+ help="The format of the output (json, yaml, tsv, table)",
+ ),
+ output: str = typer.Option(None, "--output", "-O", help="The path to the output file"),
+):
+ solr_cli.mappings(**locals())
+
+
if __name__ == "__main__":
app()
diff --git a/backend/src/monarch_py/datamodels/model.py b/backend/src/monarch_py/datamodels/model.py
index 2d1df70be..b735b6a77 100644
--- a/backend/src/monarch_py/datamodels/model.py
+++ b/backend/src/monarch_py/datamodels/model.py
@@ -2,7 +2,7 @@
from datetime import datetime, date
from enum import Enum
from typing import List, Dict, Optional, Any, Union
-from pydantic import BaseModel as BaseModel, Field
+from pydantic import BaseModel as BaseModel, ConfigDict, Field
import sys
if sys.version_info >= (3, 8):
@@ -435,6 +435,7 @@ class Mapping(ConfiguredBaseModel):
object_id: str = Field(...)
object_label: Optional[str] = Field(None, description="""The name of the object entity""")
mapping_justification: Optional[str] = Field(None)
+ id: str = Field(...)
class Node(Entity):
@@ -543,6 +544,10 @@ class MappingResults(Results):
SSSOM Mappings returned as a results collection
"""
+ items: List[Mapping] = Field(
+ default_factory=list,
+ description="""A collection of items, with the type to be overriden by slot_usage""",
+ )
limit: int = Field(..., description="""number of items to return in a response""")
offset: int = Field(..., description="""offset into the total number of items""")
total: int = Field(..., description="""total number of items matching a query""")
diff --git a/backend/src/monarch_py/datamodels/model.yaml b/backend/src/monarch_py/datamodels/model.yaml
index b7bc4323d..33604a394 100644
--- a/backend/src/monarch_py/datamodels/model.yaml
+++ b/backend/src/monarch_py/datamodels/model.yaml
@@ -210,9 +210,12 @@ classes:
- object_id
- object_label
- mapping_justification
+ - id
MappingResults:
description: SSSOM Mappings returned as a results collection
is_a: Results
+ slots:
+ - items
slot_usage:
items:
range: Mapping
diff --git a/backend/src/monarch_py/implementations/solr/solr_implementation.py b/backend/src/monarch_py/implementations/solr/solr_implementation.py
index a4c895ba7..bc3afe350 100644
--- a/backend/src/monarch_py/implementations/solr/solr_implementation.py
+++ b/backend/src/monarch_py/implementations/solr/solr_implementation.py
@@ -11,6 +11,7 @@
CategoryGroupedAssociationResults,
Entity,
HistoPheno,
+ MappingResults,
MultiEntityAssociationResults,
Node,
NodeHierarchy,
@@ -26,6 +27,7 @@
parse_autocomplete,
parse_entity,
parse_histopheno,
+ parse_mappings,
parse_search,
)
from monarch_py.implementations.solr.solr_query_utils import (
@@ -241,7 +243,7 @@ def get_associations(
limit=limit,
)
query_result = solr.query(query)
- associations = parse_associations(query_result)
+ associations = parse_associations(query_result, offset, limit)
return associations
def get_histopheno(self, subject_closure: str = None) -> HistoPheno:
@@ -427,12 +429,21 @@ def get_mappings(
predicate_id: List[str] = None,
object_id: List[str] = None,
mapping_justification: List[str] = None,
+ offset: int = 0,
+ limit: int = 20,
) -> MappingResults:
solr = SolrService(base_url=self.base_url, core=core.SSSOM)
query = build_mapping_query(
- entity_id=entity_id,
- subject_id=subject_id,
- predicate_id=predicate_id,
- object_id=object_id,
- mapping_justification=mapping_justification,
+ entity_id=[entity_id] if isinstance(entity_id, str) else entity_id,
+ subject_id=[subject_id] if isinstance(subject_id, str) else subject_id,
+ predicate_id=[predicate_id] if isinstance(predicate_id, str) else predicate_id,
+ object_id=[object_id] if isinstance(object_id, str) else object_id,
+ mapping_justification=[mapping_justification]
+ if isinstance(mapping_justification, str)
+ else mapping_justification,
+ offset=offset,
+ limit=limit,
)
+ query_result = solr.query(query)
+ mappings = parse_mappings(query_result, offset, limit)
+ return mappings
diff --git a/backend/src/monarch_py/implementations/solr/solr_parsers.py b/backend/src/monarch_py/implementations/solr/solr_parsers.py
index 3700e7239..de054b77e 100644
--- a/backend/src/monarch_py/implementations/solr/solr_parsers.py
+++ b/backend/src/monarch_py/implementations/solr/solr_parsers.py
@@ -170,7 +170,7 @@ def parse_autocomplete(query_result: SolrQueryResult) -> SearchResults:
return SearchResults(limit=10, offset=0, total=total, items=items)
-def parse_mapping(query_result: SolrQueryResult, offset: int, limit: int) -> MappingResults:
+def parse_mappings(query_result: SolrQueryResult, offset: int, limit: int) -> MappingResults:
total = query_result.response.num_found
items = []
for doc in query_result.response.docs:
diff --git a/backend/src/monarch_py/solr_cli.py b/backend/src/monarch_py/solr_cli.py
index 9d11b64af..e45807375 100644
--- a/backend/src/monarch_py/solr_cli.py
+++ b/backend/src/monarch_py/solr_cli.py
@@ -96,7 +96,7 @@ def entity(
"-f",
help="The format of the output (json, yaml, tsv, table)",
),
- output: str = typer.Option(None, "--output", "-o", help="The path to the output file"),
+ output: str = typer.Option(None, "--output", "-O", help="The path to the output file"),
):
"""
Retrieve an entity by ID
@@ -123,11 +123,13 @@ def entity(
@solr_app.command("associations")
def associations(
- category: List[str] = typer.Option(None, "--category", "-c", help="Comma-separated list of categories"),
- subject: List[str] = typer.Option(None, "--subject", "-s", help="Comma-separated list of subjects"),
- predicate: List[str] = typer.Option(None, "--predicate", "-p", help="Comma-separated list of predicates"),
- object: List[str] = typer.Option(None, "--object", "-o", help="Comma-separated list of objects"),
- entity: List[str] = typer.Option(None, "--entity", "-e", help="Comma-separated list of entities"),
+ category: List[str] = typer.Option(None, "--category", "-c", help="Category to get associations for"),
+ subject: List[str] = typer.Option(None, "--subject", "-s", help="Subject ID to get associations for"),
+ predicate: List[str] = typer.Option(None, "--predicate", "-p", help="Predicate ID to get associations for"),
+ object: List[str] = typer.Option(None, "--object", "-o", help="Object ID to get associations for"),
+ entity: List[str] = typer.Option(
+ None, "--entity", "-e", help="Entity (subject or object) ID to get associations for"
+ ),
direct: bool = typer.Option(
False,
"--direct",
@@ -142,22 +144,22 @@ def associations(
"-f",
help="The format of the output (json, yaml, tsv, table)",
),
- output: str = typer.Option(None, "--output", "-o", help="The path to the output file"),
+ output: str = typer.Option(None, "--output", "-O", help="The path to the output file"),
):
"""
Paginate through associations
Args:
- category: A comma-separated list of categories
- subject: A comma-separated list of subjects
- predicate: A comma-separated list of predicates
- object: A comma-separated list of objects
- entity: A comma-separated list of entities
- limit: The number of associations to return
- direct: Whether to exclude associations with subject/object as ancestors
+ category: The category of the association (multi-valued)
+ subject: The subject of the association (multi-valued)
+ predicate: The predicate of the association (multi-valued)
+ object: The object of the association (multi-valued)
+ entity: The entity (subject or object) of the association (multi-valued)
+ limit: The number of associations to return (default 20)
+ direct: Whether to exclude associations with subject/object as ancestors (default False)
offset: The offset of the first association to be retrieved
- fmt: The format of the output (json, yaml, tsv, table)
- output: The path to the output file (stdout if not specified)
+ fmt: The format of the output (json, yaml, tsv, table) (default json)
+ output: The path to the output file (stdout if not specified) (default None)
"""
args = locals()
args.pop("fmt", None)
@@ -182,7 +184,7 @@ def multi_entity_associations(
"-f",
help="The format of the output (json, yaml, tsv, table)",
),
- output: str = typer.Option(None, "--output", "-o", help="The path to the output file"),
+ output: str = typer.Option(None, "--output", "-O", help="The path to the output file"),
):
"""
Paginate through associations for multiple entities
@@ -222,7 +224,7 @@ def search(
"-f",
help="The format of the output (json, yaml, tsv, table)",
),
- output: str = typer.Option(None, "--output", "-o", help="The path to the output file"),
+ output: str = typer.Option(None, "--output", "-O", help="The path to the output file"),
# sort: str = typer.Option(None, "--sort", "-s"),
):
"""
@@ -257,7 +259,7 @@ def autocomplete(
"-f",
help="The format of the output (json, yaml, tsv, table)",
),
- output: str = typer.Option(None, "--output", "-o", help="The path to the output file"),
+ output: str = typer.Option(None, "--output", "-O", help="The path to the output file"),
):
"""
Return entity autcomplete matches for a query string
@@ -282,7 +284,7 @@ def histopheno(
"-f",
help="The format of the output (json, yaml, tsv, table)",
),
- output: str = typer.Option(None, "--output", "-o", help="The path to the output file"),
+ output: str = typer.Option(None, "--output", "-O", help="The path to the output file"),
):
"""
Retrieve the histopheno associations for a given subject
@@ -313,7 +315,7 @@ def association_counts(
"-f",
help="The format of the output (json, yaml, tsv, table)",
),
- output: str = typer.Option(None, "--output", "-o", help="The path to the output file"),
+ output: str = typer.Option(None, "--output", "-O", help="The path to the output file"),
):
"""
Retrieve the association counts for a given entity
@@ -349,8 +351,36 @@ def association_table(
"-f",
help="The format of the output (json, yaml, tsv, table)",
),
- output: str = typer.Option(None, "--output", "-o", help="The path to the output file"),
+ output: str = typer.Option(None, "--output", "-O", help="The path to the output file"),
):
solr = get_solr(update=False)
response = solr.get_association_table(entity=entity, category=category, q=q, limit=limit, offset=offset)
format_output(fmt, response, output)
+
+
+@solr_app.command("mappings")
+def mappings(
+ entity_id: List[str] = typer.Option(None, "--entity-id", "-e", help="entity ID to get mappings for"),
+ subject_id: List[str] = typer.Option(None, "--subject-id", "-s", help="subject ID to get mappings for"),
+ predicate_id: List[str] = typer.Option(None, "--predicate-id", "-p", help="predicate ID to get mappings for"),
+ object_id: List[str] = typer.Option(None, "--object-id", "-o", help="object ID to get mappings for"),
+ mapping_justification: List[str] = typer.Option(
+ None, "--mapping-justification", "-m", help="mapping justification to get mappings for"
+ ),
+ offset: int = typer.Option(0, "--offset", help="The offset of the first mapping to be retrieved"),
+ limit: int = typer.Option(20, "--limit", "-l", help="The number of mappings to return"),
+ fmt: str = typer.Option(
+ "json",
+ "--format",
+ "-f",
+ help="The format of the output (json, yaml, tsv, table)",
+ ),
+ output: str = typer.Option(None, "--output", "-O", help="The path to the output file"),
+):
+ args = locals()
+ args.pop("fmt", None)
+ args.pop("output", None)
+
+ solr = get_solr(update=False)
+ response = solr.get_mappings(**args)
+ format_output(fmt, response, output)
diff --git a/frontend/src/api/model.ts b/frontend/src/api/model.ts
index d6d59466f..febc18638 100644
--- a/frontend/src/api/model.ts
+++ b/frontend/src/api/model.ts
@@ -4,6 +4,7 @@ export type ExpandedCurieId = string;
export type EntityId = string;
export type HistoPhenoId = string;
export type HistoBinId = string;
+export type MappingId = string;
export type MultiEntityAssociationResultsId = string;
export type NodeId = string;
export type SearchResultId = string;
@@ -375,11 +376,14 @@ export interface Mapping {
/** The name of the object entity */
object_label?: string,
mapping_justification?: string,
+ id: string,
};
/**
* SSSOM Mappings returned as a results collection
*/
export interface MappingResults extends Results {
+ /** A collection of items, with the type to be overriden by slot_usage */
+ items: Mapping[],
/** number of items to return in a response */
limit: number,
/** offset into the total number of items */
From 59d71832fdaad896e57274f8823a2a704949bb7f Mon Sep 17 00:00:00 2001
From: glass-ships
Date: Wed, 8 Nov 2023 12:26:37 -0700
Subject: [PATCH 5/9] update fixtures, add mapping tests
---
backend/src/monarch_py/api/main.py | 4 +-
.../implementations/solr/solr_parsers.py | 2 +-
backend/tests/api/test_mapping_endpoint.py | 18 ++++
.../fixtures/association_counts_response.py | 2 +-
backend/tests/fixtures/histopheno_response.py | 2 +-
backend/tests/fixtures/mapping_query.py | 21 +++++
backend/tests/fixtures/mapping_response.py | 87 +++++++++++++++++++
backend/tests/fixtures/mappings.py | 75 ++++++++++++++++
backend/tests/fixtures/search_response.py | 2 +-
backend/tests/unit/test_solr_parsers.py | 10 +++
backend/tests/unit/test_solr_queries.py | 7 ++
frontend/fixtures/mappings.json | 70 +++++++++++++++
scripts/generate_fixtures.py | 9 +-
13 files changed, 301 insertions(+), 8 deletions(-)
create mode 100644 backend/tests/api/test_mapping_endpoint.py
create mode 100644 backend/tests/fixtures/mapping_query.py
create mode 100644 backend/tests/fixtures/mapping_response.py
create mode 100644 backend/tests/fixtures/mappings.py
create mode 100644 frontend/fixtures/mappings.json
diff --git a/backend/src/monarch_py/api/main.py b/backend/src/monarch_py/api/main.py
index 7bba7265a..1e0cbe98d 100644
--- a/backend/src/monarch_py/api/main.py
+++ b/backend/src/monarch_py/api/main.py
@@ -22,10 +22,10 @@ async def initialize_app():
CurieService()
-app.include_router(entity.router, prefix=f"{PREFIX}/entity")
app.include_router(association.router, prefix=f"{PREFIX}/association")
-app.include_router(search.router, prefix=PREFIX)
+app.include_router(entity.router, prefix=f"{PREFIX}/entity")
app.include_router(histopheno.router, prefix=f"{PREFIX}/histopheno")
+app.include_router(search.router, prefix=PREFIX)
app.include_router(semsim.router, prefix=f"{PREFIX}/semsim")
# Allow CORS
diff --git a/backend/src/monarch_py/implementations/solr/solr_parsers.py b/backend/src/monarch_py/implementations/solr/solr_parsers.py
index de054b77e..f2dcbae2a 100644
--- a/backend/src/monarch_py/implementations/solr/solr_parsers.py
+++ b/backend/src/monarch_py/implementations/solr/solr_parsers.py
@@ -170,7 +170,7 @@ def parse_autocomplete(query_result: SolrQueryResult) -> SearchResults:
return SearchResults(limit=10, offset=0, total=total, items=items)
-def parse_mappings(query_result: SolrQueryResult, offset: int, limit: int) -> MappingResults:
+def parse_mappings(query_result: SolrQueryResult, offset: int = 0, limit: int = 20) -> MappingResults:
total = query_result.response.num_found
items = []
for doc in query_result.response.docs:
diff --git a/backend/tests/api/test_mapping_endpoint.py b/backend/tests/api/test_mapping_endpoint.py
new file mode 100644
index 000000000..6752c1a06
--- /dev/null
+++ b/backend/tests/api/test_mapping_endpoint.py
@@ -0,0 +1,18 @@
+from unittest.mock import MagicMock, patch
+
+from fastapi.testclient import TestClient
+from httpx import Response
+from monarch_py.api.search import router
+
+client = TestClient(router)
+
+
+def test_mappings(search):
+ with patch.object(
+ client, "get", MagicMock(return_value=Response(200, json=search, headers={"content-type": "application/json"}))
+ ):
+ response = client.get("/mappings?entity_id=MONDO:0000015")
+ assert response.status_code == 200
+ assert response.headers["content-type"] == "application/json"
+ assert response.json() == search
+
diff --git a/backend/tests/fixtures/association_counts_response.py b/backend/tests/fixtures/association_counts_response.py
index b223b0016..8878112b5 100644
--- a/backend/tests/fixtures/association_counts_response.py
+++ b/backend/tests/fixtures/association_counts_response.py
@@ -5,7 +5,7 @@
def association_counts_response():
return {
"responseHeader": {
- "QTime": 1,
+ "QTime": 0,
"params": {
"facet.query": [
'(category:"biolink:DiseaseToPhenotypicFeatureAssociation") AND (subject:"MONDO:0020121" OR subject_closure:"MONDO:0020121")',
diff --git a/backend/tests/fixtures/histopheno_response.py b/backend/tests/fixtures/histopheno_response.py
index 44789afcf..67fb5632e 100644
--- a/backend/tests/fixtures/histopheno_response.py
+++ b/backend/tests/fixtures/histopheno_response.py
@@ -5,7 +5,7 @@
def histopheno_response():
return {
"responseHeader": {
- "QTime": 1,
+ "QTime": 2,
"params": {
"facet.query": [
'object_closure:"HP:0000924"',
diff --git a/backend/tests/fixtures/mapping_query.py b/backend/tests/fixtures/mapping_query.py
new file mode 100644
index 000000000..10c157459
--- /dev/null
+++ b/backend/tests/fixtures/mapping_query.py
@@ -0,0 +1,21 @@
+import pytest
+
+
+@pytest.fixture
+def mapping_query():
+ return {
+ "q": "*:*",
+ "rows": 20,
+ "start": 0,
+ "facet": True,
+ "facet_fields": [],
+ "facet_queries": [],
+ "filter_queries": ['subject_id:"MONDO\\:0020121" OR object_id:"MONDO\\:0020121"'],
+ "query_fields": None,
+ "def_type": "edismax",
+ "q_op": "AND",
+ "mm": "100%",
+ "boost": None,
+ "sort": None,
+ "facet_min_count": 1,
+ }
diff --git a/backend/tests/fixtures/mapping_response.py b/backend/tests/fixtures/mapping_response.py
new file mode 100644
index 000000000..7515868ce
--- /dev/null
+++ b/backend/tests/fixtures/mapping_response.py
@@ -0,0 +1,87 @@
+import pytest
+
+
+@pytest.fixture
+def mapping_response():
+ return {
+ "responseHeader": {
+ "QTime": 0,
+ "params": {
+ "mm": "100%",
+ "q": "*:*",
+ "defType": "edismax",
+ "facet_min_count": "1",
+ "start": "0",
+ "q.op": "AND",
+ "fq": 'subject_id:"MONDO\\:0020121" OR object_id:"MONDO\\:0020121"',
+ "rows": "20",
+ "facet": "true",
+ },
+ },
+ "response": {
+ "num_found": 7,
+ "start": 0,
+ "docs": [
+ {
+ "subject_id": "MONDO:0020121",
+ "subject_label": "muscular dystrophy",
+ "predicate_id": "skos:exactMatch",
+ "object_id": "DOID:9884",
+ "object_label": "muscular dystrophy",
+ "mapping_justification": "semapv:UnspecifiedMatching",
+ "id": "cda26856-16a7-499c-956f-119cbaac5b96",
+ },
+ {
+ "subject_id": "MONDO:0020121",
+ "subject_label": "muscular dystrophy",
+ "predicate_id": "skos:exactMatch",
+ "object_id": "ICD10CM:G71.0",
+ "object_label": "Muscular dystrophy",
+ "mapping_justification": "semapv:UnspecifiedMatching",
+ "id": "25777569-b997-4c8f-a1f3-5af352a16ee1",
+ },
+ {
+ "subject_id": "MONDO:0020121",
+ "subject_label": "muscular dystrophy",
+ "predicate_id": "skos:exactMatch",
+ "object_id": "MESH:D009136",
+ "mapping_justification": "semapv:UnspecifiedMatching",
+ "id": "819ab197-2ab1-4b73-8d0f-d7d4ec14d8a7",
+ },
+ {
+ "subject_id": "MONDO:0020121",
+ "subject_label": "muscular dystrophy",
+ "predicate_id": "skos:exactMatch",
+ "object_id": "NCIT:C84910",
+ "object_label": "Muscular Dystrophy",
+ "mapping_justification": "semapv:UnspecifiedMatching",
+ "id": "adb4b8ed-c4dc-4353-a08e-a4cb02b1826e",
+ },
+ {
+ "subject_id": "MONDO:0020121",
+ "subject_label": "muscular dystrophy",
+ "predicate_id": "skos:exactMatch",
+ "object_id": "SCTID:73297009",
+ "mapping_justification": "semapv:UnspecifiedMatching",
+ "id": "f6417283-c9d1-4289-aee6-16d30a4445b1",
+ },
+ {
+ "subject_id": "MONDO:0020121",
+ "subject_label": "muscular dystrophy",
+ "predicate_id": "skos:exactMatch",
+ "object_id": "UMLS:C0026850",
+ "mapping_justification": "semapv:UnspecifiedMatching",
+ "id": "93968631-eedb-448b-b58a-e31e3e411dde",
+ },
+ {
+ "subject_id": "MONDO:0020121",
+ "subject_label": "muscular dystrophy",
+ "predicate_id": "skos:exactMatch",
+ "object_id": "Orphanet:98473",
+ "mapping_justification": "semapv:UnspecifiedMatching",
+ "id": "e39e8ba9-8d7e-4b33-9f46-3867b652bdb5",
+ },
+ ],
+ },
+ "facet_counts": {"facet_fields": {}, "facet_queries": {}},
+ }
diff --git a/backend/tests/fixtures/mappings.py b/backend/tests/fixtures/mappings.py
new file mode 100644
index 000000000..7d3e92885
--- /dev/null
+++ b/backend/tests/fixtures/mappings.py
@@ -0,0 +1,75 @@
+import pytest
+
+
+@pytest.fixture
+def mappings():
+ return {
+ "limit": 20,
+ "offset": 0,
+ "total": 7,
+ "items": [
+ {
+ "subject_id": "MONDO:0020121",
+ "subject_label": "muscular dystrophy",
+ "predicate_id": "skos:exactMatch",
+ "object_id": "DOID:9884",
+ "object_label": "muscular dystrophy",
+ "mapping_justification": "semapv:UnspecifiedMatching",
+ "id": "cda26856-16a7-499c-956f-119cbaac5b96",
+ },
+ {
+ "subject_id": "MONDO:0020121",
+ "subject_label": "muscular dystrophy",
+ "predicate_id": "skos:exactMatch",
+ "object_id": "ICD10CM:G71.0",
+ "object_label": "Muscular dystrophy",
+ "mapping_justification": "semapv:UnspecifiedMatching",
+ "id": "25777569-b997-4c8f-a1f3-5af352a16ee1",
+ },
+ {
+ "subject_id": "MONDO:0020121",
+ "subject_label": "muscular dystrophy",
+ "predicate_id": "skos:exactMatch",
+ "object_id": "MESH:D009136",
+ "object_label": None,
+ "mapping_justification": "semapv:UnspecifiedMatching",
+ "id": "819ab197-2ab1-4b73-8d0f-d7d4ec14d8a7",
+ },
+ {
+ "subject_id": "MONDO:0020121",
+ "subject_label": "muscular dystrophy",
+ "predicate_id": "skos:exactMatch",
+ "object_id": "NCIT:C84910",
+ "object_label": "Muscular Dystrophy",
+ "mapping_justification": "semapv:UnspecifiedMatching",
+ "id": "adb4b8ed-c4dc-4353-a08e-a4cb02b1826e",
+ },
+ {
+ "subject_id": "MONDO:0020121",
+ "subject_label": "muscular dystrophy",
+ "predicate_id": "skos:exactMatch",
+ "object_id": "SCTID:73297009",
+ "object_label": None,
+ "mapping_justification": "semapv:UnspecifiedMatching",
+ "id": "f6417283-c9d1-4289-aee6-16d30a4445b1",
+ },
+ {
+ "subject_id": "MONDO:0020121",
+ "subject_label": "muscular dystrophy",
+ "predicate_id": "skos:exactMatch",
+ "object_id": "UMLS:C0026850",
+ "object_label": None,
+ "mapping_justification": "semapv:UnspecifiedMatching",
+ "id": "93968631-eedb-448b-b58a-e31e3e411dde",
+ },
+ {
+ "subject_id": "MONDO:0020121",
+ "subject_label": "muscular dystrophy",
+ "predicate_id": "skos:exactMatch",
+ "object_id": "Orphanet:98473",
+ "object_label": None,
+ "mapping_justification": "semapv:UnspecifiedMatching",
+ "id": "e39e8ba9-8d7e-4b33-9f46-3867b652bdb5",
+ },
+ ],
+ }
diff --git a/backend/tests/fixtures/search_response.py b/backend/tests/fixtures/search_response.py
index 5fbe50b82..c2791ef80 100644
--- a/backend/tests/fixtures/search_response.py
+++ b/backend/tests/fixtures/search_response.py
@@ -5,7 +5,7 @@
def search_response():
return {
"responseHeader": {
- "QTime": 1,
+ "QTime": 0,
"params": {
"mm": "100%",
"q": "fanconi",
diff --git a/backend/tests/unit/test_solr_parsers.py b/backend/tests/unit/test_solr_parsers.py
index 352bbffce..cda34ac6b 100644
--- a/backend/tests/unit/test_solr_parsers.py
+++ b/backend/tests/unit/test_solr_parsers.py
@@ -7,6 +7,7 @@
parse_autocomplete,
parse_entity,
parse_histopheno,
+ parse_mappings,
parse_search,
)
from monarch_py.utils.utils import dict_diff
@@ -65,3 +66,12 @@ def test_parse_autocomplete(autocomplete_response, autocomplete):
assert (
parsed == autocomplete
), f"Parsed result is not as expected. Difference: {dict_diff(parsed.dict(), autocomplete)}"
+
+
+def test_parse_mappings(mapping_response, mappings):
+ mapping_response["response"]["numFound"] = mapping_response["response"].pop("num_found")
+ solr_response = SolrQueryResult(**mapping_response)
+ parsed = parse_mappings(solr_response)
+ assert (
+ parsed == mappings
+ ), f"Parsed result is not as expected. Difference: {dict_diff(parsed.dict(), mappings)}"
\ No newline at end of file
diff --git a/backend/tests/unit/test_solr_queries.py b/backend/tests/unit/test_solr_queries.py
index 64c58844f..0e6c75a42 100644
--- a/backend/tests/unit/test_solr_queries.py
+++ b/backend/tests/unit/test_solr_queries.py
@@ -5,6 +5,7 @@
build_association_query,
build_autocomplete_query,
build_histopheno_query,
+ build_mapping_query,
build_search_query,
)
from monarch_py.utils.utils import compare_dicts, dict_diff
@@ -111,3 +112,9 @@ def test_build_autocomplete_query(autocomplete_query):
query = build_autocomplete_query(q="fanc").dict()
expected = autocomplete_query
assert compare_dicts(query, expected), f"Query is not as expected. Difference: {dict_diff(query, expected)}"
+
+
+def test_build_mappings_query(mapping_query):
+ query = build_mapping_query(entity_id=["MONDO:0020121"]).dict()
+ expected = mapping_query
+ assert compare_dicts(query, expected), f"Query is not as expected. Difference: {dict_diff(query, expected)}"
diff --git a/frontend/fixtures/mappings.json b/frontend/fixtures/mappings.json
new file mode 100644
index 000000000..016753b75
--- /dev/null
+++ b/frontend/fixtures/mappings.json
@@ -0,0 +1,70 @@
+{
+ "limit": 20,
+ "offset": 0,
+ "total": 7,
+ "items": [
+ {
+ "subject_id": "MONDO:0020121",
+ "subject_label": "muscular dystrophy",
+ "predicate_id": "skos:exactMatch",
+ "object_id": "DOID:9884",
+ "object_label": "muscular dystrophy",
+ "mapping_justification": "semapv:UnspecifiedMatching",
+ "id": "cda26856-16a7-499c-956f-119cbaac5b96"
+ },
+ {
+ "subject_id": "MONDO:0020121",
+ "subject_label": "muscular dystrophy",
+ "predicate_id": "skos:exactMatch",
+ "object_id": "ICD10CM:G71.0",
+ "object_label": "Muscular dystrophy",
+ "mapping_justification": "semapv:UnspecifiedMatching",
+ "id": "25777569-b997-4c8f-a1f3-5af352a16ee1"
+ },
+ {
+ "subject_id": "MONDO:0020121",
+ "subject_label": "muscular dystrophy",
+ "predicate_id": "skos:exactMatch",
+ "object_id": "MESH:D009136",
+ "object_label": null,
+ "mapping_justification": "semapv:UnspecifiedMatching",
+ "id": "819ab197-2ab1-4b73-8d0f-d7d4ec14d8a7"
+ },
+ {
+ "subject_id": "MONDO:0020121",
+ "subject_label": "muscular dystrophy",
+ "predicate_id": "skos:exactMatch",
+ "object_id": "NCIT:C84910",
+ "object_label": "Muscular Dystrophy",
+ "mapping_justification": "semapv:UnspecifiedMatching",
+ "id": "adb4b8ed-c4dc-4353-a08e-a4cb02b1826e"
+ },
+ {
+ "subject_id": "MONDO:0020121",
+ "subject_label": "muscular dystrophy",
+ "predicate_id": "skos:exactMatch",
+ "object_id": "SCTID:73297009",
+ "object_label": null,
+ "mapping_justification": "semapv:UnspecifiedMatching",
+ "id": "f6417283-c9d1-4289-aee6-16d30a4445b1"
+ },
+ {
+ "subject_id": "MONDO:0020121",
+ "subject_label": "muscular dystrophy",
+ "predicate_id": "skos:exactMatch",
+ "object_id": "UMLS:C0026850",
+ "object_label": null,
+ "mapping_justification": "semapv:UnspecifiedMatching",
+ "id": "93968631-eedb-448b-b58a-e31e3e411dde"
+ },
+ {
+ "subject_id": "MONDO:0020121",
+ "subject_label": "muscular dystrophy",
+ "predicate_id": "skos:exactMatch",
+ "object_id": "Orphanet:98473",
+ "object_label": null,
+ "mapping_justification": "semapv:UnspecifiedMatching",
+ "id": "e39e8ba9-8d7e-4b33-9f46-3867b652bdb5"
+ }
+ ]
+}
diff --git a/scripts/generate_fixtures.py b/scripts/generate_fixtures.py
index ddf39b26c..6939e22fc 100644
--- a/scripts/generate_fixtures.py
+++ b/scripts/generate_fixtures.py
@@ -9,15 +9,16 @@
from monarch_py.implementations.solr.solr_query_utils import (
build_association_query,
build_association_counts_query,
+ build_association_table_query,
build_autocomplete_query,
build_histopheno_query,
+ build_mapping_query,
build_search_query,
- build_association_table_query,
)
from monarch_py.service.solr_service import SolrService, core
from monarch_py.utils.utils import format_output
-from pprint import pprint as pp
+# from pprint import pprint as pp
### Define variables
oak = OakImplementation()
@@ -26,6 +27,7 @@
solr_url = os.getenv("MONARCH_SOLR_URL", "http://localhost:8983/solr")
solr_entities = SolrService(base_url=solr_url, core=core.ENTITY)
solr_associations = SolrService(base_url=solr_url, core=core.ASSOCIATION)
+solr_mappings = SolrService(base_url=solr_url, core=core.SSSOM)
root = Path(__file__).parent.parent
frontend_fixture_dir = Path(root) / "frontend" / "fixtures"
@@ -192,6 +194,7 @@ def main(
fixtures["histopheno"] = si.get_histopheno(node_id)
fixtures["entity"] = si.get_entity(id=node_id, extra=False)
fixtures["node"] = si.get_entity(id=node_id, extra=True)
+ fixtures["mappings"] = si.get_mappings(entity_id=node_id)
# fixtures['node-publication-abstract'] =
# fixtures['node-publication-summary'] =
# fixtures['ontologies'] =
@@ -227,6 +230,7 @@ def main(
)
extra_fixtures["autocomplete-query"] = build_autocomplete_query(q="fanc")
extra_fixtures["histopheno-query"] = build_histopheno_query(subject_closure=node_id)
+ extra_fixtures["mapping-query"] = build_mapping_query(entity_id=[node_id])
extra_fixtures["search-query"] = build_search_query(q="fanconi")
# solr doc fixtures
@@ -240,6 +244,7 @@ def main(
extra_fixtures["autocomplete-response"] = solr_entities.query(extra_fixtures["autocomplete-query"])
extra_fixtures["entity-response"] = solr_entities.get(node_id)
extra_fixtures["histopheno-response"] = solr_associations.query(extra_fixtures["histopheno-query"])
+ extra_fixtures["mapping-response"] = solr_mappings.query(extra_fixtures["mapping-query"])
extra_fixtures["search-response"] = solr_entities.query(extra_fixtures["search-query"])
### Write frontend fixtures
From 8daf6015cb6c77900e38b108b0ff67d482154d43 Mon Sep 17 00:00:00 2001
From: glass-ships
Date: Wed, 8 Nov 2023 12:35:39 -0700
Subject: [PATCH 6/9] update models to fix FE type test
---
backend/src/monarch_py/datamodels/model.py | 505 ++++++---------------
backend/tests/api/test_mapping_endpoint.py | 1 -
backend/tests/unit/test_solr_parsers.py | 4 +-
frontend/src/api/model.ts | 12 +-
4 files changed, 142 insertions(+), 380 deletions(-)
diff --git a/backend/src/monarch_py/datamodels/model.py b/backend/src/monarch_py/datamodels/model.py
index b735b6a77..b74d9d289 100644
--- a/backend/src/monarch_py/datamodels/model.py
+++ b/backend/src/monarch_py/datamodels/model.py
@@ -4,7 +4,6 @@
from typing import List, Dict, Optional, Any, Union
from pydantic import BaseModel as BaseModel, ConfigDict, Field
import sys
-
if sys.version_info >= (3, 8):
from typing import Literal
else:
@@ -14,20 +13,16 @@
metamodel_version = "None"
version = "None"
-
class WeakRefShimBaseModel(BaseModel):
- __slots__ = "__weakref__"
-
-
-class ConfiguredBaseModel(
- WeakRefShimBaseModel,
- validate_assignment=True,
- validate_all=True,
- underscore_attrs_are_private=True,
- extra="forbid",
- arbitrary_types_allowed=True,
- use_enum_values=True,
-):
+ __slots__ = '__weakref__'
+
+class ConfiguredBaseModel(WeakRefShimBaseModel,
+ validate_assignment = True,
+ validate_all = True,
+ underscore_attrs_are_private = True,
+ extra = 'forbid',
+ arbitrary_types_allowed = True,
+ use_enum_values = True):
pass
@@ -35,30 +30,24 @@ class AssociationDirectionEnum(str, Enum):
"""
The directionality of an association as it relates to a specified entity, with edges being categorized as incoming or outgoing
"""
-
# An association for which a specified entity is the object or part of the object closure
incoming = "incoming"
# An association for which a specified entity is the subject or part of the subject closure
outgoing = "outgoing"
-
+
+
class Association(ConfiguredBaseModel):
-
+
id: str = Field(...)
category: Optional[str] = Field(None)
subject: str = Field(...)
original_subject: Optional[str] = Field(None)
subject_namespace: Optional[str] = Field(None, description="""The namespace/prefix of the subject entity""")
subject_category: Optional[str] = Field(None, description="""The category of the subject entity""")
- subject_closure: Optional[List[str]] = Field(
- default_factory=list,
- description="""Field containing subject id and the ids of all of it's ancestors""",
- )
+ subject_closure: Optional[List[str]] = Field(default_factory=list, description="""Field containing subject id and the ids of all of it's ancestors""")
subject_label: Optional[str] = Field(None, description="""The name of the subject entity""")
- subject_closure_label: Optional[List[str]] = Field(
- default_factory=list,
- description="""Field containing subject name and the names of all of it's ancestors""",
- )
+ subject_closure_label: Optional[List[str]] = Field(default_factory=list, description="""Field containing subject name and the names of all of it's ancestors""")
subject_taxon: Optional[str] = Field(None)
subject_taxon_label: Optional[str] = Field(None)
predicate: str = Field(...)
@@ -66,176 +55,86 @@ class Association(ConfiguredBaseModel):
original_object: Optional[str] = Field(None)
object_namespace: Optional[str] = Field(None, description="""The namespace/prefix of the object entity""")
object_category: Optional[str] = Field(None, description="""The category of the object entity""")
- object_closure: Optional[List[str]] = Field(
- default_factory=list,
- description="""Field containing object id and the ids of all of it's ancestors""",
- )
+ object_closure: Optional[List[str]] = Field(default_factory=list, description="""Field containing object id and the ids of all of it's ancestors""")
object_label: Optional[str] = Field(None, description="""The name of the object entity""")
- object_closure_label: Optional[List[str]] = Field(
- default_factory=list,
- description="""Field containing object name and the names of all of it's ancestors""",
- )
+ object_closure_label: Optional[List[str]] = Field(default_factory=list, description="""Field containing object name and the names of all of it's ancestors""")
object_taxon: Optional[str] = Field(None)
object_taxon_label: Optional[str] = Field(None)
primary_knowledge_source: Optional[str] = Field(None)
aggregator_knowledge_source: Optional[List[str]] = Field(default_factory=list)
negated: Optional[bool] = Field(None)
pathway: Optional[str] = Field(None)
- evidence_count: Optional[int] = Field(
- None,
- description="""count of supporting documents, evidence codes, and sources supplying evidence""",
- )
+ evidence_count: Optional[int] = Field(None, description="""count of supporting documents, evidence codes, and sources supplying evidence""")
has_evidence: Optional[List[str]] = Field(default_factory=list)
- has_evidence_links: Optional[List[ExpandedCurie]] = Field(
- default_factory=list,
- description="""List of ExpandedCuries with id and url for evidence""",
- )
- grouping_key: Optional[str] = Field(
- None,
- description="""A concatenation of fields used to group associations with the same essential/defining properties""",
- )
+ has_evidence_links: Optional[List[ExpandedCurie]] = Field(default_factory=list, description="""List of ExpandedCuries with id and url for evidence""")
+ grouping_key: Optional[str] = Field(None, description="""A concatenation of fields used to group associations with the same essential/defining properties""")
provided_by: Optional[str] = Field(None)
- provided_by_link: Optional[ExpandedCurie] = Field(
- None,
- description="""A link to the docs for the knowledge source that provided the node/edge.""",
- )
+ provided_by_link: Optional[ExpandedCurie] = Field(None, description="""A link to the docs for the knowledge source that provided the node/edge.""")
publications: Optional[List[str]] = Field(default_factory=list)
- publications_links: Optional[List[ExpandedCurie]] = Field(
- default_factory=list,
- description="""List of ExpandedCuries with id and url for publications""",
- )
+ publications_links: Optional[List[ExpandedCurie]] = Field(default_factory=list, description="""List of ExpandedCuries with id and url for publications""")
qualifiers: Optional[List[str]] = Field(default_factory=list)
frequency_qualifier: Optional[str] = Field(None)
onset_qualifier: Optional[str] = Field(None)
sex_qualifier: Optional[str] = Field(None)
stage_qualifier: Optional[str] = Field(None)
qualifiers_label: Optional[str] = Field(None, description="""The name of the frequency_qualifier entity""")
- qualifiers_namespace: Optional[str] = Field(
- None, description="""The namespace/prefix of the frequency_qualifier entity"""
- )
+ qualifiers_namespace: Optional[str] = Field(None, description="""The namespace/prefix of the frequency_qualifier entity""")
qualifiers_category: Optional[str] = Field(None, description="""The category of the frequency_qualifier entity""")
- qualifiers_closure: Optional[List[str]] = Field(
- default_factory=list,
- description="""Field containing frequency_qualifier id and the ids of all of it's ancestors""",
- )
- qualifiers_closure_label: Optional[List[str]] = Field(
- default_factory=list,
- description="""Field containing frequency_qualifier name and the names of all of it's ancestors""",
- )
+ qualifiers_closure: Optional[List[str]] = Field(default_factory=list, description="""Field containing frequency_qualifier id and the ids of all of it's ancestors""")
+ qualifiers_closure_label: Optional[List[str]] = Field(default_factory=list, description="""Field containing frequency_qualifier name and the names of all of it's ancestors""")
frequency_qualifier_label: Optional[str] = Field(None, description="""The name of the frequency_qualifier entity""")
- frequency_qualifier_namespace: Optional[str] = Field(
- None, description="""The namespace/prefix of the frequency_qualifier entity"""
- )
- frequency_qualifier_category: Optional[str] = Field(
- None, description="""The category of the frequency_qualifier entity"""
- )
- frequency_qualifier_closure: Optional[List[str]] = Field(
- default_factory=list,
- description="""Field containing frequency_qualifier id and the ids of all of it's ancestors""",
- )
- frequency_qualifier_closure_label: Optional[List[str]] = Field(
- default_factory=list,
- description="""Field containing frequency_qualifier name and the names of all of it's ancestors""",
- )
+ frequency_qualifier_namespace: Optional[str] = Field(None, description="""The namespace/prefix of the frequency_qualifier entity""")
+ frequency_qualifier_category: Optional[str] = Field(None, description="""The category of the frequency_qualifier entity""")
+ frequency_qualifier_closure: Optional[List[str]] = Field(default_factory=list, description="""Field containing frequency_qualifier id and the ids of all of it's ancestors""")
+ frequency_qualifier_closure_label: Optional[List[str]] = Field(default_factory=list, description="""Field containing frequency_qualifier name and the names of all of it's ancestors""")
onset_qualifier_label: Optional[str] = Field(None, description="""The name of the onset_qualifier entity""")
- onset_qualifier_namespace: Optional[str] = Field(
- None, description="""The namespace/prefix of the onset_qualifier entity"""
- )
+ onset_qualifier_namespace: Optional[str] = Field(None, description="""The namespace/prefix of the onset_qualifier entity""")
onset_qualifier_category: Optional[str] = Field(None, description="""The category of the onset_qualifier entity""")
- onset_qualifier_closure: Optional[List[str]] = Field(
- default_factory=list,
- description="""Field containing onset_qualifier id and the ids of all of it's ancestors""",
- )
- onset_qualifier_closure_label: Optional[List[str]] = Field(
- default_factory=list,
- description="""Field containing onset_qualifier name and the names of all of it's ancestors""",
- )
+ onset_qualifier_closure: Optional[List[str]] = Field(default_factory=list, description="""Field containing onset_qualifier id and the ids of all of it's ancestors""")
+ onset_qualifier_closure_label: Optional[List[str]] = Field(default_factory=list, description="""Field containing onset_qualifier name and the names of all of it's ancestors""")
sex_qualifier_label: Optional[str] = Field(None, description="""The name of the sex_qualifier entity""")
- sex_qualifier_namespace: Optional[str] = Field(
- None, description="""The namespace/prefix of the sex_qualifier entity"""
- )
+ sex_qualifier_namespace: Optional[str] = Field(None, description="""The namespace/prefix of the sex_qualifier entity""")
sex_qualifier_category: Optional[str] = Field(None, description="""The category of the sex_qualifier entity""")
- sex_qualifier_closure: Optional[List[str]] = Field(
- default_factory=list,
- description="""Field containing sex_qualifier id and the ids of all of it's ancestors""",
- )
- sex_qualifier_closure_label: Optional[List[str]] = Field(
- default_factory=list,
- description="""Field containing sex_qualifier name and the names of all of it's ancestors""",
- )
+ sex_qualifier_closure: Optional[List[str]] = Field(default_factory=list, description="""Field containing sex_qualifier id and the ids of all of it's ancestors""")
+ sex_qualifier_closure_label: Optional[List[str]] = Field(default_factory=list, description="""Field containing sex_qualifier name and the names of all of it's ancestors""")
stage_qualifier_label: Optional[str] = Field(None, description="""The name of the stage_qualifier entity""")
- stage_qualifier_namespace: Optional[str] = Field(
- None, description="""The namespace/prefix of the stage_qualifier entity"""
- )
+ stage_qualifier_namespace: Optional[str] = Field(None, description="""The namespace/prefix of the stage_qualifier entity""")
stage_qualifier_category: Optional[str] = Field(None, description="""The category of the stage_qualifier entity""")
- stage_qualifier_closure: Optional[List[str]] = Field(
- default_factory=list,
- description="""Field containing stage_qualifier id and the ids of all of it's ancestors""",
- )
- stage_qualifier_closure_label: Optional[List[str]] = Field(
- default_factory=list,
- description="""Field containing stage_qualifier name and the names of all of it's ancestors""",
- )
-
+ stage_qualifier_closure: Optional[List[str]] = Field(default_factory=list, description="""Field containing stage_qualifier id and the ids of all of it's ancestors""")
+ stage_qualifier_closure_label: Optional[List[str]] = Field(default_factory=list, description="""Field containing stage_qualifier name and the names of all of it's ancestors""")
+
class AssociationCountList(ConfiguredBaseModel):
"""
Container class for a list of association counts
"""
-
- items: List[AssociationCount] = Field(
- default_factory=list,
- description="""A collection of items, with the type to be overriden by slot_usage""",
- )
-
+ items: List[AssociationCount] = Field(default_factory=list, description="""A collection of items, with the type to be overriden by slot_usage""")
+
class AssociationTypeMapping(ConfiguredBaseModel):
"""
A data class to hold the necessary information to produce association type counts for given entities with appropriate directional labels
"""
-
- subject_label: Optional[str] = Field(
- None,
- description="""A label to describe the subjects of the association type as a whole for use in the UI""",
- )
- object_label: Optional[str] = Field(
- None,
- description="""A label to describe the objects of the association type as a whole for use in the UI""",
- )
- symmetric: bool = Field(
- False,
- description="""Whether the association type is symmetric, meaning that the subject and object labels should be interchangeable""",
- )
- category: str = Field(
- ...,
- description="""The biolink category to use in queries for this association type""",
- )
-
+ subject_label: Optional[str] = Field(None, description="""A label to describe the subjects of the association type as a whole for use in the UI""")
+ object_label: Optional[str] = Field(None, description="""A label to describe the objects of the association type as a whole for use in the UI""")
+ symmetric: bool = Field(False, description="""Whether the association type is symmetric, meaning that the subject and object labels should be interchangeable""")
+ category: str = Field(..., description="""The biolink category to use in queries for this association type""")
+
class DirectionalAssociation(Association):
"""
An association that gives it's direction relative to a specified entity
"""
-
- direction: AssociationDirectionEnum = Field(
- ...,
- description="""The directionality of the association relative to a given entity for an association_count. If the entity is the subject or in the subject closure, the direction is forwards, if it is the object or in the object closure, the direction is backwards.""",
- )
+ direction: AssociationDirectionEnum = Field(..., description="""The directionality of the association relative to a given entity for an association_count. If the entity is the subject or in the subject closure, the direction is forwards, if it is the object or in the object closure, the direction is backwards.""")
id: str = Field(...)
category: Optional[str] = Field(None)
subject: str = Field(...)
original_subject: Optional[str] = Field(None)
subject_namespace: Optional[str] = Field(None, description="""The namespace/prefix of the subject entity""")
subject_category: Optional[str] = Field(None, description="""The category of the subject entity""")
- subject_closure: Optional[List[str]] = Field(
- default_factory=list,
- description="""Field containing subject id and the ids of all of it's ancestors""",
- )
+ subject_closure: Optional[List[str]] = Field(default_factory=list, description="""Field containing subject id and the ids of all of it's ancestors""")
subject_label: Optional[str] = Field(None, description="""The name of the subject entity""")
- subject_closure_label: Optional[List[str]] = Field(
- default_factory=list,
- description="""Field containing subject name and the names of all of it's ancestors""",
- )
+ subject_closure_label: Optional[List[str]] = Field(default_factory=list, description="""Field containing subject name and the names of all of it's ancestors""")
subject_taxon: Optional[str] = Field(None)
subject_taxon_label: Optional[str] = Field(None)
predicate: str = Field(...)
@@ -243,132 +142,67 @@ class DirectionalAssociation(Association):
original_object: Optional[str] = Field(None)
object_namespace: Optional[str] = Field(None, description="""The namespace/prefix of the object entity""")
object_category: Optional[str] = Field(None, description="""The category of the object entity""")
- object_closure: Optional[List[str]] = Field(
- default_factory=list,
- description="""Field containing object id and the ids of all of it's ancestors""",
- )
+ object_closure: Optional[List[str]] = Field(default_factory=list, description="""Field containing object id and the ids of all of it's ancestors""")
object_label: Optional[str] = Field(None, description="""The name of the object entity""")
- object_closure_label: Optional[List[str]] = Field(
- default_factory=list,
- description="""Field containing object name and the names of all of it's ancestors""",
- )
+ object_closure_label: Optional[List[str]] = Field(default_factory=list, description="""Field containing object name and the names of all of it's ancestors""")
object_taxon: Optional[str] = Field(None)
object_taxon_label: Optional[str] = Field(None)
primary_knowledge_source: Optional[str] = Field(None)
aggregator_knowledge_source: Optional[List[str]] = Field(default_factory=list)
negated: Optional[bool] = Field(None)
pathway: Optional[str] = Field(None)
- evidence_count: Optional[int] = Field(
- None,
- description="""count of supporting documents, evidence codes, and sources supplying evidence""",
- )
+ evidence_count: Optional[int] = Field(None, description="""count of supporting documents, evidence codes, and sources supplying evidence""")
has_evidence: Optional[List[str]] = Field(default_factory=list)
- has_evidence_links: Optional[List[ExpandedCurie]] = Field(
- default_factory=list,
- description="""List of ExpandedCuries with id and url for evidence""",
- )
- grouping_key: Optional[str] = Field(
- None,
- description="""A concatenation of fields used to group associations with the same essential/defining properties""",
- )
+ has_evidence_links: Optional[List[ExpandedCurie]] = Field(default_factory=list, description="""List of ExpandedCuries with id and url for evidence""")
+ grouping_key: Optional[str] = Field(None, description="""A concatenation of fields used to group associations with the same essential/defining properties""")
provided_by: Optional[str] = Field(None)
- provided_by_link: Optional[ExpandedCurie] = Field(
- None,
- description="""A link to the docs for the knowledge source that provided the node/edge.""",
- )
+ provided_by_link: Optional[ExpandedCurie] = Field(None, description="""A link to the docs for the knowledge source that provided the node/edge.""")
publications: Optional[List[str]] = Field(default_factory=list)
- publications_links: Optional[List[ExpandedCurie]] = Field(
- default_factory=list,
- description="""List of ExpandedCuries with id and url for publications""",
- )
+ publications_links: Optional[List[ExpandedCurie]] = Field(default_factory=list, description="""List of ExpandedCuries with id and url for publications""")
qualifiers: Optional[List[str]] = Field(default_factory=list)
frequency_qualifier: Optional[str] = Field(None)
onset_qualifier: Optional[str] = Field(None)
sex_qualifier: Optional[str] = Field(None)
stage_qualifier: Optional[str] = Field(None)
qualifiers_label: Optional[str] = Field(None, description="""The name of the frequency_qualifier entity""")
- qualifiers_namespace: Optional[str] = Field(
- None, description="""The namespace/prefix of the frequency_qualifier entity"""
- )
+ qualifiers_namespace: Optional[str] = Field(None, description="""The namespace/prefix of the frequency_qualifier entity""")
qualifiers_category: Optional[str] = Field(None, description="""The category of the frequency_qualifier entity""")
- qualifiers_closure: Optional[List[str]] = Field(
- default_factory=list,
- description="""Field containing frequency_qualifier id and the ids of all of it's ancestors""",
- )
- qualifiers_closure_label: Optional[List[str]] = Field(
- default_factory=list,
- description="""Field containing frequency_qualifier name and the names of all of it's ancestors""",
- )
+ qualifiers_closure: Optional[List[str]] = Field(default_factory=list, description="""Field containing frequency_qualifier id and the ids of all of it's ancestors""")
+ qualifiers_closure_label: Optional[List[str]] = Field(default_factory=list, description="""Field containing frequency_qualifier name and the names of all of it's ancestors""")
frequency_qualifier_label: Optional[str] = Field(None, description="""The name of the frequency_qualifier entity""")
- frequency_qualifier_namespace: Optional[str] = Field(
- None, description="""The namespace/prefix of the frequency_qualifier entity"""
- )
- frequency_qualifier_category: Optional[str] = Field(
- None, description="""The category of the frequency_qualifier entity"""
- )
- frequency_qualifier_closure: Optional[List[str]] = Field(
- default_factory=list,
- description="""Field containing frequency_qualifier id and the ids of all of it's ancestors""",
- )
- frequency_qualifier_closure_label: Optional[List[str]] = Field(
- default_factory=list,
- description="""Field containing frequency_qualifier name and the names of all of it's ancestors""",
- )
+ frequency_qualifier_namespace: Optional[str] = Field(None, description="""The namespace/prefix of the frequency_qualifier entity""")
+ frequency_qualifier_category: Optional[str] = Field(None, description="""The category of the frequency_qualifier entity""")
+ frequency_qualifier_closure: Optional[List[str]] = Field(default_factory=list, description="""Field containing frequency_qualifier id and the ids of all of it's ancestors""")
+ frequency_qualifier_closure_label: Optional[List[str]] = Field(default_factory=list, description="""Field containing frequency_qualifier name and the names of all of it's ancestors""")
onset_qualifier_label: Optional[str] = Field(None, description="""The name of the onset_qualifier entity""")
- onset_qualifier_namespace: Optional[str] = Field(
- None, description="""The namespace/prefix of the onset_qualifier entity"""
- )
+ onset_qualifier_namespace: Optional[str] = Field(None, description="""The namespace/prefix of the onset_qualifier entity""")
onset_qualifier_category: Optional[str] = Field(None, description="""The category of the onset_qualifier entity""")
- onset_qualifier_closure: Optional[List[str]] = Field(
- default_factory=list,
- description="""Field containing onset_qualifier id and the ids of all of it's ancestors""",
- )
- onset_qualifier_closure_label: Optional[List[str]] = Field(
- default_factory=list,
- description="""Field containing onset_qualifier name and the names of all of it's ancestors""",
- )
+ onset_qualifier_closure: Optional[List[str]] = Field(default_factory=list, description="""Field containing onset_qualifier id and the ids of all of it's ancestors""")
+ onset_qualifier_closure_label: Optional[List[str]] = Field(default_factory=list, description="""Field containing onset_qualifier name and the names of all of it's ancestors""")
sex_qualifier_label: Optional[str] = Field(None, description="""The name of the sex_qualifier entity""")
- sex_qualifier_namespace: Optional[str] = Field(
- None, description="""The namespace/prefix of the sex_qualifier entity"""
- )
+ sex_qualifier_namespace: Optional[str] = Field(None, description="""The namespace/prefix of the sex_qualifier entity""")
sex_qualifier_category: Optional[str] = Field(None, description="""The category of the sex_qualifier entity""")
- sex_qualifier_closure: Optional[List[str]] = Field(
- default_factory=list,
- description="""Field containing sex_qualifier id and the ids of all of it's ancestors""",
- )
- sex_qualifier_closure_label: Optional[List[str]] = Field(
- default_factory=list,
- description="""Field containing sex_qualifier name and the names of all of it's ancestors""",
- )
+ sex_qualifier_closure: Optional[List[str]] = Field(default_factory=list, description="""Field containing sex_qualifier id and the ids of all of it's ancestors""")
+ sex_qualifier_closure_label: Optional[List[str]] = Field(default_factory=list, description="""Field containing sex_qualifier name and the names of all of it's ancestors""")
stage_qualifier_label: Optional[str] = Field(None, description="""The name of the stage_qualifier entity""")
- stage_qualifier_namespace: Optional[str] = Field(
- None, description="""The namespace/prefix of the stage_qualifier entity"""
- )
+ stage_qualifier_namespace: Optional[str] = Field(None, description="""The namespace/prefix of the stage_qualifier entity""")
stage_qualifier_category: Optional[str] = Field(None, description="""The category of the stage_qualifier entity""")
- stage_qualifier_closure: Optional[List[str]] = Field(
- default_factory=list,
- description="""Field containing stage_qualifier id and the ids of all of it's ancestors""",
- )
- stage_qualifier_closure_label: Optional[List[str]] = Field(
- default_factory=list,
- description="""Field containing stage_qualifier name and the names of all of it's ancestors""",
- )
-
+ stage_qualifier_closure: Optional[List[str]] = Field(default_factory=list, description="""Field containing stage_qualifier id and the ids of all of it's ancestors""")
+ stage_qualifier_closure_label: Optional[List[str]] = Field(default_factory=list, description="""Field containing stage_qualifier name and the names of all of it's ancestors""")
+
class ExpandedCurie(ConfiguredBaseModel):
"""
A curie bundled along with its expanded url
"""
-
id: str = Field(...)
url: Optional[str] = Field(None)
-
+
class Entity(ConfiguredBaseModel):
"""
Represents an Entity in the Monarch KG data model
"""
-
id: str = Field(...)
category: Optional[str] = Field(None)
name: Optional[str] = Field(None)
@@ -377,58 +211,48 @@ class Entity(ConfiguredBaseModel):
xref: Optional[List[str]] = Field(default_factory=list)
provided_by: Optional[str] = Field(None)
in_taxon: Optional[str] = Field(None, description="""The biolink taxon that the entity is in the closure of.""")
- in_taxon_label: Optional[str] = Field(
- None,
- description="""The label of the biolink taxon that the entity is in the closure of.""",
- )
+ in_taxon_label: Optional[str] = Field(None, description="""The label of the biolink taxon that the entity is in the closure of.""")
symbol: Optional[str] = Field(None)
synonym: Optional[List[str]] = Field(default_factory=list)
uri: Optional[str] = Field(None, description="""The URI of the entity""")
-
+
class FacetValue(ConfiguredBaseModel):
-
+
label: str = Field(...)
count: Optional[int] = Field(None, description="""count of documents""")
-
+
class AssociationCount(FacetValue):
-
+
category: Optional[str] = Field(None)
label: str = Field(...)
count: Optional[int] = Field(None, description="""count of documents""")
-
+
class FacetField(ConfiguredBaseModel):
-
+
label: str = Field(...)
- facet_values: Optional[List[FacetValue]] = Field(
- default_factory=list,
- description="""Collection of FacetValue label/value instances belonging to a FacetField""",
- )
-
+ facet_values: Optional[List[FacetValue]] = Field(default_factory=list, description="""Collection of FacetValue label/value instances belonging to a FacetField""")
+
class HistoPheno(ConfiguredBaseModel):
-
+
id: str = Field(...)
- items: List[HistoBin] = Field(
- default_factory=list,
- description="""A collection of items, with the type to be overriden by slot_usage""",
- )
-
+ items: List[HistoBin] = Field(default_factory=list, description="""A collection of items, with the type to be overriden by slot_usage""")
+
class HistoBin(FacetValue):
-
+
id: str = Field(...)
label: str = Field(...)
count: Optional[int] = Field(None, description="""count of documents""")
-
+
class Mapping(ConfiguredBaseModel):
"""
A minimal class to hold a SSSOM mapping
"""
-
subject_id: str = Field(...)
subject_label: Optional[str] = Field(None, description="""The name of the subject entity""")
predicate_id: str = Field(...)
@@ -436,34 +260,19 @@ class Mapping(ConfiguredBaseModel):
object_label: Optional[str] = Field(None, description="""The name of the object entity""")
mapping_justification: Optional[str] = Field(None)
id: str = Field(...)
-
+
class Node(Entity):
"""
UI container class extending Entity with additional information
"""
-
in_taxon: Optional[str] = Field(None, description="""The biolink taxon that the entity is in the closure of.""")
- in_taxon_label: Optional[str] = Field(
- None,
- description="""The label of the biolink taxon that the entity is in the closure of.""",
- )
+ in_taxon_label: Optional[str] = Field(None, description="""The label of the biolink taxon that the entity is in the closure of.""")
inheritance: Optional[Entity] = Field(None)
- causal_gene: Optional[List[Entity]] = Field(
- default_factory=list,
- description="""A list of genes that are known to be causally associated with a disease""",
- )
- causes_disease: Optional[List[Entity]] = Field(
- default_factory=list,
- description="""A list of diseases that are known to be causally associated with a gene""",
- )
- external_links: Optional[List[ExpandedCurie]] = Field(
- default_factory=list, description="""ExpandedCurie with id and url for xrefs"""
- )
- provided_by_link: Optional[ExpandedCurie] = Field(
- None,
- description="""A link to the docs for the knowledge source that provided the node/edge.""",
- )
+ causal_gene: Optional[List[Entity]] = Field(default_factory=list, description="""A list of genes that are known to be causally associated with a disease""")
+ causes_disease: Optional[List[Entity]] = Field(default_factory=list, description="""A list of diseases that are known to be causally associated with a gene""")
+ external_links: Optional[List[ExpandedCurie]] = Field(default_factory=list, description="""ExpandedCurie with id and url for xrefs""")
+ provided_by_link: Optional[ExpandedCurie] = Field(None, description="""A link to the docs for the knowledge source that provided the node/edge.""")
association_counts: List[AssociationCount] = Field(default_factory=list)
node_hierarchy: Optional[NodeHierarchy] = Field(None)
id: str = Field(...)
@@ -476,95 +285,76 @@ class Node(Entity):
symbol: Optional[str] = Field(None)
synonym: Optional[List[str]] = Field(default_factory=list)
uri: Optional[str] = Field(None, description="""The URI of the entity""")
-
+
class NodeHierarchy(ConfiguredBaseModel):
-
+
super_classes: List[Entity] = Field(default_factory=list)
sub_classes: List[Entity] = Field(default_factory=list)
-
+
class Results(ConfiguredBaseModel):
-
+
limit: int = Field(..., description="""number of items to return in a response""")
offset: int = Field(..., description="""offset into the total number of items""")
total: int = Field(..., description="""total number of items matching a query""")
-
+
class AssociationResults(Results):
-
- items: List[Association] = Field(
- default_factory=list,
- description="""A collection of items, with the type to be overriden by slot_usage""",
- )
+
+ items: List[Association] = Field(default_factory=list, description="""A collection of items, with the type to be overriden by slot_usage""")
limit: int = Field(..., description="""number of items to return in a response""")
offset: int = Field(..., description="""offset into the total number of items""")
total: int = Field(..., description="""total number of items matching a query""")
-
+
class AssociationTableResults(Results):
-
- items: List[DirectionalAssociation] = Field(
- default_factory=list,
- description="""A collection of items, with the type to be overriden by slot_usage""",
- )
+
+ items: List[DirectionalAssociation] = Field(default_factory=list, description="""A collection of items, with the type to be overriden by slot_usage""")
limit: int = Field(..., description="""number of items to return in a response""")
offset: int = Field(..., description="""offset into the total number of items""")
total: int = Field(..., description="""total number of items matching a query""")
-
+
class CategoryGroupedAssociationResults(Results):
-
- counterpart_category: Optional[str] = Field(
- None,
- description="""The category of the counterpart entity in a given association, eg. the category of the entity that is not the subject""",
- )
- items: List[Association] = Field(
- default_factory=list,
- description="""A collection of items, with the type to be overriden by slot_usage""",
- )
+
+ counterpart_category: Optional[str] = Field(None, description="""The category of the counterpart entity in a given association, eg. the category of the entity that is not the subject""")
+ items: List[Association] = Field(default_factory=list, description="""A collection of items, with the type to be overriden by slot_usage""")
limit: int = Field(..., description="""number of items to return in a response""")
offset: int = Field(..., description="""offset into the total number of items""")
total: int = Field(..., description="""total number of items matching a query""")
-
+
class EntityResults(Results):
-
- items: List[Entity] = Field(
- default_factory=list,
- description="""A collection of items, with the type to be overriden by slot_usage""",
- )
+
+ items: List[Entity] = Field(default_factory=list, description="""A collection of items, with the type to be overriden by slot_usage""")
limit: int = Field(..., description="""number of items to return in a response""")
offset: int = Field(..., description="""offset into the total number of items""")
total: int = Field(..., description="""total number of items matching a query""")
-
+
class MappingResults(Results):
"""
SSSOM Mappings returned as a results collection
"""
-
- items: List[Mapping] = Field(
- default_factory=list,
- description="""A collection of items, with the type to be overriden by slot_usage""",
- )
+ items: List[Mapping] = Field(default_factory=list, description="""A collection of items, with the type to be overriden by slot_usage""")
limit: int = Field(..., description="""number of items to return in a response""")
offset: int = Field(..., description="""offset into the total number of items""")
total: int = Field(..., description="""total number of items matching a query""")
-
+
class MultiEntityAssociationResults(Results):
-
+
id: str = Field(...)
name: Optional[str] = Field(None)
associated_categories: List[CategoryGroupedAssociationResults] = Field(default_factory=list)
limit: int = Field(..., description="""number of items to return in a response""")
offset: int = Field(..., description="""offset into the total number of items""")
total: int = Field(..., description="""total number of items matching a query""")
-
+
class SearchResult(Entity):
-
+
highlight: Optional[str] = Field(None, description="""matching text snippet containing html tags""")
score: Optional[float] = Field(None)
id: str = Field(...)
@@ -575,82 +365,55 @@ class SearchResult(Entity):
xref: Optional[List[str]] = Field(default_factory=list)
provided_by: Optional[str] = Field(None)
in_taxon: Optional[str] = Field(None, description="""The biolink taxon that the entity is in the closure of.""")
- in_taxon_label: Optional[str] = Field(
- None,
- description="""The label of the biolink taxon that the entity is in the closure of.""",
- )
+ in_taxon_label: Optional[str] = Field(None, description="""The label of the biolink taxon that the entity is in the closure of.""")
symbol: Optional[str] = Field(None)
synonym: Optional[List[str]] = Field(default_factory=list)
uri: Optional[str] = Field(None, description="""The URI of the entity""")
-
+
class SearchResults(Results):
-
- items: List[SearchResult] = Field(
- default_factory=list,
- description="""A collection of items, with the type to be overriden by slot_usage""",
- )
- facet_fields: Optional[List[FacetField]] = Field(
- default_factory=list,
- description="""Collection of facet field responses with the field values and counts""",
- )
- facet_queries: Optional[List[FacetValue]] = Field(
- default_factory=list,
- description="""Collection of facet query responses with the query string values and counts""",
- )
+
+ items: List[SearchResult] = Field(default_factory=list, description="""A collection of items, with the type to be overriden by slot_usage""")
+ facet_fields: Optional[List[FacetField]] = Field(default_factory=list, description="""Collection of facet field responses with the field values and counts""")
+ facet_queries: Optional[List[FacetValue]] = Field(default_factory=list, description="""Collection of facet query responses with the query string values and counts""")
limit: int = Field(..., description="""number of items to return in a response""")
offset: int = Field(..., description="""offset into the total number of items""")
total: int = Field(..., description="""total number of items matching a query""")
-
+
class PairwiseSimilarity(ConfiguredBaseModel):
"""
Abstract grouping for representing individual pairwise similarities
"""
-
None
-
+
class TermPairwiseSimilarity(PairwiseSimilarity):
"""
A simple pairwise similarity between two atomic concepts/terms
"""
-
subject_id: str = Field(...)
subject_label: Optional[str] = Field(None, description="""The name of the subject entity""")
subject_source: Optional[str] = Field(None, description="""the source for the first entity""")
object_id: str = Field(...)
object_label: Optional[str] = Field(None, description="""The name of the object entity""")
object_source: Optional[str] = Field(None, description="""the source for the second entity""")
- ancestor_id: Optional[str] = Field(
- None,
- description="""the most recent common ancestor of the two compared entities. If there are multiple MRCAs then the most informative one is selected""",
- )
+ ancestor_id: Optional[str] = Field(None, description="""the most recent common ancestor of the two compared entities. If there are multiple MRCAs then the most informative one is selected""")
ancestor_label: Optional[str] = Field(None, description="""the name or label of the ancestor concept""")
ancestor_source: Optional[str] = Field(None)
object_information_content: Optional[float] = Field(None, description="""The IC of the object""")
subject_information_content: Optional[float] = Field(None, description="""The IC of the subject""")
ancestor_information_content: Optional[float] = Field(None, description="""The IC of the object""")
- jaccard_similarity: Optional[float] = Field(
- None,
- description="""The number of concepts in the intersection divided by the number in the union""",
- )
- cosine_similarity: Optional[float] = Field(
- None,
- description="""the dot product of two node embeddings divided by the product of their lengths""",
- )
+ jaccard_similarity: Optional[float] = Field(None, description="""The number of concepts in the intersection divided by the number in the union""")
+ cosine_similarity: Optional[float] = Field(None, description="""the dot product of two node embeddings divided by the product of their lengths""")
dice_similarity: Optional[float] = Field(None)
- phenodigm_score: Optional[float] = Field(
- None,
- description="""the geometric mean of the jaccard similarity and the information content""",
- )
-
+ phenodigm_score: Optional[float] = Field(None, description="""the geometric mean of the jaccard similarity and the information content""")
+
class TermSetPairwiseSimilarity(PairwiseSimilarity):
"""
A simple pairwise similarity between two sets of concepts/terms
"""
-
subject_termset: Optional[Dict[str, TermInfo]] = Field(default_factory=dict)
object_termset: Optional[Dict[str, TermInfo]] = Field(default_factory=dict)
subject_best_matches: Optional[Dict[str, BestMatch]] = Field(default_factory=dict)
@@ -658,16 +421,16 @@ class TermSetPairwiseSimilarity(PairwiseSimilarity):
average_score: Optional[float] = Field(None)
best_score: Optional[float] = Field(None)
metric: Optional[str] = Field(None)
-
+
class TermInfo(ConfiguredBaseModel):
-
+
id: str = Field(...)
label: Optional[str] = Field(None)
-
+
class BestMatch(ConfiguredBaseModel):
-
+
match_source: str = Field(...)
match_source_label: Optional[str] = Field(None)
match_target: Optional[str] = Field(None, description="""the entity matches""")
@@ -676,6 +439,7 @@ class BestMatch(ConfiguredBaseModel):
match_subsumer: Optional[str] = Field(None)
match_subsumer_label: Optional[str] = Field(None)
similarity: TermPairwiseSimilarity = Field(...)
+
# Update forward refs
@@ -708,3 +472,4 @@ class BestMatch(ConfiguredBaseModel):
TermSetPairwiseSimilarity.update_forward_refs()
TermInfo.update_forward_refs()
BestMatch.update_forward_refs()
+
diff --git a/backend/tests/api/test_mapping_endpoint.py b/backend/tests/api/test_mapping_endpoint.py
index 6752c1a06..506679c01 100644
--- a/backend/tests/api/test_mapping_endpoint.py
+++ b/backend/tests/api/test_mapping_endpoint.py
@@ -15,4 +15,3 @@ def test_mappings(search):
assert response.status_code == 200
assert response.headers["content-type"] == "application/json"
assert response.json() == search
-
diff --git a/backend/tests/unit/test_solr_parsers.py b/backend/tests/unit/test_solr_parsers.py
index cda34ac6b..18aab675e 100644
--- a/backend/tests/unit/test_solr_parsers.py
+++ b/backend/tests/unit/test_solr_parsers.py
@@ -72,6 +72,4 @@ def test_parse_mappings(mapping_response, mappings):
mapping_response["response"]["numFound"] = mapping_response["response"].pop("num_found")
solr_response = SolrQueryResult(**mapping_response)
parsed = parse_mappings(solr_response)
- assert (
- parsed == mappings
- ), f"Parsed result is not as expected. Difference: {dict_diff(parsed.dict(), mappings)}"
\ No newline at end of file
+ assert parsed == mappings, f"Parsed result is not as expected. Difference: {dict_diff(parsed.dict(), mappings)}"
diff --git a/frontend/src/api/model.ts b/frontend/src/api/model.ts
index febc18638..0c74ac2f6 100644
--- a/frontend/src/api/model.ts
+++ b/frontend/src/api/model.ts
@@ -511,18 +511,18 @@ export interface TermPairwiseSimilarity extends PairwiseSimilarity {
ancestor_label?: string,
ancestor_source?: string,
/** The IC of the object */
- object_information_content?: string,
+ object_information_content?: number,
/** The IC of the subject */
- subject_information_content?: string,
+ subject_information_content?: number,
/** The IC of the object */
- ancestor_information_content?: string,
+ ancestor_information_content?: number,
/** The number of concepts in the intersection divided by the number in the union */
- jaccard_similarity?: string,
+ jaccard_similarity?: number,
/** the dot product of two node embeddings divided by the product of their lengths */
cosine_similarity?: number,
- dice_similarity?: string,
+ dice_similarity?: number,
/** the geometric mean of the jaccard similarity and the information content */
- phenodigm_score?: string,
+ phenodigm_score?: number,
};
/**
* A simple pairwise similarity between two sets of concepts/terms
From 100152725fa8ec7f134cf18a5c835d1779d89501 Mon Sep 17 00:00:00 2001
From: glass-ships
Date: Fri, 10 Nov 2023 11:12:56 -0700
Subject: [PATCH 7/9] update fixtures
---
backend/src/monarch_py/datamodels/model.py | 509 +++++++++++++-----
backend/src/monarch_py/datamodels/model.yaml | 10 +-
.../solr/solr_implementation.py | 15 +
backend/src/monarch_py/utils/entity_utils.py | 6 +
backend/tests/fixtures/histopheno_response.py | 2 +-
backend/tests/fixtures/node.py | 9 +
frontend/fixtures/node.json | 30 ++
frontend/src/api/model.ts | 14 +-
8 files changed, 451 insertions(+), 144 deletions(-)
diff --git a/backend/src/monarch_py/datamodels/model.py b/backend/src/monarch_py/datamodels/model.py
index b74d9d289..dbe8b7e46 100644
--- a/backend/src/monarch_py/datamodels/model.py
+++ b/backend/src/monarch_py/datamodels/model.py
@@ -4,6 +4,7 @@
from typing import List, Dict, Optional, Any, Union
from pydantic import BaseModel as BaseModel, ConfigDict, Field
import sys
+
if sys.version_info >= (3, 8):
from typing import Literal
else:
@@ -13,16 +14,20 @@
metamodel_version = "None"
version = "None"
+
class WeakRefShimBaseModel(BaseModel):
- __slots__ = '__weakref__'
-
-class ConfiguredBaseModel(WeakRefShimBaseModel,
- validate_assignment = True,
- validate_all = True,
- underscore_attrs_are_private = True,
- extra = 'forbid',
- arbitrary_types_allowed = True,
- use_enum_values = True):
+ __slots__ = "__weakref__"
+
+
+class ConfiguredBaseModel(
+ WeakRefShimBaseModel,
+ validate_assignment=True,
+ validate_all=True,
+ underscore_attrs_are_private=True,
+ extra="forbid",
+ arbitrary_types_allowed=True,
+ use_enum_values=True,
+):
pass
@@ -30,24 +35,30 @@ class AssociationDirectionEnum(str, Enum):
"""
The directionality of an association as it relates to a specified entity, with edges being categorized as incoming or outgoing
"""
+
# An association for which a specified entity is the object or part of the object closure
incoming = "incoming"
# An association for which a specified entity is the subject or part of the subject closure
outgoing = "outgoing"
-
-
+
class Association(ConfiguredBaseModel):
-
+
id: str = Field(...)
category: Optional[str] = Field(None)
subject: str = Field(...)
original_subject: Optional[str] = Field(None)
subject_namespace: Optional[str] = Field(None, description="""The namespace/prefix of the subject entity""")
subject_category: Optional[str] = Field(None, description="""The category of the subject entity""")
- subject_closure: Optional[List[str]] = Field(default_factory=list, description="""Field containing subject id and the ids of all of it's ancestors""")
+ subject_closure: Optional[List[str]] = Field(
+ default_factory=list,
+ description="""Field containing subject id and the ids of all of it's ancestors""",
+ )
subject_label: Optional[str] = Field(None, description="""The name of the subject entity""")
- subject_closure_label: Optional[List[str]] = Field(default_factory=list, description="""Field containing subject name and the names of all of it's ancestors""")
+ subject_closure_label: Optional[List[str]] = Field(
+ default_factory=list,
+ description="""Field containing subject name and the names of all of it's ancestors""",
+ )
subject_taxon: Optional[str] = Field(None)
subject_taxon_label: Optional[str] = Field(None)
predicate: str = Field(...)
@@ -55,86 +66,176 @@ class Association(ConfiguredBaseModel):
original_object: Optional[str] = Field(None)
object_namespace: Optional[str] = Field(None, description="""The namespace/prefix of the object entity""")
object_category: Optional[str] = Field(None, description="""The category of the object entity""")
- object_closure: Optional[List[str]] = Field(default_factory=list, description="""Field containing object id and the ids of all of it's ancestors""")
+ object_closure: Optional[List[str]] = Field(
+ default_factory=list,
+ description="""Field containing object id and the ids of all of it's ancestors""",
+ )
object_label: Optional[str] = Field(None, description="""The name of the object entity""")
- object_closure_label: Optional[List[str]] = Field(default_factory=list, description="""Field containing object name and the names of all of it's ancestors""")
+ object_closure_label: Optional[List[str]] = Field(
+ default_factory=list,
+ description="""Field containing object name and the names of all of it's ancestors""",
+ )
object_taxon: Optional[str] = Field(None)
object_taxon_label: Optional[str] = Field(None)
primary_knowledge_source: Optional[str] = Field(None)
aggregator_knowledge_source: Optional[List[str]] = Field(default_factory=list)
negated: Optional[bool] = Field(None)
pathway: Optional[str] = Field(None)
- evidence_count: Optional[int] = Field(None, description="""count of supporting documents, evidence codes, and sources supplying evidence""")
+ evidence_count: Optional[int] = Field(
+ None,
+ description="""count of supporting documents, evidence codes, and sources supplying evidence""",
+ )
has_evidence: Optional[List[str]] = Field(default_factory=list)
- has_evidence_links: Optional[List[ExpandedCurie]] = Field(default_factory=list, description="""List of ExpandedCuries with id and url for evidence""")
- grouping_key: Optional[str] = Field(None, description="""A concatenation of fields used to group associations with the same essential/defining properties""")
+ has_evidence_links: Optional[List[ExpandedCurie]] = Field(
+ default_factory=list,
+ description="""List of ExpandedCuries with id and url for evidence""",
+ )
+ grouping_key: Optional[str] = Field(
+ None,
+ description="""A concatenation of fields used to group associations with the same essential/defining properties""",
+ )
provided_by: Optional[str] = Field(None)
- provided_by_link: Optional[ExpandedCurie] = Field(None, description="""A link to the docs for the knowledge source that provided the node/edge.""")
+ provided_by_link: Optional[ExpandedCurie] = Field(
+ None,
+ description="""A link to the docs for the knowledge source that provided the node/edge.""",
+ )
publications: Optional[List[str]] = Field(default_factory=list)
- publications_links: Optional[List[ExpandedCurie]] = Field(default_factory=list, description="""List of ExpandedCuries with id and url for publications""")
+ publications_links: Optional[List[ExpandedCurie]] = Field(
+ default_factory=list,
+ description="""List of ExpandedCuries with id and url for publications""",
+ )
qualifiers: Optional[List[str]] = Field(default_factory=list)
frequency_qualifier: Optional[str] = Field(None)
onset_qualifier: Optional[str] = Field(None)
sex_qualifier: Optional[str] = Field(None)
stage_qualifier: Optional[str] = Field(None)
qualifiers_label: Optional[str] = Field(None, description="""The name of the frequency_qualifier entity""")
- qualifiers_namespace: Optional[str] = Field(None, description="""The namespace/prefix of the frequency_qualifier entity""")
+ qualifiers_namespace: Optional[str] = Field(
+ None, description="""The namespace/prefix of the frequency_qualifier entity"""
+ )
qualifiers_category: Optional[str] = Field(None, description="""The category of the frequency_qualifier entity""")
- qualifiers_closure: Optional[List[str]] = Field(default_factory=list, description="""Field containing frequency_qualifier id and the ids of all of it's ancestors""")
- qualifiers_closure_label: Optional[List[str]] = Field(default_factory=list, description="""Field containing frequency_qualifier name and the names of all of it's ancestors""")
+ qualifiers_closure: Optional[List[str]] = Field(
+ default_factory=list,
+ description="""Field containing frequency_qualifier id and the ids of all of it's ancestors""",
+ )
+ qualifiers_closure_label: Optional[List[str]] = Field(
+ default_factory=list,
+ description="""Field containing frequency_qualifier name and the names of all of it's ancestors""",
+ )
frequency_qualifier_label: Optional[str] = Field(None, description="""The name of the frequency_qualifier entity""")
- frequency_qualifier_namespace: Optional[str] = Field(None, description="""The namespace/prefix of the frequency_qualifier entity""")
- frequency_qualifier_category: Optional[str] = Field(None, description="""The category of the frequency_qualifier entity""")
- frequency_qualifier_closure: Optional[List[str]] = Field(default_factory=list, description="""Field containing frequency_qualifier id and the ids of all of it's ancestors""")
- frequency_qualifier_closure_label: Optional[List[str]] = Field(default_factory=list, description="""Field containing frequency_qualifier name and the names of all of it's ancestors""")
+ frequency_qualifier_namespace: Optional[str] = Field(
+ None, description="""The namespace/prefix of the frequency_qualifier entity"""
+ )
+ frequency_qualifier_category: Optional[str] = Field(
+ None, description="""The category of the frequency_qualifier entity"""
+ )
+ frequency_qualifier_closure: Optional[List[str]] = Field(
+ default_factory=list,
+ description="""Field containing frequency_qualifier id and the ids of all of it's ancestors""",
+ )
+ frequency_qualifier_closure_label: Optional[List[str]] = Field(
+ default_factory=list,
+ description="""Field containing frequency_qualifier name and the names of all of it's ancestors""",
+ )
onset_qualifier_label: Optional[str] = Field(None, description="""The name of the onset_qualifier entity""")
- onset_qualifier_namespace: Optional[str] = Field(None, description="""The namespace/prefix of the onset_qualifier entity""")
+ onset_qualifier_namespace: Optional[str] = Field(
+ None, description="""The namespace/prefix of the onset_qualifier entity"""
+ )
onset_qualifier_category: Optional[str] = Field(None, description="""The category of the onset_qualifier entity""")
- onset_qualifier_closure: Optional[List[str]] = Field(default_factory=list, description="""Field containing onset_qualifier id and the ids of all of it's ancestors""")
- onset_qualifier_closure_label: Optional[List[str]] = Field(default_factory=list, description="""Field containing onset_qualifier name and the names of all of it's ancestors""")
+ onset_qualifier_closure: Optional[List[str]] = Field(
+ default_factory=list,
+ description="""Field containing onset_qualifier id and the ids of all of it's ancestors""",
+ )
+ onset_qualifier_closure_label: Optional[List[str]] = Field(
+ default_factory=list,
+ description="""Field containing onset_qualifier name and the names of all of it's ancestors""",
+ )
sex_qualifier_label: Optional[str] = Field(None, description="""The name of the sex_qualifier entity""")
- sex_qualifier_namespace: Optional[str] = Field(None, description="""The namespace/prefix of the sex_qualifier entity""")
+ sex_qualifier_namespace: Optional[str] = Field(
+ None, description="""The namespace/prefix of the sex_qualifier entity"""
+ )
sex_qualifier_category: Optional[str] = Field(None, description="""The category of the sex_qualifier entity""")
- sex_qualifier_closure: Optional[List[str]] = Field(default_factory=list, description="""Field containing sex_qualifier id and the ids of all of it's ancestors""")
- sex_qualifier_closure_label: Optional[List[str]] = Field(default_factory=list, description="""Field containing sex_qualifier name and the names of all of it's ancestors""")
+ sex_qualifier_closure: Optional[List[str]] = Field(
+ default_factory=list,
+ description="""Field containing sex_qualifier id and the ids of all of it's ancestors""",
+ )
+ sex_qualifier_closure_label: Optional[List[str]] = Field(
+ default_factory=list,
+ description="""Field containing sex_qualifier name and the names of all of it's ancestors""",
+ )
stage_qualifier_label: Optional[str] = Field(None, description="""The name of the stage_qualifier entity""")
- stage_qualifier_namespace: Optional[str] = Field(None, description="""The namespace/prefix of the stage_qualifier entity""")
+ stage_qualifier_namespace: Optional[str] = Field(
+ None, description="""The namespace/prefix of the stage_qualifier entity"""
+ )
stage_qualifier_category: Optional[str] = Field(None, description="""The category of the stage_qualifier entity""")
- stage_qualifier_closure: Optional[List[str]] = Field(default_factory=list, description="""Field containing stage_qualifier id and the ids of all of it's ancestors""")
- stage_qualifier_closure_label: Optional[List[str]] = Field(default_factory=list, description="""Field containing stage_qualifier name and the names of all of it's ancestors""")
-
+ stage_qualifier_closure: Optional[List[str]] = Field(
+ default_factory=list,
+ description="""Field containing stage_qualifier id and the ids of all of it's ancestors""",
+ )
+ stage_qualifier_closure_label: Optional[List[str]] = Field(
+ default_factory=list,
+ description="""Field containing stage_qualifier name and the names of all of it's ancestors""",
+ )
+
class AssociationCountList(ConfiguredBaseModel):
"""
Container class for a list of association counts
"""
- items: List[AssociationCount] = Field(default_factory=list, description="""A collection of items, with the type to be overriden by slot_usage""")
-
+
+ items: List[AssociationCount] = Field(
+ default_factory=list,
+ description="""A collection of items, with the type to be overriden by slot_usage""",
+ )
+
class AssociationTypeMapping(ConfiguredBaseModel):
"""
A data class to hold the necessary information to produce association type counts for given entities with appropriate directional labels
"""
- subject_label: Optional[str] = Field(None, description="""A label to describe the subjects of the association type as a whole for use in the UI""")
- object_label: Optional[str] = Field(None, description="""A label to describe the objects of the association type as a whole for use in the UI""")
- symmetric: bool = Field(False, description="""Whether the association type is symmetric, meaning that the subject and object labels should be interchangeable""")
- category: str = Field(..., description="""The biolink category to use in queries for this association type""")
-
+
+ subject_label: Optional[str] = Field(
+ None,
+ description="""A label to describe the subjects of the association type as a whole for use in the UI""",
+ )
+ object_label: Optional[str] = Field(
+ None,
+ description="""A label to describe the objects of the association type as a whole for use in the UI""",
+ )
+ symmetric: bool = Field(
+ False,
+ description="""Whether the association type is symmetric, meaning that the subject and object labels should be interchangeable""",
+ )
+ category: str = Field(
+ ...,
+ description="""The biolink category to use in queries for this association type""",
+ )
+
class DirectionalAssociation(Association):
"""
An association that gives it's direction relative to a specified entity
"""
- direction: AssociationDirectionEnum = Field(..., description="""The directionality of the association relative to a given entity for an association_count. If the entity is the subject or in the subject closure, the direction is forwards, if it is the object or in the object closure, the direction is backwards.""")
+
+ direction: AssociationDirectionEnum = Field(
+ ...,
+ description="""The directionality of the association relative to a given entity for an association_count. If the entity is the subject or in the subject closure, the direction is forwards, if it is the object or in the object closure, the direction is backwards.""",
+ )
id: str = Field(...)
category: Optional[str] = Field(None)
subject: str = Field(...)
original_subject: Optional[str] = Field(None)
subject_namespace: Optional[str] = Field(None, description="""The namespace/prefix of the subject entity""")
subject_category: Optional[str] = Field(None, description="""The category of the subject entity""")
- subject_closure: Optional[List[str]] = Field(default_factory=list, description="""Field containing subject id and the ids of all of it's ancestors""")
+ subject_closure: Optional[List[str]] = Field(
+ default_factory=list,
+ description="""Field containing subject id and the ids of all of it's ancestors""",
+ )
subject_label: Optional[str] = Field(None, description="""The name of the subject entity""")
- subject_closure_label: Optional[List[str]] = Field(default_factory=list, description="""Field containing subject name and the names of all of it's ancestors""")
+ subject_closure_label: Optional[List[str]] = Field(
+ default_factory=list,
+ description="""Field containing subject name and the names of all of it's ancestors""",
+ )
subject_taxon: Optional[str] = Field(None)
subject_taxon_label: Optional[str] = Field(None)
predicate: str = Field(...)
@@ -142,67 +243,132 @@ class DirectionalAssociation(Association):
original_object: Optional[str] = Field(None)
object_namespace: Optional[str] = Field(None, description="""The namespace/prefix of the object entity""")
object_category: Optional[str] = Field(None, description="""The category of the object entity""")
- object_closure: Optional[List[str]] = Field(default_factory=list, description="""Field containing object id and the ids of all of it's ancestors""")
+ object_closure: Optional[List[str]] = Field(
+ default_factory=list,
+ description="""Field containing object id and the ids of all of it's ancestors""",
+ )
object_label: Optional[str] = Field(None, description="""The name of the object entity""")
- object_closure_label: Optional[List[str]] = Field(default_factory=list, description="""Field containing object name and the names of all of it's ancestors""")
+ object_closure_label: Optional[List[str]] = Field(
+ default_factory=list,
+ description="""Field containing object name and the names of all of it's ancestors""",
+ )
object_taxon: Optional[str] = Field(None)
object_taxon_label: Optional[str] = Field(None)
primary_knowledge_source: Optional[str] = Field(None)
aggregator_knowledge_source: Optional[List[str]] = Field(default_factory=list)
negated: Optional[bool] = Field(None)
pathway: Optional[str] = Field(None)
- evidence_count: Optional[int] = Field(None, description="""count of supporting documents, evidence codes, and sources supplying evidence""")
+ evidence_count: Optional[int] = Field(
+ None,
+ description="""count of supporting documents, evidence codes, and sources supplying evidence""",
+ )
has_evidence: Optional[List[str]] = Field(default_factory=list)
- has_evidence_links: Optional[List[ExpandedCurie]] = Field(default_factory=list, description="""List of ExpandedCuries with id and url for evidence""")
- grouping_key: Optional[str] = Field(None, description="""A concatenation of fields used to group associations with the same essential/defining properties""")
+ has_evidence_links: Optional[List[ExpandedCurie]] = Field(
+ default_factory=list,
+ description="""List of ExpandedCuries with id and url for evidence""",
+ )
+ grouping_key: Optional[str] = Field(
+ None,
+ description="""A concatenation of fields used to group associations with the same essential/defining properties""",
+ )
provided_by: Optional[str] = Field(None)
- provided_by_link: Optional[ExpandedCurie] = Field(None, description="""A link to the docs for the knowledge source that provided the node/edge.""")
+ provided_by_link: Optional[ExpandedCurie] = Field(
+ None,
+ description="""A link to the docs for the knowledge source that provided the node/edge.""",
+ )
publications: Optional[List[str]] = Field(default_factory=list)
- publications_links: Optional[List[ExpandedCurie]] = Field(default_factory=list, description="""List of ExpandedCuries with id and url for publications""")
+ publications_links: Optional[List[ExpandedCurie]] = Field(
+ default_factory=list,
+ description="""List of ExpandedCuries with id and url for publications""",
+ )
qualifiers: Optional[List[str]] = Field(default_factory=list)
frequency_qualifier: Optional[str] = Field(None)
onset_qualifier: Optional[str] = Field(None)
sex_qualifier: Optional[str] = Field(None)
stage_qualifier: Optional[str] = Field(None)
qualifiers_label: Optional[str] = Field(None, description="""The name of the frequency_qualifier entity""")
- qualifiers_namespace: Optional[str] = Field(None, description="""The namespace/prefix of the frequency_qualifier entity""")
+ qualifiers_namespace: Optional[str] = Field(
+ None, description="""The namespace/prefix of the frequency_qualifier entity"""
+ )
qualifiers_category: Optional[str] = Field(None, description="""The category of the frequency_qualifier entity""")
- qualifiers_closure: Optional[List[str]] = Field(default_factory=list, description="""Field containing frequency_qualifier id and the ids of all of it's ancestors""")
- qualifiers_closure_label: Optional[List[str]] = Field(default_factory=list, description="""Field containing frequency_qualifier name and the names of all of it's ancestors""")
+ qualifiers_closure: Optional[List[str]] = Field(
+ default_factory=list,
+ description="""Field containing frequency_qualifier id and the ids of all of it's ancestors""",
+ )
+ qualifiers_closure_label: Optional[List[str]] = Field(
+ default_factory=list,
+ description="""Field containing frequency_qualifier name and the names of all of it's ancestors""",
+ )
frequency_qualifier_label: Optional[str] = Field(None, description="""The name of the frequency_qualifier entity""")
- frequency_qualifier_namespace: Optional[str] = Field(None, description="""The namespace/prefix of the frequency_qualifier entity""")
- frequency_qualifier_category: Optional[str] = Field(None, description="""The category of the frequency_qualifier entity""")
- frequency_qualifier_closure: Optional[List[str]] = Field(default_factory=list, description="""Field containing frequency_qualifier id and the ids of all of it's ancestors""")
- frequency_qualifier_closure_label: Optional[List[str]] = Field(default_factory=list, description="""Field containing frequency_qualifier name and the names of all of it's ancestors""")
+ frequency_qualifier_namespace: Optional[str] = Field(
+ None, description="""The namespace/prefix of the frequency_qualifier entity"""
+ )
+ frequency_qualifier_category: Optional[str] = Field(
+ None, description="""The category of the frequency_qualifier entity"""
+ )
+ frequency_qualifier_closure: Optional[List[str]] = Field(
+ default_factory=list,
+ description="""Field containing frequency_qualifier id and the ids of all of it's ancestors""",
+ )
+ frequency_qualifier_closure_label: Optional[List[str]] = Field(
+ default_factory=list,
+ description="""Field containing frequency_qualifier name and the names of all of it's ancestors""",
+ )
onset_qualifier_label: Optional[str] = Field(None, description="""The name of the onset_qualifier entity""")
- onset_qualifier_namespace: Optional[str] = Field(None, description="""The namespace/prefix of the onset_qualifier entity""")
+ onset_qualifier_namespace: Optional[str] = Field(
+ None, description="""The namespace/prefix of the onset_qualifier entity"""
+ )
onset_qualifier_category: Optional[str] = Field(None, description="""The category of the onset_qualifier entity""")
- onset_qualifier_closure: Optional[List[str]] = Field(default_factory=list, description="""Field containing onset_qualifier id and the ids of all of it's ancestors""")
- onset_qualifier_closure_label: Optional[List[str]] = Field(default_factory=list, description="""Field containing onset_qualifier name and the names of all of it's ancestors""")
+ onset_qualifier_closure: Optional[List[str]] = Field(
+ default_factory=list,
+ description="""Field containing onset_qualifier id and the ids of all of it's ancestors""",
+ )
+ onset_qualifier_closure_label: Optional[List[str]] = Field(
+ default_factory=list,
+ description="""Field containing onset_qualifier name and the names of all of it's ancestors""",
+ )
sex_qualifier_label: Optional[str] = Field(None, description="""The name of the sex_qualifier entity""")
- sex_qualifier_namespace: Optional[str] = Field(None, description="""The namespace/prefix of the sex_qualifier entity""")
+ sex_qualifier_namespace: Optional[str] = Field(
+ None, description="""The namespace/prefix of the sex_qualifier entity"""
+ )
sex_qualifier_category: Optional[str] = Field(None, description="""The category of the sex_qualifier entity""")
- sex_qualifier_closure: Optional[List[str]] = Field(default_factory=list, description="""Field containing sex_qualifier id and the ids of all of it's ancestors""")
- sex_qualifier_closure_label: Optional[List[str]] = Field(default_factory=list, description="""Field containing sex_qualifier name and the names of all of it's ancestors""")
+ sex_qualifier_closure: Optional[List[str]] = Field(
+ default_factory=list,
+ description="""Field containing sex_qualifier id and the ids of all of it's ancestors""",
+ )
+ sex_qualifier_closure_label: Optional[List[str]] = Field(
+ default_factory=list,
+ description="""Field containing sex_qualifier name and the names of all of it's ancestors""",
+ )
stage_qualifier_label: Optional[str] = Field(None, description="""The name of the stage_qualifier entity""")
- stage_qualifier_namespace: Optional[str] = Field(None, description="""The namespace/prefix of the stage_qualifier entity""")
+ stage_qualifier_namespace: Optional[str] = Field(
+ None, description="""The namespace/prefix of the stage_qualifier entity"""
+ )
stage_qualifier_category: Optional[str] = Field(None, description="""The category of the stage_qualifier entity""")
- stage_qualifier_closure: Optional[List[str]] = Field(default_factory=list, description="""Field containing stage_qualifier id and the ids of all of it's ancestors""")
- stage_qualifier_closure_label: Optional[List[str]] = Field(default_factory=list, description="""Field containing stage_qualifier name and the names of all of it's ancestors""")
-
+ stage_qualifier_closure: Optional[List[str]] = Field(
+ default_factory=list,
+ description="""Field containing stage_qualifier id and the ids of all of it's ancestors""",
+ )
+ stage_qualifier_closure_label: Optional[List[str]] = Field(
+ default_factory=list,
+ description="""Field containing stage_qualifier name and the names of all of it's ancestors""",
+ )
+
class ExpandedCurie(ConfiguredBaseModel):
"""
A curie bundled along with its expanded url
"""
+
id: str = Field(...)
url: Optional[str] = Field(None)
-
+
class Entity(ConfiguredBaseModel):
"""
Represents an Entity in the Monarch KG data model
"""
+
id: str = Field(...)
category: Optional[str] = Field(None)
name: Optional[str] = Field(None)
@@ -211,48 +377,58 @@ class Entity(ConfiguredBaseModel):
xref: Optional[List[str]] = Field(default_factory=list)
provided_by: Optional[str] = Field(None)
in_taxon: Optional[str] = Field(None, description="""The biolink taxon that the entity is in the closure of.""")
- in_taxon_label: Optional[str] = Field(None, description="""The label of the biolink taxon that the entity is in the closure of.""")
+ in_taxon_label: Optional[str] = Field(
+ None,
+ description="""The label of the biolink taxon that the entity is in the closure of.""",
+ )
symbol: Optional[str] = Field(None)
synonym: Optional[List[str]] = Field(default_factory=list)
uri: Optional[str] = Field(None, description="""The URI of the entity""")
-
+
class FacetValue(ConfiguredBaseModel):
-
+
label: str = Field(...)
count: Optional[int] = Field(None, description="""count of documents""")
-
+
class AssociationCount(FacetValue):
-
+
category: Optional[str] = Field(None)
label: str = Field(...)
count: Optional[int] = Field(None, description="""count of documents""")
-
+
class FacetField(ConfiguredBaseModel):
-
+
label: str = Field(...)
- facet_values: Optional[List[FacetValue]] = Field(default_factory=list, description="""Collection of FacetValue label/value instances belonging to a FacetField""")
-
+ facet_values: Optional[List[FacetValue]] = Field(
+ default_factory=list,
+ description="""Collection of FacetValue label/value instances belonging to a FacetField""",
+ )
+
class HistoPheno(ConfiguredBaseModel):
-
+
id: str = Field(...)
- items: List[HistoBin] = Field(default_factory=list, description="""A collection of items, with the type to be overriden by slot_usage""")
-
+ items: List[HistoBin] = Field(
+ default_factory=list,
+ description="""A collection of items, with the type to be overriden by slot_usage""",
+ )
+
class HistoBin(FacetValue):
-
+
id: str = Field(...)
label: str = Field(...)
count: Optional[int] = Field(None, description="""count of documents""")
-
+
class Mapping(ConfiguredBaseModel):
"""
A minimal class to hold a SSSOM mapping
"""
+
subject_id: str = Field(...)
subject_label: Optional[str] = Field(None, description="""The name of the subject entity""")
predicate_id: str = Field(...)
@@ -260,19 +436,38 @@ class Mapping(ConfiguredBaseModel):
object_label: Optional[str] = Field(None, description="""The name of the object entity""")
mapping_justification: Optional[str] = Field(None)
id: str = Field(...)
-
+
class Node(Entity):
"""
UI container class extending Entity with additional information
"""
+
in_taxon: Optional[str] = Field(None, description="""The biolink taxon that the entity is in the closure of.""")
- in_taxon_label: Optional[str] = Field(None, description="""The label of the biolink taxon that the entity is in the closure of.""")
+ in_taxon_label: Optional[str] = Field(
+ None,
+ description="""The label of the biolink taxon that the entity is in the closure of.""",
+ )
inheritance: Optional[Entity] = Field(None)
- causal_gene: Optional[List[Entity]] = Field(default_factory=list, description="""A list of genes that are known to be causally associated with a disease""")
- causes_disease: Optional[List[Entity]] = Field(default_factory=list, description="""A list of diseases that are known to be causally associated with a gene""")
- external_links: Optional[List[ExpandedCurie]] = Field(default_factory=list, description="""ExpandedCurie with id and url for xrefs""")
- provided_by_link: Optional[ExpandedCurie] = Field(None, description="""A link to the docs for the knowledge source that provided the node/edge.""")
+ causal_gene: Optional[List[Entity]] = Field(
+ default_factory=list,
+ description="""A list of genes that are known to be causally associated with a disease""",
+ )
+ causes_disease: Optional[List[Entity]] = Field(
+ default_factory=list,
+ description="""A list of diseases that are known to be causally associated with a gene""",
+ )
+ mappings: Optional[List[ExpandedCurie]] = Field(
+ default_factory=list,
+ description="""List of ExpandedCuries with id and url for mapped entities""",
+ )
+ external_links: Optional[List[ExpandedCurie]] = Field(
+ default_factory=list, description="""ExpandedCurie with id and url for xrefs"""
+ )
+ provided_by_link: Optional[ExpandedCurie] = Field(
+ None,
+ description="""A link to the docs for the knowledge source that provided the node/edge.""",
+ )
association_counts: List[AssociationCount] = Field(default_factory=list)
node_hierarchy: Optional[NodeHierarchy] = Field(None)
id: str = Field(...)
@@ -285,76 +480,95 @@ class Node(Entity):
symbol: Optional[str] = Field(None)
synonym: Optional[List[str]] = Field(default_factory=list)
uri: Optional[str] = Field(None, description="""The URI of the entity""")
-
+
class NodeHierarchy(ConfiguredBaseModel):
-
+
super_classes: List[Entity] = Field(default_factory=list)
sub_classes: List[Entity] = Field(default_factory=list)
-
+
class Results(ConfiguredBaseModel):
-
+
limit: int = Field(..., description="""number of items to return in a response""")
offset: int = Field(..., description="""offset into the total number of items""")
total: int = Field(..., description="""total number of items matching a query""")
-
+
class AssociationResults(Results):
-
- items: List[Association] = Field(default_factory=list, description="""A collection of items, with the type to be overriden by slot_usage""")
+
+ items: List[Association] = Field(
+ default_factory=list,
+ description="""A collection of items, with the type to be overriden by slot_usage""",
+ )
limit: int = Field(..., description="""number of items to return in a response""")
offset: int = Field(..., description="""offset into the total number of items""")
total: int = Field(..., description="""total number of items matching a query""")
-
+
class AssociationTableResults(Results):
-
- items: List[DirectionalAssociation] = Field(default_factory=list, description="""A collection of items, with the type to be overriden by slot_usage""")
+
+ items: List[DirectionalAssociation] = Field(
+ default_factory=list,
+ description="""A collection of items, with the type to be overriden by slot_usage""",
+ )
limit: int = Field(..., description="""number of items to return in a response""")
offset: int = Field(..., description="""offset into the total number of items""")
total: int = Field(..., description="""total number of items matching a query""")
-
+
class CategoryGroupedAssociationResults(Results):
-
- counterpart_category: Optional[str] = Field(None, description="""The category of the counterpart entity in a given association, eg. the category of the entity that is not the subject""")
- items: List[Association] = Field(default_factory=list, description="""A collection of items, with the type to be overriden by slot_usage""")
+
+ counterpart_category: Optional[str] = Field(
+ None,
+ description="""The category of the counterpart entity in a given association, eg. the category of the entity that is not the subject""",
+ )
+ items: List[Association] = Field(
+ default_factory=list,
+ description="""A collection of items, with the type to be overriden by slot_usage""",
+ )
limit: int = Field(..., description="""number of items to return in a response""")
offset: int = Field(..., description="""offset into the total number of items""")
total: int = Field(..., description="""total number of items matching a query""")
-
+
class EntityResults(Results):
-
- items: List[Entity] = Field(default_factory=list, description="""A collection of items, with the type to be overriden by slot_usage""")
+
+ items: List[Entity] = Field(
+ default_factory=list,
+ description="""A collection of items, with the type to be overriden by slot_usage""",
+ )
limit: int = Field(..., description="""number of items to return in a response""")
offset: int = Field(..., description="""offset into the total number of items""")
total: int = Field(..., description="""total number of items matching a query""")
-
+
class MappingResults(Results):
"""
SSSOM Mappings returned as a results collection
"""
- items: List[Mapping] = Field(default_factory=list, description="""A collection of items, with the type to be overriden by slot_usage""")
+
+ items: List[Mapping] = Field(
+ default_factory=list,
+ description="""A collection of items, with the type to be overriden by slot_usage""",
+ )
limit: int = Field(..., description="""number of items to return in a response""")
offset: int = Field(..., description="""offset into the total number of items""")
total: int = Field(..., description="""total number of items matching a query""")
-
+
class MultiEntityAssociationResults(Results):
-
+
id: str = Field(...)
name: Optional[str] = Field(None)
associated_categories: List[CategoryGroupedAssociationResults] = Field(default_factory=list)
limit: int = Field(..., description="""number of items to return in a response""")
offset: int = Field(..., description="""offset into the total number of items""")
total: int = Field(..., description="""total number of items matching a query""")
-
+
class SearchResult(Entity):
-
+
highlight: Optional[str] = Field(None, description="""matching text snippet containing html tags""")
score: Optional[float] = Field(None)
id: str = Field(...)
@@ -365,55 +579,82 @@ class SearchResult(Entity):
xref: Optional[List[str]] = Field(default_factory=list)
provided_by: Optional[str] = Field(None)
in_taxon: Optional[str] = Field(None, description="""The biolink taxon that the entity is in the closure of.""")
- in_taxon_label: Optional[str] = Field(None, description="""The label of the biolink taxon that the entity is in the closure of.""")
+ in_taxon_label: Optional[str] = Field(
+ None,
+ description="""The label of the biolink taxon that the entity is in the closure of.""",
+ )
symbol: Optional[str] = Field(None)
synonym: Optional[List[str]] = Field(default_factory=list)
uri: Optional[str] = Field(None, description="""The URI of the entity""")
-
+
class SearchResults(Results):
-
- items: List[SearchResult] = Field(default_factory=list, description="""A collection of items, with the type to be overriden by slot_usage""")
- facet_fields: Optional[List[FacetField]] = Field(default_factory=list, description="""Collection of facet field responses with the field values and counts""")
- facet_queries: Optional[List[FacetValue]] = Field(default_factory=list, description="""Collection of facet query responses with the query string values and counts""")
+
+ items: List[SearchResult] = Field(
+ default_factory=list,
+ description="""A collection of items, with the type to be overriden by slot_usage""",
+ )
+ facet_fields: Optional[List[FacetField]] = Field(
+ default_factory=list,
+ description="""Collection of facet field responses with the field values and counts""",
+ )
+ facet_queries: Optional[List[FacetValue]] = Field(
+ default_factory=list,
+ description="""Collection of facet query responses with the query string values and counts""",
+ )
limit: int = Field(..., description="""number of items to return in a response""")
offset: int = Field(..., description="""offset into the total number of items""")
total: int = Field(..., description="""total number of items matching a query""")
-
+
class PairwiseSimilarity(ConfiguredBaseModel):
"""
Abstract grouping for representing individual pairwise similarities
"""
+
None
-
+
class TermPairwiseSimilarity(PairwiseSimilarity):
"""
A simple pairwise similarity between two atomic concepts/terms
"""
+
subject_id: str = Field(...)
subject_label: Optional[str] = Field(None, description="""The name of the subject entity""")
subject_source: Optional[str] = Field(None, description="""the source for the first entity""")
object_id: str = Field(...)
object_label: Optional[str] = Field(None, description="""The name of the object entity""")
object_source: Optional[str] = Field(None, description="""the source for the second entity""")
- ancestor_id: Optional[str] = Field(None, description="""the most recent common ancestor of the two compared entities. If there are multiple MRCAs then the most informative one is selected""")
+ ancestor_id: Optional[str] = Field(
+ None,
+ description="""the most recent common ancestor of the two compared entities. If there are multiple MRCAs then the most informative one is selected""",
+ )
ancestor_label: Optional[str] = Field(None, description="""the name or label of the ancestor concept""")
ancestor_source: Optional[str] = Field(None)
object_information_content: Optional[float] = Field(None, description="""The IC of the object""")
subject_information_content: Optional[float] = Field(None, description="""The IC of the subject""")
ancestor_information_content: Optional[float] = Field(None, description="""The IC of the object""")
- jaccard_similarity: Optional[float] = Field(None, description="""The number of concepts in the intersection divided by the number in the union""")
- cosine_similarity: Optional[float] = Field(None, description="""the dot product of two node embeddings divided by the product of their lengths""")
+ jaccard_similarity: Optional[float] = Field(
+ None,
+ description="""The number of concepts in the intersection divided by the number in the union""",
+ )
+ cosine_similarity: Optional[float] = Field(
+ None,
+ description="""the dot product of two node embeddings divided by the product of their lengths""",
+ )
dice_similarity: Optional[float] = Field(None)
- phenodigm_score: Optional[float] = Field(None, description="""the geometric mean of the jaccard similarity and the information content""")
-
+ phenodigm_score: Optional[float] = Field(
+ None,
+ description="""the geometric mean of the jaccard similarity and the information content""",
+ )
+
class TermSetPairwiseSimilarity(PairwiseSimilarity):
"""
A simple pairwise similarity between two sets of concepts/terms
"""
+
subject_termset: Optional[Dict[str, TermInfo]] = Field(default_factory=dict)
object_termset: Optional[Dict[str, TermInfo]] = Field(default_factory=dict)
subject_best_matches: Optional[Dict[str, BestMatch]] = Field(default_factory=dict)
@@ -421,16 +662,16 @@ class TermSetPairwiseSimilarity(PairwiseSimilarity):
average_score: Optional[float] = Field(None)
best_score: Optional[float] = Field(None)
metric: Optional[str] = Field(None)
-
+
class TermInfo(ConfiguredBaseModel):
-
+
id: str = Field(...)
label: Optional[str] = Field(None)
-
+
class BestMatch(ConfiguredBaseModel):
-
+
match_source: str = Field(...)
match_source_label: Optional[str] = Field(None)
match_target: Optional[str] = Field(None, description="""the entity matches""")
@@ -439,7 +680,6 @@ class BestMatch(ConfiguredBaseModel):
match_subsumer: Optional[str] = Field(None)
match_subsumer_label: Optional[str] = Field(None)
similarity: TermPairwiseSimilarity = Field(...)
-
# Update forward refs
@@ -472,4 +712,3 @@ class BestMatch(ConfiguredBaseModel):
TermSetPairwiseSimilarity.update_forward_refs()
TermInfo.update_forward_refs()
BestMatch.update_forward_refs()
-
diff --git a/backend/src/monarch_py/datamodels/model.yaml b/backend/src/monarch_py/datamodels/model.yaml
index 33604a394..6458fc9b3 100644
--- a/backend/src/monarch_py/datamodels/model.yaml
+++ b/backend/src/monarch_py/datamodels/model.yaml
@@ -234,6 +234,7 @@ classes:
- inheritance
- causal_gene
- causes_disease
+ - mappings
- external_links
- provided_by_link
- association_counts
@@ -526,7 +527,6 @@ slots:
qualifiers_closure_label:
multivalued: true
description: Field containing frequency_qualifier name and the names of all of it's ancestors
-
frequency_qualifier_label:
is_a: name
description: The name of the frequency_qualifier entity
@@ -587,7 +587,13 @@ slots:
stage_qualifier_closure_label:
multivalued: true
description: Field containing stage_qualifier name and the names of all of it's ancestors
-# sssom slots
+
+ # sssom slots
+ mappings:
+ description: List of ExpandedCuries with id and url for mapped entities
+ range: ExpandedCurie
+ multivalued: true
+ inlined_as_list: true
subject_id:
range: string
required: true
diff --git a/backend/src/monarch_py/implementations/solr/solr_implementation.py b/backend/src/monarch_py/implementations/solr/solr_implementation.py
index bc3afe350..0b2cc581d 100644
--- a/backend/src/monarch_py/implementations/solr/solr_implementation.py
+++ b/backend/src/monarch_py/implementations/solr/solr_implementation.py
@@ -44,6 +44,7 @@
from monarch_py.interfaces.entity_interface import EntityInterface
from monarch_py.interfaces.search_interface import SearchInterface
from monarch_py.service.solr_service import SolrService
+from monarch_py.utils.entity_utils import get_expanded_curie
from monarch_py.utils.utils import get_provided_by_link, get_links_for_field
@@ -116,11 +117,25 @@ def get_entity(self, id: str, extra: bool) -> Optional[Union[Node, Entity]]:
node.association_counts = self.get_association_counts(id).items
node.external_links = get_links_for_field(node.xref) if node.xref else []
node.provided_by_link = get_provided_by_link(node.provided_by)
+ node.mappings = self._get_mapped_entities(node)
return node
### Entity helpers ###
+ def _get_mapped_entities(self, this_entity: Entity) -> list:
+ """..."""
+ mapped_entities = []
+ mappings = self.get_mappings(entity_id=this_entity.id)
+ for m in mappings.items:
+ if this_entity.id == m.subject_id:
+ mapped_entities.append(get_expanded_curie(m.object_id))
+ elif this_entity.id == m.object_id:
+ mapped_entities.append(get_expanded_curie(m.subject_id))
+ else:
+ pass
+ return mapped_entities
+
def _get_associated_entity(self, association: Association, this_entity: Entity) -> Entity:
"""Returns the id, name, and category of the other Entity in an Association given this_entity"""
if this_entity.id == association.subject:
diff --git a/backend/src/monarch_py/utils/entity_utils.py b/backend/src/monarch_py/utils/entity_utils.py
index 97056219a..9cb8d032f 100644
--- a/backend/src/monarch_py/utils/entity_utils.py
+++ b/backend/src/monarch_py/utils/entity_utils.py
@@ -1,6 +1,12 @@
+from monarch_py.datamodels.model import ExpandedCurie
from monarch_py.service.curie_service import CurieService
def get_uri(id: str) -> str:
"""Returns the URI for the given CURIE."""
return CurieService().expand(id)
+
+
+def get_expanded_curie(id: str) -> ExpandedCurie:
+ """Returns the URI for the given CURIE."""
+ return ExpandedCurie(id=id, url=get_uri(id))
diff --git a/backend/tests/fixtures/histopheno_response.py b/backend/tests/fixtures/histopheno_response.py
index 67fb5632e..44789afcf 100644
--- a/backend/tests/fixtures/histopheno_response.py
+++ b/backend/tests/fixtures/histopheno_response.py
@@ -5,7 +5,7 @@
def histopheno_response():
return {
"responseHeader": {
- "QTime": 2,
+ "QTime": 1,
"params": {
"facet.query": [
'object_closure:"HP:0000924"',
diff --git a/backend/tests/fixtures/node.py b/backend/tests/fixtures/node.py
index a25b43ff0..b37dfc336 100644
--- a/backend/tests/fixtures/node.py
+++ b/backend/tests/fixtures/node.py
@@ -19,6 +19,15 @@ def node():
"inheritance": None,
"causal_gene": [],
"causes_disease": [],
+ "mappings": [
+ {"id": "DOID:9884", "url": "http://purl.obolibrary.org/obo/DOID_9884"},
+ {"id": "ICD10CM:G71.0", "url": "https://icd.codes/icd10cm/G71.0"},
+ {"id": "MESH:D009136", "url": "http://identifiers.org/mesh/D009136"},
+ {"id": "NCIT:C84910", "url": "http://purl.obolibrary.org/obo/NCIT_C84910"},
+ {"id": "SCTID:73297009", "url": None},
+ {"id": "UMLS:C0026850", "url": "http://identifiers.org/umls/C0026850"},
+ {"id": "Orphanet:98473", "url": None},
+ ],
"external_links": [],
"provided_by_link": {
"id": "phenio",
diff --git a/frontend/fixtures/node.json b/frontend/fixtures/node.json
index baf9051e2..d7f9825b0 100644
--- a/frontend/fixtures/node.json
+++ b/frontend/fixtures/node.json
@@ -14,6 +14,36 @@
"inheritance": null,
"causal_gene": [],
"causes_disease": [],
+ "mappings": [
+ {
+ "id": "DOID:9884",
+ "url": "http://purl.obolibrary.org/obo/DOID_9884"
+ },
+ {
+ "id": "ICD10CM:G71.0",
+ "url": "https://icd.codes/icd10cm/G71.0"
+ },
+ {
+ "id": "MESH:D009136",
+ "url": "http://identifiers.org/mesh/D009136"
+ },
+ {
+ "id": "NCIT:C84910",
+ "url": "http://purl.obolibrary.org/obo/NCIT_C84910"
+ },
+ {
+ "id": "SCTID:73297009",
+ "url": null
+ },
+ {
+ "id": "UMLS:C0026850",
+ "url": "http://identifiers.org/umls/C0026850"
+ },
+ {
+ "id": "Orphanet:98473",
+ "url": null
+ }
+ ],
"external_links": [],
"provided_by_link": {
"id": "phenio",
diff --git a/frontend/src/api/model.ts b/frontend/src/api/model.ts
index 0c74ac2f6..9ba9ee499 100644
--- a/frontend/src/api/model.ts
+++ b/frontend/src/api/model.ts
@@ -416,6 +416,8 @@ export interface Node extends Entity {
causal_gene?: Entity[],
/** A list of diseases that are known to be causally associated with a gene */
causes_disease?: Entity[],
+ /** List of ExpandedCuries with id and url for mapped entities */
+ mappings?: ExpandedCurie[],
/** ExpandedCurie with id and url for xrefs */
external_links?: ExpandedCurie[],
/** A link to the docs for the knowledge source that provided the node/edge. */
@@ -511,18 +513,18 @@ export interface TermPairwiseSimilarity extends PairwiseSimilarity {
ancestor_label?: string,
ancestor_source?: string,
/** The IC of the object */
- object_information_content?: number,
+ object_information_content?: string,
/** The IC of the subject */
- subject_information_content?: number,
+ subject_information_content?: string,
/** The IC of the object */
- ancestor_information_content?: number,
+ ancestor_information_content?: string,
/** The number of concepts in the intersection divided by the number in the union */
- jaccard_similarity?: number,
+ jaccard_similarity?: string,
/** the dot product of two node embeddings divided by the product of their lengths */
cosine_similarity?: number,
- dice_similarity?: number,
+ dice_similarity?: string,
/** the geometric mean of the jaccard similarity and the information content */
- phenodigm_score?: number,
+ phenodigm_score?: string,
};
/**
* A simple pairwise similarity between two sets of concepts/terms
From 3eb6463b0eb904ac718eb95e92d8f298f96ca557 Mon Sep 17 00:00:00 2001
From: Vincent Rubinetti
Date: Fri, 10 Nov 2023 14:16:15 -0500
Subject: [PATCH 8/9] implement in frontend
---
frontend/src/pages/node/SectionOverview.vue | 71 ++++++++++++++++++++-
frontend/yarn.lock | 30 ++++-----
2 files changed, 81 insertions(+), 20 deletions(-)
diff --git a/frontend/src/pages/node/SectionOverview.vue b/frontend/src/pages/node/SectionOverview.vue
index f831d3295..aae3fe9ee 100644
--- a/frontend/src/pages/node/SectionOverview.vue
+++ b/frontend/src/pages/node/SectionOverview.vue
@@ -80,13 +80,55 @@
>
+
+
+
+
+ {{ mapping.id }}
+
+
+
+
+
+
+ {{ mapping.id }}
+
+
+
+
+
+
+ {{ mapping.id }}
+
+
+
+
-
+