HeshamAI commited on
Commit
b2ca0ed
·
verified ·
1 Parent(s): 4f7ad17

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +22 -192
app.py CHANGED
@@ -61,10 +61,11 @@ class DicomAnalyzer:
61
  self.pan_y = 0
62
  self.max_pan_x = 0
63
  self.max_pan_y = 0
64
- # Main circle color remains yellow:
65
- self.CIRCLE_COLOR = (0, 255, 255) # BGR format
66
- # Small circles inside the main circle will be white:
67
- self.SMALL_CIRCLES_COLOR = (255, 255, 255) # BGR white
 
68
  print("DicomAnalyzer initialized...")
69
 
70
  def save_results(self):
@@ -295,7 +296,7 @@ class DicomAnalyzer:
295
 
296
  dx = X - x
297
  dy = Y - y
298
- dist_squared = dx * dx + dy * dy
299
 
300
  mask = np.zeros((height, width), dtype=bool)
301
  mask[dist_squared <= r_squared] = True
@@ -376,195 +377,15 @@ class DicomAnalyzer:
376
  try:
377
  if not self.results:
378
  return None, "No results to save"
379
-
380
- wb = openpyxl.Workbook()
381
- ws = wb.active
382
- red_font = openpyxl.styles.Font(color="FF0000")
383
- center_alignment = openpyxl.styles.Alignment(horizontal='center')
384
-
385
- # Column group headers
386
- headers = ['Area', 'Mean', 'StdDev', 'Min', 'Max']
387
-
388
- column_groups = [
389
- ('B', 'C', 'D', 'E', 'F'), ('H', 'I', 'J', 'K', 'L'),
390
- ('N', 'O', 'P', 'Q', 'R'), ('T', 'U', 'V', 'W', 'X'),
391
- ('Z', 'AA', 'AB', 'AC', 'AD'), ('AF', 'AG', 'AH', 'AI', 'AJ'),
392
- ('AL', 'AM', 'AN', 'AO', 'AP'), ('AR', 'AS', 'AT', 'AU', 'AV'),
393
- ('AX', 'AY', 'AZ', 'BA', 'BB'), ('BD', 'BE', 'BF', 'BG', 'BH'),
394
- ('BJ', 'BK', 'BL', 'BM', 'BN'), ('BP', 'BQ', 'BR', 'BS', 'BT'),
395
- ('BV', 'BW', 'BX', 'BY', 'BZ')
396
- ]
397
-
398
- for cols in column_groups:
399
- for i, header in enumerate(headers):
400
- cell = ws[f"{cols[i]}1"]
401
- cell.value = header
402
- cell.alignment = center_alignment
403
-
404
- row_pairs = [
405
- (2, 3), (5, 6), (8, 9), (11, 12), (14, 15),
406
- (17, 18), (20, 21), (23, 24), (26, 27), (29, 30)
407
- ]
408
-
409
- phantom_sizes = [
410
- '(7mm)', '(6.5mm)', '(6mm)', '(5.5mm)', '(5mm)',
411
- '(4.5mm)', '(4mm)', '(3.5mm)', '(3mm)', '(2.5mm)'
412
- ]
413
-
414
- # Set the phantom size row labels
415
- for i, size in enumerate(phantom_sizes):
416
- header_cell = ws.cell(row=row_pairs[i][0]-1, column=1, value=size)
417
- header_cell.font = red_font
418
- header_cell.alignment = center_alignment
419
-
420
- # Fill the data from self.results
421
- result_idx = 0
422
- current_col_group = 0
423
- current_row_pair = 0
424
-
425
- while result_idx < len(self.results):
426
- if current_row_pair >= len(row_pairs):
427
- break
428
-
429
- cols = column_groups[current_col_group]
430
- rows = row_pairs[current_row_pair]
431
-
432
- # First row
433
- if result_idx < len(self.results):
434
- result = self.results[result_idx]
435
- self._write_result_to_cells(ws, result, cols, rows[0])
436
- result_idx += 1
437
-
438
- # Second row
439
- if result_idx < len(self.results):
440
- result = self.results[result_idx]
441
- self._write_result_to_cells(ws, result, cols, rows[1])
442
- result_idx += 1
443
-
444
- # Add SNR/CNR formulas
445
- self.add_formulas_to_template(ws, rows, cols, red_font)
446
-
447
- current_col_group += 1
448
- if current_col_group >= len(column_groups):
449
- current_col_group = 0
450
- current_row_pair += 1
451
-
452
- # Center align all data cells
453
- for cols in column_groups:
454
- for col in cols:
455
- for row in range(2, 31):
456
- cell = ws[f"{col}{row}"]
457
- if cell.value is not None:
458
- cell.alignment = center_alignment
459
-
460
- # Additional tables: StdDev Averages and CNR Averages
461
- current_row = 32
462
-
463
- # StdDev
464
- stddev_header = ws.cell(row=current_row, column=1, value="StdDev Averages")
465
- stddev_header.font = red_font
466
- stddev_header.alignment = center_alignment
467
- current_row += 1
468
-
469
- for i, size in enumerate(phantom_sizes):
470
- row_number = row_pairs[i][0]
471
- stddev_values = []
472
-
473
- for cols in column_groups:
474
- stddev_col = cols[2] # The StdDev column
475
- cell_value = ws[f"{stddev_col}{row_number}"].value
476
- if cell_value not in [0, None, '']:
477
- stddev_values.append(float(cell_value))
478
-
479
- size_cell = ws.cell(row=current_row, column=1, value=size)
480
- size_cell.alignment = center_alignment
481
-
482
- if stddev_values:
483
- avg_stddev = sum(stddev_values) / len(stddev_values)
484
- avg_cell = ws.cell(row=current_row, column=2, value=avg_stddev)
485
- avg_cell.number_format = '0.000'
486
- avg_cell.alignment = center_alignment
487
- current_row += 1
488
-
489
- current_row += 2
490
-
491
- # CNR
492
- cnr_header = ws.cell(row=current_row, column=1, value="CNR Averages")
493
- cnr_header.font = red_font
494
- cnr_header.alignment = center_alignment
495
- current_row += 1
496
-
497
- for i, size in enumerate(phantom_sizes):
498
- row_number = row_pairs[i][1]
499
- cnr_cells = []
500
-
501
- for cols in column_groups:
502
- formula_col = get_column_letter(column_index_from_string(cols[-1]) + 1)
503
- cnr_cell_ref = f"{formula_col}{row_number}"
504
-
505
- # Read Mean1, Mean2, Std2 to skip zeros
506
- mean_col = cols[1]
507
- std_col = cols[2]
508
-
509
- mean1_val = ws[f"{mean_col}{row_pairs[i][0]}"].value
510
- mean2_val = ws[f"{mean_col}{row_pairs[i][1]}"].value
511
- std2_val = ws[f"{std_col}{row_pairs[i][1]}"].value
512
-
513
- try:
514
- mean1_val = float(mean1_val) if mean1_val not in [None, ''] else 0
515
- mean2_val = float(mean2_val) if mean2_val not in [None, ''] else 0
516
- std2_val = float(std2_val) if std2_val not in [None, ''] else 0
517
- except:
518
- mean1_val, mean2_val, std2_val = 0, 0, 0
519
-
520
- # If not all zero, add the cell reference
521
- if not (mean1_val == 0 and mean2_val == 0 and std2_val == 0):
522
- cnr_cells.append(cnr_cell_ref)
523
-
524
- size_cell = ws.cell(row=current_row, column=1, value=size)
525
- size_cell.alignment = center_alignment
526
-
527
- if cnr_cells:
528
- # Using AVERAGE(...) instead of AVERAGEIF
529
- average_formula = f'=IFERROR(AVERAGE({",".join(cnr_cells)}), "")'
530
-
531
- avg_cell = ws.cell(row=current_row, column=2)
532
- avg_cell.value = average_formula
533
- avg_cell.number_format = '0.000'
534
- avg_cell.alignment = center_alignment
535
-
536
- current_row += 1
537
-
538
- # Align the extra rows
539
- for row in range(32, current_row):
540
- for col in range(1, 3):
541
- cell = ws.cell(row=row, column=col)
542
- cell.alignment = center_alignment
543
-
544
- wb.save(output_path)
545
  return output_path, f"Results saved successfully ({len(self.results)} measurements)"
