|
26 | 26 | import sqlite3
|
27 | 27 | import sys
|
28 | 28 | from collections import Counter
|
29 |
| -from typing import Iterable, List |
| 29 | +from typing import Iterable, List, Union |
30 | 30 |
|
31 | 31 | from . import broad_splits, smart_sort
|
32 | 32 | from . import data_repository as dr
|
33 | 33 | from . import db
|
34 |
| -from .exceptions import InvalidAlleleError, InvalidMACError, InvalidTypingError |
35 |
| -from .misc import ( |
36 |
| - get_n_field_allele, |
37 |
| - get_2field_allele, |
38 |
| - is_2_field_allele, |
39 |
| - validate_reduction_type, |
40 |
| -) |
41 | 34 | from .constants import (
|
42 | 35 | HLA_regex,
|
43 | 36 | VALID_REDUCTION_TYPES,
|
44 | 37 | expression_chars,
|
45 | 38 | DEFAULT_CACHE_SIZE,
|
46 | 39 | G_GROUP_LOCI,
|
47 | 40 | )
|
| 41 | +from .exceptions import InvalidAlleleError, InvalidMACError, InvalidTypingError |
| 42 | +from .misc import ( |
| 43 | + get_n_field_allele, |
| 44 | + get_2field_allele, |
| 45 | + is_2_field_allele, |
| 46 | + validate_reduction_type, |
| 47 | +) |
48 | 48 |
|
49 | 49 | default_config = {
|
50 | 50 | "reduce_serology": True,
|
@@ -837,3 +837,47 @@ def get_db_version(self) -> str:
|
837 | 837 | @return:
|
838 | 838 | """
|
839 | 839 | return dr.get_db_version(self.db_connection)
|
| 840 | + |
| 841 | + def similar_alleles(self, prefix: str) -> Union[List, None]: |
| 842 | + """ |
| 843 | + Given a prefix, find similar alleles or MACs starting with the prefix. |
| 844 | + The minimum prefix needs to specify is the locus with a `*`, |
| 845 | + and a first field of the allele/MAC. |
| 846 | +
|
| 847 | + @param prefix: The prefix for allele or MAC |
| 848 | + @return: List of alleles/MACs that start with the prefix |
| 849 | + """ |
| 850 | + |
| 851 | + if "*" not in prefix: # Only for those that have locus |
| 852 | + return None |
| 853 | + |
| 854 | + locus, fields = prefix.split("*") |
| 855 | + # if at least a field is specified after * |
| 856 | + if fields: |
| 857 | + # Will check only for and after 2 fields |
| 858 | + if len(fields.split(":")) == 2: |
| 859 | + first_field, mac_prefix = fields.split(":") |
| 860 | + if mac_prefix.isalpha(): # Check for MACs |
| 861 | + similar_mac_names = db.similar_mac(self.db_connection, mac_prefix) |
| 862 | + if similar_mac_names: |
| 863 | + locus_prefix = f"{locus}*{first_field}" |
| 864 | + # Build all the mac codes with the prefix |
| 865 | + mac_codes = [ |
| 866 | + f"{locus_prefix}:{code}" for code in similar_mac_names |
| 867 | + ] |
| 868 | + # show only the valid macs |
| 869 | + real_mac_codes = sorted( |
| 870 | + filter(lambda mac: self.is_mac(mac), mac_codes) |
| 871 | + ) |
| 872 | + return real_mac_codes |
| 873 | + |
| 874 | + # find similar alleles |
| 875 | + similar_allele_names = db.similar_alleles(self.db_connection, prefix) |
| 876 | + if similar_allele_names: |
| 877 | + alleles = sorted( |
| 878 | + similar_allele_names, |
| 879 | + key=functools.cmp_to_key(smart_sort.smart_sort_comparator), |
| 880 | + ) |
| 881 | + return alleles |
| 882 | + |
| 883 | + return None |
0 commit comments