Examples

Real-world examples demonstrating common use cases and workflows.

Example 1: Basic Isotropic Analysis

Scenario: Quick analysis of an isotropic sample for preliminary results.

Configuration (isotropic_example.json):

{
  "metadata": {
    "sample_name": "polymer_solution",
    "analysis_mode": "static_isotropic"
  },
  "analysis_settings": {
    "static_mode": true,
    "static_submode": "isotropic"
  },
  "file_paths": {
    "c2_data_file": "data/polymer_c2_data.h5"
  },
  "initial_parameters": {
    "values": [1500, -0.8, 50]
  }
}

Command:

# Run classical analysis (results saved to ./homodyne_results/)
homodyne --config isotropic_example.json --method classical

# Generate data validation plots only (saved to ./homodyne_results/exp_data/)
homodyne --config isotropic_example.json --plot-experimental-data

# Run in quiet mode for batch processing
homodyne --config isotropic_example.json --method classical --quiet

Expected Output:

✅ Analysis completed successfully
📊 Results summary:
- D₀: 1423.5 ± 45.2
- α: -0.76 ± 0.03
- D_offset: 62.1 ± 8.9
- Chi-squared: 1.23
- Analysis time: 12.3s

Example 2: Flow Analysis with Robust Methods

Scenario: Complete analysis of a system under flow conditions with noise resistance.

Configuration (flow_robust_example.json):

{
  "metadata": {
    "sample_name": "flowing_suspension",
    "analysis_mode": "laminar_flow"
  },
  "analysis_settings": {
    "static_mode": false,
    "enable_angle_filtering": true,
    "angle_filter_ranges": [[-5, 5], [175, 185]]
  },
  "file_paths": {
    "c2_data_file": "data/suspension_flow.h5",
    "phi_angles_file": "data/phi_angles_flow.txt"
  },
  "initial_parameters": {
    "parameter_names": ["D0", "alpha", "D_offset", "gamma_dot_t0", "beta", "gamma_dot_t_offset", "phi0"],
    "values": [2000, -1.0, 100, 15, 0.3, 2, 0],
    "active_parameters": ["D0", "alpha", "D_offset", "gamma_dot_t0"]
  },
  "optimization_config": {
    "robust_optimization": {
      "enabled": true,
      "uncertainty_model": "wasserstein",
      "uncertainty_radius": 0.05
    }
  }
}

Workflow:

# Step 1: Data validation (optional, saves to ./homodyne_results/exp_data/)
homodyne --config flow_robust_example.json --plot-experimental-data

# Step 2: Classical optimization for initial estimates (saves to ./homodyne_results/classical/)
homodyne --config flow_robust_example.json --method classical

# Step 3: Robust optimization for uncertainty resistance (saves to ./homodyne_results/robust/)
homodyne --config flow_robust_example.json --method robust

# Step 4: Complete analysis with both methods (recommended)
homodyne --config flow_robust_example.json --method all

Expected Output:

Classical Results:
- D₀: 1876.3, α: -0.94, D_offset: 112.5, γ̇₀: 12.8
- Chi-squared: 1.45

Robust Results:
- Optimization: ✅ Converged
- D₀: 1881 ± 45, α: -0.93 ± 0.05
- D_offset: 108 ± 18, γ̇₀: 12.6 ± 0.8
- Uncertainty resistance: Excellent

Example 3: Performance-Optimized Analysis

Scenario: Large dataset requiring optimized performance settings.

Configuration (performance_example.json):

{
  "analysis_settings": {
    "static_mode": true,
    "static_submode": "anisotropic",
    "enable_angle_filtering": true,
    "angle_filter_ranges": [[-3, 3], [177, 183]]
  },
  "file_paths": {
    "c2_data_file": "data/large_dataset.h5",
    "phi_angles_file": "data/angles_high_res.txt"
  },
  "performance_settings": {
    "num_threads": 8,
    "data_type": "float32",
    "memory_limit_gb": 16,
    "enable_jit": true,
    "chunked_processing": true
  },
  "initial_parameters": {
    "values": [3000, -0.6, 200]
  }
}

