Skip to content
Merged
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
22 changes: 16 additions & 6 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ py-ard
:alt: Documentation Status


ARD reduction for HLA with python
ARD reduction for HLA with Python

* Free software: LGPL 3.0
* Documentation: https://pyard.readthedocs.io.
Expand Down Expand Up @@ -68,26 +68,33 @@ Example
# You can choose to refresh the MAC code for previously used versions
# ard = pyard.ARD(3290, refresh_mac=True)

# Allele to reduce
#
# Reduce Allele
#
allele = "A*01:01:01"

ard.redux(allele, 'G')
# 'A*01:01:01G'
# >>> 'A*01:01:01G'

ard.redux(allele, 'lg')
# 'A*01:01g'
# >>> 'A*01:01g'

ard.redux(allele, 'lgx')
# 'A*01:01'
# >>> 'A*01:01'

#
# Reduce GL String
#
ard.redux_gl("A*01:01/A*01:01N+A*02:AB^B*07:02+B*07:AB", "G")
# 'B*07:02:01G+B*07:02:01G^A*01:01:01G+A*02:01:01G/A*02:02'

# py-ard can also reduce serology based typings
ard.redux_gl('HLA-A*10^HLA-A*9', 'lg')
# >>> ard_gl
# 'HLA-A*24:19g/HLA-A*24:22g^HLA-A*26:01g/HLA-A*26:10g/HLA-A*26:15g/HLA-A*26:92g/HLA-A*66:01g/HLA-A*66:03g'



Command Line Tools
------------------

Expand All @@ -107,6 +114,9 @@ Command Line Tools
Created py-ard version 3290 database
Updated v2_mapping table with 'map2to3.csv' mapping file.

# Replace the Latest IMGT database with V2 mappings
$ pyard-import --v2-to-v3-mapping map2to3.csv

# Reduce a gl string from command line
$ pyard --gl 'A*01:AB' -r lgx
A*01:01/A*01:02
Expand All @@ -115,4 +125,4 @@ Command Line Tools
DRB1*08:01:01G/DRB1*08:02:01G/DRB1*08:03:02G/DRB1*08:04:01G/DRB1*08:05/ ...

$ pyard -v 3290 --gl 'A1' -r lgx
A*01:01/A*01:02/A*01:03/A*01:06/A*01:07/A*01:08/A*01:09/A*01:10/A*01:12/ ...
A*01:01/A*01:02/A*01:03/A*01:06/A*01:07/A*01:08/A*01:09/A*01:10/A*01:12/ ...
63 changes: 60 additions & 3 deletions pyard/pyard.py
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ def redux_gl(self, glstring: str, redux_type: str) -> str:
loc_antigen, code = loc_allele[0], loc_allele[1]

# Handle XX codes
if self.is_mac(glstring) and code == "XX" and loc_antigen in self.xx_codes:
if self.is_XX(glstring, loc_antigen, code):
return self.redux_gl("/".join(self.xx_codes[loc_antigen]), redux_type)

# Handle MAC
Expand All @@ -205,6 +205,12 @@ def redux_gl(self, glstring: str, redux_type: str) -> str:

return self.redux(glstring, redux_type)

def is_XX(self, glstring: str, loc_antigen: str = None, code: str = None) -> bool:
if loc_antigen is None or code is None:
loc_allele = glstring.split(":")
loc_antigen, code = loc_allele[0], loc_allele[1]
return self.is_mac(glstring) and code == "XX" and loc_antigen in self.xx_codes

@staticmethod
def is_serology(allele: str) -> bool:
"""
Expand Down Expand Up @@ -248,7 +254,7 @@ def is_v2(allele: str) -> bool:
:param allele: Possible allele
:return: Is the allele in V2 nomenclature
"""
return '*' in allele and not ':' in allele
return '*' in allele and ':' not in allele

def _is_valid_allele(self, allele):
"""
Expand Down Expand Up @@ -290,13 +296,53 @@ def _get_alleles_from_serology(self, serology) -> Iterable[str]:
else:
return alleles

def _combine_with_colon(self, digits_field):
num_of_digits = len(digits_field)
return ':'.join(digits_field[i:i + 2] for i in range(0, num_of_digits, 2))

def _predict_v3(self, v2_allele: str) -> str:
"""
Use heuristic to predict V3 from V2

:param v2_allele: Allele in V2 format
:return: V3 format of V2 allele
"""
# Separate out the locus and the allele name part
locus, allele_name = v2_allele.split('*')
# Separate out the numeric and non-numeric components
components = re.findall(r'^(\d+)(.*)', allele_name)
if not components:
return v2_allele
digits_field, non_digits_field = components.pop()
# final_allele is the result of the transformation
final_allele = digits_field
num_of_digits = len(digits_field)
if num_of_digits == 1:
return v2_allele
if num_of_digits > 2:
if locus.startswith('DP') and num_of_digits == 5: # covers DPs with 5 digits
final_allele = digits_field[:3] + ':' + (digits_field[3:]) + non_digits_field
elif num_of_digits % 2 == 0: # covers digits with 2, 4, 6, 8
final_allele = self._combine_with_colon(digits_field) + non_digits_field
else:
final_allele = digits_field[:2] + ':' + (digits_field[2:]) + non_digits_field
else:
if non_digits_field:
final_allele = digits_field + ':' + non_digits_field
return locus + '*' + final_allele

def _map_v2_to_v3(self, v2_allele):
"""
Get V3 version of V2 versioned allele
:param v2_allele: V2 versioned allele
:return: V3 versioned allele
"""
return v2_to_v3_allele(self.db_connection, v2_allele)
# Check if it's in the exception case mapping
v3_allele = v2_to_v3_allele(self.db_connection, v2_allele)
if not v3_allele:
# Try and predict V3
v3_allele = self._predict_v3(v2_allele)
return v3_allele

def isvalid(self, allele: str) -> bool:
"""
Expand Down Expand Up @@ -404,3 +450,14 @@ def expand_mac(self, mac_code: str):
return list(self._get_alleles(code, locus_antigen))

return ''

def v2_to_v3(self, v2_allele) -> str:
"""
Convert Version 2 Allele Name to Version 3 Allele Name

:param v2_allele: Version 2 Allele Name
:return: Version 3 Allele Name
"""
if self.is_v2(v2_allele):
return self._map_v2_to_v3(v2_allele)
return v2_allele
3 changes: 2 additions & 1 deletion scripts/pyard-import
Original file line number Diff line number Diff line change
Expand Up @@ -92,11 +92,12 @@ if __name__ == '__main__':
print(f"Created py-ard version {imgt_version} database")
else:
ard = pyard.ARD(data_dir=data_dir)
imgt_version = 'Latest'
print(f"Created Latest py-ard database")
del ard

if v2_to_v3_dict:
db_connection = db.create_db_connection(data_dir, imgt_version, ro=False)
db.save_dict(db_connection, table_name='v2_mapping',
dictionary=v2_to_v3_dict, columns=('v2', 'v3'))
print(f"Updated v2_mapping table with '{args.v2_v3_mapping}' mapping file.")
print(f"Updated v2_mapping table with '{args.v2_v3_mapping}' mapping file for {imgt_version} IMGT database.")