Upload app.py with huggingface_hub
Browse files
app.py
CHANGED
|
@@ -206,7 +206,7 @@ def get_confident_alleles(bead_results, bead_hla_map):
|
|
| 206 |
return ag
|
| 207 |
|
| 208 |
x6x8 = set()
|
| 209 |
-
not_x6x8 = set() # Rxn
|
| 210 |
for bid, r in bead_results.items():
|
| 211 |
hla = bead_hla_map.get(bid, {})
|
| 212 |
alleles = {_clean(a) for a in _parse_allele_list(hla.get('allele', ''))}
|
|
@@ -217,6 +217,54 @@ def get_confident_alleles(bead_results, bead_hla_map):
|
|
| 217 |
return x6x8 - not_x6x8
|
| 218 |
|
| 219 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 220 |
def _build_allele_to_sero(bead_hla_map):
|
| 221 |
"""從 bead map 建立 allele→sero 對照"""
|
| 222 |
mapping = {}
|
|
@@ -613,7 +661,10 @@ def parse_xls_file(raw_bytes):
|
|
| 613 |
br_dict = OrderedDict()
|
| 614 |
for b in beads_detail:
|
| 615 |
br_dict[b['bead']] = {'rxn': b['rxn']}
|
| 616 |
-
|
|
|
|
|
|
|
|
|
|
| 617 |
|
| 618 |
sero_mfi = build_sero_mfi_stats(beads_detail, confident, bead_map) if overall == 'Positive' else []
|
| 619 |
|
|
@@ -727,7 +778,10 @@ def full_analyze(csv_content, filename='upload.csv'):
|
|
| 727 |
br = analyze_sample(median_data[sname], nc_medians, bead_ids, bead_map)
|
| 728 |
pra6, pos6, tot = calculate_pra(br, 'X6')
|
| 729 |
overall = 'Positive' if pra6 > 0 else 'Negative'
|
| 730 |
-
|
|
|
|
|
|
|
|
|
|
| 731 |
|
| 732 |
# bead 明細
|
| 733 |
beads_detail = []
|
|
|
|
| 206 |
return ag
|
| 207 |
|
| 208 |
x6x8 = set()
|
| 209 |
+
not_x6x8 = set() # Rxn<6 全部
|
| 210 |
for bid, r in bead_results.items():
|
| 211 |
hla = bead_hla_map.get(bid, {})
|
| 212 |
alleles = {_clean(a) for a in _parse_allele_list(hla.get('allele', ''))}
|
|
|
|
| 217 |
return x6x8 - not_x6x8
|
| 218 |
|
| 219 |
|
| 220 |
+
def get_confident_alleles_pra2(bead_results, bead_hla_map, threshold=0.8):
|
| 221 |
+
"""
|
| 222 |
+
PRA2 專用:80% Rule + Gray Zone
|
| 223 |
+
Step 1: 有 X2/X1 → 硬性排除
|
| 224 |
+
Step 2: 只有 X4 → 80% rule(X6X8/total ≥ 80% 才列入)
|
| 225 |
+
"""
|
| 226 |
+
def _clean(ag):
|
| 227 |
+
ag = ag.split('/')[0]
|
| 228 |
+
ag = ag.split('=')[0]
|
| 229 |
+
return ag
|
| 230 |
+
|
| 231 |
+
# 收集每個 allele 在不同 Rxn 層級的 bead
|
| 232 |
+
allele_beads = {} # allele -> {'x6x8': set, 'x4': set, 'x2x1': set}
|
| 233 |
+
for bid, r in bead_results.items():
|
| 234 |
+
hla = bead_hla_map.get(bid, {})
|
| 235 |
+
alleles = {_clean(a) for a in _parse_allele_list(hla.get('allele', ''))}
|
| 236 |
+
for ag in alleles:
|
| 237 |
+
if ag not in allele_beads:
|
| 238 |
+
allele_beads[ag] = {'x6x8': set(), 'x4': set(), 'x2x1': set()}
|
| 239 |
+
if r['rxn'] >= 6:
|
| 240 |
+
allele_beads[ag]['x6x8'].add(bid)
|
| 241 |
+
elif r['rxn'] >= 4:
|
| 242 |
+
allele_beads[ag]['x4'].add(bid)
|
| 243 |
+
else:
|
| 244 |
+
allele_beads[ag]['x2x1'].add(bid)
|
| 245 |
+
|
| 246 |
+
confident = set()
|
| 247 |
+
for ag, levels in allele_beads.items():
|
| 248 |
+
# 必須有 X6/X8
|
| 249 |
+
if not levels['x6x8']:
|
| 250 |
+
continue
|
| 251 |
+
# Step 1: 有 X2/X1 → 硬性排除
|
| 252 |
+
if levels['x2x1']:
|
| 253 |
+
continue
|
| 254 |
+
# Step 2: 只有 X4 → 80% rule
|
| 255 |
+
if levels['x4']:
|
| 256 |
+
total = len(levels['x6x8']) + len(levels['x4'])
|
| 257 |
+
ratio = len(levels['x6x8']) / total
|
| 258 |
+
if ratio >= threshold:
|
| 259 |
+
confident.add(ag) # X4 調整為 Positive
|
| 260 |
+
# else: < 80% → 排除
|
| 261 |
+
else:
|
| 262 |
+
# 全部都是 X6/X8,直接列入
|
| 263 |
+
confident.add(ag)
|
| 264 |
+
|
| 265 |
+
return confident
|
| 266 |
+
|
| 267 |
+
|
| 268 |
def _build_allele_to_sero(bead_hla_map):
|
| 269 |
"""從 bead map 建立 allele→sero 對照"""
|
| 270 |
mapping = {}
|
|
|
|
| 661 |
br_dict = OrderedDict()
|
| 662 |
for b in beads_detail:
|
| 663 |
br_dict[b['bead']] = {'rxn': b['rxn']}
|
| 664 |
+
if pra_class == 'PRA2':
|
| 665 |
+
confident = get_confident_alleles_pra2(br_dict, bead_map)
|
| 666 |
+
else:
|
| 667 |
+
confident = get_confident_alleles(br_dict, bead_map)
|
| 668 |
|
| 669 |
sero_mfi = build_sero_mfi_stats(beads_detail, confident, bead_map) if overall == 'Positive' else []
|
| 670 |
|
|
|
|
| 778 |
br = analyze_sample(median_data[sname], nc_medians, bead_ids, bead_map)
|
| 779 |
pra6, pos6, tot = calculate_pra(br, 'X6')
|
| 780 |
overall = 'Positive' if pra6 > 0 else 'Negative'
|
| 781 |
+
if pra_class == 'PRA2':
|
| 782 |
+
confident = get_confident_alleles_pra2(br, bead_map)
|
| 783 |
+
else:
|
| 784 |
+
confident = get_confident_alleles(br, bead_map)
|
| 785 |
|
| 786 |
# bead 明細
|
| 787 |
beads_detail = []
|