Results:

  • Memory usage: Reduced by ~50% with float32

  • Speed improvement: 3-4x faster with angle filtering

  • Accuracy: Maintained with optimized angle ranges

Example 4: Batch Processing Multiple Samples

Scenario: Process multiple samples with consistent parameters.

Batch Script (batch_analysis.py):

import os
import json
import numpy as np
from homodyne.analysis.core import HomodyneAnalysisCore
from homodyne.optimization.classical import ClassicalOptimizer
from homodyne.data.xpcs_loader import load_xpcs_data

# Sample list
samples = [
    {"name": "sample_01", "file": "data/sample_01.h5"},
    {"name": "sample_02", "file": "data/sample_02.h5"},
    {"name": "sample_03", "file": "data/sample_03.h5"}
]

# Base configuration
base_config = {
    "analysis_settings": {
        "static_mode": True,
        "static_submode": "isotropic"
    },
    "initial_parameters": {
        "values": [1000, -0.5, 100]
    },
    "experimental_data": {
        "data_folder_path": "data/"
    }
}

results = {}

for sample in samples:
    print(f"Processing {sample['name']}...")

    # Create sample-specific config
    config = base_config.copy()
    config["file_paths"] = {"c2_data_file": sample["file"]}
    config["metadata"] = {"sample_name": sample["name"]}

    # Run analysis
    try:
        # Initialize analysis core
        core = HomodyneAnalysisCore(config)

        # Load experimental data
        phi_angles = np.array([0])  # Isotropic mode uses single angle
        c2_data = load_xpcs_data(
            data_path=config['experimental_data']['data_folder_path'],
            phi_angles=phi_angles,
            n_angles=1
        )

        # Run optimization
        optimizer = ClassicalOptimizer(core, config)
        params, result = optimizer.run_classical_optimization_optimized(
            phi_angles=phi_angles,
            c2_experimental=c2_data
        )

        results[sample['name']] = {
            "parameters": params.tolist(),
            "chi_squared": result.chi_squared,
            "best_method": result.best_method
        }

        print(f"✅ {sample['name']}: χ² = {result.chi_squared:.3f}")

    except Exception as e:
        print(f"❌ {sample['name']}: {str(e)}")
        results[sample['name']] = {"error": str(e)}

# Save batch results
with open("batch_results.json", 'w') as f:
    json.dump(results, f, indent=2)

print(f"Batch processing complete. Results saved to batch_results.json")

Example 5: Progressive Analysis Workflow

Scenario: Systematic approach from simple to complex analysis.

Workflow Script (progressive_analysis.py):

import json
import numpy as np
from homodyne.analysis.core import HomodyneAnalysisCore
from homodyne.optimization.classical import ClassicalOptimizer
from homodyne.data.xpcs_loader import load_xpcs_data

def progressive_analysis(data_file, angles_file):
    """
    Perform progressive analysis: isotropic → anisotropic → flow
    """

    results = {}

    # Step 1: Isotropic analysis (fastest)
    print("Step 1: Isotropic analysis...")
    iso_config = {
        "analysis_settings": {"static_mode": True, "static_submode": "isotropic"},
        "file_paths": {"c2_data_file": data_file},
        "initial_parameters": {"values": [1000, -0.5, 100]},
        "experimental_data": {"data_folder_path": "data/"}
    }

    iso_result = run_analysis(iso_config, "isotropic", np.array([0]), 1)
    results["isotropic"] = iso_result

    # Step 2: Anisotropic analysis
    print("Step 2: Anisotropic analysis...")
    aniso_config = iso_config.copy()
    aniso_config["analysis_settings"]["static_submode"] = "anisotropic"
    aniso_config["analysis_settings"]["enable_angle_filtering"] = True
    aniso_config["file_paths"]["phi_angles_file"] = angles_file

    phi_angles = np.array([0, 36, 72, 108, 144])
    aniso_result = run_analysis(aniso_config, "anisotropic", phi_angles, len(phi_angles))
    results["anisotropic"] = aniso_result

    # Compare isotropic vs anisotropic
    iso_chi2 = results["isotropic"]["chi_squared"]
    aniso_chi2 = results["anisotropic"]["chi_squared"]
    improvement = (iso_chi2 - aniso_chi2) / iso_chi2 * 100

    print(f"Chi-squared improvement: {improvement:.1f}%")

    # Step 3: Flow analysis (if significant improvement)
    if improvement > 5:  # 5% improvement threshold
        print("Step 3: Flow analysis...")
        flow_config = aniso_config.copy()
        flow_config["analysis_settings"]["static_mode"] = False
        flow_config["initial_parameters"] = {
            "parameter_names": ["D0", "alpha", "D_offset", "gamma_dot_t0", "beta", "gamma_dot_t_offset", "phi0"],
            "values": list(aniso_result["parameters"]) + [10, 0.5, 1, 0],
            "active_parameters": ["D0", "alpha", "D_offset", "gamma_dot_t0"]
        }

        flow_result = run_analysis(flow_config, "flow", phi_angles, len(phi_angles))
        results["flow"] = flow_result
    else:
        print("Skipping flow analysis - anisotropic improvement < 5%")

    return results

