diff --git a/seqr/views/apis/family_api.py b/seqr/views/apis/family_api.py
index 2c4ce793a0..dcae71adeb 100644
--- a/seqr/views/apis/family_api.py
+++ b/seqr/views/apis/family_api.py
@@ -23,7 +23,7 @@
from seqr.views.utils.project_context_utils import add_families_context, families_discovery_tags, add_project_tag_types, \
MME_TAG_NAME
from seqr.models import Family, FamilyAnalysedBy, Individual, FamilyNote, Sample, VariantTag, AnalysisGroup, RnaSeqTpm, \
- PhenotypePrioritization, Project
+ PhenotypePrioritization, Project, RnaSeqOutlier, RnaSeqSpliceOutlier
from seqr.views.utils.permissions_utils import check_project_permissions, get_project_and_check_pm_permissions, \
login_and_policies_required, user_is_analyst, has_case_review_permissions
from seqr.views.utils.variant_utils import get_phenotype_prioritization, get_omim_intervals_query, DISCOVERY_CATEGORY
@@ -43,10 +43,21 @@ def family_page_data(request, family_guid):
has_case_review_perm = has_case_review_permissions(project, request.user)
sample_models = Sample.objects.filter(individual__family=family)
- samples = get_json_for_samples(sample_models, project_guid=project.guid, family_guid=family_guid, skip_nested=True, is_analyst=is_analyst)
+ samples = get_json_for_samples(
+ sample_models, project_guid=project.guid, family_guid=family_guid, skip_nested=True, is_analyst=is_analyst
+ )
response = {
- 'samplesByGuid': {s['sampleGuid']: s for s in samples},
+ 'samplesByGuid': {s['sampleGuid']: s for s in samples}
+ }
+ rna_type_samples = {
+ 'TPM': set(RnaSeqTpm.objects.filter(sample__in=sample_models).values_list('sample__guid', flat=True)),
+ 'Expression Outlier': set(RnaSeqOutlier.objects.filter(sample__in=sample_models).values_list('sample__guid', flat=True)),
+ 'Splice Outlier': set(RnaSeqSpliceOutlier.objects.filter(sample__in=sample_models).values_list('sample__guid', flat=True)),
}
+ for sample in response['samplesByGuid'].values():
+ sample['rnaSeqTypes'] = [
+ rnaseq_type for rnaseq_type, sample_ids in rna_type_samples.items() if sample['sampleGuid'] in sample_ids
+ ]
add_families_context(response, families, project.guid, request.user, is_analyst, has_case_review_perm)
family_response = response['familiesByGuid'][family_guid]
@@ -77,11 +88,6 @@ def family_page_data(request, family_guid):
'postDiscoveryOmimOptions': omim_map,
})
- outlier_individual_guids = sample_models.filter(sample_type=Sample.SAMPLE_TYPE_RNA, is_active=True)\
- .exclude(rnaseqoutlier__isnull=True, rnaseqspliceoutlier__isnull=True).values_list('individual__guid', flat=True)
- for individual_guid in outlier_individual_guids:
- response['individualsByGuid'][individual_guid]['hasRnaOutlierData'] = True
-
tools_by_indiv = {}
tools_agg = PhenotypePrioritization.objects.filter(individual__family=family).values('individual__guid').annotate(
phenotypePrioritizationTools=ArrayAgg(
diff --git a/seqr/views/apis/family_api_tests.py b/seqr/views/apis/family_api_tests.py
index eb22e8e85d..bd43d8d697 100644
--- a/seqr/views/apis/family_api_tests.py
+++ b/seqr/views/apis/family_api_tests.py
@@ -32,6 +32,10 @@
INDIVIDUAL_GUIDS = [INDIVIDUAL_GUID, INDIVIDUAL2_GUID, INDIVIDUAL3_GUID]
+FAMILY_API_SAMPLE_FIELDS = {*SAMPLE_FIELDS, 'rnaSeqTypes'}
+SAMPLE_GUIDS = ['S000129_na19675', 'S000130_na19678', 'S000131_na19679', 'S000151_na19675_1', 'S000152_na19675_d2', 'S000153_na19679']
+
+
class FamilyAPITest(AuthenticationTestCase):
fixtures = ['users', '1kg_project', 'reference_data']
@@ -69,8 +73,7 @@ def test_family_page_data(self):
self.assertEqual(len(response_json['individualsByGuid']), 3)
individual = response_json['individualsByGuid'][INDIVIDUAL_GUID]
- individual_fields = {'sampleGuids', 'igvSampleGuids', 'mmeSubmissionGuid', 'hasRnaOutlierData',
- 'phenotypePrioritizationTools'}
+ individual_fields = {'sampleGuids', 'igvSampleGuids', 'mmeSubmissionGuid', 'phenotypePrioritizationTools'}
individual_fields.update(INDIVIDUAL_FIELDS)
self.assertSetEqual(set(individual.keys()), individual_fields)
self.assertListEqual([
@@ -83,19 +86,19 @@ def test_family_page_data(self):
],
[response_json['individualsByGuid'][guid].get('phenotypePrioritizationTools') for guid in INDIVIDUAL_GUIDS]
)
- self.assertListEqual(
- [True, False, True],
- [response_json['individualsByGuid'][guid].get('hasRnaOutlierData', False) for guid in INDIVIDUAL_GUIDS]
- )
self.assertSetEqual({PROJECT_GUID}, {i['projectGuid'] for i in response_json['individualsByGuid'].values()})
self.assertSetEqual({FAMILY_GUID}, {i['familyGuid'] for i in response_json['individualsByGuid'].values()})
self.assertEqual(len(response_json['samplesByGuid']), 6)
- self.assertSetEqual(set(next(iter(response_json['samplesByGuid'].values())).keys()), SAMPLE_FIELDS)
+ self.assertSetEqual(set(next(iter(response_json['samplesByGuid'].values())).keys()), FAMILY_API_SAMPLE_FIELDS)
self.assertSetEqual({PROJECT_GUID}, {s['projectGuid'] for s in response_json['samplesByGuid'].values()})
self.assertSetEqual({FAMILY_GUID}, {s['familyGuid'] for s in response_json['samplesByGuid'].values()})
self.assertEqual(len(individual['sampleGuids']), 3)
self.assertTrue(set(individual['sampleGuids']).issubset(set(response_json['samplesByGuid'].keys())))
+ self.assertListEqual(
+ [[], [], [], ['TPM', 'Splice Outlier'], ['TPM', 'Expression Outlier', 'Splice Outlier'], ['Splice Outlier']],
+ [response_json['samplesByGuid'][guid].get('rnaSeqTypes', {}) for guid in SAMPLE_GUIDS]
+ )
self.assertEqual(len(response_json['igvSamplesByGuid']), 1)
self.assertSetEqual(set(next(iter(response_json['igvSamplesByGuid'].values())).keys()), IGV_SAMPLE_FIELDS)
diff --git a/ui/pages/Project/components/FamilyTable/IndividualRow.jsx b/ui/pages/Project/components/FamilyTable/IndividualRow.jsx
index 4cb355b7c1..0d9c035f82 100644
--- a/ui/pages/Project/components/FamilyTable/IndividualRow.jsx
+++ b/ui/pages/Project/components/FamilyTable/IndividualRow.jsx
@@ -169,7 +169,7 @@ const DataDetails = React.memo(({ loadedSamples, individual, mmeSubmission }) =>
/>
) :