From 4af15c04dceb5526838621692445840abd5bbaff Mon Sep 17 00:00:00 2001 From: Kevin Schaper <kevinschaper@gmail.com> Date: Tue, 26 Sep 2023 08:19:12 -0700 Subject: [PATCH] Bring in similarty through copy & paste instead of import (#346) Initially this PR started off with just pulling the schema and seeing if we could minimally just move to using a Dict for now, but since the frontend was using the typescript interfaces for the similarity classes, I ended up just bringing the schema in minus the three conflicting slots...which is actually the most minimal change. --- backend/src/monarch_py/cli.py | 2 +- backend/src/monarch_py/datamodels/model.py | 174 +++++++++++---- backend/src/monarch_py/datamodels/model.yaml | 4 +- .../src/monarch_py/datamodels/similarity.yaml | 206 ++++++++++++++++++ backend/src/monarch_py/utils/utils.py | 14 +- frontend/src/api/model.ts | 15 +- 6 files changed, 355 insertions(+), 60 deletions(-) create mode 100644 backend/src/monarch_py/datamodels/similarity.yaml diff --git a/backend/src/monarch_py/cli.py b/backend/src/monarch_py/cli.py index 19f105d2d..aafd47597 100644 --- a/backend/src/monarch_py/cli.py +++ b/backend/src/monarch_py/cli.py @@ -275,7 +275,7 @@ def compare( """Compare two entities using semantic similarity via OAK""" subjects = subjects.split(",") objects = objects.split(",") - response = oak.compare(subjects, objects) + response = oak().compare(subjects, objects) format_output(fmt, response, output) diff --git a/backend/src/monarch_py/datamodels/model.py b/backend/src/monarch_py/datamodels/model.py index 228b962a3..bad0a341b 100644 --- a/backend/src/monarch_py/datamodels/model.py +++ b/backend/src/monarch_py/datamodels/model.py @@ -47,13 +47,19 @@ class Association(ConfiguredBaseModel): id: str = Field(...) 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 label or name for the first 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""", @@ -63,13 +69,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 label or name for the second 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""", @@ -97,7 +109,9 @@ class Association(ConfiguredBaseModel): description="""count of supporting documents, evidence codes, and sources supplying evidence""", ) pathway: Optional[str] = Field(None) - 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""" ) @@ -112,11 +126,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""", @@ -125,11 +143,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""", @@ -138,11 +160,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""", @@ -199,13 +225,19 @@ class DirectionalAssociation(Association): id: str = Field(...) 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 label or name for the first 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""", @@ -215,13 +247,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 label or name for the second 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""", @@ -249,7 +287,9 @@ class DirectionalAssociation(Association): description="""count of supporting documents, evidence codes, and sources supplying evidence""", ) pathway: Optional[str] = Field(None) - 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""" ) @@ -264,11 +304,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""", @@ -277,11 +321,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""", @@ -290,11 +338,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""", @@ -322,11 +374,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.""", @@ -378,7 +434,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.""", @@ -404,7 +462,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) @@ -460,16 +520,22 @@ class EntityResults(Results): class SearchResult(Entity): - highlight: Optional[str] = Field(None, description="""matching text snippet containing html tags""") - score: Optional[str] = Field(None, description="""Abstract base slot for different kinds of scores""") + 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.""", @@ -510,21 +576,41 @@ class TermPairwiseSimilarity(PairwiseSimilarity): A simple pairwise similarity between two atomic concepts/terms """ - subject_id: str = Field(..., description="""The first of the two entities being compared""") - subject_label: Optional[str] = Field(None, description="""the label or name for the first entity""") - subject_source: Optional[str] = Field(None, description="""the source for the first entity""") - object_id: Optional[str] = Field(None, description="""The second of the two entities being compared""") - object_label: Optional[str] = Field(None, description="""the label or name for the second entity""") - object_source: Optional[str] = Field(None, description="""the source for the second entity""") + subject_id: str = Field( + ..., description="""The first of the two entities being compared""" + ) + 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: Optional[str] = Field( + None, description="""The second of the two entities being compared""" + ) + 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/model.yaml b/backend/src/monarch_py/datamodels/model.yaml index 90076427b..fe6ffc201 100644 --- a/backend/src/monarch_py/datamodels/model.yaml +++ b/backend/src/monarch_py/datamodels/model.yaml @@ -4,10 +4,9 @@ description: Data models for the Monarch Initiative data access library prefixes: linkml: https://w3id.org/linkml/ biolink: https://w3id.org/biolink/vocab/ - oak: https://w3id.org/oak/ imports: - linkml:types - - oak:similarity + - similarity default_range: string @@ -239,7 +238,6 @@ classes: items: range: SearchResult - slots: aggregator_knowledge_source: multivalued: true diff --git a/backend/src/monarch_py/datamodels/similarity.yaml b/backend/src/monarch_py/datamodels/similarity.yaml new file mode 100644 index 000000000..79f759334 --- /dev/null +++ b/backend/src/monarch_py/datamodels/similarity.yaml @@ -0,0 +1,206 @@ +id: https://w3id.org/monarch/monarch-py-similarity +name: monarch-py-similarity +description: Data models for the Monarch Initiative data access library +prefixes: + linkml: https://w3id.org/linkml/ +imports: + - linkml:types +default_range: string + +# This is a copy and paste from https://w3id.org/oak/similarity.yaml with some slots commented out because they +# conflicted with slots in the monarch-py schema + +classes: + PairwiseSimilarity: + abstract: true + description: >- + Abstract grouping for representing individual pairwise similarities + + TermPairwiseSimilarity: + is_a: PairwiseSimilarity + description: >- + A simple pairwise similarity between two atomic concepts/terms + slots: + - subject_id + - subject_label + - subject_source + - object_id + - object_label + - object_source + - ancestor_id + - ancestor_label + - ancestor_source + - object_information_content + - subject_information_content + - ancestor_information_content + - jaccard_similarity + - cosine_similarity + - dice_similarity + - phenodigm_score + + TermSetPairwiseSimilarity: + is_a: PairwiseSimilarity + description: >- + A simple pairwise similarity between two sets of concepts/terms + slots: + - subject_termset + - object_termset + - subject_best_matches + - object_best_matches + - average_score + - best_score + - metric + + TermInfo: + attributes: + id: + identifier: true + label: + slot_uri: rdfs:label + + BestMatch: + attributes: + match_source: + identifier: true + comments: + - note that the match_source is either the subject or the object + match_source_label: + match_target: + description: the entity matches + match_target_label: + score: + range: float + required: true + match_subsumer: + range: uriorcurie + match_subsumer_label: + similarity: + range: TermPairwiseSimilarity + required: true + + +types: + ZeroToOne: + typeof: float + minimum_value: 0 + maximum_value: 0 + NonNegativeFloat: + typeof: float + minimum_value: 0 + NegativeLogValue: + typeof: float + minimum_value: 0 + ItemCount: + typeof: integer + minimum_value: 0 + +slots: + subject_id: + slot_uri: sssom:subject_id + required: true + range: uriorcurie + description: The first of the two entities being compared + # Excluded, since it conflicts with subject_label from this schema + # subject_label: + # slot_uri: sssom:subject_label + # description: the label or name for the first entity + subject_source: + slot_uri: sssom:subject_source + description: the source for the first entity + object_id: + slot_uri: sssom:object_id + range: uriorcurie + description: The second of the two entities being compared + # Excluded, since it conflicts with object_label from this schema + # object_label: + # slot_uri: sssom:object_label + # description: the label or name for the second entity + object_source: + slot_uri: sssom:object_source + description: the source for the second entity + ancestor_id: + range: uriorcurie + description: >- + the most recent common ancestor of the two compared entities. If there are multiple MRCAs then + the most informative one is selected + todos: + - decide on what to do when there are multiple possible ancestos + ancestor_label: + description: the name or label of the ancestor concept + ancestor_source: + # Excluded, conflicts with score from this schema + # score: + # abstract: true + # description: Abstract base slot for different kinds of scores + information_content: + abstract: true + aliases: + - IC + is_a: score + range: NegativeLogValue + description: The IC is the negative log of the probability of the concept + subject_information_content: + is_a: information_content + description: The IC of the subject + object_information_content: + is_a: information_content + description: The IC of the object + ancestor_information_content: + is_a: information_content + description: The IC of the object + jaccard_similarity: + is_a: score + range: ZeroToOne + description: The number of concepts in the intersection divided by the number in the union + cosine_similarity: + is_a: score + range: float + description: the dot product of two node embeddings divided by the product of their lengths + dice_similarity: + is_a: score + range: ZeroToOne + phenodigm_score: + is_a: score + range: NonNegativeFloat + description: the geometric mean of the jaccard similarity and the information content + equals_expression: sqrt({jaccard_similarity} * {information_content}) + overlap_coefficient: + is_a: score + range: ZeroToOne + subsumes_score: + is_a: score + range: ZeroToOne + subsumed_by_score: + is_a: score + range: ZeroToOne + intersection_count: + is_a: score + range: ItemCount + union_count: + is_a: score + range: ItemCount + # TermSets + subject_termset: + range: TermInfo + multivalued: true + inlined: true + object_termset: + range: TermInfo + multivalued: true + inlined: true + subject_best_matches: + range: BestMatch + multivalued: true + inlined: true + object_best_matches: + range: BestMatch + multivalued: true + inlined: true + metric: + range: uriorcurie + average_score: + range: float + required: false + best_score: + range: float + required: false diff --git a/backend/src/monarch_py/utils/utils.py b/backend/src/monarch_py/utils/utils.py index c01786749..72d04ee99 100644 --- a/backend/src/monarch_py/utils/utils.py +++ b/backend/src/monarch_py/utils/utils.py @@ -1,5 +1,7 @@ import csv +import json import sys +from typing import Union, Dict import typer import yaml @@ -86,14 +88,18 @@ def get_headers_from_obj(obj: ConfiguredBaseModel) -> list: return list(headers) -def to_json(obj: ConfiguredBaseModel, file: str): +def to_json(obj: Union[ConfiguredBaseModel, Dict], file: str): """Converts a pydantic model to a JSON string.""" + if isinstance(obj, ConfiguredBaseModel): + json_value = obj.json(indent=4) + elif isinstance(obj, dict): + json_value = json.dumps(obj, indent=4) if file: with open(file, "w") as f: - f.write(obj.json(indent=4)) + f.write(json_value) console.print(f"\nOutput written to {file}\n") else: - print_json(obj.json(indent=4)) + print_json(json_value) def to_tsv(obj: ConfiguredBaseModel, file: str) -> str: @@ -182,7 +188,7 @@ def to_yaml(obj: ConfiguredBaseModel, file: str): return -def format_output(fmt: str, response: ConfiguredBaseModel, output: str): +def format_output(fmt: str, response: Union[ConfiguredBaseModel, Dict], output: str): if fmt.lower() == "json": to_json(response, output) elif fmt.lower() == "tsv": diff --git a/frontend/src/api/model.ts b/frontend/src/api/model.ts index be1347dec..112c9980a 100644 --- a/frontend/src/api/model.ts +++ b/frontend/src/api/model.ts @@ -31,7 +31,7 @@ export interface Association { subject_category?: string, /** Field containing subject id and the ids of all of it's ancestors */ subject_closure?: string[], - /** the label or name for the first entity */ + /** The name of the subject entity */ subject_label?: string, /** Field containing subject name and the names of all of it's ancestors */ subject_closure_label?: string[], @@ -46,7 +46,7 @@ export interface Association { object_category?: string, /** Field containing object id and the ids of all of it's ancestors */ object_closure?: string[], - /** the label or name for the second entity */ + /** The name of the object entity */ object_label?: string, /** Field containing object name and the names of all of it's ancestors */ object_closure_label?: string[], @@ -174,7 +174,7 @@ export interface DirectionalAssociation extends Association { subject_category?: string, /** Field containing subject id and the ids of all of it's ancestors */ subject_closure?: string[], - /** the label or name for the first entity */ + /** The name of the subject entity */ subject_label?: string, /** Field containing subject name and the names of all of it's ancestors */ subject_closure_label?: string[], @@ -189,7 +189,7 @@ export interface DirectionalAssociation extends Association { object_category?: string, /** Field containing object id and the ids of all of it's ancestors */ object_closure?: string[], - /** the label or name for the second entity */ + /** The name of the object entity */ object_label?: string, /** Field containing object name and the names of all of it's ancestors */ object_closure_label?: string[], @@ -363,8 +363,7 @@ export interface Results { export interface SearchResult extends Entity { /** matching text snippet containing html tags */ highlight?: string, - /** Abstract base slot for different kinds of scores */ - score?: string, + score?: number, id: string, category: string, name: string, @@ -406,13 +405,13 @@ export interface PairwiseSimilarity { export interface TermPairwiseSimilarity extends PairwiseSimilarity { /** The first of the two entities being compared */ subject_id: string, - /** the label or name for the first entity */ + /** The name of the subject entity */ subject_label?: string, /** the source for the first entity */ subject_source?: string, /** The second of the two entities being compared */ object_id?: string, - /** the label or name for the second entity */ + /** The name of the object entity */ object_label?: string, /** the source for the second entity */ object_source?: string,