diff --git a/lib/import/brca/providers/sheffield/sheffield_handler.rb b/lib/import/brca/providers/sheffield/sheffield_handler.rb index b316f9c6..728bc779 100644 --- a/lib/import/brca/providers/sheffield/sheffield_handler.rb +++ b/lib/import/brca/providers/sheffield/sheffield_handler.rb @@ -71,6 +71,7 @@ def get_genes_set_targeted(record) @genes_set = [] @genes_set.append(karyo_column.scan(BRCA_REGEX)) @genes_set.append(genotype_column.scan(BRCA_REGEX)) + @genes_set.flatten.uniq end def process_scope_ovarian_panel(karyo, genotype, _record) @@ -126,7 +127,11 @@ def process_scope_r207(karyo, genotype, record) @logger.debug "ADDED FULL_SCREEN TEST for: #{karyo}" genotype.add_test_scope(:full_screen) @genes_set = R207_GENE_MAPPING_FS[karyo] - elsif R207_GENE_MAPPING_TAR.include? karyo + elsif /^R207.1/ix.match(karyo) + @logger.debug "ADDED FULL_SCREEN TEST for: #{karyo}" + genotype.add_test_scope(:full_screen) + @genes_set = R207_1_FS_GENES + elsif /^R240|^R242/ix.match(karyo) @logger.debug "ADDED TARGETED TEST for: #{karyo}" genotype.add_test_scope(:targeted_mutation) get_genes_set_targeted(record) @@ -162,20 +167,24 @@ def process_scope_r208_new(karyo, genotype, record) date = DateTime.parse(record.raw_fields['authoriseddate']) @genes_set.concat(%w[RAD51C RAD51D]) if date >= DateTime.parse('01/02/2023') end - elsif R208_GENE_MAPPING_TAR_NEW.include? karyo + elsif /^R240|^R242/ix.match(karyo) || /^R370.1\s::\sConfirmation\sof\sresearch\sresult/ix.match(karyo) @logger.debug "ADDED TARGETED TEST for: #{karyo}" genotype.add_test_scope(:targeted_mutation) get_genes_set_targeted(record) else genotype.add_test_scope(:no_genetictestscope) end - @genes_set = @genes_set.uniq + @genes_set = @genes_set.flatten.uniq end - def process_scope_r430(karyo, genotype, _record) - if R430_GENE_MAPPING_FS.keys.include? karyo - @genes_set = R430_GENE_MAPPING_FS[karyo] + def process_scope_r430(karyo, genotype, record) + if /^R430/.match(karyo) || /^R420.1\s::\sNGS\sin\sLeeds\s-\sSend\sBlood/ix.match(karyo) + @genes_set = R430_FS_GENES genotype.add_test_scope(:full_screen) + elsif /^R240|^R242/ix.match(karyo) + @logger.debug "ADDED TARGETED TEST for: #{karyo}" + genotype.add_test_scope(:targeted_mutation) + get_genes_set_targeted(record) else genotype.add_test_scope(:no_genetictestscope) end @@ -217,40 +226,46 @@ def process_scope_r242(karyo, genotype, record) end def add_test_type(genotype, record) - Maybe(record.raw_fields['moleculartestingtype']).each do |type| - genotype.add_molecular_testing_type_strict(TEST_TYPE_MAPPING[type.strip]) + karyo = record.raw_fields['karyotypingmethod'].strip + moleculartestingtype = record.raw_fields['moleculartestingtype'].strip + + test_type = determine_test_type(moleculartestingtype, karyo) + genotype.add_molecular_testing_type_strict(test_type) if test_type + end + + def determine_test_type(moleculartestingtype, karyo) + # First priority: moleculartestingtype + return TEST_TYPE_MAPPING[moleculartestingtype] if TEST_TYPE_MAPPING.key?(moleculartestingtype) + return :predictive if moleculartestingtype.match?(/unaffected/i) + + # Second priority: karyo R-number patterns + test_type_from_karyo(karyo) + end + + def test_type_from_karyo(karyo) + case karyo + when /^R(240|205|206|207|208|209|210|211|430|444|216|414|370)/ + :diagnostic + when /^R242/ + :predictive + when /^R(244|246)/ + :carrier + when /^R448/ + :prenatal end end def process_variants_from_record(genotype, record) genotypes = [] - if full_screen?(genotype) + if genotype.full_screen? process_fullscreen_records(genotype, record, genotypes) - elsif targeted?(genotype) || no_scope?(genotype) + elsif genotype.targeted? || genotype.no_scope? process_targeted_no_scope_records(genotype, record, genotypes) end genotypes end - def full_screen?(genotype) - return if genotype.attribute_map['genetictestscope'].nil? - - genotype.attribute_map['genetictestscope'].scan(/Full screen/i).size.positive? - end - - def targeted?(genotype) - return if genotype.attribute_map['genetictestscope'].nil? - - genotype.attribute_map['genetictestscope'].scan(/Targeted/i).size.positive? - end - - def no_scope?(genotype) - return if genotype.attribute_map['genetictestscope'].nil? - - genotype.attribute_map['genetictestscope'].scan(/Unable to assign/i).size.positive? - end - - # rubocop:disable Metrics/MethodLength disabled as rubcop reduces redability if the method + # rubocop:disable Metrics/MethodLength -- disabled as rubocop reduces readability if the method def process_targeted_no_scope_records(genotype, record, genotypes) genotype_str = record.raw_fields['genotype'] positive_genes = genotype_str.scan(BRCA_REGEX).flatten.uniq @@ -350,8 +365,9 @@ def add_other_genes_with_status(other_genes, genotype, genotypes, status) def process_multi_genes(genotype, record, genotypes) positive_genes = record.raw_fields['genotype'].scan(BRCA_REGEX).flatten - positive_genes = positive_genes.join('|') - raw_genotypes = record.raw_fields['genotype'].split(/(?=#{positive_genes})/) + positive_genes = positive_genes.uniq.join('|') + cleaned = record.raw_fields['genotype'].gsub(RISK_PREFIX_REGEX, '').strip + raw_genotypes = cleaned.split(/(?=#{positive_genes})/) process_raw_genotypes(raw_genotypes, genotype, genotypes) end diff --git a/lib/import/helpers/brca/providers/rcu/rcu_constants.rb b/lib/import/helpers/brca/providers/rcu/rcu_constants.rb index a2ef1fc3..bfe6a7ea 100644 --- a/lib/import/helpers/brca/providers/rcu/rcu_constants.rb +++ b/lib/import/helpers/brca/providers/rcu/rcu_constants.rb @@ -23,8 +23,10 @@ module RcuConstants 'R206 :: Inherited breast cancer ' \ 'and ovarian cancer at high familial risk levels' => :process_scope_r206, 'R207 :: Inherited ovarian cancer (without breast cancer)' => :process_scope_r207, + 'R207' => :process_scope_r207, 'R208 :: BRCA1 and BRCA2 testing at high familial risk' => :process_scope_r208, 'R208 :: Inherited breast cancer and ovarian cancer' => :process_scope_r208_new, + 'R208' => :process_scope_r208_new, 'R240 - Familial Diagnostic testing - Hered Cancers' => :process_scope_r240, 'R242 - Predictive testing - Hered Cancers' => :process_scope_r242, 'R430 :: Inherited Prostate Cancer' => :process_scope_r430, @@ -111,25 +113,14 @@ module RcuConstants }.freeze R207_GENE_MAPPING_FS = { - 'R207.1 :: Unknown mutation(s) by Small panel' => %w[BRCA1 BRCA2 BRIP1 EPCAM MLH1 - MSH2 MSH6 PALB2 RAD51C RAD51D - PMS2], 'R207.2 :: Unknown mutation(s) by MLPA or equivalent' => %w[BRCA1 BRCA2 MLH1 MSH2], 'R387.1 :: NGS analysis only' => %w[BRCA1 BRCA2 BRIP1 EPCAM MLH1 MSH2 MSH6 PALB2 RAD51C RAD51D PMS2], - 'R207.1 :: NGS in Leeds' => %w[BRCA1 BRCA2 BRIP1 EPCAM MLH1 MSH2 - MSH6 PALB2 RAD51C RAD51D PMS2], - 'R207.1 :: NGS in Leeds - Send DNA to Leeds' => %w[BRCA1 BRCA2 BRIP1 EPCAM MLH1 MSH2 - MSH6 PALB2 RAD51C RAD51D PMS2] + 'R387.1 :: Reanalysis of existing NGS data' => %w[BRCA1 BRCA2 BRIP1 EPCAM MLH1 MSH2 + MSH6 PALB2 RAD51C RAD51D PMS2] }.freeze - R207_GENE_MAPPING_TAR = [ - 'R240.1 :: Diagnostic familial', - 'R242.1 :: Predictive testing', - 'R242.1 :: Predictive testing - Seq in Leeds - Send Blood', - 'R242.1 :: Predictive testing - Seq in Leeds - Send DNA', - 'R242.1 :: Predictive testing - MLPA in Leeds - Send Blood' - ].freeze + R207_1_FS_GENES = %w[BRCA1 BRCA2 BRIP1 EPCAM MLH1 MSH2 MSH6 PALB2 RAD51C RAD51D PMS2] R208_GENE_MAPPING_FS = { 'R208.1 :: Unknown mutation(s) by Single gene sequencing' => %w[BRCA1 BRCA2 PALB2], @@ -173,9 +164,7 @@ module RcuConstants 'R242.1 :: Predictive testing - ATM gene' ].freeze - R430_GENE_MAPPING_FS = { - 'R420.1 :: NGS in Leeds - Send Blood' => %w[ATM BRCA1 BRCA2 CHEK2 MLH1 MSH2 MSH6 PALB2] - }.freeze + R430_FS_GENES = %w[ATM BRCA1 BRCA2 CHEK2 MLH1 MSH2 MSH6 PALB2].freeze R444_GENE_MAPPING = { 'R444.1 :: PARPi for Breast cancer - NGS in Leeds' => %w[ATM BRCA1 BRCA2 CHEK2 PALB2 RAD51C RAD51D], @@ -210,7 +199,14 @@ module RcuConstants BRCA_REGEX = /(?BRCA1|BRCA2|PALB2|ATM|CHEK2|TP53|MLH1|CDH1| MSH2|MSH6|PMS2|STK11|PTEN|BRIP1|NBN|RAD51C|RAD51D|EPCAM)/ix - + GENE_PATTERN = Regexp.union(GENES_LIST) + + RISK_PREFIX_REGEX = / + At\selevated\srisk\sof\s+ + #{GENE_PATTERN}\s+ + and\s+ + #{GENE_PATTERN}-related\ cancers; + ?/ix # rubocop:disable Lint/MixedRegexpCaptureTypes CDNA_REGEX = /((c(\.)?-?\*?(? (\[[0-9]+[+>_-][0-9][+>_-][0-9]+[+>_-][0-9][ACGTdelinsup]+\])| diff --git a/test/lib/import/brca/providers/sheffield/sheffield_handler_test.rb b/test/lib/import/brca/providers/sheffield/sheffield_handler_test.rb index 237e4eba..436ad0df 100644 --- a/test/lib/import/brca/providers/sheffield/sheffield_handler_test.rb +++ b/test/lib/import/brca/providers/sheffield/sheffield_handler_test.rb @@ -29,9 +29,36 @@ def setup assert_equal 'Unable to assign BRCA genetictestscope', @genotype.attribute_map['genetictestscope'] end - test 'add_test_type' do + test 'add_test_type from moleculartestingtype mapping' do @handler.add_test_type(@genotype, @record) assert_equal 2, @genotype.attribute_map['moleculartestingtype'] + mtype_record = build_raw_record('pseudo_id1' => 'bob') + mtype_record.raw_fields['moleculartestingtype'] = 'Testing for unaffected family member' + @handler.add_test_type(@genotype, mtype_record) + assert_equal 2, @genotype.attribute_map['moleculartestingtype'] # :predictive + end + + test 'add_test_type from karyo when moleculartestingtype cannot be determined' do + karyo_mtype_record = build_raw_record('pseudo_id1' => 'bob') + karyo_mtype_record.raw_fields['moleculartestingtype'] = '' + karyo_mtype_record.raw_fields['karyotypingmethod'] = 'R240.1 :: Some test' + @handler.add_test_type(@genotype, karyo_mtype_record) + assert_equal 1, @genotype.attribute_map['moleculartestingtype'] # :diagnostic + karyo_mtype_record.raw_fields['karyotypingmethod'] = 'R242.1 :: Predictive testing' + @handler.add_test_type(@genotype, karyo_mtype_record) + assert_equal 2, @genotype.attribute_map['moleculartestingtype'] # :predictive + karyo_mtype_record.raw_fields['karyotypingmethod'] = 'R448.1 :: Prenatal testing' + @handler.add_test_type(@genotype, karyo_mtype_record) + assert_equal 4, @genotype.attribute_map['moleculartestingtype'] # :prenatal + end + + test 'add_test_type moleculartestingtype takes priority over karyo' do + priority_record = build_raw_record('pseudo_id1' => 'bob') + priority_record.raw_fields['moleculartestingtype'] = 'Diagnostic testing' + priority_record.raw_fields['karyotypingmethod'] = 'R242.1 :: Predictive testing' + @handler.add_test_type(@genotype, priority_record) + # Should be diagnostic from moleculartestingtype, not predictive from karyo + assert_equal 1, @genotype.attribute_map['moleculartestingtype'] end test 'process_variants_from_record' do @@ -311,6 +338,110 @@ def setup assert_nil genotypes[1].attribute_map['codingdnasequencechange'] end + test 'process_scope_r207 with R207.1 full screen' do + r207_1_record = build_raw_record('pseudo_id1' => 'bob') + r207_1_record.raw_fields['genetictestscope'] = 'R207 :: Inherited ovarian cancer (without breast cancer)' + r207_1_record.raw_fields['karyotypingmethod'] = 'R207.1 :: NGS in Leeds' + r207_1_record.raw_fields['genotype'] = 'BRCA1-c.5266dup-p.(Gln1756fs)-Heterozygous-UV5;MSH6-c.3649A>G-p.(Arg1217Gly)-Heterozygous-UV3' + @handler.add_test_scope_from_geno_karyo(@genotype, r207_1_record) + assert_equal 'Full screen BRCA1 and BRCA2', @genotype.attribute_map['genetictestscope'] + genotypes = @handler.process_variants_from_record(@genotype, r207_1_record) + assert_equal 11, genotypes.size + variant_genotype_brca = genotypes.find { |g| g.attribute_map['gene'] == 7 } # BRCA1 + assert_equal 2, variant_genotype_brca.attribute_map['teststatus'] + assert_equal 'c.5266dup', variant_genotype_brca.attribute_map['codingdnasequencechange'] + assert_equal 'p.Gln1756fs', variant_genotype_brca.attribute_map['proteinimpact'] + + variant_genotype_msh6 = genotypes.find { |g| g.attribute_map['gene'] == 2808 } # MSH6 + assert_equal 2, variant_genotype_msh6.attribute_map['teststatus'] + assert_equal 'c.3649A>G', variant_genotype_msh6.attribute_map['codingdnasequencechange'] + assert_equal 'p.Arg1217Gly', variant_genotype_msh6.attribute_map['proteinimpact'] + genotypes.each do |genotype| + next if [7, 2808].include?(genotype.attribute_map['gene']) + + assert_equal 1, genotype.attribute_map['teststatus'] + end + end + + test 'process_scope_r207 with R240 targeted' do + r207_r240_record = build_raw_record('pseudo_id1' => 'bob') + r207_r240_record.raw_fields['genetictestscope'] = 'R207' + r207_r240_record.raw_fields['karyotypingmethod'] = 'R240 :: Diagnostic testing for known pathogenic variant(s) - Hereditary Cancers' + r207_r240_record.raw_fields['genotype'] = 'Genetic diagnosis of BRCA2-related cancer susceptibility; BRCA2(NM_000059.3);c.4218_4221del;p.(Lys1406Asnfs*3);Heterozygous;UV5' + @handler.add_test_scope_from_geno_karyo(@genotype, r207_r240_record) + assert_equal 'Targeted BRCA mutation test', @genotype.attribute_map['genetictestscope'] + genotypes = @handler.process_variants_from_record(@genotype, r207_r240_record) + assert_equal 1, genotypes.size + assert_equal 2, genotypes[0].attribute_map['teststatus'] + assert_equal 8, genotypes[0].attribute_map['gene'] + assert_equal 'c.4218_4221del', genotypes[0].attribute_map['codingdnasequencechange'] + assert_equal 'p.Lys1406AsnfsTer3', genotypes[0].attribute_map['proteinimpact'] + end + + test 'process_scope_r208_new with R242 targeted' do + r208_r242_record = build_raw_record('pseudo_id1' => 'bob') + r208_r242_record.raw_fields['genetictestscope'] = 'R208' + r208_r242_record.raw_fields['karyotypingmethod'] = 'R242 :: Predictive testing for known familial pathogenic variant(s) - Hereditary Cancers' + r208_r242_record.raw_fields['genotype'] = 'At elevated risk of BRCA1 and BRCA2-related cancers; BRCA1(NM_007294.3);deletion including exons 1-2Heterozygous;' + @handler.add_test_scope_from_geno_karyo(@genotype, r208_r242_record) + assert_equal 'Targeted BRCA mutation test', @genotype.attribute_map['genetictestscope'] + genotypes = @handler.process_variants_from_record(@genotype, r208_r242_record) + assert_equal 1, genotypes.size + assert_equal 2, genotypes[0].attribute_map['teststatus'] + assert_equal 7, genotypes[0].attribute_map['gene'] + end + + test 'process_scope_r430 with R430 full screen' do + r430_record = build_raw_record('pseudo_id1' => 'bob') + r430_record.raw_fields['genetictestscope'] = 'R430 :: Inherited Prostate Cancer' + r430_record.raw_fields['karyotypingmethod'] = 'R430.1 :: NGS in Leeds' + r430_record.raw_fields['genotype'] = 'Genetic diagnosis of CHEK2-related cancer susceptibility; CHEK2(NM_007194.4);c.1100del;p.(Glu1493fs);Heterozygous;UV5' + @handler.add_test_scope_from_geno_karyo(@genotype, r430_record) + assert_equal 'Full screen BRCA1 and BRCA2', @genotype.attribute_map['genetictestscope'] + genotypes = @handler.process_variants_from_record(@genotype, r430_record) + assert_equal 8, genotypes.size + variant_genotype = genotypes.find { |g| g.attribute_map['gene'] == 865 } # CHEK2 + assert_equal 2, variant_genotype.attribute_map['teststatus'] + assert_equal 'c.1100del', variant_genotype.attribute_map['codingdnasequencechange'] + assert_equal 'p.Glu1493fs', variant_genotype.attribute_map['proteinimpact'] + + genotypes.each do |genotype| + next if genotype.attribute_map['gene'] == 865 + + assert_equal 1, genotype.attribute_map['teststatus'] + end + end + + test 'process_scope_r207 with R387.1 targeted' do + r207_r387_1_record = build_raw_record('pseudo_id1' => 'bob') + r207_r387_1_record.raw_fields['genetictestscope'] = 'R207' + r207_r387_1_record.raw_fields['karyotypingmethod'] = 'R387.1 :: Reanalysis of existing NGS data' + r207_r387_1_record.raw_fields['genotype'] = 'No variant detected' + @handler.add_test_scope_from_geno_karyo(@genotype, r207_r387_1_record) + assert_equal 'Full screen BRCA1 and BRCA2', @genotype.attribute_map['genetictestscope'] + genotypes = @handler.process_variants_from_record(@genotype, r207_r387_1_record) + assert_equal 11, genotypes.size + genotypes.each do |genotype| + assert_not_nil genotype.attribute_map['gene'] + assert_equal 1, genotype.attribute_map['teststatus'] + end + end + + test 'process_scope_r208 with R370.1 targeted' do + r208_r370_1_record = build_raw_record('pseudo_id1' => 'bob') + r208_r370_1_record.raw_fields['genetictestscope'] = 'R208 :: Inherited breast cancer and ovarian cancer' + r208_r370_1_record.raw_fields['karyotypingmethod'] = 'R370.1 :: Confirmation of research result' + r208_r370_1_record.raw_fields['genotype'] = 'BRCA1-GRCh38(chr17):g.43118884_43155545dup; (NM_007294.3):c.1100del-Heterozygous-UV3' + @handler.add_test_scope_from_geno_karyo(@genotype, r208_r370_1_record) + assert_equal 'Targeted BRCA mutation test', @genotype.attribute_map['genetictestscope'] + genotypes = @handler.process_variants_from_record(@genotype, r208_r370_1_record) + assert_equal 1, genotypes.size + assert_equal 2, genotypes[0].attribute_map['teststatus'] + assert_equal 7, genotypes[0].attribute_map['gene'] + assert_equal 'c.1100del', genotypes[0].attribute_map['codingdnasequencechange'] + assert_nil genotypes[0].attribute_map['proteinimpact'] + end + private def clinical_json