HeshamAI commited on
Commit
d34f7dd
·
verified ·
1 Parent(s): b9e0532

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +253 -243
app.py CHANGED
@@ -115,6 +115,7 @@ class DicomAnalyzer:
115
  except Exception as e:
116
  print(f"Error normalizing image: {str(e)}")
117
  return None
 
118
  def reset_view(self):
119
  self.zoom_factor = 1.0
120
  self.pan_x = 0
@@ -229,8 +230,11 @@ class DicomAnalyzer:
229
  new_height = int(height * self.zoom_factor)
230
  new_width = int(width * self.zoom_factor)
231
 
232
- zoomed = cv2.resize(self.original_display, (new_width, new_height),
233
- interpolation=cv2.INTER_CUBIC)
 
 
 
234
 
235
  zoomed_bgr = cv2.cvtColor(zoomed, cv2.COLOR_RGB2BGR)
236
 
@@ -239,24 +243,28 @@ class DicomAnalyzer:
239
  zoomed_y = int(y * self.zoom_factor)
240
  zoomed_radius = int((diameter/2.0) * self.zoom_factor)
241
 
242
- cv2.circle(zoomed_bgr,
243
- (zoomed_x, zoomed_y),
244
- zoomed_radius,
245
- self.CIRCLE_COLOR,
246
- 1,
247
- lineType=cv2.LINE_AA)
 
 
248
 
249
  num_points = 8
250
  for i in range(num_points):
251
  angle = 2 * np.pi * i / num_points
252
  point_x = int(zoomed_x + zoomed_radius * np.cos(angle))
253
  point_y = int(zoomed_y + zoomed_radius * np.sin(angle))
254
- cv2.circle(zoomed_bgr,
255
- (point_x, point_y),
256
- 1,
257
- self.CIRCLE_COLOR,
258
- -1,
259
- lineType=cv2.LINE_AA)
 
 
260
 
261
  zoomed = cv2.cvtColor(zoomed_bgr, cv2.COLOR_BGR2RGB)
262
 
@@ -310,6 +318,7 @@ class DicomAnalyzer:
310
  logger.error(error_msg)
311
  logger.error(traceback.format_exc())
312
  return None, error_msg
 
313
  def add_formulas_to_template(self, ws, row_pair, col_group, red_font):
314
  try:
315
  base_col = col_group[1] # Mean column
@@ -326,7 +335,10 @@ class DicomAnalyzer:
326
  cell1.alignment = openpyxl.styles.Alignment(horizontal='center')
327
 
328
  # CNR Formula for second row
329
- formula2 = f"=IF(OR({std_col}{row2}=0,{base_col}{row1}=0,{base_col}{row2}=0),0,({base_col}{row1}-{base_col}{row2})/{std_col}{row2})"
 
 
 
330
  cell2 = ws[f"{formula_col}{row2}"]
331
  cell2.value = formula2
332
  cell2.font = red_font
@@ -371,8 +383,10 @@ class DicomAnalyzer:
371
  (17, 18), (20, 21), (23, 24), (26, 27), (29, 30)
372
  ]
373
 
374
- phantom_sizes = ['(7mm)', '(6.5mm)', '(6mm)', '(5.5mm)', '(5mm)',
375
- '(4.5mm)', '(4mm)', '(3.5mm)', '(3mm)', '(2.5mm)']
 
 
376
 
377
  for i, size in enumerate(phantom_sizes):
378
  header_cell = ws.cell(row=row_pairs[i][0]-1, column=1, value=size)
@@ -424,15 +438,15 @@ class DicomAnalyzer:
424
  stddev_header.alignment = center_alignment
425
  current_row += 1
426
 
427
- # Calculate StdDev averages for each row pair
428
  for i, size in enumerate(phantom_sizes):
429
- row_number = row_pairs[i][0] # First row only
430
  stddev_values = []
431
 
432
  for cols in column_groups:
433
  stddev_col = cols[2] # StdDev column
434
  cell_value = ws[f"{stddev_col}{row_number}"].value
435
- if cell_value not in [0, None, '']: # Ignore zeros and empty values
436
  stddev_values.append(float(cell_value))
437
 
