From a55b6322761379f7219738d38293b973e554e0a5 Mon Sep 17 00:00:00 2001 From: Jennifer Jou Date: Mon, 23 Sep 2024 12:32:44 -0700 Subject: [PATCH 1/3] Adjust NIC audit for multiplexed samples --- src/igvfd/audit/measurement_set.py | 25 +++++++++++++++--- src/igvfd/tests/test_audit_measurement_set.py | 26 +++++++++++++++++++ src/igvfd/types/sample.py | 18 +++++++++++++ 3 files changed, 66 insertions(+), 3 deletions(-) diff --git a/src/igvfd/audit/measurement_set.py b/src/igvfd/audit/measurement_set.py index d727818c0..cd25a5d5d 100644 --- a/src/igvfd/audit/measurement_set.py +++ b/src/igvfd/audit/measurement_set.py @@ -224,19 +224,38 @@ def audit_missing_institutional_certification(value, system): award = value.get('award', '') samples = value.get('samples', []) + non_multiplexed_samples_to_check = [] + multiplexed_samples_to_check = [] + sample_objects_to_check = [] for sample in samples: sample_object = system.get('request').embed(sample, '@@object') + if 'MultiplexedSample' in sample_object['@type']: + multiplexed_sample_id = sample_object['@id'] + multiplexed_phrase = f' that is multiplexed in {audit_link(path_to_text(multiplexed_sample_id), multiplexed_sample_id)}' + for mux_sample in sample_object['multiplexed_samples']: + mux_sample_object = system.get('request').embed(mux_sample, '@@object') + # multiplexed_samples_to_check.append(mux_sample_object) + sample_objects_to_check.append((mux_sample_object, multiplexed_phrase)) + else: + sample_objects_to_check.append((sample_object, '')) + # sample_objects_to_check = non_multiplexed_samples_to_check + # multiplexed_phrase = '' + + for sample_tuple in sample_objects_to_check: + sample = sample_tuple[0] + multiplexed_phrase = sample_tuple[1] nic_labs = [] nic_awards = [] - for nic in sample_object.get('institutional_certificates', []): + for nic in sample.get('institutional_certificates', []): nic_object = system.get('request').embed(nic, '@@object?skip_calculated=true') nic_labs.append(nic_object.get('lab', '')) nic_awards.append(nic_object.get('award', '')) if lab not in nic_labs or award not in nic_awards: detail = ( f'Measurement set {audit_link(path_to_text(value["@id"]), value["@id"])} has ' - f'a sample {audit_link(path_to_text(sample), sample)} that lacks any `institutional_certificates` ' - f'issued to the lab that submitted this file set.' + f'a sample {audit_link(path_to_text(sample["@id"]), sample["@id"])}{multiplexed_phrase} ' + f'that lacks any `institutional_certificates` issued to the lab ' + f'that submitted this file set.' ) yield AuditFailure(audit_message.get('audit_category', ''), f'{detail} {audit_message.get("audit_description", "")}', level=audit_message.get('audit_level', '')) diff --git a/src/igvfd/tests/test_audit_measurement_set.py b/src/igvfd/tests/test_audit_measurement_set.py index e07cba8fc..b11d4c6d4 100644 --- a/src/igvfd/tests/test_audit_measurement_set.py +++ b/src/igvfd/tests/test_audit_measurement_set.py @@ -278,6 +278,7 @@ def test_audit_missing_institutional_certification( assay_term_mpra, other_lab, tissue, + multiplexed_sample, human_donor, assay_term_chip, institutional_certificate, @@ -344,7 +345,32 @@ def test_audit_missing_institutional_certification( for error in res.json['audit'].get('NOT_COMPLIANT', []) ) + # If the Measurement Set studies a Multiplexed Sample, + # its input samples are checked for their NIC. + testapp.patch_json( + measurement_set['@id'], + { + 'samples': [multiplexed_sample['@id']] + } + ) + res = testapp.get(measurement_set['@id'] + '@@audit') + print(res) + assert any( + error['category'] == 'missing NIH certification' + for error in res.json['audit'].get('NOT_COMPLIANT', []) + ) + assert any( + f'multiplexed in [{multiplexed_sample["accession"]}]' in error['detail'] + for error in res.json['audit'].get('NOT_COMPLIANT', []) + ) + # No flag if the NIC's lab and award match the Measurement Set. + testapp.patch_json( + measurement_set['@id'], + { + 'samples': [tissue['@id']] + } + ) testapp.patch_json( institutional_certificate['@id'], { diff --git a/src/igvfd/types/sample.py b/src/igvfd/types/sample.py index e692525fa..e7b5b5829 100644 --- a/src/igvfd/types/sample.py +++ b/src/igvfd/types/sample.py @@ -972,6 +972,24 @@ def sources(self, request, multiplexed_samples): def construct_library_sets(self, request, multiplexed_samples): return collect_multiplexed_samples_prop(request, multiplexed_samples, 'construct_library_sets') + @calculated_property( + schema={ + 'title': 'Institutional Certificates', + 'type': 'array', + 'description': 'The institutional certificates of the samples included in this multiplexed sample.', + 'minItems': 1, + 'uniqueItems': True, + 'notSubmittable': True, + 'items': { + 'title': 'Institutional Certificate', + 'type': 'string', + 'linkTo': 'InstitutionalCertificate' + } + } + ) + def institutional_certificates(self, request, multiplexed_samples): + return collect_multiplexed_samples_prop(request, multiplexed_samples, 'institutional_certificates') + @calculated_property( schema={ 'title': 'Classifications', From f72076acca4c5854cacf7a7d62ea423a89ba6376 Mon Sep 17 00:00:00 2001 From: Jennifer Jou Date: Mon, 23 Sep 2024 12:33:39 -0700 Subject: [PATCH 2/3] Delete unused code --- src/igvfd/audit/measurement_set.py | 5 ----- src/igvfd/tests/test_audit_measurement_set.py | 1 - 2 files changed, 6 deletions(-) diff --git a/src/igvfd/audit/measurement_set.py b/src/igvfd/audit/measurement_set.py index cd25a5d5d..229248719 100644 --- a/src/igvfd/audit/measurement_set.py +++ b/src/igvfd/audit/measurement_set.py @@ -224,8 +224,6 @@ def audit_missing_institutional_certification(value, system): award = value.get('award', '') samples = value.get('samples', []) - non_multiplexed_samples_to_check = [] - multiplexed_samples_to_check = [] sample_objects_to_check = [] for sample in samples: sample_object = system.get('request').embed(sample, '@@object') @@ -234,12 +232,9 @@ def audit_missing_institutional_certification(value, system): multiplexed_phrase = f' that is multiplexed in {audit_link(path_to_text(multiplexed_sample_id), multiplexed_sample_id)}' for mux_sample in sample_object['multiplexed_samples']: mux_sample_object = system.get('request').embed(mux_sample, '@@object') - # multiplexed_samples_to_check.append(mux_sample_object) sample_objects_to_check.append((mux_sample_object, multiplexed_phrase)) else: sample_objects_to_check.append((sample_object, '')) - # sample_objects_to_check = non_multiplexed_samples_to_check - # multiplexed_phrase = '' for sample_tuple in sample_objects_to_check: sample = sample_tuple[0] diff --git a/src/igvfd/tests/test_audit_measurement_set.py b/src/igvfd/tests/test_audit_measurement_set.py index b11d4c6d4..d7fa67faa 100644 --- a/src/igvfd/tests/test_audit_measurement_set.py +++ b/src/igvfd/tests/test_audit_measurement_set.py @@ -354,7 +354,6 @@ def test_audit_missing_institutional_certification( } ) res = testapp.get(measurement_set['@id'] + '@@audit') - print(res) assert any( error['category'] == 'missing NIH certification' for error in res.json['audit'].get('NOT_COMPLIANT', []) From 5f1a1a77941c9958988c7d30ec084687607e846b Mon Sep 17 00:00:00 2001 From: Jennifer Jou Date: Mon, 23 Sep 2024 14:23:45 -0700 Subject: [PATCH 3/3] Update mappings --- src/igvfd/mappings/measurement_set.json | 4 ++-- src/igvfd/mappings/multiplexed_sample.json | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/igvfd/mappings/measurement_set.json b/src/igvfd/mappings/measurement_set.json index bd31f1840..f2f9cb724 100644 --- a/src/igvfd/mappings/measurement_set.json +++ b/src/igvfd/mappings/measurement_set.json @@ -1,6 +1,6 @@ { - "hash": "352b45520f2fbb50256a2a7ce8b7ef62", - "index_name": "measurement_set_352b4552", + "hash": "860efa91714167146eaeab6130a6c665", + "index_name": "measurement_set_860efa91", "item_type": "measurement_set", "mapping": { "dynamic_templates": [ diff --git a/src/igvfd/mappings/multiplexed_sample.json b/src/igvfd/mappings/multiplexed_sample.json index c84c5ae58..a756aacc4 100644 --- a/src/igvfd/mappings/multiplexed_sample.json +++ b/src/igvfd/mappings/multiplexed_sample.json @@ -1,6 +1,6 @@ { - "hash": "fb8479a35acfd8440c65f8dea5192f00", - "index_name": "multiplexed_sample_fb8479a3", + "hash": "5a0b11c7af0b9e512e1e5cc00f0f502e", + "index_name": "multiplexed_sample_5a0b11c7", "item_type": "multiplexed_sample", "mapping": { "dynamic_templates": [