diff --git a/clickhouse_search/all_search_tests.py b/clickhouse_search/all_search_tests.py index 88f80e2dc6..fc11948cdc 100644 --- a/clickhouse_search/all_search_tests.py +++ b/clickhouse_search/all_search_tests.py @@ -1318,13 +1318,43 @@ def test_variant_lookup(self, mock_liftover): project_guids=['R0001_1kg'], family_guids=['F000002_2'], individual_guids=['I000006_hg00733', 'I000005_hg00732', 'I000004_hg00731'] ) - self.assert_json_logs(self.manager_user, [ + unmapped_sample_logs = [ ('Looking up variant 7-143270172-A-G with data type SNV_INDEL', None), ('Unable to map sample HG00733 in family F000002_2 to an individual for variant 7-143270172-A-G', { 'severity': 'ERROR', '@type': 'type.googleapis.com/google.devtools.clouderrorreporting.v1beta1.ReportedErrorEvent', }), - ]) + ] + self.assert_json_logs(self.manager_user, unmapped_sample_logs) + + self.login_base_user() + self.reset_logs() + expected_individuals = {'I1_F0_7-143270172-A-G': { + 'affected': 'A', + 'familyGuid': 'F0_7-143270172-A-G', + 'features': [ + {'category': 'HP:0000707', 'id': 'HP:0002011', 'label': 'Morphological abnormality of the central nervous system'}, + {'category': 'HP:0001626', 'id': 'HP:0011675', 'label': 'Arrhythmia'}, + ], + 'individualGuid': 'I1_F0_7-143270172-A-G', + 'sex': 'X0', + 'vlmContactEmail': 'test@broadinstitute.org,vlm@broadinstitute.org', + }} + no_access_missing_gt_variant = { + **GRCH37_VARIANT, + 'familyGuids': ['F0_7-143270172-A-G'], + 'genotypes': {'I1_F0_7-143270172-A-G': { + k: v for k, v in GRCH37_VARIANT['genotypes']['I000004_hg00731'].items() + if k not in {'familyGuid', 'individualGuid', 'sampleId'} + }} + } + self._assert_expected_lookup( + '7-143270172-A-G', no_access_missing_gt_variant, cache_key, cached_variants=[GRCH37_VARIANT], + genome_version='37', expected_individuals=expected_individuals, locusListsByGuid={}, skip_fields={ + 'variantFunctionalDataByGuid', 'variantNotesByGuid', 'variantTagsByGuid', + }, + ) + self.assert_json_logs(self.no_access_user, unmapped_sample_logs) def _assert_expected_lookup(self, variant_id, variant, cache_key, genome_version='38', hom_only=False, affected_only=False, project_guids=None, family_guids=None, individual_guids=None, expected_individuals=None, skip_fields=None, cached_variants=None, additional_variant=None, sample_type=None, **kwargs): url = f'{reverse(variant_lookup_handler)}?variantId={variant_id}&genomeVersion={genome_version}' diff --git a/seqr/admin.py b/seqr/admin.py index 09d595c0be..cb86f6b040 100644 --- a/seqr/admin.py +++ b/seqr/admin.py @@ -3,13 +3,14 @@ from matchmaker.models import MatchmakerSubmission, MatchmakerIncomingQuery, MatchmakerResult, MatchmakerContactNotes from seqr.models import Project, Family, Individual, Dataset, LocusList, LocusListGene, LocusListInterval, VariantNote, \ VariantTag, VariantTagType, VariantFunctionalData, SavedVariant, GeneNote, AnalysisGroup, ProjectCategory, \ - FamilyAnalysedBy, VariantSearch, VariantSearchResults, IgvSample, UserPolicy, WarningMessage, FamilyNote, DynamicAnalysisGroup + FamilyAnalysedBy, VariantSearch, VariantSearchResults, IgvSample, UserPolicy, WarningMessage, FamilyNote, DynamicAnalysisGroup, \ + RnaSample, PhenotypePrioritization for model_class in [ Project, Family, Individual, Dataset, IgvSample, LocusList, LocusListGene, LocusListInterval, VariantNote, VariantTag, VariantTagType, VariantFunctionalData, SavedVariant, GeneNote, AnalysisGroup, ProjectCategory, FamilyAnalysedBy, VariantSearch, VariantSearchResults, MatchmakerSubmission, MatchmakerIncomingQuery, MatchmakerResult, - MatchmakerContactNotes, FamilyNote, DynamicAnalysisGroup, + MatchmakerContactNotes, FamilyNote, DynamicAnalysisGroup, RnaSample, PhenotypePrioritization, ]: @admin.register(model_class) diff --git a/seqr/views/apis/variant_search_api.py b/seqr/views/apis/variant_search_api.py index 61f1748532..85875748b6 100644 --- a/seqr/views/apis/variant_search_api.py +++ b/seqr/views/apis/variant_search_api.py @@ -666,7 +666,14 @@ def _update_lookup_variant(variant, response, individual_guid_map, user): variant['liftedFamilyGuids'][variant['liftedFamilyGuids'].index(unmapped_family_guid)] = family_guid individual_guid_map = {} for j, genotype in enumerate(genotypes): - unmapped_individual_guid, individual = individual_summary_map[(genotype.pop('familyGuid'), genotype.pop('sampleId'))] + individual_key = (genotype.pop('familyGuid'), genotype.pop('sampleId')) + if individual_key not in individual_summary_map: + logger.error( + f'Unable to map sample {individual_key[1]} in family {individual_key[0]} to an individual for variant {variant["variantId"]}', + user, + ) + continue + unmapped_individual_guid, individual = individual_summary_map[individual_key] if unmapped_individual_guid in individual_guid_map: individual_guid = individual_guid_map[unmapped_individual_guid] variant['genotypes'][individual_guid] = [variant['genotypes'][individual_guid], genotype] diff --git a/ui/pages/Project/fixtures.js b/ui/pages/Project/fixtures.js index 6689bcb1e0..8829d75078 100644 --- a/ui/pages/Project/fixtures.js +++ b/ui/pages/Project/fixtures.js @@ -66,7 +66,6 @@ export const STATE1 = { label: 'Skeletal dysplasia', }, ], - sampleGuids: [], sex: 'F', }, I021475_na19675: { @@ -101,7 +100,6 @@ export const STATE1 = { gene: 'LGMD panel', }, ], - sampleGuids: [], sex: 'M', }, I021476_na19678: { @@ -117,7 +115,6 @@ export const STATE1 = { maternalId: '', paternalId: '', death_year: 2008, - sampleGuids: [], sex: 'M', }, }, @@ -211,7 +208,6 @@ export const STATE_WITH_2_FAMILIES = { caseReviewStatusLastModifiedBy: null, caseReviewStatusLastModifiedDate: '2016-12-05T10:28:00.000Z', createdDate: '2016-12-05T10:28:00.000Z', - sampleGuids: [], sex: 'F', }, I021475_na19675_1: { @@ -223,7 +219,6 @@ export const STATE_WITH_2_FAMILIES = { caseReviewStatusLastModifiedBy: null, caseReviewStatusLastModifiedDate: '2016-12-05T10:29:00.000Z', createdDate: '2016-12-05T10:29:00.000Z', - sampleGuids: [], sex: 'M', birthYear: 2010, deathYear: 0, @@ -267,7 +262,6 @@ export const STATE_WITH_2_FAMILIES = { caseReviewStatusLastModifiedBy: null, caseReviewStatusLastModifiedDate: '2016-12-05T10:30:00.000Z', createdDate: '2016-12-05T10:30:00.000Z', - sampleGuids: [], sex: 'M', }, I021476_na19678_2: { @@ -281,7 +275,6 @@ export const STATE_WITH_2_FAMILIES = { caseReviewStatusLastModifiedBy: null, caseReviewStatusLastModifiedDate: '2016-12-06T10:28:00.000Z', createdDate: '2016-12-06T10:28:00.000Z', - sampleGuids: ['S2310656_wal_mc16200_mc16203'], igvSampleGuids: ['IS2310656_wal_mc16200_mc16203'], sex: 'F', }, @@ -294,7 +287,6 @@ export const STATE_WITH_2_FAMILIES = { caseReviewStatusLastModifiedBy: null, caseReviewStatusLastModifiedDate: '2016-12-06T10:29:00.000Z', createdDate: '2016-12-06T10:29:00.000Z', - sampleGuids: [], sex: 'M', }, I021474_na19679_2: { @@ -306,7 +298,6 @@ export const STATE_WITH_2_FAMILIES = { caseReviewStatusLastModifiedBy: null, caseReviewStatusLastModifiedDate: '2016-12-06T10:30:00.000Z', createdDate: '2016-12-06T10:30:00.000Z', - sampleGuids: [], sex: 'M', }, }, diff --git a/ui/pages/Search/components/filters/CustomInheritanceFilter.jsx b/ui/pages/Search/components/filters/CustomInheritanceFilter.jsx index ca61361fbe..d224b40bf1 100644 --- a/ui/pages/Search/components/filters/CustomInheritanceFilter.jsx +++ b/ui/pages/Search/components/filters/CustomInheritanceFilter.jsx @@ -5,7 +5,7 @@ import { FormSpy } from 'react-final-form' import { Table, Header, Popup, Loader, Divider } from 'semantic-ui-react' import { loadFamilyDetails } from 'redux/rootReducer' -import { getFamiliesByGuid, getIndividualsByGuid, getFamilyDetailsLoading } from 'redux/selectors' +import { getFamiliesByGuid, getIndividualsByGuid, getFamilyDetailsLoading, getActiveDatasetsByIndividual } from 'redux/selectors' import DataLoader from 'shared/components/DataLoader' import { helpLabel } from 'shared/components/form/FormHelpers' import { Select, InlineToggle } from 'shared/components/form/Inputs' @@ -19,7 +19,9 @@ const CUSTOM_FILTERS = [ { filterField: 'genotype', options: NUM_ALT_OPTIONS, placeholder: 'Allele count' }, ] -const CustomInheritanceFilterContent = React.memo(({ value, onChange, family, individualsByGuid }) => { +const CustomInheritanceFilterContent = React.memo(( + { value, onChange, family, individualsByGuid, activeDatasetsByIndividual }, +) => { const individuals = (family.individualGuids || []).map(individualGuid => individualsByGuid[individualGuid]).filter( individual => individual, ) @@ -70,7 +72,7 @@ const CustomInheritanceFilterContent = React.memo(({ value, onChange, family, in