diff --git a/backend/app/main.py b/backend/app/main.py index 7a6824e2..fefc7a49 100644 --- a/backend/app/main.py +++ b/backend/app/main.py @@ -10,7 +10,7 @@ from fastapi.staticfiles import StaticFiles from starlette.background import BackgroundTask from starlette.requests import Request -from starlette.responses import FileResponse, RedirectResponse, Response, StreamingResponse +from starlette.responses import FileResponse, JSONResponse, Response, StreamingResponse # Load environment env = os.environ @@ -34,7 +34,38 @@ if os.path.exists(VERSION_FILE): # pragma: no cover with open(VERSION_FILE) as f: REEV_VERSION = f.read().strip() or None - +#: Template for ACMG rating +ACMG_RATING: dict = { + "pvs1": False, + "ps1": False, + "ps2": False, + "ps3": False, + "ps4": False, + "pm1": False, + "pm2": False, + "pm3": False, + "pm4": False, + "pm5": False, + "pm6": False, + "pp1": False, + "pp2": False, + "pp3": False, + "pp4": False, + "pp5": False, + "ba1": False, + "bs1": False, + "bs2": False, + "bs3": False, + "bs4": False, + "bp1": False, + "bp2": False, + "bp3": False, + "bp4": False, + "bp5": False, + "bp6": False, + "bp7": False, + "class_override": None, +} app = FastAPI() @@ -125,6 +156,17 @@ async def variantvalidator(request: Request, path: str): ) +# Register app for retrieving ACMG classification. +@app.get("/acmg/{path:path}") +async def acmg(request: Request, path: str): + """Implement searching for ACMG classification.""" + query_params = request.query_params + print(query_params) + acmg_rating = ACMG_RATING.copy() + acmg_rating["class_override"] = query_params.get("class_override", None) + return JSONResponse(acmg_rating) + + # Register route for favicon. @app.get("/favicon.ico") async def favicon(): diff --git a/frontend/src/components/VariantDetails/AcmgRating.vue b/frontend/src/components/VariantDetails/AcmgRating.vue index 502fb58e..7332d56c 100644 --- a/frontend/src/components/VariantDetails/AcmgRating.vue +++ b/frontend/src/components/VariantDetails/AcmgRating.vue @@ -2,48 +2,45 @@ import { computed, onMounted, ref, watch } from 'vue' import isEqual from 'lodash.isequal' -import { copy } from '@/api/utils' import { StoreState } from '@/stores/misc' import { useVariantAcmgRatingStore } from '@/stores/variantAcmgRating' -import { useVariantInfoStore } from '@/stores/variantInfo' const props = defineProps({ smallVariant: Object }) const acmgRatingStore = useVariantAcmgRatingStore() -const variantInfoStore = useVariantInfoStore() const emptyAcmgRatingTemplate: any = { - pvs1: 0, - ps1: 0, - ps2: 0, - ps3: 0, - ps4: 0, - pm1: 0, - pm2: 0, - pm3: 0, - pm4: 0, - pm5: 0, - pm6: 0, - pp1: 0, - pp2: 0, - pp3: 0, - pp4: 0, - pp5: 0, - ba1: 0, - bs1: 0, - bs2: 0, - bs3: 0, - bs4: 0, - bp1: 0, - bp2: 0, - bp3: 0, - bp4: 0, - bp5: 0, - bp6: 0, - bp7: 0, - class_auto: 3, + pvs1: false, + ps1: false, + ps2: false, + ps3: false, + ps4: false, + pm1: false, + pm2: false, + pm3: false, + pm4: false, + pm5: false, + pm6: false, + pp1: false, + pp2: false, + pp3: false, + pp4: false, + pp5: false, + ba1: false, + bs1: false, + bs2: false, + bs3: false, + bs4: false, + bp1: false, + bp2: false, + bp3: false, + bp4: false, + bp5: false, + bp6: false, + bp7: false, + // class_auto: 3, class_override: null } @@ -84,50 +81,13 @@ const resetAcmgRating = () => { acmgRatingToSubmit.value.bp5 = acmgRatingStore.acmgRating.bp5 acmgRatingToSubmit.value.bp6 = acmgRatingStore.acmgRating.bp6 acmgRatingToSubmit.value.bp7 = acmgRatingStore.acmgRating.bp7 - acmgRatingToSubmit.value.class_auto = acmgRatingStore.acmgRating.class_auto + // acmgRatingToSubmit.value.class_auto = acmgRatingStore.acmgRating.class_auto acmgRatingToSubmit.value.class_override = acmgRatingStore.acmgRating.class_override } else { unsetAcmgRating() } } -const acmgRatingSubmitted = computed(() => { - if (!acmgRatingStore.acmgRating) { - return false - } - return ( - acmgRatingToSubmit.value.pvs1 === acmgRatingStore.acmgRating.pvs1 && - acmgRatingToSubmit.value.ps1 === acmgRatingStore.acmgRating.ps1 && - acmgRatingToSubmit.value.ps2 === acmgRatingStore.acmgRating.ps2 && - acmgRatingToSubmit.value.ps3 === acmgRatingStore.acmgRating.ps3 && - acmgRatingToSubmit.value.ps4 === acmgRatingStore.acmgRating.ps4 && - acmgRatingToSubmit.value.pm1 === acmgRatingStore.acmgRating.pm1 && - acmgRatingToSubmit.value.pm2 === acmgRatingStore.acmgRating.pm2 && - acmgRatingToSubmit.value.pm3 === acmgRatingStore.acmgRating.pm3 && - acmgRatingToSubmit.value.pm4 === acmgRatingStore.acmgRating.pm4 && - acmgRatingToSubmit.value.pm5 === acmgRatingStore.acmgRating.pm5 && - acmgRatingToSubmit.value.pm6 === acmgRatingStore.acmgRating.pm6 && - acmgRatingToSubmit.value.pp1 === acmgRatingStore.acmgRating.pp1 && - acmgRatingToSubmit.value.pp2 === acmgRatingStore.acmgRating.pp2 && - acmgRatingToSubmit.value.pp3 === acmgRatingStore.acmgRating.pp3 && - acmgRatingToSubmit.value.pp4 === acmgRatingStore.acmgRating.pp4 && - acmgRatingToSubmit.value.pp5 === acmgRatingStore.acmgRating.pp5 && - acmgRatingToSubmit.value.ba1 === acmgRatingStore.acmgRating.ba1 && - acmgRatingToSubmit.value.bs1 === acmgRatingStore.acmgRating.bs1 && - acmgRatingToSubmit.value.bs2 === acmgRatingStore.acmgRating.bs2 && - acmgRatingToSubmit.value.bs3 === acmgRatingStore.acmgRating.bs3 && - acmgRatingToSubmit.value.bs4 === acmgRatingStore.acmgRating.bs4 && - acmgRatingToSubmit.value.bp1 === acmgRatingStore.acmgRating.bp1 && - acmgRatingToSubmit.value.bp2 === acmgRatingStore.acmgRating.bp2 && - acmgRatingToSubmit.value.bp3 === acmgRatingStore.acmgRating.bp3 && - acmgRatingToSubmit.value.bp4 === acmgRatingStore.acmgRating.bp4 && - acmgRatingToSubmit.value.bp5 === acmgRatingStore.acmgRating.bp5 && - acmgRatingToSubmit.value.bp6 === acmgRatingStore.acmgRating.bp6 && - acmgRatingToSubmit.value.bp7 === acmgRatingStore.acmgRating.bp7 && - acmgRatingToSubmit.value.class_override === acmgRatingStore.acmgRating.class_override - ) -}) - const updateAcmgClass = (acmgClass: number, isConflicting: boolean) => { acmgRatingToSubmit.value.class_auto = acmgClass acmgRatingConflicting.value = isConflicting @@ -210,19 +170,12 @@ const convertEmptyToNull = (classOverride: any) => { } const onSubmitAcmgRating = async () => { - const acmgRatingToSubmitEmpty = isEqual(acmgRatingToSubmit, emptyAcmgRatingTemplate) - if (acmgRatingStore.acmgRating && acmgRatingToSubmitEmpty) { - // IS not empty but SHOULD be empty, so delete the ACMG rating - await acmgRatingStore.deleteAcmgRating() - } else if (!acmgRatingStore.acmgRating && acmgRatingToSubmitEmpty) { + if (isEqual(acmgRatingToSubmit, emptyAcmgRatingTemplate)) { // IS empty and SHOULD be empty, so no update needed - acmgRatingToSubmit.value = copy(emptyAcmgRatingTemplate) - } else if (acmgRatingStore.acmgRating && !acmgRatingToSubmitEmpty) { - // IS not empty and SHOULD not be empty, so update the ACMG rating - await acmgRatingStore.updateAcmgRating(acmgRatingToSubmit.value) - } else if (!acmgRatingStore.acmgRating && !acmgRatingToSubmitEmpty) { - // IS empty but SHOULD not be empty, so create the ACMG rating - await acmgRatingStore.createAcmgRating(variantInfoStore.smallVariant, acmgRatingToSubmit.value) + return + } else { + // Submit ACMG rating to ClinVar + await acmgRatingStore.submitAcmgRating(props.smallVariant, acmgRatingToSubmit.value) } } @@ -478,11 +431,10 @@ const acmgCriteriaInfo = {