Skip to content

Commit

Permalink
finish implementation, cli, and api endpoint
Browse files Browse the repository at this point in the history
  • Loading branch information
glass-ships committed Nov 8, 2023
1 parent 0f97e16 commit 9f55969
Show file tree
Hide file tree
Showing 9 changed files with 275 additions and 179 deletions.
298 changes: 149 additions & 149 deletions backend/poetry.lock

Large diffs are not rendered by default.

21 changes: 21 additions & 0 deletions backend/src/monarch_py/api/search.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
22 changes: 22 additions & 0 deletions backend/src/monarch_py/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -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()
7 changes: 6 additions & 1 deletion backend/src/monarch_py/datamodels/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand Down Expand Up @@ -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):
Expand Down Expand Up @@ -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""")
Expand Down
3 changes: 3 additions & 0 deletions backend/src/monarch_py/datamodels/model.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
23 changes: 17 additions & 6 deletions backend/src/monarch_py/implementations/solr/solr_implementation.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
CategoryGroupedAssociationResults,
Entity,
HistoPheno,
MappingResults,
MultiEntityAssociationResults,
Node,
NodeHierarchy,
Expand All @@ -26,6 +27,7 @@
parse_autocomplete,
parse_entity,
parse_histopheno,
parse_mappings,
parse_search,
)
from monarch_py.implementations.solr.solr_query_utils import (
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
74 changes: 52 additions & 22 deletions backend/src/monarch_py/solr_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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",
Expand All @@ -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)
Expand All @@ -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
Expand Down Expand Up @@ -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"),
):
"""
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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)
4 changes: 4 additions & 0 deletions frontend/src/api/model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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 */
Expand Down

0 comments on commit 9f55969

Please sign in to comment.