438
  if stddev_values:
@@ -453,7 +467,7 @@ class DicomAnalyzer:
453
  cnr_header.alignment = center_alignment
454
  current_row += 1
455
 
456
- # Calculate CNR averages for each row pair
457
  for i, size in enumerate(phantom_sizes):
458
  row_number = row_pairs[i][1] # Second row for CNR
459
  cnr_references = []
@@ -501,238 +515,234 @@ class DicomAnalyzer:
501
  logger.error(f"Error saving formatted results: {str(e)}")
502
  return None, f"Error saving results: {str(e)}"
503
 
504
- except Exception as e:
505
- logger.error(f"Error saving formatted results: {str(e)}")
506
- return None, f"Error saving results: {str(e)}"
507
 
508
- def _write_result_to_cells(self, ws, result, cols, row):
509
- """Helper method to write a single result to worksheet cells"""
510
- center_alignment = openpyxl.styles.Alignment(horizontal='center')
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
511
 
512
- # Map the headers to the result keys
513
- value_mapping = {
514
- 'Area': 'Area (mm²)',
515
- 'Mean': 'Mean',
516
- 'StdDev': 'StdDev',
517
- 'Min': 'Min',
518
- 'Max': 'Max'
519
- }
520
 
521
- for i, (header, key) in enumerate(value_mapping.items()):
522
- cell = ws[f"{cols[i]}{row}"]
523
- cell.value = float(result[key])
524
- cell.alignment = center_alignment
 
 
 
 
 
 
 
 
 
 
 
 
 
525
 
526
- def format_results(self):
527
- if not self.results:
528
- return "No measurements yet"
529
- df = pd.DataFrame(self.results)
530
- columns_order = ['Area (mm²)', 'Mean', 'StdDev', 'Min', 'Max', 'Point']
531
- df = df[columns_order]
532
- return df.to_string(index=False)
 
 
 
 
 
 
 
 
 
 
533
 
534
- def add_blank_row(self, image):
535
- self.results.append({
536
- 'Area (mm²)': '',
537
- 'Mean': '',
538
- 'StdDev': '',
539
- 'Min': '',
540
- 'Max': '',
541
- 'Point': ''
542
- })
543
- return image, self.format_results()
544
 
545
- def add_zero_row(self, image):
546
- self.results.append({
547
- 'Area (mm²)': '0.000',
548
- 'Mean': '0.000',
549
- 'StdDev': '0.000',
550
- 'Min': '0.000',
551
- 'Max': '0.000',
552
- 'Point': '(0, 0)'
553
- })
554
- return image, self.format_results()
555
 
556
- def undo_last(self, image):
557
- if self.results:
558
- self.results.pop()
559
- if self.marks:
560
- self.marks.pop()
561
- return self.update_display(), self.format_results()
562
 
563
- # Interface Creation and Main Execution
564
- def create_interface():
565
- print("Creating interface...")
566
- analyzer = DicomAnalyzer()
567
-
568
- with gr.Blocks(css="#image_display { outline: none; }") as interface:
569
- gr.Markdown("# DICOM Image Analyzer")
570
-
571
- with gr.Row():
572
- with gr.Column():
573
- file_input = gr.File(label="Upload DICOM file")
574
- diameter_slider = gr.Slider(
575
- minimum=1,
576
- maximum=20,
577
- value=9,
578
- step=1,
579
- label="ROI Diameter (pixels)"
580
- )
581
-
582
- with gr.Row():
583
- zoom_in_btn = gr.Button("Zoom In (+)")
584
- zoom_out_btn = gr.Button("Zoom Out (-)")
585
- reset_btn = gr.Button("Reset View")
586
- reset_all_btn = gr.Button("Reset All")
587
-
588
- with gr.Column():
589
- image_display = gr.Image(
590
- label="DICOM Image",
591
- interactive=True,
592
- elem_id="image_display"
593
- )
594
-
595
- with gr.Row():
596
- blank_btn = gr.Button("Add Blank Row")
597
- zero_btn = gr.Button("Add Zero Row")
598
- undo_btn = gr.Button("Undo Last")
599
- save_btn = gr.Button("Save Results")
600
- save_formatted_btn = gr.Button("Save Formatted Results")
601
-
602
- results_display = gr.Textbox(label="Results", interactive=False)
603
- file_output = gr.File(label="Download Results")
604
- key_press = gr.Textbox(visible=False, elem_id="key_press")
605
-
606
- gr.Markdown("""
607
- ### Controls:
608
- - Use arrow keys to pan when zoomed in
609
- - Click points to measure
610
- - Use Zoom In/Out buttons or Reset View to adjust zoom level
611
- - Use Reset All to clear all measurements
612
- - Save Formatted Results will create Excel file with formulas
613
- """)
614
-
615
- def update_diameter(x):
616
- analyzer.circle_diameter = float(x)
617
- print(f"Diameter updated to: {x}")
618
- return f"Diameter set to {x} pixels"
619
 