def run_analysis(config_dict, mode_name, phi_angles, n_angles):
    """Run analysis with given configuration"""
    try:
        # Initialize analysis core
        core = HomodyneAnalysisCore(config_dict)

        # Load experimental data
        c2_data = load_xpcs_data(
            data_path=config_dict['experimental_data']['data_folder_path'],
            phi_angles=phi_angles,
            n_angles=n_angles
        )

        # Run optimization
        optimizer = ClassicalOptimizer(core, config_dict)
        params, result = optimizer.run_classical_optimization_optimized(
            phi_angles=phi_angles,
            c2_experimental=c2_data
        )

        return {
            "parameters": params.tolist(),
            "chi_squared": float(result.chi_squared),
            "best_method": result.best_method
        }
    except Exception as e:
        print(f"Analysis failed: {str(e)}")
        return {"error": str(e)}

# Run progressive analysis
if __name__ == "__main__":
    results = progressive_analysis(
        "data/my_sample.h5",
        "data/my_angles.txt"
    )

    with open("progressive_results.json", 'w') as f:
        json.dump(results, f, indent=2)

Common Patterns

Error Handling:

import numpy as np
from homodyne.analysis.core import HomodyneAnalysisCore
from homodyne.optimization.classical import ClassicalOptimizer
from homodyne.data.xpcs_loader import load_xpcs_data

try:
    # Initialize analysis
    core = HomodyneAnalysisCore(config)
    optimizer = ClassicalOptimizer(core, config)

    # Load data and run optimization
    phi_angles = np.array([0, 36, 72, 108, 144])
    c2_data = load_xpcs_data(data_path="data/", phi_angles=phi_angles, n_angles=5)

    params, result = optimizer.run_classical_optimization_optimized(
        phi_angles=phi_angles,
        c2_experimental=c2_data
    )

    print(f"✅ Optimization successful: χ² = {result.chi_squared:.3f}")
    print(f"Best method: {result.best_method}")

except FileNotFoundError as e:
    print(f"❌ File not found: {e}")
except ValueError as e:
    print(f"❌ Configuration error: {e}")

Parameter Validation:

def validate_parameters(params, mode="isotropic"):
    """Validate parameter values are physically reasonable"""

    if mode == "isotropic":
        D0, alpha, D_offset = params[:3]

        if not (100 <= D0 <= 10000):
            print(f"⚠️ D0 = {D0} may be outside typical range [100, 10000]")

        if not (-2.0 <= alpha <= 0.0):
            print(f"⚠️ α = {alpha} may be outside typical range [-2.0, 0.0]")

        if abs(D_offset) > 100:
            print(f"⚠️ D_offset = {D_offset} is outside typical range [-100, 100]")

Result Comparison:

