Skip to content

Commit

Permalink
feat: add a flag for incidental findings (#1121) (#1466)
Browse files Browse the repository at this point in the history
  • Loading branch information
stolpeo authored Mar 25, 2024
1 parent 98a95c1 commit 04bd4f6
Show file tree
Hide file tree
Showing 48 changed files with 172 additions and 41 deletions.
2 changes: 2 additions & 0 deletions cases/vueapp/src/components/CaseDetail/CardAnnotations.vue
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ const svCommentsStore = useVariantCommentsStore()
const flagIds = [
'flag_bookmarked',
'flag_incidental',
'flag_candidate',
'flag_final_causative',
'flag_for_validation',
Expand All @@ -42,6 +43,7 @@ const buildComputedAnnoCountByFlag = (theList: Map<string, any>) => {
return computed<{ [flagId in FlagIds]: number }>(() => {
const result = {
flag_bookmarked: 0,
flag_incidental: 0,
flag_candidate: 0,
flag_final_causative: 0,
flag_for_validation: 0,
Expand Down
1 change: 1 addition & 0 deletions cases/vueapp/src/components/CaseDetail/FlagIcon.vue
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ const props = defineProps<{
<template>
<span>
<i-fa-solid-star v-if="flag === 'flag_bookmarked'" />
<i-mdi-dice-5 v-else-if="flag === 'flag_incidental'" />
<i-fa-solid-flask v-else-if="flag === 'flag_for_validation'" />
<i-fa-solid-heart v-else-if="flag === 'flag_candidate'" />
<i-fa-solid-flag-checkered v-else-if="flag === 'flag_final_causative'" />
Expand Down
1 change: 1 addition & 0 deletions clinvar_export/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -415,6 +415,7 @@ class Meta:
"flag_molecular",
"flag_validation",
"flag_phenotype_match",
"flag_incidental",
"flag_summary",
]
)
Expand Down
1 change: 1 addition & 0 deletions clinvar_export/tests/test_views_ajax.py
Original file line number Diff line number Diff line change
Expand Up @@ -992,6 +992,7 @@ def test_query(self):
"flag_doesnt_segregate": False,
"flag_final_causative": False,
"flag_for_validation": False,
"flag_incidental": False,
"flag_molecular": "",
"flag_no_disease_association": False,
"flag_phenotype_match": "",
Expand Down
Git LFS file not shown
1 change: 1 addition & 0 deletions maintenance/management/commands/repair_result_set.py
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,7 @@ def _handle_case(self, case): # noqa: C901
"flag_bookmarked",
"flag_segregates",
"flag_validation",
"flag_incidental",
"flag_for_validation",
"flag_final_causative",
"flag_phenotype_match",
Expand Down
18 changes: 18 additions & 0 deletions svs/migrations/0025_structuralvariantflags_flag_incidental.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Generated by Django 3.2.24 on 2024-03-22 15:02

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
("svs", "0024_clear_sv_queries"),
]

operations = [
migrations.AddField(
model_name="structuralvariantflags",
name="flag_incidental",
field=models.BooleanField(default=False),
),
]
3 changes: 3 additions & 0 deletions svs/models/user_annos.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,8 @@ class StructuralVariantFlags(HumanReadableMixin, _UserAnnotation):
flag_segregates = models.BooleanField(default=False, null=False)
#: Variant does not segregate
flag_doesnt_segregate = models.BooleanField(default=False, null=False)
#: Variant is an incidental finding
flag_incidental = models.BooleanField(default=False, null=False)

# Choice fields for gradual rating

Expand Down Expand Up @@ -155,6 +157,7 @@ def no_flags_set(self):
self.flag_no_disease_association,
self.flag_segregates,
self.flag_doesnt_segregate,
self.flag_incidental,
self.flag_molecular != "empty",
self.flag_visual != "empty",
self.flag_validation != "empty",
Expand Down
1 change: 1 addition & 0 deletions svs/serializers/user_annos.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ class Meta:
"flag_molecular",
"flag_validation",
"flag_phenotype_match",
"flag_incidental",
"flag_summary",
)
read_only_fields = ("sodar_uuid", "date_created", "date_modified", "case")
1 change: 1 addition & 0 deletions svs/tests/factories.py
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,7 @@ class Meta:
flag_no_disease_association = False
flag_segregates = False
flag_doesnt_segregate = False
flag_incidental = False

flag_molecular = "empty"
flag_visual = "empty"
Expand Down
1 change: 1 addition & 0 deletions svs/vueapp/src/stores/strucvarFlags/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ type StructuralVariantFlags = any

export const emptyFlagsTemplate = Object.freeze({
flag_bookmarked: false,
flag_incidental: false,
flag_for_validation: false,
flag_candidate: false,
flag_final_causative: false,
Expand Down
12 changes: 12 additions & 0 deletions varfish/tests/drf_spectacular/varfish_api_schema.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10872,6 +10872,8 @@ components:
type: boolean
flag_bookmarked:
type: boolean
flag_incidental:
type: boolean
flag_candidate:
type: boolean
flag_doesnt_segregate:
Expand Down Expand Up @@ -12711,6 +12713,8 @@ components:
type: boolean
flag_bookmarked:
type: boolean
flag_incidental:
type: boolean
flag_candidate:
type: boolean
flag_doesnt_segregate:
Expand Down Expand Up @@ -13287,6 +13291,8 @@ components:
maxLength: 512
flag_bookmarked:
type: boolean
flag_incidental:
type: boolean
flag_candidate:
type: boolean
flag_final_causative:
Expand Down Expand Up @@ -13476,6 +13482,8 @@ components:
$ref: '#/components/schemas/VariantRatingEnum'
flag_phenotype_match:
$ref: '#/components/schemas/VariantRatingEnum'
flag_incidental:
type: boolean
flag_summary:
$ref: '#/components/schemas/VariantRatingEnum'
PatchedTargetBedFile:
Expand Down Expand Up @@ -14361,6 +14369,8 @@ components:
maxLength: 512
flag_bookmarked:
type: boolean
flag_incidental:
type: boolean
flag_candidate:
type: boolean
flag_final_causative:
Expand Down Expand Up @@ -14940,6 +14950,8 @@ components:
$ref: '#/components/schemas/VariantRatingEnum'
flag_phenotype_match:
$ref: '#/components/schemas/VariantRatingEnum'
flag_incidental:
type: boolean
flag_summary:
$ref: '#/components/schemas/VariantRatingEnum'
required:
Expand Down
7 changes: 7 additions & 0 deletions varfish/vueapp/components.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ declare module 'vue' {
IFaSolidCode: typeof import('~icons/fa-solid/code')['default']
IFaSolidComment: typeof import('~icons/fa-solid/comment')['default']
IFaSolidDatabase: typeof import('~icons/fa-solid/database')['default']
IFaSolidDice: typeof import('~icons/fa-solid/dice')['default']
IFaSolidDice5Outline: typeof import('~icons/fa-solid/dice5-outline')['default']
IFaSolidDiceFive: typeof import('~icons/fa-solid/dice-five')['default']
IFaSolidExclamationCircle: typeof import('~icons/fa-solid/exclamation-circle')['default']
IFaSolidFlagCheckered: typeof import('~icons/fa-solid/flag-checkered')['default']
IFaSolidFlask: typeof import('~icons/fa-solid/flask')['default']
Expand Down Expand Up @@ -71,6 +74,8 @@ declare module 'vue' {
IMdiContentCopy: typeof import('~icons/mdi/content-copy')['default']
IMdiDelete: typeof import('~icons/mdi/delete')['default']
IMdiDeleteForever: typeof import('~icons/mdi/delete-forever')['default']
IMdiDice5: typeof import('~icons/mdi/dice5')['default']
IMdiDice5Outline: typeof import('~icons/mdi/dice5-outline')['default']
IMdiDoNotDisturbOn: typeof import('~icons/mdi/do-not-disturb-on')['default']
IMdiDotsHorizontal: typeof import('~icons/mdi/dots-horizontal')['default']
IMdiDownload: typeof import('~icons/mdi/download')['default']
Expand Down Expand Up @@ -99,6 +104,8 @@ declare module 'vue' {
IMdiPodium: typeof import('~icons/mdi/podium')['default']
IMdiRefresh: typeof import('~icons/mdi/refresh')['default']
IMdiSquareEditOutline: typeof import('~icons/mdi/square-edit-outline')['default']
IMdiTableColumnWidth: typeof import('~icons/mdi/table-column-width')['default']
IMdiTableMergeCells: typeof import('~icons/mdi/table-merge-cells')['default']
IMdiToggleSwitchOutline: typeof import('~icons/mdi/toggle-switch-outline')['default']
IMdiTools: typeof import('~icons/mdi/tools')['default']
IMdiUndoVariant: typeof import('~icons/mdi/undo-variant')['default']
Expand Down
3 changes: 3 additions & 0 deletions varfish/vueapp/src/varfish/components/FlagsCard/FlagsCard.vue
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ const flagsSubmitted = computed(() => {
return (
flagsToSubmit.value.flag_bookmarked ===
props.flagsStore.flags.flag_bookmarked &&
flagsToSubmit.value.flag_incidental ===
props.flagsStore.flags.flag_incidental &&
flagsToSubmit.value.flag_for_validation ===
props.flagsStore.flags.flag_for_validation &&
flagsToSubmit.value.flag_candidate ===
Expand All @@ -54,6 +56,7 @@ const flagsSubmitted = computed(() => {
const resetFlags = async () => {
if (props.flagsStore.flags) {
flagsToSubmit.value.flag_bookmarked = props.flagsStore.flags.flag_bookmarked
flagsToSubmit.value.flag_incidental = props.flagsStore.flags.flag_incidental
flagsToSubmit.value.flag_for_validation =
props.flagsStore.flags.flag_for_validation
flagsToSubmit.value.flag_candidate = props.flagsStore.flags.flag_candidate
Expand Down
6 changes: 6 additions & 0 deletions varfish/vueapp/src/varfish/components/FlagsCard/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ export interface BooleanFlagSpec {
icon: string
key:
| 'flag_bookmarked'
| 'flag_incidental'
| 'flag_for_validation'
| 'flag_candidate'
| 'flag_final_causative'
Expand All @@ -24,6 +25,11 @@ export const BOOLEAN_FLAGS: BooleanFlagSpec[] = [
icon: 'mdi-flask-empty',
key: 'flag_for_validation',
},
{
label: 'incidental finding',
icon: 'mdi-dice-5',
key: 'flag_incidental',
},
{
label: 'candidate',
icon: 'mdi-cards-heart',
Expand Down
1 change: 1 addition & 0 deletions variants/file_export.py
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@ def to_str(val):
("flag_no_disease_association", "Flag: selected for no known disease association", str),
("flag_segregates", "Flag: selected as segregating variant", str),
("flag_doesnt_segregate", "Flag: selected as not segregating variant", str),
("flag_incidental", "Flag: selected as incidental finding", str),
("flag_molecular", "Rating: variant is molecular", str),
("flag_visual", "Rating: visual inspection of alignment", str),
("flag_validation", "Rating: validation result", str),
Expand Down
12 changes: 0 additions & 12 deletions variants/migrations/0071_smallvariantflags_flag_molecular.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,6 @@

from django.db import migrations, models

from variants.models import SmallVariantComment, SmallVariantFlags


# Was in migration 0062 before. Didn't work anymore, because of the new field in SmallVariantFlags
def update_chromosome_no_in_existing_flags_and_comments(apps, schema_editor):
if not schema_editor.connection.alias == "default":
return
for o in list(SmallVariantFlags.objects.all()) + list(SmallVariantComment.objects.all()):
o.save()


class Migration(migrations.Migration):
dependencies = [
Expand All @@ -35,6 +25,4 @@ class Migration(migrations.Migration):
max_length=32,
),
),
# Was in migration 0062 before. Didn't work anymore, because of the new field in SmallVariantFlags
migrations.RunPython(update_chromosome_no_in_existing_flags_and_comments),
]
37 changes: 37 additions & 0 deletions variants/migrations/0102_auto_20240322_1502.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# Generated by Django 3.2.24 on 2024-03-22 15:02

from django.db import migrations, models

from variants.models import SmallVariantComment, SmallVariantFlags


# Was in migration 0062 before. Didn't work anymore, because of the new field in SmallVariantFlags
# Was in migration 0071 before
def update_chromosome_no_in_existing_flags_and_comments(apps, schema_editor):
if not schema_editor.connection.alias == "default":
return
for o in list(SmallVariantFlags.objects.all()) + list(SmallVariantComment.objects.all()):
o.save()


class Migration(migrations.Migration):

dependencies = [
("variants", "0101_auto_20240301_1141_not_null_sodar_field"),
]

operations = [
migrations.AddField(
model_name="flagsetcpresets",
name="flag_incidental",
field=models.BooleanField(default=True),
),
migrations.AddField(
model_name="smallvariantflags",
name="flag_incidental",
field=models.BooleanField(default=False),
),
# Was in migration 0062 before. Didn't work anymore, because of the new field in SmallVariantFlags
# Was in migration 0071 before
migrations.RunPython(update_chromosome_no_in_existing_flags_and_comments),
]
1 change: 1 addition & 0 deletions variants/models/presets.py
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,7 @@ class FlagsEtcPresets(PresetBase):
clinvar_include_pathogenic = models.BooleanField(null=False, default=True)
clinvar_include_uncertain_significance = models.BooleanField(null=False, default=True)
flag_bookmarked = models.BooleanField(null=False, default=True)
flag_incidental = models.BooleanField(null=False, default=True)
flag_candidate = models.BooleanField(null=False, default=True)
flag_doesnt_segregate = models.BooleanField(null=False, default=True)
flag_final_causative = models.BooleanField(null=False, default=True)
Expand Down
3 changes: 3 additions & 0 deletions variants/models/userannos.py
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,8 @@ class SmallVariantFlags(GetGeneSymbolsMixin, HumanReadableMixin, models.Model):

#: Bookmarked: saved for later
flag_bookmarked = models.BooleanField(default=False, null=False)
#: Incidental finding
flag_incidental = models.BooleanField(default=False, null=False)
#: Candidate variant
flag_candidate = models.BooleanField(default=False, null=False)
#: Finally selected causative variant
Expand Down Expand Up @@ -261,6 +263,7 @@ def no_flags_set(self):
return not any(
(
self.flag_bookmarked,
self.flag_incidental,
self.flag_candidate,
self.flag_final_causative,
self.flag_for_validation,
Expand Down
2 changes: 2 additions & 0 deletions variants/queries.py
Original file line number Diff line number Diff line change
Expand Up @@ -1210,6 +1210,7 @@ def __init__(self, *args, **kwargs):
[
func.count(SmallVariantFlags.sa.id).label("flag_count"),
func.bool_or(SmallVariantFlags.sa.flag_bookmarked).label("flag_bookmarked"),
func.bool_or(SmallVariantFlags.sa.flag_incidental).label("flag_incidental"),
func.bool_or(SmallVariantFlags.sa.flag_candidate).label("flag_candidate"),
func.bool_or(SmallVariantFlags.sa.flag_segregates).label("flag_segregates"),
func.bool_or(SmallVariantFlags.sa.flag_doesnt_segregate).label(
Expand Down Expand Up @@ -1256,6 +1257,7 @@ def extend_fields(self, _query_parts):
return [
self.subquery.c.flag_count,
self.subquery.c.flag_bookmarked,
self.subquery.c.flag_incidental,
self.subquery.c.flag_candidate,
self.subquery.c.flag_segregates,
self.subquery.c.flag_doesnt_segregate,
Expand Down
3 changes: 3 additions & 0 deletions variants/query_presets.py
Original file line number Diff line number Diff line change
Expand Up @@ -914,6 +914,7 @@ class _FlagsEtcPresets:
"clinvar_include_pathogenic": True,
"clinvar_include_uncertain_significance": False,
"flag_bookmarked": True,
"flag_incidental": True,
"flag_candidate": True,
"flag_doesnt_segregate": True,
"flag_final_causative": True,
Expand Down Expand Up @@ -949,6 +950,7 @@ class _FlagsEtcPresets:
#: Presets for the "Clinvar only" flags etc. settings
clinvar_only: typing.Dict[str, typing.Any] = {
"flag_bookmarked": True,
"flag_incidental": True,
"flag_candidate": True,
"flag_doesnt_segregate": True,
"flag_final_causative": True,
Expand Down Expand Up @@ -989,6 +991,7 @@ class _FlagsEtcPresets:
"clinvar_include_pathogenic": True,
"clinvar_include_uncertain_significance": False,
"flag_bookmarked": True,
"flag_incidental": True,
"flag_candidate": True,
"flag_doesnt_segregate": True,
"flag_final_causative": True,
Expand Down
2 changes: 2 additions & 0 deletions variants/query_schemas.py
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,7 @@ class CaseQueryV1:

flag_simple_empty: bool = True
flag_bookmarked: bool = True
flag_incidental: bool = True
flag_candidate: bool = True
flag_doesnt_segregate: bool = True
flag_final_causative: bool = True
Expand Down Expand Up @@ -343,6 +344,7 @@ def convert(self, case: Case, query: CaseQueryV1) -> typing.Dict[str, typing.Any
"clinvar_include_pathogenic": query.clinvar_include_pathogenic,
"flag_simple_empty": query.flag_simple_empty,
"flag_bookmarked": query.flag_bookmarked,
"flag_incidental": query.flag_incidental,
"flag_candidate": query.flag_candidate,
"flag_doesnt_segregate": query.flag_doesnt_segregate,
"flag_final_causative": query.flag_final_causative,
Expand Down
Loading

0 comments on commit 04bd4f6

Please sign in to comment.