620
- def save_formatted():
621
- output_path = "analysis_results_formatted.xlsx"
622
- return analyzer.save_formatted_results(output_path)
 
 
 
623
 
624
- # Event handlers
625
- file_input.change(
626
- fn=analyzer.load_dicom,
627
- inputs=file_input,
628
- outputs=[image_display, results_display]
629
- )
630
-
631
- image_display.select(
632
- fn=analyzer.analyze_roi,
633
- outputs=[image_display, results_display]
634
- )
635
-
636
- diameter_slider.change(
637
- fn=update_diameter,
638
- inputs=diameter_slider,
639
- outputs=gr.Textbox(label="Status")
640
- )
641
-
642
- zoom_in_btn.click(
643
- fn=analyzer.zoom_in,
644
- inputs=image_display,
645
- outputs=image_display,
646
- queue=False
647
- )
648
-
649
- zoom_out_btn.click(
650
- fn=analyzer.zoom_out,
651
- inputs=image_display,
652
- outputs=image_display,
653
- queue=False
654
- )
655
-
656
- reset_btn.click(
657
- fn=analyzer.reset_view,
658
- outputs=image_display
659
- )
660
-
661
- reset_all_btn.click(
662
- fn=analyzer.reset_all,
663
- inputs=image_display,
664
- outputs=[image_display, results_display]
665
- )
666
-
667
- key_press.change(
668
- fn=analyzer.handle_keyboard,
669
- inputs=key_press,
670
- outputs=image_display
671
- )
672
-
673
- blank_btn.click(
674
- fn=analyzer.add_blank_row,
675
- inputs=image_display,
676
- outputs=[image_display, results_display]
677
- )
678
-
679
- zero_btn.click(
680
- fn=analyzer.add_zero_row,
681
- inputs=image_display,
682
- outputs=[image_display, results_display]
683
- )
684
-
685
- undo_btn.click(
686
- fn=analyzer.undo_last,
687
- inputs=image_display,
688
- outputs=[image_display, results_display]
689
- )
690
-
691
- save_btn.click(
692
- fn=analyzer.save_results,
693
- outputs=[file_output, results_display]
694
- )
695
 
696
- save_formatted_btn.click(
697
- fn=save_formatted,
698
- outputs=[file_output, results_display]
699
- )
 
700
 
701
- js = """
702
- <script>
703
- document.addEventListener('keydown', function(e) {
704
- if (['ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight'].includes(e.key)) {
705
- e.preventDefault();
706
- const keyPressElement = document.querySelector('#key_press textarea');
707
- if (keyPressElement) {
708
- keyPressElement.value = e.key;
709
- keyPressElement.dispatchEvent(new Event('input'));
710
- }
711
- }
712
- });
713
- </script>
714
- """
715
- gr.HTML(js)
716
-
717
- print("Interface created successfully")
718
- return interface
719
 
720
- if __name__ == "__main__":
721
- try:
722
- print("Starting application...")
723
- interface = create_interface()
724
- print("Launching interface...")
725
- interface.queue()
726
- interface.launch(
727
- server_name="0.0.0.0",
728
- server_port=7860,
729
- share=True,
730
- debug=True,
731
- show_error=True,
732
- quiet=False
733
- )
734
- except Exception as e:
735
- print(f"Error launching application: {str(e)}")
736
- logger.error(f"Error launching application: {str(e)}")
737
- logger.error(traceback.format_exc())
738
- raise e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
115
  except Exception as e:
116
  print(f"Error normalizing image: {str(e)}")
117
  return None
118
+
119
  def reset_view(self):
120
  self.zoom_factor = 1.0
121
  self.pan_x = 0
 
230
  new_height = int(height * self.zoom_factor)
231
  new_width = int(width * self.zoom_factor)
232
 
233
+ zoomed = cv2.resize(
234
+ self.original_display,
235
+ (new_width, new_height),
236
+ interpolation=cv2.INTER_CUBIC
237
+ )
238
 
239
  zoomed_bgr = cv2.cvtColor(zoomed, cv2.COLOR_RGB2BGR)
240
 
 
243
  zoomed_y = int(y * self.zoom_factor)
244
  zoomed_radius = int((diameter/2.0) * self.zoom_factor)
245
 
246
+ cv2.circle(
247
+ zoomed_bgr,
248
+ (zoomed_x, zoomed_y),
249
+ zoomed_radius,
250
+ self.CIRCLE_COLOR,
251
+ 1,
252
+ lineType=cv2.LINE_AA
253
+ )
254
 
255
  num_points = 8
256
  for i in range(num_points):
257
  angle = 2 * np.pi * i / num_points
258
  point_x = int(zoomed_x + zoomed_radius * np.cos(angle))
259
  point_y = int(zoomed_y + zoomed_radius * np.sin(angle))
260
+ cv2.circle(
261
+ zoomed_bgr,
262
+ (point_x, point_y),
263
+ 1,
264
+ self.CIRCLE_COLOR,
265
+ -1,
266
+ lineType=cv2.LINE_AA
267
+ )
268
 
269
  zoomed = cv2.cvtColor(zoomed_bgr, cv2.COLOR_BGR2RGB)
270
 
 
318
  logger.error(error_msg)
319
  logger.error(traceback.format_exc())
320
  return None, error_msg
321
+
322
  def add_formulas_to_template(self, ws, row_pair, col_group, red_font):
323
  try:
324
  base_col = col_group[1] # Mean column
 
335
  cell1.alignment = openpyxl.styles.Alignment(horizontal='center')
336
 
337
  # CNR Formula for second row
338
+ formula2 = (
339
+ f"=IF(OR({std_col}{row2}=0,{base_col}{row1}=0,{base_col}{row2}=0),"
340
+ f"0,({base_col}{row1}-{base_col}{row2})/{std_col}{row2})"
341
+ )
342
  cell2 = ws[f"{formula_col}{row2}"]
343
  cell2.value = formula2
344
  cell2.font = red_font
 
383
  (17, 18), (20, 21), (23, 24), (26, 27), (29, 30)
384
  ]
385
 
386
+ phantom_sizes = [
387
+ '(7mm)', '(6.5mm)', '(6mm)', '(5.5mm)', '(5mm)',
388
+ '(4.5mm)', '(4mm)', '(3.5mm)', '(3mm)', '(2.5mm)'
389
+ ]
390
 
391
  for i, size in enumerate(phantom_sizes):
392
  header_cell = ws.cell(row=row_pairs[i][0]-1, column=1, value=size)
 
438
  stddev_header.alignment = center_alignment
439
  current_row += 1
440
 
441
+ # Calculate StdDev averages for each row pair (first row only)
442
  for i, size in enumerate(phantom_sizes):
443
+ row_number = row_pairs[i][0] # First row
444
  stddev_values = []
445
 
446
  for cols in column_groups:
447
  stddev_col = cols[2] # StdDev column
448
  cell_value = ws[f"{stddev_col}{row_number}"].value
449
+ if cell_value not in [0, None, '']: # Ignore zeros and empty
450
  stddev_values.append(float(cell_value))
451
 
452
  if stddev_values:
 
467
  cnr_header.alignment = center_alignment
468
  current_row += 1
469
 
470
+ # Calculate CNR averages for each row pair (second row)
471
  for i, size in enumerate(phantom_sizes):
472
  row_number = row_pairs[i][1] # Second row for CNR
473
  cnr_references = []
 