def compare_results(result1, result2, labels=["Method 1", "Method 2"]):
    """Compare two analysis results"""

    chi2_1 = result1.chi_squared
    chi2_2 = result2.chi_squared
    improvement = (chi2_1 - chi2_2) / chi2_1 * 100

    print(f"{labels[0]} χ²: {chi2_1:.4f}")
    print(f"{labels[1]} χ²: {chi2_2:.4f}")
    print(f"Improvement: {improvement:+.1f}%")

    if improvement > 5:
        print("✅ Significant improvement")
    elif improvement > 1:
        print("⚠️ Modest improvement")
    else:
        print("❌ No significant improvement")

Output Directory Structure

Starting from version 6.0, the analysis results are organized into method-specific subdirectories:

./homodyne_results/
├── homodyne_analysis_results.json    # Main results file
├── run.log                           # Analysis log file
├── exp_data/                         # Experimental data plots (--plot-experimental-data)
│   ├── data_validation_phi_*.png
│   └── summary_statistics.txt
├── classical/                       # Classical method outputs (--method classical)
│   ├── all_classical_methods_summary.json  # Summary of all classical methods
│   ├── nelder_mead/                  # Nelder-Mead method results
│   │   ├── analysis_results_nelder_mead.json
│   │   ├── parameters.json           # Parameters with uncertainties
│   │   ├── fitted_data.npz          # Complete data (experimental, fitted, residuals)
│   │   └── c2_heatmaps_nelder_mead.png
│   └── gurobi/                      # Gurobi method results
│       ├── analysis_results_gurobi.json
│       ├── parameters.json
│       ├── fitted_data.npz
│       └── c2_heatmaps_gurobi.png
├── robust/                          # Robust method outputs (--method robust)
│   ├── all_robust_methods_summary.json  # Summary of all robust methods
│   ├── wasserstein/                 # Wasserstein robust method
│   │   ├── analysis_results_wasserstein.json
│   │   ├── parameters.json
│   │   ├── fitted_data.npz
│   │   └── c2_heatmaps_wasserstein.png
│   ├── scenario/                    # Scenario-based robust method
│   │   └── [similar structure]
│   └── ellipsoidal/                 # Ellipsoidal robust method
│       └── [similar structure]
    ├── fitted_data.npz              # Consolidated data (experimental, fitted, residuals, parameters)
    ├── c2_heatmaps_phi_*.png        # C2 correlation heatmaps using posterior means

Key Changes:

  • Main results file: Now saved in output directory instead of current directory

  • Classical method: Results organized in dedicated ./homodyne_results/classical/ subdirectory

  • Experimental data plots: Saved to ./homodyne_results/exp_data/ when using --plot-experimental-data

  • Method-specific outputs: - Classical: Point estimates with C2 heatmaps (diagnostic plots skipped)

  • Fitted data calculation: Both methods use least squares scaling optimization (fitted = contrast * theory + offset)

  • Plotting behavior: The --plot-experimental-data flag now skips all fitting and exits immediately after plotting

Diagnostic Summary Visualizations

The package automatically generates comprehensive diagnostic summary plots that combine multiple analysis components into a single visualization. These provide researchers with immediate feedback on analysis quality and method performance.

Main Diagnostic Summary Plot

Each analysis generates a main diagnostic_summary.png file in the root results directory (./homodyne_results/diagnostic_summary.png) with a 2×3 grid layout containing:

Subplot 1: Method Comparison (Top Left)
  • Bar chart comparing χ² values across optimization methods

  • Log-scale Y-axis with scientific notation value labels

  • Color-coded methods (Nelder-Mead, Gurobi, Robust-Wasserstein, etc.)

Subplot 2: Parameter Uncertainties (Top Middle)
  • Horizontal bar chart of parameter uncertainties (σ)

  • Parameter names on Y-axis (amplitude, frequency, phase, etc.)

  • Grid lines for enhanced readability

  • Shows placeholder if uncertainties unavailable

Subplot 3: Method Performance Metrics (Top Right)
  • Performance comparison across different optimization methods

  • Execution time and convergence metrics

  • Quality indicators for classical and robust methods

  • Shows success status and solution quality

