Tutorials

Step-by-step guides to common EZInput patterns and workflows

Tutorial 1: Your First EZInput GUI

Build a simple parameter collection GUI that works in both Jupyter and terminal.

Step 1: Import and Initialize

from ezinput import EZInput

# Create GUI with a unique, descriptive title
gui = EZInput("my_first_app_v1")

Step 2: Add Input Widgets

# Text input
name = gui.add_text("user_name", "What's your name?")

# Number with range
age = gui.add_int_range("age", "Your age:", 0, 120, value=25)

# Boolean choice
student = gui.add_check("is_student", "Are you a student?", value=False)

Step 3: Display the GUI

# Show the GUI and collect input
gui.show()

📓 Jupyter Notebooks: Create a new cell here! The code in Step 4 should go in a separate cell below this one, so you can interact with the widgets before running the code that accesses their values.

Step 4: Use the Values

# Access widget values
print(f"Hello {name.value}!")
print(f"You are {age.value} years old")

if student.value:
    print("Student discount applied! 🎓")
else:
    print("Regular pricing applies")

🎉 Complete Code

from ezinput import EZInput

# Create and populate GUI
gui = EZInput("my_first_app_v1")
name = gui.add_text("user_name", "What's your name?")
age = gui.add_int_range("age", "Your age:", 0, 120, value=25)
student = gui.add_check("is_student", "Are you a student?", value=False)

# Display
gui.show()

# Use values
print(f"Hello {name.value}!")
print(f"You are {age.value} years old")
if student.value:
    print("Student discount applied! 🎓")

Try it! This code works identically in Jupyter notebooks and Python scripts.

📓 Jupyter Notebooks: Split the code into two cells - first cell ends at gui.show(), second cell contains the code that accesses .value. This lets you interact with widgets before running the processing code.

Tutorial 2: Image Analysis Pipeline

Build a complete image processing GUI with file selection, parameters, and callbacks.

from ezinput import EZInput
import numpy as np
from pathlib import Path

def analyze_image(values):
    """Process image with parameters from GUI."""
    # Extract values
    input_path = values["input_file"].value
    threshold = values["threshold"].value
    method = values["method"].value
    save_result = values["save_output"].value
    
    print(f"Processing: {input_path}")
    print(f"Method: {method}, Threshold: {threshold}")
    
    # Your image processing code here
    # image = load_image(input_path)
    # result = process(image, method, threshold)
    
    if save_result:
        output_path = Path(input_path).stem + "_processed.tif"
        print(f"Saved to: {output_path}")
    
    print("✓ Analysis complete!")
    return True

# Create GUI
gui = EZInput("image_analysis_v3")

# Section 1: Input/Output
gui.add_label(value="=== File Selection ===")
input_file = gui.add_text("input_file", "Input file path:", placeholder="/path/to/image.tif")

# Section 2: Processing Parameters  
gui.add_label(value="=== Processing Parameters ===")
method = gui.add_dropdown("method", 
                          ["watershed", "otsu", "adaptive", "manual"],
                          "Segmentation method:",
                          value="watershed")
threshold = gui.add_float_range("threshold", "Threshold:", 0.0, 1.0, value=0.5)
min_size = gui.add_bounded_int_text("min_size", "Min object size (px):", 10, 10000, value=100)

# Section 3: Options
gui.add_label(value="=== Options ===")
use_gpu = gui.add_check("use_gpu", "Use GPU acceleration?", value=False)
save_output = gui.add_check("save_output", "Save processed image?", value=True)

# Add processing callback
gui.add_callback("process", analyze_image, gui.get_values(),
                 description="▶ Start Analysis")

# Display GUI
gui.show()

💡 Key Patterns

  • Labels as sections: Use add_label() to organize parameters into logical groups
  • Remember stable params: Use remember_value=True parameter for method/threshold but not file paths
  • Callbacks for actions: Create a button (Jupyter) or immediate execution (terminal)
  • Descriptive titles: Version your GUI title for different analysis workflows

Tutorial 3: Multi-Step Analysis Workflow

Create separate GUIs for different analysis stages with configuration sharing.

from ezinput import EZInput

# ============================================
# Step 1: Preprocessing
# ============================================
preprocess_gui = EZInput("preprocessing_v1")

preprocess_gui.add_label(value="=== Preprocessing Parameters ===")
denoise = preprocess_gui.add_check("denoise", "Apply denoising?", default=True)
denoise_sigma = preprocess_gui.add_float_range("sigma", "Denoise sigma:", 0.1, 5.0, default=1.0)
normalize = preprocess_gui.add_check("normalize", "Normalize intensity?", default=True)

preprocess_gui.show()

# Save preprocessing config for reproducibility
preprocess_gui.save_parameters("preprocess_config.yml")

print("Preprocessing complete!")
print(f"Denoise: {denoise.value}, Sigma: {denoise_sigma.value}")

# ============================================
# Step 2: Segmentation
# ============================================
segment_gui = EZInput("segmentation_v1")

segment_gui.add_label(value="=== Segmentation Parameters ===")
method = segment_gui.add_dropdown("method", 
                                  ["watershed", "otsu"], 
                                  "Method:")
threshold = segment_gui.add_float_range("thresh", "Threshold:", 0, 1, default=0.5)
min_size = segment_gui.add_int_range("min_size", "Min size:", 10, 1000, default=50)

# Remember these for next time
segment_gui.remember_value("method")
segment_gui.remember_value("thresh")