515
  logger.error(f"Error saving formatted results: {str(e)}")
516
  return None, f"Error saving results: {str(e)}"
517
 
518
+ def _write_result_to_cells(self, ws, result, cols, row):
519
+ """Helper method to write a single result to worksheet cells"""
520
+ center_alignment = openpyxl.styles.Alignment(horizontal='center')
521
 
522
+ # Map the headers to the result keys
523
+ value_mapping = {
524
+ 'Area': 'Area (mm²)',
525
+ 'Mean': 'Mean',
526
+ 'StdDev': 'StdDev',
527
+ 'Min': 'Min',
528
+ 'Max': 'Max'
529
+ }
530
+
531
+ for i, (header, key) in enumerate(value_mapping.items()):
532
+ cell = ws[f"{cols[i]}{row}"]
533
+ cell.value = float(result[key])
534
+ cell.alignment = center_alignment
535
+
536
+ def format_results(self):
537
+ if not self.results:
538
+ return "No measurements yet"
539
+ df = pd.DataFrame(self.results)
540
+ columns_order = ['Area (mm²)', 'Mean', 'StdDev', 'Min', 'Max', 'Point']
541
+ df = df[columns_order]
542
+ return df.to_string(index=False)
543
+
544
+ def add_blank_row(self, image):
545
+ self.results.append({
546
+ 'Area (mm²)': '',
547
+ 'Mean': '',
548
+ 'StdDev': '',
549
+ 'Min': '',
550
+ 'Max': '',
551
+ 'Point': ''
552
+ })
553
+ return image, self.format_results()
554
+
555
+ def add_zero_row(self, image):
556
+ self.results.append({
557
+ 'Area (mm²)': '0.000',
558
+ 'Mean': '0.000',
559
+ 'StdDev': '0.000',
560
+ 'Min': '0.000',
561
+ 'Max': '0.000',
562
+ 'Point': '(0, 0)'
563
+ })
564
+ return image, self.format_results()
565
+
566
+ def undo_last(self, image):
567
+ if self.results:
568
+ self.results.pop()
569
+ if self.marks:
570
+ self.marks.pop()
571
+ return self.update_display(), self.format_results()
572
+
573
+ # Interface Creation and Main Execution
574
+ def create_interface():
575
+ print("Creating interface...")
576
+ analyzer = DicomAnalyzer()
577
+
578
+ with gr.Blocks(css="#image_display { outline: none; }") as interface:
579
+ gr.Markdown("# DICOM Image Analyzer")
580
+
581
+ with gr.Row():
582
+ with gr.Column():
583
+ file_input = gr.File(label="Upload DICOM file")
584
+ diameter_slider = gr.Slider(
585
+ minimum=1,
586
+ maximum=20,
587
+ value=9,
588
+ step=1,
589
+ label="ROI Diameter (pixels)"
590
+ )
591
 
592
+ with gr.Row():
593
+ zoom_in_btn = gr.Button("Zoom In (+)")
594
+ zoom_out_btn = gr.Button("Zoom Out (-)")
595
+ reset_btn = gr.Button("Reset View")
596
+ reset_all_btn = gr.Button("Reset All")
 
 
 
597
 
598
+ with gr.Column():
599
+ image_display = gr.Image(
600
+ label="DICOM Image",
601
+ interactive=True,
602
+ elem_id="image_display"
603
+ )
604
+
605
+ with gr.Row():
606
+ blank_btn = gr.Button("Add Blank Row")
607
+ zero_btn = gr.Button("Add Zero Row")
608
+ undo_btn = gr.Button("Undo Last")
609
+ save_btn = gr.Button("Save Results")
610
+ save_formatted_btn = gr.Button("Save Formatted Results")
611
+
612
+ results_display = gr.Textbox(label="Results", interactive=False)
613
+ file_output = gr.File(label="Download Results")
614
+ key_press = gr.Textbox(visible=False, elem_id="key_press")
615
 