Subplot 4: Residuals Distribution Analysis (Bottom, Full Width)
  • Histogram of residuals (experimental - theoretical)

  • Overlaid normal distribution curve for comparison

  • Statistical summary with mean (μ) and standard deviation (σ)

  • Shows placeholder if residuals data unavailable

Method-Specific Diagnostic Summaries (Removed)

Note: Method-specific diagnostic summary plots have been removed to reduce redundant output. Only the main diagnostic_summary.png is generated for --method all to provide meaningful cross-method comparisons.

Additional Visualization Outputs

C2 Correlation Heatmaps (c2_heatmaps_*.png)
  • 2D heatmaps of experimental vs theoretical correlation functions

  • Individual plots for each scattering angle (φ = 0°, 45°, 90°, 135°)

  • Method-specific versions for each optimization approach

  • Time axes (t₁, t₂) showing correlation delay times

  • Viridis colormap for correlation intensity visualization

Method-Specific Diagnostics
  • Classical method diagnostics showing convergence criteria

  • Robust method diagnostics showing uncertainty resistance

  • Parameter error estimates and confidence intervals

Data Validation Plots (data_validation_*.png)
  • Experimental data quality assessment plots

  • Individual plots for each scattering angle

  • 2D heatmaps and cross-sections of raw experimental data

  • Statistical summaries and data quality metrics

Key Features

  1. Adaptive Content: Appropriate placeholders shown when data unavailable

  2. Cross-Method Comparison: Easy comparison of different optimization approaches

  3. Quality Assessment: Convergence and fitting quality metrics at a glance

  4. Statistical Analysis: Residuals analysis and uncertainty quantification

  5. Professional Formatting: Consistent styling with grid lines, proper labels, and legends

These diagnostic summaries provide immediate visual feedback on analysis quality, method performance, and parameter reliability, enabling researchers to quickly assess their results and identify potential issues.

Common Output Structure for All 5 Classical Methods

Each of the 5 optimization methods (Nelder-Mead, Gurobi, Robust-Wasserstein, Robust-Scenario, Robust-Ellipsoidal) generates standardized outputs for consistent analysis and comparison.

Individual Method Directory Structure

./homodyne_results/classical/
├── nelder_mead/
├── gurobi/
├── robust_wasserstein/
├── robust_scenario/
└── robust_ellipsoidal/

Per-Method Files

Each method directory contains two primary files:

parameters.json - Human-readable parameter results

Contains fitted parameter values with uncertainties, goodness-of-fit metrics (chi-squared, degrees of freedom), convergence information (iterations, function evaluations, termination status), and data statistics.

fitted_data.npz - Consolidated Numerical Data Archive

Complete data structure for each method:

import numpy as np

# Load method-specific data
data = np.load("fitted_data.npz")

# Primary correlation function data
c2_fitted = data["c2_fitted"]           # Method-specific fitted data (n_angles, n_t2, n_t1)
c2_experimental = data["c2_experimental"] # Original experimental data (n_angles, n_t2, n_t1)
residuals = data["residuals"]           # Method-specific residuals (n_angles, n_t2, n_t1)

# Parameter and fit results
parameters = data["parameters"]         # Fitted parameter values (n_params,)
uncertainties = data["uncertainties"]   # Parameter uncertainties (n_params,)
chi_squared = data["chi_squared"]       # Chi-squared goodness-of-fit (scalar)

# Coordinate arrays
phi_angles = data["phi_angles"]         # Angular coordinates (n_angles,) [degrees]
t1 = data["t1"]                        # First correlation time array (n_t1,) [seconds]
t2 = data["t2"]                        # Second correlation time array (n_t2,) [seconds]
Key Features:
  • Consolidated structure: All method-specific data in a single NPZ file per method

  • Complete data access: Experimental, fitted, and residual data together

  • Coordinate information: Full time and angular coordinate arrays included

  • Statistical metadata: Parameter uncertainties and goodness-of-fit metrics