segment_gui.show()

# Save segmentation config
segment_gui.save_parameters("segment_config.yml")

print("Segmentation complete!")
print(f"Method: {method.value}, Threshold: {threshold.value}")

# ============================================
# Step 3: Analysis
# ============================================
analysis_gui = EZInput("analysis_v1")

analysis_gui.add_label(value="=== Analysis Options ===")
measure_intensity = analysis_gui.add_check("intensity", "Measure intensity?", default=True)
measure_shape = analysis_gui.add_check("shape", "Measure shape?", default=True)
export_csv = analysis_gui.add_check("export", "Export to CSV?", default=True)

analysis_gui.show()

print("Analysis complete!")
print(f"Measurements: intensity={measure_intensity.value}, shape={measure_shape.value}")

🔑 Multi-Step Best Practices

  • Separate GUIs: One per analysis step with unique titles
  • Save configs: save_parameters() after each step for reproducibility
  • Version control: Commit config files to track parameter evolution
  • Clear naming: Use descriptive titles like preprocessing_v1, segmentation_v2

Tutorial 4: Running Jupyter Notebooks from Terminal

Execute your Jupyter notebooks as command-line tools using the ezinput command.

Step 1: Create a Notebook with EZInput

In your Jupyter notebook (analysis.ipynb):

# Cell 1: Import and setup
from ezinput import EZInput

gui = EZInput("notebook_analysis_v1")
threshold = gui.add_float_range("thresh", "Threshold:", 0, 1)
method = gui.add_dropdown("method", ["A", "B", "C"], "Method:")
gui.show()

# Cell 2: Analysis code
print(f"Running analysis with threshold={threshold.value}, method={method.value}")
# Your analysis code here...

Step 2: Run from Terminal

# Run the notebook from command line
ezinput analysis.ipynb

# EZInput will prompt for parameters in the terminal!
# Threshold: [user enters value]
# Method: [user selects from list]
# Then executes all cells with those values

Step 3: Use Saved Configs

Load a pre-configured parameter set:

# In notebook: load config before showing GUI
gui = EZInput("notebook_analysis_v1")
gui.load_parameters("optimal_params.yml")  # Load saved params

threshold = gui.add_float_range("thresh", "Threshold:", 0, 1)
method = gui.add_dropdown("method", ["A", "B", "C"], "Method:")
gui.show()  # Now shows values from optimal_params.yml!
# Run from terminal - uses config values automatically
ezinput analysis.ipynb

# Values from optimal_params.yml are used as defaults
# Just press Enter to accept, or change as needed

🚀 Use Cases

  • Batch processing: Run same analysis on multiple datasets
  • Automation: Integrate notebooks into shell scripts or pipelines
  • Server execution: Run notebooks on remote servers without Jupyter
  • Reproducibility: Document exact parameters used for each run

Tutorial 5: Advanced Callbacks and Output

Use callbacks for interactive processing and output areas for results display.

from ezinput import EZInput
import time

def validate_params(values):
    """Validate that parameters make sense."""
    min_val = values["min_threshold"].value
    max_val = values["max_threshold"].value
    
    if min_val >= max_val:
        print("❌ Error: Min threshold must be less than max!")
        return False
    
    print("✓ Parameters valid")
    return True

def run_analysis(values):
    """Run the analysis with progress updates."""
    print("Starting analysis...")
    
    # Extract parameters
    min_thresh = values["min_threshold"].value
    max_thresh = values["max_threshold"].value
    iterations = values["iterations"].value
    
    print(f"Threshold range: {min_thresh} - {max_thresh}")
    print(f"Iterations: {iterations}")
    
    # Simulate processing with progress
    for i in range(iterations):
        time.sleep(0.1)  # Simulate work
        if i % 10 == 0:
            print(f"Progress: {i}/{iterations}")
    
    print("✓ Analysis complete!")
    print(f"Processed {iterations} iterations")
    return True

# Create GUI
gui = EZInput("advanced_callbacks")

# Parameters
gui.add_label(value="=== Threshold Range ===")
min_threshold = gui.add_float_range("min_threshold", "Min:", 0.0, 1.0, default=0.3)
max_threshold = gui.add_float_range("max_threshold", "Max:", 0.0, 1.0, default=0.7)

gui.add_label(value="=== Processing ===")
iterations = gui.add_int_range("iterations", "Iterations:", 10, 100, default=50)

# Output area (Jupyter only - ignored in terminal)
gui.add_output("results")

# Multiple callbacks for different actions
gui.add_callback("validate", validate_params, gui.get_values(),
                 description="Validate Parameters")
                 
gui.add_callback("run", run_analysis, gui.get_values(),
                 description="▶ Run Analysis")

# Show GUI
gui.show()

# In Jupyter, output appears in the "results" output widget
# In terminal, output goes to stdout

💡 Callback Tips

  • Multiple callbacks: Create separate buttons for validate, preview, and run actions
  • Output areas: Use add_output() in Jupyter to contain callback output
  • Progress updates: Print status messages during long-running callbacks
  • Return values: Return True/False to indicate success/failure
  • Error handling: Wrap callback code in try/except to show friendly errors

Additional Resources

📖 Widget Reference

Complete documentation of all available widgets

View Widget Docs →

⚙️ Configuration Guide

Learn about persistence, configs, and value priority

Read Config Guide →

📔 Example Notebooks

Download working notebook examples

Browse Examples →