Skip to content

Commit

Permalink
feat: qc values thresholds should be adjustable (#1530) (#1644)
Browse files Browse the repository at this point in the history
  • Loading branch information
stolpeo authored May 27, 2024
1 parent 75cb2ea commit beed42c
Show file tree
Hide file tree
Showing 14 changed files with 221 additions and 23 deletions.
4 changes: 4 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -116,3 +116,7 @@ format-isort:
.PHONY: format-black
format-black:
black --line-length 100 --exclude '/(\.eggs|\.git|\.hg|\.mypy_cache|\.nox|\.tox|\.?v?env|_build|buck-out|build|dist|src|node_modules)/' .

.PHONY: gen-api-schema
gen-api-schema:
$(MANAGE) spectacular > ./varfish/tests/drf_spectacular/varfish_api_schema.yaml
8 changes: 8 additions & 0 deletions cases/vueapp/src/api/caseClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -217,4 +217,12 @@ export class CaseClient extends ClientBase {
'DELETE',
)
}

/** Retrieve project settings. */
async retrieveProjectSettings(projectUuid: string) {
return await this.fetchHelper(
`/variants/ajax/project-settings/retrieve/${projectUuid}/`,
'GET',
)
}
}
18 changes: 10 additions & 8 deletions cases/vueapp/src/components/CaseDetail/CardVariantQc.vue
Original file line number Diff line number Diff line change
Expand Up @@ -65,21 +65,23 @@ const tsTv = (member) => {
}}
</td>
<td
v-if="tsTv(member) >= 2.0 && tsTv(member) <= 2.9"
class="text-right"
>
{{ tsTv(member) }}
</td>
<td
v-else
v-if="
tsTv(member) <
caseDetailsStore.projectSettings.ts_tv_valid_lower ||
tsTv(member) >
caseDetailsStore.projectSettings.ts_tv_valid_upper
"
class="text-right text-danger font-weight-bold"
:title="`Ts/Tv ratio should be within 2.0-2.9 but is ${tsTv(
:title="`Ts/Tv ratio should be within ${caseDetailsStore.projectSettings.ts_tv_warning_lower}-${caseDetailsStore.projectSettings.ts_tv_warning_upper} but is ${tsTv(
member,
)}`"
>
<i-bi-exclamation-circle />
{{ tsTv(member) }}
</td>
<td v-else class="text-right">
{{ tsTv(member) }}
</td>
<td class="text-right">
{{
caseDetailsStore.caseVariantStats[
Expand Down
12 changes: 10 additions & 2 deletions cases/vueapp/src/components/CaseDetail/QcTableVarStats.vue
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
<script setup>
import { displayName, formatLargeInt } from '@varfish/helpers'
import { useCaseDetailsStore } from '@cases/stores/caseDetails'
import { tsTvRatio } from '@cases/common'
const props = defineProps({
// eslint-disable-next-line vue/require-default-prop
varStats: Object,
})
const caseDetailsStore = useCaseDetailsStore()
</script>

<template>
Expand Down Expand Up @@ -37,11 +40,16 @@ const props = defineProps({
</td>
<td class="text-right">
<span
v-if="tsTvRatio(entry) < 1.0 || tsTvRatio(entry) > 2.9"
v-if="
tsTvRatio(entry) <
caseDetailsStore.projectSettings.ts_tv_valid_lower ||
tsTvRatio(entry) >
caseDetailsStore.projectSettings.ts_tv_valid_upper
"
class="text-danger"
>
<i-bi-exclamation-circle
:title="`On-target Ts/Tv ratio should be between 2.0 and 2.9 but was ${tsTvRatio(
:title="`On-target Ts/Tv ratio should be between ${caseDetailsStore.projectSettings.ts_tv_warning_lower} and ${caseDetailsStore.projectSettings.ts_tv_warning_upper} but was ${tsTvRatio(
entry,
)}.`"
/>
Expand Down
9 changes: 9 additions & 0 deletions cases/vueapp/src/stores/caseDetails.ts
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,11 @@ export const useCaseDetailsStore = defineStore('caseDetails', () => {

const projectDefaultPresetSet = ref<any | null>(null)

const projectSettings = ref<any>({
ts_tv_valid_lower: 2.0,
ts_tv_valid_upper: 2.9,
})

/** Promise for initialization of the store. */
const initializeRes = ref<Promise<any> | null>(null)

Expand Down Expand Up @@ -235,6 +240,9 @@ export const useCaseDetailsStore = defineStore('caseDetails', () => {
.then((res) => {
projectDefaultPresetSet.value = res
}),
caseClient.retrieveProjectSettings(projectUuid.value).then((res) => {
projectSettings.value = res
}),
])
.then(() => {
storeState.serverInteractions -= 1
Expand Down Expand Up @@ -460,6 +468,7 @@ export const useCaseDetailsStore = defineStore('caseDetails', () => {
caseSvAnnotationReleaseInfos,
genotypeMapping,
projectDefaultPresetSet,
projectSettings,
// functions
initialize,
updateCase,
Expand Down
4 changes: 2 additions & 2 deletions cases/vueapp/tests/data/caseDetailsStoreData.json
Git LFS file not shown
19 changes: 8 additions & 11 deletions cases/vueapp/tests/unit/cases/CaseDetail/QcTableVarStats.spec.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,8 @@
import QcTableVarStats from '@cases/components/CaseDetail/QcTableVarStats.vue'
import { mount } from '@vue/test-utils'
import { beforeAll, describe, expect, test, vi } from 'vitest'

import caseDetailsStoreData from '../../../data/caseDetailsStoreData.json'

const makeWrapper = (varStats) => {
return mount(QcTableVarStats, {
props: {
varStats: varStats,
},
})
}
import { makeWrapper } from '../CaseDetailApp.common'

describe('QcTableVarStats.vue', () => {
beforeAll(() => {
Expand All @@ -19,13 +11,15 @@ describe('QcTableVarStats.vue', () => {
})

test('test with null data', async () => {
const wrapper = makeWrapper(null)
const wrapper = makeWrapper(QcTableVarStats)

expect(wrapper.findAll('table').length).toBe(1)
expect(wrapper.html()).toMatch(/No variant statistics to display./)
})

// TODO Fix me
test('test with data data', async () => {
// console.log(caseDetailsStoreData.caseVariantStats)
const varStats = Object.entries(caseDetailsStoreData.caseVariantStats).map(
([name, stats]) => {
return {
Expand All @@ -34,7 +28,10 @@ describe('QcTableVarStats.vue', () => {
}
},
)
const wrapper = makeWrapper(varStats)

const wrapper = makeWrapper(QcTableVarStats, caseDetailsStoreData, {
varStats: varStats,
})

expect(wrapper.findAll('table').length).toBe(1)
expect(wrapper.html()).toMatch(/<td>NA12878<\/td>/)
Expand Down
79 changes: 79 additions & 0 deletions varfish/tests/drf_spectacular/varfish_api_schema.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5870,6 +5870,38 @@ paths:
schema:
$ref: '#/components/schemas/PresetSet'
description: ''
/variants/ajax/project-settings/retrieve/{project}/:
get:
operationId: variants_ajax_project_settings_retrieve_retrieve
description: |-
A view that returns project settings for the given project.
**URL:** ``/variants/ajax/project-settings/retrieve/{project.uuid}``
**Methods:** ``GET``
**Returns:** {
ts_tv_warning_upper,
ts_tv_warning_lower
}
parameters:
- in: path
name: project
schema:
type: string
pattern: ^[0-9a-f-]+$
required: true
tags:
- variants
security:
- cookieAuth: []
responses:
'200':
content:
application/vnd.bihealth.varfish+json:
schema:
$ref: '#/components/schemas/ProjectSettings'
description: ''
/variants/ajax/project/qc/{project}/:
get:
operationId: variants_ajax_project_qc_retrieve
Expand Down Expand Up @@ -7660,6 +7692,40 @@ paths:
items:
$ref: '#/components/schemas/HpoTerm'
description: ''
/variants/api/project-settings/retrieve/{project}/:
get:
operationId: variants_api_project_settings_retrieve_retrieve
description: |-
A view that returns project settings for the given project.
**URL:** ``/variants/api/project-settings/retrieve/{project.uuid}``
**Methods:** ``GET``
**Returns:** {
ts_tv_warning_upper,
ts_tv_warning_lower
}
parameters:
- in: path
name: project
schema:
type: string
pattern: ^[0-9a-f-]+$
required: true
tags:
- variants
security:
- basicAuth: []
- cookieAuth: []
- knoxApiToken: []
responses:
'200':
content:
application/vnd.bihealth.varfish+json:
schema:
$ref: '#/components/schemas/ProjectSettings'
description: ''
/variants/api/project/qc/{project}/:
get:
operationId: variants_api_project_qc_retrieve
Expand Down Expand Up @@ -13258,6 +13324,19 @@ components:
- qualitypresets_set
- quickpresets_set
- sodar_uuid
ProjectSettings:
type: object
description: Serializer for project settings.
properties:
ts_tv_valid_upper:
type: number
format: double
ts_tv_valid_lower:
type: number
format: double
required:
- ts_tv_valid_lower
- ts_tv_valid_upper
QualityPresets:
type: object
description: Serializer for ``QualityPresets``.
Expand Down
1 change: 1 addition & 0 deletions varfish/vueapp/components.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ declare module 'vue' {
IMdiPlusCircle: typeof import('~icons/mdi/plus-circle')['default']
IMdiPodium: typeof import('~icons/mdi/podium')['default']
IMdiRefresh: typeof import('~icons/mdi/refresh')['default']
IMdiSettings: typeof import('~icons/mdi/settings')['default']
IMdiSquareEditOutline: typeof import('~icons/mdi/square-edit-outline')['default']
IMdiStar: typeof import('~icons/mdi/star')['default']
IMdiTableColumnWidth: typeof import('~icons/mdi/table-column-width')['default']
Expand Down
10 changes: 10 additions & 0 deletions variants/plugins.py
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,16 @@ class ProjectAppPlugin(ProjectAppPluginPoint):
"database (such as no variant of a case showing up because being in the in-house database many times)."
),
},
"ts_tv_valid_range": {
"scope": SODAR_CONSTANTS["APP_SETTING_SCOPE_PROJECT"],
"type": "STRING",
"default": "2.0-2.9",
"label": "Ts/Tv valid range",
"description": (
"Variants with a Ts/Tv ratio outside this range will be highlighted as a warning. "
"The recommended value is <code>2.0-2.9</code>"
),
},
}

#: Additional columns to display for the projects.
Expand Down
15 changes: 15 additions & 0 deletions variants/serializers/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -779,3 +779,18 @@ class CaseListQcStatsSerializer(serializers.Serializer):
dpQuantiles = serializers.JSONField()
hetRatioQuantiles = serializers.JSONField()
dpHetData = serializers.JSONField()


@attrs.define
class ProjectSettings:
"""Helper class that contains the results of the settings shortcuts"""

ts_tv_valid_upper: float
ts_tv_valid_lower: float


class ProjectSettingsSerializer(serializers.Serializer):
"""Serializer for project settings."""

ts_tv_valid_upper = serializers.FloatField()
ts_tv_valid_lower = serializers.FloatField()
10 changes: 10 additions & 0 deletions variants/urls/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,11 @@
view=views_ajax.HpoTermsAjaxView.as_view(),
name="ajax-hpo-terms",
),
url(
regex=r"^ajax/project-settings/retrieve/(?P<project>[0-9a-f-]+)/?$",
view=views_ajax.ProjectSettingsRetrieveAjaxView.as_view(),
name="ajax-project-settings-retrieve",
),
]

api_urlpatterns = [
Expand Down Expand Up @@ -457,6 +462,11 @@
name="api-extra-anno-fields",
),
url(regex=r"^api/hpo-terms/?$", view=views_api.HpoTermsApiView.as_view(), name="api-hpo-terms"),
url(
regex=r"^api/project-settings/retrieve/(?P<project>[0-9a-f-]+)/?$",
view=views_api.ProjectSettingsRetrieveApiView.as_view(),
name="api-project-settings-retrieve",
),
]


Expand Down
17 changes: 17 additions & 0 deletions variants/views/ajax/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
CaseRetrieveApiView,
ExtraAnnoFieldsApiView,
HpoTermsApiView,
ProjectSettingsRetrieveApiView,
SmallVariantCommentDeleteApiView,
SmallVariantCommentListCreateApiView,
SmallVariantCommentListProjectApiView,
Expand Down Expand Up @@ -434,3 +435,19 @@ class CaseListQcStatsAjaxView(CaseListQcStatsApiView):
"""

authentication_classes = [SessionAuthentication]


class ProjectSettingsRetrieveAjaxView(ProjectSettingsRetrieveApiView):
"""A view that returns project settings for the given project.
**URL:** ``/variants/ajax/project-settings/retrieve/{project.uuid}``
**Methods:** ``GET``
**Returns:** {
ts_tv_warning_upper,
ts_tv_warning_lower
}
"""

authentication_classes = [SessionAuthentication]
Loading

0 comments on commit beed42c

Please sign in to comment.