Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
84 changes: 59 additions & 25 deletions VariantValidator/modules/complex_descriptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@
import copy
from vvhgvs.assemblymapper import AssemblyMapper
from VariantValidator.modules import utils as vv_utils, format_converters
from VariantValidator.modules.hgvs_utils import hgvs_obj_from_existing_edit
from VariantValidator.modules.hgvs_utils import hgvs_obj_from_existing_edit,\
_hgvs_offset_pos_from_str_in
import vvhgvs.exceptions
from vvhgvs.enums import Datum, ValidationLevel
from vvhgvs.location import Interval

class UncertainConversionError(Exception):
Expand All @@ -12,8 +14,10 @@ class UncertainConversionError(Exception):
# fuzzy but specified ended intervals, take a normal interval for both ends
# can take a pair of Intervals or BaseOffsetIntervals
class FEInterval(Interval):
uncertain = True
pass
def __init__(self,start = None,end = None):
self.uncertain = True
self.start = start
self.end = end
def validate(self):
if self.start:
(res, msg) = self.start.validate()
Expand Down Expand Up @@ -258,12 +262,12 @@ def fuzzy_ends(my_variant, validator):
raise FuzzyRangeError("Fuzzy/unknown variant end position in submitted variant description")

else:
if "?" in str(my_variant.hgvs_formatted.posedit.pos):
if "?" in str(my_variant.hgvs_formatted.posedit.pos.end) and "?" not in str(
my_variant.hgvs_formatted.posedit.pos.start):
if "?" in str(my_variant.quibble.posedit.pos):
if "?" in str(my_variant.quibble.posedit.pos.end) and "?" not in str(
my_variant.quibble.posedit.pos.start):
raise FuzzyPositionError("Fuzzy/unknown variant end position in submitted variant description")
elif "?" in str(my_variant.hgvs_formatted.posedit.pos.start) and "?" not in str(
my_variant.hgvs_formatted.posedit.pos.end):
elif "?" in str(my_variant.quibble.posedit.pos.start) and "?" not in str(
my_variant.quibble.posedit.pos.end):
raise FuzzyPositionError("Fuzzy/unknown variant start position in submitted variant description")
else:
raise FuzzyPositionError("Fuzzy/unknown variant start and end positions "
Expand Down Expand Up @@ -369,9 +373,28 @@ def uncertain_positions(my_variant, validator):

# Genomic Variants
if "NC_" in my_variant.quibble:
my_variant.hgvs_genomic = my_variant.quibble
start_pos = position_1.split("_")[0]
end_pos = position_2.split("_")[1]
start_pos, _sep, start_end = position_1.partition("_")
o_start_pos, start_end = _hgvs_offset_pos_from_str_in(
start_pos,
None,
ref_type=var_type,
end=start_end)
start = Interval(start=o_start_pos,end=start_end)
end_start, _sep, end_pos = position_2.partition("_")
end_start, o_end_pos = _hgvs_offset_pos_from_str_in(
end_start,
None,
ref_type=var_type,
end=end_pos)
end = Interval(start=end_start,end=o_end_pos)
full_obj = hgvs_obj_from_existing_edit(
accession,
var_type,
FEInterval(
start=start,
end=end),
edit)
my_variant.hgvs_genomic = full_obj
parsed_v3 = hgvs_obj_from_existing_edit(
accession,
var_type,
Expand Down Expand Up @@ -438,7 +461,6 @@ def uncertain_positions(my_variant, validator):
end=t_position_2),
edit)

