|
1 | 1 | # -*- coding: utf-8 -*- |
2 | 2 |
|
3 | | -import functools |
4 | 3 | from typing import TYPE_CHECKING |
5 | 4 |
|
6 | | -from ..constants import VALID_REDUCTION_TYPES, expression_chars |
7 | | -from ..exceptions import InvalidAlleleError |
8 | | -from ..misc import get_n_field_allele |
| 5 | +from ..constants import VALID_REDUCTION_TYPE |
| 6 | +from ..strategies.strategy_factory import StrategyFactory |
9 | 7 |
|
10 | 8 | if TYPE_CHECKING: |
11 | 9 | from ..ard import ARD |
12 | 10 |
|
13 | 11 |
|
14 | 12 | class AlleleReducer: |
15 | | - """Handles core allele reduction logic""" |
| 13 | + """Handles core allele reduction logic using Strategy Pattern""" |
16 | 14 |
|
17 | 15 | def __init__(self, ard_instance: "ARD"): |
18 | 16 | self.ard = ard_instance |
| 17 | + self.strategy_factory = StrategyFactory(ard_instance) |
19 | 18 |
|
20 | 19 | def reduce_allele( |
21 | | - self, allele: str, redux_type: VALID_REDUCTION_TYPES, re_ping=True |
| 20 | + self, allele: str, redux_type: VALID_REDUCTION_TYPE, re_ping=True |
22 | 21 | ) -> str: |
23 | | - """Core allele reduction logic extracted from _redux_allele""" |
24 | | - |
25 | | - if redux_type == "G" and allele in self.ard.ars_mappings.g_group: |
26 | | - if allele in self.ard.ars_mappings.dup_g: |
27 | | - return self.ard.ars_mappings.dup_g[allele] |
28 | | - else: |
29 | | - return self.ard.ars_mappings.g_group[allele] |
30 | | - |
31 | | - elif redux_type == "P" and allele in self.ard.ars_mappings.p_group: |
32 | | - return self.ard.ars_mappings.p_group[allele] |
33 | | - |
34 | | - elif redux_type in ["lgx", "lg"]: |
35 | | - if allele in self.ard.ars_mappings.lgx_group: |
36 | | - redux_allele = self.ard.ars_mappings.lgx_group[allele] |
37 | | - else: |
38 | | - redux_allele = ":".join(allele.split(":")[0:2]) |
39 | | - if redux_type == "lg": |
40 | | - return self._add_lg_suffix(redux_allele) |
41 | | - return redux_allele |
42 | | - |
43 | | - elif redux_type == "W": |
44 | | - if self.ard._is_who_allele(allele): |
45 | | - return allele |
46 | | - if allele in self.ard.code_mappings.who_group: |
47 | | - return self.ard.redux( |
48 | | - "/".join(self.ard.code_mappings.who_group[allele]), redux_type |
49 | | - ) |
50 | | - else: |
51 | | - return allele |
52 | | - |
53 | | - elif redux_type == "exon": |
54 | | - return self._handle_exon_reduction(allele) |
55 | | - |
56 | | - elif redux_type == "U2": |
57 | | - return self._handle_u2_reduction(allele) |
58 | | - |
59 | | - elif redux_type == "S": |
60 | | - return self._handle_serology_reduction(allele) |
61 | | - |
62 | | - else: |
63 | | - return self._handle_default_reduction(allele) |
| 22 | + """Core allele reduction logic using Strategy Pattern""" |
| 23 | + strategy = self.strategy_factory.get_strategy(redux_type) |
| 24 | + return strategy.reduce(allele) |
64 | 25 |
|
65 | 26 | def _add_lg_suffix(self, redux_allele): |
66 | | - """Add lg suffix to reduced allele""" |
| 27 | + """Add lg suffix to reduced allele - kept for backward compatibility""" |
67 | 28 | if "/" in redux_allele: |
68 | 29 | return "/".join( |
69 | 30 | [self._add_lg_suffix(allele) for allele in redux_allele.split("/")] |
70 | 31 | ) |
71 | 32 | if self.ard._config["ARS_as_lg"]: |
72 | 33 | return redux_allele + "ARS" |
73 | 34 | return redux_allele + "g" |
74 | | - |
75 | | - def _handle_exon_reduction(self, allele): |
76 | | - """Handle exon reduction type""" |
77 | | - if allele in self.ard.ars_mappings.exon_group: |
78 | | - exon_group_allele = self.ard.ars_mappings.exon_group[allele] |
79 | | - last_char = allele[-1] |
80 | | - if last_char in expression_chars: |
81 | | - exon_short_null_allele = exon_group_allele + last_char |
82 | | - if self.ard.is_shortnull(exon_short_null_allele): |
83 | | - return exon_short_null_allele |
84 | | - return exon_group_allele |
85 | | - else: |
86 | | - w_redux = self.ard.redux(allele, "W") |
87 | | - if w_redux == allele or len(w_redux.split(":")) == 2: |
88 | | - return allele |
89 | | - else: |
90 | | - return self.ard.redux(w_redux, "exon") |
91 | | - |
92 | | - def _handle_u2_reduction(self, allele): |
93 | | - """Handle U2 reduction type""" |
94 | | - allele_fields = allele.split(":") |
95 | | - if len(allele_fields) == 2: |
96 | | - return allele |
97 | | - allele_2_fields = get_n_field_allele(allele, 2, preserve_expression=True) |
98 | | - if self.ard._is_allele_in_db(allele_2_fields): |
99 | | - return allele_2_fields |
100 | | - else: |
101 | | - return self.reduce_allele(allele, "lgx") |
102 | | - |
103 | | - def _handle_serology_reduction(self, allele): |
104 | | - """Handle serology reduction type""" |
105 | | - from .. import db |
106 | | - from ..misc import is_2_field_allele |
107 | | - |
108 | | - if is_2_field_allele(allele): |
109 | | - allele = self.reduce_allele(allele, "lgx") |
110 | | - serology_mapping = db.find_serology_for_allele( |
111 | | - self.ard.db_connection, allele, "lgx_allele_list" |
112 | | - ) |
113 | | - else: |
114 | | - serology_mapping = db.find_serology_for_allele( |
115 | | - self.ard.db_connection, allele |
116 | | - ) |
117 | | - |
118 | | - serology_set = set() |
119 | | - for serology, allele_list in serology_mapping.items(): |
120 | | - if allele in allele_list.split("/"): |
121 | | - serology_set.add(serology) |
122 | | - |
123 | | - if not serology_set and is_2_field_allele(allele): |
124 | | - for serology, allele_list in serology_mapping.items(): |
125 | | - allele_list_lgx = self.ard.redux(allele_list, "lgx") |
126 | | - if allele in allele_list_lgx.split("/"): |
127 | | - serology_set.add(serology) |
128 | | - |
129 | | - return "/".join( |
130 | | - sorted( |
131 | | - serology_set, key=functools.cmp_to_key(self.ard.smart_sort_comparator) |
132 | | - ) |
133 | | - ) |
134 | | - |
135 | | - def _handle_default_reduction(self, allele): |
136 | | - """Handle default reduction cases""" |
137 | | - if allele.endswith("P"): |
138 | | - if allele in self.ard.ars_mappings.p_group.values(): |
139 | | - return allele |
140 | | - elif allele.endswith("G"): |
141 | | - if allele in self.ard.ars_mappings.g_group.values(): |
142 | | - return allele |
143 | | - |
144 | | - if self.ard._is_allele_in_db(allele): |
145 | | - return allele |
146 | | - else: |
147 | | - raise InvalidAlleleError(f"{allele} is an invalid allele.") |
0 commit comments