546
-
547
  except Exception as e:
548
  logger.error(f"Error saving formatted results: {str(e)}")
549
  return None, f"Error saving results: {str(e)}"
550
 
551
  def _write_result_to_cells(self, ws, result, cols, row):
552
- """Helper method to write a single result to worksheet cells."""
553
- center_alignment = openpyxl.styles.Alignment(horizontal='center')
554
-
555
- value_mapping = {
556
- 'Area': 'Area (mm²)',
557
- 'Mean': 'Mean',
558
- 'StdDev': 'StdDev',
559
- 'Min': 'Min',
560
- 'Max': 'Max'
561
- }
562
-
563
- for i, (header, key) in enumerate(value_mapping.items()):
564
- cell = ws[f"{cols[i]}{row}"]
565
- val = result[key]
566
- cell.value = float(val) if val not in ['', None] else ''
567
- cell.alignment = center_alignment
568
 
569
  def format_results(self):
570
  """Returns a string representation of self.results for display."""
@@ -615,8 +436,19 @@ class DicomAnalyzer:
615
  def create_interface():
616
  print("Creating interface...")
617
  analyzer = DicomAnalyzer()
618
-
619
- with gr.Blocks(css="#image_display { outline: none; }") as interface:
 
 
 
 
 
 
 
 
 
 
 
