Update app.py
Browse files
app.py
CHANGED
|
@@ -434,7 +434,7 @@ class DicomAnalyzer:
|
|
| 434 |
cell.alignment = center_alignment
|
| 435 |
|
| 436 |
#########################################################
|
| 437 |
-
#
|
| 438 |
#########################################################
|
| 439 |
start_row = 35
|
| 440 |
ws['C35'] = "1-AVG"
|
|
@@ -463,7 +463,6 @@ class DicomAnalyzer:
|
|
| 463 |
for i, size_label in enumerate(phantom_sizes2):
|
| 464 |
row = start_row + i + 1 # 36..45
|
| 465 |
|
| 466 |
-
# merge cells for each row (D-E, F-G, H-I)
|
| 467 |
ws.merge_cells(f'D{row}:E{row}')
|
| 468 |
ws.merge_cells(f'F{row}:G{row}')
|
| 469 |
ws.merge_cells(f'H{row}:I{row}')
|
|
@@ -473,73 +472,89 @@ class DicomAnalyzer:
|
|
| 473 |
c_cell.font = red_font
|
| 474 |
c_cell.alignment = center_alignment
|
| 475 |
|
| 476 |
-
# We'll read from row_pairs[i]: row1->(2,5,8..), row2->(3,6,9..)
|
| 477 |
if i >= len(row_pairs):
|
| 478 |
continue
|
| 479 |
(raw_row1, raw_row2) = row_pairs[i]
|
| 480 |
|
| 481 |
mean_values = []
|
| 482 |
stddev_values = []
|
| 483 |
-
cnr_cells = [] # We'll
|
| 484 |
|
| 485 |
-
#
|
| 486 |
-
# plus the CNR formula in row2.
|
| 487 |
for group in column_groups:
|
| 488 |
mean_col = group[1] # e.g. 'C'
|
| 489 |
std_col = group[2] # e.g. 'D'
|
| 490 |
|
|
|
|
| 491 |
m1_val = ws[f"{mean_col}{raw_row1}"].value
|
| 492 |
-
|
| 493 |
-
|
| 494 |
-
|
| 495 |
-
|
| 496 |
-
|
| 497 |
-
|
| 498 |
-
|
| 499 |
-
|
| 500 |
-
|
| 501 |
-
|
| 502 |
-
|
| 503 |
-
|
| 504 |
-
|
| 505 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 506 |
formula_col = get_column_letter(column_index_from_string(group[-1]) + 1)
|
| 507 |
cnr_cell_ref = f"{formula_col}{raw_row2}"
|
| 508 |
|
| 509 |
-
#
|
|
|
|
|
|
|
|
|
|
| 510 |
try:
|
| 511 |
-
mean2_val =
|
| 512 |
-
std2_val =
|
| 513 |
-
|
| 514 |
-
mean2_val = float(mean2_val) if mean2_val not in [None,''] else 0
|
| 515 |
-
std2_val = float(std2_val) if std2_val not in [None,''] else 0
|
| 516 |
except:
|
| 517 |
-
mean2_val, std2_val =
|
| 518 |
-
|
| 519 |
-
if
|
| 520 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 521 |
cnr_cells.append(cnr_cell_ref)
|
| 522 |
|
| 523 |
-
#
|
| 524 |
final_mean = sum(mean_values)/len(mean_values) if mean_values else None
|
| 525 |
-
final_std = sum(stddev_values)/len(stddev_values) if stddev_values else None
|
| 526 |
-
|
| 527 |
-
# For CNR, we build a formula =AVERAGE(...) referencing all the row2 formula cells.
|
| 528 |
-
# But we'll do it as an Excel formula:
|
| 529 |
-
# e.g. =IFERROR(AVERAGE(G3, G6, ...),"")
|
| 530 |
-
|
| 531 |
if final_mean is not None:
|
| 532 |
ws[f'D{row}'].value = final_mean
|
| 533 |
ws[f'D{row}'].alignment = center_alignment
|
| 534 |
ws[f'D{row}'].number_format = '0.0000'
|
| 535 |
|
|
|
|
|
|
|
| 536 |
if final_std is not None:
|
| 537 |
ws[f'F{row}'].value = final_std
|
| 538 |
ws[f'F{row}'].alignment = center_alignment
|
| 539 |
ws[f'F{row}'].number_format = '0.0000'
|
| 540 |
|
|
|
|
| 541 |
if cnr_cells:
|
| 542 |
-
# create a formula for average of those CNR references.
|
| 543 |
formula_avg_cnr = f"=IFERROR(AVERAGE({','.join(cnr_cells)}),\"\")"
|
| 544 |
ws[f'H{row}'].value = formula_avg_cnr
|
| 545 |
ws[f'H{row}'].alignment = center_alignment
|
|
@@ -763,15 +778,15 @@ def create_interface():
|
|
| 763 |
js = """
|
| 764 |
<script>
|
| 765 |
document.addEventListener('keydown', function(e) {
|
| 766 |
-
if (['ArrowUp',
|
| 767 |
e.preventDefault();
|
| 768 |
-
const
|
| 769 |
-
if (
|
| 770 |
-
|
| 771 |
-
|
| 772 |
setTimeout(() => {
|
| 773 |
-
|
| 774 |
-
|
| 775 |
}, 100);
|
| 776 |
}
|
| 777 |
}
|
|
|
|
| 434 |
cell.alignment = center_alignment
|
| 435 |
|
| 436 |
#########################################################
|
| 437 |
+
# تصميم "1-AVG" في الصف 35، مع تجاهل الأصفار في الحساب
|
| 438 |
#########################################################
|
| 439 |
start_row = 35
|
| 440 |
ws['C35'] = "1-AVG"
|
|
|
|
| 463 |
for i, size_label in enumerate(phantom_sizes2):
|
| 464 |
row = start_row + i + 1 # 36..45
|
| 465 |
|
|
|
|
| 466 |
ws.merge_cells(f'D{row}:E{row}')
|
| 467 |
ws.merge_cells(f'F{row}:G{row}')
|
| 468 |
ws.merge_cells(f'H{row}:I{row}')
|
|
|
|
| 472 |
c_cell.font = red_font
|
| 473 |
c_cell.alignment = center_alignment
|
| 474 |
|
|
|
|
| 475 |
if i >= len(row_pairs):
|
| 476 |
continue
|
| 477 |
(raw_row1, raw_row2) = row_pairs[i]
|
| 478 |
|
| 479 |
mean_values = []
|
| 480 |
stddev_values = []
|
| 481 |
+
cnr_cells = [] # We'll store references to the row2 formula for CNR
|
| 482 |
|
| 483 |
+
# Loop over column_groups to gather Mean (row1), StdDev (row1), and CNR references (row2).
|
|
|
|
| 484 |
for group in column_groups:
|
| 485 |
mean_col = group[1] # e.g. 'C'
|
| 486 |
std_col = group[2] # e.g. 'D'
|
| 487 |
|
| 488 |
+
# Read mean from row1 => if 0 => skip.
|
| 489 |
m1_val = ws[f"{mean_col}{raw_row1}"].value
|
| 490 |
+
try:
|
| 491 |
+
m1_val = float(m1_val) if m1_val not in [None,''] else None
|
| 492 |
+
except:
|
| 493 |
+
m1_val = None
|
| 494 |
+
# تجاهل أي خلية = 0
|
| 495 |
+
if m1_val == 0:
|
| 496 |
+
m1_val = None
|
| 497 |
+
|
| 498 |
+
if m1_val is not None:
|
| 499 |
+
mean_values.append(m1_val)
|
| 500 |
+
|
| 501 |
+
# Read std from row1 => if 0 => skip.
|
| 502 |
+
s1_val = ws[f"{std_col}{raw_row1}"].value
|
| 503 |
+
try:
|
| 504 |
+
s1_val = float(s1_val) if s1_val not in [None,''] else None
|
| 505 |
+
except:
|
| 506 |
+
s1_val = None
|
| 507 |
+
if s1_val == 0:
|
| 508 |
+
s1_val = None
|
| 509 |
+
|
| 510 |
+
if s1_val is not None:
|
| 511 |
+
stddev_values.append(s1_val)
|
| 512 |
+
|
| 513 |
+
# For CNR, we have formula in the column after group[-1], row2.
|
| 514 |
formula_col = get_column_letter(column_index_from_string(group[-1]) + 1)
|
| 515 |
cnr_cell_ref = f"{formula_col}{raw_row2}"
|
| 516 |
|
| 517 |
+
# حتى لا نُدخل خلية الـCNR في الحساب إن كانت قيم الصف الثاني = 0
|
| 518 |
+
# مثلاً mean2=0 أو std2=0 => نعتبرها غير صالحة.
|
| 519 |
+
mean2_val = ws[f"{mean_col}{raw_row2}"].value
|
| 520 |
+
std2_val = ws[f"{std_col}{raw_row2}"].value
|
| 521 |
try:
|
| 522 |
+
mean2_val = float(mean2_val) if mean2_val not in [None,''] else None
|
| 523 |
+
std2_val = float(std2_val) if std2_val not in [None,''] else None
|
|
|
|
|
|
|
|
|
|
| 524 |
except:
|
| 525 |
+
mean2_val, std2_val = None, None
|
| 526 |
+
|
| 527 |
+
if mean2_val == 0:
|
| 528 |
+
mean2_val = None
|
| 529 |
+
if std2_val == 0:
|
| 530 |
+
std2_val = None
|
| 531 |
+
|
| 532 |
+
# لو عندك منطق إضافي: التحقق أن Mean1 !=0 أيضاً (m1_val)
|
| 533 |
+
# إذا أردت تجاهل الخلية إن كان m1_val=0...الخ.
|
| 534 |
+
# لكن عادة, تحسب CNR من Mean1,Mean2,Std2 => if any=0 => skip.
|
| 535 |
+
# نحسب Mean1 من نفس row1_col.
|
| 536 |
+
# m1_val = read it above, but we didn't store it if zero => might do it again.
|
| 537 |
+
|
| 538 |
+
# Decide if we require m1_val !=0 too? If so:
|
| 539 |
+
if (m1_val is not None) and (mean2_val is not None) and (std2_val is not None):
|
| 540 |
cnr_cells.append(cnr_cell_ref)
|
| 541 |
|
| 542 |
+
# حساب متوسط المين.
|
| 543 |
final_mean = sum(mean_values)/len(mean_values) if mean_values else None
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 544 |
if final_mean is not None:
|
| 545 |
ws[f'D{row}'].value = final_mean
|
| 546 |
ws[f'D{row}'].alignment = center_alignment
|
| 547 |
ws[f'D{row}'].number_format = '0.0000'
|
| 548 |
|
| 549 |
+
# حساب متوسط stddev
|
| 550 |
+
final_std = sum(stddev_values)/len(stddev_values) if stddev_values else None
|
| 551 |
if final_std is not None:
|
| 552 |
ws[f'F{row}'].value = final_std
|
| 553 |
ws[f'F{row}'].alignment = center_alignment
|
| 554 |
ws[f'F{row}'].number_format = '0.0000'
|
| 555 |
|
| 556 |
+
# أما الـCNR, فننشئ صيغة AVERAGE(...) لو عندنا cnr_cells.
|
| 557 |
if cnr_cells:
|
|
|
|
| 558 |
formula_avg_cnr = f"=IFERROR(AVERAGE({','.join(cnr_cells)}),\"\")"
|
| 559 |
ws[f'H{row}'].value = formula_avg_cnr
|
| 560 |
ws[f'H{row}'].alignment = center_alignment
|
|
|
|
| 778 |
js = """
|
| 779 |
<script>
|
| 780 |
document.addEventListener('keydown', function(e) {
|
| 781 |
+
if (['ArrowUp','ArrowDown','ArrowLeft','ArrowRight'].includes(e.key)) {
|
| 782 |
e.preventDefault();
|
| 783 |
+
const el = document.querySelector('#key_press textarea');
|
| 784 |
+
if (el) {
|
| 785 |
+
el.value = e.key;
|
| 786 |
+
el.dispatchEvent(new Event('input'));
|
| 787 |
setTimeout(() => {
|
| 788 |
+
el.value = '';
|
| 789 |
+
el.dispatchEvent(new Event('input'));
|
| 790 |
}, 100);
|
| 791 |
}
|
| 792 |
}
|