my_variant.hgvs_coding = tx_variant
my_variant.quibble = copy.copy(tx_variant)
my_variant.hgvs_transcript_variant = tx_variant
else:
Expand Down Expand Up @@ -472,15 +494,15 @@ def uncertain_positions(my_variant, validator):
end=g_position_2),
edit)
my_variant.hgvs_genomic = gen_variant
my_variant.hgvs_coding = hgvs_obj_from_existing_edit(
hgvs_coding = hgvs_obj_from_existing_edit(
parsed_v1.ac,
parsed_v2.type,
FEInterval(start=parsed_v1.posedit.pos,
end=parsed_v2.posedit.pos),
edit
)
my_variant.hgvs_transcript_variant = copy.copy(my_variant.hgvs_coding)
my_variant.quibble = copy.copy(my_variant.hgvs_coding)
my_variant.hgvs_transcript_variant = copy.copy(hgvs_coding)
my_variant.quibble = copy.copy(hgvs_coding)
my_variant.output_type_flag = "gene"

elif ")_(" not in my_variant.quibble and not "?" in my_variant.quibble:
Expand All @@ -489,7 +511,6 @@ def uncertain_positions(my_variant, validator):
accession, _sep, var_type_and_posedit = my_variant.quibble.partition(':')
var_type, _sep ,position_and_edit = var_type_and_posedit.partition(".(")
position_1, variation = position_and_edit.split(")")
v1 = f"{accession}:{var_type}.{position_1}="
my_variant.reftype = f":{var_type}."
try:
if var_type == 'p':
Expand Down Expand Up @@ -517,7 +538,7 @@ def uncertain_positions(my_variant, validator):
raise IncompatibleTypeError(str(e))
elif "base start position must be <= end position" in str(e):
raise InvalidRangeError(f"{str(e)} in position {str(parsed_v1.posedit.pos)}")
elif re.search("[+-]", str(parsed_v1.posedit.pos)) or re.search("[+-]", str(parsed_v1.posedit.pos)):
elif "+" in str(parsed_v1.posedit.pos) or "-" in str(parsed_v1.posedit.pos):
pass
else:
raise InvalidRangeError(f"{position_1} is an invalid range for "
Expand All @@ -529,8 +550,23 @@ def uncertain_positions(my_variant, validator):

# Genomic Variants
if "NC_" in my_variant.quibble:
my_variant.hgvs_genomic = my_variant.quibble

start_pos, _sep, start_end = position_1.partition("_")
start_pos, end_pos = _hgvs_offset_pos_from_str_in(
start_pos,
None,
end=start_end,
ref_type=var_type)
pos = Interval(start=start_pos,end=end_pos)
try:
full_obj = hgvs_obj_from_existing_edit(
accession,
var_type,
pos,
edit)
except Exception as e:
raise e
full_obj.posedit.pos.uncertain = True
my_variant.hgvs_genomic = full_obj
# Make select_transcriopts "select" unless specified
if (validator.select_transcripts != "select" and ("NM_" in validator.select_transcripts or
"ENST" in validator.select_transcripts) and
Expand Down Expand Up @@ -567,8 +603,6 @@ def uncertain_positions(my_variant, validator):
ptv1[0].posedit.pos,
edit)
tx_variant.posedit.pos.uncertain = True

my_variant.hgvs_coding = tx_variant
my_variant.quibble = copy.copy(tx_variant)
my_variant.hgvs_transcript_variant = tx_variant
else:
Expand All @@ -587,14 +621,14 @@ def uncertain_positions(my_variant, validator):
gen_variant.posedit.pos.uncertain = True

my_variant.hgvs_genomic = gen_variant
my_variant.hgvs_coding = hgvs_obj_from_existing_edit(
hgvs_coding = hgvs_obj_from_existing_edit(
parsed_v1.ac,
parsed_v1.type,
parsed_v1.posedit.pos,
edit)
my_variant.hgvs_coding.posedit.pos.uncertain = True
my_variant.hgvs_transcript_variant = my_variant.hgvs_coding
my_variant.quibble = copy.copy(my_variant.hgvs_coding)
hgvs_coding.posedit.pos.uncertain = True
my_variant.hgvs_transcript_variant = hgvs_coding
my_variant.quibble = copy.copy(hgvs_coding)
my_variant.output_type_flag = "gene"

else:
Expand Down
12 changes: 6 additions & 6 deletions VariantValidator/modules/exon_numbering.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ def finds_exon_number(variant, validator):
info_dict = {}
for i in range(len(response_dictionary["transcripts"])):

if response_dictionary["transcripts"][i]["reference"] == variant.hgvs_coding.ac:
if response_dictionary["transcripts"][i]["reference"] == variant.quibble.ac:

# Create record
info_dict[(response_dictionary["transcripts"][i]["reference"])] = {}
Expand All @@ -53,7 +53,7 @@ def finds_exon_number(variant, validator):

# Step 2 - Get the necessary variant information
# Find the variant position from the variant nomenclature
coordinates = str(variant.hgvs_coding.posedit.pos)
coordinates = str(variant.quibble.posedit.pos)

# Identify start and end of variant from input coordinates
if '_' in coordinates:
Expand All @@ -72,9 +72,9 @@ def finds_exon_number(variant, validator):

# Create c_to_n varint
try:
to_n = validator.vm.c_to_n(variant.hgvs_coding)
to_n = validator.vm.c_to_n(variant.quibble)
except vvhgvs.exceptions.HGVSInvalidVariantError:
to_n = variant.hgvs_coding
to_n = variant.quibble

"""
This for loop identifies the exon/intron number for the transcript
Expand All @@ -85,8 +85,8 @@ def finds_exon_number(variant, validator):
keys: start_exon and end_exon
values: start and position of variant in the reference sequence
"""
exon_structure_dict = info_dict[variant.hgvs_coding.ac]["exon_structure_dict"]
coding_start = info_dict[variant.hgvs_coding.ac]['coding_start']
exon_structure_dict = info_dict[variant.quibble.ac]["exon_structure_dict"]
coding_start = info_dict[variant.quibble.ac]['coding_start']
if coding_start is None:
coding_start = 1

Expand Down
59 changes: 28 additions & 31 deletions VariantValidator/modules/format_converters.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,9 @@ def initial_format_conversions(variant, validator, select_transcripts_dict_plus_
# fail if un-corrected errors persist (warning should already have been generated)
if toskip:
return True

# make sure ref type and source are set if we intend to continue
variant.set_reftype()
variant.set_refsource()
# Tackle compound variant descriptions NG or NC (NM_) i.e. correctly input NG/NC_(NM_):c.
intronic_converter(variant, validator)
return False
Expand Down Expand Up @@ -1077,45 +1079,41 @@ def lrg_to_refseq(variant, validator):
"""
caution = ''
if variant.refsource == 'LRG':
if variant.hgvs_formatted.ac.startswith('LRG') and variant.hgvs_formatted.ac[3:4].isdigit():
reference = variant.hgvs_formatted.ac.replace('LRG', 'LRG_')
caution = variant.hgvs_formatted.ac + ' updated to ' + reference + ': '
variant.hgvs_formatted.ac = reference
variant.set_quibble(variant.hgvs_formatted)
if variant.quibble.ac.startswith('LRG') and variant.quibble.ac[3:4].isdigit():
reference = variant.quibble.ac.replace('LRG', 'LRG_')
caution = variant.quibble.ac + ' updated to ' + reference + ': '
variant.quibble.ac = reference

if re.match(r'^LRG_\d+t\d+$', variant.quibble.ac):
lrg_reference = variant.quibble.ac
refseqtrans_reference = validator.db.get_refseq_transcript_id_from_lrg_transcript_id(lrg_reference)
if refseqtrans_reference != 'none':
old_var_str = str(variant.hgvs_formatted)
variant.hgvs_formatted.ac = refseqtrans_reference
variant.set_quibble(variant.hgvs_formatted)
old_var_str = str(variant.quibble)
variant.quibble.ac = refseqtrans_reference
caution += old_var_str + ' automapped to equivalent RefSeq record ' \
'' + str(variant.hgvs_formatted)
'' + str(variant.quibble)
variant.warnings.append(caution)
logger.info(caution)

elif re.match(r'^LRG_\d+p\d+$', variant.quibble.ac):
lrg_reference = variant.quibble.ac
refseqprot_reference = validator.db.get_refseq_protein_id_from_lrg_protein_id(lrg_reference)
if refseqprot_reference != 'none':
old_var_str = str(variant.hgvs_formatted)
variant.hgvs_formatted.ac = refseqprot_reference
variant.set_quibble(variant.hgvs_formatted)
old_var_str = str(variant.quibble)
variant.quibble.ac = refseqprot_reference
caution += old_var_str + ' automapped to equivalent RefSeq record ' \
'' + str(variant.hgvs_formatted)
'' + str(variant.quibble)
variant.warnings.append(caution)
logger.info(caution)

elif re.match(r'^LRG_\d+$', variant.quibble.ac):
lrg_reference = variant.quibble.ac
refseqgene_reference = validator.db.get_refseq_id_from_lrg_id(lrg_reference)
if refseqgene_reference != 'none':
old_var_str = str(variant.hgvs_formatted)
variant.hgvs_formatted.ac = refseqgene_reference
variant.set_quibble(variant.hgvs_formatted)
old_var_str = str(variant.quibble)
variant.quibble.ac = refseqgene_reference
caution += old_var_str + ' automapped to equivalent RefSeq record ' \
'' + str(variant.hgvs_formatted)
'' + str(variant.quibble)
variant.warnings.append(caution)
logger.info(caution)

Expand All @@ -1124,14 +1122,14 @@ def mitochondrial(variant, validator):
"""Will check if variant is mitochondrial and if so it will reformat the type to 'm' and save a value to the variant
hgvs_genomic attribute"""

if variant.reftype == ':m.' or variant.hgvs_formatted.ac == 'NC_012920.1' or \
variant.hgvs_formatted.ac == 'NC_001807.4':
if variant.reftype == ':m.' or variant.quibble.ac == 'NC_012920.1' or \
variant.quibble.ac == 'NC_001807.4':

# set flag
variant.output_type_flag = 'mitochondrial'

# Ensure the correct reference sequence type is used, if not, warn the user
hgvs_mito = copy.deepcopy(variant.hgvs_formatted)
hgvs_mito = copy.deepcopy(variant.quibble)
if hgvs_mito.type == 'g' and (hgvs_mito.ac == 'NC_012920.1' or hgvs_mito.ac == 'NC_001807.4'):
hgvs_mito.type = 'm'
if "NC_012920.1" in hgvs_mito.ac and "hg19" in variant.selected_assembly:
Expand Down Expand Up @@ -1164,7 +1162,7 @@ def mitochondrial(variant, validator):

# Check for movement during normalization
try:
norm_check = variant.hn.normalize(variant.hgvs_formatted)
norm_check = variant.hn.normalize(variant.quibble)
if hgvs_mito.posedit.pos != norm_check.posedit.pos:
norm_check.type = "m"
error = "%s updated to %s" % (fn.valstr(hgvs_mito), fn.valstr(norm_check))
Expand All @@ -1184,7 +1182,6 @@ def mitochondrial(variant, validator):
# Add a description of the reference sequence type and continue
variant.hgvs_genomic = hgvs_mito
if len(rel_var) == 0:
variant.genomic_g = unset_hgvs_obj_ref(hgvs_mito)
variant.description = 'Homo sapiens mitochondrion, complete genome'
logger.info('Homo sapiens mitochondrion, complete genome')
return True
Expand All @@ -1198,7 +1195,7 @@ def proteins(variant, validator):
error = None
hgvs_object = None
# Try to validate the variant
hgvs_object = variant.hgvs_formatted
hgvs_object = variant.quibble
try:
validator.vr.validate(hgvs_object)

Expand Down Expand Up @@ -1375,17 +1372,17 @@ def rna(variant, validator):
convert r, into c.
"""
if variant.reftype == ':r.' or ":r." in variant.original:
if ":r.(" in str(variant.hgvs_formatted):
if type(variant.hgvs_formatted) is str:
strip_prediction = str(variant.hgvs_formatted).replace("(", "")
if ":r.(" in str(variant.quibble):
if type(variant.quibble) is str:
strip_prediction = str(variant.quibble).replace("(", "")
strip_prediction = strip_prediction[:-1]
hgvs_input = validator.hp.parse_hgvs_variant(strip_prediction)
else:
hgvs_input = variant.hgvs_formatted
hgvs_input = variant.quibble
hgvs_input.posedit.pos.uncertain = False
#hgvs_input.posedit.uncertain = False
else:
hgvs_input = variant.hgvs_formatted
hgvs_input = variant.quibble

tx_info = validator.hdp.get_tx_identity_info(hgvs_input.ac)
if tx_info[3] is None:
Expand All @@ -1403,7 +1400,7 @@ def rna(variant, validator):
variant.warnings.append(error)
logger.info(str(error))
return True
variant.hgvs_formatted = hgvs_c
variant.quibble = hgvs_c

# Create variant.rna_data dictionary
rnd = VariantValidator.modules.rna_formatter.RnaDescriptions(validator.alt_aln_method,
Expand Down Expand Up @@ -1492,4 +1489,4 @@ def uncertain_pos(variant, validator):
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
# </LICENSE>
# </LICENSE>
4 changes: 2 additions & 2 deletions VariantValidator/modules/gapped_mapping.py
Original file line number Diff line number Diff line change
Expand Up @@ -409,11 +409,11 @@ def gapped_g_to_c(self, rel_var, select_transcripts_dict):

# take a look at the input genomic variant for potential base salvage
stash_ac = vcf_dict['chr']
stash_input = self.variant.post_format_conversion
stash_input = self.variant.quibble
if type(stash_input) is str:
stash_input = self.validator.hp.parse_hgvs_variant(stash_input)
# Re-Analyse genomic positions
if 'NG_' in str(self.variant.hgvs_formatted):
if 'NG_' in str(self.variant.quibble):
c = rel_var[0]
if hasattr(c.posedit.edit, 'ref') and c.posedit.edit.ref is not None:
c.posedit.edit.ref = c.posedit.edit.ref.upper()
Expand Down
Loading
Loading