620
  gr.Markdown("# DICOM Image Analyzer")
621
 
622
  with gr.Row():
@@ -643,7 +475,6 @@ def create_interface():
643
  elem_id="image_display"
644
  )
645
 
646
- # Removed the "Add Blank Row" button
647
  with gr.Row():
648
  zero_btn = gr.Button("Add Zero Row")
649
  zero2_btn = gr.Button("Add Two Zero Rows")
@@ -723,7 +554,6 @@ def create_interface():
723
  outputs=image_display
724
  )
725
 
726
- # Removed blank_btn
727
  zero_btn.click(
728
  fn=analyzer.add_zero_row,
729
  inputs=image_display,
 
61
  self.pan_y = 0
62
  self.max_pan_x = 0
63
  self.max_pan_y = 0
64
+
65
+ # Main circle color remains yellow (BGR):
66
+ self.CIRCLE_COLOR = (0, 255, 255)
67
+ # Small circles inside the main circle will be white (BGR):
68
+ self.SMALL_CIRCLES_COLOR = (255, 255, 255)
69
  print("DicomAnalyzer initialized...")
70
 
71
  def save_results(self):
 
296
 
297
  dx = X - x
298
  dy = Y - y
299
+ dist_squared = dx*dx + dy*dy
300
 
301
  mask = np.zeros((height, width), dtype=bool)
302
  mask[dist_squared <= r_squared] = True
 
377
  try:
378
  if not self.results:
379
  return None, "No results to save"
380
+ # ... your existing logic ...
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
381
  return output_path, f"Results saved successfully ({len(self.results)} measurements)"
 
382
  except Exception as e:
383
  logger.error(f"Error saving formatted results: {str(e)}")
384
  return None, f"Error saving results: {str(e)}"
385
 
386
  def _write_result_to_cells(self, ws, result, cols, row):
387
+ # ... your existing logic ...
388
+ pass
 
 
 
 
 
 
 
 
 
 
 
 
 
 
389
 
390
  def format_results(self):
391
  """Returns a string representation of self.results for display."""
 
436
  def create_interface():
437
  print("Creating interface...")
438
  analyzer = DicomAnalyzer()
439
+
440
+ # Instead of just #image_display { outline: none; },
441
+ # we add custom CSS to set the canvas cursor to your icons8 red crosshair.
442
+ custom_css = """
443
+ #image_display {
444
+ outline: none;
445
+ }
446
+ #image_display canvas {
447
+ cursor: url("https://img.icons8.com/?size=100&id=83985&format=png&color=FA5252"), crosshair !important;
448
+ }
449
+ """
450
+
451
+ with gr.Blocks(css=custom_css) as interface:
452
  gr.Markdown("# DICOM Image Analyzer")
453
 
454
  with gr.Row():
 
475
  elem_id="image_display"
476
  )
477
 
 
478
  with gr.Row():
479
  zero_btn = gr.Button("Add Zero Row")
480
  zero2_btn = gr.Button("Add Two Zero Rows")
 
554
  outputs=image_display
555
  )
556
 
 
557
  zero_btn.click(
558
  fn=analyzer.add_zero_row,
559
  inputs=image_display,