forked from ave-dcd/dcd_mapping
-
Notifications
You must be signed in to change notification settings - Fork 0
Error reporting #20
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Error reporting #20
Changes from all commits
Commits
Show all changes
17 commits
Select commit
Hold shift + click to select a range
6d1bbf7
Initialize dcd_mapping api server
sallybg 18e340c
Have the api create vrs mapped objects with preferred layer only
sallybg 0b1c7c1
squash: formatting changes
sallybg 06caf58
Allow pre-map genomic variant without corresponding post-map genomic …
sallybg 5f05d8c
Generate MappedScore with error message if mapping fails
sallybg 5ce5a09
fixup mapped error messages
sallybg 3e771d5
Add score set-based error handling
sallybg 7a7a009
Initialize versioning, add date and version to output
sallybg 7b4dd8e
Add error handling for external data sources
sallybg 4535bcd
Add error messages for VRS id lookups
sallybg 20ea78b
Merge branch 'api' into error-reporting
sallybg 589c050
Add error handling to api map function
sallybg 5b3c2fb
Add API docstrings
sallybg 2fbecd0
Use Field() to set values for default fields in ScoresetMapping
sallybg 46f1b2d
Make Authenticated Requests if Envvars are Set
bencap 3a097b5
User python serialization mode instead of json
sallybg cc8f3ad
Set envvar in Git Actions Tests
bencap File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| """Provide VRS mapping utilities API""" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| """Provide routers for dcd mapping API""" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,161 @@ | ||
| """"Provide mapping router""" | ||
| from cool_seq_tool.schemas import AnnotationLayer | ||
| from fastapi import APIRouter, HTTPException | ||
| from fastapi.responses import JSONResponse | ||
| from requests import HTTPError | ||
|
|
||
| from dcd_mapping.align import AlignmentError, BlatNotFoundError, align | ||
| from dcd_mapping.annotate import ( | ||
| _get_computed_reference_sequence, | ||
| _get_mapped_reference_sequence, | ||
| _set_scoreset_layer, | ||
| annotate, | ||
| ) | ||
| from dcd_mapping.lookup import DataLookupError | ||
| from dcd_mapping.mavedb_data import ( | ||
| ScoresetNotSupportedError, | ||
| get_raw_scoreset_metadata, | ||
| get_scoreset_metadata, | ||
| get_scoreset_records, | ||
| ) | ||
| from dcd_mapping.resource_utils import ResourceAcquisitionError | ||
| from dcd_mapping.schemas import ScoreAnnotation, ScoresetMapping, VrsVersion | ||
| from dcd_mapping.transcripts import TxSelectError, select_transcript | ||
| from dcd_mapping.vrs_map import VrsMapError, vrs_map | ||
|
|
||
| router = APIRouter( | ||
| prefix="/api/v1", tags=["mappings"], responses={404: {"description": "Not found"}} | ||
| ) | ||
|
|
||
|
|
||
| @router.post(path="/map/{urn}", status_code=200, response_model=ScoresetMapping) | ||
| async def map_scoreset(urn: str) -> ScoresetMapping: | ||
| """Perform end-to-end mapping for a scoreset. | ||
|
|
||
| :param urn: identifier for a scoreset. | ||
| :param output_path: optional path to save output at | ||
| :param vrs_version: version of VRS objects to output (1.3 or 2) | ||
| :param silent: if True, suppress console information output | ||
| """ | ||
| try: | ||
| metadata = get_scoreset_metadata(urn) | ||
| records = get_scoreset_records(urn, True) | ||
| except ScoresetNotSupportedError as e: | ||
| return ScoresetMapping( | ||
| metadata=None, | ||
| error_message=str(e).strip("'"), | ||
| ) | ||
| except ResourceAcquisitionError as e: | ||
| msg = f"Unable to acquire resource from MaveDB: {e}" | ||
| raise HTTPException(status_code=500, detail=msg) from e | ||
|
|
||
| try: | ||
| alignment_result = align(metadata, True) | ||
| except BlatNotFoundError as e: | ||
| msg = "BLAT command appears missing. Ensure it is available on the $PATH or use the environment variable BLAT_BIN_PATH to point to it. See instructions in the README prerequisites section for more." | ||
| raise HTTPException(status_code=500, detail=msg) from e | ||
| except ResourceAcquisitionError as e: | ||
| msg = f"BLAT resource could not be acquired: {e}" | ||
| raise HTTPException(status_code=500, detail=msg) from e | ||
| except AlignmentError as e: | ||
| return JSONResponse( | ||
| content=ScoresetMapping( | ||
| metadata=metadata, error_message=str(e).strip("'") | ||
| ).model_dump(exclude_none=True) | ||
| ) | ||
|
|
||
| try: | ||
| transcript = await select_transcript(metadata, records, alignment_result) | ||
| except (TxSelectError, KeyError, ValueError) as e: | ||
| return JSONResponse( | ||
| content=ScoresetMapping( | ||
| metadata=metadata, error_message=str(e).strip("'") | ||
| ).model_dump(exclude_none=True) | ||
| ) | ||
| except HTTPError as e: | ||
| msg = f"HTTP error occurred during transcript selection: {e}" | ||
| raise HTTPException(status_code=500, detail=msg) from e | ||
| except DataLookupError as e: | ||
| msg = f"Data lookup error occurred during transcript selection: {e}" | ||
| raise HTTPException(status_code=500, detail=msg) from e | ||
|
|
||
| try: | ||
| vrs_results = vrs_map(metadata, alignment_result, records, transcript, True) | ||
| except VrsMapError as e: | ||
| return JSONResponse( | ||
| content=ScoresetMapping( | ||
| metadata=metadata, error_message=str(e).strip("'") | ||
| ).model_dump(exclude_none=True) | ||
| ) | ||
| if vrs_results is None: | ||
| return ScoresetMapping( | ||
| metadata=metadata, | ||
| error_message="No variant mappings available for this score set", | ||
| ) | ||
|
|
||
| try: | ||
| vrs_results = annotate(vrs_results, transcript, metadata, VrsVersion.V_2) | ||
| except Exception as e: | ||
| return JSONResponse( | ||
| content=ScoresetMapping( | ||
| metadata=metadata, error_message=str(e).strip("'") | ||
| ).model_dump(exclude_none=True) | ||
| ) | ||
| if vrs_results is None: | ||
| return ScoresetMapping( | ||
| metadata=metadata, | ||
| error_message="No annotated variant mappings available for this score set", | ||
| ) | ||
|
|
||
| try: | ||
| raw_metadata = get_raw_scoreset_metadata(urn) | ||
| preferred_layers = { | ||
| _set_scoreset_layer(urn, vrs_results), | ||
| } | ||
|
|
||
| reference_sequences = { | ||
| layer: { | ||
| "computed_reference_sequence": None, | ||
| "mapped_reference_sequence": None, | ||
| } | ||
| for layer in AnnotationLayer | ||
| } | ||
|
|
||
| for layer in preferred_layers: | ||
| reference_sequences[layer][ | ||
| "computed_reference_sequence" | ||
| ] = _get_computed_reference_sequence(urn, layer, transcript) | ||
| reference_sequences[layer][ | ||
| "mapped_reference_sequence" | ||
| ] = _get_mapped_reference_sequence(layer, transcript, alignment_result) | ||
|
|
||
| mapped_scores: list[ScoreAnnotation] = [] | ||
| for m in vrs_results: | ||
| if m.annotation_layer in preferred_layers: | ||
| # drop annotation layer from mapping object | ||
| mapped_scores.append(ScoreAnnotation(**m.model_dump())) | ||
| except Exception as e: | ||
| return JSONResponse( | ||
| content=ScoresetMapping( | ||
| metadata=metadata, error_message=str(e).strip("'") | ||
| ).model_dump(exclude_none=True) | ||
| ) | ||
|
|
||
| return JSONResponse( | ||
| content=ScoresetMapping( | ||
| metadata=raw_metadata, | ||
| computed_protein_reference_sequence=reference_sequences[ | ||
| AnnotationLayer.PROTEIN | ||
| ]["computed_reference_sequence"], | ||
| mapped_protein_reference_sequence=reference_sequences[ | ||
| AnnotationLayer.PROTEIN | ||
| ]["mapped_reference_sequence"], | ||
| computed_genomic_reference_sequence=reference_sequences[ | ||
| AnnotationLayer.GENOMIC | ||
| ]["computed_reference_sequence"], | ||
| mapped_genomic_reference_sequence=reference_sequences[ | ||
| AnnotationLayer.GENOMIC | ||
| ]["mapped_reference_sequence"], | ||
| mapped_scores=mapped_scores, | ||
| ).model_dump(exclude_none=True) | ||
| ) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| """FastAPI server file""" | ||
| import uvicorn | ||
| from fastapi import FastAPI | ||
|
|
||
| from api.routers import map | ||
|
|
||
| app = FastAPI() | ||
|
|
||
| app.include_router(map.router) | ||
|
|
||
|
|
||
| # If the application is not already being run within a uvicorn server, start uvicorn here. | ||
| if __name__ == "__main__": | ||
| uvicorn.run(app, host="0.0.0.0", port=8000) # noqa: S104 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -205,6 +205,7 @@ def _get_best_hit(output: QueryResult, urn: str, chromosome: str | None) -> Hit: | |
| else: | ||
| if list(output): | ||
| hit_chrs = [h.id for h in output] | ||
| # TODO should this be an error rather than a warning? it seems like a problem if we can't find a hit on the expected chromosome | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. My sense is that this is fine as a warning since the chromosome isn't explicitly provided by the user, and is instead inferred via score set metadata. |
||
| _logger.warning( | ||
| "Failed to match hit chromosomes during alignment. URN: %s, expected chromosome: %s, hit chromosomes: %s", | ||
| urn, | ||
|
|
@@ -221,8 +222,8 @@ def _get_best_hit(output: QueryResult, urn: str, chromosome: str | None) -> Hit: | |
| best_score_hit = hit | ||
|
|
||
| if best_score_hit is None: | ||
| _logger.error("Couldn't get hits from %s -- check BLAT output.", urn) | ||
| raise AlignmentError | ||
| msg = f"Couldn't get BLAT hits from {urn}" | ||
| raise AlignmentError(msg) | ||
|
|
||
| return best_score_hit | ||
|
|
||
|
|
@@ -246,12 +247,8 @@ def _get_best_hsp(hit: Hit, urn: str, gene_location: GeneLocation | None) -> HSP | |
| else: | ||
| best_hsp = max(hit, key=lambda hsp: hsp.score) | ||
| if best_hsp is None: | ||
| _logger.error( | ||
| "Unable to get best HSP from hit -- this should be impossible? urn: %s, hit: %s", | ||
| urn, | ||
| hit, | ||
| ) | ||
| raise AlignmentError | ||
| msg = f"Unable to get best HSP from BLAT hit: {hit}" | ||
| raise AlignmentError(msg) | ||
| return best_hsp | ||
|
|
||
|
|
||
|
|
||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.