Diff of /lung_segmentation_gui.py [000000] .. [05a195]

Switch to side-by-side view

--- a
+++ b/lung_segmentation_gui.py
@@ -0,0 +1,166 @@
+#!/usr/bin/python3
+
+import os
+import sys
+import tkinter as tk
+from tkinter import filedialog, ttk
+import SimpleITK as sitk
+import matplotlib.pyplot as plt
+from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
+from platipy.imaging.projects.bronchus.run import run_bronchus_segmentation
+from platipy.imaging import ImageVisualiser
+from platipy.imaging.label.utils import get_com
+
+class LungSegmentationGUI:
+    def __init__(self, root):
+        self.root = root
+        self.root.title("Lung Segmentation Tool")
+        
+        # Add protocol handler for window closing
+        self.root.protocol("WM_DELETE_WINDOW", self.on_closing)
+        
+        # Set minimum window size
+        self.root.minsize(800, 600)
+        
+        # Configure grid weights
+        self.root.grid_columnconfigure(0, weight=1)
+        self.root.grid_rowconfigure(0, weight=1)
+        
+        # Create main frame with padding
+        self.main_frame = ttk.Frame(root, padding="20")
+        self.main_frame.grid(row=0, column=0, sticky=(tk.W, tk.E, tk.N, tk.S))
+        self.main_frame.grid_columnconfigure(1, weight=1)
+        
+        # Create control panel frame
+        control_frame = ttk.LabelFrame(self.main_frame, text="Controls", padding="10")
+        control_frame.grid(row=0, column=0, columnspan=2, sticky=(tk.W, tk.E, tk.N), padx=5, pady=5)
+        
+        # Input file selection
+        ttk.Button(control_frame, text="Select Input File", width=20, command=self.select_file).grid(
+            row=0, column=0, padx=(0,10), pady=5)
+        self.file_label = ttk.Label(control_frame, text="No file selected")
+        self.file_label.grid(row=0, column=1, sticky=tk.W, pady=5)
+        
+        # Output directory selection
+        ttk.Button(control_frame, text="Select Output Directory", width=20, command=self.select_output_dir).grid(
+            row=1, column=0, padx=(0,10), pady=5)
+        self.output_label = ttk.Label(control_frame, text="No directory selected")
+        self.output_label.grid(row=1, column=1, sticky=tk.W, pady=5)
+        
+        # Process button
+        self.process_button = ttk.Button(control_frame, text="Process", width=20, command=self.process_image)
+        self.process_button.grid(row=2, column=0, columnspan=2, pady=10)
+        self.process_button.state(['disabled'])
+        
+        # Create status frame
+        status_frame = ttk.LabelFrame(self.main_frame, text="Status", padding="10")
+        status_frame.grid(row=1, column=0, columnspan=2, sticky=(tk.W, tk.E), padx=5, pady=5)
+        
+        # Status label
+        self.status_label = ttk.Label(status_frame, text="")
+        self.status_label.grid(row=0, column=0, sticky=(tk.W, tk.E), padx=5, pady=5)
+        
+        # Create results frame
+        results_frame = ttk.LabelFrame(self.main_frame, text="Results", padding="10")
+        results_frame.grid(row=2, column=0, columnspan=2, sticky=(tk.W, tk.E, tk.N, tk.S), padx=5, pady=5)
+        results_frame.grid_columnconfigure(0, weight=1)
+        results_frame.grid_rowconfigure(0, weight=1)
+        
+        # Result display
+        self.figure_frame = ttk.Frame(results_frame)
+        self.figure_frame.grid(row=0, column=0, sticky=(tk.W, tk.E, tk.N, tk.S))
+
+    def on_closing(self):
+        self.root.quit()
+        self.root.destroy()
+
+    def select_output_dir(self):
+        directory = filedialog.askdirectory()
+        if directory:
+            self.output_dir = directory
+            self.output_label.config(text=directory)
+            self.check_process_ready()
+            
+    def select_file(self):
+        filepath = filedialog.askopenfilename(
+            filetypes=[("NIFTI files", "*.nii.gz"), ("All files", "*.*")]
+        )
+        if filepath:
+            self.input_file = filepath
+            self.file_label.config(text=os.path.basename(filepath))
+            self.check_process_ready()
+            
+    def check_process_ready(self):
+        if hasattr(self, 'input_file') and hasattr(self, 'output_dir'):
+            self.process_button.state(['!disabled'])
+        else:
+            self.process_button.state(['disabled'])
+            
+    def process_image(self):
+        if not hasattr(self, 'input_file') or not hasattr(self, 'output_dir'):
+            return
+            
+        self.status_label.config(text="Processing...")
+        self.process_button.state(['disabled'])
+        
+        self.root.after(100, self.run_segmentation)
+        
+    def run_segmentation(self):
+        try:
+            # Create output directory
+            filename = os.path.splitext(os.path.splitext(os.path.basename(self.input_file))[0])[0]
+            output_dir = os.path.join(self.output_dir, filename)
+            os.makedirs(output_dir, exist_ok=True)
+            
+            # Read image
+            self.status_label.config(text="Loading image...")
+            self.root.update()
+            test_image = sitk.ReadImage(self.input_file)
+            
+            # Process image
+            self.status_label.config(text="Running lung segmentation...")
+            self.root.update()
+            auto_structures = run_bronchus_segmentation(test_image)
+            
+            # Save segmentations
+            self.status_label.config(text="Saving segmentation results...")
+            self.root.update()
+            for struct_name in auto_structures.keys():
+                output_path = os.path.join(output_dir, f"{filename}_{struct_name}.nii.gz")
+                sitk.WriteImage(auto_structures[struct_name], output_path)
+            
+            # Create visualization
+            self.status_label.config(text="Generating visualization...")
+            self.root.update()
+            vis = ImageVisualiser(test_image, cut=get_com(auto_structures["Auto_Lung"]))
+            vis.add_contour({struct: auto_structures[struct] for struct in auto_structures.keys()})
+            fig = vis.show()
+            
+            # Adjust figure size
+            fig.set_size_inches(10, 10)
+            fig.tight_layout()
+            
+            # Save visualization
+            plt.savefig(os.path.join(output_dir, f"{filename}_lung_visualization.png"))
+            
+            # Display in GUI
+            for widget in self.figure_frame.winfo_children():
+                widget.destroy()
+            
+            canvas = FigureCanvasTkAgg(fig, master=self.figure_frame)
+            canvas.draw()
+            canvas.get_tk_widget().pack(fill=tk.BOTH, expand=True)
+            
+            self.status_label.config(text=f"Processing complete. Results saved to {output_dir}")
+            
+        except Exception as e:
+            self.status_label.config(text=f"Error: {str(e)}")
+        
+        finally:
+            self.process_button.state(['!disabled'])
+
+if __name__ == "__main__":
+    root = tk.Tk()
+    app = LungSegmentationGUI(root)
+    root.mainloop()
+    sys.exit(0)