HeshamAI commited on
Commit
6446c42
·
verified ·
1 Parent(s): 6492534

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +126 -177
app.py CHANGED
@@ -65,6 +65,14 @@ class DicomAnalyzer:
65
  self.SMALL_CIRCLES_COLOR = (255, 255, 255) # BGR white
66
  print("DicomAnalyzer initialized...")
67
 
 
 
 
 
 
 
 
 
68
  def save_results(self):
69
  try:
70
  if not self.results:
@@ -133,6 +141,7 @@ class DicomAnalyzer:
133
  except Exception as e:
134
  print(f"Error loading DICOM file: {str(e)}")
135
  return None, f"Error loading DICOM file: {str(e)}"
 
136
  def normalize_image(self, image):
137
  try:
138
  normalized = cv2.normalize(
@@ -319,6 +328,11 @@ class DicomAnalyzer:
319
  except Exception as e:
320
  print(f"Error analyzing ROI: {str(e)}")
321
  return self.display_image, f"Error analyzing ROI: {str(e)}"
 
 
 
 
 
322
  def add_formulas_to_template(self, ws, row_pair, col_group, red_font):
323
  """
324
  Inserts SNR (first row) and CNR (second row) formulas with IFERROR.
@@ -348,6 +362,27 @@ class DicomAnalyzer:
348
  except Exception as e:
349
  logger.error(f"Error adding formulas: {str(e)}")
350
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
351
  def save_formatted_results(self, output_path):
352
  try:
353
  if not self.results:
@@ -355,203 +390,117 @@ class DicomAnalyzer:
355
 
356
  wb = openpyxl.Workbook()
357
  ws = wb.active
 
 
358
  red_font = openpyxl.styles.Font(color="FF0000")
359
- center_alignment = openpyxl.styles.Alignment(horizontal='center')
360
-
361
- headers = ['Area', 'Mean', 'StdDev', 'Min', 'Max']
362
-
363
- column_groups = [
364
- ('B', 'C', 'D', 'E', 'F'), ('H', 'I', 'J', 'K', 'L'),
365
- ('N', 'O', 'P', 'Q', 'R'), ('T', 'U', 'V', 'W', 'X'),
366
- ('Z', 'AA', 'AB', 'AC', 'AD'), ('AF', 'AG', 'AH', 'AI', 'AJ'),
367
- ('AL', 'AM', 'AN', 'AO', 'AP'), ('AR', 'AS', 'AT', 'AU', 'AV'),
368
- ('AX', 'AY', 'AZ', 'BA', 'BB'), ('BD', 'BE', 'BF', 'BG', 'BH'),
369
- ('BJ', 'BK', 'BL', 'BM', 'BN'), ('BP', 'BQ', 'BR', 'BS', 'BT'),
370
- ('BV', 'BW', 'BX', 'BY', 'BZ')
371
- ]
372
-
373
- for cols in column_groups:
374
- for i, header in enumerate(headers):
375
- cell = ws[f"{cols[i]}1"]
376
- cell.value = header
377
- cell.alignment = center_alignment
378
-
379
- row_pairs = [
380
- (2, 3), (5, 6), (8, 9), (11, 12), (14, 15),
381
- (17, 18), (20, 21), (23, 24), (26, 27), (29, 30)
382
- ]
383
-
 
384
  phantom_sizes = [
385
- '(7mm)', '(6.5mm)', '(6mm)', '(5.5mm)', '(5mm)',
386
- '(4.5mm)', '(4mm)', '(3.5mm)', '(3mm)', '(2.5mm)'
387
  ]
388
 
389
  for i, size in enumerate(phantom_sizes):
390
- header_cell = ws.cell(row=row_pairs[i][0]-1, column=1, value=size)
391
- header_cell.font = red_font
392
- header_cell.alignment = center_alignment
393
-
394
- result_idx = 0
395
- current_col_group = 0
396
- current_row_pair = 0
397
-
398
- while result_idx < len(self.results):
399
- if current_row_pair >= len(row_pairs):
400
- break
401
-
402
- cols = column_groups[current_col_group]
403
- rows = row_pairs[current_row_pair]
404
-
405
- if result_idx < len(self.results):
406
- result = self.results[result_idx]
407
- self._write_result_to_cells(ws, result, cols, rows[0])
408
- result_idx += 1
409
-
410
- if result_idx < len(self.results):
411
- result = self.results[result_idx]
412
- self._write_result_to_cells(ws, result, cols, rows[1])
413
- result_idx += 1
414
 
415
- self.add_formulas_to_template(ws, rows, cols, red_font)
 
 
 
416
 
417
- current_col_group += 1
418
- if current_col_group >= len(column_groups):
419
- current_col_group = 0
420
- current_row_pair += 1
421
-
422
- for cols in column_groups:
423
- for col in cols:
424
- for row in range(2, 31):
425
- cell = ws[f"{col}{row}"]
426
- if cell.value is not None:
427
- cell.alignment = center_alignment
428
- # StdDev Averages
429
- current_row = 32
430
- stddev_header = ws.cell(row=current_row, column=1, value="StdDev Averages")
431
- stddev_header.font = red_font
432
- stddev_header.alignment = center_alignment
433
- current_row += 1
434
-
435
- for i, size in enumerate(phantom_sizes):
436
- row_number = row_pairs[i][0]
437
- stddev_values = []
438
-
439
- for cols in column_groups:
440
- stddev_col = cols[2]
441
- cell_value = ws[f"{stddev_col}{row_number}"].value
442
- if cell_value not in [0, None, '']:
443
- stddev_values.append(float(cell_value))
444
 
445
- size_cell = ws.cell(row=current_row, column=1, value=size)
446
- size_cell.alignment = center_alignment
447
-
448
- if stddev_values:
449
- avg_stddev = sum(stddev_values) / len(stddev_values)
450
- avg_cell = ws.cell(row=current_row, column=2, value=avg_stddev)
451
- avg_cell.number_format = '0.000'
452
- avg_cell.alignment = center_alignment
453
- current_row += 1
454
-
455
- # Mean Averages
456
- current_row += 2
457
- mean_header = ws.cell(row=current_row, column=1, value="Mean Averages")
458
- mean_header.font = red_font
459
- mean_header.alignment = center_alignment
460
- current_row += 1
461
-
462
- for i, size in enumerate(phantom_sizes):
463
- row_number = row_pairs[i][0] # نأخذ الصف الأول فقط
464
  mean_values = []
 
 
465
 
466
- for cols in column_groups:
467
- mean_col = cols[1] # The Mean column
468
- cell_value = ws[f"{mean_col}{row_number}"].value
469
- if cell_value not in [0, None, '']:
470
- mean_values.append(float(cell_value))
471
 
472
- size_cell = ws.cell(row=current_row, column=1, value=size)
473
- size_cell.alignment = center_alignment
474
-
475
- if mean_values:
476
- avg_mean = sum(mean_values) / len(mean_values)
477
- avg_cell = ws.cell(row=current_row, column=2, value=avg_mean)
478
- avg_cell.number_format = '0.000'
479
- avg_cell.alignment = center_alignment
480
- current_row += 1
481
-
482
- current_row += 2
483
-
484
- # CNR Averages
485
- cnr_header = ws.cell(row=current_row, column=1, value="CNR Averages")
486
- cnr_header.font = red_font
487
- cnr_header.alignment = center_alignment
488
- current_row += 1
489
-
490
- for i, size in enumerate(phantom_sizes):
491
- row_number = row_pairs[i][1]
492
- cnr_cells = []
493
-
494
- for cols in column_groups:
495
- formula_col = get_column_letter(column_index_from_string(cols[-1]) + 1)
496
- cnr_cell_ref = f"{formula_col}{row_number}"
497
-
498
  mean_col = cols[1]
499
- std_col = cols[2]
 
 
 
 
500
 
501
- mean1_val = ws[f"{mean_col}{row_pairs[i][0]}"].value
502
- mean2_val = ws[f"{mean_col}{row_pairs[i][1]}"].value
503
- std2_val = ws[f"{std_col}{row_pairs[i][1]}"].value
504
-
505
  try:
506
- mean1_val = float(mean1_val) if mean1_val not in [None, ''] else 0
507
- mean2_val = float(mean2_val) if mean2_val not in [None, ''] else 0
508
- std2_val = float(std2_val) if std2_val not in [None, ''] else 0
509
- except:
510
- mean1_val, mean2_val, std2_val = 0, 0, 0
511
-
512
- if not (mean1_val == 0 and mean2_val == 0 and std2_val == 0):
513
- cnr_cells.append(cnr_cell_ref)
 
 
514
 
515
- size_cell = ws.cell(row=current_row, column=1, value=size)
516
- size_cell.alignment = center_alignment
517
-
518
- if cnr_cells:
519
- average_formula = f'=IFERROR(AVERAGE({",".join(cnr_cells)}), "")'
520
- avg_cell = ws.cell(row=current_row, column=2)
521
- avg_cell.value = average_formula
522
- avg_cell.number_format = '0.000'
523
- avg_cell.alignment = center_alignment
524
 
525
- current_row += 1
526
-
527
- for row in range(32, current_row):
528
- for col in range(1, 3):
529
- cell = ws.cell(row=row, column=col)
530
- cell.alignment = center_alignment
531
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
532
  wb.save(output_path)
533
- return output_path, f"Results saved successfully ({len(self.results)} measurements)"
534
-
535
  except Exception as e:
536
  logger.error(f"Error saving formatted results: {str(e)}")
537
  return None, f"Error saving results: {str(e)}"
538
 
539
- def _write_result_to_cells(self, ws, result, cols, row):
540
- center_alignment = openpyxl.styles.Alignment(horizontal='center')
541
-
542
- value_mapping = {
543
- 'Area': 'Area (mm²)',
544
- 'Mean': 'Mean',
545
- 'StdDev': 'StdDev',
546
- 'Min': 'Min',
547
- 'Max': 'Max'
548
- }
549
-
550
- for i, (header, key) in enumerate(value_mapping.items()):
551
- cell = ws[f"{cols[i]}{row}"]
552
- val = result[key]
553
- cell.value = float(val) if val not in ['', None] else ''
554
- cell.alignment = center_alignment
555
 
556
  def format_results(self):
557
  if not self.results:
@@ -781,4 +730,4 @@ if __name__ == "__main__":
781
  print(f"Error launching application: {str(e)}")
782
  logger.error(f"Error launching application: {str(e)}")
783
  logger.error(traceback.format_exc())
784
- raise e
 
65
  self.SMALL_CIRCLES_COLOR = (255, 255, 255) # BGR white
66
  print("DicomAnalyzer initialized...")
67
 
68
+ # If you rely on self.column_groups in your new snippet, define it here:
69
+ # Adjust the column letters to match how your raw (Mean, StdDev) data are actually laid out.
70
+ self.column_groups = [
71
+ # Example: (AreaCol, MeanCol, StdDevCol) if you store area in B, mean in C, std in D, etc.
72
+ # If you only store mean & std, just treat the first col as a placeholder.
73
+ ('B','C','D'),
74
+ ]
75
+
76
  def save_results(self):
77
  try:
78
  if not self.results:
 
141
  except Exception as e:
142
  print(f"Error loading DICOM file: {str(e)}")
143
  return None, f"Error loading DICOM file: {str(e)}"
144
+
145
  def normalize_image(self, image):
146
  try:
147
  normalized = cv2.normalize(
 
328
  except Exception as e:
329
  print(f"Error analyzing ROI: {str(e)}")
330
  return self.display_image, f"Error analyzing ROI: {str(e)}"
331
+
332
+ # -------------------------------------------------------------------
333
+ # The following two helper methods were in your original code.
334
+ # We keep them, in case you still need them. Adjust or remove if needed.
335
+ # -------------------------------------------------------------------
336
  def add_formulas_to_template(self, ws, row_pair, col_group, red_font):
337
  """
338
  Inserts SNR (first row) and CNR (second row) formulas with IFERROR.
 
362
  except Exception as e:
363
  logger.error(f"Error adding formulas: {str(e)}")
364
 
365
+ def _write_result_to_cells(self, ws, result, cols, row):
366
+ center_alignment = openpyxl.styles.Alignment(horizontal='center')
367
+
368
+ value_mapping = {
369
+ 'Area': 'Area (mm²)',
370
+ 'Mean': 'Mean',
371
+ 'StdDev': 'StdDev',
372
+ 'Min': 'Min',
373
+ 'Max': 'Max'
374
+ }
375
+
376
+ for i, (header, key) in enumerate(value_mapping.items()):
377
+ cell = ws[f"{cols[i]}{row}"]
378
+ val = result[key]
379
+ cell.value = float(val) if val not in ['', None] else ''
380
+ cell.alignment = center_alignment
381
+
382
+
383
+ # -------------------------------------------------------------------
384
+ # REPLACEMENT SAVE_FORMATTED_RESULTS (Your updated snippet):
385
+ # -------------------------------------------------------------------
386
  def save_formatted_results(self, output_path):
387
  try:
388
  if not self.results:
 
390
 
391
  wb = openpyxl.Workbook()
392
  ws = wb.active
393
+
394
+ # Define styles
395
  red_font = openpyxl.styles.Font(color="FF0000")
396
+ center_alignment = openpyxl.styles.Alignment(horizontal='center', vertical='center')
397
+
398
+ # Start creating the averages table at row 35
399
+ start_row = 35
400
+
401
+ # Write the "1-AVG" header
402
+ ws['C35'] = "1-AVG"
403
+ ws['C35'].alignment = center_alignment
404
+
405
+ # Merge cells for headers and add titles
406
+ ws.merge_cells('D35:E35')
407
+ ws.merge_cells('F35:G35')
408
+ ws.merge_cells('H35:I35')
409
+
410
+ headers = {
411
+ 'D35': 'AVG MEAN',
412
+ 'F35': 'AVG STDDEV',
413
+ 'H35': 'AVG CNR'
414
+ }
415
+
416
+ for cell, value in headers.items():
417
+ ws[cell] = value
418
+ ws[cell].alignment = center_alignment
419
+ ws[cell].font = red_font
420
+
421
+ # Add phantom sizes in red
422
  phantom_sizes = [
423
+ '(7.0mm)', '(6.5mm)', '(6.0mm)', '(5.5mm)', '(5.0mm)',
424
+ '(4.5mm)', '(4.0mm)', '(3.5mm)', '(3.0mm)', '(2.5mm)'
425
  ]
426
 
427
  for i, size in enumerate(phantom_sizes):
428
+ row = start_row + i + 1 # Start from row 36
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
429
 
430
+ # Merge cells for each row
431
+ ws.merge_cells(f'D{row}:E{row}')
432
+ ws.merge_cells(f'F{row}:G{row}')
433
+ ws.merge_cells(f'H{row}:I{row}')
434
 
435
+ cell = ws[f'C{row}"]
436
+ cell.value = size
437
+ cell.font = red_font
438
+ cell.alignment = center_alignment
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
439
 
440
+ # Calculate averages as before
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
441
  mean_values = []
442
+ stddev_values = []
443
+ cnr_values = []
444
 
445
+ # For example, row_pair = (2 + i*3, 3 + i*3).
446
+ row_pair = (2 + i * 3, 3 + i * 3)
 
 
 
447
 
448
+ for cols in self.column_groups:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
449
  mean_col = cols[1]
450
+ stddev_col = cols[2]
451
+
452
+ mean1_val = ws[f"{mean_col}{row_pair[0]}"].value
453
+ mean2_val = ws[f"{mean_col}{row_pair[1]}"].value
454
+ stddev2_val = ws[f"{stddev_col}{row_pair[1]}"].value
455
 
 
 
 
 
456
  try:
457
+ mean1_val = float(mean1_val) if mean1_val not in [None, ''] else None
458
+ mean2_val = float(mean2_val) if mean2_val not in [None, ''] else None
459
+ stddev2_val = float(stddev2_val) if stddev2_val not in [None, ''] else None
460
+
461
+ if all(v is not None for v in [mean1_val, mean2_val, stddev2_val]):
462
+ mean_values.append(mean1_val)
463
+ stddev_values.append(stddev2_val)
464
+ cnr_values.append((mean1_val - mean2_val) / stddev2_val)
465
+ except (ValueError, TypeError):
466
+ continue
467
 
468
+ # Write averages to merged cells
469
+ if mean_values:
470
+ ws[f'D{row}'].value = sum(mean_values) / len(mean_values)
471
+ ws[f'D{row}'].alignment = center_alignment
472
+ ws[f'D{row}'].number_format = '0.0000'
 
 
 
 
473
 
474
+ if stddev_values:
475
+ ws[f'F{row}'].value = sum(stddev_values) / len(stddev_values)
476
+ ws[f'F{row}'].alignment = center_alignment
477
+ ws[f'F{row}'].number_format = '0.0000'
478
+
479
+ if cnr_values:
480
+ ws[f'H{row}'].value = sum(cnr_values) / len(cnr_values)
481
+ ws[f'H{row}'].alignment = center_alignment
482
+ ws[f'H{row}'].number_format = '0.0000'
483
+
484
+ # Add borders to the table including merged cells
485
+ border = openpyxl.styles.Border(
486
+ left=openpyxl.styles.Side(style='thin'),
487
+ right=openpyxl.styles.Side(style='thin'),
488
+ top=openpyxl.styles.Side(style='thin'),
489
+ bottom=openpyxl.styles.Side(style='thin')
490
+ )
491
+
492
+ for row in range(35, 46): # From row 35 to 45
493
+ for col in ['C', 'D', 'E', 'F', 'G', 'H', 'I']:
494
+ ws[f'{col}{row}'].border = border
495
+
496
+ # Save the workbook
497
  wb.save(output_path)
498
+ return output_path, "Results saved successfully with formatted averages table"
499
+
500
  except Exception as e:
501
  logger.error(f"Error saving formatted results: {str(e)}")
502
  return None, f"Error saving results: {str(e)}"
503
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
504
 
505
  def format_results(self):
506
  if not self.results:
 
730
  print(f"Error launching application: {str(e)}")
731
  logger.error(f"Error launching application: {str(e)}")
732
  logger.error(traceback.format_exc())
733
+ raise e