616
+ gr.Markdown("""
617
+ ### Controls:
618
+ - Use arrow keys to pan when zoomed in
619
+ - Click points to measure
620
+ - Use Zoom In/Out buttons or Reset View to adjust zoom level
621
+ - Use Reset All to clear all measurements
622
+ - Save Formatted Results will create Excel file with formulas
623
+ """)
624
+
625
+ def update_diameter(x):
626
+ analyzer.circle_diameter = float(x)
627
+ print(f"Diameter updated to: {x}")
628
+ return f"Diameter set to {x} pixels"
629
+
630
+ def save_formatted():
631
+ output_path = "analysis_results_formatted.xlsx"
632
+ return analyzer.save_formatted_results(output_path)
633
 
634
+ # Event handlers
635
+ file_input.change(
636
+ fn=analyzer.load_dicom,
637
+ inputs=file_input,
638
+ outputs=[image_display, results_display]
639
+ )
 
 
 
 
640
 
641
+ image_display.select(
642
+ fn=analyzer.analyze_roi,
643
+ outputs=[image_display, results_display]
644
+ )
 
 
 
 
 
 
645
 
646
+ diameter_slider.change(
647
+ fn=update_diameter,
648
+ inputs=diameter_slider,
649
+ outputs=gr.Textbox(label="Status")
650
+ )
 
651
 
652
+ zoom_in_btn.click(
653
+ fn=analyzer.zoom_in,
654
+ inputs=image_display,
655
+ outputs=image_display,
656
+ queue=False
657
+ )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
658
 
659
+ zoom_out_btn.click(
660
+ fn=analyzer.zoom_out,
661
+ inputs=image_display,
662
+ outputs=image_display,
663
+ queue=False
664
+ )
665
 
666
+ reset_btn.click(
667
+ fn=analyzer.reset_view,
668
+ outputs=image_display
669
+ )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
670
 
671
+ reset_all_btn.click(
672
+ fn=analyzer.reset_all,
673
+ inputs=image_display,
674
+ outputs=[image_display, results_display]
675
+ )
676
 
677
+ key_press.change(
678
+ fn=analyzer.handle_keyboard,
679
+ inputs=key_press,
680
+ outputs=image_display
681
+ )
 
 
 
 
 
 
 
 
 
 
 
 
 
682
 
683
+ blank_btn.click(
684
+ fn=analyzer.add_blank_row,
685
+ inputs=image_display,
686
+ outputs=[image_display, results_display]
687
+ )
688
+
689
+ zero_btn.click(
690
+ fn=analyzer.add_zero_row,
691
+ inputs=image_display,
692
+ outputs=[image_display, results_display]
693
+ )
694
+
695
+ undo_btn.click(
696
+ fn=analyzer.undo_last,
697
+ inputs=image_display,
698
+ outputs=[image_display, results_display]
699
+ )
700
+
701
+ save_btn.click(
702
+ fn=analyzer.save_results,
703
+ outputs=[file_output, results_display]
704
+ )
705
+
706
+ save_formatted_btn.click(
707
+ fn=save_formatted,
708
+ outputs=[file_output, results_display]
709
+ )
710
+
711
+ js = """
712
+ <script>
713
+ document.addEventListener('keydown', function(e) {
714
+ if (['ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight'].includes(e.key)) {
715
+ e.preventDefault();
716
+ const keyPressElement = document.querySelector('#key_press textarea');
717
+ if (keyPressElement) {
718
+ keyPressElement.value = e.key;
719
+ keyPressElement.dispatchEvent(new Event('input'));
720
+ }
721
+ }
722
+ });
723
+ </script>
724
+ """
725
+ gr.HTML(js)
726
+
727
+ print("Interface created successfully")
728
+ return interface
729
+
730
+ if __name__ == "__main__":
731
+ try:
732
+ print("Starting application...")
733
+ interface = create_interface()
734
+ print("Launching interface...")
735
+ interface.queue()
736
+ interface.launch(
737
+ server_name="0.0.0.0",
738
+ server_port=7860,
739
+ share=True,
740
+ debug=True,
741
+ show_error=True,
742
+ quiet=False
743
+ )
744
+ except Exception as e:
745
+ print(f"Error launching application: {str(e)}")
746
+ logger.error(f"Error launching application: {str(e)}")
747
+ logger.error(traceback.format_exc())
748
+ raise e