numpy matplotlib import gradio as gr import numpy as np import matplotlib.pyplot as plt def generate_synthetic_kidney(snr, enable_motion): grid_size = 128 y, x = np.ogrid[:grid_size, :grid_size] center_y, center_x = 64, 64 if enable_motion: center_y += int(8 * np.sin(np.pi / 3)) dx = (x - center_x) / 35.0 dy = (y - center_y) / 45.0 r = np.sqrt(dx**2 + dy**2) theta = np.arctan2(dy, dx) bean_radius = ( 1.0 + 0.25 * np.cos(theta) - 0.2 * np.sin(2 * theta) ) kidney_mask = r <= bean_radius img = np.zeros((grid_size, grid_size)) img[kidney_mask] = 1000.0 noise_sigma = 1000.0 / max(snr, 1) noise_real = np.random.normal( 0, noise_sigma, (grid_size, grid_size) ) noise_imag = np.random.normal( 0, noise_sigma, (grid_size, grid_size) ) noisy_img = np.sqrt( (img + noise_real)**2 + noise_imag**2 ) fig, ax = plt.subplots(figsize=(5, 5)) ax.imshow(noisy_img, cmap="gray") ax.set_title(f"Synthetic Renal Scan (SNR: {snr} dB)") ax.axis("off") plt.tight_layout() return fig with gr.Blocks(title="Renal T1 Simulator") as demo: gr.Markdown("# 🫘 Interactive Renal MRI Simulator") gr.Markdown( "Adjust parameters to generate a synthetic kidney slice " "directly in your browser." ) with gr.Column(): snr_slider = gr.Slider( minimum=5, maximum=50, value=20, step=1, label="Signal-to-Noise Ratio (SNR)" ) motion_checkbox = gr.Checkbox( label="Simulate Respiratory Motion", value=False ) run_btn = gr.Button( "Generate Phantom", variant="primary" ) plot_output = gr.Plot( label="Reconstructed Slice" ) run_btn.click( fn=generate_synthetic_kidney, inputs=[snr_slider, motion_checkbox], outputs=[plot_output] ) demo.launch()