From a01fe8a35c3908c044343fc54521e5f3cf9f3c1c Mon Sep 17 00:00:00 2001 From: john Date: Fri, 16 May 2025 13:52:44 +0000 Subject: [PATCH] Update analyize_discovery.py MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ✅ New Features Graphical file selectors for both: Choosing the discovery output file Choosing the name and location of the analysis output file Output saved to a text file formatted for easy copy/paste into Excel Tab-separated values in the summary for compatibility with Excel columns Modality breakdown + exam statistics in one concise report 📝 How to Use It Save the code below as dicom_analysis_tool.py. Run it (python dicom_analysis_tool.py or double-click if .py is registered). Click the button to: Select the discovery results .txt file. Specify the output .txt destination. It will create a text summary that can be easily opened in Excel (tab-delimited). --- analyize_discovery.py | 76 +++++++++++++++++++++++-------------------- 1 file changed, 40 insertions(+), 36 deletions(-) diff --git a/analyize_discovery.py b/analyize_discovery.py index 3c07be4..320483a 100644 --- a/analyize_discovery.py +++ b/analyize_discovery.py @@ -1,27 +1,35 @@ import tkinter as tk -from tkinter import filedialog, ttk +from tkinter import filedialog, simpledialog import pandas as pd import os -def load_and_analyze_file(): - file_path = filedialog.askopenfilename(title="Select DICOM Discovery Output File", filetypes=[("Text Files", "*.txt")]) - if not file_path: +def normalize_modalities(val): + if val.startswith("[") and val.endswith("]"): + try: + return ", ".join(eval(val)) + except: + return val + return val + +def analyze_and_save(): + input_path = filedialog.askopenfilename( + title="Select DICOM Discovery Output File", + filetypes=[("Text Files", "*.txt")] + ) + if not input_path: return - df = pd.read_csv(file_path, delimiter='|', dtype=str).fillna('') - - # Normalize modalities to upper case and flatten list-like strings - def normalize_modalities(val): - if val.startswith("[") and val.endswith("]"): - try: - return ", ".join(eval(val)) - except: - return val - return val + output_path = filedialog.asksaveasfilename( + title="Save Analysis Output As", + defaultextension=".txt", + filetypes=[("Text Files", "*.txt")] + ) + if not output_path: + return + df = pd.read_csv(input_path, delimiter='|', dtype=str).fillna('') df['ModalitiesInStudy'] = df['ModalitiesInStudy'].apply(normalize_modalities) - # Prepare metrics stats = { "Distinct StudyInstanceUIDs": df['StudyInstanceUID'].nunique(), "Distinct AccessionNumbers": df['AccessionNumber'].nunique(), @@ -38,9 +46,9 @@ def load_and_analyze_file(): "*TEST* in PatientName": df['PatientName'].str.contains('TEST', case=False, na=False).sum() } - # Modality breakdown modality_counts = { - "CR": 0, "DX": 0, "CT": 0, "MR": 0, "NM": 0, "US": 0, "XA": 0, "PR": 0, "SC": 0, "OT": 0, "Other": 0 + "CR": 0, "DX": 0, "CT": 0, "MR": 0, "NM": 0, "US": 0, + "XA": 0, "PR": 0, "SC": 0, "OT": 0, "Other": 0 } for val in df['ModalitiesInStudy']: @@ -50,30 +58,26 @@ def load_and_analyze_file(): else: modality_counts["Other"] += 1 - # Display results - output_window = tk.Toplevel(root) - output_window.title("DICOM Discovery Analysis") + with open(output_path, 'w') as f: + f.write("DICOM Discovery Analysis Summary\n") + f.write("="*40 + "\n\n") + for key, value in stats.items(): + f.write(f"{key}\t{value}\n") + f.write("\nModality Breakdown\n") + f.write("-"*40 + "\n") + for modality, count in modality_counts.items(): + f.write(f"{modality}\t{count}\n") - row = 0 - for key, val in stats.items(): - tk.Label(output_window, text=f"{key}:").grid(row=row, column=0, sticky='w', padx=5, pady=2) - tk.Label(output_window, text=f"{val}").grid(row=row, column=1, sticky='w', padx=5, pady=2) - row += 1 + tk.messagebox.showinfo("Analysis Complete", f"Analysis saved to:\n{output_path}") - tk.Label(output_window, text="Modality Breakdown:").grid(row=row, column=0, sticky='w', padx=5, pady=10) - row += 1 - for modality, count in modality_counts.items(): - tk.Label(output_window, text=f"{modality}:").grid(row=row, column=0, sticky='w', padx=20, pady=2) - tk.Label(output_window, text=f"{count}").grid(row=row, column=1, sticky='w', padx=5, pady=2) - row += 1 - -# GUI setup +# GUI root = tk.Tk() root.title("DICOM Discovery Analyzer") +root.geometry("400x150") -frame = tk.Frame(root, padx=10, pady=10) -frame.pack() +frame = tk.Frame(root, padx=10, pady=20) +frame.pack(expand=True) -ttk.Button(frame, text="Select and Analyze Output File", command=load_and_analyze_file).pack() +tk.Button(frame, text="Select Input File and Analyze", command=analyze_and_save, width=30).pack(pady=10) root.mainloop()