Array Dimensions:
  • Correlation functions: (n_angles, n_t2, n_t1) - typically (4, 60-100, 60-100)

  • Parameters: (n_params,) - 3 for static modes, 7 for laminar flow

  • Time arrays: (n_t1,), (n_t2,) - discretized with dt spacing

  • Angles: (n_angles,) - typically [0°, 45°, 90°, 135°]

Method-Specific Characteristics

Classical Methods (Nelder-Mead, Gurobi)
  • Point estimates only with deterministic convergence metrics

  • Faster execution with iterations and function evaluations tracking

  • Termination reasons and solver-specific status information

  • No built-in uncertainty quantification from optimization method

Robust Methods (Wasserstein, Scenario, Ellipsoidal)
  • Robust optimization against data uncertainty with worst-case guarantees

  • Additional robust-specific parameters (uncertainty radius, scenarios, confidence levels)

  • Convex optimization solver status codes and solve times

  • Enhanced reliability under data perturbations

Cross-Method Comparison

The all_classical_methods_summary.json and all_robust_methods_summary.json files provide easy comparison across all methods with:
  • Analysis timestamp and methods analyzed

  • Best method selection based on chi-squared values

  • Consolidated results showing parameters and goodness-of-fit for each method

  • Success status for each optimization approach

Data Array Structure

All methods use consistent data array dimensions:
  • Correlation data: (n_angles, n_t2, n_t1) format

  • Time arrays: t1 = np.arange(n_t1) * dt and t2 = np.arange(n_t2) * dt

  • Individual angles: (n_t2, n_t1) where rows=t₂, columns=t₁

This standardized structure enables direct comparison of optimization performance and facilitates automated analysis workflows across different methods.

Available Optimization Methods

The homodyne package provides two main optimization approaches:

  1. Classical Optimization (Default) - Fast parameter estimation using Nelder-Mead and Gurobi algorithms - Reliable convergence with parameter error estimates - Best for clean experimental data with minimal noise

  2. Robust Optimization (For noisy data) - Handles measurement noise and experimental uncertainties - Distributionally robust methods (Wasserstein, Scenario-based, Ellipsoidal) - Better for experimental data with outliers or systematic errors

Usage Examples:

# Classical optimization (default)
homodyne --method classical

# Robust optimization for noisy data
homodyne --method robust

# Run both methods for comparison
homodyne --method all

Uncertainty Quantification: - Classical methods provide parameter error estimates - Robust methods provide uncertainty resistance guarantees - Both methods include comprehensive goodness-of-fit metrics

Example 6: Logging Control for Different Scenarios

Scenario: Using different logging modes for various use cases.

Interactive Analysis (default logging):

# Normal interactive analysis with console and file logging
homodyne --config my_config.json --method classical

# With detailed debugging information
homodyne --config my_config.json --method all --verbose

Batch Processing (quiet mode):

# Process multiple samples quietly (logs only to files)
for sample in sample_01 sample_02 sample_03; do
    homodyne --config configs/${sample}_config.json \
            --output-dir results/${sample} \
            --method classical \
            --quiet
done

Automated Scripts (batch_quiet_analysis.sh):

#!/bin/bash
# Batch processing script with quiet logging

SAMPLES_DIR="./data/samples"
RESULTS_DIR="./results"

for config_file in configs/*.json; do
    sample_name=$(basename "$config_file" .json)

    echo "Processing ${sample_name}..."

    # Run analysis in quiet mode
    homodyne --config "$config_file" \
            --output-dir "${RESULTS_DIR}/${sample_name}" \
            --method classical \
            --quiet

    # Check if analysis succeeded (logs are in file)
    if [ -f "${RESULTS_DIR}/${sample_name}/run.log" ]; then
        echo "✅ ${sample_name}: Check ${RESULTS_DIR}/${sample_name}/run.log"
    else
        echo "❌ ${sample_name}: Analysis failed"
    fi
done

echo "Batch processing complete. Check individual run.log files for details."

Debugging Mode (verbose logging):

# Troubleshoot analysis with detailed logging
homodyne --config problem_sample.json --method all --verbose

# Debug robust optimization issues
homodyne --config robust_issue.json --method robust --verbose

Key Benefits:

  • Default mode: Best for interactive use, shows progress and errors

  • Verbose mode (--verbose): Essential for troubleshooting and development

  • Quiet mode (--quiet): Perfect for batch processing and automation

  • File logging: Always enabled, provides complete analysis record

Log File Locations:

./output_directory/
├── run.log                    # Complete analysis log
├── classical/                 # Classical method results
└── homodyne_analysis_results.json  # Main results

Error Handling Note: In quiet mode, errors are only logged to files, so check run.log files for troubleshooting.

Example 7: Performance Monitoring and Optimization

Scenario: Monitor and optimize performance with production-ready stability. The homodyne package has been rebalanced for excellent performance consistency with 97% reduction in chi-squared calculation variability.

Advanced Performance Monitoring (performance_monitoring.py):

from homodyne.core.config import performance_monitor
from homodyne.tests.conftest_performance import (
    stable_benchmark,
    assert_performance_within_bounds
)
import time
import numpy as np

# Performance-monitored analysis function
def analyze_sample_with_monitoring(config_file, phi_angles, c2_data, output_dir):
    """Analyze sample with comprehensive performance monitoring."""
    from homodyne.analysis.core import HomodyneAnalysisCore
    from homodyne.optimization.classical import ClassicalOptimizer
    import json

    with performance_monitor.time_function("full_analysis"):
        with open(config_file) as f:
            config = json.load(f)
        core = HomodyneAnalysisCore(config)

        # Perform analysis with monitoring
        optimizer = ClassicalOptimizer(core, config)
        params, results = optimizer.run_classical_optimization_optimized(
            phi_angles=phi_angles,
            c2_experimental=c2_data
        )

    # Log performance summary
    performance_monitor.log_performance_summary()
    return params, results

# Setup and warmup
def setup_optimized_environment():
    """Setup optimized numerical environment."""
    # Initialize performance monitoring
    print("Setting up performance monitoring...")
    performance_monitor.reset_timings()

    print("✓ Performance monitoring initialized")
    print("✓ Numba available: True (JIT compilation enabled)")
    print("✓ Multi-threading enabled")

    return True

# Performance benchmarking example
def benchmark_analysis_performance():
    """Benchmark analysis performance with different strategies."""

    def sample_computation():
        """Sample computation for benchmarking."""
        # Simulate typical analysis computation
        data = np.random.rand(1000, 1000)
        result = np.sum(data @ data.T)
        time.sleep(0.001)  # Simulate I/O overhead
        return result

    print("=== Performance Benchmarking ===")

    # Standard stable benchmarking
    print("Running stable benchmark...")
    stable_results = stable_benchmark(
        sample_computation,
        warmup_runs=5,
        measurement_runs=15,
        outlier_threshold=2.0
    )

    cv_stable = stable_results['std'] / stable_results['mean']
    print(f"Stable benchmark: {stable_results['mean']:.4f}s ± {cv_stable:.3f} CV")
    print(f"Outliers removed: {stable_results['outlier_count']}/{len(stable_results['times'])}")

    # Adaptive benchmarking
    print("Running adaptive benchmark...")
    adaptive_results = adaptive_stable_benchmark(
        sample_computation,
        target_cv=0.10,  # Target 10% coefficient of variation
        max_runs=30,
        min_runs=10
    )

    print(f"Adaptive benchmark: {adaptive_results['cv']:.3f} CV in {adaptive_results['total_runs']} runs")
    print(f"Target achieved: {adaptive_results['achieved_target']}")

    return stable_results, adaptive_results

# Memory and cache monitoring
def monitor_cache_performance():
    """Monitor smart cache performance."""
    cache = get_performance_cache()

    # Simulate some cached operations
    for i in range(10):
        key = f"test_data_{i}"
        data = np.random.rand(100, 100)
        cache.put(key, data)

    # Get cache statistics
    stats = cache.stats()
    print("=== Cache Performance ===")
    print(f"Cached items: {stats['items']}")
    print(f"Memory usage: {stats['memory_mb']:.1f} MB")
    print(f"Utilization: {stats['utilization']:.1%}")
    print(f"Memory utilization: {stats['memory_utilization']:.1%}")

    return stats

# Complete performance analysis workflow
def run_performance_analysis_example():
    """Complete example of performance-optimized analysis."""
    print("=== Homodyne Performance Analysis Example ===")

    # Step 1: Environment setup and warmup
    warmup_results, kernel_config = setup_optimized_environment()

    # Step 2: Performance benchmarking
    stable_results, adaptive_results = benchmark_analysis_performance()

    # Step 3: Cache monitoring
    cache_stats = monitor_cache_performance()

    # Step 4: Run sample analysis with monitoring
    # Note: This would need actual data files
    print("=== Sample Analysis (simulated) ===")

    def simulated_analysis():
        # Simulate analysis computation with performance monitoring
        with performance_monitor.time_function("simulated_analysis"):
            time.sleep(0.1)
        return {"chi_squared": 1.23, "parameters": [1.0, 0.1, 0.05]}

    result = simulated_analysis()
    print(f"Analysis result: {result}")

    # Step 5: Get comprehensive performance summary
    summary = get_performance_summary()
    print("=== Performance Summary ===")

    if summary:
        for func_name, stats in summary.items():
            if isinstance(stats, dict) and "calls" in stats:
                print(f"{func_name}:")
                print(f"  Calls: {stats['calls']}")
                print(f"  Avg time: {stats['avg_time']:.4f}s")
                print(f"  Total time: {stats['total_time']:.4f}s")

    # Performance achievements and recommendations
    print("=== Performance Stability Achievements ===")
    print("✓ Chi-squared calculations: CV < 0.31 across all array sizes")
    print("✓ 97% reduction in performance variability achieved")
    print("✓ Conservative threading (max 4 cores) for optimal stability")
    print("✓ Balanced JIT optimization for numerical precision")

    print("=== Performance Recommendations ===")

    if warmup_results.get('total_warmup_time', 0) > 2.0:
        print("⚠ Consider caching warmup results for faster startup")

    if cv_stable > 0.31:  # Updated threshold reflecting rebalanced performance
        print("⚠ Performance variability above rebalanced threshold - check system load")
    elif cv_stable < 0.10:
        print("✓ Excellent stability achieved (CV < 0.10)")

    if cache_stats['memory_utilization'] > 0.80:
        print("⚠ Cache memory usage high - consider increasing max_memory_mb")

    print("✓ Performance analysis complete")

    return {
        'warmup': warmup_results,
        'kernel_config': kernel_config,
        'benchmarks': {'stable': stable_results, 'adaptive': adaptive_results},
        'cache_stats': cache_stats,
        'performance_summary': summary
    }

# Run the complete example
if __name__ == "__main__":
    results = run_performance_analysis_example()

Configuration for Performance Monitoring (performance_config.json):

{
  "performance_settings": {
    "numba_optimization": {
      "enable_numba": true,
      "warmup_numba": true,
      "stability_enhancements": {
        "enable_kernel_warmup": true,
        "warmup_iterations": 5,
        "optimize_memory_layout": true,
        "environment_optimization": {
          "auto_configure": true,
          "max_threads": 8,
          "gc_optimization": true
        }
      },
      "performance_monitoring": {
        "enable_profiling": true,
        "adaptive_benchmarking": true,
        "target_cv": 0.10,
        "memory_monitoring": true,
        "smart_caching": {
          "enabled": true,
          "max_items": 200,
          "max_memory_mb": 1000.0
        }
      }
    }
  }
}

Key Performance Features Demonstrated:

  • JIT Warmup: Pre-compile kernels for stable performance

  • Adaptive Benchmarking: Automatically find optimal measurement counts

  • Memory Monitoring: Track and optimize memory usage

  • Smart Caching: Memory-aware LRU caching with cleanup

  • Performance Profiling: Comprehensive monitoring and statistics

  • Environment Optimization: Automatic BLAS/threading configuration

Next Steps