diff --git a/.gitignore b/.gitignore index b5c0c07..b721819 100644 --- a/.gitignore +++ b/.gitignore @@ -177,6 +177,8 @@ cython_debug/ /tests/data *.npy *.feat +*.prof +*.png /tests/output/* !/tests/output/figs /tests/output/figs/* diff --git a/README.md b/README.md index 761a347..b5d8aae 100644 --- a/README.md +++ b/README.md @@ -49,4 +49,13 @@ repository of Interpretable Deconvolution for Calcium imaging. 1. Run `CUDA_PATH=whatever python setup.py install`. If you followed the steps correctly, `CUDA_PATH` shouldn't matter (but it has to be set). 1. Verify that `cuosqp` is installed under your environment. + +## Profiling + +For comprehensive profiling documentation, see [`benchmarks/profile/README.md`](benchmarks/profile/README.md). + +Quick reference: +- **Line-level profiling**: Use `kernprof -l -v your_script.py` for functions decorated with `@profile` +- **Pipeline-level profiling**: Use `yappi_profile` context manager for function-level attribution +- **Benchmark scripts**: Deterministic benchmarks in `benchmarks/profile/` for regression detection \ No newline at end of file diff --git a/benchmarks/profile/README.md b/benchmarks/profile/README.md new file mode 100644 index 0000000..bd4188f --- /dev/null +++ b/benchmarks/profile/README.md @@ -0,0 +1,158 @@ +# Profiling + +InDeCa provides two complementary profiling approaches for performance analysis and optimization. + +## 1. Line-Level Profiling (line_profiler) + +For deep numerical inspection of hot loops, solvers, and kernel construction. + +Functions decorated with `@profile` can be profiled using: + +```bash +kernprof -l -v your_script.py +``` + +This is particularly useful for: +- Hot inner loops +- Solver internals +- Kernel construction +- Deconvolution steps + +## 2. Pipeline-Level Profiling (yappi + snakeviz) + +For function-level attribution and call graph analysis. + +### Quick Start + +```python +from indeca.utils.profiling import yappi_profile +from indeca.pipeline import pipeline_bin_new, DeconvPipelineConfig + +Y = load_your_data() +config = DeconvPipelineConfig(...) + +with yappi_profile("pipeline.prof"): + C, S, metrics = pipeline_bin_new(Y, config=config, spawn_dashboard=False) +``` + +View results: +```bash +snakeviz pipeline.prof +``` + +### Clock Types + +- **wall** (default): Real elapsed time, includes I/O and waiting +- **cpu**: Actual computation time, excludes I/O + +```python +with yappi_profile("cpu_profile.prof", clock="cpu"): + ... +``` + +### Usage + +The `yappi_profile` context manager wraps code execution and saves profiling data in pstat format: + +```python +from indeca.utils.profiling import yappi_profile + +with yappi_profile("output.prof", clock="wall"): + # Your code here + result = expensive_function() +``` + +## Benchmark Scripts + +Deterministic benchmarks for performance regression detection. All scripts use fixed seeds and configurations for reproducible results. + +### Small Benchmark (10 cells × 1K frames) + +Quick iterations and fast profiling: + +```bash +# Quick runtime check +python benchmarks/profile/profile_pipeline_small.py + +# With yappi profiling (wall-clock time) +python benchmarks/profile/profile_pipeline_small.py --profile + +# With yappi profiling (CPU time) +python benchmarks/profile/profile_pipeline_small.py --profile --clock cpu + +# View results +snakeviz benchmarks/profile/output/profile_pipeline_small.prof +``` + +### Medium Benchmark (50 cells × 5K frames) + +Realistic workload testing: + +```bash +# Quick runtime check +python benchmarks/profile/profile_pipeline_medium.py + +# With profiling +python benchmarks/profile/profile_pipeline_medium.py --profile + +# View results +snakeviz benchmarks/profile/output/profile_pipeline_medium.prof +``` + +### Large Benchmark (100 cells × 10K frames) + +Comprehensive profiling - **warning: may take several minutes**: + +```bash +# Quick runtime check +python benchmarks/profile/profile_pipeline_large.py + +# With profiling +python benchmarks/profile/profile_pipeline_large.py --profile + +# View results +snakeviz benchmarks/profile/output/profile_pipeline_large.prof +``` + +## When to Use Each Tool + +| Tool | Use Case | +|------|----------| +| line_profiler | Hot inner loops, solver internals, kernel construction | +| yappi | Pipeline flow, function call attribution, call graphs | +| Benchmark scripts | Performance regression detection, optimization validation | + +## Performance Regression Workflow + +1. **Baseline**: Run benchmark without profiling to establish baseline runtime + ```bash + python benchmarks/profile/profile_pipeline_small.py + ``` + +2. **Profile**: Run with profiling to identify bottlenecks + ```bash + python benchmarks/profile/profile_pipeline_small.py --profile + ``` + +3. **Analyze**: View call graph and function timings in snakeviz + ```bash + snakeviz benchmarks/profile/output/profile_pipeline_small.prof + ``` + +4. **Optimize**: Focus on functions with highest cumulative time + +5. **Validate**: Re-run benchmark to measure improvement + +## Output Location + +All profiling output files are saved in `benchmarks/profile/output/`: + +- `profile_pipeline_small.prof` +- `profile_pipeline_medium.prof` +- `profile_pipeline_large.prof` + +These files are in pstat format and can be viewed with: +- **snakeviz** (recommended): Interactive web-based visualization +- **gprof2dot**: Generate call graph diagrams +- **pyprof2calltree**: Convert for use with kcachegrind + diff --git a/benchmarks/profile/profile_pipeline_large.py b/benchmarks/profile/profile_pipeline_large.py new file mode 100644 index 0000000..175d1ba --- /dev/null +++ b/benchmarks/profile/profile_pipeline_large.py @@ -0,0 +1,183 @@ +#!/usr/bin/env python +"""Large deterministic benchmark for comprehensive pipeline profiling. + +Configuration: 100 cells x 10,000 frames +Purpose: Comprehensive profiling and performance baseline establishment + +Warning: This benchmark may take several minutes to complete. + +Usage: + # Quick runtime check + python benchmarks/profile/profile_pipeline_large.py + + # With yappi profiling (wall-clock time) + python benchmarks/profile/profile_pipeline_large.py --profile + + # With yappi profiling (CPU time) + python benchmarks/profile/profile_pipeline_large.py --profile --clock cpu + + # View results + snakeviz benchmarks/profile/output/profile_pipeline_large.prof +""" + +import argparse +import sys +import time +from pathlib import Path + +import numpy as np + +# Add project root to path for imports +PROJECT_ROOT = Path(__file__).parent.parent.parent +sys.path.insert(0, str(PROJECT_ROOT / "src")) + +from indeca.core.simulation import ar_trace +from indeca.pipeline import DeconvPipelineConfig, pipeline_bin_new + +# Benchmark parameters +NCELL = 100 +T = 10000 +SEED = 42 +TAU_D = 6.0 +TAU_R = 1.0 +SIGNAL_LEVEL = (1.0, 5.0) +NOISE_STD = 1.0 +MAX_ITERS = 20 + +# Markov transition matrix for spike generation (P[from_state, to_state]) +MARKOV_P = np.array([[0.95, 0.05], [0.8, 0.2]]) + +# Output directory +OUTPUT_DIR = Path(__file__).parent / "output" + + +def make_test_data(ncell: int, T: int, seed: int) -> np.ndarray: + """Generate deterministic synthetic calcium imaging data. + + Parameters + ---------- + ncell : int + Number of cells + T : int + Number of time frames + seed : int + Random seed for reproducibility + + Returns + ------- + Y : np.ndarray + Noisy calcium traces, shape (ncell, T) + """ + rng = np.random.default_rng(seed) + + # Generate signal levels for each cell + sig_levels = np.sort(rng.uniform(SIGNAL_LEVEL[0], SIGNAL_LEVEL[1], size=ncell)) + + # Generate traces + Y = np.zeros((ncell, T)) + for i in range(ncell): + C, S = ar_trace(T, MARKOV_P, tau_d=TAU_D, tau_r=TAU_R, rng=rng) + noise = rng.normal(0, NOISE_STD, size=T) + Y[i] = C * sig_levels[i] + noise + + return Y + + +def get_config() -> DeconvPipelineConfig: + """Get fixed pipeline configuration for benchmarking.""" + return DeconvPipelineConfig.from_legacy_kwargs( + up_factor=1, + max_iters=MAX_ITERS, + ar_use_all=True, + est_noise_freq=0.06, + est_use_smooth=True, + est_add_lag=50, + deconv_norm="l2", + deconv_backend="osqp", + ) + + +def run_benchmark(profile: bool = False, clock: str = "wall") -> float: + """Run the benchmark. + + Parameters + ---------- + profile : bool + Whether to enable yappi profiling + clock : str + Clock type for yappi: "wall" or "cpu" + + Returns + ------- + elapsed : float + Elapsed time in seconds + """ + # Generate data + print(f"Generating test data: {NCELL} cells x {T} frames (seed={SEED})") + Y = make_test_data(NCELL, T, SEED) + config = get_config() + + print(f"Running pipeline (max_iters={MAX_ITERS})...") + print("Note: This may take several minutes...") + + if profile: + from indeca.utils.profiling import yappi_profile + + OUTPUT_DIR.mkdir(parents=True, exist_ok=True) + prof_path = OUTPUT_DIR / "profile_pipeline_large.prof" + print(f"Profiling enabled (clock={clock})") + print(f"Profile output: {prof_path}") + + t0 = time.perf_counter() + with yappi_profile(str(prof_path), clock=clock): + C, S, metrics = pipeline_bin_new( + Y, config=config, spawn_dashboard=False, da_client=None + ) + elapsed = time.perf_counter() - t0 + + print(f"\nView profile with: snakeviz {prof_path}") + else: + t0 = time.perf_counter() + C, S, metrics = pipeline_bin_new( + Y, config=config, spawn_dashboard=False, da_client=None + ) + elapsed = time.perf_counter() - t0 + + return elapsed + + +def main(): + parser = argparse.ArgumentParser( + description="Large benchmark for comprehensive pipeline profiling" + ) + parser.add_argument( + "--profile", + action="store_true", + help="Enable yappi profiling", + ) + parser.add_argument( + "--clock", + choices=["wall", "cpu"], + default="wall", + help="Clock type for profiling (default: wall)", + ) + args = parser.parse_args() + + print("=" * 60) + print("Pipeline Benchmark: LARGE") + print(f" Cells: {NCELL}") + print(f" Frames: {T}") + print(f" Max iterations: {MAX_ITERS}") + print(" Warning: This may take several minutes") + print("=" * 60) + + elapsed = run_benchmark(profile=args.profile, clock=args.clock) + + print("=" * 60) + print(f"Total runtime: {elapsed:.3f} seconds") + print("=" * 60) + + +if __name__ == "__main__": + main() + diff --git a/benchmarks/profile/profile_pipeline_medium.py b/benchmarks/profile/profile_pipeline_medium.py new file mode 100644 index 0000000..7cb5ef4 --- /dev/null +++ b/benchmarks/profile/profile_pipeline_medium.py @@ -0,0 +1,179 @@ +#!/usr/bin/env python +"""Medium deterministic benchmark for pipeline profiling. + +Configuration: 50 cells x 5,000 frames +Purpose: Realistic workload testing and performance regression detection + +Usage: + # Quick runtime check + python benchmarks/profile/profile_pipeline_medium.py + + # With yappi profiling (wall-clock time) + python benchmarks/profile/profile_pipeline_medium.py --profile + + # With yappi profiling (CPU time) + python benchmarks/profile/profile_pipeline_medium.py --profile --clock cpu + + # View results + snakeviz benchmarks/profile/output/profile_pipeline_medium.prof +""" + +import argparse +import sys +import time +from pathlib import Path + +import numpy as np + +# Add project root to path for imports +PROJECT_ROOT = Path(__file__).parent.parent.parent +sys.path.insert(0, str(PROJECT_ROOT / "src")) + +from indeca.core.simulation import ar_trace +from indeca.pipeline import DeconvPipelineConfig, pipeline_bin_new + +# Benchmark parameters +NCELL = 50 +T = 5000 +SEED = 42 +TAU_D = 6.0 +TAU_R = 1.0 +SIGNAL_LEVEL = (1.0, 5.0) +NOISE_STD = 1.0 +MAX_ITERS = 15 + +# Markov transition matrix for spike generation (P[from_state, to_state]) +MARKOV_P = np.array([[0.95, 0.05], [0.8, 0.2]]) + +# Output directory +OUTPUT_DIR = Path(__file__).parent / "output" + + +def make_test_data(ncell: int, T: int, seed: int) -> np.ndarray: + """Generate deterministic synthetic calcium imaging data. + + Parameters + ---------- + ncell : int + Number of cells + T : int + Number of time frames + seed : int + Random seed for reproducibility + + Returns + ------- + Y : np.ndarray + Noisy calcium traces, shape (ncell, T) + """ + rng = np.random.default_rng(seed) + + # Generate signal levels for each cell + sig_levels = np.sort(rng.uniform(SIGNAL_LEVEL[0], SIGNAL_LEVEL[1], size=ncell)) + + # Generate traces + Y = np.zeros((ncell, T)) + for i in range(ncell): + C, S = ar_trace(T, MARKOV_P, tau_d=TAU_D, tau_r=TAU_R, rng=rng) + noise = rng.normal(0, NOISE_STD, size=T) + Y[i] = C * sig_levels[i] + noise + + return Y + + +def get_config() -> DeconvPipelineConfig: + """Get fixed pipeline configuration for benchmarking.""" + return DeconvPipelineConfig.from_legacy_kwargs( + up_factor=1, + max_iters=MAX_ITERS, + ar_use_all=True, + est_noise_freq=0.06, + est_use_smooth=True, + est_add_lag=50, + deconv_norm="l2", + deconv_backend="osqp", + ) + + +def run_benchmark(profile: bool = False, clock: str = "wall") -> float: + """Run the benchmark. + + Parameters + ---------- + profile : bool + Whether to enable yappi profiling + clock : str + Clock type for yappi: "wall" or "cpu" + + Returns + ------- + elapsed : float + Elapsed time in seconds + """ + # Generate data + print(f"Generating test data: {NCELL} cells x {T} frames (seed={SEED})") + Y = make_test_data(NCELL, T, SEED) + config = get_config() + + print(f"Running pipeline (max_iters={MAX_ITERS})...") + + if profile: + from indeca.utils.profiling import yappi_profile + + OUTPUT_DIR.mkdir(parents=True, exist_ok=True) + prof_path = OUTPUT_DIR / "profile_pipeline_medium.prof" + print(f"Profiling enabled (clock={clock})") + print(f"Profile output: {prof_path}") + + t0 = time.perf_counter() + with yappi_profile(str(prof_path), clock=clock): + C, S, metrics = pipeline_bin_new( + Y, config=config, spawn_dashboard=False, da_client=None + ) + elapsed = time.perf_counter() - t0 + + print(f"\nView profile with: snakeviz {prof_path}") + else: + t0 = time.perf_counter() + C, S, metrics = pipeline_bin_new( + Y, config=config, spawn_dashboard=False, da_client=None + ) + elapsed = time.perf_counter() - t0 + + return elapsed + + +def main(): + parser = argparse.ArgumentParser( + description="Medium benchmark for pipeline profiling" + ) + parser.add_argument( + "--profile", + action="store_true", + help="Enable yappi profiling", + ) + parser.add_argument( + "--clock", + choices=["wall", "cpu"], + default="wall", + help="Clock type for profiling (default: wall)", + ) + args = parser.parse_args() + + print("=" * 60) + print("Pipeline Benchmark: MEDIUM") + print(f" Cells: {NCELL}") + print(f" Frames: {T}") + print(f" Max iterations: {MAX_ITERS}") + print("=" * 60) + + elapsed = run_benchmark(profile=args.profile, clock=args.clock) + + print("=" * 60) + print(f"Total runtime: {elapsed:.3f} seconds") + print("=" * 60) + + +if __name__ == "__main__": + main() + diff --git a/benchmarks/profile/profile_pipeline_small.py b/benchmarks/profile/profile_pipeline_small.py new file mode 100644 index 0000000..23c19fc --- /dev/null +++ b/benchmarks/profile/profile_pipeline_small.py @@ -0,0 +1,309 @@ +#!/usr/bin/env python +"""Small deterministic benchmark for pipeline profiling. + +Configuration: 10 cells x 1,000 frames +Purpose: Quick runtime checks and fast profiling iterations + +Usage: + # Quick runtime check + python benchmarks/profile/profile_pipeline_small.py + + # With yappi profiling (wall-clock time) + python benchmarks/profile/profile_pipeline_small.py --profile + + # With yappi profiling (CPU time) + python benchmarks/profile/profile_pipeline_small.py --profile --clock cpu + + # View results + snakeviz benchmarks/profile/output/profile_pipeline_small.prof +""" + +import argparse +import os +import sys +import time +from pathlib import Path + +import matplotlib.pyplot as plt +import numpy as np + +# Add project root to path for imports +PROJECT_ROOT = Path(__file__).parent.parent.parent +sys.path.insert(0, str(PROJECT_ROOT / "src")) + +from indeca.core.simulation import ar_trace, tau2AR +from indeca.pipeline import DeconvPipelineConfig, pipeline_bin_new + +# Benchmark parameters +NCELL = 10 +T = 1000 +SEED = 42 + +# Set global random seed for full reproducibility +# This ensures all random operations (including those using np.random.* directly) +# are deterministic across runs +np.random.seed(SEED) +TAU_D = 6.0 +TAU_R = 1.0 +SIGNAL_LEVEL = (1.0, 5.0) +NOISE_STD = 1.0 +MAX_ITERS = 10 + +# Markov transition matrix for spike generation (P[from_state, to_state]) +# State 0 = no spike, State 1 = spike +MARKOV_P = np.array([[0.95, 0.05], [0.8, 0.2]]) + +# Output directory +OUTPUT_DIR = Path(__file__).parent / "output" + + +def make_test_data(ncell: int, T: int, seed: int) -> np.ndarray: + """Generate deterministic synthetic calcium imaging data. + + Parameters + ---------- + ncell : int + Number of cells + T : int + Number of time frames + seed : int + Random seed for reproducibility + + Returns + ------- + Y : np.ndarray + Noisy calcium traces, shape (ncell, T) + """ + rng = np.random.default_rng(seed) + + # Generate signal levels for each cell + sig_levels = np.sort(rng.uniform(SIGNAL_LEVEL[0], SIGNAL_LEVEL[1], size=ncell)) + + # Generate traces + Y = np.zeros((ncell, T)) + for i in range(ncell): + C, S = ar_trace(T, MARKOV_P, tau_d=TAU_D, tau_r=TAU_R, rng=rng) + noise = rng.normal(0, NOISE_STD, size=T) + Y[i] = C * sig_levels[i] + noise + + return Y + + +def plot_pipeline_results( + Y: np.ndarray, C: np.ndarray, S: np.ndarray, output_dir: Path +) -> None: + """Plot and save pipeline results visualization. + + For each cell, overlays: + - Y: Input fluorescence trace (test data) + - C: Deconvolved calcium trace + - S: Inferred spike train + + Parameters + ---------- + Y : np.ndarray + Input fluorescence traces, shape (ncell, T) + C : np.ndarray + Deconvolved calcium traces, shape (ncell, T * up_factor) + S : np.ndarray + Inferred spike trains, shape (ncell, T * up_factor) + output_dir : Path + Directory to save the plot + """ + ncell, T = Y.shape + T_up = C.shape[1] + + # Create figure with subplots (one row per cell) + fig, axes = plt.subplots(ncell, 1, figsize=(14, 2.5 * ncell), sharex=True) + if ncell == 1: + axes = [axes] + + time_axis = np.arange(T) + time_axis_up = np.arange(T_up) + + for i in range(ncell): + ax = axes[i] + + # Normalize traces for better visualization (optional scaling) + y_norm = Y[i] + c_norm = C[i] + s_norm = S[i] + + # Plot input fluorescence (Y) - use original time axis + ax.plot( + time_axis, + y_norm, + linewidth=1.2, + alpha=0.7, + color="blue", + label="Y (input)", + zorder=1, + ) + + # Plot deconvolved calcium (C) - use upsampled time axis + ax.plot( + time_axis_up, + c_norm, + linewidth=1.0, + alpha=0.8, + color="green", + label="C (calcium)", + zorder=2, + ) + + # Plot inferred spikes (S) - use upsampled time axis + # Scale spikes for visibility (multiply by max of Y or C for relative scaling) + scale_factor = max(y_norm.max(), c_norm.max()) * 0.3 + spike_times = np.where(S[i] > 0.1)[0] # Threshold for visualization + if len(spike_times) > 0: + spike_heights = S[i][spike_times] * scale_factor + ax.vlines( + spike_times, + 0, + spike_heights, + colors="red", + linewidths=2.0, + alpha=0.9, + label="S (spikes)", + zorder=3, + ) + # Also plot spike trace as line for continuity + ax.plot( + time_axis_up, + S[i] * scale_factor, + linewidth=0.8, + alpha=0.5, + color="red", + linestyle="--", + zorder=2, + ) + + ax.set_ylabel(f"Cell {i+1}", fontsize=10, fontweight="bold") + ax.grid(True, alpha=0.3, zorder=0) + ax.legend(loc="upper right", fontsize=9) + ax.set_title(f"Cell {i+1}: Input (Y), Calcium (C), and Spikes (S)", fontsize=11) + + axes[-1].set_xlabel("Time (frames)", fontsize=10) + fig.suptitle( + f"Pipeline Results: {ncell} cells × {T} frames (upsampled to {T_up})", + fontsize=12, + y=0.995, + ) + plt.tight_layout() + + # Save plot + output_dir.mkdir(parents=True, exist_ok=True) + plot_path = output_dir / "pipeline_results.png" + plt.savefig(plot_path, dpi=150, bbox_inches="tight") + plt.close() + + print(f"Saved pipeline results plot: {plot_path}") + + +def get_config() -> DeconvPipelineConfig: + """Get fixed pipeline configuration for benchmarking.""" + return DeconvPipelineConfig.from_legacy_kwargs( + up_factor=1, + max_iters=MAX_ITERS, + ar_use_all=True, + est_noise_freq=0.06, + est_use_smooth=True, + est_add_lag=50, + deconv_norm="l2", + deconv_backend="osqp", + # Provide initial tau values matching the data generation to avoid AR fitting issues + tau_init=(TAU_D, TAU_R), + ) + + +def run_benchmark(profile: bool = False, clock: str = "wall") -> float: + """Run the benchmark. + + Parameters + ---------- + profile : bool + Whether to enable yappi profiling + clock : str + Clock type for yappi: "wall" or "cpu" + + Returns + ------- + elapsed : float + Elapsed time in seconds + """ + # Reset random seed for reproducibility + # This ensures deterministic behavior across runs + np.random.seed(SEED) + + # Generate data + print(f"Generating test data: {NCELL} cells x {T} frames (seed={SEED})") + Y = make_test_data(NCELL, T, SEED) + + config = get_config() + + print(f"Running pipeline (max_iters={MAX_ITERS})...") + + if profile: + from indeca.utils.profiling import yappi_profile + + OUTPUT_DIR.mkdir(parents=True, exist_ok=True) + prof_path = OUTPUT_DIR / "profile_pipeline_small.prof" + print(f"Profiling enabled (clock={clock})") + print(f"Profile output: {prof_path}") + + t0 = time.perf_counter() + with yappi_profile(str(prof_path), clock=clock): + C, S, metrics = pipeline_bin_new( + Y, config=config, spawn_dashboard=False, da_client=None + ) + elapsed = time.perf_counter() - t0 + + print(f"\nView profile with: snakeviz {prof_path}") + else: + t0 = time.perf_counter() + C, S, metrics = pipeline_bin_new( + Y, config=config, spawn_dashboard=False, da_client=None + ) + elapsed = time.perf_counter() - t0 + + # Plot and save results + print("Plotting results...") + plot_pipeline_results(Y, C, S, OUTPUT_DIR) + + return elapsed + + +def main(): + parser = argparse.ArgumentParser( + description="Small benchmark for pipeline profiling" + ) + parser.add_argument( + "--profile", + action="store_true", + help="Enable yappi profiling", + ) + parser.add_argument( + "--clock", + choices=["wall", "cpu"], + default="wall", + help="Clock type for profiling (default: wall)", + ) + args = parser.parse_args() + + print("=" * 60) + print("Pipeline Benchmark: SMALL") + print(f" Cells: {NCELL}") + print(f" Frames: {T}") + print(f" Max iterations: {MAX_ITERS}") + print("=" * 60) + + elapsed = run_benchmark(profile=args.profile, clock=args.clock) + + print("=" * 60) + print(f"Total runtime: {elapsed:.3f} seconds") + print("=" * 60) + + +if __name__ == "__main__": + main() + diff --git a/pdm.lock b/pdm.lock index 7c4ca53..4052532 100644 --- a/pdm.lock +++ b/pdm.lock @@ -2,10 +2,10 @@ # It is not intended for manual editing. [metadata] -groups = ["default", "test"] +groups = ["default", "dev", "test"] strategy = [] lock_version = "4.5.0" -content_hash = "sha256:4f5ed9e8f685d76eb0697a6fe96b8bc2a91790bca75dbe477816cf4ca61a32e4" +content_hash = "sha256:da50177f3ccfd4d6e21114501ab254028d2d6b4e5746784c562e5afbedc1a759" [[metadata.targets]] requires_python = ">=3.11,<3.13" @@ -22,12 +22,12 @@ files = [ [[package]] name = "aiohttp" -version = "3.12.2" +version = "3.13.2" requires_python = ">=3.9" summary = "Async http client/server framework (asyncio)" dependencies = [ "aiohappyeyeballs>=2.5.0", - "aiosignal>=1.1.2", + "aiosignal>=1.4.0", "async-timeout<6.0,>=4.0; python_version < \"3.11\"", "attrs>=17.3.0", "frozenlist>=1.1.1", @@ -36,70 +36,83 @@ dependencies = [ "yarl<2.0,>=1.17.0", ] files = [ - {file = "aiohttp-3.12.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:536a37af26ed50bd4f3cf7d989955e5a987e9343f1a55f5393e7950a6ac93fce"}, - {file = "aiohttp-3.12.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6f8fbb48953238e7ba8ab9dee6757a4f6b72cd6242eb7fe1cb004b24f91effee"}, - {file = "aiohttp-3.12.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:74190229bd54bc3df7090f634b0b7fe53c45fb41aae5fbfae462093ced35c950"}, - {file = "aiohttp-3.12.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7af4737ab145fb1ac6e2db24ee206ee9e9f3abb1f7c6b74bd75c9ce0d36fe286"}, - {file = "aiohttp-3.12.2-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:2711392a2afe1dcf4a93b05a94ee25efa966971fa0bf3944f2ce101da182ce91"}, - {file = "aiohttp-3.12.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5169898d17a2ac30e31ea814832ad4cf6bb652459a031af40ed56c9d05894c80"}, - {file = "aiohttp-3.12.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3a590566c5c139edfbeeb69de62c6868e6ef667322b0080489607acc39e92add"}, - {file = "aiohttp-3.12.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ad4be1c1adb604591a607abb9c4474eedc6add6739656ee91a9daddf35f7f9fa"}, - {file = "aiohttp-3.12.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0cf15667ecf20bfe545adb02882d895e10c8d5c821e46b1a62f22d5170c4803e"}, - {file = "aiohttp-3.12.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:875df9e4ed4f24af643f4e35bf267be3cb25b9461d25da4a0d181877a2b401e4"}, - {file = "aiohttp-3.12.2-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:722fe14a899ee049562417449a449dfc7c616fdb5409f8a0a2c459815473767f"}, - {file = "aiohttp-3.12.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:59668d843c91bd22abc1f70674270ce38e1dad3020284cccecc60f492d6f88ae"}, - {file = "aiohttp-3.12.2-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:64e48ed61d5c74b5a4a68fdb3fde664034e59788625ebf3fcae87fb5a2dbde7b"}, - {file = "aiohttp-3.12.2-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:7061bce1accdfce6e02c80ac10efcdfcae95718f97f77fc5fbe3273b16b8d4bf"}, - {file = "aiohttp-3.12.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:ef392a613f53fc4c3e6ebba2c3b90729266139a3f534e7eba9bf04e2eac40287"}, - {file = "aiohttp-3.12.2-cp311-cp311-win32.whl", hash = "sha256:e405ccdd3cada578e5bc4000b7d35b80a345c832089d23b04be30c0e7606fb80"}, - {file = "aiohttp-3.12.2-cp311-cp311-win_amd64.whl", hash = "sha256:a84cf5db31efc14e811ef830288614bf40093befd445efe743dc015d01e6e92c"}, - {file = "aiohttp-3.12.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:7679b2af5a1d43d8470672079baedc1a843e4f27a47b630fbe092833f9bc4e73"}, - {file = "aiohttp-3.12.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:4d6941dd4d8f6dfd9292f391bc2e321c9583a9532b4e9b571b84f163bb3f8135"}, - {file = "aiohttp-3.12.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8345cea33295cc28945c8365ac44ba383ebb757a599b384d752347f40671e984"}, - {file = "aiohttp-3.12.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8259a311666becf7049ae43c984208ac20eda5ea16aa5f26ea5d24b863f9afcd"}, - {file = "aiohttp-3.12.2-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:7a6f09589cb5928ee793210806d35d69fffc78d46eca9acaa2d38cc30b3f194e"}, - {file = "aiohttp-3.12.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d0c32972b485828f2b9326a95851520e9a92cdd97efe0a04ae62c7315e8d1098"}, - {file = "aiohttp-3.12.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:851d226ecaf30ec7f12d9e9793081ecd0e66fea7f6345bcb5283b39e9ea79c71"}, - {file = "aiohttp-3.12.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f7127241e62621eabe437cce249a4858e79896abcdafed4c6f7a90d14d449066"}, - {file = "aiohttp-3.12.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bca43af1c77f83e88641e74d1bd24b6089bb518fa0e6be97805a048bdac6bbc3"}, - {file = "aiohttp-3.12.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:9d913623c7e3be188fe5c718bce186e0bbc5977e74c12e4832d540c3637b9f47"}, - {file = "aiohttp-3.12.2-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:b4924ca6bc74cb630e47edaf111f1d05e13dfe3c1e580c35277dc998965913d3"}, - {file = "aiohttp-3.12.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:a38e144942d4f0740dcb5be2ceb932cc45fc29e404fe64ffd5eef5bc62eafe39"}, - {file = "aiohttp-3.12.2-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:6c31782dae093a507b94792d9f32978bf154d051d5237fdedbb9e74d9464d5dd"}, - {file = "aiohttp-3.12.2-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:7f10d664b638f85acdeb7622f7b16773aaf7d67214a7c3b6075735f171d2f021"}, - {file = "aiohttp-3.12.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:7181b4ebd70ad9731f4f7af03e3ed0ff003e49cefbf0b6846b5decb32abc30b7"}, - {file = "aiohttp-3.12.2-cp312-cp312-win32.whl", hash = "sha256:d602fc26cb307993965e5f5dacb2aaa7fea4f01c6658250658bef51e48dd454e"}, - {file = "aiohttp-3.12.2-cp312-cp312-win_amd64.whl", hash = "sha256:35df44dde19fcd146ed13e8847c70f8e138e91138f7615df2bd68b478ac04f99"}, - {file = "aiohttp-3.12.2.tar.gz", hash = "sha256:0018956472ee535d2cad761a5bb88eb4ad80f94cd86472cee26a244799f7c79f"}, + {file = "aiohttp-3.13.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:4647d02df098f6434bafd7f32ad14942f05a9caa06c7016fdcc816f343997dd0"}, + {file = "aiohttp-3.13.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:e3403f24bcb9c3b29113611c3c16a2a447c3953ecf86b79775e7be06f7ae7ccb"}, + {file = "aiohttp-3.13.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:43dff14e35aba17e3d6d5ba628858fb8cb51e30f44724a2d2f0c75be492c55e9"}, + {file = "aiohttp-3.13.2-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e2a9ea08e8c58bb17655630198833109227dea914cd20be660f52215f6de5613"}, + {file = "aiohttp-3.13.2-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:53b07472f235eb80e826ad038c9d106c2f653584753f3ddab907c83f49eedead"}, + {file = "aiohttp-3.13.2-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:e736c93e9c274fce6419af4aac199984d866e55f8a4cec9114671d0ea9688780"}, + {file = "aiohttp-3.13.2-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:ff5e771f5dcbc81c64898c597a434f7682f2259e0cd666932a913d53d1341d1a"}, + {file = "aiohttp-3.13.2-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a3b6fb0c207cc661fa0bf8c66d8d9b657331ccc814f4719468af61034b478592"}, + {file = "aiohttp-3.13.2-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:97a0895a8e840ab3520e2288db7cace3a1981300d48babeb50e7425609e2e0ab"}, + {file = "aiohttp-3.13.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:9e8f8afb552297aca127c90cb840e9a1d4bfd6a10d7d8f2d9176e1acc69bad30"}, + {file = "aiohttp-3.13.2-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:ed2f9c7216e53c3df02264f25d824b079cc5914f9e2deba94155190ef648ee40"}, + {file = "aiohttp-3.13.2-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:99c5280a329d5fa18ef30fd10c793a190d996567667908bef8a7f81f8202b948"}, + {file = "aiohttp-3.13.2-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:2ca6ffef405fc9c09a746cb5d019c1672cd7f402542e379afc66b370833170cf"}, + {file = "aiohttp-3.13.2-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:47f438b1a28e926c37632bff3c44df7d27c9b57aaf4e34b1def3c07111fdb782"}, + {file = "aiohttp-3.13.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:9acda8604a57bb60544e4646a4615c1866ee6c04a8edef9b8ee6fd1d8fa2ddc8"}, + {file = "aiohttp-3.13.2-cp311-cp311-win32.whl", hash = "sha256:868e195e39b24aaa930b063c08bb0c17924899c16c672a28a65afded9c46c6ec"}, + {file = "aiohttp-3.13.2-cp311-cp311-win_amd64.whl", hash = "sha256:7fd19df530c292542636c2a9a85854fab93474396a52f1695e799186bbd7f24c"}, + {file = "aiohttp-3.13.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:b1e56bab2e12b2b9ed300218c351ee2a3d8c8fdab5b1ec6193e11a817767e47b"}, + {file = "aiohttp-3.13.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:364e25edaabd3d37b1db1f0cbcee8c73c9a3727bfa262b83e5e4cf3489a2a9dc"}, + {file = "aiohttp-3.13.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:c5c94825f744694c4b8db20b71dba9a257cd2ba8e010a803042123f3a25d50d7"}, + {file = "aiohttp-3.13.2-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ba2715d842ffa787be87cbfce150d5e88c87a98e0b62e0f5aa489169a393dbbb"}, + {file = "aiohttp-3.13.2-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:585542825c4bc662221fb257889e011a5aa00f1ae4d75d1d246a5225289183e3"}, + {file = "aiohttp-3.13.2-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:39d02cb6025fe1aabca329c5632f48c9532a3dabccd859e7e2f110668972331f"}, + {file = "aiohttp-3.13.2-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:e67446b19e014d37342f7195f592a2a948141d15a312fe0e700c2fd2f03124f6"}, + {file = "aiohttp-3.13.2-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4356474ad6333e41ccefd39eae869ba15a6c5299c9c01dfdcfdd5c107be4363e"}, + {file = "aiohttp-3.13.2-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:eeacf451c99b4525f700f078becff32c32ec327b10dcf31306a8a52d78166de7"}, + {file = "aiohttp-3.13.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:d8a9b889aeabd7a4e9af0b7f4ab5ad94d42e7ff679aaec6d0db21e3b639ad58d"}, + {file = "aiohttp-3.13.2-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:fa89cb11bc71a63b69568d5b8a25c3ca25b6d54c15f907ca1c130d72f320b76b"}, + {file = "aiohttp-3.13.2-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:8aa7c807df234f693fed0ecd507192fc97692e61fee5702cdc11155d2e5cadc8"}, + {file = "aiohttp-3.13.2-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:9eb3e33fdbe43f88c3c75fa608c25e7c47bbd80f48d012763cb67c47f39a7e16"}, + {file = "aiohttp-3.13.2-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:9434bc0d80076138ea986833156c5a48c9c7a8abb0c96039ddbb4afc93184169"}, + {file = "aiohttp-3.13.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ff15c147b2ad66da1f2cbb0622313f2242d8e6e8f9b79b5206c84523a4473248"}, + {file = "aiohttp-3.13.2-cp312-cp312-win32.whl", hash = "sha256:27e569eb9d9e95dbd55c0fc3ec3a9335defbf1d8bc1d20171a49f3c4c607b93e"}, + {file = "aiohttp-3.13.2-cp312-cp312-win_amd64.whl", hash = "sha256:8709a0f05d59a71f33fd05c17fc11fcb8c30140506e13c2f5e8ee1b8964e1b45"}, + {file = "aiohttp-3.13.2.tar.gz", hash = "sha256:40176a52c186aefef6eb3cad2cdd30cd06e3afbe88fe8ab2af9c0b90f228daca"}, ] [[package]] name = "aiosignal" -version = "1.3.2" +version = "1.4.0" requires_python = ">=3.9" summary = "aiosignal: a list of registered asynchronous callbacks" dependencies = [ "frozenlist>=1.1.0", + "typing-extensions>=4.2; python_version < \"3.13\"", ] files = [ - {file = "aiosignal-1.3.2-py2.py3-none-any.whl", hash = "sha256:45cde58e409a301715980c2b01d0c28bdde3770d8290b5eb2173759d9acb31a5"}, - {file = "aiosignal-1.3.2.tar.gz", hash = "sha256:a8c255c66fafb1e499c9351d0bf32ff2d8a0321595ebac3b93713656d2436f54"}, + {file = "aiosignal-1.4.0-py3-none-any.whl", hash = "sha256:053243f8b92b990551949e63930a839ff0cf0b0ebbe0597b0f3fb19e1a0fe82e"}, + {file = "aiosignal-1.4.0.tar.gz", hash = "sha256:f47eecd9468083c2029cc99945502cb7708b082c232f9aca65da147157b251c7"}, +] + +[[package]] +name = "annotated-types" +version = "0.7.0" +requires_python = ">=3.8" +summary = "Reusable constraint types to use with typing.Annotated" +dependencies = [ + "typing-extensions>=4.0.0; python_version < \"3.9\"", +] +files = [ + {file = "annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53"}, + {file = "annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89"}, ] [[package]] name = "anyio" -version = "4.9.0" +version = "4.12.0" requires_python = ">=3.9" -summary = "High level compatibility layer for multiple asynchronous event loop implementations" +summary = "High-level concurrency and networking framework on top of asyncio or Trio" dependencies = [ "exceptiongroup>=1.0.2; python_version < \"3.11\"", "idna>=2.8", - "sniffio>=1.1", "typing-extensions>=4.5; python_version < \"3.13\"", ] files = [ - {file = "anyio-4.9.0-py3-none-any.whl", hash = "sha256:9f76d541cad6e36af7beb62e978876f3b41e3e04f2c1fbf0884604c0a9c4d93c"}, - {file = "anyio-4.9.0.tar.gz", hash = "sha256:673c0c244e15788651a4ff38710fea9675823028a6f08a5eda409e0c9840a028"}, + {file = "anyio-4.12.0-py3-none-any.whl", hash = "sha256:dad2376a628f98eeca4881fc56cd06affd18f659b17a747d3ff0307ced94b1bb"}, + {file = "anyio-4.12.0.tar.gz", hash = "sha256:73c693b567b0c55130c104d0b43a9baf3aa6a31fc6110116509f27bf75e21ec0"}, ] [[package]] @@ -114,62 +127,63 @@ files = [ [[package]] name = "argon2-cffi" -version = "23.1.0" -requires_python = ">=3.7" +version = "25.1.0" +requires_python = ">=3.8" summary = "Argon2 for Python" dependencies = [ "argon2-cffi-bindings", - "typing-extensions; python_version < \"3.8\"", ] files = [ - {file = "argon2_cffi-23.1.0-py3-none-any.whl", hash = "sha256:c670642b78ba29641818ab2e68bd4e6a78ba53b7eff7b4c3815ae16abf91c7ea"}, - {file = "argon2_cffi-23.1.0.tar.gz", hash = "sha256:879c3e79a2729ce768ebb7d36d4609e3a78a4ca2ec3a9f12286ca057e3d0db08"}, + {file = "argon2_cffi-25.1.0-py3-none-any.whl", hash = "sha256:fdc8b074db390fccb6eb4a3604ae7231f219aa669a2652e0f20e16ba513d5741"}, + {file = "argon2_cffi-25.1.0.tar.gz", hash = "sha256:694ae5cc8a42f4c4e2bf2ca0e64e51e23a040c6a517a85074683d3959e1346c1"}, ] [[package]] name = "argon2-cffi-bindings" -version = "21.2.0" -requires_python = ">=3.6" +version = "25.1.0" +requires_python = ">=3.9" summary = "Low-level CFFI bindings for Argon2" dependencies = [ - "cffi>=1.0.1", + "cffi>=1.0.1; python_version < \"3.14\"", + "cffi>=2.0.0b1; python_version >= \"3.14\"", ] files = [ - {file = "argon2-cffi-bindings-21.2.0.tar.gz", hash = "sha256:bb89ceffa6c791807d1305ceb77dbfacc5aa499891d2c55661c6459651fc39e3"}, - {file = "argon2_cffi_bindings-21.2.0-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:ccb949252cb2ab3a08c02024acb77cfb179492d5701c7cbdbfd776124d4d2367"}, - {file = "argon2_cffi_bindings-21.2.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9524464572e12979364b7d600abf96181d3541da11e23ddf565a32e70bd4dc0d"}, - {file = "argon2_cffi_bindings-21.2.0-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b746dba803a79238e925d9046a63aa26bf86ab2a2fe74ce6b009a1c3f5c8f2ae"}, - {file = "argon2_cffi_bindings-21.2.0-cp36-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:58ed19212051f49a523abb1dbe954337dc82d947fb6e5a0da60f7c8471a8476c"}, - {file = "argon2_cffi_bindings-21.2.0-cp36-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:bd46088725ef7f58b5a1ef7ca06647ebaf0eb4baff7d1d0d177c6cc8744abd86"}, - {file = "argon2_cffi_bindings-21.2.0-cp36-abi3-musllinux_1_1_i686.whl", hash = "sha256:8cd69c07dd875537a824deec19f978e0f2078fdda07fd5c42ac29668dda5f40f"}, - {file = "argon2_cffi_bindings-21.2.0-cp36-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:f1152ac548bd5b8bcecfb0b0371f082037e47128653df2e8ba6e914d384f3c3e"}, - {file = "argon2_cffi_bindings-21.2.0-cp36-abi3-win32.whl", hash = "sha256:603ca0aba86b1349b147cab91ae970c63118a0f30444d4bc80355937c950c082"}, - {file = "argon2_cffi_bindings-21.2.0-cp36-abi3-win_amd64.whl", hash = "sha256:b2ef1c30440dbbcba7a5dc3e319408b59676e2e039e2ae11a8775ecf482b192f"}, - {file = "argon2_cffi_bindings-21.2.0-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:e415e3f62c8d124ee16018e491a009937f8cf7ebf5eb430ffc5de21b900dad93"}, + {file = "argon2_cffi_bindings-25.1.0-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:aecba1723ae35330a008418a91ea6cfcedf6d31e5fbaa056a166462ff066d500"}, + {file = "argon2_cffi_bindings-25.1.0-cp39-abi3-macosx_10_9_x86_64.whl", hash = "sha256:2630b6240b495dfab90aebe159ff784d08ea999aa4b0d17efa734055a07d2f44"}, + {file = "argon2_cffi_bindings-25.1.0-cp39-abi3-macosx_11_0_arm64.whl", hash = "sha256:7aef0c91e2c0fbca6fc68e7555aa60ef7008a739cbe045541e438373bc54d2b0"}, + {file = "argon2_cffi_bindings-25.1.0-cp39-abi3-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1e021e87faa76ae0d413b619fe2b65ab9a037f24c60a1e6cc43457ae20de6dc6"}, + {file = "argon2_cffi_bindings-25.1.0-cp39-abi3-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d3e924cfc503018a714f94a49a149fdc0b644eaead5d1f089330399134fa028a"}, + {file = "argon2_cffi_bindings-25.1.0-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:c87b72589133f0346a1cb8d5ecca4b933e3c9b64656c9d175270a000e73b288d"}, + {file = "argon2_cffi_bindings-25.1.0-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:1db89609c06afa1a214a69a462ea741cf735b29a57530478c06eb81dd403de99"}, + {file = "argon2_cffi_bindings-25.1.0-cp39-abi3-win32.whl", hash = "sha256:473bcb5f82924b1becbb637b63303ec8d10e84c8d241119419897a26116515d2"}, + {file = "argon2_cffi_bindings-25.1.0-cp39-abi3-win_amd64.whl", hash = "sha256:a98cd7d17e9f7ce244c0803cad3c23a7d379c301ba618a5fa76a67d116618b98"}, + {file = "argon2_cffi_bindings-25.1.0-cp39-abi3-win_arm64.whl", hash = "sha256:b0fdbcf513833809c882823f98dc2f931cf659d9a1429616ac3adebb49f5db94"}, + {file = "argon2_cffi_bindings-25.1.0.tar.gz", hash = "sha256:b957f3e6ea4d55d820e40ff76f450952807013d361a65d7f28acc0acbf29229d"}, ] [[package]] name = "arrow" -version = "1.3.0" +version = "1.4.0" requires_python = ">=3.8" summary = "Better dates & times for Python" dependencies = [ + "backports-zoneinfo==0.2.1; python_version < \"3.9\"", "python-dateutil>=2.7.0", - "types-python-dateutil>=2.8.10", + "tzdata; python_version >= \"3.9\"", ] files = [ - {file = "arrow-1.3.0-py3-none-any.whl", hash = "sha256:c728b120ebc00eb84e01882a6f5e7927a53960aa990ce7dd2b10f39005a67f80"}, - {file = "arrow-1.3.0.tar.gz", hash = "sha256:d4540617648cb5f895730f1ad8c82a65f2dad0166f57b75f3ca54759c4d67a85"}, + {file = "arrow-1.4.0-py3-none-any.whl", hash = "sha256:749f0769958ebdc79c173ff0b0670d59051a535fa26e8eba02953dc19eb43205"}, + {file = "arrow-1.4.0.tar.gz", hash = "sha256:ed0cc050e98001b8779e84d461b0098c4ac597e88704a655582b21d116e526d7"}, ] [[package]] name = "asttokens" -version = "3.0.0" +version = "3.0.1" requires_python = ">=3.8" summary = "Annotate AST trees with source code positions" files = [ - {file = "asttokens-3.0.0-py3-none-any.whl", hash = "sha256:e3078351a059199dd5138cb1c706e6430c05eff2ff136af5eb4790f9d28932e2"}, - {file = "asttokens-3.0.0.tar.gz", hash = "sha256:0dcd8baa8d62b0c1d118b399b2ddba3c4aff271d0d7a9e0d4c1681c79035bbc7"}, + {file = "asttokens-3.0.1-py3-none-any.whl", hash = "sha256:15a3ebc0f43c2d0a50eeafea25e19046c68398e487b9f1f5b517f7c0f40f976a"}, + {file = "asttokens-3.0.1.tar.gz", hash = "sha256:71a4ee5de0bde6a31d64f6b13f2293ac190344478f081c3d1bccfcf5eacb0cb7"}, ] [[package]] @@ -187,12 +201,12 @@ files = [ [[package]] name = "attrs" -version = "25.3.0" -requires_python = ">=3.8" +version = "25.4.0" +requires_python = ">=3.9" summary = "Classes Without Boilerplate" files = [ - {file = "attrs-25.3.0-py3-none-any.whl", hash = "sha256:427318ce031701fea540783410126f03899a97ffc6f61596ad581ac2e40e3bc3"}, - {file = "attrs-25.3.0.tar.gz", hash = "sha256:75d7cefc7fb576747b2c81b4442d4d4a1ce0900973527c011d1030fd3bf4af1b"}, + {file = "attrs-25.4.0-py3-none-any.whl", hash = "sha256:adcf7e2a1fb3b36ac48d97835bb6d8ade15b8dcce26aba8bf1d14847b57a3373"}, + {file = "attrs-25.4.0.tar.gz", hash = "sha256:16d5969b87f0859ef33a48b35d55ac1be6e42ae49d5e853b597db70c35c57e11"}, ] [[package]] @@ -208,18 +222,31 @@ files = [ {file = "babel-2.17.0.tar.gz", hash = "sha256:0c54cffb19f690cdcc52a3b50bcbf71e07a808d1c80d549f2459b9d2cf0afb9d"}, ] +[[package]] +name = "bashlex" +version = "0.18" +requires_python = ">=2.7, !=3.0, !=3.1, !=3.2, !=3.3, !=3.4" +summary = "Python parser for bash" +dependencies = [ + "enum34; python_version < \"3.4\"", +] +files = [ + {file = "bashlex-0.18-py2.py3-none-any.whl", hash = "sha256:91d73a23a3e51711919c1c899083890cdecffc91d8c088942725ac13e9dcfffa"}, + {file = "bashlex-0.18.tar.gz", hash = "sha256:5bb03a01c6d5676338c36fd1028009c8ad07e7d61d8a1ce3f513b7fff52796ee"}, +] + [[package]] name = "beautifulsoup4" -version = "4.13.4" +version = "4.14.3" requires_python = ">=3.7.0" summary = "Screen-scraping library" dependencies = [ - "soupsieve>1.2", + "soupsieve>=1.6.1", "typing-extensions>=4.0.0", ] files = [ - {file = "beautifulsoup4-4.13.4-py3-none-any.whl", hash = "sha256:9bbbb14bfde9d79f38b8cd5f8c7c85f4b8f2523190ebed90e950a8dea4cb1c4b"}, - {file = "beautifulsoup4-4.13.4.tar.gz", hash = "sha256:dbb3c4e1ceae6aefebdaf2423247260cd062430a410e38c66f2baa50a8437195"}, + {file = "beautifulsoup4-4.14.3-py3-none-any.whl", hash = "sha256:0918bfe44902e6ad8d57732ba310582e98da931428d231a5ecb9e7c703a735bb"}, + {file = "beautifulsoup4-4.14.3.tar.gz", hash = "sha256:6292b1c5186d356bba669ef9f7f051757099565ad9ada5dd630bd9de5fa7fb86"}, ] [[package]] @@ -251,35 +278,35 @@ files = [ [[package]] name = "bleach" -version = "6.2.0" -requires_python = ">=3.9" +version = "6.3.0" +requires_python = ">=3.10" summary = "An easy safelist-based HTML-sanitizing tool." dependencies = [ "webencodings", ] files = [ - {file = "bleach-6.2.0-py3-none-any.whl", hash = "sha256:117d9c6097a7c3d22fd578fcd8d35ff1e125df6736f554da4e432fdd63f31e5e"}, - {file = "bleach-6.2.0.tar.gz", hash = "sha256:123e894118b8a599fd80d3ec1a6d4cc7ce4e5882b1317a7e1ba69b56e95f991f"}, + {file = "bleach-6.3.0-py3-none-any.whl", hash = "sha256:fe10ec77c93ddf3d13a73b035abaac7a9f5e436513864ccdad516693213c65d6"}, + {file = "bleach-6.3.0.tar.gz", hash = "sha256:6f3b91b1c0a02bb9a78b5a454c92506aa0fdf197e1d5e114d2e00c6f64306d22"}, ] [[package]] name = "bleach" -version = "6.2.0" +version = "6.3.0" extras = ["css"] -requires_python = ">=3.9" +requires_python = ">=3.10" summary = "An easy safelist-based HTML-sanitizing tool." dependencies = [ - "bleach==6.2.0", + "bleach==6.3.0", "tinycss2<1.5,>=1.1.0", ] files = [ - {file = "bleach-6.2.0-py3-none-any.whl", hash = "sha256:117d9c6097a7c3d22fd578fcd8d35ff1e125df6736f554da4e432fdd63f31e5e"}, - {file = "bleach-6.2.0.tar.gz", hash = "sha256:123e894118b8a599fd80d3ec1a6d4cc7ce4e5882b1317a7e1ba69b56e95f991f"}, + {file = "bleach-6.3.0-py3-none-any.whl", hash = "sha256:fe10ec77c93ddf3d13a73b035abaac7a9f5e436513864ccdad516693213c65d6"}, + {file = "bleach-6.3.0.tar.gz", hash = "sha256:6f3b91b1c0a02bb9a78b5a454c92506aa0fdf197e1d5e114d2e00c6f64306d22"}, ] [[package]] name = "bokeh" -version = "3.7.3" +version = "3.8.1" requires_python = ">=3.10" summary = "Interactive plots and applications in the browser from Python" dependencies = [ @@ -295,155 +322,241 @@ dependencies = [ "xyzservices>=2021.09.1", ] files = [ - {file = "bokeh-3.7.3-py3-none-any.whl", hash = "sha256:b0e79dd737f088865212e4fdcb0f3b95d087f0f088bf8ca186a300ab1641e2c7"}, - {file = "bokeh-3.7.3.tar.gz", hash = "sha256:70a89a9f797b103d5ee6ad15fb7944adda115cf0da996ed0b75cfba61cb12f2b"}, + {file = "bokeh-3.8.1-py3-none-any.whl", hash = "sha256:89a66cb8bfe85e91bce144e3ccf3c4a6f0f1347e7006282972568ea0ecacbb00"}, + {file = "bokeh-3.8.1.tar.gz", hash = "sha256:40df8e632de367399d06979cbd76c9e68a133a3138e1adde37c4a4715ecb4d6e"}, +] + +[[package]] +name = "bracex" +version = "2.6" +requires_python = ">=3.9" +summary = "Bash style brace expander." +files = [ + {file = "bracex-2.6-py3-none-any.whl", hash = "sha256:0b0049264e7340b3ec782b5cb99beb325f36c3782a32e36e876452fd49a09952"}, + {file = "bracex-2.6.tar.gz", hash = "sha256:98f1347cd77e22ee8d967a30ad4e310b233f7754dbf31ff3fceb76145ba47dc7"}, +] + +[[package]] +name = "build" +version = "1.3.0" +requires_python = ">=3.9" +summary = "A simple, correct Python build frontend" +dependencies = [ + "colorama; os_name == \"nt\"", + "importlib-metadata>=4.6; python_full_version < \"3.10.2\"", + "packaging>=19.1", + "pyproject-hooks", + "tomli>=1.1.0; python_version < \"3.11\"", +] +files = [ + {file = "build-1.3.0-py3-none-any.whl", hash = "sha256:7145f0b5061ba90a1500d60bd1b13ca0a8a4cebdd0cc16ed8adf1c0e739f43b4"}, + {file = "build-1.3.0.tar.gz", hash = "sha256:698edd0ea270bde950f53aed21f3a0135672206f3911e0176261a31e0e07b397"}, ] [[package]] name = "certifi" -version = "2025.4.26" -requires_python = ">=3.6" +version = "2025.11.12" +requires_python = ">=3.7" summary = "Python package for providing Mozilla's CA Bundle." files = [ - {file = "certifi-2025.4.26-py3-none-any.whl", hash = "sha256:30350364dfe371162649852c63336a15c70c6510c2ad5015b21c2345311805f3"}, - {file = "certifi-2025.4.26.tar.gz", hash = "sha256:0a816057ea3cdefcef70270d2c515e4506bbc954f417fa5ade2021213bb8f0c6"}, + {file = "certifi-2025.11.12-py3-none-any.whl", hash = "sha256:97de8790030bbd5c2d96b7ec782fc2f7820ef8dba6db909ccf95449f2d062d4b"}, + {file = "certifi-2025.11.12.tar.gz", hash = "sha256:d8ab5478f2ecd78af242878415affce761ca6bc54a22a27e026d7c25357c3316"}, ] [[package]] name = "cffi" -version = "1.17.1" -requires_python = ">=3.8" +version = "2.0.0" +requires_python = ">=3.9" summary = "Foreign Function Interface for Python calling C code." dependencies = [ - "pycparser", -] -files = [ - {file = "cffi-1.17.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a45e3c6913c5b87b3ff120dcdc03f6131fa0065027d0ed7ee6190736a74cd401"}, - {file = "cffi-1.17.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:30c5e0cb5ae493c04c8b42916e52ca38079f1b235c2f8ae5f4527b963c401caf"}, - {file = "cffi-1.17.1-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f75c7ab1f9e4aca5414ed4d8e5c0e303a34f4421f8a0d47a4d019ceff0ab6af4"}, - {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a1ed2dd2972641495a3ec98445e09766f077aee98a1c896dcb4ad0d303628e41"}, - {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:46bf43160c1a35f7ec506d254e5c890f3c03648a4dbac12d624e4490a7046cd1"}, - {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a24ed04c8ffd54b0729c07cee15a81d964e6fee0e3d4d342a27b020d22959dc6"}, - {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:610faea79c43e44c71e1ec53a554553fa22321b65fae24889706c0a84d4ad86d"}, - {file = "cffi-1.17.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:a9b15d491f3ad5d692e11f6b71f7857e7835eb677955c00cc0aefcd0669adaf6"}, - {file = "cffi-1.17.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:de2ea4b5833625383e464549fec1bc395c1bdeeb5f25c4a3a82b5a8c756ec22f"}, - {file = "cffi-1.17.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:fc48c783f9c87e60831201f2cce7f3b2e4846bf4d8728eabe54d60700b318a0b"}, - {file = "cffi-1.17.1-cp311-cp311-win32.whl", hash = "sha256:85a950a4ac9c359340d5963966e3e0a94a676bd6245a4b55bc43949eee26a655"}, - {file = "cffi-1.17.1-cp311-cp311-win_amd64.whl", hash = "sha256:caaf0640ef5f5517f49bc275eca1406b0ffa6aa184892812030f04c2abf589a0"}, - {file = "cffi-1.17.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:805b4371bf7197c329fcb3ead37e710d1bca9da5d583f5073b799d5c5bd1eee4"}, - {file = "cffi-1.17.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:733e99bc2df47476e3848417c5a4540522f234dfd4ef3ab7fafdf555b082ec0c"}, - {file = "cffi-1.17.1-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1257bdabf294dceb59f5e70c64a3e2f462c30c7ad68092d01bbbfb1c16b1ba36"}, - {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da95af8214998d77a98cc14e3a3bd00aa191526343078b530ceb0bd710fb48a5"}, - {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d63afe322132c194cf832bfec0dc69a99fb9bb6bbd550f161a49e9e855cc78ff"}, - {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f79fc4fc25f1c8698ff97788206bb3c2598949bfe0fef03d299eb1b5356ada99"}, - {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b62ce867176a75d03a665bad002af8e6d54644fad99a3c70905c543130e39d93"}, - {file = "cffi-1.17.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:386c8bf53c502fff58903061338ce4f4950cbdcb23e2902d86c0f722b786bbe3"}, - {file = "cffi-1.17.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4ceb10419a9adf4460ea14cfd6bc43d08701f0835e979bf821052f1805850fe8"}, - {file = "cffi-1.17.1-cp312-cp312-win32.whl", hash = "sha256:a08d7e755f8ed21095a310a693525137cfe756ce62d066e53f502a83dc550f65"}, - {file = "cffi-1.17.1-cp312-cp312-win_amd64.whl", hash = "sha256:51392eae71afec0d0c8fb1a53b204dbb3bcabcb3c9b807eedf3e1e6ccf2de903"}, - {file = "cffi-1.17.1.tar.gz", hash = "sha256:1c39c6016c32bc48dd54561950ebd6836e1670f2ae46128f67cf49e789c52824"}, + "pycparser; implementation_name != \"PyPy\"", +] +files = [ + {file = "cffi-2.0.0-cp311-cp311-macosx_10_13_x86_64.whl", hash = "sha256:b4c854ef3adc177950a8dfc81a86f5115d2abd545751a304c5bcf2c2c7283cfe"}, + {file = "cffi-2.0.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2de9a304e27f7596cd03d16f1b7c72219bd944e99cc52b84d0145aefb07cbd3c"}, + {file = "cffi-2.0.0-cp311-cp311-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:baf5215e0ab74c16e2dd324e8ec067ef59e41125d3eade2b863d294fd5035c92"}, + {file = "cffi-2.0.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:730cacb21e1bdff3ce90babf007d0a0917cc3e6492f336c2f0134101e0944f93"}, + {file = "cffi-2.0.0-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:6824f87845e3396029f3820c206e459ccc91760e8fa24422f8b0c3d1731cbec5"}, + {file = "cffi-2.0.0-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:9de40a7b0323d889cf8d23d1ef214f565ab154443c42737dfe52ff82cf857664"}, + {file = "cffi-2.0.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:8941aaadaf67246224cee8c3803777eed332a19d909b47e29c9842ef1e79ac26"}, + {file = "cffi-2.0.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:a05d0c237b3349096d3981b727493e22147f934b20f6f125a3eba8f994bec4a9"}, + {file = "cffi-2.0.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:94698a9c5f91f9d138526b48fe26a199609544591f859c870d477351dc7b2414"}, + {file = "cffi-2.0.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:5fed36fccc0612a53f1d4d9a816b50a36702c28a2aa880cb8a122b3466638743"}, + {file = "cffi-2.0.0-cp311-cp311-win32.whl", hash = "sha256:c649e3a33450ec82378822b3dad03cc228b8f5963c0c12fc3b1e0ab940f768a5"}, + {file = "cffi-2.0.0-cp311-cp311-win_amd64.whl", hash = "sha256:66f011380d0e49ed280c789fbd08ff0d40968ee7b665575489afa95c98196ab5"}, + {file = "cffi-2.0.0-cp311-cp311-win_arm64.whl", hash = "sha256:c6638687455baf640e37344fe26d37c404db8b80d037c3d29f58fe8d1c3b194d"}, + {file = "cffi-2.0.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:6d02d6655b0e54f54c4ef0b94eb6be0607b70853c45ce98bd278dc7de718be5d"}, + {file = "cffi-2.0.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8eca2a813c1cb7ad4fb74d368c2ffbbb4789d377ee5bb8df98373c2cc0dee76c"}, + {file = "cffi-2.0.0-cp312-cp312-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:21d1152871b019407d8ac3985f6775c079416c282e431a4da6afe7aefd2bccbe"}, + {file = "cffi-2.0.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:b21e08af67b8a103c71a250401c78d5e0893beff75e28c53c98f4de42f774062"}, + {file = "cffi-2.0.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:1e3a615586f05fc4065a8b22b8152f0c1b00cdbc60596d187c2a74f9e3036e4e"}, + {file = "cffi-2.0.0-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:81afed14892743bbe14dacb9e36d9e0e504cd204e0b165062c488942b9718037"}, + {file = "cffi-2.0.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:3e17ed538242334bf70832644a32a7aae3d83b57567f9fd60a26257e992b79ba"}, + {file = "cffi-2.0.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:3925dd22fa2b7699ed2617149842d2e6adde22b262fcbfada50e3d195e4b3a94"}, + {file = "cffi-2.0.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:2c8f814d84194c9ea681642fd164267891702542f028a15fc97d4674b6206187"}, + {file = "cffi-2.0.0-cp312-cp312-win32.whl", hash = "sha256:da902562c3e9c550df360bfa53c035b2f241fed6d9aef119048073680ace4a18"}, + {file = "cffi-2.0.0-cp312-cp312-win_amd64.whl", hash = "sha256:da68248800ad6320861f129cd9c1bf96ca849a2771a59e0344e88681905916f5"}, + {file = "cffi-2.0.0-cp312-cp312-win_arm64.whl", hash = "sha256:4671d9dd5ec934cb9a73e7ee9676f9362aba54f7f34910956b84d727b0d73fb6"}, + {file = "cffi-2.0.0.tar.gz", hash = "sha256:44d1b5909021139fe36001ae048dbdde8214afa20200eda0f64c068cac5d5529"}, ] [[package]] name = "cftime" -version = "1.6.4.post1" -requires_python = ">=3.8" +version = "1.6.5" +requires_python = ">=3.10" summary = "Time-handling functionality from netcdf4-python" dependencies = [ - "numpy>1.13.3; python_version < \"3.12.0.rc1\"", - "numpy>=1.26.0b1; python_version >= \"3.12.0.rc1\"", + "numpy>=1.21.2", ] files = [ - {file = "cftime-1.6.4.post1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:1bf7be0a0afc87628cb8c8483412aac6e48e83877004faa0936afb5bf8a877ba"}, - {file = "cftime-1.6.4.post1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:0f64ca83acc4e3029f737bf3a32530ffa1fbf53124f5bee70b47548bc58671a7"}, - {file = "cftime-1.6.4.post1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d7ebdfd81726b0cfb8b524309224fa952898dfa177c13d5f6af5b18cefbf497d"}, - {file = "cftime-1.6.4.post1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c9ea0965a4c87739aebd84fe8eed966e5809d10065eeffd35c99c274b6f8da15"}, - {file = "cftime-1.6.4.post1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:800a18aea4e8cb2b206450397cb8a53b154798738af3cdd3c922ce1ca198b0e6"}, - {file = "cftime-1.6.4.post1-cp311-cp311-win_amd64.whl", hash = "sha256:5dcfc872f455db1f12eabe3c3ba98e93757cd60ed3526a53246e966ccde46c8a"}, - {file = "cftime-1.6.4.post1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:a590f73506f4704ba5e154ef55bfbaed5e1b4ac170f3caeb8c58e4f2c619ee4e"}, - {file = "cftime-1.6.4.post1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:933cb10e1af4e362e77f513e3eb92b34a688729ddbf938bbdfa5ac20a7f44ba0"}, - {file = "cftime-1.6.4.post1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cf17a1b36f62e9e73c4c9363dd811e1bbf1170f5ac26d343fb26012ccf482908"}, - {file = "cftime-1.6.4.post1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8e18021f421aa26527bad8688c1acf0c85fa72730beb6efce969c316743294f2"}, - {file = "cftime-1.6.4.post1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:5835b9d622f9304d1c23a35603a0f068739f428d902860f25e6e7e5a1b7cd8ea"}, - {file = "cftime-1.6.4.post1-cp312-cp312-win_amd64.whl", hash = "sha256:7f50bf0d1b664924aaee636eb2933746b942417d1f8b82ab6c1f6e8ba0da6885"}, - {file = "cftime-1.6.4.post1.tar.gz", hash = "sha256:50ac76cc9f10ab7bd46e44a71c51a6927051b499b4407df4f29ab13d741b942f"}, + {file = "cftime-1.6.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:474e728f5a387299418f8d7cb9c52248dcd5d977b2a01de7ec06bba572e26b02"}, + {file = "cftime-1.6.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ab9e80d4de815cac2e2d88a2335231254980e545d0196eb34ee8f7ed612645f1"}, + {file = "cftime-1.6.5-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:ad24a563784e4795cb3d04bd985895b5db49ace2cbb71fcf1321fd80141f9a52"}, + {file = "cftime-1.6.5-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:a3cda6fd12c7fb25eff40a6a857a2bf4d03e8cc71f80485d8ddc65ccbd80f16a"}, + {file = "cftime-1.6.5-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:28cda78d685397ba23d06273b9c916c3938d8d9e6872a537e76b8408a321369b"}, + {file = "cftime-1.6.5-cp311-cp311-win_amd64.whl", hash = "sha256:93ead088e3a216bdeb9368733a0ef89a7451dfc1d2de310c1c0366a56ad60dc8"}, + {file = "cftime-1.6.5-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:eef25caed5ebd003a38719bd3ff8847cd52ef2ea56c3ebdb2c9345ba131fc7c5"}, + {file = "cftime-1.6.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:c87d2f3b949e45463e559233c69e6a9cf691b2b378c1f7556166adfabbd1c6b0"}, + {file = "cftime-1.6.5-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:82cb413973cc51b55642b3a1ca5b28db5b93a294edbef7dc049c074b478b4647"}, + {file = "cftime-1.6.5-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:85ba8e7356d239cfe56ef7707ac30feaf67964642ac760a82e507ee3c5db4ac4"}, + {file = "cftime-1.6.5-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:456039af7907a3146689bb80bfd8edabd074c7f3b4eca61f91b9c2670addd7ad"}, + {file = "cftime-1.6.5-cp312-cp312-win_amd64.whl", hash = "sha256:da84534c43699960dc980a9a765c33433c5de1a719a4916748c2d0e97a071e44"}, + {file = "cftime-1.6.5.tar.gz", hash = "sha256:8225fed6b9b43fb87683ebab52130450fc1730011150d3092096a90e54d1e81e"}, ] [[package]] name = "charset-normalizer" -version = "3.4.2" +version = "3.4.4" requires_python = ">=3.7" summary = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." files = [ - {file = "charset_normalizer-3.4.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:be1e352acbe3c78727a16a455126d9ff83ea2dfdcbc83148d2982305a04714c2"}, - {file = "charset_normalizer-3.4.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aa88ca0b1932e93f2d961bf3addbb2db902198dca337d88c89e1559e066e7645"}, - {file = "charset_normalizer-3.4.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d524ba3f1581b35c03cb42beebab4a13e6cdad7b36246bd22541fa585a56cccd"}, - {file = "charset_normalizer-3.4.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28a1005facc94196e1fb3e82a3d442a9d9110b8434fc1ded7a24a2983c9888d8"}, - {file = "charset_normalizer-3.4.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fdb20a30fe1175ecabed17cbf7812f7b804b8a315a25f24678bcdf120a90077f"}, - {file = "charset_normalizer-3.4.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0f5d9ed7f254402c9e7d35d2f5972c9bbea9040e99cd2861bd77dc68263277c7"}, - {file = "charset_normalizer-3.4.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:efd387a49825780ff861998cd959767800d54f8308936b21025326de4b5a42b9"}, - {file = "charset_normalizer-3.4.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:f0aa37f3c979cf2546b73e8222bbfa3dc07a641585340179d768068e3455e544"}, - {file = "charset_normalizer-3.4.2-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:e70e990b2137b29dc5564715de1e12701815dacc1d056308e2b17e9095372a82"}, - {file = "charset_normalizer-3.4.2-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:0c8c57f84ccfc871a48a47321cfa49ae1df56cd1d965a09abe84066f6853b9c0"}, - {file = "charset_normalizer-3.4.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:6b66f92b17849b85cad91259efc341dce9c1af48e2173bf38a85c6329f1033e5"}, - {file = "charset_normalizer-3.4.2-cp311-cp311-win32.whl", hash = "sha256:daac4765328a919a805fa5e2720f3e94767abd632ae410a9062dff5412bae65a"}, - {file = "charset_normalizer-3.4.2-cp311-cp311-win_amd64.whl", hash = "sha256:e53efc7c7cee4c1e70661e2e112ca46a575f90ed9ae3fef200f2a25e954f4b28"}, - {file = "charset_normalizer-3.4.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:0c29de6a1a95f24b9a1aa7aefd27d2487263f00dfd55a77719b530788f75cff7"}, - {file = "charset_normalizer-3.4.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cddf7bd982eaa998934a91f69d182aec997c6c468898efe6679af88283b498d3"}, - {file = "charset_normalizer-3.4.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fcbe676a55d7445b22c10967bceaaf0ee69407fbe0ece4d032b6eb8d4565982a"}, - {file = "charset_normalizer-3.4.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d41c4d287cfc69060fa91cae9683eacffad989f1a10811995fa309df656ec214"}, - {file = "charset_normalizer-3.4.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4e594135de17ab3866138f496755f302b72157d115086d100c3f19370839dd3a"}, - {file = "charset_normalizer-3.4.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cf713fe9a71ef6fd5adf7a79670135081cd4431c2943864757f0fa3a65b1fafd"}, - {file = "charset_normalizer-3.4.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:a370b3e078e418187da8c3674eddb9d983ec09445c99a3a263c2011993522981"}, - {file = "charset_normalizer-3.4.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:a955b438e62efdf7e0b7b52a64dc5c3396e2634baa62471768a64bc2adb73d5c"}, - {file = "charset_normalizer-3.4.2-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:7222ffd5e4de8e57e03ce2cef95a4c43c98fcb72ad86909abdfc2c17d227fc1b"}, - {file = "charset_normalizer-3.4.2-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:bee093bf902e1d8fc0ac143c88902c3dfc8941f7ea1d6a8dd2bcb786d33db03d"}, - {file = "charset_normalizer-3.4.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:dedb8adb91d11846ee08bec4c8236c8549ac721c245678282dcb06b221aab59f"}, - {file = "charset_normalizer-3.4.2-cp312-cp312-win32.whl", hash = "sha256:db4c7bf0e07fc3b7d89ac2a5880a6a8062056801b83ff56d8464b70f65482b6c"}, - {file = "charset_normalizer-3.4.2-cp312-cp312-win_amd64.whl", hash = "sha256:5a9979887252a82fefd3d3ed2a8e3b937a7a809f65dcb1e068b090e165bbe99e"}, - {file = "charset_normalizer-3.4.2-py3-none-any.whl", hash = "sha256:7f56930ab0abd1c45cd15be65cc741c28b1c9a34876ce8c17a2fa107810c0af0"}, - {file = "charset_normalizer-3.4.2.tar.gz", hash = "sha256:5baececa9ecba31eff645232d59845c07aa030f0c81ee70184a90d35099a0e63"}, + {file = "charset_normalizer-3.4.4-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:6e1fcf0720908f200cd21aa4e6750a48ff6ce4afe7ff5a79a90d5ed8a08296f8"}, + {file = "charset_normalizer-3.4.4-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5f819d5fe9234f9f82d75bdfa9aef3a3d72c4d24a6e57aeaebba32a704553aa0"}, + {file = "charset_normalizer-3.4.4-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:a59cb51917aa591b1c4e6a43c132f0cdc3c76dbad6155df4e28ee626cc77a0a3"}, + {file = "charset_normalizer-3.4.4-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:8ef3c867360f88ac904fd3f5e1f902f13307af9052646963ee08ff4f131adafc"}, + {file = "charset_normalizer-3.4.4-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d9e45d7faa48ee908174d8fe84854479ef838fc6a705c9315372eacbc2f02897"}, + {file = "charset_normalizer-3.4.4-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:840c25fb618a231545cbab0564a799f101b63b9901f2569faecd6b222ac72381"}, + {file = "charset_normalizer-3.4.4-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:ca5862d5b3928c4940729dacc329aa9102900382fea192fc5e52eb69d6093815"}, + {file = "charset_normalizer-3.4.4-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d9c7f57c3d666a53421049053eaacdd14bbd0a528e2186fcb2e672effd053bb0"}, + {file = "charset_normalizer-3.4.4-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:277e970e750505ed74c832b4bf75dac7476262ee2a013f5574dd49075879e161"}, + {file = "charset_normalizer-3.4.4-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:31fd66405eaf47bb62e8cd575dc621c56c668f27d46a61d975a249930dd5e2a4"}, + {file = "charset_normalizer-3.4.4-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:0d3d8f15c07f86e9ff82319b3d9ef6f4bf907608f53fe9d92b28ea9ae3d1fd89"}, + {file = "charset_normalizer-3.4.4-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:9f7fcd74d410a36883701fafa2482a6af2ff5ba96b9a620e9e0721e28ead5569"}, + {file = "charset_normalizer-3.4.4-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:ebf3e58c7ec8a8bed6d66a75d7fb37b55e5015b03ceae72a8e7c74495551e224"}, + {file = "charset_normalizer-3.4.4-cp311-cp311-win32.whl", hash = "sha256:eecbc200c7fd5ddb9a7f16c7decb07b566c29fa2161a16cf67b8d068bd21690a"}, + {file = "charset_normalizer-3.4.4-cp311-cp311-win_amd64.whl", hash = "sha256:5ae497466c7901d54b639cf42d5b8c1b6a4fead55215500d2f486d34db48d016"}, + {file = "charset_normalizer-3.4.4-cp311-cp311-win_arm64.whl", hash = "sha256:65e2befcd84bc6f37095f5961e68a6f077bf44946771354a28ad434c2cce0ae1"}, + {file = "charset_normalizer-3.4.4-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:0a98e6759f854bd25a58a73fa88833fba3b7c491169f86ce1180c948ab3fd394"}, + {file = "charset_normalizer-3.4.4-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b5b290ccc2a263e8d185130284f8501e3e36c5e02750fc6b6bdeb2e9e96f1e25"}, + {file = "charset_normalizer-3.4.4-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:74bb723680f9f7a6234dcf67aea57e708ec1fbdf5699fb91dfd6f511b0a320ef"}, + {file = "charset_normalizer-3.4.4-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f1e34719c6ed0b92f418c7c780480b26b5d9c50349e9a9af7d76bf757530350d"}, + {file = "charset_normalizer-3.4.4-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:2437418e20515acec67d86e12bf70056a33abdacb5cb1655042f6538d6b085a8"}, + {file = "charset_normalizer-3.4.4-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:11d694519d7f29d6cd09f6ac70028dba10f92f6cdd059096db198c283794ac86"}, + {file = "charset_normalizer-3.4.4-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:ac1c4a689edcc530fc9d9aa11f5774b9e2f33f9a0c6a57864e90908f5208d30a"}, + {file = "charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:21d142cc6c0ec30d2efee5068ca36c128a30b0f2c53c1c07bd78cb6bc1d3be5f"}, + {file = "charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:5dbe56a36425d26d6cfb40ce79c314a2e4dd6211d51d6d2191c00bed34f354cc"}, + {file = "charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:5bfbb1b9acf3334612667b61bd3002196fe2a1eb4dd74d247e0f2a4d50ec9bbf"}, + {file = "charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:d055ec1e26e441f6187acf818b73564e6e6282709e9bcb5b63f5b23068356a15"}, + {file = "charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:af2d8c67d8e573d6de5bc30cdb27e9b95e49115cd9baad5ddbd1a6207aaa82a9"}, + {file = "charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:780236ac706e66881f3b7f2f32dfe90507a09e67d1d454c762cf642e6e1586e0"}, + {file = "charset_normalizer-3.4.4-cp312-cp312-win32.whl", hash = "sha256:5833d2c39d8896e4e19b689ffc198f08ea58116bee26dea51e362ecc7cd3ed26"}, + {file = "charset_normalizer-3.4.4-cp312-cp312-win_amd64.whl", hash = "sha256:a79cfe37875f822425b89a82333404539ae63dbdddf97f84dcbc3d339aae9525"}, + {file = "charset_normalizer-3.4.4-cp312-cp312-win_arm64.whl", hash = "sha256:376bec83a63b8021bb5c8ea75e21c4ccb86e7e45ca4eb81146091b56599b80c3"}, + {file = "charset_normalizer-3.4.4-py3-none-any.whl", hash = "sha256:7a32c560861a02ff789ad905a2fe94e3f840803362c84fecf1851cb4cf3dc37f"}, + {file = "charset_normalizer-3.4.4.tar.gz", hash = "sha256:94537985111c35f28720e43603b8e7b43a6ecfb2ce1d3058bbe955b73404e21a"}, +] + +[[package]] +name = "cibuildwheel" +version = "3.3.0" +requires_python = ">=3.11" +summary = "Build Python wheels on CI with minimal configuration." +dependencies = [ + "bashlex!=0.13", + "bracex", + "build>=1.0.0", + "certifi", + "dependency-groups>=1.2", + "filelock", + "humanize", + "packaging>=20.9", + "patchelf; (sys_platform == \"linux\" or sys_platform == \"darwin\") and (platform_machine == \"x86_64\" or platform_machine == \"arm64\" or platform_machine == \"aarch64\")", + "platformdirs", + "pyelftools>=0.29", + "wheel>=0.33.6", +] +files = [ + {file = "cibuildwheel-3.3.0-py3-none-any.whl", hash = "sha256:99bdcc34e27f9160bfeb0ef8a49fcc5d0378369ec50d4f587e093431d7f5de71"}, + {file = "cibuildwheel-3.3.0.tar.gz", hash = "sha256:034f606fa0b69b8f6e160a0fa0eb52eba797dd4dc4edcbcb34491f592e8fb1a1"}, ] [[package]] name = "clarabel" -version = "0.10.0" +version = "0.11.1" requires_python = ">=3.9" summary = "Clarabel Conic Interior Point Solver for Rust / Python" dependencies = [ + "cffi", "numpy", "scipy", ] files = [ - {file = "clarabel-0.10.0-cp39-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:ac0375778b351ed0a6a209a3a671e438181f640e98ea56761acf44681f05f211"}, - {file = "clarabel-0.10.0-cp39-abi3-macosx_10_12_x86_64.whl", hash = "sha256:385c29169918a0fbf7eaece919db381120519241d9806f65b291444ef52deccc"}, - {file = "clarabel-0.10.0-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:325468980cd4495005926d413ccca4bb534e52ecc9e43fbd915f5d0e63859bd8"}, - {file = "clarabel-0.10.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9be6910e0ae1694996aa0c5f3db9b99ab6b619f6735ad178086b6f1e3eeef5e2"}, - {file = "clarabel-0.10.0-cp39-abi3-win_amd64.whl", hash = "sha256:7871b6f499ad66f71d4e7fb40754c4d986d4316f242beb62ff4f63a69785a50c"}, - {file = "clarabel-0.10.0.tar.gz", hash = "sha256:a8a2105058fd7db54718be53c48715a50910500b10ff0b8f5380434e69c10a10"}, + {file = "clarabel-0.11.1-cp39-abi3-macosx_10_12_x86_64.whl", hash = "sha256:c39160e4222040f051f2a0598691c4f9126b4d17f5b9e7678f76c71d611e12d8"}, + {file = "clarabel-0.11.1-cp39-abi3-macosx_11_0_arm64.whl", hash = "sha256:8963687ee250d27310d139eea5a6816f9c3ae31f33691b56579ca4f0f0b64b63"}, + {file = "clarabel-0.11.1-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e4837b9d0db01e98239f04b1e3526a6cf568529d3c19a8b3f591befdc467f9bb"}, + {file = "clarabel-0.11.1-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c8c41aaa6f3f8c0f3bd9d86c3e568dcaee079562c075bd2ec9fb3a80287380ef"}, + {file = "clarabel-0.11.1-cp39-abi3-win_amd64.whl", hash = "sha256:557d5148a4377ae1980b65d00605ae870a8f34f95f0f6a41e04aa6d3edf67148"}, + {file = "clarabel-0.11.1.tar.gz", hash = "sha256:e7c41c47f0e59aeab99aefff9e58af4a8753ee5269bbeecbd5526fc6f41b9598"}, ] [[package]] name = "click" -version = "8.2.0" +version = "8.3.1" requires_python = ">=3.10" summary = "Composable command line interface toolkit" dependencies = [ "colorama; platform_system == \"Windows\"", ] files = [ - {file = "click-8.2.0-py3-none-any.whl", hash = "sha256:6b303f0b2aa85f1cb4e5303078fadcbcd4e476f114fab9b5007005711839325c"}, - {file = "click-8.2.0.tar.gz", hash = "sha256:f5452aeddd9988eefa20f90f05ab66f17fce1ee2a36907fd30b05bbb5953814d"}, + {file = "click-8.3.1-py3-none-any.whl", hash = "sha256:981153a64e25f12d547d3426c367a4857371575ee7ad18df2a6183ab0545b2a6"}, + {file = "click-8.3.1.tar.gz", hash = "sha256:12ff4785d337a1bb490bb7e9c2b1ee5da3112e94a8622f26a6c77f5d2fc6842a"}, ] [[package]] name = "cloudpickle" -version = "3.1.1" +version = "3.1.2" requires_python = ">=3.8" summary = "Pickler class to extend the standard pickle.Pickler functionality" files = [ - {file = "cloudpickle-3.1.1-py3-none-any.whl", hash = "sha256:c8c5a44295039331ee9dad40ba100a9c7297b6f988e50e87ccdf3765a668350e"}, - {file = "cloudpickle-3.1.1.tar.gz", hash = "sha256:b216fa8ae4019d5482a8ac3c95d8f6346115d8835911fd4aefd1a445e4242c64"}, + {file = "cloudpickle-3.1.2-py3-none-any.whl", hash = "sha256:9acb47f6afd73f60dc1df93bb801b472f05ff42fa6c84167d25cb206be1fbf4a"}, + {file = "cloudpickle-3.1.2.tar.gz", hash = "sha256:7fda9eb655c9c230dab534f1983763de5835249750e85fbcef43aaa30a9a2414"}, +] + +[[package]] +name = "cmake" +version = "4.2.0" +requires_python = ">=3.8" +summary = "CMake is an open-source, cross-platform family of tools designed to build, test and package software" +files = [ + {file = "cmake-4.2.0-py3-none-macosx_10_10_universal2.whl", hash = "sha256:28595ec42fb6f81128b7a9bdbdfcb7b785ad197dbfb1b785cec5727a97a521f4"}, + {file = "cmake-4.2.0-py3-none-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:1a914c39a9349246b66089e6d741f1a3009c32fcd3a5110f9ddfc49adb4952c2"}, + {file = "cmake-4.2.0-py3-none-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:0940b5b00d2b65efbd409bfe83c4144a1a4f9bac5845c2c2f52b5cb71d5ca87f"}, + {file = "cmake-4.2.0-py3-none-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:a94596c64c3a302ad27fd2aa23dd19829b3a64e9493adf87758b0c7ceee6e544"}, + {file = "cmake-4.2.0-py3-none-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:1b537c69c4e91a29e82e2651e54f92b9794f4f7e9bb5385951065272cd11abe0"}, + {file = "cmake-4.2.0-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:5461ceca47ad352bdb3db2fdd5affdbc5707aaee415c5ff12773b8cc0d5f5949"}, + {file = "cmake-4.2.0-py3-none-manylinux_2_31_armv7l.whl", hash = "sha256:c4ea343eba9896b8ae94ffc7141902c2a40ce5ade5be1ebe5d2dc14109a4d9b4"}, + {file = "cmake-4.2.0-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:9f34c9018425767e4ff42b66442a57dea34809341208c5de5432ec2a87bdce59"}, + {file = "cmake-4.2.0-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:de8784c73dc24c34f6e9cadafc4848db5ff124aaf372e58b6550ed50726a81f9"}, + {file = "cmake-4.2.0-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:3b71cc13ba664b19eddbdf68ab30f12c27af93f987ee5ef66ce585d0b4ef5614"}, + {file = "cmake-4.2.0-py3-none-musllinux_1_2_i686.whl", hash = "sha256:3dd6dcb08b5562e22f6b433d45bd07e3ef2e156284ddeefcb9da4ec68b9ba6bb"}, + {file = "cmake-4.2.0-py3-none-musllinux_1_2_ppc64le.whl", hash = "sha256:1971a8ef69a31e814cb72c48f39bcbe6b45fff4afced4a3970c85dda7f4a755c"}, + {file = "cmake-4.2.0-py3-none-musllinux_1_2_riscv64.whl", hash = "sha256:ce565817a47798d75d6b17b21b2389826dee069e2a9eeb07beefc6f055e79191"}, + {file = "cmake-4.2.0-py3-none-musllinux_1_2_s390x.whl", hash = "sha256:c43baab5a829b92660d4eaf2896063da49d500a066a5088139d87793cb75b2e0"}, + {file = "cmake-4.2.0-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:bf11883a4cb3529f69746857df9733cae6175f07361f8016f8f050a3177e7767"}, + {file = "cmake-4.2.0-py3-none-win32.whl", hash = "sha256:a052030a9722c55d50025fac1f74b499aa2ce0cb137733aa1c6fb49689f560cb"}, + {file = "cmake-4.2.0-py3-none-win_amd64.whl", hash = "sha256:fb33a0c0486c3f4923a133dbeef4d009b798f1d4e6768381670736665a7f8c0a"}, + {file = "cmake-4.2.0-py3-none-win_arm64.whl", hash = "sha256:5c0dbe7a37991720d89c84825a4818f19debc8b10d5e4636b56c8fc08bec7a00"}, + {file = "cmake-4.2.0.tar.gz", hash = "sha256:7744c20e4a23e68dea276d819767d2bdbb45442cc342560b03ff693b755cd181"}, ] [[package]] @@ -458,117 +571,128 @@ files = [ [[package]] name = "comm" -version = "0.2.2" +version = "0.2.3" requires_python = ">=3.8" summary = "Jupyter Python Comm implementation, for usage in ipykernel, xeus-python etc." -dependencies = [ - "traitlets>=4", -] files = [ - {file = "comm-0.2.2-py3-none-any.whl", hash = "sha256:e6fb86cb70ff661ee8c9c14e7d36d6de3b4066f1441be4063df9c5009f0a64d3"}, - {file = "comm-0.2.2.tar.gz", hash = "sha256:3fd7a84065306e07bea1773df6eb8282de51ba82f77c72f9c85716ab11fe980e"}, + {file = "comm-0.2.3-py3-none-any.whl", hash = "sha256:c615d91d75f7f04f095b30d1c1711babd43bdc6419c1be9886a85f2f4e489417"}, + {file = "comm-0.2.3.tar.gz", hash = "sha256:2dc8048c10962d55d7ad693be1e7045d891b7ce8d999c97963a5e3e99c055971"}, ] [[package]] name = "contourpy" -version = "1.3.2" -requires_python = ">=3.10" +version = "1.3.3" +requires_python = ">=3.11" summary = "Python library for calculating contours of 2D quadrilateral grids" dependencies = [ - "numpy>=1.23", -] -files = [ - {file = "contourpy-1.3.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6a37a2fb93d4df3fc4c0e363ea4d16f83195fc09c891bc8ce072b9d084853445"}, - {file = "contourpy-1.3.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:b7cd50c38f500bbcc9b6a46643a40e0913673f869315d8e70de0438817cb7773"}, - {file = "contourpy-1.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d6658ccc7251a4433eebd89ed2672c2ed96fba367fd25ca9512aa92a4b46c4f1"}, - {file = "contourpy-1.3.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:70771a461aaeb335df14deb6c97439973d253ae70660ca085eec25241137ef43"}, - {file = "contourpy-1.3.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:65a887a6e8c4cd0897507d814b14c54a8c2e2aa4ac9f7686292f9769fcf9a6ab"}, - {file = "contourpy-1.3.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3859783aefa2b8355697f16642695a5b9792e7a46ab86da1118a4a23a51a33d7"}, - {file = "contourpy-1.3.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:eab0f6db315fa4d70f1d8ab514e527f0366ec021ff853d7ed6a2d33605cf4b83"}, - {file = "contourpy-1.3.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:d91a3ccc7fea94ca0acab82ceb77f396d50a1f67412efe4c526f5d20264e6ecd"}, - {file = "contourpy-1.3.2-cp311-cp311-win32.whl", hash = "sha256:1c48188778d4d2f3d48e4643fb15d8608b1d01e4b4d6b0548d9b336c28fc9b6f"}, - {file = "contourpy-1.3.2-cp311-cp311-win_amd64.whl", hash = "sha256:5ebac872ba09cb8f2131c46b8739a7ff71de28a24c869bcad554477eb089a878"}, - {file = "contourpy-1.3.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:4caf2bcd2969402bf77edc4cb6034c7dd7c0803213b3523f111eb7460a51b8d2"}, - {file = "contourpy-1.3.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:82199cb78276249796419fe36b7386bd8d2cc3f28b3bc19fe2454fe2e26c4c15"}, - {file = "contourpy-1.3.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:106fab697af11456fcba3e352ad50effe493a90f893fca6c2ca5c033820cea92"}, - {file = "contourpy-1.3.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d14f12932a8d620e307f715857107b1d1845cc44fdb5da2bc8e850f5ceba9f87"}, - {file = "contourpy-1.3.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:532fd26e715560721bb0d5fc7610fce279b3699b018600ab999d1be895b09415"}, - {file = "contourpy-1.3.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f26b383144cf2d2c29f01a1e8170f50dacf0eac02d64139dcd709a8ac4eb3cfe"}, - {file = "contourpy-1.3.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:c49f73e61f1f774650a55d221803b101d966ca0c5a2d6d5e4320ec3997489441"}, - {file = "contourpy-1.3.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:3d80b2c0300583228ac98d0a927a1ba6a2ba6b8a742463c564f1d419ee5b211e"}, - {file = "contourpy-1.3.2-cp312-cp312-win32.whl", hash = "sha256:90df94c89a91b7362e1142cbee7568f86514412ab8a2c0d0fca72d7e91b62912"}, - {file = "contourpy-1.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:8c942a01d9163e2e5cfb05cb66110121b8d07ad438a17f9e766317bcb62abf73"}, - {file = "contourpy-1.3.2-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:5f5964cdad279256c084b69c3f412b7801e15356b16efa9d78aa974041903da0"}, - {file = "contourpy-1.3.2-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:49b65a95d642d4efa8f64ba12558fcb83407e58a2dfba9d796d77b63ccfcaff5"}, - {file = "contourpy-1.3.2-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:8c5acb8dddb0752bf252e01a3035b21443158910ac16a3b0d20e7fed7d534ce5"}, - {file = "contourpy-1.3.2.tar.gz", hash = "sha256:b6945942715a034c671b7fc54f9588126b0b8bf23db2696e3ca8328f3ff0ab54"}, + "numpy>=1.25", +] +files = [ + {file = "contourpy-1.3.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:709a48ef9a690e1343202916450bc48b9e51c049b089c7f79a267b46cffcdaa1"}, + {file = "contourpy-1.3.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:23416f38bfd74d5d28ab8429cc4d63fa67d5068bd711a85edb1c3fb0c3e2f381"}, + {file = "contourpy-1.3.3-cp311-cp311-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:929ddf8c4c7f348e4c0a5a3a714b5c8542ffaa8c22954862a46ca1813b667ee7"}, + {file = "contourpy-1.3.3-cp311-cp311-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:9e999574eddae35f1312c2b4b717b7885d4edd6cb46700e04f7f02db454e67c1"}, + {file = "contourpy-1.3.3-cp311-cp311-manylinux_2_26_s390x.manylinux_2_28_s390x.whl", hash = "sha256:0bf67e0e3f482cb69779dd3061b534eb35ac9b17f163d851e2a547d56dba0a3a"}, + {file = "contourpy-1.3.3-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:51e79c1f7470158e838808d4a996fa9bac72c498e93d8ebe5119bc1e6becb0db"}, + {file = "contourpy-1.3.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:598c3aaece21c503615fd59c92a3598b428b2f01bfb4b8ca9c4edeecc2438620"}, + {file = "contourpy-1.3.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:322ab1c99b008dad206d406bb61d014cf0174df491ae9d9d0fac6a6fda4f977f"}, + {file = "contourpy-1.3.3-cp311-cp311-win32.whl", hash = "sha256:fd907ae12cd483cd83e414b12941c632a969171bf90fc937d0c9f268a31cafff"}, + {file = "contourpy-1.3.3-cp311-cp311-win_amd64.whl", hash = "sha256:3519428f6be58431c56581f1694ba8e50626f2dd550af225f82fb5f5814d2a42"}, + {file = "contourpy-1.3.3-cp311-cp311-win_arm64.whl", hash = "sha256:15ff10bfada4bf92ec8b31c62bf7c1834c244019b4a33095a68000d7075df470"}, + {file = "contourpy-1.3.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:b08a32ea2f8e42cf1d4be3169a98dd4be32bafe4f22b6c4cb4ba810fa9e5d2cb"}, + {file = "contourpy-1.3.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:556dba8fb6f5d8742f2923fe9457dbdd51e1049c4a43fd3986a0b14a1d815fc6"}, + {file = "contourpy-1.3.3-cp312-cp312-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:92d9abc807cf7d0e047b95ca5d957cf4792fcd04e920ca70d48add15c1a90ea7"}, + {file = "contourpy-1.3.3-cp312-cp312-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:b2e8faa0ed68cb29af51edd8e24798bb661eac3bd9f65420c1887b6ca89987c8"}, + {file = "contourpy-1.3.3-cp312-cp312-manylinux_2_26_s390x.manylinux_2_28_s390x.whl", hash = "sha256:626d60935cf668e70a5ce6ff184fd713e9683fb458898e4249b63be9e28286ea"}, + {file = "contourpy-1.3.3-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4d00e655fcef08aba35ec9610536bfe90267d7ab5ba944f7032549c55a146da1"}, + {file = "contourpy-1.3.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:451e71b5a7d597379ef572de31eeb909a87246974d960049a9848c3bc6c41bf7"}, + {file = "contourpy-1.3.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:459c1f020cd59fcfe6650180678a9993932d80d44ccde1fa1868977438f0b411"}, + {file = "contourpy-1.3.3-cp312-cp312-win32.whl", hash = "sha256:023b44101dfe49d7d53932be418477dba359649246075c996866106da069af69"}, + {file = "contourpy-1.3.3-cp312-cp312-win_amd64.whl", hash = "sha256:8153b8bfc11e1e4d75bcb0bff1db232f9e10b274e0929de9d608027e0d34ff8b"}, + {file = "contourpy-1.3.3-cp312-cp312-win_arm64.whl", hash = "sha256:07ce5ed73ecdc4a03ffe3e1b3e3c1166db35ae7584be76f65dbbe28a7791b0cc"}, + {file = "contourpy-1.3.3-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:cd5dfcaeb10f7b7f9dc8941717c6c2ade08f587be2226222c12b25f0483ed497"}, + {file = "contourpy-1.3.3-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:0c1fc238306b35f246d61a1d416a627348b5cf0648648a031e14bb8705fcdfe8"}, + {file = "contourpy-1.3.3-pp311-pypy311_pp73-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:70f9aad7de812d6541d29d2bbf8feb22ff7e1c299523db288004e3157ff4674e"}, + {file = "contourpy-1.3.3-pp311-pypy311_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5ed3657edf08512fc3fe81b510e35c2012fbd3081d2e26160f27ca28affec989"}, + {file = "contourpy-1.3.3-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:3d1a3799d62d45c18bafd41c5fa05120b96a28079f2393af559b843d1a966a77"}, + {file = "contourpy-1.3.3.tar.gz", hash = "sha256:083e12155b210502d0bca491432bb04d56dc3432f95a979b429f2848c3dbe880"}, ] [[package]] name = "coverage" -version = "7.8.0" -requires_python = ">=3.9" +version = "7.13.0" +requires_python = ">=3.10" summary = "Code coverage measurement for Python" files = [ - {file = "coverage-7.8.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:e7ac22a0bb2c7c49f441f7a6d46c9c80d96e56f5a8bc6972529ed43c8b694e27"}, - {file = "coverage-7.8.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:bf13d564d310c156d1c8e53877baf2993fb3073b2fc9f69790ca6a732eb4bfea"}, - {file = "coverage-7.8.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a5761c70c017c1b0d21b0815a920ffb94a670c8d5d409d9b38857874c21f70d7"}, - {file = "coverage-7.8.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e5ff52d790c7e1628241ffbcaeb33e07d14b007b6eb00a19320c7b8a7024c040"}, - {file = "coverage-7.8.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d39fc4817fd67b3915256af5dda75fd4ee10621a3d484524487e33416c6f3543"}, - {file = "coverage-7.8.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:b44674870709017e4b4036e3d0d6c17f06a0e6d4436422e0ad29b882c40697d2"}, - {file = "coverage-7.8.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:8f99eb72bf27cbb167b636eb1726f590c00e1ad375002230607a844d9e9a2318"}, - {file = "coverage-7.8.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:b571bf5341ba8c6bc02e0baeaf3b061ab993bf372d982ae509807e7f112554e9"}, - {file = "coverage-7.8.0-cp311-cp311-win32.whl", hash = "sha256:e75a2ad7b647fd8046d58c3132d7eaf31b12d8a53c0e4b21fa9c4d23d6ee6d3c"}, - {file = "coverage-7.8.0-cp311-cp311-win_amd64.whl", hash = "sha256:3043ba1c88b2139126fc72cb48574b90e2e0546d4c78b5299317f61b7f718b78"}, - {file = "coverage-7.8.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:bbb5cc845a0292e0c520656d19d7ce40e18d0e19b22cb3e0409135a575bf79fc"}, - {file = "coverage-7.8.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:4dfd9a93db9e78666d178d4f08a5408aa3f2474ad4d0e0378ed5f2ef71640cb6"}, - {file = "coverage-7.8.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f017a61399f13aa6d1039f75cd467be388d157cd81f1a119b9d9a68ba6f2830d"}, - {file = "coverage-7.8.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0915742f4c82208ebf47a2b154a5334155ed9ef9fe6190674b8a46c2fb89cb05"}, - {file = "coverage-7.8.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8a40fcf208e021eb14b0fac6bdb045c0e0cab53105f93ba0d03fd934c956143a"}, - {file = "coverage-7.8.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:a1f406a8e0995d654b2ad87c62caf6befa767885301f3b8f6f73e6f3c31ec3a6"}, - {file = "coverage-7.8.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:77af0f6447a582fdc7de5e06fa3757a3ef87769fbb0fdbdeba78c23049140a47"}, - {file = "coverage-7.8.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:f2d32f95922927186c6dbc8bc60df0d186b6edb828d299ab10898ef3f40052fe"}, - {file = "coverage-7.8.0-cp312-cp312-win32.whl", hash = "sha256:769773614e676f9d8e8a0980dd7740f09a6ea386d0f383db6821df07d0f08545"}, - {file = "coverage-7.8.0-cp312-cp312-win_amd64.whl", hash = "sha256:e5d2b9be5b0693cf21eb4ce0ec8d211efb43966f6657807f6859aab3814f946b"}, - {file = "coverage-7.8.0-pp39.pp310.pp311-none-any.whl", hash = "sha256:b8194fb8e50d556d5849753de991d390c5a1edeeba50f68e3a9253fbd8bf8ccd"}, - {file = "coverage-7.8.0-py3-none-any.whl", hash = "sha256:dbf364b4c5e7bae9250528167dfe40219b62e2d573c854d74be213e1e52069f7"}, - {file = "coverage-7.8.0.tar.gz", hash = "sha256:7a3d62b3b03b4b6fd41a085f3574874cf946cb4604d2b4d3e8dca8cd570ca501"}, + {file = "coverage-7.13.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:0dfa3855031070058add1a59fdfda0192fd3e8f97e7c81de0596c145dea51820"}, + {file = "coverage-7.13.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4fdb6f54f38e334db97f72fa0c701e66d8479af0bc3f9bfb5b90f1c30f54500f"}, + {file = "coverage-7.13.0-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:7e442c013447d1d8d195be62852270b78b6e255b79b8675bad8479641e21fd96"}, + {file = "coverage-7.13.0-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:1ed5630d946859de835a85e9a43b721123a8a44ec26e2830b296d478c7fd4259"}, + {file = "coverage-7.13.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7f15a931a668e58087bc39d05d2b4bf4b14ff2875b49c994bbdb1c2217a8daeb"}, + {file = "coverage-7.13.0-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:30a3a201a127ea57f7e14ba43c93c9c4be8b7d17a26e03bb49e6966d019eede9"}, + {file = "coverage-7.13.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:7a485ff48fbd231efa32d58f479befce52dcb6bfb2a88bb7bf9a0b89b1bc8030"}, + {file = "coverage-7.13.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:22486cdafba4f9e471c816a2a5745337742a617fef68e890d8baf9f3036d7833"}, + {file = "coverage-7.13.0-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:263c3dbccc78e2e331e59e90115941b5f53e85cfcc6b3b2fbff1fd4e3d2c6ea8"}, + {file = "coverage-7.13.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:e5330fa0cc1f5c3c4c3bb8e101b742025933e7848989370a1d4c8c5e401ea753"}, + {file = "coverage-7.13.0-cp311-cp311-win32.whl", hash = "sha256:0f4872f5d6c54419c94c25dd6ae1d015deeb337d06e448cd890a1e89a8ee7f3b"}, + {file = "coverage-7.13.0-cp311-cp311-win_amd64.whl", hash = "sha256:51a202e0f80f241ccb68e3e26e19ab5b3bf0f813314f2c967642f13ebcf1ddfe"}, + {file = "coverage-7.13.0-cp311-cp311-win_arm64.whl", hash = "sha256:d2a9d7f1c11487b1c69367ab3ac2d81b9b3721f097aa409a3191c3e90f8f3dd7"}, + {file = "coverage-7.13.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:0b3d67d31383c4c68e19a88e28fc4c2e29517580f1b0ebec4a069d502ce1e0bf"}, + {file = "coverage-7.13.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:581f086833d24a22c89ae0fe2142cfaa1c92c930adf637ddf122d55083fb5a0f"}, + {file = "coverage-7.13.0-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:0a3a30f0e257df382f5f9534d4ce3d4cf06eafaf5192beb1a7bd066cb10e78fb"}, + {file = "coverage-7.13.0-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:583221913fbc8f53b88c42e8dbb8fca1d0f2e597cb190ce45916662b8b9d9621"}, + {file = "coverage-7.13.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5f5d9bd30756fff3e7216491a0d6d520c448d5124d3d8e8f56446d6412499e74"}, + {file = "coverage-7.13.0-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:a23e5a1f8b982d56fa64f8e442e037f6ce29322f1f9e6c2344cd9e9f4407ee57"}, + {file = "coverage-7.13.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:9b01c22bc74a7fb44066aaf765224c0d933ddf1f5047d6cdfe4795504a4493f8"}, + {file = "coverage-7.13.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:898cce66d0836973f48dda4e3514d863d70142bdf6dfab932b9b6a90ea5b222d"}, + {file = "coverage-7.13.0-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:3ab483ea0e251b5790c2aac03acde31bff0c736bf8a86829b89382b407cd1c3b"}, + {file = "coverage-7.13.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:1d84e91521c5e4cb6602fe11ece3e1de03b2760e14ae4fcf1a4b56fa3c801fcd"}, + {file = "coverage-7.13.0-cp312-cp312-win32.whl", hash = "sha256:193c3887285eec1dbdb3f2bd7fbc351d570ca9c02ca756c3afbc71b3c98af6ef"}, + {file = "coverage-7.13.0-cp312-cp312-win_amd64.whl", hash = "sha256:4f3e223b2b2db5e0db0c2b97286aba0036ca000f06aca9b12112eaa9af3d92ae"}, + {file = "coverage-7.13.0-cp312-cp312-win_arm64.whl", hash = "sha256:086cede306d96202e15a4b77ace8472e39d9f4e5f9fd92dd4fecdfb2313b2080"}, + {file = "coverage-7.13.0-py3-none-any.whl", hash = "sha256:850d2998f380b1e266459ca5b47bc9e7daf9af1d070f66317972f382d46f1904"}, + {file = "coverage-7.13.0.tar.gz", hash = "sha256:a394aa27f2d7ff9bc04cf703817773a59ad6dfbd577032e690f961d2460ee936"}, ] [[package]] name = "coverage" -version = "7.8.0" +version = "7.13.0" extras = ["toml"] -requires_python = ">=3.9" +requires_python = ">=3.10" summary = "Code coverage measurement for Python" dependencies = [ - "coverage==7.8.0", + "coverage==7.13.0", "tomli; python_full_version <= \"3.11.0a6\"", ] files = [ - {file = "coverage-7.8.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:e7ac22a0bb2c7c49f441f7a6d46c9c80d96e56f5a8bc6972529ed43c8b694e27"}, - {file = "coverage-7.8.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:bf13d564d310c156d1c8e53877baf2993fb3073b2fc9f69790ca6a732eb4bfea"}, - {file = "coverage-7.8.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a5761c70c017c1b0d21b0815a920ffb94a670c8d5d409d9b38857874c21f70d7"}, - {file = "coverage-7.8.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e5ff52d790c7e1628241ffbcaeb33e07d14b007b6eb00a19320c7b8a7024c040"}, - {file = "coverage-7.8.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d39fc4817fd67b3915256af5dda75fd4ee10621a3d484524487e33416c6f3543"}, - {file = "coverage-7.8.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:b44674870709017e4b4036e3d0d6c17f06a0e6d4436422e0ad29b882c40697d2"}, - {file = "coverage-7.8.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:8f99eb72bf27cbb167b636eb1726f590c00e1ad375002230607a844d9e9a2318"}, - {file = "coverage-7.8.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:b571bf5341ba8c6bc02e0baeaf3b061ab993bf372d982ae509807e7f112554e9"}, - {file = "coverage-7.8.0-cp311-cp311-win32.whl", hash = "sha256:e75a2ad7b647fd8046d58c3132d7eaf31b12d8a53c0e4b21fa9c4d23d6ee6d3c"}, - {file = "coverage-7.8.0-cp311-cp311-win_amd64.whl", hash = "sha256:3043ba1c88b2139126fc72cb48574b90e2e0546d4c78b5299317f61b7f718b78"}, - {file = "coverage-7.8.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:bbb5cc845a0292e0c520656d19d7ce40e18d0e19b22cb3e0409135a575bf79fc"}, - {file = "coverage-7.8.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:4dfd9a93db9e78666d178d4f08a5408aa3f2474ad4d0e0378ed5f2ef71640cb6"}, - {file = "coverage-7.8.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f017a61399f13aa6d1039f75cd467be388d157cd81f1a119b9d9a68ba6f2830d"}, - {file = "coverage-7.8.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0915742f4c82208ebf47a2b154a5334155ed9ef9fe6190674b8a46c2fb89cb05"}, - {file = "coverage-7.8.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8a40fcf208e021eb14b0fac6bdb045c0e0cab53105f93ba0d03fd934c956143a"}, - {file = "coverage-7.8.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:a1f406a8e0995d654b2ad87c62caf6befa767885301f3b8f6f73e6f3c31ec3a6"}, - {file = "coverage-7.8.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:77af0f6447a582fdc7de5e06fa3757a3ef87769fbb0fdbdeba78c23049140a47"}, - {file = "coverage-7.8.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:f2d32f95922927186c6dbc8bc60df0d186b6edb828d299ab10898ef3f40052fe"}, - {file = "coverage-7.8.0-cp312-cp312-win32.whl", hash = "sha256:769773614e676f9d8e8a0980dd7740f09a6ea386d0f383db6821df07d0f08545"}, - {file = "coverage-7.8.0-cp312-cp312-win_amd64.whl", hash = "sha256:e5d2b9be5b0693cf21eb4ce0ec8d211efb43966f6657807f6859aab3814f946b"}, - {file = "coverage-7.8.0-pp39.pp310.pp311-none-any.whl", hash = "sha256:b8194fb8e50d556d5849753de991d390c5a1edeeba50f68e3a9253fbd8bf8ccd"}, - {file = "coverage-7.8.0-py3-none-any.whl", hash = "sha256:dbf364b4c5e7bae9250528167dfe40219b62e2d573c854d74be213e1e52069f7"}, - {file = "coverage-7.8.0.tar.gz", hash = "sha256:7a3d62b3b03b4b6fd41a085f3574874cf946cb4604d2b4d3e8dca8cd570ca501"}, + {file = "coverage-7.13.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:0dfa3855031070058add1a59fdfda0192fd3e8f97e7c81de0596c145dea51820"}, + {file = "coverage-7.13.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4fdb6f54f38e334db97f72fa0c701e66d8479af0bc3f9bfb5b90f1c30f54500f"}, + {file = "coverage-7.13.0-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:7e442c013447d1d8d195be62852270b78b6e255b79b8675bad8479641e21fd96"}, + {file = "coverage-7.13.0-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:1ed5630d946859de835a85e9a43b721123a8a44ec26e2830b296d478c7fd4259"}, + {file = "coverage-7.13.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7f15a931a668e58087bc39d05d2b4bf4b14ff2875b49c994bbdb1c2217a8daeb"}, + {file = "coverage-7.13.0-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:30a3a201a127ea57f7e14ba43c93c9c4be8b7d17a26e03bb49e6966d019eede9"}, + {file = "coverage-7.13.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:7a485ff48fbd231efa32d58f479befce52dcb6bfb2a88bb7bf9a0b89b1bc8030"}, + {file = "coverage-7.13.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:22486cdafba4f9e471c816a2a5745337742a617fef68e890d8baf9f3036d7833"}, + {file = "coverage-7.13.0-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:263c3dbccc78e2e331e59e90115941b5f53e85cfcc6b3b2fbff1fd4e3d2c6ea8"}, + {file = "coverage-7.13.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:e5330fa0cc1f5c3c4c3bb8e101b742025933e7848989370a1d4c8c5e401ea753"}, + {file = "coverage-7.13.0-cp311-cp311-win32.whl", hash = "sha256:0f4872f5d6c54419c94c25dd6ae1d015deeb337d06e448cd890a1e89a8ee7f3b"}, + {file = "coverage-7.13.0-cp311-cp311-win_amd64.whl", hash = "sha256:51a202e0f80f241ccb68e3e26e19ab5b3bf0f813314f2c967642f13ebcf1ddfe"}, + {file = "coverage-7.13.0-cp311-cp311-win_arm64.whl", hash = "sha256:d2a9d7f1c11487b1c69367ab3ac2d81b9b3721f097aa409a3191c3e90f8f3dd7"}, + {file = "coverage-7.13.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:0b3d67d31383c4c68e19a88e28fc4c2e29517580f1b0ebec4a069d502ce1e0bf"}, + {file = "coverage-7.13.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:581f086833d24a22c89ae0fe2142cfaa1c92c930adf637ddf122d55083fb5a0f"}, + {file = "coverage-7.13.0-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:0a3a30f0e257df382f5f9534d4ce3d4cf06eafaf5192beb1a7bd066cb10e78fb"}, + {file = "coverage-7.13.0-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:583221913fbc8f53b88c42e8dbb8fca1d0f2e597cb190ce45916662b8b9d9621"}, + {file = "coverage-7.13.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5f5d9bd30756fff3e7216491a0d6d520c448d5124d3d8e8f56446d6412499e74"}, + {file = "coverage-7.13.0-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:a23e5a1f8b982d56fa64f8e442e037f6ce29322f1f9e6c2344cd9e9f4407ee57"}, + {file = "coverage-7.13.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:9b01c22bc74a7fb44066aaf765224c0d933ddf1f5047d6cdfe4795504a4493f8"}, + {file = "coverage-7.13.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:898cce66d0836973f48dda4e3514d863d70142bdf6dfab932b9b6a90ea5b222d"}, + {file = "coverage-7.13.0-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:3ab483ea0e251b5790c2aac03acde31bff0c736bf8a86829b89382b407cd1c3b"}, + {file = "coverage-7.13.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:1d84e91521c5e4cb6602fe11ece3e1de03b2760e14ae4fcf1a4b56fa3c801fcd"}, + {file = "coverage-7.13.0-cp312-cp312-win32.whl", hash = "sha256:193c3887285eec1dbdb3f2bd7fbc351d570ca9c02ca756c3afbc71b3c98af6ef"}, + {file = "coverage-7.13.0-cp312-cp312-win_amd64.whl", hash = "sha256:4f3e223b2b2db5e0db0c2b97286aba0036ca000f06aca9b12112eaa9af3d92ae"}, + {file = "coverage-7.13.0-cp312-cp312-win_arm64.whl", hash = "sha256:086cede306d96202e15a4b77ace8472e39d9f4e5f9fd92dd4fecdfb2313b2080"}, + {file = "coverage-7.13.0-py3-none-any.whl", hash = "sha256:850d2998f380b1e266459ca5b47bc9e7daf9af1d070f66317972f382d46f1904"}, + {file = "coverage-7.13.0.tar.gz", hash = "sha256:a394aa27f2d7ff9bc04cf703817773a59ad6dfbd577032e690f961d2460ee936"}, ] [[package]] @@ -608,9 +732,36 @@ files = [ {file = "cycler-0.12.1.tar.gz", hash = "sha256:88bb128f02ba341da8ef447245a9e138fae777f6a23943da4540077d3601eb1c"}, ] +[[package]] +name = "cython" +version = "3.2.2" +requires_python = ">=3.8" +summary = "The Cython compiler for writing C extensions in the Python language." +files = [ + {file = "cython-3.2.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d140c2701cbb8cf960300cf1b67f3b4fa9d294d32e51b85f329bff56936a82fd"}, + {file = "cython-3.2.2-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:50bbaabee733fd2780985e459fc20f655e02def83e8eff10220ad88455a34622"}, + {file = "cython-3.2.2-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a9509f1e9c41c86b790cff745bb31927bbc861662a3b462596d71d3d2a578abb"}, + {file = "cython-3.2.2-cp311-cp311-win_amd64.whl", hash = "sha256:034ab96cb8bc8e7432bc27491f8d66f51e435b1eb21ddc03aa844be8f21ad847"}, + {file = "cython-3.2.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:692a41c8fe06fb2dc55ca2c8d71c80c469fd16fe69486ed99f3b3cbb2d3af83f"}, + {file = "cython-3.2.2-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:098590c1dc309f8a0406ade031963a95a87714296b425539f9920aebf924560d"}, + {file = "cython-3.2.2-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a3898c076e9c458bcb3e4936187919fda5f5365fe4c567d35d2b003444b6f3fe"}, + {file = "cython-3.2.2-cp312-cp312-win_amd64.whl", hash = "sha256:2b910b89a2a71004064c5e890b9512a251eda63fae252caa0feb9835057035f9"}, + {file = "cython-3.2.2-cp39-abi3-macosx_10_9_x86_64.whl", hash = "sha256:a6387e3ad31342443916db9a419509935fddd8d4cbac34aab9c895ae55326a56"}, + {file = "cython-3.2.2-cp39-abi3-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:436eb562d0affbc0b959f62f3f9c1ed251b9499e4f29c1d19514ae859894b6bf"}, + {file = "cython-3.2.2-cp39-abi3-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:f560ff3aea5b5df93853ec7bf1a1e9623d6d511f4192f197559aca18fca43392"}, + {file = "cython-3.2.2-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:d8c93fe128b58942832b1fcac96e48f93c2c69b569eff0d38d30fb5995fecfa0"}, + {file = "cython-3.2.2-cp39-abi3-musllinux_1_2_armv7l.whl", hash = "sha256:b4fe499eed7cd70b2aa4e096b9ce2588f5e6fdf049b46d40a5e55efcde6e4904"}, + {file = "cython-3.2.2-cp39-abi3-musllinux_1_2_i686.whl", hash = "sha256:14432d7f207245a3c35556155873f494784169297b28978a6204f1c60d31553e"}, + {file = "cython-3.2.2-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:820c4a99dbf6b3e6c0300be42b4040b501eff0e1feeb80cfa52c48a346fb0df2"}, + {file = "cython-3.2.2-cp39-abi3-win32.whl", hash = "sha256:826cad0ad43ab05a26e873b5d625f64d458dc739ec6fdeecab848b60a91c4252"}, + {file = "cython-3.2.2-cp39-abi3-win_arm64.whl", hash = "sha256:5f818d40bbcf17e2089e2de7840f0de1c0ca527acf9b044aba79d5f5d8a5bdba"}, + {file = "cython-3.2.2-py3-none-any.whl", hash = "sha256:13b99ecb9482aff6a6c12d1ca6feef6940c507af909914b49f568de74fa965fb"}, + {file = "cython-3.2.2.tar.gz", hash = "sha256:c3add3d483acc73129a61d105389344d792c17e7c1cee24863f16416bd071634"}, +] + [[package]] name = "dask" -version = "2025.5.0" +version = "2025.12.0" requires_python = ">=3.10" summary = "Parallel PyData with Task Scheduling" dependencies = [ @@ -621,29 +772,29 @@ dependencies = [ "packaging>=20.0", "partd>=1.4.0", "pyyaml>=5.3.1", - "toolz>=0.10.0", + "toolz>=0.12.0", ] files = [ - {file = "dask-2025.5.0-py3-none-any.whl", hash = "sha256:77e9a64bb09098515bc579477b7051b0909474cd7b3e0005e3d0968a70c84015"}, - {file = "dask-2025.5.0.tar.gz", hash = "sha256:3ec9175e53effe1c2b0086668352e0d5261c5ef6f71a410264eda83659d686ef"}, + {file = "dask-2025.12.0-py3-none-any.whl", hash = "sha256:4213ce9c5d51d6d89337cff69de35d902aa0bf6abdb8a25c942a4d0281f3a598"}, + {file = "dask-2025.12.0.tar.gz", hash = "sha256:8d478f2aabd025e2453cf733ad64559de90cf328c20209e4574e9543707c3e1b"}, ] [[package]] name = "debugpy" -version = "1.8.14" +version = "1.8.18" requires_python = ">=3.8" summary = "An implementation of the Debug Adapter Protocol for Python" files = [ - {file = "debugpy-1.8.14-cp311-cp311-macosx_14_0_universal2.whl", hash = "sha256:1b2ac8c13b2645e0b1eaf30e816404990fbdb168e193322be8f545e8c01644a9"}, - {file = "debugpy-1.8.14-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cf431c343a99384ac7eab2f763980724834f933a271e90496944195318c619e2"}, - {file = "debugpy-1.8.14-cp311-cp311-win32.whl", hash = "sha256:c99295c76161ad8d507b413cd33422d7c542889fbb73035889420ac1fad354f2"}, - {file = "debugpy-1.8.14-cp311-cp311-win_amd64.whl", hash = "sha256:7816acea4a46d7e4e50ad8d09d963a680ecc814ae31cdef3622eb05ccacf7b01"}, - {file = "debugpy-1.8.14-cp312-cp312-macosx_14_0_universal2.whl", hash = "sha256:8899c17920d089cfa23e6005ad9f22582fd86f144b23acb9feeda59e84405b84"}, - {file = "debugpy-1.8.14-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f6bb5c0dcf80ad5dbc7b7d6eac484e2af34bdacdf81df09b6a3e62792b722826"}, - {file = "debugpy-1.8.14-cp312-cp312-win32.whl", hash = "sha256:281d44d248a0e1791ad0eafdbbd2912ff0de9eec48022a5bfbc332957487ed3f"}, - {file = "debugpy-1.8.14-cp312-cp312-win_amd64.whl", hash = "sha256:5aa56ef8538893e4502a7d79047fe39b1dae08d9ae257074c6464a7b290b806f"}, - {file = "debugpy-1.8.14-py2.py3-none-any.whl", hash = "sha256:5cd9a579d553b6cb9759a7908a41988ee6280b961f24f63336835d9418216a20"}, - {file = "debugpy-1.8.14.tar.gz", hash = "sha256:7cd287184318416850aa8b60ac90105837bb1e59531898c07569d197d2ed5322"}, + {file = "debugpy-1.8.18-cp311-cp311-macosx_15_0_universal2.whl", hash = "sha256:3dae1d65e581406a4d7c1bb44391f47e621b8c87c5639b6607e6007a5d823205"}, + {file = "debugpy-1.8.18-cp311-cp311-manylinux_2_34_x86_64.whl", hash = "sha256:8804d1288e6006629a87d53eb44b7b66e695d428ac529ffd75bfc7d730a9c821"}, + {file = "debugpy-1.8.18-cp311-cp311-win32.whl", hash = "sha256:ded8a5a413bd0a249b3c0be9f43128f437755180ac431222a6354c7d76a76a54"}, + {file = "debugpy-1.8.18-cp311-cp311-win_amd64.whl", hash = "sha256:df6c1243dedcb6bf9a5dc1c5668009e2b5508b8525f27d9821be91da57827743"}, + {file = "debugpy-1.8.18-cp312-cp312-macosx_15_0_universal2.whl", hash = "sha256:530c38114725505a7e4ea95328dbc24aabb9be708c6570623c8163412e6d1d6b"}, + {file = "debugpy-1.8.18-cp312-cp312-manylinux_2_34_x86_64.whl", hash = "sha256:a114865099283cbed4c9330cb0c9cb7a04cfa92e803577843657302d526141ec"}, + {file = "debugpy-1.8.18-cp312-cp312-win32.whl", hash = "sha256:4d26736dfabf404e9f3032015ec7b0189e7396d0664e29e5bdbe7ac453043c95"}, + {file = "debugpy-1.8.18-cp312-cp312-win_amd64.whl", hash = "sha256:7e68ba950acbcf95ee862210133681f408cbb78d1c9badbb515230ec55ed6487"}, + {file = "debugpy-1.8.18-py2.py3-none-any.whl", hash = "sha256:ab8cf0abe0fe2dfe1f7e65abc04b1db8740f9be80c1274acb625855c5c3ece6e"}, + {file = "debugpy-1.8.18.tar.gz", hash = "sha256:02551b1b84a91faadd2db9bc4948873f2398190c95b3cc6f97dc706f43e8c433"}, ] [[package]] @@ -680,15 +831,29 @@ files = [ {file = "defusedxml-0.7.1.tar.gz", hash = "sha256:1bb3032db185915b62d7c6209c5a8792be6a32ab2fedacc84e01b52c51aa3e69"}, ] +[[package]] +name = "dependency-groups" +version = "1.3.1" +requires_python = ">=3.8" +summary = "A tool for resolving PEP 735 Dependency Group data" +dependencies = [ + "packaging", + "tomli; python_version < \"3.11\"", +] +files = [ + {file = "dependency_groups-1.3.1-py3-none-any.whl", hash = "sha256:51aeaa0dfad72430fcfb7bcdbefbd75f3792e5919563077f30bc0d73f4493030"}, + {file = "dependency_groups-1.3.1.tar.gz", hash = "sha256:78078301090517fd938c19f64a53ce98c32834dfe0dee6b88004a569a6adfefd"}, +] + [[package]] name = "distributed" -version = "2025.5.0" +version = "2025.12.0" requires_python = ">=3.10" summary = "Distributed scheduler for Dask" dependencies = [ "click>=8.0", "cloudpickle>=3.0.0", - "dask==2025.5.0", + "dask<2025.12.1,>=2025.12.0", "jinja2>=2.10.3", "locket>=1.0.0", "msgpack>=1.0.2", @@ -696,15 +861,25 @@ dependencies = [ "psutil>=5.8.0", "pyyaml>=5.4.1", "sortedcontainers>=2.0.5", - "tblib>=1.6.0", - "toolz>=0.11.2", + "tblib!=3.2.0,!=3.2.1,>=1.6.0", + "toolz>=0.12.0", "tornado>=6.2.0", "urllib3>=1.26.5", "zict>=3.0.0", ] files = [ - {file = "distributed-2025.5.0-py3-none-any.whl", hash = "sha256:374e3236b4945745b48cd821025f802095abb18fd6477123dd237905253bc60f"}, - {file = "distributed-2025.5.0.tar.gz", hash = "sha256:49dc3395eb3b7169800160731064bbc7ee6f5235bbea49d9b85baa6358a2e37a"}, + {file = "distributed-2025.12.0-py3-none-any.whl", hash = "sha256:35d18449002ea191e97f7e04a33e16f90c2243486be52d4d0f991072ea06b48a"}, + {file = "distributed-2025.12.0.tar.gz", hash = "sha256:b1e58f1b3d733885335817562ee1723379f23733e4ef3546f141080d9cb01a74"}, +] + +[[package]] +name = "distro" +version = "1.9.0" +requires_python = ">=3.6" +summary = "Distro - an OS platform information API" +files = [ + {file = "distro-1.9.0-py3-none-any.whl", hash = "sha256:7bffd925d65168f85027d8da9af6bddab658135b840670a223589bc0c8ef02b2"}, + {file = "distro-1.9.0.tar.gz", hash = "sha256:2fa77c6fd8940f116ee1d6b94a2f90b13b5ea8d019b98bc8bafdcabcdd9bdbed"}, ] [[package]] @@ -767,41 +942,41 @@ files = [ [[package]] name = "execnet" -version = "2.1.1" +version = "2.1.2" requires_python = ">=3.8" summary = "execnet: rapid multi-Python deployment" files = [ - {file = "execnet-2.1.1-py3-none-any.whl", hash = "sha256:26dee51f1b80cebd6d0ca8e74dd8745419761d3bef34163928cbebbdc4749fdc"}, - {file = "execnet-2.1.1.tar.gz", hash = "sha256:5189b52c6121c24feae288166ab41b32549c7e2348652736540b9e6e7d4e72e3"}, + {file = "execnet-2.1.2-py3-none-any.whl", hash = "sha256:67fba928dd5a544b783f6056f449e5e3931a5c378b128bc18501f7ea79e296ec"}, + {file = "execnet-2.1.2.tar.gz", hash = "sha256:63d83bfdd9a23e35b9c6a3261412324f964c2ec8dcd8d3c6916ee9373e0befcd"}, ] [[package]] name = "executing" -version = "2.2.0" +version = "2.2.1" requires_python = ">=3.8" summary = "Get the currently executing AST node of a frame, and other information" files = [ - {file = "executing-2.2.0-py2.py3-none-any.whl", hash = "sha256:11387150cad388d62750327a53d3339fad4888b39a6fe233c3afbb54ecffd3aa"}, - {file = "executing-2.2.0.tar.gz", hash = "sha256:5d108c028108fe2551d1a7b2e8b713341e2cb4fc0aa7dcf966fa4327a5226755"}, + {file = "executing-2.2.1-py2.py3-none-any.whl", hash = "sha256:760643d3452b4d777d295bb167ccc74c64a81df23fb5e08eff250c425a4b2017"}, + {file = "executing-2.2.1.tar.gz", hash = "sha256:3632cc370565f6648cc328b32435bd120a1e4ebb20c77e3fdde9a13cd1e533c4"}, ] [[package]] name = "fastjsonschema" -version = "2.21.1" +version = "2.21.2" summary = "Fastest Python implementation of JSON schema" files = [ - {file = "fastjsonschema-2.21.1-py3-none-any.whl", hash = "sha256:c9e5b7e908310918cf494a434eeb31384dd84a98b57a30bcb1f535015b554667"}, - {file = "fastjsonschema-2.21.1.tar.gz", hash = "sha256:794d4f0a58f848961ba16af7b9c85a3e88cd360df008c59aac6fc5ae9323b5d4"}, + {file = "fastjsonschema-2.21.2-py3-none-any.whl", hash = "sha256:1c797122d0a86c5cace2e54bf4e819c36223b552017172f32c5c024a6b77e463"}, + {file = "fastjsonschema-2.21.2.tar.gz", hash = "sha256:b1eb43748041c880796cd077f1a07c3d94e93ae84bba5ed36800a33554ae05de"}, ] [[package]] name = "filelock" -version = "3.18.0" -requires_python = ">=3.9" +version = "3.20.0" +requires_python = ">=3.10" summary = "A platform independent file lock." files = [ - {file = "filelock-3.18.0-py3-none-any.whl", hash = "sha256:c401f4f8377c4464e6db25fff06205fd89bdd83b65eb0488ed1b160f780e21de"}, - {file = "filelock-3.18.0.tar.gz", hash = "sha256:adbc88eabb99d2fec8c9c1b229b171f18afa655400173ddc653d5d01501fb9f2"}, + {file = "filelock-3.20.0-py3-none-any.whl", hash = "sha256:339b4732ffda5cd79b13f4e2711a31b0365ce445d95d243bb996273d072546a2"}, + {file = "filelock-3.20.0.tar.gz", hash = "sha256:711e943b4ec6be42e1d4e6690b48dc175c822967466bb31c0c293f34334c13f4"}, ] [[package]] @@ -821,28 +996,28 @@ files = [ [[package]] name = "fonttools" -version = "4.58.0" -requires_python = ">=3.9" +version = "4.61.1" +requires_python = ">=3.10" summary = "Tools to manipulate font files" files = [ - {file = "fonttools-4.58.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:9345b1bb994476d6034996b31891c0c728c1059c05daa59f9ab57d2a4dce0f84"}, - {file = "fonttools-4.58.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:1d93119ace1e2d39ff1340deb71097932f72b21c054bd3da727a3859825e24e5"}, - {file = "fonttools-4.58.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:79c9e4f01bb04f19df272ae35314eb6349fdb2e9497a163cd22a21be999694bd"}, - {file = "fonttools-4.58.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:62ecda1465d38248aaf9bee1c17a21cf0b16aef7d121d7d303dbb320a6fd49c2"}, - {file = "fonttools-4.58.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:29d0499bff12a26733c05c1bfd07e68465158201624b2fba4a40b23d96c43f94"}, - {file = "fonttools-4.58.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1871abdb0af582e2d96cc12d88889e3bfa796928f491ec14d34a2e58ca298c7e"}, - {file = "fonttools-4.58.0-cp311-cp311-win32.whl", hash = "sha256:e292485d70402093eb94f6ab7669221743838b8bd4c1f45c84ca76b63338e7bf"}, - {file = "fonttools-4.58.0-cp311-cp311-win_amd64.whl", hash = "sha256:6df3755fcf9ad70a74ad3134bd5c9738f73c9bb701a304b1c809877b11fe701c"}, - {file = "fonttools-4.58.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:aa8316798f982c751d71f0025b372151ea36405733b62d0d94d5e7b8dd674fa6"}, - {file = "fonttools-4.58.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:c6db489511e867633b859b11aefe1b7c0d90281c5bdb903413edbb2ba77b97f1"}, - {file = "fonttools-4.58.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:107bdb2dacb1f627db3c4b77fb16d065a10fe88978d02b4fc327b9ecf8a62060"}, - {file = "fonttools-4.58.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba7212068ab20f1128a0475f169068ba8e5b6e35a39ba1980b9f53f6ac9720ac"}, - {file = "fonttools-4.58.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:f95ea3b6a3b9962da3c82db73f46d6a6845a6c3f3f968f5293b3ac1864e771c2"}, - {file = "fonttools-4.58.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:874f1225cc4ccfeac32009887f722d7f8b107ca5e867dcee067597eef9d4c80b"}, - {file = "fonttools-4.58.0-cp312-cp312-win32.whl", hash = "sha256:5f3cde64ec99c43260e2e6c4fa70dfb0a5e2c1c1d27a4f4fe4618c16f6c9ff71"}, - {file = "fonttools-4.58.0-cp312-cp312-win_amd64.whl", hash = "sha256:2aee08e2818de45067109a207cbd1b3072939f77751ef05904d506111df5d824"}, - {file = "fonttools-4.58.0-py3-none-any.whl", hash = "sha256:c96c36880be2268be409df7b08c5b5dacac1827083461a6bc2cb07b8cbcec1d7"}, - {file = "fonttools-4.58.0.tar.gz", hash = "sha256:27423d0606a2c7b336913254bf0b1193ebd471d5f725d665e875c5e88a011a43"}, + {file = "fonttools-4.61.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:c6604b735bb12fef8e0efd5578c9fb5d3d8532d5001ea13a19cddf295673ee09"}, + {file = "fonttools-4.61.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:5ce02f38a754f207f2f06557523cd39a06438ba3aafc0639c477ac409fc64e37"}, + {file = "fonttools-4.61.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:77efb033d8d7ff233385f30c62c7c79271c8885d5c9657d967ede124671bbdfb"}, + {file = "fonttools-4.61.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:75c1a6dfac6abd407634420c93864a1e274ebc1c7531346d9254c0d8f6ca00f9"}, + {file = "fonttools-4.61.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:0de30bfe7745c0d1ffa2b0b7048fb7123ad0d71107e10ee090fa0b16b9452e87"}, + {file = "fonttools-4.61.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:58b0ee0ab5b1fc9921eccfe11d1435added19d6494dde14e323f25ad2bc30c56"}, + {file = "fonttools-4.61.1-cp311-cp311-win32.whl", hash = "sha256:f79b168428351d11e10c5aeb61a74e1851ec221081299f4cf56036a95431c43a"}, + {file = "fonttools-4.61.1-cp311-cp311-win_amd64.whl", hash = "sha256:fe2efccb324948a11dd09d22136fe2ac8a97d6c1347cf0b58a911dcd529f66b7"}, + {file = "fonttools-4.61.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:f3cb4a569029b9f291f88aafc927dd53683757e640081ca8c412781ea144565e"}, + {file = "fonttools-4.61.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:41a7170d042e8c0024703ed13b71893519a1a6d6e18e933e3ec7507a2c26a4b2"}, + {file = "fonttools-4.61.1-cp312-cp312-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:10d88e55330e092940584774ee5e8a6971b01fc2f4d3466a1d6c158230880796"}, + {file = "fonttools-4.61.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:15acc09befd16a0fb8a8f62bc147e1a82817542d72184acca9ce6e0aeda9fa6d"}, + {file = "fonttools-4.61.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:e6bcdf33aec38d16508ce61fd81838f24c83c90a1d1b8c68982857038673d6b8"}, + {file = "fonttools-4.61.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:5fade934607a523614726119164ff621e8c30e8fa1ffffbbd358662056ba69f0"}, + {file = "fonttools-4.61.1-cp312-cp312-win32.whl", hash = "sha256:75da8f28eff26defba42c52986de97b22106cb8f26515b7c22443ebc9c2d3261"}, + {file = "fonttools-4.61.1-cp312-cp312-win_amd64.whl", hash = "sha256:497c31ce314219888c0e2fce5ad9178ca83fe5230b01a5006726cdf3ac9f24d9"}, + {file = "fonttools-4.61.1-py3-none-any.whl", hash = "sha256:17d2bf5d541add43822bcf0c43d7d847b160c9bb01d15d5007d84e2217aaa371"}, + {file = "fonttools-4.61.1.tar.gz", hash = "sha256:6675329885c44657f826ef01d9e4fb33b9158e9d93c537d84ad8399539bc6f69"}, ] [[package]] @@ -860,71 +1035,69 @@ files = [ [[package]] name = "frozenlist" -version = "1.6.0" +version = "1.8.0" requires_python = ">=3.9" summary = "A list-like structure which implements collections.abc.MutableSequence" files = [ - {file = "frozenlist-1.6.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:ae8337990e7a45683548ffb2fee1af2f1ed08169284cd829cdd9a7fa7470530d"}, - {file = "frozenlist-1.6.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:8c952f69dd524558694818a461855f35d36cc7f5c0adddce37e962c85d06eac0"}, - {file = "frozenlist-1.6.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:8f5fef13136c4e2dee91bfb9a44e236fff78fc2cd9f838eddfc470c3d7d90afe"}, - {file = "frozenlist-1.6.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:716bbba09611b4663ecbb7cd022f640759af8259e12a6ca939c0a6acd49eedba"}, - {file = "frozenlist-1.6.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:7b8c4dc422c1a3ffc550b465090e53b0bf4839047f3e436a34172ac67c45d595"}, - {file = "frozenlist-1.6.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b11534872256e1666116f6587a1592ef395a98b54476addb5e8d352925cb5d4a"}, - {file = "frozenlist-1.6.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1c6eceb88aaf7221f75be6ab498dc622a151f5f88d536661af3ffc486245a626"}, - {file = "frozenlist-1.6.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:62c828a5b195570eb4b37369fcbbd58e96c905768d53a44d13044355647838ff"}, - {file = "frozenlist-1.6.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e1c6bd2c6399920c9622362ce95a7d74e7f9af9bfec05fff91b8ce4b9647845a"}, - {file = "frozenlist-1.6.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:49ba23817781e22fcbd45fd9ff2b9b8cdb7b16a42a4851ab8025cae7b22e96d0"}, - {file = "frozenlist-1.6.0-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:431ef6937ae0f853143e2ca67d6da76c083e8b1fe3df0e96f3802fd37626e606"}, - {file = "frozenlist-1.6.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:9d124b38b3c299ca68433597ee26b7819209cb8a3a9ea761dfe9db3a04bba584"}, - {file = "frozenlist-1.6.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:118e97556306402e2b010da1ef21ea70cb6d6122e580da64c056b96f524fbd6a"}, - {file = "frozenlist-1.6.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:fb3b309f1d4086b5533cf7bbcf3f956f0ae6469664522f1bde4feed26fba60f1"}, - {file = "frozenlist-1.6.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:54dece0d21dce4fdb188a1ffc555926adf1d1c516e493c2914d7c370e454bc9e"}, - {file = "frozenlist-1.6.0-cp311-cp311-win32.whl", hash = "sha256:654e4ba1d0b2154ca2f096bed27461cf6160bc7f504a7f9a9ef447c293caf860"}, - {file = "frozenlist-1.6.0-cp311-cp311-win_amd64.whl", hash = "sha256:3e911391bffdb806001002c1f860787542f45916c3baf764264a52765d5a5603"}, - {file = "frozenlist-1.6.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:c5b9e42ace7d95bf41e19b87cec8f262c41d3510d8ad7514ab3862ea2197bfb1"}, - {file = "frozenlist-1.6.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:ca9973735ce9f770d24d5484dcb42f68f135351c2fc81a7a9369e48cf2998a29"}, - {file = "frozenlist-1.6.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6ac40ec76041c67b928ca8aaffba15c2b2ee3f5ae8d0cb0617b5e63ec119ca25"}, - {file = "frozenlist-1.6.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:95b7a8a3180dfb280eb044fdec562f9b461614c0ef21669aea6f1d3dac6ee576"}, - {file = "frozenlist-1.6.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:c444d824e22da6c9291886d80c7d00c444981a72686e2b59d38b285617cb52c8"}, - {file = "frozenlist-1.6.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bb52c8166499a8150bfd38478248572c924c003cbb45fe3bcd348e5ac7c000f9"}, - {file = "frozenlist-1.6.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b35298b2db9c2468106278537ee529719228950a5fdda686582f68f247d1dc6e"}, - {file = "frozenlist-1.6.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d108e2d070034f9d57210f22fefd22ea0d04609fc97c5f7f5a686b3471028590"}, - {file = "frozenlist-1.6.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4e1be9111cb6756868ac242b3c2bd1f09d9aea09846e4f5c23715e7afb647103"}, - {file = "frozenlist-1.6.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:94bb451c664415f02f07eef4ece976a2c65dcbab9c2f1705b7031a3a75349d8c"}, - {file = "frozenlist-1.6.0-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:d1a686d0b0949182b8faddea596f3fc11f44768d1f74d4cad70213b2e139d821"}, - {file = "frozenlist-1.6.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:ea8e59105d802c5a38bdbe7362822c522230b3faba2aa35c0fa1765239b7dd70"}, - {file = "frozenlist-1.6.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:abc4e880a9b920bc5020bf6a431a6bb40589d9bca3975c980495f63632e8382f"}, - {file = "frozenlist-1.6.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:9a79713adfe28830f27a3c62f6b5406c37376c892b05ae070906f07ae4487046"}, - {file = "frozenlist-1.6.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:9a0318c2068e217a8f5e3b85e35899f5a19e97141a45bb925bb357cfe1daf770"}, - {file = "frozenlist-1.6.0-cp312-cp312-win32.whl", hash = "sha256:853ac025092a24bb3bf09ae87f9127de9fe6e0c345614ac92536577cf956dfcc"}, - {file = "frozenlist-1.6.0-cp312-cp312-win_amd64.whl", hash = "sha256:2bdfe2d7e6c9281c6e55523acd6c2bf77963cb422fdc7d142fb0cb6621b66878"}, - {file = "frozenlist-1.6.0-py3-none-any.whl", hash = "sha256:535eec9987adb04701266b92745d6cdcef2e77669299359c3009c3404dd5d191"}, - {file = "frozenlist-1.6.0.tar.gz", hash = "sha256:b99655c32c1c8e06d111e7f41c06c29a5318cb1835df23a45518e02a47c63b68"}, + {file = "frozenlist-1.8.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:09474e9831bc2b2199fad6da3c14c7b0fbdd377cce9d3d77131be28906cb7d84"}, + {file = "frozenlist-1.8.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:17c883ab0ab67200b5f964d2b9ed6b00971917d5d8a92df149dc2c9779208ee9"}, + {file = "frozenlist-1.8.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:fa47e444b8ba08fffd1c18e8cdb9a75db1b6a27f17507522834ad13ed5922b93"}, + {file = "frozenlist-1.8.0-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:2552f44204b744fba866e573be4c1f9048d6a324dfe14475103fd51613eb1d1f"}, + {file = "frozenlist-1.8.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:957e7c38f250991e48a9a73e6423db1bb9dd14e722a10f6b8bb8e16a0f55f695"}, + {file = "frozenlist-1.8.0-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:8585e3bb2cdea02fc88ffa245069c36555557ad3609e83be0ec71f54fd4abb52"}, + {file = "frozenlist-1.8.0-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:edee74874ce20a373d62dc28b0b18b93f645633c2943fd90ee9d898550770581"}, + {file = "frozenlist-1.8.0-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:c9a63152fe95756b85f31186bddf42e4c02c6321207fd6601a1c89ebac4fe567"}, + {file = "frozenlist-1.8.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:b6db2185db9be0a04fecf2f241c70b63b1a242e2805be291855078f2b404dd6b"}, + {file = "frozenlist-1.8.0-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:f4be2e3d8bc8aabd566f8d5b8ba7ecc09249d74ba3c9ed52e54dc23a293f0b92"}, + {file = "frozenlist-1.8.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:c8d1634419f39ea6f5c427ea2f90ca85126b54b50837f31497f3bf38266e853d"}, + {file = "frozenlist-1.8.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:1a7fa382a4a223773ed64242dbe1c9c326ec09457e6b8428efb4118c685c3dfd"}, + {file = "frozenlist-1.8.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:11847b53d722050808926e785df837353bd4d75f1d494377e59b23594d834967"}, + {file = "frozenlist-1.8.0-cp311-cp311-win32.whl", hash = "sha256:27c6e8077956cf73eadd514be8fb04d77fc946a7fe9f7fe167648b0b9085cc25"}, + {file = "frozenlist-1.8.0-cp311-cp311-win_amd64.whl", hash = "sha256:ac913f8403b36a2c8610bbfd25b8013488533e71e62b4b4adce9c86c8cea905b"}, + {file = "frozenlist-1.8.0-cp311-cp311-win_arm64.whl", hash = "sha256:d4d3214a0f8394edfa3e303136d0575eece0745ff2b47bd2cb2e66dd92d4351a"}, + {file = "frozenlist-1.8.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:78f7b9e5d6f2fdb88cdde9440dc147259b62b9d3b019924def9f6478be254ac1"}, + {file = "frozenlist-1.8.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:229bf37d2e4acdaf808fd3f06e854a4a7a3661e871b10dc1f8f1896a3b05f18b"}, + {file = "frozenlist-1.8.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f833670942247a14eafbb675458b4e61c82e002a148f49e68257b79296e865c4"}, + {file = "frozenlist-1.8.0-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:494a5952b1c597ba44e0e78113a7266e656b9794eec897b19ead706bd7074383"}, + {file = "frozenlist-1.8.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:96f423a119f4777a4a056b66ce11527366a8bb92f54e541ade21f2374433f6d4"}, + {file = "frozenlist-1.8.0-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:3462dd9475af2025c31cc61be6652dfa25cbfb56cbbf52f4ccfe029f38decaf8"}, + {file = "frozenlist-1.8.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c4c800524c9cd9bac5166cd6f55285957fcfc907db323e193f2afcd4d9abd69b"}, + {file = "frozenlist-1.8.0-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d6a5df73acd3399d893dafc71663ad22534b5aa4f94e8a2fabfe856c3c1b6a52"}, + {file = "frozenlist-1.8.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:405e8fe955c2280ce66428b3ca55e12b3c4e9c336fb2103a4937e891c69a4a29"}, + {file = "frozenlist-1.8.0-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:908bd3f6439f2fef9e85031b59fd4f1297af54415fb60e4254a95f75b3cab3f3"}, + {file = "frozenlist-1.8.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:294e487f9ec720bd8ffcebc99d575f7eff3568a08a253d1ee1a0378754b74143"}, + {file = "frozenlist-1.8.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:74c51543498289c0c43656701be6b077f4b265868fa7f8a8859c197006efb608"}, + {file = "frozenlist-1.8.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:776f352e8329135506a1d6bf16ac3f87bc25b28e765949282dcc627af36123aa"}, + {file = "frozenlist-1.8.0-cp312-cp312-win32.whl", hash = "sha256:433403ae80709741ce34038da08511d4a77062aa924baf411ef73d1146e74faf"}, + {file = "frozenlist-1.8.0-cp312-cp312-win_amd64.whl", hash = "sha256:34187385b08f866104f0c0617404c8eb08165ab1272e884abc89c112e9c00746"}, + {file = "frozenlist-1.8.0-cp312-cp312-win_arm64.whl", hash = "sha256:fe3c58d2f5db5fbd18c2987cba06d51b0529f52bc3a6cdc33d3f4eab725104bd"}, + {file = "frozenlist-1.8.0-py3-none-any.whl", hash = "sha256:0c18a16eab41e82c295618a77502e17b195883241c563b00f0aa5106fc4eaa0d"}, + {file = "frozenlist-1.8.0.tar.gz", hash = "sha256:3ede829ed8d842f6cd48fc7081d7a41001a56f1f38603f9d49bf3020d59a31ad"}, ] [[package]] name = "fsspec" -version = "2025.5.1" -requires_python = ">=3.9" +version = "2025.12.0" +requires_python = ">=3.10" summary = "File-system specification" files = [ - {file = "fsspec-2025.5.1-py3-none-any.whl", hash = "sha256:24d3a2e663d5fc735ab256263c4075f374a174c3410c0b25e5bd1970bceaa462"}, - {file = "fsspec-2025.5.1.tar.gz", hash = "sha256:2e55e47a540b91843b755e83ded97c6e897fa0942b11490113f09e9c443c2475"}, + {file = "fsspec-2025.12.0-py3-none-any.whl", hash = "sha256:8bf1fe301b7d8acfa6e8571e3b1c3d158f909666642431cc78a1b7b4dbc5ec5b"}, + {file = "fsspec-2025.12.0.tar.gz", hash = "sha256:c505de011584597b1060ff778bb664c1bc022e87921b0e4f10cc9c44f9635973"}, ] [[package]] name = "fsspec" -version = "2025.5.1" +version = "2025.12.0" extras = ["http"] -requires_python = ">=3.9" +requires_python = ">=3.10" summary = "File-system specification" dependencies = [ "aiohttp!=4.0.0a0,!=4.0.0a1", - "fsspec==2025.5.1", + "fsspec==2025.12.0", ] files = [ - {file = "fsspec-2025.5.1-py3-none-any.whl", hash = "sha256:24d3a2e663d5fc735ab256263c4075f374a174c3410c0b25e5bd1970bceaa462"}, - {file = "fsspec-2025.5.1.tar.gz", hash = "sha256:2e55e47a540b91843b755e83ded97c6e897fa0942b11490113f09e9c443c2475"}, + {file = "fsspec-2025.12.0-py3-none-any.whl", hash = "sha256:8bf1fe301b7d8acfa6e8571e3b1c3d158f909666642431cc78a1b7b4dbc5ec5b"}, + {file = "fsspec-2025.12.0.tar.gz", hash = "sha256:c505de011584597b1060ff778bb664c1bc022e87921b0e4f10cc9c44f9635973"}, ] [[package]] @@ -942,16 +1115,16 @@ files = [ [[package]] name = "gitpython" -version = "3.1.44" +version = "3.1.45" requires_python = ">=3.7" summary = "GitPython is a Python library used to interact with Git repositories" dependencies = [ "gitdb<5,>=4.0.1", - "typing-extensions>=3.7.4.3; python_version < \"3.8\"", + "typing-extensions>=3.10.0.2; python_version < \"3.10\"", ] files = [ - {file = "GitPython-3.1.44-py3-none-any.whl", hash = "sha256:9e0e10cda9bed1ee64bc9a6de50e7e38a9c9943241cd7f585f6df3ed28011110"}, - {file = "gitpython-3.1.44.tar.gz", hash = "sha256:c87e30b26253bf5418b01b0660f818967f3c503193838337fe5e573331249269"}, + {file = "gitpython-3.1.45-py3-none-any.whl", hash = "sha256:8908cb2e02fb3b93b7eb0f2827125cb699869470432cc885f019b8fd0fccff77"}, + {file = "gitpython-3.1.45.tar.gz", hash = "sha256:85b0ee964ceddf211c41b9f27a49086010a190fd8132a24e21f362a4b36a791c"}, ] [[package]] @@ -994,28 +1167,38 @@ files = [ {file = "httpx-0.28.1.tar.gz", hash = "sha256:75e98c5f16b0f35b567856f597f06ff2270a374470a5c2392242528e3e3e42fc"}, ] +[[package]] +name = "humanize" +version = "4.14.0" +requires_python = ">=3.10" +summary = "Python humanize utilities" +files = [ + {file = "humanize-4.14.0-py3-none-any.whl", hash = "sha256:d57701248d040ad456092820e6fde56c930f17749956ac47f4f655c0c547bfff"}, + {file = "humanize-4.14.0.tar.gz", hash = "sha256:2fa092705ea640d605c435b1ca82b2866a1b601cdf96f076d70b79a855eba90d"}, +] + [[package]] name = "idna" -version = "3.10" -requires_python = ">=3.6" +version = "3.11" +requires_python = ">=3.8" summary = "Internationalized Domain Names in Applications (IDNA)" files = [ - {file = "idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3"}, - {file = "idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9"}, + {file = "idna-3.11-py3-none-any.whl", hash = "sha256:771a87f49d9defaf64091e6e6fe9c18d4833f140bd19464795bc32d966ca37ea"}, + {file = "idna-3.11.tar.gz", hash = "sha256:795dafcc9c04ed0c1fb032c2aa73654d8e8c5023a7df64a53f39190ada629902"}, ] [[package]] name = "imageio" -version = "2.37.0" +version = "2.37.2" requires_python = ">=3.9" -summary = "Library for reading and writing a wide range of image, video, scientific, and volumetric data formats." +summary = "Read and write images and video across all major formats. Supports scientific and volumetric data." dependencies = [ "numpy", "pillow>=8.3.2", ] files = [ - {file = "imageio-2.37.0-py3-none-any.whl", hash = "sha256:11efa15b87bc7871b61590326b2d635439acc321cf7f8ce996f812543ce10eed"}, - {file = "imageio-2.37.0.tar.gz", hash = "sha256:71b57b3669666272c818497aebba2b4c5f20d5b37c81720e5e1a56d59c492996"}, + {file = "imageio-2.37.2-py3-none-any.whl", hash = "sha256:ad9adfb20335d718c03de457358ed69f141021a333c40a53e57273d8a5bd0b9b"}, + {file = "imageio-2.37.2.tar.gz", hash = "sha256:0212ef2727ac9caa5ca4b2c75ae89454312f440a756fcfc8ef1993e718f50f8a"}, ] [[package]] @@ -1034,60 +1217,60 @@ files = [ [[package]] name = "iniconfig" -version = "2.1.0" -requires_python = ">=3.8" +version = "2.3.0" +requires_python = ">=3.10" summary = "brain-dead simple config-ini parsing" files = [ - {file = "iniconfig-2.1.0-py3-none-any.whl", hash = "sha256:9deba5723312380e77435581c6bf4935c94cbfab9b1ed33ef8d238ea168eb760"}, - {file = "iniconfig-2.1.0.tar.gz", hash = "sha256:3abbd2e30b36733fee78f9c7f7308f2d0050e88f0087fd25c2645f63c773e1c7"}, + {file = "iniconfig-2.3.0-py3-none-any.whl", hash = "sha256:f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12"}, + {file = "iniconfig-2.3.0.tar.gz", hash = "sha256:c76315c77db068650d49c5b56314774a7804df16fee4402c1f19d6d15d8c4730"}, ] [[package]] name = "ipykernel" -version = "6.29.5" -requires_python = ">=3.8" +version = "7.1.0" +requires_python = ">=3.10" summary = "IPython Kernel for Jupyter" dependencies = [ - "appnope; platform_system == \"Darwin\"", + "appnope>=0.1.2; platform_system == \"Darwin\"", "comm>=0.1.1", "debugpy>=1.6.5", "ipython>=7.23.1", - "jupyter-client>=6.1.12", + "jupyter-client>=8.0.0", "jupyter-core!=5.0.*,>=4.12", "matplotlib-inline>=0.1", - "nest-asyncio", - "packaging", - "psutil", - "pyzmq>=24", - "tornado>=6.1", + "nest-asyncio>=1.4", + "packaging>=22", + "psutil>=5.7", + "pyzmq>=25", + "tornado>=6.2", "traitlets>=5.4.0", ] files = [ - {file = "ipykernel-6.29.5-py3-none-any.whl", hash = "sha256:afdb66ba5aa354b09b91379bac28ae4afebbb30e8b39510c9690afb7a10421b5"}, - {file = "ipykernel-6.29.5.tar.gz", hash = "sha256:f093a22c4a40f8828f8e330a9c297cb93dcab13bd9678ded6de8e5cf81c56215"}, + {file = "ipykernel-7.1.0-py3-none-any.whl", hash = "sha256:763b5ec6c5b7776f6a8d7ce09b267693b4e5ce75cb50ae696aaefb3c85e1ea4c"}, + {file = "ipykernel-7.1.0.tar.gz", hash = "sha256:58a3fc88533d5930c3546dc7eac66c6d288acde4f801e2001e65edc5dc9cf0db"}, ] [[package]] name = "ipython" -version = "9.2.0" +version = "9.8.0" requires_python = ">=3.11" summary = "IPython: Productive Interactive Computing" dependencies = [ - "colorama; sys_platform == \"win32\"", - "decorator", - "ipython-pygments-lexers", - "jedi>=0.16", - "matplotlib-inline", + "colorama>=0.4.4; sys_platform == \"win32\"", + "decorator>=4.3.2", + "ipython-pygments-lexers>=1.0.0", + "jedi>=0.18.1", + "matplotlib-inline>=0.1.5", "pexpect>4.3; sys_platform != \"win32\" and sys_platform != \"emscripten\"", "prompt-toolkit<3.1.0,>=3.0.41", - "pygments>=2.4.0", - "stack-data", + "pygments>=2.11.0", + "stack-data>=0.6.0", "traitlets>=5.13.0", "typing-extensions>=4.6; python_version < \"3.12\"", ] files = [ - {file = "ipython-9.2.0-py3-none-any.whl", hash = "sha256:fef5e33c4a1ae0759e0bba5917c9db4eb8c53fee917b6a526bd973e1ca5159f6"}, - {file = "ipython-9.2.0.tar.gz", hash = "sha256:62a9373dbc12f28f9feaf4700d052195bf89806279fc8ca11f3f54017d04751b"}, + {file = "ipython-9.8.0-py3-none-any.whl", hash = "sha256:ebe6d1d58d7d988fbf23ff8ff6d8e1622cfdb194daf4b7b73b792c4ec3b85385"}, + {file = "ipython-9.8.0.tar.gz", hash = "sha256:8e4ce129a627eb9dd221c41b1d2cdaed4ef7c9da8c17c63f6f578fe231141f83"}, ] [[package]] @@ -1105,7 +1288,7 @@ files = [ [[package]] name = "ipywidgets" -version = "8.1.7" +version = "8.1.8" requires_python = ">=3.7" summary = "Jupyter interactive widgets" dependencies = [ @@ -1116,8 +1299,8 @@ dependencies = [ "widgetsnbextension~=4.0.14", ] files = [ - {file = "ipywidgets-8.1.7-py3-none-any.whl", hash = "sha256:764f2602d25471c213919b8a1997df04bef869251db4ca8efba1b76b1bd9f7bb"}, - {file = "ipywidgets-8.1.7.tar.gz", hash = "sha256:15f1ac050b9ccbefd45dccfbb2ef6bed0029d8278682d569d71b8dd96bee0376"}, + {file = "ipywidgets-8.1.8-py3-none-any.whl", hash = "sha256:ecaca67aed704a338f88f67b1181b58f821ab5dc89c1f0f5ef99db43c1c2921e"}, + {file = "ipywidgets-8.1.8.tar.gz", hash = "sha256:61f969306b95f85fba6b6986b7fe45d73124d1d9e3023a8068710d47a22ea668"}, ] [[package]] @@ -1161,22 +1344,22 @@ files = [ [[package]] name = "joblib" -version = "1.5.0" +version = "1.5.2" requires_python = ">=3.9" summary = "Lightweight pipelining with Python functions" files = [ - {file = "joblib-1.5.0-py3-none-any.whl", hash = "sha256:206144b320246485b712fc8cc51f017de58225fa8b414a1fe1764a7231aca491"}, - {file = "joblib-1.5.0.tar.gz", hash = "sha256:d8757f955389a3dd7a23152e43bc297c2e0c2d3060056dad0feefc88a06939b5"}, + {file = "joblib-1.5.2-py3-none-any.whl", hash = "sha256:4e1f0bdbb987e6d843c70cf43714cb276623def372df3c22fe5266b2670bc241"}, + {file = "joblib-1.5.2.tar.gz", hash = "sha256:3faa5c39054b2f03ca547da9b2f52fde67c06240c31853f306aea97f13647b55"}, ] [[package]] name = "json5" -version = "0.12.0" +version = "0.12.1" requires_python = ">=3.8.0" summary = "A Python implementation of the JSON5 data format." files = [ - {file = "json5-0.12.0-py3-none-any.whl", hash = "sha256:6d37aa6c08b0609f16e1ec5ff94697e2cbbfbad5ac112afa05794da9ab7810db"}, - {file = "json5-0.12.0.tar.gz", hash = "sha256:0b4b6ff56801a1c7dc817b0241bca4ce474a0e6a163bfef3fc594d3fd263ff3a"}, + {file = "json5-0.12.1-py3-none-any.whl", hash = "sha256:d9c9b3bc34a5f54d43c35e11ef7cb87d8bdd098c6ace87117a7b7e83e705c1d5"}, + {file = "json5-0.12.1.tar.gz", hash = "sha256:b2743e77b3242f8d03c143dd975a6ec7c52e2f2afe76ed934e53503dd4ad4990"}, ] [[package]] @@ -1191,55 +1374,54 @@ files = [ [[package]] name = "jsonschema" -version = "4.23.0" -requires_python = ">=3.8" +version = "4.25.1" +requires_python = ">=3.9" summary = "An implementation of JSON Schema validation for Python" dependencies = [ "attrs>=22.2.0", - "importlib-resources>=1.4.0; python_version < \"3.9\"", "jsonschema-specifications>=2023.03.6", - "pkgutil-resolve-name>=1.3.10; python_version < \"3.9\"", "referencing>=0.28.4", "rpds-py>=0.7.1", ] files = [ - {file = "jsonschema-4.23.0-py3-none-any.whl", hash = "sha256:fbadb6f8b144a8f8cf9f0b89ba94501d143e50411a1278633f56a7acf7fd5566"}, - {file = "jsonschema-4.23.0.tar.gz", hash = "sha256:d71497fef26351a33265337fa77ffeb82423f3ea21283cd9467bb03999266bc4"}, + {file = "jsonschema-4.25.1-py3-none-any.whl", hash = "sha256:3fba0169e345c7175110351d456342c364814cfcf3b964ba4587f22915230a63"}, + {file = "jsonschema-4.25.1.tar.gz", hash = "sha256:e4a9655ce0da0c0b67a085847e00a3a51449e1157f4f75e9fb5aa545e122eb85"}, ] [[package]] name = "jsonschema-specifications" -version = "2025.4.1" +version = "2025.9.1" requires_python = ">=3.9" summary = "The JSON Schema meta-schemas and vocabularies, exposed as a Registry" dependencies = [ "referencing>=0.31.0", ] files = [ - {file = "jsonschema_specifications-2025.4.1-py3-none-any.whl", hash = "sha256:4653bffbd6584f7de83a67e0d620ef16900b390ddc7939d56684d6c81e33f1af"}, - {file = "jsonschema_specifications-2025.4.1.tar.gz", hash = "sha256:630159c9f4dbea161a6a2205c3011cc4f18ff381b189fff48bb39b9bf26ae608"}, + {file = "jsonschema_specifications-2025.9.1-py3-none-any.whl", hash = "sha256:98802fee3a11ee76ecaca44429fda8a41bff98b00a0f2838151b113f210cc6fe"}, + {file = "jsonschema_specifications-2025.9.1.tar.gz", hash = "sha256:b540987f239e745613c7a9176f3edb72b832a4ac465cf02712288397832b5e8d"}, ] [[package]] name = "jsonschema" -version = "4.23.0" +version = "4.25.1" extras = ["format-nongpl"] -requires_python = ">=3.8" +requires_python = ">=3.9" summary = "An implementation of JSON Schema validation for Python" dependencies = [ "fqdn", "idna", "isoduration", "jsonpointer>1.13", - "jsonschema==4.23.0", + "jsonschema==4.25.1", "rfc3339-validator", "rfc3986-validator>0.1.0", + "rfc3987-syntax>=1.1.0", "uri-template", "webcolors>=24.6.0", ] files = [ - {file = "jsonschema-4.23.0-py3-none-any.whl", hash = "sha256:fbadb6f8b144a8f8cf9f0b89ba94501d143e50411a1278633f56a7acf7fd5566"}, - {file = "jsonschema-4.23.0.tar.gz", hash = "sha256:d71497fef26351a33265337fa77ffeb82423f3ea21283cd9467bb03999266bc4"}, + {file = "jsonschema-4.25.1-py3-none-any.whl", hash = "sha256:3fba0169e345c7175110351d456342c364814cfcf3b964ba4587f22915230a63"}, + {file = "jsonschema-4.25.1.tar.gz", hash = "sha256:e4a9655ce0da0c0b67a085847e00a3a51449e1157f4f75e9fb5aa545e122eb85"}, ] [[package]] @@ -1261,20 +1443,19 @@ files = [ [[package]] name = "jupyter-client" -version = "8.6.3" -requires_python = ">=3.8" +version = "8.7.0" +requires_python = ">=3.10" summary = "Jupyter protocol implementation and client libraries" dependencies = [ - "importlib-metadata>=4.8.3; python_version < \"3.10\"", - "jupyter-core!=5.0.*,>=4.12", + "jupyter-core>=5.1", "python-dateutil>=2.8.2", - "pyzmq>=23.0", - "tornado>=6.2", + "pyzmq>=25.0", + "tornado>=6.4.1", "traitlets>=5.3", ] files = [ - {file = "jupyter_client-8.6.3-py3-none-any.whl", hash = "sha256:e8a19cc986cc45905ac3362915f410f3af85424b4c0905e94fa5f2cb08e8f23f"}, - {file = "jupyter_client-8.6.3.tar.gz", hash = "sha256:35b3a0947c4a6e9d589eb97d7d4cd5e90f910ee73101611f01283732bd6d9419"}, + {file = "jupyter_client-8.7.0-py3-none-any.whl", hash = "sha256:3671a94fd25e62f5f2f554f5e95389c2294d89822378a5f2dd24353e1494a9e0"}, + {file = "jupyter_client-8.7.0.tar.gz", hash = "sha256:3357212d9cbe01209e59190f67a3a7e1f387a4f4e88d1e0433ad84d7b262531d"}, ] [[package]] @@ -1299,17 +1480,16 @@ files = [ [[package]] name = "jupyter-core" -version = "5.7.2" -requires_python = ">=3.8" +version = "5.9.1" +requires_python = ">=3.10" summary = "Jupyter core package. A base package on which Jupyter projects rely." dependencies = [ "platformdirs>=2.5", - "pywin32>=300; sys_platform == \"win32\" and platform_python_implementation != \"PyPy\"", "traitlets>=5.3", ] files = [ - {file = "jupyter_core-5.7.2-py3-none-any.whl", hash = "sha256:4f7315d2f6b4bcf2e3e7cb6e46772eba760ae459cd1f59d29eb57b0a01bd7409"}, - {file = "jupyter_core-5.7.2.tar.gz", hash = "sha256:aa5f8d32bbf6b431ac830496da7392035d6f61b4f54872f15c4bd2a9c3f536d9"}, + {file = "jupyter_core-5.9.1-py3-none-any.whl", hash = "sha256:ebf87fdc6073d142e114c72c9e29a9d7ca03fad818c5d300ce2adc1fb0743407"}, + {file = "jupyter_core-5.9.1.tar.gz", hash = "sha256:4d09aaff303b9566c3ce657f580bd089ff5c91f5f89cf7d8846c3cdf465b5508"}, ] [[package]] @@ -1334,7 +1514,7 @@ files = [ [[package]] name = "jupyter-lsp" -version = "2.2.5" +version = "2.3.0" requires_python = ">=3.8" summary = "Multi-Language Server WebSocket proxy for Jupyter Notebook/Lab server" dependencies = [ @@ -1342,13 +1522,13 @@ dependencies = [ "jupyter-server>=1.1.2", ] files = [ - {file = "jupyter-lsp-2.2.5.tar.gz", hash = "sha256:793147a05ad446f809fd53ef1cd19a9f5256fd0a2d6b7ce943a982cb4f545001"}, - {file = "jupyter_lsp-2.2.5-py3-none-any.whl", hash = "sha256:45fbddbd505f3fbfb0b6cb2f1bc5e15e83ab7c79cd6e89416b248cb3c00c11da"}, + {file = "jupyter_lsp-2.3.0-py3-none-any.whl", hash = "sha256:e914a3cb2addf48b1c7710914771aaf1819d46b2e5a79b0f917b5478ec93f34f"}, + {file = "jupyter_lsp-2.3.0.tar.gz", hash = "sha256:458aa59339dc868fb784d73364f17dbce8836e906cd75fd471a325cba02e0245"}, ] [[package]] name = "jupyter-server" -version = "2.16.0" +version = "2.17.0" requires_python = ">=3.9" summary = "The backend—i.e. core services, APIs, and REST endpoints—to Jupyter web applications." dependencies = [ @@ -1361,7 +1541,7 @@ dependencies = [ "jupyter-server-terminals>=0.4.4", "nbconvert>=6.4.4", "nbformat>=5.3.0", - "overrides>=5.0", + "overrides>=5.0; python_version < \"3.12\"", "packaging>=22.0", "prometheus-client>=0.9", "pywinpty>=2.0.1; os_name == \"nt\"", @@ -1373,8 +1553,8 @@ dependencies = [ "websocket-client>=1.7", ] files = [ - {file = "jupyter_server-2.16.0-py3-none-any.whl", hash = "sha256:3d8db5be3bc64403b1c65b400a1d7f4647a5ce743f3b20dbdefe8ddb7b55af9e"}, - {file = "jupyter_server-2.16.0.tar.gz", hash = "sha256:65d4b44fdf2dcbbdfe0aa1ace4a842d4aaf746a2b7b168134d5aaed35621b7f6"}, + {file = "jupyter_server-2.17.0-py3-none-any.whl", hash = "sha256:e8cb9c7db4251f51ed307e329b81b72ccf2056ff82d50524debde1ee1870e13f"}, + {file = "jupyter_server-2.17.0.tar.gz", hash = "sha256:c38ea898566964c888b4772ae1ed58eca84592e88251d2cfc4d171f81f7e99d5"}, ] [[package]] @@ -1393,19 +1573,19 @@ files = [ [[package]] name = "jupyterlab" -version = "4.4.2" +version = "4.5.0" requires_python = ">=3.9" summary = "JupyterLab computational environment" dependencies = [ "async-lru>=1.0.0", - "httpx>=0.25.0", + "httpx<1,>=0.25.0", "importlib-metadata>=4.8.3; python_version < \"3.10\"", - "ipykernel>=6.5.0", + "ipykernel!=6.30.0,>=6.5.0", "jinja2>=3.0.3", "jupyter-core", "jupyter-lsp>=2.0.0", "jupyter-server<3,>=2.4.0", - "jupyterlab-server<3,>=2.27.1", + "jupyterlab-server<3,>=2.28.0", "notebook-shim>=0.2", "packaging", "setuptools>=41.1.0", @@ -1414,8 +1594,8 @@ dependencies = [ "traitlets", ] files = [ - {file = "jupyterlab-4.4.2-py3-none-any.whl", hash = "sha256:857111a50bed68542bf55dca784522fe728f9f88b4fe69e8c585db5c50900419"}, - {file = "jupyterlab-4.4.2.tar.gz", hash = "sha256:afa9caf28c0cb966488be18e5e8daba9f018a1c4273a406b7d5006344cbc6d16"}, + {file = "jupyterlab-4.5.0-py3-none-any.whl", hash = "sha256:88e157c75c1afff64c7dc4b801ec471450b922a4eae4305211ddd40da8201c8a"}, + {file = "jupyterlab-4.5.0.tar.gz", hash = "sha256:aec33d6d8f1225b495ee2cf20f0514f45e6df8e360bdd7ac9bace0b7ac5177ea"}, ] [[package]] @@ -1430,7 +1610,7 @@ files = [ [[package]] name = "jupyterlab-server" -version = "2.27.3" +version = "2.28.0" requires_python = ">=3.8" summary = "A set of server components for JupyterLab and JupyterLab like applications." dependencies = [ @@ -1444,57 +1624,68 @@ dependencies = [ "requests>=2.31", ] files = [ - {file = "jupyterlab_server-2.27.3-py3-none-any.whl", hash = "sha256:e697488f66c3db49df675158a77b3b017520d772c6e1548c7d9bcc5df7944ee4"}, - {file = "jupyterlab_server-2.27.3.tar.gz", hash = "sha256:eb36caca59e74471988f0ae25c77945610b887f777255aa21f8065def9e51ed4"}, + {file = "jupyterlab_server-2.28.0-py3-none-any.whl", hash = "sha256:e4355b148fdcf34d312bbbc80f22467d6d20460e8b8736bf235577dd18506968"}, + {file = "jupyterlab_server-2.28.0.tar.gz", hash = "sha256:35baa81898b15f93573e2deca50d11ac0ae407ebb688299d3a5213265033712c"}, ] [[package]] name = "jupyterlab-widgets" -version = "3.0.15" +version = "3.0.16" requires_python = ">=3.7" summary = "Jupyter interactive widgets for JupyterLab" files = [ - {file = "jupyterlab_widgets-3.0.15-py3-none-any.whl", hash = "sha256:d59023d7d7ef71400d51e6fee9a88867f6e65e10a4201605d2d7f3e8f012a31c"}, - {file = "jupyterlab_widgets-3.0.15.tar.gz", hash = "sha256:2920888a0c2922351a9202817957a68c07d99673504d6cd37345299e971bb08b"}, + {file = "jupyterlab_widgets-3.0.16-py3-none-any.whl", hash = "sha256:45fa36d9c6422cf2559198e4db481aa243c7a32d9926b500781c830c80f7ecf8"}, + {file = "jupyterlab_widgets-3.0.16.tar.gz", hash = "sha256:423da05071d55cf27a9e602216d35a3a65a3e41cdf9c5d3b643b814ce38c19e0"}, ] [[package]] name = "kiwisolver" -version = "1.4.8" +version = "1.4.9" requires_python = ">=3.10" summary = "A fast implementation of the Cassowary constraint solver" files = [ - {file = "kiwisolver-1.4.8-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:a4d3601908c560bdf880f07d94f31d734afd1bb71e96585cace0e38ef44c6d84"}, - {file = "kiwisolver-1.4.8-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:856b269c4d28a5c0d5e6c1955ec36ebfd1651ac00e1ce0afa3e28da95293b561"}, - {file = "kiwisolver-1.4.8-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c2b9a96e0f326205af81a15718a9073328df1173a2619a68553decb7097fd5d7"}, - {file = "kiwisolver-1.4.8-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c5020c83e8553f770cb3b5fc13faac40f17e0b205bd237aebd21d53d733adb03"}, - {file = "kiwisolver-1.4.8-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dace81d28c787956bfbfbbfd72fdcef014f37d9b48830829e488fdb32b49d954"}, - {file = "kiwisolver-1.4.8-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:11e1022b524bd48ae56c9b4f9296bce77e15a2e42a502cceba602f804b32bb79"}, - {file = "kiwisolver-1.4.8-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3b9b4d2892fefc886f30301cdd80debd8bb01ecdf165a449eb6e78f79f0fabd6"}, - {file = "kiwisolver-1.4.8-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3a96c0e790ee875d65e340ab383700e2b4891677b7fcd30a699146f9384a2bb0"}, - {file = "kiwisolver-1.4.8-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:23454ff084b07ac54ca8be535f4174170c1094a4cff78fbae4f73a4bcc0d4dab"}, - {file = "kiwisolver-1.4.8-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:87b287251ad6488e95b4f0b4a79a6d04d3ea35fde6340eb38fbd1ca9cd35bbbc"}, - {file = "kiwisolver-1.4.8-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:b21dbe165081142b1232a240fc6383fd32cdd877ca6cc89eab93e5f5883e1c25"}, - {file = "kiwisolver-1.4.8-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:768cade2c2df13db52475bd28d3a3fac8c9eff04b0e9e2fda0f3760f20b3f7fc"}, - {file = "kiwisolver-1.4.8-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:d47cfb2650f0e103d4bf68b0b5804c68da97272c84bb12850d877a95c056bd67"}, - {file = "kiwisolver-1.4.8-cp311-cp311-win_amd64.whl", hash = "sha256:ed33ca2002a779a2e20eeb06aea7721b6e47f2d4b8a8ece979d8ba9e2a167e34"}, - {file = "kiwisolver-1.4.8-cp311-cp311-win_arm64.whl", hash = "sha256:16523b40aab60426ffdebe33ac374457cf62863e330a90a0383639ce14bf44b2"}, - {file = "kiwisolver-1.4.8-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:d6af5e8815fd02997cb6ad9bbed0ee1e60014438ee1a5c2444c96f87b8843502"}, - {file = "kiwisolver-1.4.8-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:bade438f86e21d91e0cf5dd7c0ed00cda0f77c8c1616bd83f9fc157fa6760d31"}, - {file = "kiwisolver-1.4.8-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:b83dc6769ddbc57613280118fb4ce3cd08899cc3369f7d0e0fab518a7cf37fdb"}, - {file = "kiwisolver-1.4.8-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:111793b232842991be367ed828076b03d96202c19221b5ebab421ce8bcad016f"}, - {file = "kiwisolver-1.4.8-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:257af1622860e51b1a9d0ce387bf5c2c4f36a90594cb9514f55b074bcc787cfc"}, - {file = "kiwisolver-1.4.8-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:69b5637c3f316cab1ec1c9a12b8c5f4750a4c4b71af9157645bf32830e39c03a"}, - {file = "kiwisolver-1.4.8-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:782bb86f245ec18009890e7cb8d13a5ef54dcf2ebe18ed65f795e635a96a1c6a"}, - {file = "kiwisolver-1.4.8-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cc978a80a0db3a66d25767b03688f1147a69e6237175c0f4ffffaaedf744055a"}, - {file = "kiwisolver-1.4.8-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:36dbbfd34838500a31f52c9786990d00150860e46cd5041386f217101350f0d3"}, - {file = "kiwisolver-1.4.8-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:eaa973f1e05131de5ff3569bbba7f5fd07ea0595d3870ed4a526d486fe57fa1b"}, - {file = "kiwisolver-1.4.8-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:a66f60f8d0c87ab7f59b6fb80e642ebb29fec354a4dfad687ca4092ae69d04f4"}, - {file = "kiwisolver-1.4.8-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:858416b7fb777a53f0c59ca08190ce24e9abbd3cffa18886a5781b8e3e26f65d"}, - {file = "kiwisolver-1.4.8-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:085940635c62697391baafaaeabdf3dd7a6c3643577dde337f4d66eba021b2b8"}, - {file = "kiwisolver-1.4.8-cp312-cp312-win_amd64.whl", hash = "sha256:01c3d31902c7db5fb6182832713d3b4122ad9317c2c5877d0539227d96bb2e50"}, - {file = "kiwisolver-1.4.8-cp312-cp312-win_arm64.whl", hash = "sha256:a3c44cb68861de93f0c4a8175fbaa691f0aa22550c331fefef02b618a9dcb476"}, - {file = "kiwisolver-1.4.8.tar.gz", hash = "sha256:23d5f023bdc8c7e54eb65f03ca5d5bb25b601eac4d7f1a042888a1f45237987e"}, + {file = "kiwisolver-1.4.9-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:eb14a5da6dc7642b0f3a18f13654847cd8b7a2550e2645a5bda677862b03ba16"}, + {file = "kiwisolver-1.4.9-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:39a219e1c81ae3b103643d2aedb90f1ef22650deb266ff12a19e7773f3e5f089"}, + {file = "kiwisolver-1.4.9-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2405a7d98604b87f3fc28b1716783534b1b4b8510d8142adca34ee0bc3c87543"}, + {file = "kiwisolver-1.4.9-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:dc1ae486f9abcef254b5618dfb4113dd49f94c68e3e027d03cf0143f3f772b61"}, + {file = "kiwisolver-1.4.9-cp311-cp311-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8a1f570ce4d62d718dce3f179ee78dac3b545ac16c0c04bb363b7607a949c0d1"}, + {file = "kiwisolver-1.4.9-cp311-cp311-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:cb27e7b78d716c591e88e0a09a2139c6577865d7f2e152488c2cc6257f460872"}, + {file = "kiwisolver-1.4.9-cp311-cp311-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:15163165efc2f627eb9687ea5f3a28137217d217ac4024893d753f46bce9de26"}, + {file = "kiwisolver-1.4.9-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:bdee92c56a71d2b24c33a7d4c2856bd6419d017e08caa7802d2963870e315028"}, + {file = "kiwisolver-1.4.9-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:412f287c55a6f54b0650bd9b6dce5aceddb95864a1a90c87af16979d37c89771"}, + {file = "kiwisolver-1.4.9-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:2c93f00dcba2eea70af2be5f11a830a742fe6b579a1d4e00f47760ef13be247a"}, + {file = "kiwisolver-1.4.9-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f117e1a089d9411663a3207ba874f31be9ac8eaa5b533787024dc07aeb74f464"}, + {file = "kiwisolver-1.4.9-cp311-cp311-win_amd64.whl", hash = "sha256:be6a04e6c79819c9a8c2373317d19a96048e5a3f90bec587787e86a1153883c2"}, + {file = "kiwisolver-1.4.9-cp311-cp311-win_arm64.whl", hash = "sha256:0ae37737256ba2de764ddc12aed4956460277f00c4996d51a197e72f62f5eec7"}, + {file = "kiwisolver-1.4.9-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:ac5a486ac389dddcc5bef4f365b6ae3ffff2c433324fb38dd35e3fab7c957999"}, + {file = "kiwisolver-1.4.9-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:f2ba92255faa7309d06fe44c3a4a97efe1c8d640c2a79a5ef728b685762a6fd2"}, + {file = "kiwisolver-1.4.9-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:4a2899935e724dd1074cb568ce7ac0dce28b2cd6ab539c8e001a8578eb106d14"}, + {file = "kiwisolver-1.4.9-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:f6008a4919fdbc0b0097089f67a1eb55d950ed7e90ce2cc3e640abadd2757a04"}, + {file = "kiwisolver-1.4.9-cp312-cp312-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:67bb8b474b4181770f926f7b7d2f8c0248cbcb78b660fdd41a47054b28d2a752"}, + {file = "kiwisolver-1.4.9-cp312-cp312-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:2327a4a30d3ee07d2fbe2e7933e8a37c591663b96ce42a00bc67461a87d7df77"}, + {file = "kiwisolver-1.4.9-cp312-cp312-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:7a08b491ec91b1d5053ac177afe5290adacf1f0f6307d771ccac5de30592d198"}, + {file = "kiwisolver-1.4.9-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:d8fc5c867c22b828001b6a38d2eaeb88160bf5783c6cb4a5e440efc981ce286d"}, + {file = "kiwisolver-1.4.9-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:3b3115b2581ea35bb6d1f24a4c90af37e5d9b49dcff267eeed14c3893c5b86ab"}, + {file = "kiwisolver-1.4.9-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:858e4c22fb075920b96a291928cb7dea5644e94c0ee4fcd5af7e865655e4ccf2"}, + {file = "kiwisolver-1.4.9-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ed0fecd28cc62c54b262e3736f8bb2512d8dcfdc2bcf08be5f47f96bf405b145"}, + {file = "kiwisolver-1.4.9-cp312-cp312-win_amd64.whl", hash = "sha256:f68208a520c3d86ea51acf688a3e3002615a7f0238002cccc17affecc86a8a54"}, + {file = "kiwisolver-1.4.9-cp312-cp312-win_arm64.whl", hash = "sha256:2c1a4f57df73965f3f14df20b80ee29e6a7930a57d2d9e8491a25f676e197c60"}, + {file = "kiwisolver-1.4.9-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:720e05574713db64c356e86732c0f3c5252818d05f9df320f0ad8380641acea5"}, + {file = "kiwisolver-1.4.9-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:17680d737d5335b552994a2008fab4c851bcd7de33094a82067ef3a576ff02fa"}, + {file = "kiwisolver-1.4.9-pp311-pypy311_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:85b5352f94e490c028926ea567fc569c52ec79ce131dadb968d3853e809518c2"}, + {file = "kiwisolver-1.4.9-pp311-pypy311_pp73-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:464415881e4801295659462c49461a24fb107c140de781d55518c4b80cb6790f"}, + {file = "kiwisolver-1.4.9-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:fb940820c63a9590d31d88b815e7a3aa5915cad3ce735ab45f0c730b39547de1"}, + {file = "kiwisolver-1.4.9.tar.gz", hash = "sha256:c3b22c26c6fd6811b0ae8363b95ca8ce4ea3c202d3d0975b2914310ceb1bcc4d"}, +] + +[[package]] +name = "lark" +version = "1.3.1" +requires_python = ">=3.8" +summary = "a modern parsing library" +files = [ + {file = "lark-1.3.1-py3-none-any.whl", hash = "sha256:c629b661023a014c37da873b4ff58a817398d12635d3bbb2c5a03be7fe5d1e12"}, + {file = "lark-1.3.1.tar.gz", hash = "sha256:b426a7a6d6d53189d318f2b6236ab5d6429eaf09259f1ca33eb716eed10d2905"}, ] [[package]] @@ -1513,75 +1704,155 @@ files = [ [[package]] name = "levenshtein" -version = "0.27.1" -requires_python = ">=3.9" +version = "0.27.3" +requires_python = ">=3.10" summary = "Python extension for computing string edit distances and similarities." dependencies = [ "rapidfuzz<4.0.0,>=3.9.0", ] files = [ - {file = "levenshtein-0.27.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2e6f1760108319a108dceb2f02bc7cdb78807ad1f9c673c95eaa1d0fe5dfcaae"}, - {file = "levenshtein-0.27.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c4ed8400d94ab348099395e050b8ed9dd6a5d6b5b9e75e78b2b3d0b5f5b10f38"}, - {file = "levenshtein-0.27.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7826efe51be8ff58bc44a633e022fdd4b9fc07396375a6dbc4945a3bffc7bf8f"}, - {file = "levenshtein-0.27.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ff5afb78719659d353055863c7cb31599fbea6865c0890b2d840ee40214b3ddb"}, - {file = "levenshtein-0.27.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:201dafd5c004cd52018560cf3213da799534d130cf0e4db839b51f3f06771de0"}, - {file = "levenshtein-0.27.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e5ddd59f3cfaec216811ee67544779d9e2d6ed33f79337492a248245d6379e3d"}, - {file = "levenshtein-0.27.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6afc241d27ecf5b921063b796812c55b0115423ca6fa4827aa4b1581643d0a65"}, - {file = "levenshtein-0.27.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:ee2e766277cceb8ca9e584ea03b8dc064449ba588d3e24c1923e4b07576db574"}, - {file = "levenshtein-0.27.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:920b23d6109453913ce78ec451bc402ff19d020ee8be4722e9d11192ec2fac6f"}, - {file = "levenshtein-0.27.1-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:560d7edba126e2eea3ac3f2f12e7bd8bc9c6904089d12b5b23b6dfa98810b209"}, - {file = "levenshtein-0.27.1-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:8d5362b6c7aa4896dc0cb1e7470a4ad3c06124e0af055dda30d81d3c5549346b"}, - {file = "levenshtein-0.27.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:65ba880815b0f80a80a293aeebac0fab8069d03ad2d6f967a886063458f9d7a1"}, - {file = "levenshtein-0.27.1-cp311-cp311-win32.whl", hash = "sha256:fcc08effe77fec0bc5b0f6f10ff20b9802b961c4a69047b5499f383119ddbe24"}, - {file = "levenshtein-0.27.1-cp311-cp311-win_amd64.whl", hash = "sha256:0ed402d8902be7df212ac598fc189f9b2d520817fdbc6a05e2ce44f7f3ef6857"}, - {file = "levenshtein-0.27.1-cp311-cp311-win_arm64.whl", hash = "sha256:7fdaab29af81a8eb981043737f42450efca64b9761ca29385487b29c506da5b5"}, - {file = "levenshtein-0.27.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:25fb540d8c55d1dc7bdc59b7de518ea5ed9df92eb2077e74bcb9bb6de7b06f69"}, - {file = "levenshtein-0.27.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f09cfab6387e9c908c7b37961c045e8e10eb9b7ec4a700367f8e080ee803a562"}, - {file = "levenshtein-0.27.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dafa29c0e616f322b574e0b2aeb5b1ff2f8d9a1a6550f22321f3bd9bb81036e3"}, - {file = "levenshtein-0.27.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:be7a7642ea64392fa1e6ef7968c2e50ef2152c60948f95d0793361ed97cf8a6f"}, - {file = "levenshtein-0.27.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:060b48c45ed54bcea9582ce79c6365b20a1a7473767e0b3d6be712fa3a22929c"}, - {file = "levenshtein-0.27.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:712f562c5e64dd0398d3570fe99f8fbb88acec7cc431f101cb66c9d22d74c542"}, - {file = "levenshtein-0.27.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a6141ad65cab49aa4527a3342d76c30c48adb2393b6cdfeca65caae8d25cb4b8"}, - {file = "levenshtein-0.27.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:799b8d73cda3265331116f62932f553804eae16c706ceb35aaf16fc2a704791b"}, - {file = "levenshtein-0.27.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:ec99871d98e517e1cc4a15659c62d6ea63ee5a2d72c5ddbebd7bae8b9e2670c8"}, - {file = "levenshtein-0.27.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:8799164e1f83588dbdde07f728ea80796ea72196ea23484d78d891470241b222"}, - {file = "levenshtein-0.27.1-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:583943813898326516ab451a83f734c6f07488cda5c361676150d3e3e8b47927"}, - {file = "levenshtein-0.27.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:5bb22956af44bb4eade93546bf95be610c8939b9a9d4d28b2dfa94abf454fed7"}, - {file = "levenshtein-0.27.1-cp312-cp312-win32.whl", hash = "sha256:d9099ed1bcfa7ccc5540e8ad27b5dc6f23d16addcbe21fdd82af6440f4ed2b6d"}, - {file = "levenshtein-0.27.1-cp312-cp312-win_amd64.whl", hash = "sha256:7f071ecdb50aa6c15fd8ae5bcb67e9da46ba1df7bba7c6bf6803a54c7a41fd96"}, - {file = "levenshtein-0.27.1-cp312-cp312-win_arm64.whl", hash = "sha256:83b9033a984ccace7703f35b688f3907d55490182fd39b33a8e434d7b2e249e6"}, - {file = "levenshtein-0.27.1-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:909b7b6bce27a4ec90576c9a9bd9af5a41308dfecf364b410e80b58038277bbe"}, - {file = "levenshtein-0.27.1-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:d193a7f97b8c6a350e36ec58e41a627c06fa4157c3ce4b2b11d90cfc3c2ebb8f"}, - {file = "levenshtein-0.27.1-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:614be316e3c06118705fae1f717f9072d35108e5fd4e66a7dd0e80356135340b"}, - {file = "levenshtein-0.27.1-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:31fc0a5bb070722bdabb6f7e14955a294a4a968c68202d294699817f21545d22"}, - {file = "levenshtein-0.27.1-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9415aa5257227af543be65768a80c7a75e266c3c818468ce6914812f88f9c3df"}, - {file = "levenshtein-0.27.1-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:7987ef006a3cf56a4532bd4c90c2d3b7b4ca9ad3bf8ae1ee5713c4a3bdfda913"}, - {file = "levenshtein-0.27.1.tar.gz", hash = "sha256:3e18b73564cfc846eec94dd13fab6cb006b5d2e0cc56bad1fd7d5585881302e3"}, + {file = "levenshtein-0.27.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:245b6ffb6e1b0828cafbce35c500cb3265d0962c121d090669f177968c5a2980"}, + {file = "levenshtein-0.27.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:8f44c98fa23f489eb7b2ad87d5dd24b6a784434bb5edb73f6b0513309c949690"}, + {file = "levenshtein-0.27.3-cp311-cp311-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1f5f85a1fc96dfc147bba82b4c67d6346ea26c27ef77a6a9de689118e26dddbe"}, + {file = "levenshtein-0.27.3-cp311-cp311-manylinux_2_24_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:18ceddd38d0e990d2c1c9b72f3e191dace87e2f8f0446207ce9e9cd2bfdfc8a1"}, + {file = "levenshtein-0.27.3-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:222b81adca29ee4128183328c6e1b25a48c817d14a008ab49e74be9df963b293"}, + {file = "levenshtein-0.27.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:ee3769ab6e89c24f901e6b7004100630e86721464d7d0384860a322d7953d3a5"}, + {file = "levenshtein-0.27.3-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:03eba8fda9f3f2b4b0760263fa20b20a90ab00cbeeab4d0d9d899b4f77912b0a"}, + {file = "levenshtein-0.27.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:c870b19e2d5c7bc7f16213cc10312b82d873a4d46e1c6d51857a12ef39a76552"}, + {file = "levenshtein-0.27.3-cp311-cp311-win32.whl", hash = "sha256:1987622e9b8ba2ae47dc27469291da1f58462660fa34f4358e9d9c1830fb1355"}, + {file = "levenshtein-0.27.3-cp311-cp311-win_amd64.whl", hash = "sha256:a2b2aa81851e01bb09667b07e80c3fbf0f5a7c6ee9cd80caf43cce705e65832a"}, + {file = "levenshtein-0.27.3-cp311-cp311-win_arm64.whl", hash = "sha256:a084b335c54def1aef9a594b7163faa44dd00056323808bab783f43d8e4c1395"}, + {file = "levenshtein-0.27.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:2de7f095b0ca8e44de9de986ccba661cd0dec3511c751b499e76b60da46805e9"}, + {file = "levenshtein-0.27.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:d9b8b29e5d5145a3c958664c85151b1bb4b26e4ca764380b947e6a96a321217c"}, + {file = "levenshtein-0.27.3-cp312-cp312-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:fc975465a51b1c5889eadee1a583b81fba46372b4b22df28973e49e8ddb8f54a"}, + {file = "levenshtein-0.27.3-cp312-cp312-manylinux_2_24_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:57573ed885118554770979fdee584071b66103f6d50beddeabb54607a1213d81"}, + {file = "levenshtein-0.27.3-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:23aff800a6dd5d91bb3754a6092085aa7ad46b28e497682c155c74f681cfaa2d"}, + {file = "levenshtein-0.27.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:c08a952432b8ad9dccb145f812176db94c52cda732311ddc08d29fd3bf185b0a"}, + {file = "levenshtein-0.27.3-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:3bfcb2d78ab9cc06a1e75da8fcfb7a430fe513d66cfe54c07e50f32805e5e6db"}, + {file = "levenshtein-0.27.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ba7235f6dcb31a217247468295e2dd4c6c1d3ac81629dc5d355d93e1a5f4c185"}, + {file = "levenshtein-0.27.3-cp312-cp312-win32.whl", hash = "sha256:ea80d70f1d18c161a209be556b9094968627cbaae620e102459ef9c320a98cbb"}, + {file = "levenshtein-0.27.3-cp312-cp312-win_amd64.whl", hash = "sha256:fbaa1219d9b2d955339a37e684256a861e9274a3fe3a6ee1b8ea8724c3231ed9"}, + {file = "levenshtein-0.27.3-cp312-cp312-win_arm64.whl", hash = "sha256:2edbaa84f887ea1d9d8e4440af3fdda44769a7855d581c6248d7ee51518402a8"}, + {file = "levenshtein-0.27.3-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:d2d7d22b6117a143f0cf101fe18a3ca90bd949fc33716a42d6165b9768d4a78c"}, + {file = "levenshtein-0.27.3-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:a55e7a2f317abd28576636e1f840fd268261f447c496a8481a9997a5ce889c59"}, + {file = "levenshtein-0.27.3-pp311-pypy311_pp73-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:55fa5f11952c38186bd4719e936eb4595b3d519218634924928787c36840256c"}, + {file = "levenshtein-0.27.3-pp311-pypy311_pp73-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:559d3588e6766134d95f84f830cf40166360e1769d253f5f83474bff10a24341"}, + {file = "levenshtein-0.27.3-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:82d40da143c1b9e27adcd34a33dfcc4a0761aa717c5f618b9c6f57dec5d7a958"}, + {file = "levenshtein-0.27.3.tar.gz", hash = "sha256:1ac326b2c84215795163d8a5af471188918b8797b4953ec87aaba22c9c1f9fc0"}, +] + +[[package]] +name = "librt" +version = "0.7.3" +requires_python = ">=3.9" +summary = "Mypyc runtime library" +files = [ + {file = "librt-0.7.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:687403cced6a29590e6be6964463835315905221d797bc5c934a98750fe1a9af"}, + {file = "librt-0.7.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:24d70810f6e2ea853ff79338001533716b373cc0f63e2a0be5bc96129edb5fb5"}, + {file = "librt-0.7.3-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:bf8c7735fbfc0754111f00edda35cf9e98a8d478de6c47b04eaa9cef4300eaa7"}, + {file = "librt-0.7.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e32d43610dff472eab939f4d7fbdd240d1667794192690433672ae22d7af8445"}, + {file = "librt-0.7.3-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:adeaa886d607fb02563c1f625cf2ee58778a2567c0c109378da8f17ec3076ad7"}, + {file = "librt-0.7.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:572a24fc5958c61431da456a0ef1eeea6b4989d81eeb18b8e5f1f3077592200b"}, + {file = "librt-0.7.3-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:6488e69d408b492e08bfb68f20c4a899a354b4386a446ecd490baff8d0862720"}, + {file = "librt-0.7.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:ed028fc3d41adda916320712838aec289956c89b4f0a361ceadf83a53b4c047a"}, + {file = "librt-0.7.3-cp311-cp311-win32.whl", hash = "sha256:2cf9d73499486ce39eebbff5f42452518cc1f88d8b7ea4a711ab32962b176ee2"}, + {file = "librt-0.7.3-cp311-cp311-win_amd64.whl", hash = "sha256:35f1609e3484a649bb80431310ddbec81114cd86648f1d9482bc72a3b86ded2e"}, + {file = "librt-0.7.3-cp311-cp311-win_arm64.whl", hash = "sha256:550fdbfbf5bba6a2960b27376ca76d6aaa2bd4b1a06c4255edd8520c306fcfc0"}, + {file = "librt-0.7.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:0fa9ac2e49a6bee56e47573a6786cb635e128a7b12a0dc7851090037c0d397a3"}, + {file = "librt-0.7.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2e980cf1ed1a2420a6424e2ed884629cdead291686f1048810a817de07b5eb18"}, + {file = "librt-0.7.3-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:e094e445c37c57e9ec612847812c301840239d34ccc5d153a982fa9814478c60"}, + {file = "librt-0.7.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:aca73d70c3f553552ba9133d4a09e767dcfeee352d8d8d3eb3f77e38a3beb3ed"}, + {file = "librt-0.7.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c634a0a6db395fdaba0361aa78395597ee72c3aad651b9a307a3a7eaf5efd67e"}, + {file = "librt-0.7.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:a59a69deeb458c858b8fea6acf9e2acd5d755d76cd81a655256bc65c20dfff5b"}, + {file = "librt-0.7.3-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:d91e60ac44bbe3a77a67af4a4c13114cbe9f6d540337ce22f2c9eaf7454ca71f"}, + {file = "librt-0.7.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:703456146dc2bf430f7832fd1341adac5c893ec3c1430194fdcefba00012555c"}, + {file = "librt-0.7.3-cp312-cp312-win32.whl", hash = "sha256:b7c1239b64b70be7759554ad1a86288220bbb04d68518b527783c4ad3fb4f80b"}, + {file = "librt-0.7.3-cp312-cp312-win_amd64.whl", hash = "sha256:ef59c938f72bdbc6ab52dc50f81d0637fde0f194b02d636987cea2ab30f8f55a"}, + {file = "librt-0.7.3-cp312-cp312-win_arm64.whl", hash = "sha256:ff21c554304e8226bf80c3a7754be27c6c3549a9fec563a03c06ee8f494da8fc"}, + {file = "librt-0.7.3.tar.gz", hash = "sha256:3ec50cf65235ff5c02c5b747748d9222e564ad48597122a361269dd3aa808798"}, ] [[package]] name = "line-profiler" -version = "4.2.0" +version = "5.0.0" requires_python = ">=3.8" summary = "Line-by-line profiler" +dependencies = [ + "tomli; python_version < \"3.11\"", +] files = [ - {file = "line_profiler-4.2.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:402406f200401a496fb93e1788387bf2d87c921d7f8f7e5f88324ac9efb672ac"}, - {file = "line_profiler-4.2.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d9a0b5696f1ad42bb31e90706e5d57845833483d1d07f092b66b4799847a2f76"}, - {file = "line_profiler-4.2.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f2f950fa19f797a9ab55c8d7b33a7cdd95c396cf124c3adbc1cf93a1978d2767"}, - {file = "line_profiler-4.2.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7d09fd8f580716da5a0b9a7f544a306b468f38eee28ba2465c56e0aa5d7d1822"}, - {file = "line_profiler-4.2.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:628f585960c6538873a9760d112db20b76b6035d3eaad7711a8bd80fa909d7ea"}, - {file = "line_profiler-4.2.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:63ed929c7d41e230cc1c4838c25bbee165d7f2fa974ca28d730ea69e501fc44d"}, - {file = "line_profiler-4.2.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:6bda74fc206ba375396068526e9e7b5466a24c7e54cbd6ee1c98c1e0d1f0fd99"}, - {file = "line_profiler-4.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:eaf6eb827c202c07b8b8d82363bb039a6747fbf84ca04279495a91b7da3b773f"}, - {file = "line_profiler-4.2.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:82d29887f1226938a86db30ca3a125b1bde89913768a2a486fa14d0d3f8c0d91"}, - {file = "line_profiler-4.2.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:bf60706467203db0a872b93775a5e5902a02b11d79f8f75a8f8ef381b75789e1"}, - {file = "line_profiler-4.2.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:934fd964eed9bed87e3c01e8871ee6bdc54d10edf7bf14d20e72f7be03567ae3"}, - {file = "line_profiler-4.2.0-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d623e5b37fa48c7ad0c29b4353244346a5dcb1bf75e117e19400b8ffd3393d1b"}, - {file = "line_profiler-4.2.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:efcdbed9ba9003792d8bfd56c11bb3d4e29ad7e0d2f583e1c774de73bbf02933"}, - {file = "line_profiler-4.2.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:df0149c191a95f2dbc93155b2f9faaee563362d61e78b8986cdb67babe017cdc"}, - {file = "line_profiler-4.2.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:5e3a1ca491a8606ed674882b59354087f6e9ab6b94aa6d5fa5d565c6f2acc7a8"}, - {file = "line_profiler-4.2.0-cp312-cp312-win_amd64.whl", hash = "sha256:a85ff57d4ef9d899ca12d6b0883c3cab1786388b29d2fb5f30f909e70bb9a691"}, - {file = "line_profiler-4.2.0.tar.gz", hash = "sha256:09e10f25f876514380b3faee6de93fb0c228abba85820ba1a591ddb3eb451a96"}, + {file = "line_profiler-5.0.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:f32d536c056393b7ca703e459632edc327ff9e0fc320c7b0e0ed14b84d342b7f"}, + {file = "line_profiler-5.0.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a7da04ffc5a0a1f6653f43b13ad2e7ebf66f1d757174b7e660dfa0cbe74c4fc6"}, + {file = "line_profiler-5.0.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d2746f6b13c19ca4847efd500402d53a5ebb2fe31644ce8af74fbeac5ea4c54c"}, + {file = "line_profiler-5.0.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7b4290319a59730c04cbd03755472d10524130065a20a695dc10dd66ffd92172"}, + {file = "line_profiler-5.0.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7cd168a8af0032e8e3cb2fbb9ffc7694cdcecd47ec356ae863134df07becb3a2"}, + {file = "line_profiler-5.0.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:cbe7b095865d00dda0f53d7d4556c2b1b5d13f723173a85edb206a78779ee07a"}, + {file = "line_profiler-5.0.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:ff176045ea8a9e33900856db31b0b979357c337862ae4837140c98bd3161c3c7"}, + {file = "line_profiler-5.0.0-cp311-cp311-win_amd64.whl", hash = "sha256:474e0962d02123f1190a804073b308a67ef5f9c3b8379184483d5016844a00df"}, + {file = "line_profiler-5.0.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:729b18c0ac66b3368ade61203459219c202609f76b34190cbb2508b8e13998c8"}, + {file = "line_profiler-5.0.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:438ed24278c428119473b61a473c8fe468ace7c97c94b005cb001137bc624547"}, + {file = "line_profiler-5.0.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:920b0076dca726caadbf29f0bfcce0cbcb4d9ff034cd9445a7308f9d556b4b3a"}, + {file = "line_profiler-5.0.0-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:53326eaad2d807487dcd45d2e385feaaed81aaf72b9ecd4f53c1a225d658006f"}, + {file = "line_profiler-5.0.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0e3995a989cdea022f0ede5db19a6ab527f818c59ffcebf4e5f7a8be4eb8e880"}, + {file = "line_profiler-5.0.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:8bf57892a1d3a42273652506746ba9f620c505773ada804367c42e5b4146d6b6"}, + {file = "line_profiler-5.0.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:43672085f149f5fbf3f08bba072ad7014dd485282e8665827b26941ea97d2d76"}, + {file = "line_profiler-5.0.0-cp312-cp312-win_amd64.whl", hash = "sha256:446bd4f04e4bd9e979d68fdd916103df89a9d419e25bfb92b31af13c33808ee0"}, + {file = "line_profiler-5.0.0.tar.gz", hash = "sha256:a80f0afb05ba0d275d9dddc5ff97eab637471167ff3e66dcc7d135755059398c"}, +] + +[[package]] +name = "line-profiler" +version = "5.0.0" +extras = ["all"] +requires_python = ">=3.8" +summary = "Line-by-line profiler" +dependencies = [ + "Cython>=3.0.3", + "IPython>=8.12.2; python_version ~= \"3.8.0\"", + "IPython>=8.14.0; python_version < \"4.0.0\" and python_version >= \"3.9.0\"", + "cibuildwheel>=2.11.2; python_version < \"3.10\" and python_version >= \"3.9\"", + "cibuildwheel>=2.11.2; python_version < \"3.11\" and python_version >= \"3.10\"", + "cibuildwheel>=2.11.2; python_version < \"3.9\" and python_version >= \"3.8\"", + "cibuildwheel>=2.11.2; python_version ~= \"3.11\"", + "cmake>=3.21.2", + "coverage[toml]>=6.5.0; python_version < \"3.10\" and python_version >= \"3.9\"", + "coverage[toml]>=6.5.0; python_version < \"3.12\" and python_version >= \"3.10\"", + "coverage[toml]>=6.5.0; python_version < \"3.9\" and python_version >= \"3.8\"", + "coverage[toml]>=7.3.0; python_version ~= \"3.12\"", + "line-profiler==5.0.0", + "ninja>=1.10.2", + "pytest-cov>=3.0.0", + "pytest>=7.4.4; python_version < \"3.10\" and python_version >= \"3.9\"", + "pytest>=7.4.4; python_version < \"3.11\" and python_version >= \"3.10\"", + "pytest>=7.4.4; python_version < \"3.12\" and python_version >= \"3.11\"", + "pytest>=7.4.4; python_version < \"3.13\" and python_version >= \"3.12\"", + "pytest>=7.4.4; python_version < \"3.9\" and python_version >= \"3.8\"", + "pytest>=7.4.4; python_version ~= \"3.13\"", + "rich>=12.3.0", + "scikit-build>=0.11.1", + "setuptools>=68.2.2; python_version ~= \"3.8\"", + "tomli; python_version < \"3.11\"", + "ubelt>=1.3.4", + "xdoctest>=1.1.3", +] +files = [ + {file = "line_profiler-5.0.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:f32d536c056393b7ca703e459632edc327ff9e0fc320c7b0e0ed14b84d342b7f"}, + {file = "line_profiler-5.0.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a7da04ffc5a0a1f6653f43b13ad2e7ebf66f1d757174b7e660dfa0cbe74c4fc6"}, + {file = "line_profiler-5.0.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d2746f6b13c19ca4847efd500402d53a5ebb2fe31644ce8af74fbeac5ea4c54c"}, + {file = "line_profiler-5.0.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7b4290319a59730c04cbd03755472d10524130065a20a695dc10dd66ffd92172"}, + {file = "line_profiler-5.0.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7cd168a8af0032e8e3cb2fbb9ffc7694cdcecd47ec356ae863134df07becb3a2"}, + {file = "line_profiler-5.0.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:cbe7b095865d00dda0f53d7d4556c2b1b5d13f723173a85edb206a78779ee07a"}, + {file = "line_profiler-5.0.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:ff176045ea8a9e33900856db31b0b979357c337862ae4837140c98bd3161c3c7"}, + {file = "line_profiler-5.0.0-cp311-cp311-win_amd64.whl", hash = "sha256:474e0962d02123f1190a804073b308a67ef5f9c3b8379184483d5016844a00df"}, + {file = "line_profiler-5.0.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:729b18c0ac66b3368ade61203459219c202609f76b34190cbb2508b8e13998c8"}, + {file = "line_profiler-5.0.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:438ed24278c428119473b61a473c8fe468ace7c97c94b005cb001137bc624547"}, + {file = "line_profiler-5.0.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:920b0076dca726caadbf29f0bfcce0cbcb4d9ff034cd9445a7308f9d556b4b3a"}, + {file = "line_profiler-5.0.0-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:53326eaad2d807487dcd45d2e385feaaed81aaf72b9ecd4f53c1a225d658006f"}, + {file = "line_profiler-5.0.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0e3995a989cdea022f0ede5db19a6ab527f818c59ffcebf4e5f7a8be4eb8e880"}, + {file = "line_profiler-5.0.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:8bf57892a1d3a42273652506746ba9f620c505773ada804367c42e5b4146d6b6"}, + {file = "line_profiler-5.0.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:43672085f149f5fbf3f08bba072ad7014dd485282e8665827b26941ea97d2d76"}, + {file = "line_profiler-5.0.0-cp312-cp312-win_amd64.whl", hash = "sha256:446bd4f04e4bd9e979d68fdd916103df89a9d419e25bfb92b31af13c33808ee0"}, + {file = "line_profiler-5.0.0.tar.gz", hash = "sha256:a80f0afb05ba0d275d9dddc5ff97eab637471167ff3e66dcc7d135755059398c"}, ] [[package]] @@ -1599,21 +1870,19 @@ files = [ [[package]] name = "llvmlite" -version = "0.44.0" +version = "0.46.0" requires_python = ">=3.10" summary = "lightweight wrapper around basic LLVM functionality" files = [ - {file = "llvmlite-0.44.0-cp311-cp311-macosx_10_14_x86_64.whl", hash = "sha256:eed7d5f29136bda63b6d7804c279e2b72e08c952b7c5df61f45db408e0ee52f3"}, - {file = "llvmlite-0.44.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ace564d9fa44bb91eb6e6d8e7754977783c68e90a471ea7ce913bff30bd62427"}, - {file = "llvmlite-0.44.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c5d22c3bfc842668168a786af4205ec8e3ad29fb1bc03fd11fd48460d0df64c1"}, - {file = "llvmlite-0.44.0-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f01a394e9c9b7b1d4e63c327b096d10f6f0ed149ef53d38a09b3749dcf8c9610"}, - {file = "llvmlite-0.44.0-cp311-cp311-win_amd64.whl", hash = "sha256:d8489634d43c20cd0ad71330dde1d5bc7b9966937a263ff1ec1cebb90dc50955"}, - {file = "llvmlite-0.44.0-cp312-cp312-macosx_10_14_x86_64.whl", hash = "sha256:1d671a56acf725bf1b531d5ef76b86660a5ab8ef19bb6a46064a705c6ca80aad"}, - {file = "llvmlite-0.44.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:5f79a728e0435493611c9f405168682bb75ffd1fbe6fc360733b850c80a026db"}, - {file = "llvmlite-0.44.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c0143a5ef336da14deaa8ec26c5449ad5b6a2b564df82fcef4be040b9cacfea9"}, - {file = "llvmlite-0.44.0-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d752f89e31b66db6f8da06df8b39f9b91e78c5feea1bf9e8c1fba1d1c24c065d"}, - {file = "llvmlite-0.44.0-cp312-cp312-win_amd64.whl", hash = "sha256:eae7e2d4ca8f88f89d315b48c6b741dcb925d6a1042da694aa16ab3dd4cbd3a1"}, - {file = "llvmlite-0.44.0.tar.gz", hash = "sha256:07667d66a5d150abed9157ab6c0b9393c9356f229784a4385c02f99e94fc94d4"}, + {file = "llvmlite-0.46.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:82f3d39b16f19aa1a56d5fe625883a6ab600d5cc9ea8906cca70ce94cabba067"}, + {file = "llvmlite-0.46.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:a3df43900119803bbc52720e758c76f316a9a0f34612a886862dfe0a5591a17e"}, + {file = "llvmlite-0.46.0-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:de183fefc8022d21b0aa37fc3e90410bc3524aed8617f0ff76732fc6c3af5361"}, + {file = "llvmlite-0.46.0-cp311-cp311-win_amd64.whl", hash = "sha256:e8b10bc585c58bdffec9e0c309bb7d51be1f2f15e169a4b4d42f2389e431eb93"}, + {file = "llvmlite-0.46.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6b9588ad4c63b4f0175a3984b85494f0c927c6b001e3a246a3a7fb3920d9a137"}, + {file = "llvmlite-0.46.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:3535bd2bb6a2d7ae4012681ac228e5132cdb75fefb1bcb24e33f2f3e0c865ed4"}, + {file = "llvmlite-0.46.0-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4cbfd366e60ff87ea6cc62f50bc4cd800ebb13ed4c149466f50cf2163a473d1e"}, + {file = "llvmlite-0.46.0-cp312-cp312-win_amd64.whl", hash = "sha256:398b39db462c39563a97b912d4f2866cd37cba60537975a09679b28fbbc0fb38"}, + {file = "llvmlite-0.46.0.tar.gz", hash = "sha256:227c9fd6d09dce2783c18b754b7cd9d9b3b3515210c46acc2d3c5badd9870ceb"}, ] [[package]] @@ -1628,45 +1897,51 @@ files = [ [[package]] name = "lxml" -version = "5.4.0" -requires_python = ">=3.6" +version = "6.0.2" +requires_python = ">=3.8" summary = "Powerful and Pythonic XML processing library combining libxml2/libxslt with the ElementTree API." files = [ - {file = "lxml-5.4.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:98a3912194c079ef37e716ed228ae0dcb960992100461b704aea4e93af6b0bb9"}, - {file = "lxml-5.4.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:0ea0252b51d296a75f6118ed0d8696888e7403408ad42345d7dfd0d1e93309a7"}, - {file = "lxml-5.4.0-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b92b69441d1bd39f4940f9eadfa417a25862242ca2c396b406f9272ef09cdcaa"}, - {file = "lxml-5.4.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:20e16c08254b9b6466526bc1828d9370ee6c0d60a4b64836bc3ac2917d1e16df"}, - {file = "lxml-5.4.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7605c1c32c3d6e8c990dd28a0970a3cbbf1429d5b92279e37fda05fb0c92190e"}, - {file = "lxml-5.4.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ecf4c4b83f1ab3d5a7ace10bafcb6f11df6156857a3c418244cef41ca9fa3e44"}, - {file = "lxml-5.4.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0cef4feae82709eed352cd7e97ae062ef6ae9c7b5dbe3663f104cd2c0e8d94ba"}, - {file = "lxml-5.4.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:df53330a3bff250f10472ce96a9af28628ff1f4efc51ccba351a8820bca2a8ba"}, - {file = "lxml-5.4.0-cp311-cp311-manylinux_2_28_ppc64le.whl", hash = "sha256:aefe1a7cb852fa61150fcb21a8c8fcea7b58c4cb11fbe59c97a0a4b31cae3c8c"}, - {file = "lxml-5.4.0-cp311-cp311-manylinux_2_28_s390x.whl", hash = "sha256:ef5a7178fcc73b7d8c07229e89f8eb45b2908a9238eb90dcfc46571ccf0383b8"}, - {file = "lxml-5.4.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:d2ed1b3cb9ff1c10e6e8b00941bb2e5bb568b307bfc6b17dffbbe8be5eecba86"}, - {file = "lxml-5.4.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:72ac9762a9f8ce74c9eed4a4e74306f2f18613a6b71fa065495a67ac227b3056"}, - {file = "lxml-5.4.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:f5cb182f6396706dc6cc1896dd02b1c889d644c081b0cdec38747573db88a7d7"}, - {file = "lxml-5.4.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:3a3178b4873df8ef9457a4875703488eb1622632a9cee6d76464b60e90adbfcd"}, - {file = "lxml-5.4.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:e094ec83694b59d263802ed03a8384594fcce477ce484b0cbcd0008a211ca751"}, - {file = "lxml-5.4.0-cp311-cp311-win32.whl", hash = "sha256:4329422de653cdb2b72afa39b0aa04252fca9071550044904b2e7036d9d97fe4"}, - {file = "lxml-5.4.0-cp311-cp311-win_amd64.whl", hash = "sha256:fd3be6481ef54b8cfd0e1e953323b7aa9d9789b94842d0e5b142ef4bb7999539"}, - {file = "lxml-5.4.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:b5aff6f3e818e6bdbbb38e5967520f174b18f539c2b9de867b1e7fde6f8d95a4"}, - {file = "lxml-5.4.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:942a5d73f739ad7c452bf739a62a0f83e2578afd6b8e5406308731f4ce78b16d"}, - {file = "lxml-5.4.0-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:460508a4b07364d6abf53acaa0a90b6d370fafde5693ef37602566613a9b0779"}, - {file = "lxml-5.4.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:529024ab3a505fed78fe3cc5ddc079464e709f6c892733e3f5842007cec8ac6e"}, - {file = "lxml-5.4.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7ca56ebc2c474e8f3d5761debfd9283b8b18c76c4fc0967b74aeafba1f5647f9"}, - {file = "lxml-5.4.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a81e1196f0a5b4167a8dafe3a66aa67c4addac1b22dc47947abd5d5c7a3f24b5"}, - {file = "lxml-5.4.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:00b8686694423ddae324cf614e1b9659c2edb754de617703c3d29ff568448df5"}, - {file = "lxml-5.4.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:c5681160758d3f6ac5b4fea370495c48aac0989d6a0f01bb9a72ad8ef5ab75c4"}, - {file = "lxml-5.4.0-cp312-cp312-manylinux_2_28_ppc64le.whl", hash = "sha256:2dc191e60425ad70e75a68c9fd90ab284df64d9cd410ba8d2b641c0c45bc006e"}, - {file = "lxml-5.4.0-cp312-cp312-manylinux_2_28_s390x.whl", hash = "sha256:67f779374c6b9753ae0a0195a892a1c234ce8416e4448fe1e9f34746482070a7"}, - {file = "lxml-5.4.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:79d5bfa9c1b455336f52343130b2067164040604e41f6dc4d8313867ed540079"}, - {file = "lxml-5.4.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:3d3c30ba1c9b48c68489dc1829a6eede9873f52edca1dda900066542528d6b20"}, - {file = "lxml-5.4.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:1af80c6316ae68aded77e91cd9d80648f7dd40406cef73df841aa3c36f6907c8"}, - {file = "lxml-5.4.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:4d885698f5019abe0de3d352caf9466d5de2baded00a06ef3f1216c1a58ae78f"}, - {file = "lxml-5.4.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:aea53d51859b6c64e7c51d522c03cc2c48b9b5d6172126854cc7f01aa11f52bc"}, - {file = "lxml-5.4.0-cp312-cp312-win32.whl", hash = "sha256:d90b729fd2732df28130c064aac9bb8aff14ba20baa4aee7bd0795ff1187545f"}, - {file = "lxml-5.4.0-cp312-cp312-win_amd64.whl", hash = "sha256:1dc4ca99e89c335a7ed47d38964abcb36c5910790f9bd106f2a8fa2ee0b909d2"}, - {file = "lxml-5.4.0.tar.gz", hash = "sha256:d12832e1dbea4be280b22fd0ea7c9b87f0d8fc51ba06e92dc62d52f804f78ebd"}, + {file = "lxml-6.0.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:13e35cbc684aadf05d8711a5d1b5857c92e5e580efa9a0d2be197199c8def607"}, + {file = "lxml-6.0.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3b1675e096e17c6fe9c0e8c81434f5736c0739ff9ac6123c87c2d452f48fc938"}, + {file = "lxml-6.0.2-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:8ac6e5811ae2870953390452e3476694196f98d447573234592d30488147404d"}, + {file = "lxml-6.0.2-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:5aa0fc67ae19d7a64c3fe725dc9a1bb11f80e01f78289d05c6f62545affec438"}, + {file = "lxml-6.0.2-cp311-cp311-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:de496365750cc472b4e7902a485d3f152ecf57bd3ba03ddd5578ed8ceb4c5964"}, + {file = "lxml-6.0.2-cp311-cp311-manylinux_2_26_i686.manylinux_2_28_i686.whl", hash = "sha256:200069a593c5e40b8f6fc0d84d86d970ba43138c3e68619ffa234bc9bb806a4d"}, + {file = "lxml-6.0.2-cp311-cp311-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7d2de809c2ee3b888b59f995625385f74629707c9355e0ff856445cdcae682b7"}, + {file = "lxml-6.0.2-cp311-cp311-manylinux_2_31_armv7l.whl", hash = "sha256:b2c3da8d93cf5db60e8858c17684c47d01fee6405e554fb55018dd85fc23b178"}, + {file = "lxml-6.0.2-cp311-cp311-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:442de7530296ef5e188373a1ea5789a46ce90c4847e597856570439621d9c553"}, + {file = "lxml-6.0.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:2593c77efde7bfea7f6389f1ab249b15ed4aa5bc5cb5131faa3b843c429fbedb"}, + {file = "lxml-6.0.2-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:3e3cb08855967a20f553ff32d147e14329b3ae70ced6edc2f282b94afbc74b2a"}, + {file = "lxml-6.0.2-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:2ed6c667fcbb8c19c6791bbf40b7268ef8ddf5a96940ba9404b9f9a304832f6c"}, + {file = "lxml-6.0.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:b8f18914faec94132e5b91e69d76a5c1d7b0c73e2489ea8929c4aaa10b76bbf7"}, + {file = "lxml-6.0.2-cp311-cp311-win32.whl", hash = "sha256:6605c604e6daa9e0d7f0a2137bdc47a2e93b59c60a65466353e37f8272f47c46"}, + {file = "lxml-6.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:e5867f2651016a3afd8dd2c8238baa66f1e2802f44bc17e236f547ace6647078"}, + {file = "lxml-6.0.2-cp311-cp311-win_arm64.whl", hash = "sha256:4197fb2534ee05fd3e7afaab5d8bfd6c2e186f65ea7f9cd6a82809c887bd1285"}, + {file = "lxml-6.0.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:a59f5448ba2ceccd06995c95ea59a7674a10de0810f2ce90c9006f3cbc044456"}, + {file = "lxml-6.0.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:e8113639f3296706fbac34a30813929e29247718e88173ad849f57ca59754924"}, + {file = "lxml-6.0.2-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:a8bef9b9825fa8bc816a6e641bb67219489229ebc648be422af695f6e7a4fa7f"}, + {file = "lxml-6.0.2-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:65ea18d710fd14e0186c2f973dc60bb52039a275f82d3c44a0e42b43440ea534"}, + {file = "lxml-6.0.2-cp312-cp312-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c371aa98126a0d4c739ca93ceffa0fd7a5d732e3ac66a46e74339acd4d334564"}, + {file = "lxml-6.0.2-cp312-cp312-manylinux_2_26_i686.manylinux_2_28_i686.whl", hash = "sha256:700efd30c0fa1a3581d80a748157397559396090a51d306ea59a70020223d16f"}, + {file = "lxml-6.0.2-cp312-cp312-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c33e66d44fe60e72397b487ee92e01da0d09ba2d66df8eae42d77b6d06e5eba0"}, + {file = "lxml-6.0.2-cp312-cp312-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:90a345bbeaf9d0587a3aaffb7006aa39ccb6ff0e96a57286c0cb2fd1520ea192"}, + {file = "lxml-6.0.2-cp312-cp312-manylinux_2_31_armv7l.whl", hash = "sha256:064fdadaf7a21af3ed1dcaa106b854077fbeada827c18f72aec9346847cd65d0"}, + {file = "lxml-6.0.2-cp312-cp312-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:fbc74f42c3525ac4ffa4b89cbdd00057b6196bcefe8bce794abd42d33a018092"}, + {file = "lxml-6.0.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6ddff43f702905a4e32bc24f3f2e2edfe0f8fde3277d481bffb709a4cced7a1f"}, + {file = "lxml-6.0.2-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:6da5185951d72e6f5352166e3da7b0dc27aa70bd1090b0eb3f7f7212b53f1bb8"}, + {file = "lxml-6.0.2-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:57a86e1ebb4020a38d295c04fc79603c7899e0df71588043eb218722dabc087f"}, + {file = "lxml-6.0.2-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:2047d8234fe735ab77802ce5f2297e410ff40f5238aec569ad7c8e163d7b19a6"}, + {file = "lxml-6.0.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:6f91fd2b2ea15a6800c8e24418c0775a1694eefc011392da73bc6cef2623b322"}, + {file = "lxml-6.0.2-cp312-cp312-win32.whl", hash = "sha256:3ae2ce7d6fedfb3414a2b6c5e20b249c4c607f72cb8d2bb7cc9c6ec7c6f4e849"}, + {file = "lxml-6.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:72c87e5ee4e58a8354fb9c7c84cbf95a1c8236c127a5d1b7683f04bed8361e1f"}, + {file = "lxml-6.0.2-cp312-cp312-win_arm64.whl", hash = "sha256:61cb10eeb95570153e0c0e554f58df92ecf5109f75eacad4a95baa709e26c3d6"}, + {file = "lxml-6.0.2-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:1c06035eafa8404b5cf475bb37a9f6088b0aca288d4ccc9d69389750d5543700"}, + {file = "lxml-6.0.2-pp311-pypy311_pp73-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:c7d13103045de1bdd6fe5d61802565f1a3537d70cd3abf596aa0af62761921ee"}, + {file = "lxml-6.0.2-pp311-pypy311_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:0a3c150a95fbe5ac91de323aa756219ef9cf7fde5a3f00e2281e30f33fa5fa4f"}, + {file = "lxml-6.0.2-pp311-pypy311_pp73-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:60fa43be34f78bebb27812ed90f1925ec99560b0fa1decdb7d12b84d857d31e9"}, + {file = "lxml-6.0.2-pp311-pypy311_pp73-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:21c73b476d3cfe836be731225ec3421fa2f048d84f6df6a8e70433dff1376d5a"}, + {file = "lxml-6.0.2-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:27220da5be049e936c3aca06f174e8827ca6445a4353a1995584311487fc4e3e"}, + {file = "lxml-6.0.2.tar.gz", hash = "sha256:cd79f3367bd74b317dda655dc8fcfa304d9eb6e4fb06b7168c5cf27f96e0cd62"}, ] [[package]] @@ -1683,62 +1958,61 @@ files = [ [[package]] name = "markdown" -version = "3.8" -requires_python = ">=3.9" +version = "3.10" +requires_python = ">=3.10" summary = "Python implementation of John Gruber's Markdown." -dependencies = [ - "importlib-metadata>=4.4; python_version < \"3.10\"", -] files = [ - {file = "markdown-3.8-py3-none-any.whl", hash = "sha256:794a929b79c5af141ef5ab0f2f642d0f7b1872981250230e72682346f7cc90dc"}, - {file = "markdown-3.8.tar.gz", hash = "sha256:7df81e63f0df5c4b24b7d156eb81e4690595239b7d70937d0409f1b0de319c6f"}, + {file = "markdown-3.10-py3-none-any.whl", hash = "sha256:b5b99d6951e2e4948d939255596523444c0e677c669700b1d17aa4a8a464cb7c"}, + {file = "markdown-3.10.tar.gz", hash = "sha256:37062d4f2aa4b2b6b32aefb80faa300f82cc790cb949a35b8caede34f2b68c0e"}, ] [[package]] name = "markdown-it-py" -version = "3.0.0" -requires_python = ">=3.8" +version = "4.0.0" +requires_python = ">=3.10" summary = "Python port of markdown-it. Markdown parsing, done right!" dependencies = [ "mdurl~=0.1", ] files = [ - {file = "markdown-it-py-3.0.0.tar.gz", hash = "sha256:e3f60a94fa066dc52ec76661e37c851cb232d92f9886b15cb560aaada2df8feb"}, - {file = "markdown_it_py-3.0.0-py3-none-any.whl", hash = "sha256:355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1"}, + {file = "markdown_it_py-4.0.0-py3-none-any.whl", hash = "sha256:87327c59b172c5011896038353a81343b6754500a08cd7a4973bb48c6d578147"}, + {file = "markdown_it_py-4.0.0.tar.gz", hash = "sha256:cb0a2b4aa34f932c007117b194e945bd74e0ec24133ceb5bac59009cda1cb9f3"}, ] [[package]] name = "markupsafe" -version = "3.0.2" +version = "3.0.3" requires_python = ">=3.9" summary = "Safely add untrusted strings to HTML/XML markup." files = [ - {file = "MarkupSafe-3.0.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:9025b4018f3a1314059769c7bf15441064b2207cb3f065e6ea1e7359cb46db9d"}, - {file = "MarkupSafe-3.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:93335ca3812df2f366e80509ae119189886b0f3c2b81325d39efdb84a1e2ae93"}, - {file = "MarkupSafe-3.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2cb8438c3cbb25e220c2ab33bb226559e7afb3baec11c4f218ffa7308603c832"}, - {file = "MarkupSafe-3.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a123e330ef0853c6e822384873bef7507557d8e4a082961e1defa947aa59ba84"}, - {file = "MarkupSafe-3.0.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1e084f686b92e5b83186b07e8a17fc09e38fff551f3602b249881fec658d3eca"}, - {file = "MarkupSafe-3.0.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d8213e09c917a951de9d09ecee036d5c7d36cb6cb7dbaece4c71a60d79fb9798"}, - {file = "MarkupSafe-3.0.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:5b02fb34468b6aaa40dfc198d813a641e3a63b98c2b05a16b9f80b7ec314185e"}, - {file = "MarkupSafe-3.0.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:0bff5e0ae4ef2e1ae4fdf2dfd5b76c75e5c2fa4132d05fc1b0dabcd20c7e28c4"}, - {file = "MarkupSafe-3.0.2-cp311-cp311-win32.whl", hash = "sha256:6c89876f41da747c8d3677a2b540fb32ef5715f97b66eeb0c6b66f5e3ef6f59d"}, - {file = "MarkupSafe-3.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:70a87b411535ccad5ef2f1df5136506a10775d267e197e4cf531ced10537bd6b"}, - {file = "MarkupSafe-3.0.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:9778bd8ab0a994ebf6f84c2b949e65736d5575320a17ae8984a77fab08db94cf"}, - {file = "MarkupSafe-3.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:846ade7b71e3536c4e56b386c2a47adf5741d2d8b94ec9dc3e92e5e1ee1e2225"}, - {file = "MarkupSafe-3.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1c99d261bd2d5f6b59325c92c73df481e05e57f19837bdca8413b9eac4bd8028"}, - {file = "MarkupSafe-3.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e17c96c14e19278594aa4841ec148115f9c7615a47382ecb6b82bd8fea3ab0c8"}, - {file = "MarkupSafe-3.0.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:88416bd1e65dcea10bc7569faacb2c20ce071dd1f87539ca2ab364bf6231393c"}, - {file = "MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:2181e67807fc2fa785d0592dc2d6206c019b9502410671cc905d132a92866557"}, - {file = "MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:52305740fe773d09cffb16f8ed0427942901f00adedac82ec8b67752f58a1b22"}, - {file = "MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ad10d3ded218f1039f11a75f8091880239651b52e9bb592ca27de44eed242a48"}, - {file = "MarkupSafe-3.0.2-cp312-cp312-win32.whl", hash = "sha256:0f4ca02bea9a23221c0182836703cbf8930c5e9454bacce27e767509fa286a30"}, - {file = "MarkupSafe-3.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:8e06879fc22a25ca47312fbe7c8264eb0b662f6db27cb2d3bbbc74b1df4b9b87"}, - {file = "markupsafe-3.0.2.tar.gz", hash = "sha256:ee55d3edf80167e48ea11a923c7386f4669df67d7994554387f84e7d8b0a2bf0"}, + {file = "markupsafe-3.0.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:1cc7ea17a6824959616c525620e387f6dd30fec8cb44f649e31712db02123dad"}, + {file = "markupsafe-3.0.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4bd4cd07944443f5a265608cc6aab442e4f74dff8088b0dfc8238647b8f6ae9a"}, + {file = "markupsafe-3.0.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6b5420a1d9450023228968e7e6a9ce57f65d148ab56d2313fcd589eee96a7a50"}, + {file = "markupsafe-3.0.3-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0bf2a864d67e76e5c9a34dc26ec616a66b9888e25e7b9460e1c76d3293bd9dbf"}, + {file = "markupsafe-3.0.3-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:bc51efed119bc9cfdf792cdeaa4d67e8f6fcccab66ed4bfdd6bde3e59bfcbb2f"}, + {file = "markupsafe-3.0.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:068f375c472b3e7acbe2d5318dea141359e6900156b5b2ba06a30b169086b91a"}, + {file = "markupsafe-3.0.3-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:7be7b61bb172e1ed687f1754f8e7484f1c8019780f6f6b0786e76bb01c2ae115"}, + {file = "markupsafe-3.0.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f9e130248f4462aaa8e2552d547f36ddadbeaa573879158d721bbd33dfe4743a"}, + {file = "markupsafe-3.0.3-cp311-cp311-win32.whl", hash = "sha256:0db14f5dafddbb6d9208827849fad01f1a2609380add406671a26386cdf15a19"}, + {file = "markupsafe-3.0.3-cp311-cp311-win_amd64.whl", hash = "sha256:de8a88e63464af587c950061a5e6a67d3632e36df62b986892331d4620a35c01"}, + {file = "markupsafe-3.0.3-cp311-cp311-win_arm64.whl", hash = "sha256:3b562dd9e9ea93f13d53989d23a7e775fdfd1066c33494ff43f5418bc8c58a5c"}, + {file = "markupsafe-3.0.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:d53197da72cc091b024dd97249dfc7794d6a56530370992a5e1a08983ad9230e"}, + {file = "markupsafe-3.0.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1872df69a4de6aead3491198eaf13810b565bdbeec3ae2dc8780f14458ec73ce"}, + {file = "markupsafe-3.0.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3a7e8ae81ae39e62a41ec302f972ba6ae23a5c5396c8e60113e9066ef893da0d"}, + {file = "markupsafe-3.0.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d6dd0be5b5b189d31db7cda48b91d7e0a9795f31430b7f271219ab30f1d3ac9d"}, + {file = "markupsafe-3.0.3-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:94c6f0bb423f739146aec64595853541634bde58b2135f27f61c1ffd1cd4d16a"}, + {file = "markupsafe-3.0.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:be8813b57049a7dc738189df53d69395eba14fb99345e0a5994914a3864c8a4b"}, + {file = "markupsafe-3.0.3-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:83891d0e9fb81a825d9a6d61e3f07550ca70a076484292a70fde82c4b807286f"}, + {file = "markupsafe-3.0.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:77f0643abe7495da77fb436f50f8dab76dbc6e5fd25d39589a0f1fe6548bfa2b"}, + {file = "markupsafe-3.0.3-cp312-cp312-win32.whl", hash = "sha256:d88b440e37a16e651bda4c7c2b930eb586fd15ca7406cb39e211fcff3bf3017d"}, + {file = "markupsafe-3.0.3-cp312-cp312-win_amd64.whl", hash = "sha256:26a5784ded40c9e318cfc2bdb30fe164bdb8665ded9cd64d500a34fb42067b1c"}, + {file = "markupsafe-3.0.3-cp312-cp312-win_arm64.whl", hash = "sha256:35add3b638a5d900e807944a078b51922212fb3dedb01633a8defc4b01a3c85f"}, + {file = "markupsafe-3.0.3.tar.gz", hash = "sha256:722695808f4b6457b320fdc131280796bdceb04ab50fe1795cd540799ebe1698"}, ] [[package]] name = "matplotlib" -version = "3.10.3" +version = "3.10.8" requires_python = ">=3.10" summary = "Python plotting package" dependencies = [ @@ -1749,36 +2023,41 @@ dependencies = [ "numpy>=1.23", "packaging>=20.0", "pillow>=8", - "pyparsing>=2.3.1", + "pyparsing>=3", "python-dateutil>=2.7", ] files = [ - {file = "matplotlib-3.10.3-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:0ef061f74cd488586f552d0c336b2f078d43bc00dc473d2c3e7bfee2272f3fa8"}, - {file = "matplotlib-3.10.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d96985d14dc5f4a736bbea4b9de9afaa735f8a0fc2ca75be2fa9e96b2097369d"}, - {file = "matplotlib-3.10.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7c5f0283da91e9522bdba4d6583ed9d5521566f63729ffb68334f86d0bb98049"}, - {file = "matplotlib-3.10.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fdfa07c0ec58035242bc8b2c8aae37037c9a886370eef6850703d7583e19964b"}, - {file = "matplotlib-3.10.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:c0b9849a17bce080a16ebcb80a7b714b5677d0ec32161a2cc0a8e5a6030ae220"}, - {file = "matplotlib-3.10.3-cp311-cp311-win_amd64.whl", hash = "sha256:eef6ed6c03717083bc6d69c2d7ee8624205c29a8e6ea5a31cd3492ecdbaee1e1"}, - {file = "matplotlib-3.10.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:0ab1affc11d1f495ab9e6362b8174a25afc19c081ba5b0775ef00533a4236eea"}, - {file = "matplotlib-3.10.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2a818d8bdcafa7ed2eed74487fdb071c09c1ae24152d403952adad11fa3c65b4"}, - {file = "matplotlib-3.10.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:748ebc3470c253e770b17d8b0557f0aa85cf8c63fd52f1a61af5b27ec0b7ffee"}, - {file = "matplotlib-3.10.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ed70453fd99733293ace1aec568255bc51c6361cb0da94fa5ebf0649fdb2150a"}, - {file = "matplotlib-3.10.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:dbed9917b44070e55640bd13419de83b4c918e52d97561544814ba463811cbc7"}, - {file = "matplotlib-3.10.3-cp312-cp312-win_amd64.whl", hash = "sha256:cf37d8c6ef1a48829443e8ba5227b44236d7fcaf7647caa3178a4ff9f7a5be05"}, - {file = "matplotlib-3.10.3.tar.gz", hash = "sha256:2f82d2c5bb7ae93aaaa4cd42aca65d76ce6376f83304fa3a630b569aca274df0"}, + {file = "matplotlib-3.10.8-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:6be43b667360fef5c754dda5d25a32e6307a03c204f3c0fc5468b78fa87b4160"}, + {file = "matplotlib-3.10.8-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a2b336e2d91a3d7006864e0990c83b216fcdca64b5a6484912902cef87313d78"}, + {file = "matplotlib-3.10.8-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:efb30e3baaea72ce5928e32bab719ab4770099079d66726a62b11b1ef7273be4"}, + {file = "matplotlib-3.10.8-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d56a1efd5bfd61486c8bc968fa18734464556f0fb8e51690f4ac25d85cbbbbc2"}, + {file = "matplotlib-3.10.8-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:238b7ce5717600615c895050239ec955d91f321c209dd110db988500558e70d6"}, + {file = "matplotlib-3.10.8-cp311-cp311-win_amd64.whl", hash = "sha256:18821ace09c763ec93aef5eeff087ee493a24051936d7b9ebcad9662f66501f9"}, + {file = "matplotlib-3.10.8-cp311-cp311-win_arm64.whl", hash = "sha256:bab485bcf8b1c7d2060b4fcb6fc368a9e6f4cd754c9c2fea281f4be21df394a2"}, + {file = "matplotlib-3.10.8-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:64fcc24778ca0404ce0cb7b6b77ae1f4c7231cdd60e6778f999ee05cbd581b9a"}, + {file = "matplotlib-3.10.8-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:b9a5ca4ac220a0cdd1ba6bcba3608547117d30468fefce49bb26f55c1a3d5c58"}, + {file = "matplotlib-3.10.8-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:3ab4aabc72de4ff77b3ec33a6d78a68227bf1123465887f9905ba79184a1cc04"}, + {file = "matplotlib-3.10.8-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:24d50994d8c5816ddc35411e50a86ab05f575e2530c02752e02538122613371f"}, + {file = "matplotlib-3.10.8-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:99eefd13c0dc3b3c1b4d561c1169e65fe47aab7b8158754d7c084088e2329466"}, + {file = "matplotlib-3.10.8-cp312-cp312-win_amd64.whl", hash = "sha256:dd80ecb295460a5d9d260df63c43f4afbdd832d725a531f008dad1664f458adf"}, + {file = "matplotlib-3.10.8-cp312-cp312-win_arm64.whl", hash = "sha256:3c624e43ed56313651bc18a47f838b60d7b8032ed348911c54906b130b20071b"}, + {file = "matplotlib-3.10.8-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:6da7c2ce169267d0d066adcf63758f0604aa6c3eebf67458930f9d9b79ad1db1"}, + {file = "matplotlib-3.10.8-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:9153c3292705be9f9c64498a8872118540c3f4123d1a1c840172edf262c8be4a"}, + {file = "matplotlib-3.10.8-pp311-pypy311_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:1ae029229a57cd1e8fe542485f27e7ca7b23aa9e8944ddb4985d0bc444f1eca2"}, + {file = "matplotlib-3.10.8.tar.gz", hash = "sha256:2299372c19d56bcd35cf05a2738308758d32b9eaed2371898d8f5bd33f084aa3"}, ] [[package]] name = "matplotlib-inline" -version = "0.1.7" -requires_python = ">=3.8" +version = "0.2.1" +requires_python = ">=3.9" summary = "Inline Matplotlib backend for Jupyter" dependencies = [ "traitlets", ] files = [ - {file = "matplotlib_inline-0.1.7-py3-none-any.whl", hash = "sha256:df192d39a4ff8f21b1895d72e6a13f5fcc5099f00fa84384e0ea28c2cc0653ca"}, - {file = "matplotlib_inline-0.1.7.tar.gz", hash = "sha256:8423b23ec666be3d16e16b60bdd8ac4e86e840ebd1dd11a30b9f117f2fa0ab90"}, + {file = "matplotlib_inline-0.2.1-py3-none-any.whl", hash = "sha256:d56ce5156ba6085e00a9d54fead6ed29a9c47e215cd1bba2e976ef39f5710a76"}, + {file = "matplotlib_inline-0.2.1.tar.gz", hash = "sha256:e1ee949c340d771fc39e241ea75683deb94762c8fa5f2927ec57c83c4dffa9fe"}, ] [[package]] @@ -1793,15 +2072,15 @@ files = [ [[package]] name = "mdit-py-plugins" -version = "0.4.2" -requires_python = ">=3.8" +version = "0.5.0" +requires_python = ">=3.10" summary = "Collection of plugins for markdown-it-py" dependencies = [ - "markdown-it-py<4.0.0,>=1.0.0", + "markdown-it-py<5.0.0,>=2.0.0", ] files = [ - {file = "mdit_py_plugins-0.4.2-py3-none-any.whl", hash = "sha256:0c673c3f889399a33b95e88d2f0d111b4447bdfea7f237dab2d488f459835636"}, - {file = "mdit_py_plugins-0.4.2.tar.gz", hash = "sha256:5f2cd1fdb606ddf152d37ec30e46101a60512bc0e5fa1a7002c36647b09e26b5"}, + {file = "mdit_py_plugins-0.5.0-py3-none-any.whl", hash = "sha256:07a08422fc1936a5d26d146759e9155ea466e842f5ab2f7d2266dd084c8dab1f"}, + {file = "mdit_py_plugins-0.5.0.tar.gz", hash = "sha256:f4918cb50119f50446560513a8e311d574ff6aaed72606ddae6d35716fe809c6"}, ] [[package]] @@ -1816,120 +2095,120 @@ files = [ [[package]] name = "mistune" -version = "3.1.3" +version = "3.1.4" requires_python = ">=3.8" summary = "A sane and fast Markdown parser with useful plugins and renderers" dependencies = [ "typing-extensions; python_version < \"3.11\"", ] files = [ - {file = "mistune-3.1.3-py3-none-any.whl", hash = "sha256:1a32314113cff28aa6432e99e522677c8587fd83e3d51c29b82a52409c842bd9"}, - {file = "mistune-3.1.3.tar.gz", hash = "sha256:a7035c21782b2becb6be62f8f25d3df81ccb4d6fa477a6525b15af06539f02a0"}, + {file = "mistune-3.1.4-py3-none-any.whl", hash = "sha256:93691da911e5d9d2e23bc54472892aff676df27a75274962ff9edc210364266d"}, + {file = "mistune-3.1.4.tar.gz", hash = "sha256:b5a7f801d389f724ec702840c11d8fc48f2b33519102fc7ee739e8177b672164"}, ] [[package]] name = "msgpack" -version = "1.1.0" -requires_python = ">=3.8" +version = "1.1.2" +requires_python = ">=3.9" summary = "MessagePack serializer" files = [ - {file = "msgpack-1.1.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:3d364a55082fb2a7416f6c63ae383fbd903adb5a6cf78c5b96cc6316dc1cedc7"}, - {file = "msgpack-1.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:79ec007767b9b56860e0372085f8504db5d06bd6a327a335449508bbee9648fa"}, - {file = "msgpack-1.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:6ad622bf7756d5a497d5b6836e7fc3752e2dd6f4c648e24b1803f6048596f701"}, - {file = "msgpack-1.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8e59bca908d9ca0de3dc8684f21ebf9a690fe47b6be93236eb40b99af28b6ea6"}, - {file = "msgpack-1.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5e1da8f11a3dd397f0a32c76165cf0c4eb95b31013a94f6ecc0b280c05c91b59"}, - {file = "msgpack-1.1.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:452aff037287acb1d70a804ffd022b21fa2bb7c46bee884dbc864cc9024128a0"}, - {file = "msgpack-1.1.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8da4bf6d54ceed70e8861f833f83ce0814a2b72102e890cbdfe4b34764cdd66e"}, - {file = "msgpack-1.1.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:41c991beebf175faf352fb940bf2af9ad1fb77fd25f38d9142053914947cdbf6"}, - {file = "msgpack-1.1.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:a52a1f3a5af7ba1c9ace055b659189f6c669cf3657095b50f9602af3a3ba0fe5"}, - {file = "msgpack-1.1.0-cp311-cp311-win32.whl", hash = "sha256:58638690ebd0a06427c5fe1a227bb6b8b9fdc2bd07701bec13c2335c82131a88"}, - {file = "msgpack-1.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:fd2906780f25c8ed5d7b323379f6138524ba793428db5d0e9d226d3fa6aa1788"}, - {file = "msgpack-1.1.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:d46cf9e3705ea9485687aa4001a76e44748b609d260af21c4ceea7f2212a501d"}, - {file = "msgpack-1.1.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:5dbad74103df937e1325cc4bfeaf57713be0b4f15e1c2da43ccdd836393e2ea2"}, - {file = "msgpack-1.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:58dfc47f8b102da61e8949708b3eafc3504509a5728f8b4ddef84bd9e16ad420"}, - {file = "msgpack-1.1.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4676e5be1b472909b2ee6356ff425ebedf5142427842aa06b4dfd5117d1ca8a2"}, - {file = "msgpack-1.1.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:17fb65dd0bec285907f68b15734a993ad3fc94332b5bb21b0435846228de1f39"}, - {file = "msgpack-1.1.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a51abd48c6d8ac89e0cfd4fe177c61481aca2d5e7ba42044fd218cfd8ea9899f"}, - {file = "msgpack-1.1.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:2137773500afa5494a61b1208619e3871f75f27b03bcfca7b3a7023284140247"}, - {file = "msgpack-1.1.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:398b713459fea610861c8a7b62a6fec1882759f308ae0795b5413ff6a160cf3c"}, - {file = "msgpack-1.1.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:06f5fd2f6bb2a7914922d935d3b8bb4a7fff3a9a91cfce6d06c13bc42bec975b"}, - {file = "msgpack-1.1.0-cp312-cp312-win32.whl", hash = "sha256:ad33e8400e4ec17ba782f7b9cf868977d867ed784a1f5f2ab46e7ba53b6e1e1b"}, - {file = "msgpack-1.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:115a7af8ee9e8cddc10f87636767857e7e3717b7a2e97379dc2054712693e90f"}, - {file = "msgpack-1.1.0.tar.gz", hash = "sha256:dd432ccc2c72b914e4cb77afce64aab761c1137cc698be3984eee260bcb2896e"}, + {file = "msgpack-1.1.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2e86a607e558d22985d856948c12a3fa7b42efad264dca8a3ebbcfa2735d786c"}, + {file = "msgpack-1.1.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:283ae72fc89da59aa004ba147e8fc2f766647b1251500182fac0350d8af299c0"}, + {file = "msgpack-1.1.2-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:61c8aa3bd513d87c72ed0b37b53dd5c5a0f58f2ff9f26e1555d3bd7948fb7296"}, + {file = "msgpack-1.1.2-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:454e29e186285d2ebe65be34629fa0e8605202c60fbc7c4c650ccd41870896ef"}, + {file = "msgpack-1.1.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:7bc8813f88417599564fafa59fd6f95be417179f76b40325b500b3c98409757c"}, + {file = "msgpack-1.1.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:bafca952dc13907bdfdedfc6a5f579bf4f292bdd506fadb38389afa3ac5b208e"}, + {file = "msgpack-1.1.2-cp311-cp311-win32.whl", hash = "sha256:602b6740e95ffc55bfb078172d279de3773d7b7db1f703b2f1323566b878b90e"}, + {file = "msgpack-1.1.2-cp311-cp311-win_amd64.whl", hash = "sha256:d198d275222dc54244bf3327eb8cbe00307d220241d9cec4d306d49a44e85f68"}, + {file = "msgpack-1.1.2-cp311-cp311-win_arm64.whl", hash = "sha256:86f8136dfa5c116365a8a651a7d7484b65b13339731dd6faebb9a0242151c406"}, + {file = "msgpack-1.1.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:70a0dff9d1f8da25179ffcf880e10cf1aad55fdb63cd59c9a49a1b82290062aa"}, + {file = "msgpack-1.1.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:446abdd8b94b55c800ac34b102dffd2f6aa0ce643c55dfc017ad89347db3dbdb"}, + {file = "msgpack-1.1.2-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c63eea553c69ab05b6747901b97d620bb2a690633c77f23feb0c6a947a8a7b8f"}, + {file = "msgpack-1.1.2-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:372839311ccf6bdaf39b00b61288e0557916c3729529b301c52c2d88842add42"}, + {file = "msgpack-1.1.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:2929af52106ca73fcb28576218476ffbb531a036c2adbcf54a3664de124303e9"}, + {file = "msgpack-1.1.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:be52a8fc79e45b0364210eef5234a7cf8d330836d0a64dfbb878efa903d84620"}, + {file = "msgpack-1.1.2-cp312-cp312-win32.whl", hash = "sha256:1fff3d825d7859ac888b0fbda39a42d59193543920eda9d9bea44d958a878029"}, + {file = "msgpack-1.1.2-cp312-cp312-win_amd64.whl", hash = "sha256:1de460f0403172cff81169a30b9a92b260cb809c4cb7e2fc79ae8d0510c78b6b"}, + {file = "msgpack-1.1.2-cp312-cp312-win_arm64.whl", hash = "sha256:be5980f3ee0e6bd44f3a9e9dea01054f175b50c3e6cdb692bc9424c0bbb8bf69"}, + {file = "msgpack-1.1.2.tar.gz", hash = "sha256:3b60763c1373dd60f398488069bcdc703cd08a711477b5d480eecc9f9626f47e"}, ] [[package]] name = "multidict" -version = "6.4.4" +version = "6.7.0" requires_python = ">=3.9" summary = "multidict implementation" dependencies = [ "typing-extensions>=4.1.0; python_version < \"3.11\"", ] files = [ - {file = "multidict-6.4.4-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:4f5f29794ac0e73d2a06ac03fd18870adc0135a9d384f4a306a951188ed02f95"}, - {file = "multidict-6.4.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c04157266344158ebd57b7120d9b0b35812285d26d0e78193e17ef57bfe2979a"}, - {file = "multidict-6.4.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:bb61ffd3ab8310d93427e460f565322c44ef12769f51f77277b4abad7b6f7223"}, - {file = "multidict-6.4.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5e0ba18a9afd495f17c351d08ebbc4284e9c9f7971d715f196b79636a4d0de44"}, - {file = "multidict-6.4.4-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:9faf1b1dcaadf9f900d23a0e6d6c8eadd6a95795a0e57fcca73acce0eb912065"}, - {file = "multidict-6.4.4-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a4d1cb1327c6082c4fce4e2a438483390964c02213bc6b8d782cf782c9b1471f"}, - {file = "multidict-6.4.4-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:941f1bec2f5dbd51feeb40aea654c2747f811ab01bdd3422a48a4e4576b7d76a"}, - {file = "multidict-6.4.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e5f8a146184da7ea12910a4cec51ef85e44f6268467fb489c3caf0cd512f29c2"}, - {file = "multidict-6.4.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:232b7237e57ec3c09be97206bfb83a0aa1c5d7d377faa019c68a210fa35831f1"}, - {file = "multidict-6.4.4-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:55ae0721c1513e5e3210bca4fc98456b980b0c2c016679d3d723119b6b202c42"}, - {file = "multidict-6.4.4-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:51d662c072579f63137919d7bb8fc250655ce79f00c82ecf11cab678f335062e"}, - {file = "multidict-6.4.4-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:0e05c39962baa0bb19a6b210e9b1422c35c093b651d64246b6c2e1a7e242d9fd"}, - {file = "multidict-6.4.4-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:d5b1cc3ab8c31d9ebf0faa6e3540fb91257590da330ffe6d2393d4208e638925"}, - {file = "multidict-6.4.4-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:93ec84488a384cd7b8a29c2c7f467137d8a73f6fe38bb810ecf29d1ade011a7c"}, - {file = "multidict-6.4.4-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:b308402608493638763abc95f9dc0030bbd6ac6aff784512e8ac3da73a88af08"}, - {file = "multidict-6.4.4-cp311-cp311-win32.whl", hash = "sha256:343892a27d1a04d6ae455ecece12904d242d299ada01633d94c4f431d68a8c49"}, - {file = "multidict-6.4.4-cp311-cp311-win_amd64.whl", hash = "sha256:73484a94f55359780c0f458bbd3c39cb9cf9c182552177d2136e828269dee529"}, - {file = "multidict-6.4.4-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:dc388f75a1c00000824bf28b7633e40854f4127ede80512b44c3cfeeea1839a2"}, - {file = "multidict-6.4.4-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:98af87593a666f739d9dba5d0ae86e01b0e1a9cfcd2e30d2d361fbbbd1a9162d"}, - {file = "multidict-6.4.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:aff4cafea2d120327d55eadd6b7f1136a8e5a0ecf6fb3b6863e8aca32cd8e50a"}, - {file = "multidict-6.4.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:169c4ba7858176b797fe551d6e99040c531c775d2d57b31bcf4de6d7a669847f"}, - {file = "multidict-6.4.4-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:b9eb4c59c54421a32b3273d4239865cb14ead53a606db066d7130ac80cc8ec93"}, - {file = "multidict-6.4.4-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7cf3bd54c56aa16fdb40028d545eaa8d051402b61533c21e84046e05513d5780"}, - {file = "multidict-6.4.4-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f682c42003c7264134bfe886376299db4cc0c6cd06a3295b41b347044bcb5482"}, - {file = "multidict-6.4.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a920f9cf2abdf6e493c519492d892c362007f113c94da4c239ae88429835bad1"}, - {file = "multidict-6.4.4-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:530d86827a2df6504526106b4c104ba19044594f8722d3e87714e847c74a0275"}, - {file = "multidict-6.4.4-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:ecde56ea2439b96ed8a8d826b50c57364612ddac0438c39e473fafad7ae1c23b"}, - {file = "multidict-6.4.4-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:dc8c9736d8574b560634775ac0def6bdc1661fc63fa27ffdfc7264c565bcb4f2"}, - {file = "multidict-6.4.4-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:7f3d3b3c34867579ea47cbd6c1f2ce23fbfd20a273b6f9e3177e256584f1eacc"}, - {file = "multidict-6.4.4-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:87a728af265e08f96b6318ebe3c0f68b9335131f461efab2fc64cc84a44aa6ed"}, - {file = "multidict-6.4.4-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:9f193eeda1857f8e8d3079a4abd258f42ef4a4bc87388452ed1e1c4d2b0c8740"}, - {file = "multidict-6.4.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:be06e73c06415199200e9a2324a11252a3d62030319919cde5e6950ffeccf72e"}, - {file = "multidict-6.4.4-cp312-cp312-win32.whl", hash = "sha256:622f26ea6a7e19b7c48dd9228071f571b2fbbd57a8cd71c061e848f281550e6b"}, - {file = "multidict-6.4.4-cp312-cp312-win_amd64.whl", hash = "sha256:5e2bcda30d5009996ff439e02a9f2b5c3d64a20151d34898c000a6281faa3781"}, - {file = "multidict-6.4.4-py3-none-any.whl", hash = "sha256:bd4557071b561a8b3b6075c3ce93cf9bfb6182cb241805c3d66ced3b75eff4ac"}, - {file = "multidict-6.4.4.tar.gz", hash = "sha256:69ee9e6ba214b5245031b76233dd95408a0fd57fdb019ddcc1ead4790932a8e8"}, + {file = "multidict-6.7.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:4d409aa42a94c0b3fa617708ef5276dfe81012ba6753a0370fcc9d0195d0a1fc"}, + {file = "multidict-6.7.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:14c9e076eede3b54c636f8ce1c9c252b5f057c62131211f0ceeec273810c9721"}, + {file = "multidict-6.7.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4c09703000a9d0fa3c3404b27041e574cc7f4df4c6563873246d0e11812a94b6"}, + {file = "multidict-6.7.0-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:a265acbb7bb33a3a2d626afbe756371dce0279e7b17f4f4eda406459c2b5ff1c"}, + {file = "multidict-6.7.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:51cb455de290ae462593e5b1cb1118c5c22ea7f0d3620d9940bf695cea5a4bd7"}, + {file = "multidict-6.7.0-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:db99677b4457c7a5c5a949353e125ba72d62b35f74e26da141530fbb012218a7"}, + {file = "multidict-6.7.0-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f470f68adc395e0183b92a2f4689264d1ea4b40504a24d9882c27375e6662bb9"}, + {file = "multidict-6.7.0-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:0db4956f82723cc1c270de9c6e799b4c341d327762ec78ef82bb962f79cc07d8"}, + {file = "multidict-6.7.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3e56d780c238f9e1ae66a22d2adf8d16f485381878250db8d496623cd38b22bd"}, + {file = "multidict-6.7.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:9d14baca2ee12c1a64740d4531356ba50b82543017f3ad6de0deb943c5979abb"}, + {file = "multidict-6.7.0-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:295a92a76188917c7f99cda95858c822f9e4aae5824246bba9b6b44004ddd0a6"}, + {file = "multidict-6.7.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:39f1719f57adbb767ef592a50ae5ebb794220d1188f9ca93de471336401c34d2"}, + {file = "multidict-6.7.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:0a13fb8e748dfc94749f622de065dd5c1def7e0d2216dba72b1d8069a389c6ff"}, + {file = "multidict-6.7.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:e3aa16de190d29a0ea1b48253c57d99a68492c8dd8948638073ab9e74dc9410b"}, + {file = "multidict-6.7.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:a048ce45dcdaaf1defb76b2e684f997fb5abf74437b6cb7b22ddad934a964e34"}, + {file = "multidict-6.7.0-cp311-cp311-win32.whl", hash = "sha256:a90af66facec4cebe4181b9e62a68be65e45ac9b52b67de9eec118701856e7ff"}, + {file = "multidict-6.7.0-cp311-cp311-win_amd64.whl", hash = "sha256:95b5ffa4349df2887518bb839409bcf22caa72d82beec453216802f475b23c81"}, + {file = "multidict-6.7.0-cp311-cp311-win_arm64.whl", hash = "sha256:329aa225b085b6f004a4955271a7ba9f1087e39dcb7e65f6284a988264a63912"}, + {file = "multidict-6.7.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:8a3862568a36d26e650a19bb5cbbba14b71789032aebc0423f8cc5f150730184"}, + {file = "multidict-6.7.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:960c60b5849b9b4f9dcc9bea6e3626143c252c74113df2c1540aebce70209b45"}, + {file = "multidict-6.7.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2049be98fb57a31b4ccf870bf377af2504d4ae35646a19037ec271e4c07998aa"}, + {file = "multidict-6.7.0-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:0934f3843a1860dd465d38895c17fce1f1cb37295149ab05cd1b9a03afacb2a7"}, + {file = "multidict-6.7.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b3e34f3a1b8131ba06f1a73adab24f30934d148afcd5f5de9a73565a4404384e"}, + {file = "multidict-6.7.0-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:efbb54e98446892590dc2458c19c10344ee9a883a79b5cec4bc34d6656e8d546"}, + {file = "multidict-6.7.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a35c5fc61d4f51eb045061e7967cfe3123d622cd500e8868e7c0c592a09fedc4"}, + {file = "multidict-6.7.0-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:29fe6740ebccba4175af1b9b87bf553e9c15cd5868ee967e010efcf94e4fd0f1"}, + {file = "multidict-6.7.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:123e2a72e20537add2f33a79e605f6191fba2afda4cbb876e35c1a7074298a7d"}, + {file = "multidict-6.7.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:b284e319754366c1aee2267a2036248b24eeb17ecd5dc16022095e747f2f4304"}, + {file = "multidict-6.7.0-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:803d685de7be4303b5a657b76e2f6d1240e7e0a8aa2968ad5811fa2285553a12"}, + {file = "multidict-6.7.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:c04a328260dfd5db8c39538f999f02779012268f54614902d0afc775d44e0a62"}, + {file = "multidict-6.7.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:8a19cdb57cd3df4cd865849d93ee14920fb97224300c88501f16ecfa2604b4e0"}, + {file = "multidict-6.7.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:9b2fd74c52accced7e75de26023b7dccee62511a600e62311b918ec5c168fc2a"}, + {file = "multidict-6.7.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:3e8bfdd0e487acf992407a140d2589fe598238eaeffa3da8448d63a63cd363f8"}, + {file = "multidict-6.7.0-cp312-cp312-win32.whl", hash = "sha256:dd32a49400a2c3d52088e120ee00c1e3576cbff7e10b98467962c74fdb762ed4"}, + {file = "multidict-6.7.0-cp312-cp312-win_amd64.whl", hash = "sha256:92abb658ef2d7ef22ac9f8bb88e8b6c3e571671534e029359b6d9e845923eb1b"}, + {file = "multidict-6.7.0-cp312-cp312-win_arm64.whl", hash = "sha256:490dab541a6a642ce1a9d61a4781656b346a55c13038f0b1244653828e3a83ec"}, + {file = "multidict-6.7.0-py3-none-any.whl", hash = "sha256:394fc5c42a333c9ffc3e421a4c85e08580d990e08b99f6bf35b4132114c5dcb3"}, + {file = "multidict-6.7.0.tar.gz", hash = "sha256:c6e99d9a65ca282e578dfea819cfa9c0a62b2499d8677392e09feaf305e9e6f5"}, ] [[package]] name = "mypy" -version = "1.15.0" +version = "1.19.0" requires_python = ">=3.9" summary = "Optional static typing for Python" dependencies = [ + "librt>=0.6.2", "mypy-extensions>=1.0.0", + "pathspec>=0.9.0", "tomli>=1.1.0; python_version < \"3.11\"", "typing-extensions>=4.6.0", ] files = [ - {file = "mypy-1.15.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2922d42e16d6de288022e5ca321cd0618b238cfc5570e0263e5ba0a77dbef56f"}, - {file = "mypy-1.15.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2ee2d57e01a7c35de00f4634ba1bbf015185b219e4dc5909e281016df43f5ee5"}, - {file = "mypy-1.15.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:973500e0774b85d9689715feeffcc980193086551110fd678ebe1f4342fb7c5e"}, - {file = "mypy-1.15.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5a95fb17c13e29d2d5195869262f8125dfdb5c134dc8d9a9d0aecf7525b10c2c"}, - {file = "mypy-1.15.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1905f494bfd7d85a23a88c5d97840888a7bd516545fc5aaedff0267e0bb54e2f"}, - {file = "mypy-1.15.0-cp311-cp311-win_amd64.whl", hash = "sha256:c9817fa23833ff189db061e6d2eff49b2f3b6ed9856b4a0a73046e41932d744f"}, - {file = "mypy-1.15.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:aea39e0583d05124836ea645f412e88a5c7d0fd77a6d694b60d9b6b2d9f184fd"}, - {file = "mypy-1.15.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2f2147ab812b75e5b5499b01ade1f4a81489a147c01585cda36019102538615f"}, - {file = "mypy-1.15.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ce436f4c6d218a070048ed6a44c0bbb10cd2cc5e272b29e7845f6a2f57ee4464"}, - {file = "mypy-1.15.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8023ff13985661b50a5928fc7a5ca15f3d1affb41e5f0a9952cb68ef090b31ee"}, - {file = "mypy-1.15.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:1124a18bc11a6a62887e3e137f37f53fbae476dc36c185d549d4f837a2a6a14e"}, - {file = "mypy-1.15.0-cp312-cp312-win_amd64.whl", hash = "sha256:171a9ca9a40cd1843abeca0e405bc1940cd9b305eaeea2dda769ba096932bb22"}, - {file = "mypy-1.15.0-py3-none-any.whl", hash = "sha256:5469affef548bd1895d86d3bf10ce2b44e33d86923c29e4d675b3e323437ea3e"}, - {file = "mypy-1.15.0.tar.gz", hash = "sha256:404534629d51d3efea5c800ee7c42b72a6554d6c400e6a79eafe15d11341fd43"}, + {file = "mypy-1.19.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a31e4c28e8ddb042c84c5e977e28a21195d086aaffaf08b016b78e19c9ef8106"}, + {file = "mypy-1.19.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:34ec1ac66d31644f194b7c163d7f8b8434f1b49719d403a5d26c87fff7e913f7"}, + {file = "mypy-1.19.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:cb64b0ba5980466a0f3f9990d1c582bcab8db12e29815ecb57f1408d99b4bff7"}, + {file = "mypy-1.19.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:120cffe120cca5c23c03c77f84abc0c14c5d2e03736f6c312480020082f1994b"}, + {file = "mypy-1.19.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:7a500ab5c444268a70565e374fc803972bfd1f09545b13418a5174e29883dab7"}, + {file = "mypy-1.19.0-cp311-cp311-win_amd64.whl", hash = "sha256:c14a98bc63fd867530e8ec82f217dae29d0550c86e70debc9667fff1ec83284e"}, + {file = "mypy-1.19.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:0fb3115cb8fa7c5f887c8a8d81ccdcb94cff334684980d847e5a62e926910e1d"}, + {file = "mypy-1.19.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f3e19e3b897562276bb331074d64c076dbdd3e79213f36eed4e592272dabd760"}, + {file = "mypy-1.19.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b9d491295825182fba01b6ffe2c6fe4e5a49dbf4e2bb4d1217b6ced3b4797bc6"}, + {file = "mypy-1.19.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6016c52ab209919b46169651b362068f632efcd5eb8ef9d1735f6f86da7853b2"}, + {file = "mypy-1.19.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:f188dcf16483b3e59f9278c4ed939ec0254aa8a60e8fc100648d9ab5ee95a431"}, + {file = "mypy-1.19.0-cp312-cp312-win_amd64.whl", hash = "sha256:0e3c3d1e1d62e678c339e7ade72746a9e0325de42cd2cccc51616c7b2ed1a018"}, + {file = "mypy-1.19.0-py3-none-any.whl", hash = "sha256:0c01c99d626380752e527d5ce8e69ffbba2046eb8a060db0329690849cf9b6f9"}, + {file = "mypy-1.19.0.tar.gz", hash = "sha256:f6b874ca77f733222641e5c46e4711648c4037ea13646fd0cdc814c2eaec2528"}, ] [[package]] @@ -1944,12 +2223,12 @@ files = [ [[package]] name = "narwhals" -version = "1.39.1" -requires_python = ">=3.8" +version = "2.13.0" +requires_python = ">=3.9" summary = "Extremely lightweight compatibility layer between dataframe libraries" files = [ - {file = "narwhals-1.39.1-py3-none-any.whl", hash = "sha256:68d0f29c760f1a9419ada537f35f21ff202b0be1419e6d22135a0352c6d96deb"}, - {file = "narwhals-1.39.1.tar.gz", hash = "sha256:cf15389e6f8c5321e8cd0ca8b5bace3b1aea5f5622fa59dfd64821998741d836"}, + {file = "narwhals-2.13.0-py3-none-any.whl", hash = "sha256:9b795523c179ca78204e3be53726da374168f906e38de2ff174c2363baaaf481"}, + {file = "narwhals-2.13.0.tar.gz", hash = "sha256:ee94c97f4cf7cfeebbeca8d274784df8b3d7fd3f955ce418af998d405576fdd9"}, ] [[package]] @@ -2023,8 +2302,8 @@ files = [ [[package]] name = "netcdf4" -version = "1.7.2" -requires_python = ">=3.8" +version = "1.7.3" +requires_python = ">=3.10" summary = "Provides an object-oriented python interface to the netCDF version 4 library" dependencies = [ "certifi", @@ -2032,44 +2311,66 @@ dependencies = [ "numpy", ] files = [ - {file = "netCDF4-1.7.2-cp311-cp311-macosx_12_0_x86_64.whl", hash = "sha256:09d61c2ddb6011afb51e77ea0f25cd0bdc28887fb426ffbbc661d920f20c9749"}, - {file = "netCDF4-1.7.2-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:fd2a16dbddeb8fa7cf48c37bfc1967290332f2862bb82f984eec2007bb120aeb"}, - {file = "netCDF4-1.7.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f54f5d39ffbcf1726a1e6fd90cb5fa74277ecea739a5fa0f424636d71beafe24"}, - {file = "netCDF4-1.7.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:902aa50d70f49d002d896212a171d344c38f7b8ca520837c56c922ac1535c4a3"}, - {file = "netCDF4-1.7.2-cp311-cp311-win_amd64.whl", hash = "sha256:3291f9ad0c98c49a4dd16aefad1a9abd3a1b884171db6c81bdcee94671cfabe3"}, - {file = "netCDF4-1.7.2-cp312-cp312-macosx_12_0_x86_64.whl", hash = "sha256:e73e3baa0b74afc414e53ff5095748fdbec7fb346eda351e567c23f2f0d247f1"}, - {file = "netCDF4-1.7.2-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:a51da09258b31776f474c1d47e484fc7214914cdc59edf4cee789ba632184591"}, - {file = "netCDF4-1.7.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cb95b11804fe051897d1f2044b05d82a1847bc2549631cdd2f655dde7de77a9c"}, - {file = "netCDF4-1.7.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f9d8a848373723f41ef662590b4f5e1832227501c9fd4513e8ad8da58c269977"}, - {file = "netCDF4-1.7.2-cp312-cp312-win_amd64.whl", hash = "sha256:568ea369e00b581302d77fc5fd0b8f78e520c7e08d0b5af5219ba51f3f1cd694"}, - {file = "netcdf4-1.7.2.tar.gz", hash = "sha256:a4c6375540b19989896136943abb6d44850ff6f1fa7d3f063253b1ad3f8b7fce"}, + {file = "netcdf4-1.7.3-cp311-abi3-macosx_13_0_x86_64.whl", hash = "sha256:801c222d8ad35fd7dc7e9aa7ea6373d184bcb3b8ee6b794c5fbecaa5155b1792"}, + {file = "netcdf4-1.7.3-cp311-abi3-macosx_14_0_arm64.whl", hash = "sha256:83dbfd6f10a0ec785d5296016bd821bbe9f0df780be72fc00a1f0d179d9c5f0f"}, + {file = "netcdf4-1.7.3-cp311-abi3-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:949e086d4d2612b49e5b95f60119d216c9ceb7b17bc771e9e0fa0e9b9c0a2f9f"}, + {file = "netcdf4-1.7.3-cp311-abi3-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0c764ba6f6a1421cab5496097e8a1c4d2e36be2a04880dfd288bb61b348c217e"}, + {file = "netcdf4-1.7.3-cp311-abi3-win_amd64.whl", hash = "sha256:1b6c646fa179fb1e5e8d6e8231bc78cc0311eceaa1241256b5a853f1d04055b9"}, + {file = "netcdf4-1.7.3.tar.gz", hash = "sha256:83f122fc3415e92b1d4904fd6a0898468b5404c09432c34beb6b16c533884673"}, ] [[package]] name = "networkx" -version = "3.4.2" -requires_python = ">=3.10" +version = "3.6.1" +requires_python = "!=3.14.1,>=3.11" summary = "Python package for creating and manipulating graphs and networks" files = [ - {file = "networkx-3.4.2-py3-none-any.whl", hash = "sha256:df5d4365b724cf81b8c6a7312509d0c22386097011ad1abe274afd5e9d3bbc5f"}, - {file = "networkx-3.4.2.tar.gz", hash = "sha256:307c3669428c5362aab27c8a1260aa8f47c4e91d3891f48be0141738d8d053e1"}, + {file = "networkx-3.6.1-py3-none-any.whl", hash = "sha256:d47fbf302e7d9cbbb9e2555a0d267983d2aa476bac30e90dfbe5669bd57f3762"}, + {file = "networkx-3.6.1.tar.gz", hash = "sha256:26b7c357accc0c8cde558ad486283728b65b6a95d85ee1cd66bafab4c8168509"}, ] [[package]] -name = "notebook" -version = "7.4.2" +name = "ninja" +version = "1.13.0" requires_python = ">=3.8" +summary = "Ninja is a small build system with a focus on speed" +files = [ + {file = "ninja-1.13.0-py3-none-macosx_10_9_universal2.whl", hash = "sha256:fa2a8bfc62e31b08f83127d1613d10821775a0eb334197154c4d6067b7068ff1"}, + {file = "ninja-1.13.0-py3-none-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:3d00c692fb717fd511abeb44b8c5d00340c36938c12d6538ba989fe764e79630"}, + {file = "ninja-1.13.0-py3-none-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:be7f478ff9f96a128b599a964fc60a6a87b9fa332ee1bd44fa243ac88d50291c"}, + {file = "ninja-1.13.0-py3-none-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:60056592cf495e9a6a4bea3cd178903056ecb0943e4de45a2ea825edb6dc8d3e"}, + {file = "ninja-1.13.0-py3-none-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:1c97223cdda0417f414bf864cfb73b72d8777e57ebb279c5f6de368de0062988"}, + {file = "ninja-1.13.0-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:fb46acf6b93b8dd0322adc3a4945452a4e774b75b91293bafcc7b7f8e6517dfa"}, + {file = "ninja-1.13.0-py3-none-manylinux_2_28_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:4be9c1b082d244b1ad7ef41eb8ab088aae8c109a9f3f0b3e56a252d3e00f42c1"}, + {file = "ninja-1.13.0-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:6739d3352073341ad284246f81339a384eec091d9851a886dfa5b00a6d48b3e2"}, + {file = "ninja-1.13.0-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:11be2d22027bde06f14c343f01d31446747dbb51e72d00decca2eb99be911e2f"}, + {file = "ninja-1.13.0-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:aa45b4037b313c2f698bc13306239b8b93b4680eb47e287773156ac9e9304714"}, + {file = "ninja-1.13.0-py3-none-musllinux_1_2_i686.whl", hash = "sha256:5f8e1e8a1a30835eeb51db05cf5a67151ad37542f5a4af2a438e9490915e5b72"}, + {file = "ninja-1.13.0-py3-none-musllinux_1_2_ppc64le.whl", hash = "sha256:3d7d7779d12cb20c6d054c61b702139fd23a7a964ec8f2c823f1ab1b084150db"}, + {file = "ninja-1.13.0-py3-none-musllinux_1_2_riscv64.whl", hash = "sha256:d741a5e6754e0bda767e3274a0f0deeef4807f1fec6c0d7921a0244018926ae5"}, + {file = "ninja-1.13.0-py3-none-musllinux_1_2_s390x.whl", hash = "sha256:e8bad11f8a00b64137e9b315b137d8bb6cbf3086fbdc43bf1f90fd33324d2e96"}, + {file = "ninja-1.13.0-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:b4f2a072db3c0f944c32793e91532d8948d20d9ab83da9c0c7c15b5768072200"}, + {file = "ninja-1.13.0-py3-none-win32.whl", hash = "sha256:8cfbb80b4a53456ae8a39f90ae3d7a2129f45ea164f43fadfa15dc38c4aef1c9"}, + {file = "ninja-1.13.0-py3-none-win_amd64.whl", hash = "sha256:fb8ee8719f8af47fed145cced4a85f0755dd55d45b2bddaf7431fa89803c5f3e"}, + {file = "ninja-1.13.0-py3-none-win_arm64.whl", hash = "sha256:3c0b40b1f0bba764644385319028650087b4c1b18cdfa6f45cb39a3669b81aa9"}, + {file = "ninja-1.13.0.tar.gz", hash = "sha256:4a40ce995ded54d9dc24f8ea37ff3bf62ad192b547f6c7126e7e25045e76f978"}, +] + +[[package]] +name = "notebook" +version = "7.5.0" +requires_python = ">=3.9" summary = "Jupyter Notebook - A web-based notebook environment for interactive computing" dependencies = [ "jupyter-server<3,>=2.4.0", - "jupyterlab-server<3,>=2.27.1", - "jupyterlab<4.5,>=4.4.0", + "jupyterlab-server<3,>=2.28.0", + "jupyterlab<4.6,>=4.5.0rc0", "notebook-shim<0.3,>=0.2", "tornado>=6.2.0", ] files = [ - {file = "notebook-7.4.2-py3-none-any.whl", hash = "sha256:9ccef602721aaa5530852e3064710b8ae5415c4e2ce26f8896d0433222755259"}, - {file = "notebook-7.4.2.tar.gz", hash = "sha256:e739defd28c3f615a6bfb0a2564bd75018a9cc6613aa00bbd9c15e68eed2de1b"}, + {file = "notebook-7.5.0-py3-none-any.whl", hash = "sha256:3300262d52905ca271bd50b22617681d95f08a8360d099e097726e6d2efb5811"}, + {file = "notebook-7.5.0.tar.gz", hash = "sha256:3b27eaf9913033c28dde92d02139414c608992e1df4b969c843219acf2ff95e4"}, ] [[package]] @@ -2087,25 +2388,23 @@ files = [ [[package]] name = "numba" -version = "0.61.2" +version = "0.63.1" requires_python = ">=3.10" summary = "compiling Python code using LLVM" dependencies = [ - "llvmlite<0.45,>=0.44.0dev0", - "numpy<2.3,>=1.24", + "llvmlite<0.47,>=0.46.0dev0", + "numpy<2.4,>=1.22", ] files = [ - {file = "numba-0.61.2-cp311-cp311-macosx_10_14_x86_64.whl", hash = "sha256:efd3db391df53aaa5cfbee189b6c910a5b471488749fd6606c3f33fc984c2ae2"}, - {file = "numba-0.61.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:49c980e4171948ffebf6b9a2520ea81feed113c1f4890747ba7f59e74be84b1b"}, - {file = "numba-0.61.2-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:3945615cd73c2c7eba2a85ccc9c1730c21cd3958bfcf5a44302abae0fb07bb60"}, - {file = "numba-0.61.2-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:bbfdf4eca202cebade0b7d43896978e146f39398909a42941c9303f82f403a18"}, - {file = "numba-0.61.2-cp311-cp311-win_amd64.whl", hash = "sha256:76bcec9f46259cedf888041b9886e257ae101c6268261b19fda8cfbc52bec9d1"}, - {file = "numba-0.61.2-cp312-cp312-macosx_10_14_x86_64.whl", hash = "sha256:34fba9406078bac7ab052efbf0d13939426c753ad72946baaa5bf9ae0ebb8dd2"}, - {file = "numba-0.61.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:4ddce10009bc097b080fc96876d14c051cc0c7679e99de3e0af59014dab7dfe8"}, - {file = "numba-0.61.2-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:5b1bb509d01f23d70325d3a5a0e237cbc9544dd50e50588bc581ba860c213546"}, - {file = "numba-0.61.2-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:48a53a3de8f8793526cbe330f2a39fe9a6638efcbf11bd63f3d2f9757ae345cd"}, - {file = "numba-0.61.2-cp312-cp312-win_amd64.whl", hash = "sha256:97cf4f12c728cf77c9c1d7c23707e4d8fb4632b46275f8f3397de33e5877af18"}, - {file = "numba-0.61.2.tar.gz", hash = "sha256:8750ee147940a6637b80ecf7f95062185ad8726c8c28a2295b8ec1160a196f7d"}, + {file = "numba-0.63.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:b33db00f18ccc790ee9911ce03fcdfe9d5124637d1ecc266f5ae0df06e02fec3"}, + {file = "numba-0.63.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:7d31ea186a78a7c0f6b1b2a3fe68057fdb291b045c52d86232b5383b6cf4fc25"}, + {file = "numba-0.63.1-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ed3bb2fbdb651d6aac394388130a7001aab6f4541837123a4b4ab8b02716530c"}, + {file = "numba-0.63.1-cp311-cp311-win_amd64.whl", hash = "sha256:1ecbff7688f044b1601be70113e2fb1835367ee0b28ffa8f3adf3a05418c5c87"}, + {file = "numba-0.63.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2819cd52afa5d8d04e057bdfd54367575105f8829350d8fb5e4066fb7591cc71"}, + {file = "numba-0.63.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:5cfd45dbd3d409e713b1ccfdc2ee72ca82006860254429f4ef01867fdba5845f"}, + {file = "numba-0.63.1-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:69a599df6976c03b7ecf15d05302696f79f7e6d10d620367407517943355bcb0"}, + {file = "numba-0.63.1-cp312-cp312-win_amd64.whl", hash = "sha256:bbad8c63e4fc7eb3cdb2c2da52178e180419f7969f9a685f283b313a70b92af3"}, + {file = "numba-0.63.1.tar.gz", hash = "sha256:b320aa675d0e3b17b40364935ea52a7b1c670c9037c39cf92c49502a75902f4b"}, ] [[package]] @@ -2162,7 +2461,7 @@ files = [ [[package]] name = "osqp" -version = "1.0.4" +version = "1.0.5" requires_python = ">=3.8" summary = "OSQP: The Operator Splitting QP Solver" dependencies = [ @@ -2173,15 +2472,17 @@ dependencies = [ "setuptools", ] files = [ - {file = "osqp-1.0.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:819603a8b6d84e17bbe0e17558235e5dbe3d6b95021550d7da4942aa35b31b60"}, - {file = "osqp-1.0.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:8e76644654e30edf97eb5d400ffa57f3541b551842921ed9ac16db8f307883d9"}, - {file = "osqp-1.0.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ddd7fc52e01c602f3482878b334eed1b366a9940b2053059968d3d47688de9ef"}, - {file = "osqp-1.0.4-cp311-cp311-win_amd64.whl", hash = "sha256:c2a2ac69feb009ac43f80f33dfe5b32baaccefd22c6fcb9176b48f755506f120"}, - {file = "osqp-1.0.4-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:6432c8ea5db1b334eb20abce2c0eca081edc070ea86ec634bb62e8ca1a014e21"}, - {file = "osqp-1.0.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8510861708fe664a0942bccfea4b3ea566b12927e54b415f539c24b8cad095c0"}, - {file = "osqp-1.0.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8a3e3321b11426fa7a33b84f87f8d8608fdcd56c3992739012370f4d475b6a8f"}, - {file = "osqp-1.0.4-cp312-cp312-win_amd64.whl", hash = "sha256:73357ceb0cee581a8a18f32a50dda8954c80374bc94e77c06d8ececb402e2a22"}, - {file = "osqp-1.0.4.tar.gz", hash = "sha256:0877552e325ff4cc1c676796ba482904eb4b66e750eff5b91df3273201f5ed00"}, + {file = "osqp-1.0.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:7bd899ea81ac03030ea0e28a1102797779ffe6450315ad79009c89bb20156887"}, + {file = "osqp-1.0.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:b837236c847ac90dbd074001dbe5c921701a717fbfebe25f86af93adcad496be"}, + {file = "osqp-1.0.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e65dde66bf5001a6884082090e7311e1f6881a475e9b6c1b5924d7afa7cd5adc"}, + {file = "osqp-1.0.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c83f4a164e03fba91c244f6cfaa52acc3e6a93d11b3279a9f768f0a14e82fb18"}, + {file = "osqp-1.0.5-cp311-cp311-win_amd64.whl", hash = "sha256:e1f6d0231ea47269ccf3df5587987797a5a2fca4083058ea6d53e2d777c9e3fb"}, + {file = "osqp-1.0.5-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:f655cc1602bef3c722ba124e0f3b5127905c7cd10208968b3caad1fec34b8b51"}, + {file = "osqp-1.0.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f94fac0239136812a49de44ec24150134802f218313e37266be0629576e9d9d5"}, + {file = "osqp-1.0.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b8e0f2cc375ed485270dfa4636abac86a7499c2847e12603dafe40f7a55fdf61"}, + {file = "osqp-1.0.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bf39cc311089b5f4987b0469e8563ab378b9d1ea8f7f9d3aec93e0b6097cc51b"}, + {file = "osqp-1.0.5-cp312-cp312-win_amd64.whl", hash = "sha256:aafb6c65352ce7fd691927275a8ebd67974ceb4496925961d73a74e4f9a6e7fa"}, + {file = "osqp-1.0.5.tar.gz", hash = "sha256:60b484cf829c99d94bb7ae4e9beb2e0895d94c5e64e074b5b27b6ef887941936"}, ] [[package]] @@ -2209,7 +2510,7 @@ files = [ [[package]] name = "pandas" -version = "2.2.3" +version = "2.3.3" requires_python = ">=3.9" summary = "Powerful data structures for data analysis, time series, and statistics" dependencies = [ @@ -2221,21 +2522,21 @@ dependencies = [ "tzdata>=2022.7", ] files = [ - {file = "pandas-2.2.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:66108071e1b935240e74525006034333f98bcdb87ea116de573a6a0dccb6c039"}, - {file = "pandas-2.2.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7c2875855b0ff77b2a64a0365e24455d9990730d6431b9e0ee18ad8acee13dbd"}, - {file = "pandas-2.2.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:cd8d0c3be0515c12fed0bdbae072551c8b54b7192c7b1fda0ba56059a0179698"}, - {file = "pandas-2.2.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c124333816c3a9b03fbeef3a9f230ba9a737e9e5bb4060aa2107a86cc0a497fc"}, - {file = "pandas-2.2.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:63cc132e40a2e084cf01adf0775b15ac515ba905d7dcca47e9a251819c575ef3"}, - {file = "pandas-2.2.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:29401dbfa9ad77319367d36940cd8a0b3a11aba16063e39632d98b0e931ddf32"}, - {file = "pandas-2.2.3-cp311-cp311-win_amd64.whl", hash = "sha256:3fc6873a41186404dad67245896a6e440baacc92f5b716ccd1bc9ed2995ab2c5"}, - {file = "pandas-2.2.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:b1d432e8d08679a40e2a6d8b2f9770a5c21793a6f9f47fdd52c5ce1948a5a8a9"}, - {file = "pandas-2.2.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:a5a1595fe639f5988ba6a8e5bc9649af3baf26df3998a0abe56c02609392e0a4"}, - {file = "pandas-2.2.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:5de54125a92bb4d1c051c0659e6fcb75256bf799a732a87184e5ea503965bce3"}, - {file = "pandas-2.2.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fffb8ae78d8af97f849404f21411c95062db1496aeb3e56f146f0355c9989319"}, - {file = "pandas-2.2.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6dfcb5ee8d4d50c06a51c2fffa6cff6272098ad6540aed1a76d15fb9318194d8"}, - {file = "pandas-2.2.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:062309c1b9ea12a50e8ce661145c6aab431b1e99530d3cd60640e255778bd43a"}, - {file = "pandas-2.2.3-cp312-cp312-win_amd64.whl", hash = "sha256:59ef3764d0fe818125a5097d2ae867ca3fa64df032331b7e0917cf5d7bf66b13"}, - {file = "pandas-2.2.3.tar.gz", hash = "sha256:4f18ba62b61d7e192368b84517265a99b4d7ee8912f8708660fb4a366cc82667"}, + {file = "pandas-2.3.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:602b8615ebcc4a0c1751e71840428ddebeb142ec02c786e8ad6b1ce3c8dec523"}, + {file = "pandas-2.3.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:8fe25fc7b623b0ef6b5009149627e34d2a4657e880948ec3c840e9402e5c1b45"}, + {file = "pandas-2.3.3-cp311-cp311-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b468d3dad6ff947df92dcb32ede5b7bd41a9b3cceef0a30ed925f6d01fb8fa66"}, + {file = "pandas-2.3.3-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b98560e98cb334799c0b07ca7967ac361a47326e9b4e5a7dfb5ab2b1c9d35a1b"}, + {file = "pandas-2.3.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1d37b5848ba49824e5c30bedb9c830ab9b7751fd049bc7914533e01c65f79791"}, + {file = "pandas-2.3.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:db4301b2d1f926ae677a751eb2bd0e8c5f5319c9cb3f88b0becbbb0b07b34151"}, + {file = "pandas-2.3.3-cp311-cp311-win_amd64.whl", hash = "sha256:f086f6fe114e19d92014a1966f43a3e62285109afe874f067f5abbdcbb10e59c"}, + {file = "pandas-2.3.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:6d21f6d74eb1725c2efaa71a2bfc661a0689579b58e9c0ca58a739ff0b002b53"}, + {file = "pandas-2.3.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:3fd2f887589c7aa868e02632612ba39acb0b8948faf5cc58f0850e165bd46f35"}, + {file = "pandas-2.3.3-cp312-cp312-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ecaf1e12bdc03c86ad4a7ea848d66c685cb6851d807a26aa245ca3d2017a1908"}, + {file = "pandas-2.3.3-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b3d11d2fda7eb164ef27ffc14b4fcab16a80e1ce67e9f57e19ec0afaf715ba89"}, + {file = "pandas-2.3.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:a68e15f780eddf2b07d242e17a04aa187a7ee12b40b930bfdd78070556550e98"}, + {file = "pandas-2.3.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:371a4ab48e950033bcf52b6527eccb564f52dc826c02afd9a1bc0ab731bba084"}, + {file = "pandas-2.3.3-cp312-cp312-win_amd64.whl", hash = "sha256:a16dcec078a01eeef8ee61bf64074b4e524a2a3f4b3be9326420cabe59c4778b"}, + {file = "pandas-2.3.3.tar.gz", hash = "sha256:e05e1af93b977f7eafa636d043f9f94c7ee3ac81af99c13508215942e64c993b"}, ] [[package]] @@ -2250,16 +2551,17 @@ files = [ [[package]] name = "panel" -version = "1.7.0" +version = "1.8.4" requires_python = ">=3.10" summary = "The powerful data exploration & web app framework for Python." dependencies = [ "bleach", - "bokeh<3.8.0,>=3.5.0", + "bokeh<3.9.0,>=3.7.0", "linkify-it-py", "markdown", "markdown-it-py", "mdit-py-plugins", + "narwhals>=2", "packaging", "pandas>=1.2", "param<3.0,>=2.1.0", @@ -2269,28 +2571,28 @@ dependencies = [ "typing-extensions", ] files = [ - {file = "panel-1.7.0-py3-none-any.whl", hash = "sha256:442bb03cf03e3bb2f9a253f216c1b872adb15afcc6f6b6d5a8483b1618264553"}, - {file = "panel-1.7.0.tar.gz", hash = "sha256:631bac988ba4f1142396d20752ed98f874482ce040b252dbb443ee4ec1717a61"}, + {file = "panel-1.8.4-py3-none-any.whl", hash = "sha256:d0e0f316c78159c87544a403d4600f7f056a6cafdc035df5b13c9c8667c36c96"}, + {file = "panel-1.8.4.tar.gz", hash = "sha256:c4d6e7e3a895d3a42b6b69ee30d3acc191580619a2d1b8cd18f7f6684246a67f"}, ] [[package]] name = "param" -version = "2.2.0" -requires_python = ">=3.9" -summary = "Make your Python code clearer and more reliable by declaring Parameters." +version = "2.3.1" +requires_python = ">=3.10" +summary = "Declarative parameters for robust Python classes and a rich API for reactive programming" files = [ - {file = "param-2.2.0-py3-none-any.whl", hash = "sha256:777f8c7b66ab820b70ea5ad09faaa6818308220caae89da3b5c5f359faa72a5e"}, - {file = "param-2.2.0.tar.gz", hash = "sha256:2ef63ef7aef37412eeb8ee3a06189a51f69c58c068824ae070baecb5b2abd0b8"}, + {file = "param-2.3.1-py3-none-any.whl", hash = "sha256:886b19031438719bbecfd15044dcdd9ed3cb9edb199191294f75600c7081d163"}, + {file = "param-2.3.1.tar.gz", hash = "sha256:84e59fc3a9bfb0e4c8100eb92d5be529deea3ec9c1f0881a0068c5caf31f21f3"}, ] [[package]] name = "parso" -version = "0.8.4" +version = "0.8.5" requires_python = ">=3.6" summary = "A Python Parser" files = [ - {file = "parso-0.8.4-py2.py3-none-any.whl", hash = "sha256:a418670a20291dacd2dddc80c377c5c3791378ee1e8d12bffc35420643d43f18"}, - {file = "parso-0.8.4.tar.gz", hash = "sha256:eb3a7b58240fb99099a345571deecc0f9540ea5f4dd2fe14c2a99d6b281ab92d"}, + {file = "parso-0.8.5-py2.py3-none-any.whl", hash = "sha256:646204b5ee239c396d040b90f9e272e9a8017c630092bf59980beb62fd033887"}, + {file = "parso-0.8.5.tar.gz", hash = "sha256:034d7354a9a018bdce352f48b2a8a450f05e9d6ee85db84764e9b6bd96dafe5a"}, ] [[package]] @@ -2307,6 +2609,23 @@ files = [ {file = "partd-1.4.2.tar.gz", hash = "sha256:d022c33afbdc8405c226621b015e8067888173d85f7f5ecebb3cafed9a20f02c"}, ] +[[package]] +name = "patchelf" +version = "0.17.2.4" +requires_python = ">=3.7" +summary = "A small utility to modify the dynamic linker and RPATH of ELF executables." +files = [ + {file = "patchelf-0.17.2.4-py3-none-macosx_10_9_universal2.whl", hash = "sha256:343bb1b94e959f9070ca9607453b04390e36bbaa33c88640b989cefad0aa049e"}, + {file = "patchelf-0.17.2.4-py3-none-manylinux1_i686.manylinux_2_5_i686.musllinux_1_1_i686.whl", hash = "sha256:09fd848d625a165fc7b7e07745508c24077129b019c4415a882938781d43adf8"}, + {file = "patchelf-0.17.2.4-py3-none-manylinux1_x86_64.manylinux_2_5_x86_64.musllinux_1_1_x86_64.whl", hash = "sha256:d9b35ebfada70c02679ad036407d9724ffe1255122ba4ac5e4be5868618a5689"}, + {file = "patchelf-0.17.2.4-py3-none-manylinux2014_aarch64.manylinux_2_17_aarch64.musllinux_1_1_aarch64.whl", hash = "sha256:2931a1b5b85f3549661898af7bf746afbda7903c7c9a967cfc998a3563f84fad"}, + {file = "patchelf-0.17.2.4-py3-none-manylinux2014_armv7l.manylinux_2_17_armv7l.musllinux_1_1_armv7l.whl", hash = "sha256:ae44cb3c857d50f54b99e5697aa978726ada33a8a6129d4b8b7ffd28b996652d"}, + {file = "patchelf-0.17.2.4-py3-none-manylinux2014_ppc64le.manylinux_2_17_ppc64le.musllinux_1_1_ppc64le.whl", hash = "sha256:680a266a70f60a7a4f4c448482c5bdba80cc8e6bb155a49dcc24238ba49927b0"}, + {file = "patchelf-0.17.2.4-py3-none-manylinux2014_s390x.manylinux_2_17_s390x.musllinux_1_1_s390x.whl", hash = "sha256:d842b51f0401460f3b1f3a3a67d2c266a8f515a5adfbfa6e7b656cb3ac2ed8bc"}, + {file = "patchelf-0.17.2.4-py3-none-manylinux_2_31_riscv64.musllinux_1_1_riscv64.whl", hash = "sha256:7076d9e127230982e20a81a6e2358d3343004667ba510d9f822d4fdee29b0d71"}, + {file = "patchelf-0.17.2.4.tar.gz", hash = "sha256:970ee5cd8af33e5ea2099510b2f9013fa1b8d5cd763bf3fd3961281c18101a09"}, +] + [[package]] name = "pathspec" version = "0.12.1" @@ -2319,15 +2638,15 @@ files = [ [[package]] name = "patsy" -version = "1.0.1" +version = "1.0.2" requires_python = ">=3.6" summary = "A Python package for describing statistical models and for building design matrices." dependencies = [ "numpy>=1.4", ] files = [ - {file = "patsy-1.0.1-py2.py3-none-any.whl", hash = "sha256:751fb38f9e97e62312e921a1954b81e1bb2bcda4f5eeabaf94db251ee791509c"}, - {file = "patsy-1.0.1.tar.gz", hash = "sha256:e786a9391eec818c054e359b737bbce692f051aee4c661f4141cc88fb459c0c4"}, + {file = "patsy-1.0.2-py2.py3-none-any.whl", hash = "sha256:37bfddbc58fcf0362febb5f54f10743f8b21dd2aa73dec7e7ef59d1b02ae668a"}, + {file = "patsy-1.0.2.tar.gz", hash = "sha256:cdc995455f6233e90e22de72c37fcadb344e7586fb83f06696f54d92f8ce74c0"}, ] [[package]] @@ -2344,55 +2663,55 @@ files = [ [[package]] name = "pillow" -version = "11.2.1" -requires_python = ">=3.9" -summary = "Python Imaging Library (Fork)" -files = [ - {file = "pillow-11.2.1-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:35ca289f712ccfc699508c4658a1d14652e8033e9b69839edf83cbdd0ba39e70"}, - {file = "pillow-11.2.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e0409af9f829f87a2dfb7e259f78f317a5351f2045158be321fd135973fff7bf"}, - {file = "pillow-11.2.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d4e5c5edee874dce4f653dbe59db7c73a600119fbea8d31f53423586ee2aafd7"}, - {file = "pillow-11.2.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b93a07e76d13bff9444f1a029e0af2964e654bfc2e2c2d46bfd080df5ad5f3d8"}, - {file = "pillow-11.2.1-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:e6def7eed9e7fa90fde255afaf08060dc4b343bbe524a8f69bdd2a2f0018f600"}, - {file = "pillow-11.2.1-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:8f4f3724c068be008c08257207210c138d5f3731af6c155a81c2b09a9eb3a788"}, - {file = "pillow-11.2.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:a0a6709b47019dff32e678bc12c63008311b82b9327613f534e496dacaefb71e"}, - {file = "pillow-11.2.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f6b0c664ccb879109ee3ca702a9272d877f4fcd21e5eb63c26422fd6e415365e"}, - {file = "pillow-11.2.1-cp311-cp311-win32.whl", hash = "sha256:cc5d875d56e49f112b6def6813c4e3d3036d269c008bf8aef72cd08d20ca6df6"}, - {file = "pillow-11.2.1-cp311-cp311-win_amd64.whl", hash = "sha256:0f5c7eda47bf8e3c8a283762cab94e496ba977a420868cb819159980b6709193"}, - {file = "pillow-11.2.1-cp311-cp311-win_arm64.whl", hash = "sha256:4d375eb838755f2528ac8cbc926c3e31cc49ca4ad0cf79cff48b20e30634a4a7"}, - {file = "pillow-11.2.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:78afba22027b4accef10dbd5eed84425930ba41b3ea0a86fa8d20baaf19d807f"}, - {file = "pillow-11.2.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:78092232a4ab376a35d68c4e6d5e00dfd73454bd12b230420025fbe178ee3b0b"}, - {file = "pillow-11.2.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:25a5f306095c6780c52e6bbb6109624b95c5b18e40aab1c3041da3e9e0cd3e2d"}, - {file = "pillow-11.2.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0c7b29dbd4281923a2bfe562acb734cee96bbb129e96e6972d315ed9f232bef4"}, - {file = "pillow-11.2.1-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:3e645b020f3209a0181a418bffe7b4a93171eef6c4ef6cc20980b30bebf17b7d"}, - {file = "pillow-11.2.1-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:b2dbea1012ccb784a65349f57bbc93730b96e85b42e9bf7b01ef40443db720b4"}, - {file = "pillow-11.2.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:da3104c57bbd72948d75f6a9389e6727d2ab6333c3617f0a89d72d4940aa0443"}, - {file = "pillow-11.2.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:598174aef4589af795f66f9caab87ba4ff860ce08cd5bb447c6fc553ffee603c"}, - {file = "pillow-11.2.1-cp312-cp312-win32.whl", hash = "sha256:1d535df14716e7f8776b9e7fee118576d65572b4aad3ed639be9e4fa88a1cad3"}, - {file = "pillow-11.2.1-cp312-cp312-win_amd64.whl", hash = "sha256:14e33b28bf17c7a38eede290f77db7c664e4eb01f7869e37fa98a5aa95978941"}, - {file = "pillow-11.2.1-cp312-cp312-win_arm64.whl", hash = "sha256:21e1470ac9e5739ff880c211fc3af01e3ae505859392bf65458c224d0bf283eb"}, - {file = "pillow-11.2.1-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:80f1df8dbe9572b4b7abdfa17eb5d78dd620b1d55d9e25f834efdbee872d3aed"}, - {file = "pillow-11.2.1-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:ea926cfbc3957090becbcbbb65ad177161a2ff2ad578b5a6ec9bb1e1cd78753c"}, - {file = "pillow-11.2.1-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:738db0e0941ca0376804d4de6a782c005245264edaa253ffce24e5a15cbdc7bd"}, - {file = "pillow-11.2.1-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9db98ab6565c69082ec9b0d4e40dd9f6181dab0dd236d26f7a50b8b9bfbd5076"}, - {file = "pillow-11.2.1-pp311-pypy311_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:036e53f4170e270ddb8797d4c590e6dd14d28e15c7da375c18978045f7e6c37b"}, - {file = "pillow-11.2.1-pp311-pypy311_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:14f73f7c291279bd65fda51ee87affd7c1e097709f7fdd0188957a16c264601f"}, - {file = "pillow-11.2.1-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:208653868d5c9ecc2b327f9b9ef34e0e42a4cdd172c2988fd81d62d2bc9bc044"}, - {file = "pillow-11.2.1.tar.gz", hash = "sha256:a64dd61998416367b7ef979b73d3a85853ba9bec4c2925f74e588879a58716b6"}, +version = "12.0.0" +requires_python = ">=3.10" +summary = "Python Imaging Library (fork)" +files = [ + {file = "pillow-12.0.0-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:0fd00cac9c03256c8b2ff58f162ebcd2587ad3e1f2e397eab718c47e24d231cc"}, + {file = "pillow-12.0.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a3475b96f5908b3b16c47533daaa87380c491357d197564e0ba34ae75c0f3257"}, + {file = "pillow-12.0.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:110486b79f2d112cf6add83b28b627e369219388f64ef2f960fef9ebaf54c642"}, + {file = "pillow-12.0.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:5269cc1caeedb67e6f7269a42014f381f45e2e7cd42d834ede3c703a1d915fe3"}, + {file = "pillow-12.0.0-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:aa5129de4e174daccbc59d0a3b6d20eaf24417d59851c07ebb37aeb02947987c"}, + {file = "pillow-12.0.0-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bee2a6db3a7242ea309aa7ee8e2780726fed67ff4e5b40169f2c940e7eb09227"}, + {file = "pillow-12.0.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:90387104ee8400a7b4598253b4c406f8958f59fcf983a6cea2b50d59f7d63d0b"}, + {file = "pillow-12.0.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:bc91a56697869546d1b8f0a3ff35224557ae7f881050e99f615e0119bf934b4e"}, + {file = "pillow-12.0.0-cp311-cp311-win32.whl", hash = "sha256:27f95b12453d165099c84f8a8bfdfd46b9e4bda9e0e4b65f0635430027f55739"}, + {file = "pillow-12.0.0-cp311-cp311-win_amd64.whl", hash = "sha256:b583dc9070312190192631373c6c8ed277254aa6e6084b74bdd0a6d3b221608e"}, + {file = "pillow-12.0.0-cp311-cp311-win_arm64.whl", hash = "sha256:759de84a33be3b178a64c8ba28ad5c135900359e85fb662bc6e403ad4407791d"}, + {file = "pillow-12.0.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:53561a4ddc36facb432fae7a9d8afbfaf94795414f5cdc5fc52f28c1dca90371"}, + {file = "pillow-12.0.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:71db6b4c1653045dacc1585c1b0d184004f0d7e694c7b34ac165ca70c0838082"}, + {file = "pillow-12.0.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:2fa5f0b6716fc88f11380b88b31fe591a06c6315e955c096c35715788b339e3f"}, + {file = "pillow-12.0.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:82240051c6ca513c616f7f9da06e871f61bfd7805f566275841af15015b8f98d"}, + {file = "pillow-12.0.0-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:55f818bd74fe2f11d4d7cbc65880a843c4075e0ac7226bc1a23261dbea531953"}, + {file = "pillow-12.0.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b87843e225e74576437fd5b6a4c2205d422754f84a06942cfaf1dc32243e45a8"}, + {file = "pillow-12.0.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:c607c90ba67533e1b2355b821fef6764d1dd2cbe26b8c1005ae84f7aea25ff79"}, + {file = "pillow-12.0.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:21f241bdd5080a15bc86d3466a9f6074a9c2c2b314100dd896ac81ee6db2f1ba"}, + {file = "pillow-12.0.0-cp312-cp312-win32.whl", hash = "sha256:dd333073e0cacdc3089525c7df7d39b211bcdf31fc2824e49d01c6b6187b07d0"}, + {file = "pillow-12.0.0-cp312-cp312-win_amd64.whl", hash = "sha256:9fe611163f6303d1619bbcb653540a4d60f9e55e622d60a3108be0d5b441017a"}, + {file = "pillow-12.0.0-cp312-cp312-win_arm64.whl", hash = "sha256:7dfb439562f234f7d57b1ac6bc8fe7f838a4bd49c79230e0f6a1da93e82f1fad"}, + {file = "pillow-12.0.0-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:b22bd8c974942477156be55a768f7aa37c46904c175be4e158b6a86e3a6b7ca8"}, + {file = "pillow-12.0.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:805ebf596939e48dbb2e4922a1d3852cfc25c38160751ce02da93058b48d252a"}, + {file = "pillow-12.0.0-pp311-pypy311_pp73-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:cae81479f77420d217def5f54b5b9d279804d17e982e0f2fa19b1d1e14ab5197"}, + {file = "pillow-12.0.0-pp311-pypy311_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:aeaefa96c768fc66818730b952a862235d68825c178f1b3ffd4efd7ad2edcb7c"}, + {file = "pillow-12.0.0-pp311-pypy311_pp73-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:09f2d0abef9e4e2f349305a4f8cc784a8a6c2f58a8c4892eea13b10a943bd26e"}, + {file = "pillow-12.0.0-pp311-pypy311_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bdee52571a343d721fb2eb3b090a82d959ff37fc631e3f70422e0c2e029f3e76"}, + {file = "pillow-12.0.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:b290fd8aa38422444d4b50d579de197557f182ef1068b75f5aa8558638b8d0a5"}, + {file = "pillow-12.0.0.tar.gz", hash = "sha256:87d4f8125c9988bfbed67af47dd7a953e2fc7b0cc1e7800ec6d2080d490bb353"}, ] [[package]] name = "platformdirs" -version = "4.3.8" -requires_python = ">=3.9" +version = "4.5.1" +requires_python = ">=3.10" summary = "A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`." files = [ - {file = "platformdirs-4.3.8-py3-none-any.whl", hash = "sha256:ff7059bb7eb1179e2685604f4aaf157cfd9535242bd23742eadc3c13542139b4"}, - {file = "platformdirs-4.3.8.tar.gz", hash = "sha256:3d512d96e16bcb959a814c9f348431070822a6496326a4be0911c40b5a74c2bc"}, + {file = "platformdirs-4.5.1-py3-none-any.whl", hash = "sha256:d03afa3963c806a9bed9d5125c8f4cb2fdaf74a55ab60e5d59b3fde758104d31"}, + {file = "platformdirs-4.5.1.tar.gz", hash = "sha256:61d5cdcc6065745cdd94f0f878977f8de9437be93de97c1c12f853c9c0cdcbda"}, ] [[package]] name = "plotly" -version = "6.1.0" +version = "6.5.0" requires_python = ">=3.8" summary = "An open-source interactive data visualization library for Python" dependencies = [ @@ -2400,8 +2719,8 @@ dependencies = [ "packaging", ] files = [ - {file = "plotly-6.1.0-py3-none-any.whl", hash = "sha256:a29d3ed523c9d7960095693af1ee52689830df0f9c6bae3e5e92c20c4f5684c3"}, - {file = "plotly-6.1.0.tar.gz", hash = "sha256:f13f497ccc2d97f06f771a30b27fab0cbd220f2975865f4ecbc75057135521de"}, + {file = "plotly-6.5.0-py3-none-any.whl", hash = "sha256:5ac851e100367735250206788a2b1325412aa4a4917a4fe3e6f0bc5aa6f3d90a"}, + {file = "plotly-6.5.0.tar.gz", hash = "sha256:d5d38224883fd38c1409bef7d6a8dc32b74348d39313f3c52ca998b8e447f5c8"}, ] [[package]] @@ -2416,83 +2735,80 @@ files = [ [[package]] name = "prometheus-client" -version = "0.22.0" +version = "0.23.1" requires_python = ">=3.9" summary = "Python client for the Prometheus monitoring system." files = [ - {file = "prometheus_client-0.22.0-py3-none-any.whl", hash = "sha256:c8951bbe64e62b96cd8e8f5d917279d1b9b91ab766793f33d4dce6c228558713"}, - {file = "prometheus_client-0.22.0.tar.gz", hash = "sha256:18da1d2241ac2d10c8d2110f13eedcd5c7c0c8af18c926e8731f04fc10cd575c"}, + {file = "prometheus_client-0.23.1-py3-none-any.whl", hash = "sha256:dd1913e6e76b59cfe44e7a4b83e01afc9873c1bdfd2ed8739f1e76aeca115f99"}, + {file = "prometheus_client-0.23.1.tar.gz", hash = "sha256:6ae8f9081eaaaf153a2e959d2e6c4f4fb57b12ef76c8c7980202f1e57b48b2ce"}, ] [[package]] name = "prompt-toolkit" -version = "3.0.51" +version = "3.0.52" requires_python = ">=3.8" summary = "Library for building powerful interactive command lines in Python" dependencies = [ "wcwidth", ] files = [ - {file = "prompt_toolkit-3.0.51-py3-none-any.whl", hash = "sha256:52742911fde84e2d423e2f9a4cf1de7d7ac4e51958f648d9540e0fb8db077b07"}, - {file = "prompt_toolkit-3.0.51.tar.gz", hash = "sha256:931a162e3b27fc90c86f1b48bb1fb2c528c2761475e57c9c06de13311c7b54ed"}, + {file = "prompt_toolkit-3.0.52-py3-none-any.whl", hash = "sha256:9aac639a3bbd33284347de5ad8d68ecc044b91a762dc39b7c21095fcd6a19955"}, + {file = "prompt_toolkit-3.0.52.tar.gz", hash = "sha256:28cde192929c8e7321de85de1ddbe736f1375148b02f2e17edd840042b1be855"}, ] [[package]] name = "propcache" -version = "0.3.1" +version = "0.4.1" requires_python = ">=3.9" summary = "Accelerated property cache" files = [ - {file = "propcache-0.3.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:7f30241577d2fef2602113b70ef7231bf4c69a97e04693bde08ddab913ba0ce5"}, - {file = "propcache-0.3.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:43593c6772aa12abc3af7784bff4a41ffa921608dd38b77cf1dfd7f5c4e71371"}, - {file = "propcache-0.3.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a75801768bbe65499495660b777e018cbe90c7980f07f8aa57d6be79ea6f71da"}, - {file = "propcache-0.3.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f6f1324db48f001c2ca26a25fa25af60711e09b9aaf4b28488602776f4f9a744"}, - {file = "propcache-0.3.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5cdb0f3e1eb6dfc9965d19734d8f9c481b294b5274337a8cb5cb01b462dcb7e0"}, - {file = "propcache-0.3.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1eb34d90aac9bfbced9a58b266f8946cb5935869ff01b164573a7634d39fbcb5"}, - {file = "propcache-0.3.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f35c7070eeec2cdaac6fd3fe245226ed2a6292d3ee8c938e5bb645b434c5f256"}, - {file = "propcache-0.3.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b23c11c2c9e6d4e7300c92e022046ad09b91fd00e36e83c44483df4afa990073"}, - {file = "propcache-0.3.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:3e19ea4ea0bf46179f8a3652ac1426e6dcbaf577ce4b4f65be581e237340420d"}, - {file = "propcache-0.3.1-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:bd39c92e4c8f6cbf5f08257d6360123af72af9f4da75a690bef50da77362d25f"}, - {file = "propcache-0.3.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:b0313e8b923b3814d1c4a524c93dfecea5f39fa95601f6a9b1ac96cd66f89ea0"}, - {file = "propcache-0.3.1-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:e861ad82892408487be144906a368ddbe2dc6297074ade2d892341b35c59844a"}, - {file = "propcache-0.3.1-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:61014615c1274df8da5991a1e5da85a3ccb00c2d4701ac6f3383afd3ca47ab0a"}, - {file = "propcache-0.3.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:71ebe3fe42656a2328ab08933d420df5f3ab121772eef78f2dc63624157f0ed9"}, - {file = "propcache-0.3.1-cp311-cp311-win32.whl", hash = "sha256:58aa11f4ca8b60113d4b8e32d37e7e78bd8af4d1a5b5cb4979ed856a45e62005"}, - {file = "propcache-0.3.1-cp311-cp311-win_amd64.whl", hash = "sha256:9532ea0b26a401264b1365146c440a6d78269ed41f83f23818d4b79497aeabe7"}, - {file = "propcache-0.3.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:f78eb8422acc93d7b69964012ad7048764bb45a54ba7a39bb9e146c72ea29723"}, - {file = "propcache-0.3.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:89498dd49c2f9a026ee057965cdf8192e5ae070ce7d7a7bd4b66a8e257d0c976"}, - {file = "propcache-0.3.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:09400e98545c998d57d10035ff623266927cb784d13dd2b31fd33b8a5316b85b"}, - {file = "propcache-0.3.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aa8efd8c5adc5a2c9d3b952815ff8f7710cefdcaf5f2c36d26aff51aeca2f12f"}, - {file = "propcache-0.3.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c2fe5c910f6007e716a06d269608d307b4f36e7babee5f36533722660e8c4a70"}, - {file = "propcache-0.3.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a0ab8cf8cdd2194f8ff979a43ab43049b1df0b37aa64ab7eca04ac14429baeb7"}, - {file = "propcache-0.3.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:563f9d8c03ad645597b8d010ef4e9eab359faeb11a0a2ac9f7b4bc8c28ebef25"}, - {file = "propcache-0.3.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fb6e0faf8cb6b4beea5d6ed7b5a578254c6d7df54c36ccd3d8b3eb00d6770277"}, - {file = "propcache-0.3.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:1c5c7ab7f2bb3f573d1cb921993006ba2d39e8621019dffb1c5bc94cdbae81e8"}, - {file = "propcache-0.3.1-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:050b571b2e96ec942898f8eb46ea4bfbb19bd5502424747e83badc2d4a99a44e"}, - {file = "propcache-0.3.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:e1c4d24b804b3a87e9350f79e2371a705a188d292fd310e663483af6ee6718ee"}, - {file = "propcache-0.3.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:e4fe2a6d5ce975c117a6bb1e8ccda772d1e7029c1cca1acd209f91d30fa72815"}, - {file = "propcache-0.3.1-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:feccd282de1f6322f56f6845bf1207a537227812f0a9bf5571df52bb418d79d5"}, - {file = "propcache-0.3.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ec314cde7314d2dd0510c6787326bbffcbdc317ecee6b7401ce218b3099075a7"}, - {file = "propcache-0.3.1-cp312-cp312-win32.whl", hash = "sha256:7d2d5a0028d920738372630870e7d9644ce437142197f8c827194fca404bf03b"}, - {file = "propcache-0.3.1-cp312-cp312-win_amd64.whl", hash = "sha256:88c423efef9d7a59dae0614eaed718449c09a5ac79a5f224a8b9664d603f04a3"}, - {file = "propcache-0.3.1-py3-none-any.whl", hash = "sha256:9a8ecf38de50a7f518c21568c80f985e776397b902f1ce0b01f799aba1608b40"}, - {file = "propcache-0.3.1.tar.gz", hash = "sha256:40d980c33765359098837527e18eddefc9a24cea5b45e078a7f3bb5b032c6ecf"}, + {file = "propcache-0.4.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:60a8fda9644b7dfd5dece8c61d8a85e271cb958075bfc4e01083c148b61a7caf"}, + {file = "propcache-0.4.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c30b53e7e6bda1d547cabb47c825f3843a0a1a42b0496087bb58d8fedf9f41b5"}, + {file = "propcache-0.4.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:6918ecbd897443087a3b7cd978d56546a812517dcaaca51b49526720571fa93e"}, + {file = "propcache-0.4.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3d902a36df4e5989763425a8ab9e98cd8ad5c52c823b34ee7ef307fd50582566"}, + {file = "propcache-0.4.1-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a9695397f85973bb40427dedddf70d8dc4a44b22f1650dd4af9eedf443d45165"}, + {file = "propcache-0.4.1-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:2bb07ffd7eaad486576430c89f9b215f9e4be68c4866a96e97db9e97fead85dc"}, + {file = "propcache-0.4.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fd6f30fdcf9ae2a70abd34da54f18da086160e4d7d9251f81f3da0ff84fc5a48"}, + {file = "propcache-0.4.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:fc38cba02d1acba4e2869eef1a57a43dfbd3d49a59bf90dda7444ec2be6a5570"}, + {file = "propcache-0.4.1-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:67fad6162281e80e882fb3ec355398cf72864a54069d060321f6cd0ade95fe85"}, + {file = "propcache-0.4.1-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:f10207adf04d08bec185bae14d9606a1444715bc99180f9331c9c02093e1959e"}, + {file = "propcache-0.4.1-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:e9b0d8d0845bbc4cfcdcbcdbf5086886bc8157aa963c31c777ceff7846c77757"}, + {file = "propcache-0.4.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:981333cb2f4c1896a12f4ab92a9cc8f09ea664e9b7dbdc4eff74627af3a11c0f"}, + {file = "propcache-0.4.1-cp311-cp311-win32.whl", hash = "sha256:f1d2f90aeec838a52f1c1a32fe9a619fefd5e411721a9117fbf82aea638fe8a1"}, + {file = "propcache-0.4.1-cp311-cp311-win_amd64.whl", hash = "sha256:364426a62660f3f699949ac8c621aad6977be7126c5807ce48c0aeb8e7333ea6"}, + {file = "propcache-0.4.1-cp311-cp311-win_arm64.whl", hash = "sha256:e53f3a38d3510c11953f3e6a33f205c6d1b001129f972805ca9b42fc308bc239"}, + {file = "propcache-0.4.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:e153e9cd40cc8945138822807139367f256f89c6810c2634a4f6902b52d3b4e2"}, + {file = "propcache-0.4.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:cd547953428f7abb73c5ad82cbb32109566204260d98e41e5dfdc682eb7f8403"}, + {file = "propcache-0.4.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f048da1b4f243fc44f205dfd320933a951b8d89e0afd4c7cacc762a8b9165207"}, + {file = "propcache-0.4.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ec17c65562a827bba85e3872ead335f95405ea1674860d96483a02f5c698fa72"}, + {file = "propcache-0.4.1-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:405aac25c6394ef275dee4c709be43745d36674b223ba4eb7144bf4d691b7367"}, + {file = "propcache-0.4.1-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:0013cb6f8dde4b2a2f66903b8ba740bdfe378c943c4377a200551ceb27f379e4"}, + {file = "propcache-0.4.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:15932ab57837c3368b024473a525e25d316d8353016e7cc0e5ba9eb343fbb1cf"}, + {file = "propcache-0.4.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:031dce78b9dc099f4c29785d9cf5577a3faf9ebf74ecbd3c856a7b92768c3df3"}, + {file = "propcache-0.4.1-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:ab08df6c9a035bee56e31af99be621526bd237bea9f32def431c656b29e41778"}, + {file = "propcache-0.4.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:4d7af63f9f93fe593afbf104c21b3b15868efb2c21d07d8732c0c4287e66b6a6"}, + {file = "propcache-0.4.1-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:cfc27c945f422e8b5071b6e93169679e4eb5bf73bbcbf1ba3ae3a83d2f78ebd9"}, + {file = "propcache-0.4.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:35c3277624a080cc6ec6f847cbbbb5b49affa3598c4535a0a4682a697aaa5c75"}, + {file = "propcache-0.4.1-cp312-cp312-win32.whl", hash = "sha256:671538c2262dadb5ba6395e26c1731e1d52534bfe9ae56d0b5573ce539266aa8"}, + {file = "propcache-0.4.1-cp312-cp312-win_amd64.whl", hash = "sha256:cb2d222e72399fcf5890d1d5cc1060857b9b236adff2792ff48ca2dfd46c81db"}, + {file = "propcache-0.4.1-cp312-cp312-win_arm64.whl", hash = "sha256:204483131fb222bdaaeeea9f9e6c6ed0cac32731f75dfc1d4a567fc1926477c1"}, + {file = "propcache-0.4.1-py3-none-any.whl", hash = "sha256:af2a6052aeb6cf17d3e46ee169099044fd8224cbaf75c76a2ef596e8163e2237"}, + {file = "propcache-0.4.1.tar.gz", hash = "sha256:f48107a8c637e80362555f37ecf49abe20370e557cc4ab374f04ec4423c97c3d"}, ] [[package]] name = "psutil" -version = "7.0.0" +version = "7.1.3" requires_python = ">=3.6" -summary = "Cross-platform lib for process and system monitoring in Python. NOTE: the syntax of this script MUST be kept compatible with Python 2.7." +summary = "Cross-platform lib for process and system monitoring." files = [ - {file = "psutil-7.0.0-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:101d71dc322e3cffd7cea0650b09b3d08b8e7c4109dd6809fe452dfd00e58b25"}, - {file = "psutil-7.0.0-cp36-abi3-macosx_11_0_arm64.whl", hash = "sha256:39db632f6bb862eeccf56660871433e111b6ea58f2caea825571951d4b6aa3da"}, - {file = "psutil-7.0.0-cp36-abi3-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1fcee592b4c6f146991ca55919ea3d1f8926497a713ed7faaf8225e174581e91"}, - {file = "psutil-7.0.0-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4b1388a4f6875d7e2aff5c4ca1cc16c545ed41dd8bb596cefea80111db353a34"}, - {file = "psutil-7.0.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a5f098451abc2828f7dc6b58d44b532b22f2088f4999a937557b603ce72b1993"}, - {file = "psutil-7.0.0-cp37-abi3-win32.whl", hash = "sha256:ba3fcef7523064a6c9da440fc4d6bd07da93ac726b5733c29027d7dc95b39d99"}, - {file = "psutil-7.0.0-cp37-abi3-win_amd64.whl", hash = "sha256:4cf3d4eb1aa9b348dec30105c55cd9b7d4629285735a102beb4441e38db90553"}, - {file = "psutil-7.0.0.tar.gz", hash = "sha256:7be9c3eba38beccb6495ea33afd982a44074b78f28c434a1f51cc07fd315c456"}, + {file = "psutil-7.1.3-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:2bdbcd0e58ca14996a42adf3621a6244f1bb2e2e528886959c72cf1e326677ab"}, + {file = "psutil-7.1.3-cp36-abi3-macosx_11_0_arm64.whl", hash = "sha256:bc31fa00f1fbc3c3802141eede66f3a2d51d89716a194bf2cd6fc68310a19880"}, + {file = "psutil-7.1.3-cp36-abi3-manylinux2010_x86_64.manylinux_2_12_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3bb428f9f05c1225a558f53e30ccbad9930b11c3fc206836242de1091d3e7dd3"}, + {file = "psutil-7.1.3-cp36-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:56d974e02ca2c8eb4812c3f76c30e28836fffc311d55d979f1465c1feeb2b68b"}, + {file = "psutil-7.1.3-cp37-abi3-win_amd64.whl", hash = "sha256:f39c2c19fe824b47484b96f9692932248a54c43799a84282cfe58d05a6449efd"}, + {file = "psutil-7.1.3-cp37-abi3-win_arm64.whl", hash = "sha256:bd0d69cee829226a761e92f28140bec9a5ee9d5b4fb4b0cc589068dbfff559b1"}, + {file = "psutil-7.1.3.tar.gz", hash = "sha256:6c86281738d77335af7aec228328e944b30930899ea760ecf33a4dba66be5e74"}, ] [[package]] @@ -2515,29 +2831,25 @@ files = [ [[package]] name = "pyarrow" -version = "20.0.0" -requires_python = ">=3.9" +version = "22.0.0" +requires_python = ">=3.10" summary = "Python library for Apache Arrow" files = [ - {file = "pyarrow-20.0.0-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:24ca380585444cb2a31324c546a9a56abbe87e26069189e14bdba19c86c049f0"}, - {file = "pyarrow-20.0.0-cp311-cp311-macosx_12_0_x86_64.whl", hash = "sha256:95b330059ddfdc591a3225f2d272123be26c8fa76e8c9ee1a77aad507361cfdb"}, - {file = "pyarrow-20.0.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5f0fb1041267e9968c6d0d2ce3ff92e3928b243e2b6d11eeb84d9ac547308232"}, - {file = "pyarrow-20.0.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b8ff87cc837601532cc8242d2f7e09b4e02404de1b797aee747dd4ba4bd6313f"}, - {file = "pyarrow-20.0.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:7a3a5dcf54286e6141d5114522cf31dd67a9e7c9133d150799f30ee302a7a1ab"}, - {file = "pyarrow-20.0.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:a6ad3e7758ecf559900261a4df985662df54fb7fdb55e8e3b3aa99b23d526b62"}, - {file = "pyarrow-20.0.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:6bb830757103a6cb300a04610e08d9636f0cd223d32f388418ea893a3e655f1c"}, - {file = "pyarrow-20.0.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:96e37f0766ecb4514a899d9a3554fadda770fb57ddf42b63d80f14bc20aa7db3"}, - {file = "pyarrow-20.0.0-cp311-cp311-win_amd64.whl", hash = "sha256:3346babb516f4b6fd790da99b98bed9708e3f02e734c84971faccb20736848dc"}, - {file = "pyarrow-20.0.0-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:75a51a5b0eef32727a247707d4755322cb970be7e935172b6a3a9f9ae98404ba"}, - {file = "pyarrow-20.0.0-cp312-cp312-macosx_12_0_x86_64.whl", hash = "sha256:211d5e84cecc640c7a3ab900f930aaff5cd2702177e0d562d426fb7c4f737781"}, - {file = "pyarrow-20.0.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4ba3cf4182828be7a896cbd232aa8dd6a31bd1f9e32776cc3796c012855e1199"}, - {file = "pyarrow-20.0.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2c3a01f313ffe27ac4126f4c2e5ea0f36a5fc6ab51f8726cf41fee4b256680bd"}, - {file = "pyarrow-20.0.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:a2791f69ad72addd33510fec7bb14ee06c2a448e06b649e264c094c5b5f7ce28"}, - {file = "pyarrow-20.0.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:4250e28a22302ce8692d3a0e8ec9d9dde54ec00d237cff4dfa9c1fbf79e472a8"}, - {file = "pyarrow-20.0.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:89e030dc58fc760e4010148e6ff164d2f44441490280ef1e97a542375e41058e"}, - {file = "pyarrow-20.0.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:6102b4864d77102dbbb72965618e204e550135a940c2534711d5ffa787df2a5a"}, - {file = "pyarrow-20.0.0-cp312-cp312-win_amd64.whl", hash = "sha256:96d6a0a37d9c98be08f5ed6a10831d88d52cac7b13f5287f1e0f625a0de8062b"}, - {file = "pyarrow-20.0.0.tar.gz", hash = "sha256:febc4a913592573c8d5805091a6c2b5064c8bd6e002131f01061797d91c783c1"}, + {file = "pyarrow-22.0.0-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:3e294c5eadfb93d78b0763e859a0c16d4051fc1c5231ae8956d61cb0b5666f5a"}, + {file = "pyarrow-22.0.0-cp311-cp311-macosx_12_0_x86_64.whl", hash = "sha256:69763ab2445f632d90b504a815a2a033f74332997052b721002298ed6de40f2e"}, + {file = "pyarrow-22.0.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:b41f37cabfe2463232684de44bad753d6be08a7a072f6a83447eeaf0e4d2a215"}, + {file = "pyarrow-22.0.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:35ad0f0378c9359b3f297299c3309778bb03b8612f987399a0333a560b43862d"}, + {file = "pyarrow-22.0.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8382ad21458075c2e66a82a29d650f963ce51c7708c7c0ff313a8c206c4fd5e8"}, + {file = "pyarrow-22.0.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1a812a5b727bc09c3d7ea072c4eebf657c2f7066155506ba31ebf4792f88f016"}, + {file = "pyarrow-22.0.0-cp311-cp311-win_amd64.whl", hash = "sha256:ec5d40dd494882704fb876c16fa7261a69791e784ae34e6b5992e977bd2e238c"}, + {file = "pyarrow-22.0.0-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:bea79263d55c24a32b0d79c00a1c58bb2ee5f0757ed95656b01c0fb310c5af3d"}, + {file = "pyarrow-22.0.0-cp312-cp312-macosx_12_0_x86_64.whl", hash = "sha256:12fe549c9b10ac98c91cf791d2945e878875d95508e1a5d14091a7aaa66d9cf8"}, + {file = "pyarrow-22.0.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:334f900ff08ce0423407af97e6c26ad5d4e3b0763645559ece6fbf3747d6a8f5"}, + {file = "pyarrow-22.0.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:c6c791b09c57ed76a18b03f2631753a4960eefbbca80f846da8baefc6491fcfe"}, + {file = "pyarrow-22.0.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:c3200cb41cdbc65156e5f8c908d739b0dfed57e890329413da2748d1a2cd1a4e"}, + {file = "pyarrow-22.0.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ac93252226cf288753d8b46280f4edf3433bf9508b6977f8dd8526b521a1bbb9"}, + {file = "pyarrow-22.0.0-cp312-cp312-win_amd64.whl", hash = "sha256:44729980b6c50a5f2bfcc2668d36c569ce17f8b17bccaf470c4313dcbbf13c9d"}, + {file = "pyarrow-22.0.0.tar.gz", hash = "sha256:3d600dc583260d845c7d8a6db540339dd883081925da2bd1c5cb808f720b3cd9"}, ] [[package]] @@ -2552,12 +2864,85 @@ files = [ [[package]] name = "pycparser" -version = "2.22" +version = "2.23" requires_python = ">=3.8" summary = "C parser in Python" files = [ - {file = "pycparser-2.22-py3-none-any.whl", hash = "sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc"}, - {file = "pycparser-2.22.tar.gz", hash = "sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6"}, + {file = "pycparser-2.23-py3-none-any.whl", hash = "sha256:e5c6e8d3fbad53479cab09ac03729e0a9faf2bee3db8208a550daf5af81a5934"}, + {file = "pycparser-2.23.tar.gz", hash = "sha256:78816d4f24add8f10a06d6f05b4d424ad9e96cfebf68a4ddc99c65c0720d00c2"}, +] + +[[package]] +name = "pydantic" +version = "2.12.5" +requires_python = ">=3.9" +summary = "Data validation using Python type hints" +dependencies = [ + "annotated-types>=0.6.0", + "pydantic-core==2.41.5", + "typing-extensions>=4.14.1", + "typing-inspection>=0.4.2", +] +files = [ + {file = "pydantic-2.12.5-py3-none-any.whl", hash = "sha256:e561593fccf61e8a20fc46dfc2dfe075b8be7d0188df33f221ad1f0139180f9d"}, + {file = "pydantic-2.12.5.tar.gz", hash = "sha256:4d351024c75c0f085a9febbb665ce8c0c6ec5d30e903bdb6394b7ede26aebb49"}, +] + +[[package]] +name = "pydantic-core" +version = "2.41.5" +requires_python = ">=3.9" +summary = "Core functionality for Pydantic validation and serialization" +dependencies = [ + "typing-extensions>=4.14.1", +] +files = [ + {file = "pydantic_core-2.41.5-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:a3a52f6156e73e7ccb0f8cced536adccb7042be67cb45f9562e12b319c119da6"}, + {file = "pydantic_core-2.41.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7f3bf998340c6d4b0c9a2f02d6a400e51f123b59565d74dc60d252ce888c260b"}, + {file = "pydantic_core-2.41.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:378bec5c66998815d224c9ca994f1e14c0c21cb95d2f52b6021cc0b2a58f2a5a"}, + {file = "pydantic_core-2.41.5-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e7b576130c69225432866fe2f4a469a85a54ade141d96fd396dffcf607b558f8"}, + {file = "pydantic_core-2.41.5-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6cb58b9c66f7e4179a2d5e0f849c48eff5c1fca560994d6eb6543abf955a149e"}, + {file = "pydantic_core-2.41.5-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:88942d3a3dff3afc8288c21e565e476fc278902ae4d6d134f1eeda118cc830b1"}, + {file = "pydantic_core-2.41.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f31d95a179f8d64d90f6831d71fa93290893a33148d890ba15de25642c5d075b"}, + {file = "pydantic_core-2.41.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c1df3d34aced70add6f867a8cf413e299177e0c22660cc767218373d0779487b"}, + {file = "pydantic_core-2.41.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:4009935984bd36bd2c774e13f9a09563ce8de4abaa7226f5108262fa3e637284"}, + {file = "pydantic_core-2.41.5-cp311-cp311-musllinux_1_1_armv7l.whl", hash = "sha256:34a64bc3441dc1213096a20fe27e8e128bd3ff89921706e83c0b1ac971276594"}, + {file = "pydantic_core-2.41.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:c9e19dd6e28fdcaa5a1de679aec4141f691023916427ef9bae8584f9c2fb3b0e"}, + {file = "pydantic_core-2.41.5-cp311-cp311-win32.whl", hash = "sha256:2c010c6ded393148374c0f6f0bf89d206bf3217f201faa0635dcd56bd1520f6b"}, + {file = "pydantic_core-2.41.5-cp311-cp311-win_amd64.whl", hash = "sha256:76ee27c6e9c7f16f47db7a94157112a2f3a00e958bc626e2f4ee8bec5c328fbe"}, + {file = "pydantic_core-2.41.5-cp311-cp311-win_arm64.whl", hash = "sha256:4bc36bbc0b7584de96561184ad7f012478987882ebf9f9c389b23f432ea3d90f"}, + {file = "pydantic_core-2.41.5-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:f41a7489d32336dbf2199c8c0a215390a751c5b014c2c1c5366e817202e9cdf7"}, + {file = "pydantic_core-2.41.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:070259a8818988b9a84a449a2a7337c7f430a22acc0859c6b110aa7212a6d9c0"}, + {file = "pydantic_core-2.41.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e96cea19e34778f8d59fe40775a7a574d95816eb150850a85a7a4c8f4b94ac69"}, + {file = "pydantic_core-2.41.5-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ed2e99c456e3fadd05c991f8f437ef902e00eedf34320ba2b0842bd1c3ca3a75"}, + {file = "pydantic_core-2.41.5-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:65840751b72fbfd82c3c640cff9284545342a4f1eb1586ad0636955b261b0b05"}, + {file = "pydantic_core-2.41.5-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e536c98a7626a98feb2d3eaf75944ef6f3dbee447e1f841eae16f2f0a72d8ddc"}, + {file = "pydantic_core-2.41.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eceb81a8d74f9267ef4081e246ffd6d129da5d87e37a77c9bde550cb04870c1c"}, + {file = "pydantic_core-2.41.5-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d38548150c39b74aeeb0ce8ee1d8e82696f4a4e16ddc6de7b1d8823f7de4b9b5"}, + {file = "pydantic_core-2.41.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:c23e27686783f60290e36827f9c626e63154b82b116d7fe9adba1fda36da706c"}, + {file = "pydantic_core-2.41.5-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:482c982f814460eabe1d3bb0adfdc583387bd4691ef00b90575ca0d2b6fe2294"}, + {file = "pydantic_core-2.41.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:bfea2a5f0b4d8d43adf9d7b8bf019fb46fdd10a2e5cde477fbcb9d1fa08c68e1"}, + {file = "pydantic_core-2.41.5-cp312-cp312-win32.whl", hash = "sha256:b74557b16e390ec12dca509bce9264c3bbd128f8a2c376eaa68003d7f327276d"}, + {file = "pydantic_core-2.41.5-cp312-cp312-win_amd64.whl", hash = "sha256:1962293292865bca8e54702b08a4f26da73adc83dd1fcf26fbc875b35d81c815"}, + {file = "pydantic_core-2.41.5-cp312-cp312-win_arm64.whl", hash = "sha256:1746d4a3d9a794cacae06a5eaaccb4b8643a131d45fbc9af23e353dc0a5ba5c3"}, + {file = "pydantic_core-2.41.5-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:b2379fa7ed44ddecb5bfe4e48577d752db9fc10be00a6b7446e9663ba143de26"}, + {file = "pydantic_core-2.41.5-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:266fb4cbf5e3cbd0b53669a6d1b039c45e3ce651fd5442eff4d07c2cc8d66808"}, + {file = "pydantic_core-2.41.5-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:58133647260ea01e4d0500089a8c4f07bd7aa6ce109682b1426394988d8aaacc"}, + {file = "pydantic_core-2.41.5-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:287dad91cfb551c363dc62899a80e9e14da1f0e2b6ebde82c806612ca2a13ef1"}, + {file = "pydantic_core-2.41.5-pp311-pypy311_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:03b77d184b9eb40240ae9fd676ca364ce1085f203e1b1256f8ab9984dca80a84"}, + {file = "pydantic_core-2.41.5-pp311-pypy311_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:a668ce24de96165bb239160b3d854943128f4334822900534f2fe947930e5770"}, + {file = "pydantic_core-2.41.5-pp311-pypy311_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:f14f8f046c14563f8eb3f45f499cc658ab8d10072961e07225e507adb700e93f"}, + {file = "pydantic_core-2.41.5-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:56121965f7a4dc965bff783d70b907ddf3d57f6eba29b6d2e5dabfaf07799c51"}, + {file = "pydantic_core-2.41.5.tar.gz", hash = "sha256:08daa51ea16ad373ffd5e7606252cc32f07bc72b28284b6bc9c6df804816476e"}, +] + +[[package]] +name = "pyelftools" +version = "0.32" +summary = "Library for analyzing ELF files and DWARF debugging information" +files = [ + {file = "pyelftools-0.32-py3-none-any.whl", hash = "sha256:013df952a006db5e138b1edf6d8a68ecc50630adbd0d83a2d41e7f846163d738"}, + {file = "pyelftools-0.32.tar.gz", hash = "sha256:6de90ee7b8263e740c8715a925382d4099b354f29ac48ea40d840cf7aa14ace5"}, ] [[package]] @@ -2572,22 +2957,32 @@ files = [ [[package]] name = "pygments" -version = "2.19.1" +version = "2.19.2" requires_python = ">=3.8" summary = "Pygments is a syntax highlighting package written in Python." files = [ - {file = "pygments-2.19.1-py3-none-any.whl", hash = "sha256:9ea1544ad55cecf4b8242fab6dd35a93bbce657034b0611ee383099054ab6d8c"}, - {file = "pygments-2.19.1.tar.gz", hash = "sha256:61c16d2a8576dc0649d9f39e089b5f02bcd27fba10d8fb4dcc28173f7a45151f"}, + {file = "pygments-2.19.2-py3-none-any.whl", hash = "sha256:86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b"}, + {file = "pygments-2.19.2.tar.gz", hash = "sha256:636cb2477cec7f8952536970bc533bc43743542f70392ae026374600add5b887"}, ] [[package]] name = "pyparsing" -version = "3.2.3" +version = "3.2.5" requires_python = ">=3.9" -summary = "pyparsing module - Classes and methods to define and execute parsing grammars" +summary = "pyparsing - Classes and methods to define and execute parsing grammars" +files = [ + {file = "pyparsing-3.2.5-py3-none-any.whl", hash = "sha256:e38a4f02064cf41fe6593d328d0512495ad1f3d8a91c4f73fc401b3079a59a5e"}, + {file = "pyparsing-3.2.5.tar.gz", hash = "sha256:2df8d5b7b2802ef88e8d016a2eb9c7aeaa923529cd251ed0fe4608275d4105b6"}, +] + +[[package]] +name = "pyproject-hooks" +version = "1.2.0" +requires_python = ">=3.7" +summary = "Wrappers to call pyproject.toml-based build backend hooks." files = [ - {file = "pyparsing-3.2.3-py3-none-any.whl", hash = "sha256:a749938e02d6fd0b59b356ca504a24982314bb090c383e3cf201c95ef7e2bfcf"}, - {file = "pyparsing-3.2.3.tar.gz", hash = "sha256:b9c13f1ab8b3b542f72e28f634bad4de758ab3ce4546e4301970ad6fa77c38be"}, + {file = "pyproject_hooks-1.2.0-py3-none-any.whl", hash = "sha256:9e5c6bfa8dcc30091c74b0cf803c81fdd29d94f01992a7707bc97babb1141913"}, + {file = "pyproject_hooks-1.2.0.tar.gz", hash = "sha256:1e859bd5c40fae9448642dd871adf459e5e2084186e8d2c2a79a824c970da1f8"}, ] [[package]] @@ -2710,29 +3105,29 @@ files = [ [[package]] name = "pytest-runtime-xfail" -version = "1.0.3" -requires_python = ">=3.7" +version = "1.1.1" +requires_python = ">=3.8" summary = "Call runtime_xfail() to mark running test as xfail." dependencies = [ "pytest>=5.0.0", ] files = [ - {file = "pytest-runtime-xfail-1.0.3.tar.gz", hash = "sha256:5eefc17e499bd639ddc2734c588166b2f59649454cd5921efb9243268894f09d"}, - {file = "pytest_runtime_xfail-1.0.3-py3-none-any.whl", hash = "sha256:84aa805f8a5beb82a6f26a018ce5502909cb27a0193c9e5c7123bcd5fbb6787b"}, + {file = "pytest_runtime_xfail-1.1.1-py3-none-any.whl", hash = "sha256:1927a7505367668bbf0a85ceb9224167bc6335bf24bb2b78b40cca311c6aeb6a"}, + {file = "pytest_runtime_xfail-1.1.1.tar.gz", hash = "sha256:773c013dea99700c82e71333b966a20254491a255ced3c4c72bc7ce1c339cf1b"}, ] [[package]] name = "pytest-xdist" -version = "3.6.1" -requires_python = ">=3.8" +version = "3.8.0" +requires_python = ">=3.9" summary = "pytest xdist plugin for distributed testing, most importantly across multiple CPUs" dependencies = [ "execnet>=2.1", "pytest>=7.0.0", ] files = [ - {file = "pytest_xdist-3.6.1-py3-none-any.whl", hash = "sha256:9ed4adfb68a016610848639bb7e02c9352d5d9f03d04809919e2dafc3be4cca7"}, - {file = "pytest_xdist-3.6.1.tar.gz", hash = "sha256:ead156a4db231eec769737f57668ef58a2084a34b2e55c4a8fa20d861107300d"}, + {file = "pytest_xdist-3.8.0-py3-none-any.whl", hash = "sha256:202ca578cfeb7370784a8c33d6d05bc6e13b4f25b5053c30a152269fd10f0b88"}, + {file = "pytest_xdist-3.8.0.tar.gz", hash = "sha256:7e578125ec9bc6050861aa93f2d59f1d8d085595d6551c2c90b6f4fad8d3a9f1"}, ] [[package]] @@ -2750,28 +3145,28 @@ files = [ [[package]] name = "python-json-logger" -version = "3.3.0" +version = "4.0.0" requires_python = ">=3.8" summary = "JSON Log Formatter for the Python Logging Package" dependencies = [ "typing-extensions; python_version < \"3.10\"", ] files = [ - {file = "python_json_logger-3.3.0-py3-none-any.whl", hash = "sha256:dd980fae8cffb24c13caf6e158d3d61c0d6d22342f932cb6e9deedab3d35eec7"}, - {file = "python_json_logger-3.3.0.tar.gz", hash = "sha256:12b7e74b17775e7d565129296105bbe3910842d9d0eb083fc83a6a617aa8df84"}, + {file = "python_json_logger-4.0.0-py3-none-any.whl", hash = "sha256:af09c9daf6a813aa4cc7180395f50f2a9e5fa056034c9953aec92e381c5ba1e2"}, + {file = "python_json_logger-4.0.0.tar.gz", hash = "sha256:f58e68eb46e1faed27e0f574a55a0455eecd7b8a5b88b85a784519ba3cff047f"}, ] [[package]] name = "python-levenshtein" -version = "0.27.1" -requires_python = ">=3.9" +version = "0.27.3" +requires_python = ">=3.10" summary = "Python extension for computing string edit distances and similarities." dependencies = [ - "Levenshtein==0.27.1", + "Levenshtein==0.27.3", ] files = [ - {file = "python_levenshtein-0.27.1-py3-none-any.whl", hash = "sha256:e1a4bc2a70284b2ebc4c505646142fecd0f831e49aa04ed972995895aec57396"}, - {file = "python_levenshtein-0.27.1.tar.gz", hash = "sha256:3a5314a011016d373d309a68e875fd029caaa692ad3f32e78319299648045f11"}, + {file = "python_levenshtein-0.27.3-py3-none-any.whl", hash = "sha256:5d6168a8e8befb25abf04d2952368a446722be10e8ced218d0dc4fd3703a43a1"}, + {file = "python_levenshtein-0.27.3.tar.gz", hash = "sha256:27dc2d65aeb62a7d6852388f197073296370779286c0860b087357f3b8129a62"}, ] [[package]] @@ -2785,156 +3180,133 @@ files = [ [[package]] name = "pyviz-comms" -version = "3.0.4" +version = "3.0.6" requires_python = ">=3.8" summary = "A JupyterLab extension for rendering HoloViz content." dependencies = [ "param", ] files = [ - {file = "pyviz_comms-3.0.4-py3-none-any.whl", hash = "sha256:a40d17db26ec13cf975809633804e712bd24b473e77388c193c44043f85d0b25"}, - {file = "pyviz_comms-3.0.4.tar.gz", hash = "sha256:d70e17555f7262c4884a6b7bc9ca19cb816507a032a334d9cb411b4546caff4c"}, -] - -[[package]] -name = "pywin32" -version = "310" -summary = "Python for Window Extensions" -files = [ - {file = "pywin32-310-cp311-cp311-win32.whl", hash = "sha256:1e765f9564e83011a63321bb9d27ec456a0ed90d3732c4b2e312b855365ed8bd"}, - {file = "pywin32-310-cp311-cp311-win_amd64.whl", hash = "sha256:126298077a9d7c95c53823934f000599f66ec9296b09167810eb24875f32689c"}, - {file = "pywin32-310-cp311-cp311-win_arm64.whl", hash = "sha256:19ec5fc9b1d51c4350be7bb00760ffce46e6c95eaf2f0b2f1150657b1a43c582"}, - {file = "pywin32-310-cp312-cp312-win32.whl", hash = "sha256:8a75a5cc3893e83a108c05d82198880704c44bbaee4d06e442e471d3c9ea4f3d"}, - {file = "pywin32-310-cp312-cp312-win_amd64.whl", hash = "sha256:bf5c397c9a9a19a6f62f3fb821fbf36cac08f03770056711f765ec1503972060"}, - {file = "pywin32-310-cp312-cp312-win_arm64.whl", hash = "sha256:2349cc906eae872d0663d4d6290d13b90621eaf78964bb1578632ff20e152966"}, + {file = "pyviz_comms-3.0.6-py3-none-any.whl", hash = "sha256:4eba6238cd4a7f4add2d11879ce55411785b7d38a7c5dba42c7a0826ca53e6c2"}, + {file = "pyviz_comms-3.0.6.tar.gz", hash = "sha256:73d66b620390d97959b2c4d8a2c0778d41fe20581be4717f01e46b8fae8c5695"}, ] [[package]] name = "pywinpty" -version = "2.0.15" +version = "3.0.2" requires_python = ">=3.9" summary = "Pseudo terminal support for Windows from Python." files = [ - {file = "pywinpty-2.0.15-cp311-cp311-win_amd64.whl", hash = "sha256:9a6bcec2df2707aaa9d08b86071970ee32c5026e10bcc3cc5f6f391d85baf7ca"}, - {file = "pywinpty-2.0.15-cp312-cp312-win_amd64.whl", hash = "sha256:83a8f20b430bbc5d8957249f875341a60219a4e971580f2ba694fbfb54a45ebc"}, - {file = "pywinpty-2.0.15.tar.gz", hash = "sha256:312cf39153a8736c617d45ce8b6ad6cd2107de121df91c455b10ce6bba7a39b2"}, + {file = "pywinpty-3.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:327790d70e4c841ebd9d0f295a780177149aeb405bca44c7115a3de5c2054b23"}, + {file = "pywinpty-3.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:99fdd9b455f0ad6419aba6731a7a0d2f88ced83c3c94a80ff9533d95fa8d8a9e"}, + {file = "pywinpty-3.0.2.tar.gz", hash = "sha256:1505cc4cb248af42cb6285a65c9c2086ee9e7e574078ee60933d5d7fa86fb004"}, ] [[package]] name = "pyyaml" -version = "6.0.2" +version = "6.0.3" requires_python = ">=3.8" summary = "YAML parser and emitter for Python" files = [ - {file = "PyYAML-6.0.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:cc1c1159b3d456576af7a3e4d1ba7e6924cb39de8f67111c735f6fc832082774"}, - {file = "PyYAML-6.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1e2120ef853f59c7419231f3bf4e7021f1b936f6ebd222406c3b60212205d2ee"}, - {file = "PyYAML-6.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5d225db5a45f21e78dd9358e58a98702a0302f2659a3c6cd320564b75b86f47c"}, - {file = "PyYAML-6.0.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5ac9328ec4831237bec75defaf839f7d4564be1e6b25ac710bd1a96321cc8317"}, - {file = "PyYAML-6.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ad2a3decf9aaba3d29c8f537ac4b243e36bef957511b4766cb0057d32b0be85"}, - {file = "PyYAML-6.0.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:ff3824dc5261f50c9b0dfb3be22b4567a6f938ccce4587b38952d85fd9e9afe4"}, - {file = "PyYAML-6.0.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:797b4f722ffa07cc8d62053e4cff1486fa6dc094105d13fea7b1de7d8bf71c9e"}, - {file = "PyYAML-6.0.2-cp311-cp311-win32.whl", hash = "sha256:11d8f3dd2b9c1207dcaf2ee0bbbfd5991f571186ec9cc78427ba5bd32afae4b5"}, - {file = "PyYAML-6.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:e10ce637b18caea04431ce14fabcf5c64a1c61ec9c56b071a4b7ca131ca52d44"}, - {file = "PyYAML-6.0.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:c70c95198c015b85feafc136515252a261a84561b7b1d51e3384e0655ddf25ab"}, - {file = "PyYAML-6.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ce826d6ef20b1bc864f0a68340c8b3287705cae2f8b4b1d932177dcc76721725"}, - {file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f71ea527786de97d1a0cc0eacd1defc0985dcf6b3f17bb77dcfc8c34bec4dc5"}, - {file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9b22676e8097e9e22e36d6b7bda33190d0d400f345f23d4065d48f4ca7ae0425"}, - {file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:80bab7bfc629882493af4aa31a4cfa43a4c57c83813253626916b8c7ada83476"}, - {file = "PyYAML-6.0.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:0833f8694549e586547b576dcfaba4a6b55b9e96098b36cdc7ebefe667dfed48"}, - {file = "PyYAML-6.0.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8b9c7197f7cb2738065c481a0461e50ad02f18c78cd75775628afb4d7137fb3b"}, - {file = "PyYAML-6.0.2-cp312-cp312-win32.whl", hash = "sha256:ef6107725bd54b262d6dedcc2af448a266975032bc85ef0172c5f059da6325b4"}, - {file = "PyYAML-6.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:7e7401d0de89a9a855c839bc697c079a4af81cf878373abd7dc625847d25cbd8"}, - {file = "pyyaml-6.0.2.tar.gz", hash = "sha256:d584d9ec91ad65861cc08d42e834324ef890a082e591037abe114850ff7bbc3e"}, + {file = "pyyaml-6.0.3-cp311-cp311-macosx_10_13_x86_64.whl", hash = "sha256:44edc647873928551a01e7a563d7452ccdebee747728c1080d881d68af7b997e"}, + {file = "pyyaml-6.0.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:652cb6edd41e718550aad172851962662ff2681490a8a711af6a4d288dd96824"}, + {file = "pyyaml-6.0.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:10892704fc220243f5305762e276552a0395f7beb4dbf9b14ec8fd43b57f126c"}, + {file = "pyyaml-6.0.3-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:850774a7879607d3a6f50d36d04f00ee69e7fc816450e5f7e58d7f17f1ae5c00"}, + {file = "pyyaml-6.0.3-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b8bb0864c5a28024fac8a632c443c87c5aa6f215c0b126c449ae1a150412f31d"}, + {file = "pyyaml-6.0.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1d37d57ad971609cf3c53ba6a7e365e40660e3be0e5175fa9f2365a379d6095a"}, + {file = "pyyaml-6.0.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:37503bfbfc9d2c40b344d06b2199cf0e96e97957ab1c1b546fd4f87e53e5d3e4"}, + {file = "pyyaml-6.0.3-cp311-cp311-win32.whl", hash = "sha256:8098f252adfa6c80ab48096053f512f2321f0b998f98150cea9bd23d83e1467b"}, + {file = "pyyaml-6.0.3-cp311-cp311-win_amd64.whl", hash = "sha256:9f3bfb4965eb874431221a3ff3fdcddc7e74e3b07799e0e84ca4a0f867d449bf"}, + {file = "pyyaml-6.0.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:7f047e29dcae44602496db43be01ad42fc6f1cc0d8cd6c83d342306c32270196"}, + {file = "pyyaml-6.0.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:fc09d0aa354569bc501d4e787133afc08552722d3ab34836a80547331bb5d4a0"}, + {file = "pyyaml-6.0.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9149cad251584d5fb4981be1ecde53a1ca46c891a79788c0df828d2f166bda28"}, + {file = "pyyaml-6.0.3-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:5fdec68f91a0c6739b380c83b951e2c72ac0197ace422360e6d5a959d8d97b2c"}, + {file = "pyyaml-6.0.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ba1cc08a7ccde2d2ec775841541641e4548226580ab850948cbfda66a1befcdc"}, + {file = "pyyaml-6.0.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:8dc52c23056b9ddd46818a57b78404882310fb473d63f17b07d5c40421e47f8e"}, + {file = "pyyaml-6.0.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:41715c910c881bc081f1e8872880d3c650acf13dfa8214bad49ed4cede7c34ea"}, + {file = "pyyaml-6.0.3-cp312-cp312-win32.whl", hash = "sha256:96b533f0e99f6579b3d4d4995707cf36df9100d67e0c8303a0c55b27b5f99bc5"}, + {file = "pyyaml-6.0.3-cp312-cp312-win_amd64.whl", hash = "sha256:5fcd34e47f6e0b794d17de1b4ff496c00986e1c83f7ab2fb8fcfe9616ff7477b"}, + {file = "pyyaml-6.0.3-cp312-cp312-win_arm64.whl", hash = "sha256:64386e5e707d03a7e172c0701abfb7e10f0fb753ee1d773128192742712a98fd"}, + {file = "pyyaml-6.0.3.tar.gz", hash = "sha256:d76623373421df22fb4cf8817020cbb7ef15c725b9d5e45f17e189bfc384190f"}, ] [[package]] name = "pyzmq" -version = "26.4.0" +version = "27.1.0" requires_python = ">=3.8" summary = "Python bindings for 0MQ" dependencies = [ "cffi; implementation_name == \"pypy\"", ] files = [ - {file = "pyzmq-26.4.0-cp311-cp311-macosx_10_15_universal2.whl", hash = "sha256:bfcf82644c9b45ddd7cd2a041f3ff8dce4a0904429b74d73a439e8cab1bd9e54"}, - {file = "pyzmq-26.4.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e9bcae3979b2654d5289d3490742378b2f3ce804b0b5fd42036074e2bf35b030"}, - {file = "pyzmq-26.4.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ccdff8ac4246b6fb60dcf3982dfaeeff5dd04f36051fe0632748fc0aa0679c01"}, - {file = "pyzmq-26.4.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4550af385b442dc2d55ab7717837812799d3674cb12f9a3aa897611839c18e9e"}, - {file = "pyzmq-26.4.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:2f9f7ffe9db1187a253fca95191854b3fda24696f086e8789d1d449308a34b88"}, - {file = "pyzmq-26.4.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:3709c9ff7ba61589b7372923fd82b99a81932b592a5c7f1a24147c91da9a68d6"}, - {file = "pyzmq-26.4.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:f8f3c30fb2d26ae5ce36b59768ba60fb72507ea9efc72f8f69fa088450cff1df"}, - {file = "pyzmq-26.4.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:382a4a48c8080e273427fc692037e3f7d2851959ffe40864f2db32646eeb3cef"}, - {file = "pyzmq-26.4.0-cp311-cp311-win32.whl", hash = "sha256:d56aad0517d4c09e3b4f15adebba8f6372c5102c27742a5bdbfc74a7dceb8fca"}, - {file = "pyzmq-26.4.0-cp311-cp311-win_amd64.whl", hash = "sha256:963977ac8baed7058c1e126014f3fe58b3773f45c78cce7af5c26c09b6823896"}, - {file = "pyzmq-26.4.0-cp311-cp311-win_arm64.whl", hash = "sha256:c0c8e8cadc81e44cc5088fcd53b9b3b4ce9344815f6c4a03aec653509296fae3"}, - {file = "pyzmq-26.4.0-cp312-cp312-macosx_10_15_universal2.whl", hash = "sha256:5227cb8da4b6f68acfd48d20c588197fd67745c278827d5238c707daf579227b"}, - {file = "pyzmq-26.4.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e1c07a7fa7f7ba86554a2b1bef198c9fed570c08ee062fd2fd6a4dcacd45f905"}, - {file = "pyzmq-26.4.0-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ae775fa83f52f52de73183f7ef5395186f7105d5ed65b1ae65ba27cb1260de2b"}, - {file = "pyzmq-26.4.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:66c760d0226ebd52f1e6b644a9e839b5db1e107a23f2fcd46ec0569a4fdd4e63"}, - {file = "pyzmq-26.4.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:ef8c6ecc1d520debc147173eaa3765d53f06cd8dbe7bd377064cdbc53ab456f5"}, - {file = "pyzmq-26.4.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:3150ef4084e163dec29ae667b10d96aad309b668fac6810c9e8c27cf543d6e0b"}, - {file = "pyzmq-26.4.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:4448c9e55bf8329fa1dcedd32f661bf611214fa70c8e02fee4347bc589d39a84"}, - {file = "pyzmq-26.4.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:e07dde3647afb084d985310d067a3efa6efad0621ee10826f2cb2f9a31b89d2f"}, - {file = "pyzmq-26.4.0-cp312-cp312-win32.whl", hash = "sha256:ba034a32ecf9af72adfa5ee383ad0fd4f4e38cdb62b13624278ef768fe5b5b44"}, - {file = "pyzmq-26.4.0-cp312-cp312-win_amd64.whl", hash = "sha256:056a97aab4064f526ecb32f4343917a4022a5d9efb6b9df990ff72e1879e40be"}, - {file = "pyzmq-26.4.0-cp312-cp312-win_arm64.whl", hash = "sha256:2f23c750e485ce1eb639dbd576d27d168595908aa2d60b149e2d9e34c9df40e0"}, - {file = "pyzmq-26.4.0-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:4478b14cb54a805088299c25a79f27eaf530564a7a4f72bf432a040042b554eb"}, - {file = "pyzmq-26.4.0-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8a28ac29c60e4ba84b5f58605ace8ad495414a724fe7aceb7cf06cd0598d04e1"}, - {file = "pyzmq-26.4.0-pp311-pypy311_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:43b03c1ceea27c6520124f4fb2ba9c647409b9abdf9a62388117148a90419494"}, - {file = "pyzmq-26.4.0-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7731abd23a782851426d4e37deb2057bf9410848a4459b5ede4fe89342e687a9"}, - {file = "pyzmq-26.4.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:a222ad02fbe80166b0526c038776e8042cd4e5f0dec1489a006a1df47e9040e0"}, - {file = "pyzmq-26.4.0.tar.gz", hash = "sha256:4bd13f85f80962f91a651a7356fe0472791a5f7a92f227822b5acf44795c626d"}, + {file = "pyzmq-27.1.0-cp311-cp311-macosx_10_15_universal2.whl", hash = "sha256:226b091818d461a3bef763805e75685e478ac17e9008f49fce2d3e52b3d58b86"}, + {file = "pyzmq-27.1.0-cp311-cp311-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:0790a0161c281ca9723f804871b4027f2e8b5a528d357c8952d08cd1a9c15581"}, + {file = "pyzmq-27.1.0-cp311-cp311-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c895a6f35476b0c3a54e3eb6ccf41bf3018de937016e6e18748317f25d4e925f"}, + {file = "pyzmq-27.1.0-cp311-cp311-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5bbf8d3630bf96550b3be8e1fc0fea5cbdc8d5466c1192887bd94869da17a63e"}, + {file = "pyzmq-27.1.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:15c8bd0fe0dabf808e2d7a681398c4e5ded70a551ab47482067a572c054c8e2e"}, + {file = "pyzmq-27.1.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:bafcb3dd171b4ae9f19ee6380dfc71ce0390fefaf26b504c0e5f628d7c8c54f2"}, + {file = "pyzmq-27.1.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:e829529fcaa09937189178115c49c504e69289abd39967cd8a4c215761373394"}, + {file = "pyzmq-27.1.0-cp311-cp311-win32.whl", hash = "sha256:6df079c47d5902af6db298ec92151db82ecb557af663098b92f2508c398bb54f"}, + {file = "pyzmq-27.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:190cbf120fbc0fc4957b56866830def56628934a9d112aec0e2507aa6a032b97"}, + {file = "pyzmq-27.1.0-cp311-cp311-win_arm64.whl", hash = "sha256:eca6b47df11a132d1745eb3b5b5e557a7dae2c303277aa0e69c6ba91b8736e07"}, + {file = "pyzmq-27.1.0-cp312-abi3-macosx_10_15_universal2.whl", hash = "sha256:452631b640340c928fa343801b0d07eb0c3789a5ffa843f6e1a9cee0ba4eb4fc"}, + {file = "pyzmq-27.1.0-cp312-abi3-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:1c179799b118e554b66da67d88ed66cd37a169f1f23b5d9f0a231b4e8d44a113"}, + {file = "pyzmq-27.1.0-cp312-abi3-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3837439b7f99e60312f0c926a6ad437b067356dc2bc2ec96eb395fd0fe804233"}, + {file = "pyzmq-27.1.0-cp312-abi3-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:43ad9a73e3da1fab5b0e7e13402f0b2fb934ae1c876c51d0afff0e7c052eca31"}, + {file = "pyzmq-27.1.0-cp312-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:0de3028d69d4cdc475bfe47a6128eb38d8bc0e8f4d69646adfbcd840facbac28"}, + {file = "pyzmq-27.1.0-cp312-abi3-musllinux_1_2_i686.whl", hash = "sha256:cf44a7763aea9298c0aa7dbf859f87ed7012de8bda0f3977b6fb1d96745df856"}, + {file = "pyzmq-27.1.0-cp312-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:f30f395a9e6fbca195400ce833c731e7b64c3919aa481af4d88c3759e0cb7496"}, + {file = "pyzmq-27.1.0-cp312-abi3-win32.whl", hash = "sha256:250e5436a4ba13885494412b3da5d518cd0d3a278a1ae640e113c073a5f88edd"}, + {file = "pyzmq-27.1.0-cp312-abi3-win_amd64.whl", hash = "sha256:9ce490cf1d2ca2ad84733aa1d69ce6855372cb5ce9223802450c9b2a7cba0ccf"}, + {file = "pyzmq-27.1.0-cp312-abi3-win_arm64.whl", hash = "sha256:75a2f36223f0d535a0c919e23615fc85a1e23b71f40c7eb43d7b1dedb4d8f15f"}, + {file = "pyzmq-27.1.0-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:18770c8d3563715387139060d37859c02ce40718d1faf299abddcdcc6a649066"}, + {file = "pyzmq-27.1.0-pp311-pypy311_pp73-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:ac25465d42f92e990f8d8b0546b01c391ad431c3bf447683fdc40565941d0604"}, + {file = "pyzmq-27.1.0-pp311-pypy311_pp73-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:53b40f8ae006f2734ee7608d59ed661419f087521edbfc2149c3932e9c14808c"}, + {file = "pyzmq-27.1.0-pp311-pypy311_pp73-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f605d884e7c8be8fe1aa94e0a783bf3f591b84c24e4bc4f3e7564c82ac25e271"}, + {file = "pyzmq-27.1.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:c9f7f6e13dff2e44a6afeaf2cf54cee5929ad64afaf4d40b50f93c58fc687355"}, + {file = "pyzmq-27.1.0.tar.gz", hash = "sha256:ac0765e3d44455adb6ddbf4417dcce460fc40a05978c08efdf2948072f6db540"}, ] [[package]] name = "rapidfuzz" -version = "3.13.0" -requires_python = ">=3.9" +version = "3.14.3" +requires_python = ">=3.10" summary = "rapid fuzzy string matching" files = [ - {file = "rapidfuzz-3.13.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d395a5cad0c09c7f096433e5fd4224d83b53298d53499945a9b0e5a971a84f3a"}, - {file = "rapidfuzz-3.13.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:b7b3eda607a019169f7187328a8d1648fb9a90265087f6903d7ee3a8eee01805"}, - {file = "rapidfuzz-3.13.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:98e0bfa602e1942d542de077baf15d658bd9d5dcfe9b762aff791724c1c38b70"}, - {file = "rapidfuzz-3.13.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bef86df6d59667d9655905b02770a0c776d2853971c0773767d5ef8077acd624"}, - {file = "rapidfuzz-3.13.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fedd316c165beed6307bf754dee54d3faca2c47e1f3bcbd67595001dfa11e969"}, - {file = "rapidfuzz-3.13.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5158da7f2ec02a930be13bac53bb5903527c073c90ee37804090614cab83c29e"}, - {file = "rapidfuzz-3.13.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3b6f913ee4618ddb6d6f3e387b76e8ec2fc5efee313a128809fbd44e65c2bbb2"}, - {file = "rapidfuzz-3.13.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d25fdbce6459ccbbbf23b4b044f56fbd1158b97ac50994eaae2a1c0baae78301"}, - {file = "rapidfuzz-3.13.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:25343ccc589a4579fbde832e6a1e27258bfdd7f2eb0f28cb836d6694ab8591fc"}, - {file = "rapidfuzz-3.13.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:a9ad1f37894e3ffb76bbab76256e8a8b789657183870be11aa64e306bb5228fd"}, - {file = "rapidfuzz-3.13.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:5dc71ef23845bb6b62d194c39a97bb30ff171389c9812d83030c1199f319098c"}, - {file = "rapidfuzz-3.13.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:b7f4c65facdb94f44be759bbd9b6dda1fa54d0d6169cdf1a209a5ab97d311a75"}, - {file = "rapidfuzz-3.13.0-cp311-cp311-win32.whl", hash = "sha256:b5104b62711565e0ff6deab2a8f5dbf1fbe333c5155abe26d2cfd6f1849b6c87"}, - {file = "rapidfuzz-3.13.0-cp311-cp311-win_amd64.whl", hash = "sha256:9093cdeb926deb32a4887ebe6910f57fbcdbc9fbfa52252c10b56ef2efb0289f"}, - {file = "rapidfuzz-3.13.0-cp311-cp311-win_arm64.whl", hash = "sha256:f70f646751b6aa9d05be1fb40372f006cc89d6aad54e9d79ae97bd1f5fce5203"}, - {file = "rapidfuzz-3.13.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:4a1a6a906ba62f2556372282b1ef37b26bca67e3d2ea957277cfcefc6275cca7"}, - {file = "rapidfuzz-3.13.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2fd0975e015b05c79a97f38883a11236f5a24cca83aa992bd2558ceaa5652b26"}, - {file = "rapidfuzz-3.13.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5d4e13593d298c50c4f94ce453f757b4b398af3fa0fd2fde693c3e51195b7f69"}, - {file = "rapidfuzz-3.13.0-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ed6f416bda1c9133000009d84d9409823eb2358df0950231cc936e4bf784eb97"}, - {file = "rapidfuzz-3.13.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1dc82b6ed01acb536b94a43996a94471a218f4d89f3fdd9185ab496de4b2a981"}, - {file = "rapidfuzz-3.13.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e9d824de871daa6e443b39ff495a884931970d567eb0dfa213d234337343835f"}, - {file = "rapidfuzz-3.13.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2d18228a2390375cf45726ce1af9d36ff3dc1f11dce9775eae1f1b13ac6ec50f"}, - {file = "rapidfuzz-3.13.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:9f5fe634c9482ec5d4a6692afb8c45d370ae86755e5f57aa6c50bfe4ca2bdd87"}, - {file = "rapidfuzz-3.13.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:694eb531889f71022b2be86f625a4209c4049e74be9ca836919b9e395d5e33b3"}, - {file = "rapidfuzz-3.13.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:11b47b40650e06147dee5e51a9c9ad73bb7b86968b6f7d30e503b9f8dd1292db"}, - {file = "rapidfuzz-3.13.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:98b8107ff14f5af0243f27d236bcc6e1ef8e7e3b3c25df114e91e3a99572da73"}, - {file = "rapidfuzz-3.13.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:b836f486dba0aceb2551e838ff3f514a38ee72b015364f739e526d720fdb823a"}, - {file = "rapidfuzz-3.13.0-cp312-cp312-win32.whl", hash = "sha256:4671ee300d1818d7bdfd8fa0608580d7778ba701817216f0c17fb29e6b972514"}, - {file = "rapidfuzz-3.13.0-cp312-cp312-win_amd64.whl", hash = "sha256:6e2065f68fb1d0bf65adc289c1bdc45ba7e464e406b319d67bb54441a1b9da9e"}, - {file = "rapidfuzz-3.13.0-cp312-cp312-win_arm64.whl", hash = "sha256:65cc97c2fc2c2fe23586599686f3b1ceeedeca8e598cfcc1b7e56dc8ca7e2aa7"}, - {file = "rapidfuzz-3.13.0-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:1ba007f4d35a45ee68656b2eb83b8715e11d0f90e5b9f02d615a8a321ff00c27"}, - {file = "rapidfuzz-3.13.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:d7a217310429b43be95b3b8ad7f8fc41aba341109dc91e978cd7c703f928c58f"}, - {file = "rapidfuzz-3.13.0-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:558bf526bcd777de32b7885790a95a9548ffdcce68f704a81207be4a286c1095"}, - {file = "rapidfuzz-3.13.0-pp311-pypy311_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:202a87760f5145140d56153b193a797ae9338f7939eb16652dd7ff96f8faf64c"}, - {file = "rapidfuzz-3.13.0-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cfcccc08f671646ccb1e413c773bb92e7bba789e3a1796fd49d23c12539fe2e4"}, - {file = "rapidfuzz-3.13.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:1f219f1e3c3194d7a7de222f54450ce12bc907862ff9a8962d83061c1f923c86"}, - {file = "rapidfuzz-3.13.0.tar.gz", hash = "sha256:d2eaf3839e52cbcc0accbe9817a67b4b0fcf70aaeb229cfddc1c28061f9ce5d8"}, + {file = "rapidfuzz-3.14.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:dea2d113e260a5da0c4003e0a5e9fdf24a9dc2bb9eaa43abd030a1e46ce7837d"}, + {file = "rapidfuzz-3.14.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e6c31a4aa68cfa75d7eede8b0ed24b9e458447db604c2db53f358be9843d81d3"}, + {file = "rapidfuzz-3.14.3-cp311-cp311-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:02821366d928e68ddcb567fed8723dad7ea3a979fada6283e6914d5858674850"}, + {file = "rapidfuzz-3.14.3-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:cfe8df315ab4e6db4e1be72c5170f8e66021acde22cd2f9d04d2058a9fd8162e"}, + {file = "rapidfuzz-3.14.3-cp311-cp311-manylinux_2_31_armv7l.whl", hash = "sha256:769f31c60cd79420188fcdb3c823227fc4a6deb35cafec9d14045c7f6743acae"}, + {file = "rapidfuzz-3.14.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:54fa03062124e73086dae66a3451c553c1e20a39c077fd704dc7154092c34c63"}, + {file = "rapidfuzz-3.14.3-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:834d1e818005ed0d4ae38f6b87b86fad9b0a74085467ece0727d20e15077c094"}, + {file = "rapidfuzz-3.14.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:948b00e8476a91f510dd1ec07272efc7d78c275d83b630455559671d4e33b678"}, + {file = "rapidfuzz-3.14.3-cp311-cp311-win32.whl", hash = "sha256:43d0305c36f504232f18ea04e55f2059bb89f169d3119c4ea96a0e15b59e2a91"}, + {file = "rapidfuzz-3.14.3-cp311-cp311-win_amd64.whl", hash = "sha256:ef6bf930b947bd0735c550683939a032090f1d688dfd8861d6b45307b96fd5c5"}, + {file = "rapidfuzz-3.14.3-cp311-cp311-win_arm64.whl", hash = "sha256:f3eb0ff3b75d6fdccd40b55e7414bb859a1cda77c52762c9c82b85569f5088e7"}, + {file = "rapidfuzz-3.14.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:685c93ea961d135893b5984a5a9851637d23767feabe414ec974f43babbd8226"}, + {file = "rapidfuzz-3.14.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:fa7c8f26f009f8c673fbfb443792f0cf8cf50c4e18121ff1e285b5e08a94fbdb"}, + {file = "rapidfuzz-3.14.3-cp312-cp312-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:57f878330c8d361b2ce76cebb8e3e1dc827293b6abf404e67d53260d27b5d941"}, + {file = "rapidfuzz-3.14.3-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6c5f545f454871e6af05753a0172849c82feaf0f521c5ca62ba09e1b382d6382"}, + {file = "rapidfuzz-3.14.3-cp312-cp312-manylinux_2_31_armv7l.whl", hash = "sha256:07aa0b5d8863e3151e05026a28e0d924accf0a7a3b605da978f0359bb804df43"}, + {file = "rapidfuzz-3.14.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:73b07566bc7e010e7b5bd490fb04bb312e820970180df6b5655e9e6224c137db"}, + {file = "rapidfuzz-3.14.3-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:6de00eb84c71476af7d3110cf25d8fe7c792d7f5fa86764ef0b4ca97e78ca3ed"}, + {file = "rapidfuzz-3.14.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:d7843a1abf0091773a530636fdd2a49a41bcae22f9910b86b4f903e76ddc82dc"}, + {file = "rapidfuzz-3.14.3-cp312-cp312-win32.whl", hash = "sha256:dea97ac3ca18cd3ba8f3d04b5c1fe4aa60e58e8d9b7793d3bd595fdb04128d7a"}, + {file = "rapidfuzz-3.14.3-cp312-cp312-win_amd64.whl", hash = "sha256:b5100fd6bcee4d27f28f4e0a1c6b5127bc8ba7c2a9959cad9eab0bf4a7ab3329"}, + {file = "rapidfuzz-3.14.3-cp312-cp312-win_arm64.whl", hash = "sha256:4e49c9e992bc5fc873bd0fff7ef16a4405130ec42f2ce3d2b735ba5d3d4eb70f"}, + {file = "rapidfuzz-3.14.3-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:7cf174b52cb3ef5d49e45d0a1133b7e7d0ecf770ed01f97ae9962c5c91d97d23"}, + {file = "rapidfuzz-3.14.3-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:442cba39957a008dfc5bdef21a9c3f4379e30ffb4e41b8555dbaf4887eca9300"}, + {file = "rapidfuzz-3.14.3-pp311-pypy311_pp73-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1faa0f8f76ba75fd7b142c984947c280ef6558b5067af2ae9b8729b0a0f99ede"}, + {file = "rapidfuzz-3.14.3-pp311-pypy311_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1e6eefec45625c634926a9fd46c9e4f31118ac8f3156fff9494422cee45207e6"}, + {file = "rapidfuzz-3.14.3-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:56fefb4382bb12250f164250240b9dd7772e41c5c8ae976fd598a32292449cc5"}, + {file = "rapidfuzz-3.14.3.tar.gz", hash = "sha256:2491937177868bc4b1e469087601d53f925e8d270ccc21e07404b4b5814b7b5f"}, ] [[package]] name = "referencing" -version = "0.36.2" -requires_python = ">=3.9" +version = "0.37.0" +requires_python = ">=3.10" summary = "JSON Referencing + Python" dependencies = [ "attrs>=22.2.0", @@ -2942,14 +3314,14 @@ dependencies = [ "typing-extensions>=4.4.0; python_version < \"3.13\"", ] files = [ - {file = "referencing-0.36.2-py3-none-any.whl", hash = "sha256:e8699adbbf8b5c7de96d8ffa0eb5c158b3beafce084968e2ea8bb08c6794dcd0"}, - {file = "referencing-0.36.2.tar.gz", hash = "sha256:df2e89862cd09deabbdba16944cc3f10feb6b3e6f18e902f7cc25609a34775aa"}, + {file = "referencing-0.37.0-py3-none-any.whl", hash = "sha256:381329a9f99628c9069361716891d34ad94af76e461dcb0335825aecc7692231"}, + {file = "referencing-0.37.0.tar.gz", hash = "sha256:44aefc3142c5b842538163acb373e24cce6632bd54bdb01b21ad5863489f50d8"}, ] [[package]] name = "requests" -version = "2.32.3" -requires_python = ">=3.8" +version = "2.32.5" +requires_python = ">=3.9" summary = "Python HTTP for Humans." dependencies = [ "certifi>=2017.4.17", @@ -2958,8 +3330,8 @@ dependencies = [ "urllib3<3,>=1.21.1", ] files = [ - {file = "requests-2.32.3-py3-none-any.whl", hash = "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6"}, - {file = "requests-2.32.3.tar.gz", hash = "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760"}, + {file = "requests-2.32.5-py3-none-any.whl", hash = "sha256:2462f94637a34fd532264295e186976db0f5d453d1cdd31473c85a6a161affb6"}, + {file = "requests-2.32.5.tar.gz", hash = "sha256:dbba0bac56e100853db0ea71b82b4dfd5fe2bf6d3754a8893c3af500cec7d7cf"}, ] [[package]] @@ -2986,51 +3358,99 @@ files = [ ] [[package]] -name = "rpds-py" -version = "0.25.1" +name = "rfc3987-syntax" +version = "1.1.0" requires_python = ">=3.9" +summary = "Helper functions to syntactically validate strings according to RFC 3987." +dependencies = [ + "lark>=1.2.2", +] +files = [ + {file = "rfc3987_syntax-1.1.0-py3-none-any.whl", hash = "sha256:6c3d97604e4c5ce9f714898e05401a0445a641cfa276432b0a648c80856f6a3f"}, + {file = "rfc3987_syntax-1.1.0.tar.gz", hash = "sha256:717a62cbf33cffdd16dfa3a497d81ce48a660ea691b1ddd7be710c22f00b4a0d"}, +] + +[[package]] +name = "rich" +version = "14.2.0" +requires_python = ">=3.8.0" +summary = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal" +dependencies = [ + "markdown-it-py>=2.2.0", + "pygments<3.0.0,>=2.13.0", +] +files = [ + {file = "rich-14.2.0-py3-none-any.whl", hash = "sha256:76bc51fe2e57d2b1be1f96c524b890b816e334ab4c1e45888799bfaab0021edd"}, + {file = "rich-14.2.0.tar.gz", hash = "sha256:73ff50c7c0c1c77c8243079283f4edb376f0f6442433aecb8ce7e6d0b92d1fe4"}, +] + +[[package]] +name = "rpds-py" +version = "0.30.0" +requires_python = ">=3.10" summary = "Python bindings to Rust's persistent data structures (rpds)" files = [ - {file = "rpds_py-0.25.1-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:5f048bbf18b1f9120685c6d6bb70cc1a52c8cc11bdd04e643d28d3be0baf666d"}, - {file = "rpds_py-0.25.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4fbb0dbba559959fcb5d0735a0f87cdbca9e95dac87982e9b95c0f8f7ad10255"}, - {file = "rpds_py-0.25.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d4ca54b9cf9d80b4016a67a0193ebe0bcf29f6b0a96f09db942087e294d3d4c2"}, - {file = "rpds_py-0.25.1-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:1ee3e26eb83d39b886d2cb6e06ea701bba82ef30a0de044d34626ede51ec98b0"}, - {file = "rpds_py-0.25.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:89706d0683c73a26f76a5315d893c051324d771196ae8b13e6ffa1ffaf5e574f"}, - {file = "rpds_py-0.25.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c2013ee878c76269c7b557a9a9c042335d732e89d482606990b70a839635feb7"}, - {file = "rpds_py-0.25.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:45e484db65e5380804afbec784522de84fa95e6bb92ef1bd3325d33d13efaebd"}, - {file = "rpds_py-0.25.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:48d64155d02127c249695abb87d39f0faf410733428d499867606be138161d65"}, - {file = "rpds_py-0.25.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:048893e902132fd6548a2e661fb38bf4896a89eea95ac5816cf443524a85556f"}, - {file = "rpds_py-0.25.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:0317177b1e8691ab5879f4f33f4b6dc55ad3b344399e23df2e499de7b10a548d"}, - {file = "rpds_py-0.25.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:bffcf57826d77a4151962bf1701374e0fc87f536e56ec46f1abdd6a903354042"}, - {file = "rpds_py-0.25.1-cp311-cp311-win32.whl", hash = "sha256:cda776f1967cb304816173b30994faaf2fd5bcb37e73118a47964a02c348e1bc"}, - {file = "rpds_py-0.25.1-cp311-cp311-win_amd64.whl", hash = "sha256:dc3c1ff0abc91444cd20ec643d0f805df9a3661fcacf9c95000329f3ddf268a4"}, - {file = "rpds_py-0.25.1-cp311-cp311-win_arm64.whl", hash = "sha256:5a3ddb74b0985c4387719fc536faced33cadf2172769540c62e2a94b7b9be1c4"}, - {file = "rpds_py-0.25.1-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:b5ffe453cde61f73fea9430223c81d29e2fbf412a6073951102146c84e19e34c"}, - {file = "rpds_py-0.25.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:115874ae5e2fdcfc16b2aedc95b5eef4aebe91b28e7e21951eda8a5dc0d3461b"}, - {file = "rpds_py-0.25.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a714bf6e5e81b0e570d01f56e0c89c6375101b8463999ead3a93a5d2a4af91fa"}, - {file = "rpds_py-0.25.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:35634369325906bcd01577da4c19e3b9541a15e99f31e91a02d010816b49bfda"}, - {file = "rpds_py-0.25.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d4cb2b3ddc16710548801c6fcc0cfcdeeff9dafbc983f77265877793f2660309"}, - {file = "rpds_py-0.25.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9ceca1cf097ed77e1a51f1dbc8d174d10cb5931c188a4505ff9f3e119dfe519b"}, - {file = "rpds_py-0.25.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2c2cd1a4b0c2b8c5e31ffff50d09f39906fe351389ba143c195566056c13a7ea"}, - {file = "rpds_py-0.25.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1de336a4b164c9188cb23f3703adb74a7623ab32d20090d0e9bf499a2203ad65"}, - {file = "rpds_py-0.25.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:9fca84a15333e925dd59ce01da0ffe2ffe0d6e5d29a9eeba2148916d1824948c"}, - {file = "rpds_py-0.25.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:88ec04afe0c59fa64e2f6ea0dd9657e04fc83e38de90f6de201954b4d4eb59bd"}, - {file = "rpds_py-0.25.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:a8bd2f19e312ce3e1d2c635618e8a8d8132892bb746a7cf74780a489f0f6cdcb"}, - {file = "rpds_py-0.25.1-cp312-cp312-win32.whl", hash = "sha256:e5e2f7280d8d0d3ef06f3ec1b4fd598d386cc6f0721e54f09109a8132182fbfe"}, - {file = "rpds_py-0.25.1-cp312-cp312-win_amd64.whl", hash = "sha256:db58483f71c5db67d643857404da360dce3573031586034b7d59f245144cc192"}, - {file = "rpds_py-0.25.1-cp312-cp312-win_arm64.whl", hash = "sha256:6d50841c425d16faf3206ddbba44c21aa3310a0cebc3c1cdfc3e3f4f9f6f5728"}, - {file = "rpds_py-0.25.1-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:ee86d81551ec68a5c25373c5643d343150cc54672b5e9a0cafc93c1870a53954"}, - {file = "rpds_py-0.25.1-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:89c24300cd4a8e4a51e55c31a8ff3918e6651b241ee8876a42cc2b2a078533ba"}, - {file = "rpds_py-0.25.1-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:771c16060ff4e79584dc48902a91ba79fd93eade3aa3a12d6d2a4aadaf7d542b"}, - {file = "rpds_py-0.25.1-pp311-pypy311_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:785ffacd0ee61c3e60bdfde93baa6d7c10d86f15655bd706c89da08068dc5038"}, - {file = "rpds_py-0.25.1-pp311-pypy311_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2a40046a529cc15cef88ac5ab589f83f739e2d332cb4d7399072242400ed68c9"}, - {file = "rpds_py-0.25.1-pp311-pypy311_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:85fc223d9c76cabe5d0bff82214459189720dc135db45f9f66aa7cffbf9ff6c1"}, - {file = "rpds_py-0.25.1-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b0be9965f93c222fb9b4cc254235b3b2b215796c03ef5ee64f995b1b69af0762"}, - {file = "rpds_py-0.25.1-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:8378fa4a940f3fb509c081e06cb7f7f2adae8cf46ef258b0e0ed7519facd573e"}, - {file = "rpds_py-0.25.1-pp311-pypy311_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:33358883a4490287e67a2c391dfaea4d9359860281db3292b6886bf0be3d8692"}, - {file = "rpds_py-0.25.1-pp311-pypy311_pp73-musllinux_1_2_i686.whl", hash = "sha256:1d1fadd539298e70cac2f2cb36f5b8a65f742b9b9f1014dd4ea1f7785e2470bf"}, - {file = "rpds_py-0.25.1-pp311-pypy311_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:9a46c2fb2545e21181445515960006e85d22025bd2fe6db23e76daec6eb689fe"}, - {file = "rpds_py-0.25.1.tar.gz", hash = "sha256:8960b6dac09b62dac26e75d7e2c4a22efb835d827a7278c34f72b2b84fa160e3"}, + {file = "rpds_py-0.30.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:a2bffea6a4ca9f01b3f8e548302470306689684e61602aa3d141e34da06cf425"}, + {file = "rpds_py-0.30.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:dc4f992dfe1e2bc3ebc7444f6c7051b4bc13cd8e33e43511e8ffd13bf407010d"}, + {file = "rpds_py-0.30.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:422c3cb9856d80b09d30d2eb255d0754b23e090034e1deb4083f8004bd0761e4"}, + {file = "rpds_py-0.30.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:07ae8a593e1c3c6b82ca3292efbe73c30b61332fd612e05abee07c79359f292f"}, + {file = "rpds_py-0.30.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:12f90dd7557b6bd57f40abe7747e81e0c0b119bef015ea7726e69fe550e394a4"}, + {file = "rpds_py-0.30.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:99b47d6ad9a6da00bec6aabe5a6279ecd3c06a329d4aa4771034a21e335c3a97"}, + {file = "rpds_py-0.30.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:33f559f3104504506a44bb666b93a33f5d33133765b0c216a5bf2f1e1503af89"}, + {file = "rpds_py-0.30.0-cp311-cp311-manylinux_2_31_riscv64.whl", hash = "sha256:946fe926af6e44f3697abbc305ea168c2c31d3e3ef1058cf68f379bf0335a78d"}, + {file = "rpds_py-0.30.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:495aeca4b93d465efde585977365187149e75383ad2684f81519f504f5c13038"}, + {file = "rpds_py-0.30.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d9a0ca5da0386dee0655b4ccdf46119df60e0f10da268d04fe7cc87886872ba7"}, + {file = "rpds_py-0.30.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:8d6d1cc13664ec13c1b84241204ff3b12f9bb82464b8ad6e7a5d3486975c2eed"}, + {file = "rpds_py-0.30.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:3896fa1be39912cf0757753826bc8bdc8ca331a28a7c4ae46b7a21280b06bb85"}, + {file = "rpds_py-0.30.0-cp311-cp311-win32.whl", hash = "sha256:55f66022632205940f1827effeff17c4fa7ae1953d2b74a8581baaefb7d16f8c"}, + {file = "rpds_py-0.30.0-cp311-cp311-win_amd64.whl", hash = "sha256:a51033ff701fca756439d641c0ad09a41d9242fa69121c7d8769604a0a629825"}, + {file = "rpds_py-0.30.0-cp311-cp311-win_arm64.whl", hash = "sha256:47b0ef6231c58f506ef0b74d44e330405caa8428e770fec25329ed2cb971a229"}, + {file = "rpds_py-0.30.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:a161f20d9a43006833cd7068375a94d035714d73a172b681d8881820600abfad"}, + {file = "rpds_py-0.30.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6abc8880d9d036ecaafe709079969f56e876fcf107f7a8e9920ba6d5a3878d05"}, + {file = "rpds_py-0.30.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ca28829ae5f5d569bb62a79512c842a03a12576375d5ece7d2cadf8abe96ec28"}, + {file = "rpds_py-0.30.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a1010ed9524c73b94d15919ca4d41d8780980e1765babf85f9a2f90d247153dd"}, + {file = "rpds_py-0.30.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f8d1736cfb49381ba528cd5baa46f82fdc65c06e843dab24dd70b63d09121b3f"}, + {file = "rpds_py-0.30.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d948b135c4693daff7bc2dcfc4ec57237a29bd37e60c2fabf5aff2bbacf3e2f1"}, + {file = "rpds_py-0.30.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:47f236970bccb2233267d89173d3ad2703cd36a0e2a6e92d0560d333871a3d23"}, + {file = "rpds_py-0.30.0-cp312-cp312-manylinux_2_31_riscv64.whl", hash = "sha256:2e6ecb5a5bcacf59c3f912155044479af1d0b6681280048b338b28e364aca1f6"}, + {file = "rpds_py-0.30.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a8fa71a2e078c527c3e9dc9fc5a98c9db40bcc8a92b4e8858e36d329f8684b51"}, + {file = "rpds_py-0.30.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:73c67f2db7bc334e518d097c6d1e6fed021bbc9b7d678d6cc433478365d1d5f5"}, + {file = "rpds_py-0.30.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:5ba103fb455be00f3b1c2076c9d4264bfcb037c976167a6047ed82f23153f02e"}, + {file = "rpds_py-0.30.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:7cee9c752c0364588353e627da8a7e808a66873672bcb5f52890c33fd965b394"}, + {file = "rpds_py-0.30.0-cp312-cp312-win32.whl", hash = "sha256:1ab5b83dbcf55acc8b08fc62b796ef672c457b17dbd7820a11d6c52c06839bdf"}, + {file = "rpds_py-0.30.0-cp312-cp312-win_amd64.whl", hash = "sha256:a090322ca841abd453d43456ac34db46e8b05fd9b3b4ac0c78bcde8b089f959b"}, + {file = "rpds_py-0.30.0-cp312-cp312-win_arm64.whl", hash = "sha256:669b1805bd639dd2989b281be2cfd951c6121b65e729d9b843e9639ef1fd555e"}, + {file = "rpds_py-0.30.0-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:c2262bdba0ad4fc6fb5545660673925c2d2a5d9e2e0fb603aad545427be0fc58"}, + {file = "rpds_py-0.30.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:ee6af14263f25eedc3bb918a3c04245106a42dfd4f5c2285ea6f997b1fc3f89a"}, + {file = "rpds_py-0.30.0-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3adbb8179ce342d235c31ab8ec511e66c73faa27a47e076ccc92421add53e2bb"}, + {file = "rpds_py-0.30.0-pp311-pypy311_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:250fa00e9543ac9b97ac258bd37367ff5256666122c2d0f2bc97577c60a1818c"}, + {file = "rpds_py-0.30.0-pp311-pypy311_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9854cf4f488b3d57b9aaeb105f06d78e5529d3145b1e4a41750167e8c213c6d3"}, + {file = "rpds_py-0.30.0-pp311-pypy311_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:993914b8e560023bc0a8bf742c5f303551992dcb85e247b1e5c7f4a7d145bda5"}, + {file = "rpds_py-0.30.0-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:58edca431fb9b29950807e301826586e5bbf24163677732429770a697ffe6738"}, + {file = "rpds_py-0.30.0-pp311-pypy311_pp73-manylinux_2_31_riscv64.whl", hash = "sha256:dea5b552272a944763b34394d04577cf0f9bd013207bc32323b5a89a53cf9c2f"}, + {file = "rpds_py-0.30.0-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:ba3af48635eb83d03f6c9735dfb21785303e73d22ad03d489e88adae6eab8877"}, + {file = "rpds_py-0.30.0-pp311-pypy311_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:dff13836529b921e22f15cb099751209a60009731a68519630a24d61f0b1b30a"}, + {file = "rpds_py-0.30.0-pp311-pypy311_pp73-musllinux_1_2_i686.whl", hash = "sha256:1b151685b23929ab7beec71080a8889d4d6d9fa9a983d213f07121205d48e2c4"}, + {file = "rpds_py-0.30.0-pp311-pypy311_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:ac37f9f516c51e5753f27dfdef11a88330f04de2d564be3991384b2f3535d02e"}, + {file = "rpds_py-0.30.0.tar.gz", hash = "sha256:dd8ff7cf90014af0c0f787eea34794ebf6415242ee1d6fa91eaba725cc441e84"}, +] + +[[package]] +name = "scikit-build" +version = "0.18.1" +requires_python = ">=3.7" +summary = "Improved build system generator for Python C/C++/Fortran/Cython extensions" +dependencies = [ + "distro", + "packaging", + "setuptools>=42.0.0", + "tomli; python_version < \"3.11\"", + "typing-extensions>=3.7; python_version < \"3.8\"", + "wheel>=0.32.0", +] +files = [ + {file = "scikit_build-0.18.1-py3-none-any.whl", hash = "sha256:a6860e300f6807e76f21854163bdb9db16afc74eadf34bd6a9947d3fdfcd725a"}, + {file = "scikit_build-0.18.1.tar.gz", hash = "sha256:a4152ac5a084d499c28a7797be0628d8366c336e2fb0e1a063eb32e55efcb8e7"}, ] [[package]] @@ -3064,82 +3484,84 @@ files = [ [[package]] name = "scikit-learn" -version = "1.6.1" -requires_python = ">=3.9" +version = "1.8.0" +requires_python = ">=3.11" summary = "A set of python modules for machine learning and data mining" dependencies = [ - "joblib>=1.2.0", - "numpy>=1.19.5", - "scipy>=1.6.0", - "threadpoolctl>=3.1.0", + "joblib>=1.3.0", + "numpy>=1.24.1", + "scipy>=1.10.0", + "threadpoolctl>=3.2.0", ] files = [ - {file = "scikit_learn-1.6.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:72abc587c75234935e97d09aa4913a82f7b03ee0b74111dcc2881cba3c5a7b33"}, - {file = "scikit_learn-1.6.1-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:b3b00cdc8f1317b5f33191df1386c0befd16625f49d979fe77a8d44cae82410d"}, - {file = "scikit_learn-1.6.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dc4765af3386811c3ca21638f63b9cf5ecf66261cc4815c1db3f1e7dc7b79db2"}, - {file = "scikit_learn-1.6.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:25fc636bdaf1cc2f4a124a116312d837148b5e10872147bdaf4887926b8c03d8"}, - {file = "scikit_learn-1.6.1-cp311-cp311-win_amd64.whl", hash = "sha256:fa909b1a36e000a03c382aade0bd2063fd5680ff8b8e501660c0f59f021a6415"}, - {file = "scikit_learn-1.6.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:926f207c804104677af4857b2c609940b743d04c4c35ce0ddc8ff4f053cddc1b"}, - {file = "scikit_learn-1.6.1-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:2c2cae262064e6a9b77eee1c8e768fc46aa0b8338c6a8297b9b6759720ec0ff2"}, - {file = "scikit_learn-1.6.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1061b7c028a8663fb9a1a1baf9317b64a257fcb036dae5c8752b2abef31d136f"}, - {file = "scikit_learn-1.6.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2e69fab4ebfc9c9b580a7a80111b43d214ab06250f8a7ef590a4edf72464dd86"}, - {file = "scikit_learn-1.6.1-cp312-cp312-win_amd64.whl", hash = "sha256:70b1d7e85b1c96383f872a519b3375f92f14731e279a7b4c6cfd650cf5dffc52"}, - {file = "scikit_learn-1.6.1.tar.gz", hash = "sha256:b4fc2525eca2c69a59260f583c56a7557c6ccdf8deafdba6e060f94c1c59738e"}, + {file = "scikit_learn-1.8.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:146b4d36f800c013d267b29168813f7a03a43ecd2895d04861f1240b564421da"}, + {file = "scikit_learn-1.8.0-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:f984ca4b14914e6b4094c5d52a32ea16b49832c03bd17a110f004db3c223e8e1"}, + {file = "scikit_learn-1.8.0-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5e30adb87f0cc81c7690a84f7932dd66be5bac57cfe16b91cb9151683a4a2d3b"}, + {file = "scikit_learn-1.8.0-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ada8121bcb4dac28d930febc791a69f7cb1673c8495e5eee274190b73a4559c1"}, + {file = "scikit_learn-1.8.0-cp311-cp311-win_amd64.whl", hash = "sha256:c57b1b610bd1f40ba43970e11ce62821c2e6569e4d74023db19c6b26f246cb3b"}, + {file = "scikit_learn-1.8.0-cp311-cp311-win_arm64.whl", hash = "sha256:2838551e011a64e3053ad7618dda9310175f7515f1742fa2d756f7c874c05961"}, + {file = "scikit_learn-1.8.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:5fb63362b5a7ddab88e52b6dbb47dac3fd7dafeee740dc6c8d8a446ddedade8e"}, + {file = "scikit_learn-1.8.0-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:5025ce924beccb28298246e589c691fe1b8c1c96507e6d27d12c5fadd85bfd76"}, + {file = "scikit_learn-1.8.0-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4496bb2cf7a43ce1a2d7524a79e40bc5da45cf598dbf9545b7e8316ccba47bb4"}, + {file = "scikit_learn-1.8.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a0bcfe4d0d14aec44921545fd2af2338c7471de9cb701f1da4c9d85906ab847a"}, + {file = "scikit_learn-1.8.0-cp312-cp312-win_amd64.whl", hash = "sha256:35c007dedb2ffe38fe3ee7d201ebac4a2deccd2408e8621d53067733e3c74809"}, + {file = "scikit_learn-1.8.0-cp312-cp312-win_arm64.whl", hash = "sha256:8c497fff237d7b4e07e9ef1a640887fa4fb765647f86fbe00f969ff6280ce2bb"}, + {file = "scikit_learn-1.8.0.tar.gz", hash = "sha256:9bccbb3b40e3de10351f8f5068e105d0f4083b1a65fa07b6634fbc401a6287fd"}, ] [[package]] name = "scipy" -version = "1.15.3" -requires_python = ">=3.10" +version = "1.16.3" +requires_python = ">=3.11" summary = "Fundamental algorithms for scientific computing in Python" dependencies = [ - "numpy<2.5,>=1.23.5", -] -files = [ - {file = "scipy-1.15.3-cp311-cp311-macosx_10_13_x86_64.whl", hash = "sha256:993439ce220d25e3696d1b23b233dd010169b62f6456488567e830654ee37a6b"}, - {file = "scipy-1.15.3-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:34716e281f181a02341ddeaad584205bd2fd3c242063bd3423d61ac259ca7eba"}, - {file = "scipy-1.15.3-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:3b0334816afb8b91dab859281b1b9786934392aa3d527cd847e41bb6f45bee65"}, - {file = "scipy-1.15.3-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:6db907c7368e3092e24919b5e31c76998b0ce1684d51a90943cb0ed1b4ffd6c1"}, - {file = "scipy-1.15.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:721d6b4ef5dc82ca8968c25b111e307083d7ca9091bc38163fb89243e85e3889"}, - {file = "scipy-1.15.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:39cb9c62e471b1bb3750066ecc3a3f3052b37751c7c3dfd0fd7e48900ed52982"}, - {file = "scipy-1.15.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:795c46999bae845966368a3c013e0e00947932d68e235702b5c3f6ea799aa8c9"}, - {file = "scipy-1.15.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:18aaacb735ab38b38db42cb01f6b92a2d0d4b6aabefeb07f02849e47f8fb3594"}, - {file = "scipy-1.15.3-cp311-cp311-win_amd64.whl", hash = "sha256:ae48a786a28412d744c62fd7816a4118ef97e5be0bee968ce8f0a2fba7acf3bb"}, - {file = "scipy-1.15.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:6ac6310fdbfb7aa6612408bd2f07295bcbd3fda00d2d702178434751fe48e019"}, - {file = "scipy-1.15.3-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:185cd3d6d05ca4b44a8f1595af87f9c372bb6acf9c808e99aa3e9aa03bd98cf6"}, - {file = "scipy-1.15.3-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:05dc6abcd105e1a29f95eada46d4a3f251743cfd7d3ae8ddb4088047f24ea477"}, - {file = "scipy-1.15.3-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:06efcba926324df1696931a57a176c80848ccd67ce6ad020c810736bfd58eb1c"}, - {file = "scipy-1.15.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c05045d8b9bfd807ee1b9f38761993297b10b245f012b11b13b91ba8945f7e45"}, - {file = "scipy-1.15.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:271e3713e645149ea5ea3e97b57fdab61ce61333f97cfae392c28ba786f9bb49"}, - {file = "scipy-1.15.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6cfd56fc1a8e53f6e89ba3a7a7251f7396412d655bca2aa5611c8ec9a6784a1e"}, - {file = "scipy-1.15.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:0ff17c0bb1cb32952c09217d8d1eed9b53d1463e5f1dd6052c7857f83127d539"}, - {file = "scipy-1.15.3-cp312-cp312-win_amd64.whl", hash = "sha256:52092bc0472cfd17df49ff17e70624345efece4e1a12b23783a1ac59a1b728ed"}, - {file = "scipy-1.15.3.tar.gz", hash = "sha256:eae3cf522bc7df64b42cad3925c876e1b0b6c35c1337c93e12c0f366f55b0eaf"}, + "numpy<2.6,>=1.25.2", +] +files = [ + {file = "scipy-1.16.3-cp311-cp311-macosx_10_14_x86_64.whl", hash = "sha256:40be6cf99e68b6c4321e9f8782e7d5ff8265af28ef2cd56e9c9b2638fa08ad97"}, + {file = "scipy-1.16.3-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:8be1ca9170fcb6223cc7c27f4305d680ded114a1567c0bd2bfcbf947d1b17511"}, + {file = "scipy-1.16.3-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:bea0a62734d20d67608660f69dcda23e7f90fb4ca20974ab80b6ed40df87a005"}, + {file = "scipy-1.16.3-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:2a207a6ce9c24f1951241f4693ede2d393f59c07abc159b2cb2be980820e01fb"}, + {file = "scipy-1.16.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:532fb5ad6a87e9e9cd9c959b106b73145a03f04c7d57ea3e6f6bb60b86ab0876"}, + {file = "scipy-1.16.3-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:0151a0749efeaaab78711c78422d413c583b8cdd2011a3c1d6c794938ee9fdb2"}, + {file = "scipy-1.16.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:b7180967113560cca57418a7bc719e30366b47959dd845a93206fbed693c867e"}, + {file = "scipy-1.16.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:deb3841c925eeddb6afc1e4e4a45e418d19ec7b87c5df177695224078e8ec733"}, + {file = "scipy-1.16.3-cp311-cp311-win_amd64.whl", hash = "sha256:53c3844d527213631e886621df5695d35e4f6a75f620dca412bcd292f6b87d78"}, + {file = "scipy-1.16.3-cp311-cp311-win_arm64.whl", hash = "sha256:9452781bd879b14b6f055b26643703551320aa8d79ae064a71df55c00286a184"}, + {file = "scipy-1.16.3-cp312-cp312-macosx_10_14_x86_64.whl", hash = "sha256:81fc5827606858cf71446a5e98715ba0e11f0dbc83d71c7409d05486592a45d6"}, + {file = "scipy-1.16.3-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:c97176013d404c7346bf57874eaac5187d969293bf40497140b0a2b2b7482e07"}, + {file = "scipy-1.16.3-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:2b71d93c8a9936046866acebc915e2af2e292b883ed6e2cbe5c34beb094b82d9"}, + {file = "scipy-1.16.3-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:3d4a07a8e785d80289dfe66b7c27d8634a773020742ec7187b85ccc4b0e7b686"}, + {file = "scipy-1.16.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:0553371015692a898e1aa858fed67a3576c34edefa6b7ebdb4e9dde49ce5c203"}, + {file = "scipy-1.16.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:72d1717fd3b5e6ec747327ce9bda32d5463f472c9dce9f54499e81fbd50245a1"}, + {file = "scipy-1.16.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:1fb2472e72e24d1530debe6ae078db70fb1605350c88a3d14bc401d6306dbffe"}, + {file = "scipy-1.16.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:c5192722cffe15f9329a3948c4b1db789fbb1f05c97899187dcf009b283aea70"}, + {file = "scipy-1.16.3-cp312-cp312-win_amd64.whl", hash = "sha256:56edc65510d1331dae01ef9b658d428e33ed48b4f77b1d51caf479a0253f96dc"}, + {file = "scipy-1.16.3-cp312-cp312-win_arm64.whl", hash = "sha256:a8a26c78ef223d3e30920ef759e25625a0ecdd0d60e5a8818b7513c3e5384cf2"}, + {file = "scipy-1.16.3.tar.gz", hash = "sha256:01e87659402762f43bd2fee13370553a17ada367d42e7487800bf2916535aecb"}, ] [[package]] name = "scs" -version = "3.2.7.post2" -requires_python = ">=3.7" +version = "3.2.9" +requires_python = ">=3.9" summary = "Splitting conic solver" dependencies = [ "numpy", "scipy", ] files = [ - {file = "scs-3.2.7.post2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6d551b90d9e2c0497ee17d8c3db325d6fcefa4419057954e68709da8b9184d4f"}, - {file = "scs-3.2.7.post2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7c15d035dda04a6626d3cd9b68d3bf814d2e0eb3cb372021775bd358fd8c7405"}, - {file = "scs-3.2.7.post2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6da6add18f039e7e08f0ebc13cb1f853ec4c96ae81d7a578f46e0f9f0e5bf4b5"}, - {file = "scs-3.2.7.post2-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:d6c965f026e56c92b59a9c96744eb90178982c270ab196f58a0260ac392785aa"}, - {file = "scs-3.2.7.post2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:0427a5bf9aa43eb2a22083e1a43412db5054a88d695fdaa6018cd6fb3a9f0203"}, - {file = "scs-3.2.7.post2-cp311-cp311-win_amd64.whl", hash = "sha256:4d05ec092c891eb842630f343ebc0c46d2ef6047f325a835771b13f9804d6b3b"}, - {file = "scs-3.2.7.post2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:99e4af2968b046ee55fa0dc89dcd3bfba771f1027d9224cb6efa10008d8bfee1"}, - {file = "scs-3.2.7.post2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:bc46fef9743d4629337382f034fda92dfce338659e8377afae674517b7d8345f"}, - {file = "scs-3.2.7.post2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f92e925d89004276a449850926a45536f75c03cab701b5e758b1a7efa119ba08"}, - {file = "scs-3.2.7.post2-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:640faf61f85b933fdfc3d33d7ce4f0049b082b245e82d2d6a8c2c54aa0b7f540"}, - {file = "scs-3.2.7.post2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:a520c9bef84eee734df0da3e5e06aa9192d3be34cd5e6d4221cc01f4d09b20c0"}, - {file = "scs-3.2.7.post2-cp312-cp312-win_amd64.whl", hash = "sha256:2995d4099943c3fd754b3e39fe178a9c03dcb9c7d84b40f64ac5eb26d8d6085a"}, - {file = "scs-3.2.7.post2.tar.gz", hash = "sha256:4245a4f76328cc73911f20e1414df68d41ead4bcc4a187503a9cd639b644014b"}, + {file = "scs-3.2.9-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:af03985328c1c101ed097294ccdd9df78e4a8b76d0a335ac844df107c53ceba6"}, + {file = "scs-3.2.9-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:49b40ce47f6f0fabce13c9d9c9972b9fc58174c314a88ae2d314d7b9b713a83f"}, + {file = "scs-3.2.9-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3476c1e6b98596f572dc48e77466013e2ca88ec391df804429fdb1317e264df2"}, + {file = "scs-3.2.9-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:be6db6874326360d82e771fbfefbc96943bdc977f29a34c89652f47d0b2dc40e"}, + {file = "scs-3.2.9-cp311-cp311-win_amd64.whl", hash = "sha256:d56f5df1dc6b465f9ad544c6d2f83d8829da03856c9874aa81a7257f1b5a98dd"}, + {file = "scs-3.2.9-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:25e1820f5b71430ab05c0b50a1b858b5e482c8fd8d47aa419d18684f5884fc43"}, + {file = "scs-3.2.9-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:78b5a7fd71e4627d7faf0c84a808393a0e51864d0e3db92a69abdb33c4a6bf0c"}, + {file = "scs-3.2.9-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bf730f64158b6e924b43348a609bb0bac819b8e517a990c2f156b0de5251990f"}, + {file = "scs-3.2.9-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:c9cfb3abb4662b1d4662415c7c6049b5b0f60299f515b64f0d4f2a8c53c0d5a4"}, + {file = "scs-3.2.9-cp312-cp312-win_amd64.whl", hash = "sha256:e35cb089d536bc001a53fa708a40db0e6c304f1a318b623be3779db89d3411e7"}, + {file = "scs-3.2.9.tar.gz", hash = "sha256:df9542d435d21938ed09494a6c525a9772779902b61300961e16890a2df7f572"}, ] [[package]] @@ -3169,12 +3591,12 @@ files = [ [[package]] name = "setuptools" -version = "80.7.1" +version = "80.9.0" requires_python = ">=3.9" summary = "Easily download, build, install, upgrade, and uninstall Python packages" files = [ - {file = "setuptools-80.7.1-py3-none-any.whl", hash = "sha256:ca5cc1069b85dc23070a6628e6bcecb3292acac802399c7f8edc0100619f9009"}, - {file = "setuptools-80.7.1.tar.gz", hash = "sha256:f6ffc5f0142b1bd8d0ca94ee91b30c0ca862ffd50826da1ea85258a06fd94552"}, + {file = "setuptools-80.9.0-py3-none-any.whl", hash = "sha256:062d34222ad13e0cc312a4c02d73f059e86a4acbfbdea8f8f76b28c99f306922"}, + {file = "setuptools-80.9.0.tar.gz", hash = "sha256:f36b47402ecde768dbfafc46e8e4207b4360c654f1f3bb84475f0a28628fb19c"}, ] [[package]] @@ -3198,13 +3620,16 @@ files = [ ] [[package]] -name = "sniffio" -version = "1.3.1" -requires_python = ">=3.7" -summary = "Sniff out which async library your code is running under" +name = "snakeviz" +version = "2.2.2" +requires_python = ">=3.9" +summary = "A web-based viewer for Python profiler output" +dependencies = [ + "tornado>=2.0", +] files = [ - {file = "sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2"}, - {file = "sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc"}, + {file = "snakeviz-2.2.2-py3-none-any.whl", hash = "sha256:77e7b9c82f6152edc330040319b97612351cd9b48c706434c535c2df31d10ac5"}, + {file = "snakeviz-2.2.2.tar.gz", hash = "sha256:08028c6f8e34a032ff14757a38424770abb8662fb2818985aeea0d9bc13a7d83"}, ] [[package]] @@ -3218,17 +3643,17 @@ files = [ [[package]] name = "soupsieve" -version = "2.7" -requires_python = ">=3.8" +version = "2.8" +requires_python = ">=3.9" summary = "A modern CSS selector implementation for Beautiful Soup." files = [ - {file = "soupsieve-2.7-py3-none-any.whl", hash = "sha256:6e60cc5c1ffaf1cebcc12e8188320b72071e922c2e897f737cadce79ad5d30c4"}, - {file = "soupsieve-2.7.tar.gz", hash = "sha256:ad282f9b6926286d2ead4750552c8a6142bc4c783fd66b0293547c8fe6ae126a"}, + {file = "soupsieve-2.8-py3-none-any.whl", hash = "sha256:0cc76456a30e20f5d7f2e14a98a4ae2ee4e5abdc7c5ea0aafe795f344bc7984c"}, + {file = "soupsieve-2.8.tar.gz", hash = "sha256:e2dd4a40a628cb5f28f6d4b0db8800b8f581b65bb380b97de22ba5ca8d72572f"}, ] [[package]] name = "sparse" -version = "0.16.0" +version = "0.17.0" requires_python = ">=3.10" summary = "Sparse n-dimensional arrays for the PyData ecosystem" dependencies = [ @@ -3236,8 +3661,8 @@ dependencies = [ "numpy>=1.17", ] files = [ - {file = "sparse-0.16.0-py2.py3-none-any.whl", hash = "sha256:25d4463cf36315ee16a19b6951f1d6b8e9128a07dafd58f846eb6dfb4cd5b9d8"}, - {file = "sparse-0.16.0.tar.gz", hash = "sha256:26973e5dc80d54a37dfc2622ec554c5a3aa8396c4bafe7e9da59d2101b133588"}, + {file = "sparse-0.17.0-py2.py3-none-any.whl", hash = "sha256:1922d1d97f692b1061c4f03a1dd6ee21850aedc88e171aa845715f5069952f18"}, + {file = "sparse-0.17.0.tar.gz", hash = "sha256:6b1ad51a810c5be40b6f95e28513ec810fe1c785923bd83b2e4839a751df4bf7"}, ] [[package]] @@ -3273,7 +3698,7 @@ files = [ [[package]] name = "statsmodels" -version = "0.14.4" +version = "0.14.6" requires_python = ">=3.9" summary = "Statistical computations and models for Python" dependencies = [ @@ -3284,19 +3709,19 @@ dependencies = [ "scipy!=1.9.2,>=1.8", ] files = [ - {file = "statsmodels-0.14.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:5ed7e118e6e3e02d6723a079b8c97eaadeed943fa1f7f619f7148dfc7862670f"}, - {file = "statsmodels-0.14.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f5f537f7d000de4a1708c63400755152b862cd4926bb81a86568e347c19c364b"}, - {file = "statsmodels-0.14.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aa74aaa26eaa5012b0a01deeaa8a777595d0835d3d6c7175f2ac65435a7324d2"}, - {file = "statsmodels-0.14.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e332c2d9b806083d1797231280602340c5c913f90d4caa0213a6a54679ce9331"}, - {file = "statsmodels-0.14.4-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:d9c8fa28dfd75753d9cf62769ba1fecd7e73a0be187f35cc6f54076f98aa3f3f"}, - {file = "statsmodels-0.14.4-cp311-cp311-win_amd64.whl", hash = "sha256:a6087ecb0714f7c59eb24c22781491e6f1cfffb660b4740e167625ca4f052056"}, - {file = "statsmodels-0.14.4-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:5221dba7424cf4f2561b22e9081de85f5bb871228581124a0d1b572708545199"}, - {file = "statsmodels-0.14.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:17672b30c6b98afe2b095591e32d1d66d4372f2651428e433f16a3667f19eabb"}, - {file = "statsmodels-0.14.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ab5e6312213b8cfb9dca93dd46a0f4dccb856541f91d3306227c3d92f7659245"}, - {file = "statsmodels-0.14.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4bbb150620b53133d6cd1c5d14c28a4f85701e6c781d9b689b53681effaa655f"}, - {file = "statsmodels-0.14.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:bb695c2025d122a101c2aca66d2b78813c321b60d3a7c86bb8ec4467bb53b0f9"}, - {file = "statsmodels-0.14.4-cp312-cp312-win_amd64.whl", hash = "sha256:7f7917a51766b4e074da283c507a25048ad29a18e527207883d73535e0dc6184"}, - {file = "statsmodels-0.14.4.tar.gz", hash = "sha256:5d69e0f39060dc72c067f9bb6e8033b6dccdb0bae101d76a7ef0bcc94e898b67"}, + {file = "statsmodels-0.14.6-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6ad5c2810fc6c684254a7792bf1cbaf1606cdee2a253f8bd259c43135d87cfb4"}, + {file = "statsmodels-0.14.6-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:341fa68a7403e10a95c7b6e41134b0da3a7b835ecff1eb266294408535a06eb6"}, + {file = "statsmodels-0.14.6-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:bdf1dfe2a3ca56f5529118baf33a13efed2783c528f4a36409b46bbd2d9d48eb"}, + {file = "statsmodels-0.14.6-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a3764ba8195c9baf0925a96da0743ff218067a269f01d155ca3558deed2658ca"}, + {file = "statsmodels-0.14.6-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:9e8d2e519852adb1b420e018f5ac6e6684b2b877478adf7fda2cfdb58f5acb5d"}, + {file = "statsmodels-0.14.6-cp311-cp311-win_amd64.whl", hash = "sha256:2738a00fca51196f5a7d44b06970ace6b8b30289839e4808d656f8a98e35faa7"}, + {file = "statsmodels-0.14.6-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:fe76140ae7adc5ff0e60a3f0d56f4fffef484efa803c3efebf2fcd734d72ecb5"}, + {file = "statsmodels-0.14.6-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:26d4f0ed3b31f3c86f83a92f5c1f5cbe63fc992cd8915daf28ca49be14463a1c"}, + {file = "statsmodels-0.14.6-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d8c00a42863e4f4733ac9d078bbfad816249c01451740e6f5053ecc7db6d6368"}, + {file = "statsmodels-0.14.6-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:19b58cf7474aa9e7e3b0771a66537148b2df9b5884fbf156096c0e6c1ff0469d"}, + {file = "statsmodels-0.14.6-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:81e7dcc5e9587f2567e52deaff5220b175bf2f648951549eae5fc9383b62bc37"}, + {file = "statsmodels-0.14.6-cp312-cp312-win_amd64.whl", hash = "sha256:b5eb07acd115aa6208b4058211138393a7e6c2cf12b6f213ede10f658f6a714f"}, + {file = "statsmodels-0.14.6.tar.gz", hash = "sha256:4d17873d3e607d398b85126cd4ed7aad89e4e9d89fc744cdab1af3189a996c2a"}, ] [[package]] @@ -3313,12 +3738,12 @@ files = [ [[package]] name = "tblib" -version = "3.1.0" +version = "3.2.2" requires_python = ">=3.9" summary = "Traceback serialization library." files = [ - {file = "tblib-3.1.0-py3-none-any.whl", hash = "sha256:670bb4582578134b3d81a84afa1b016128b429f3d48e6cbbaecc9d15675e984e"}, - {file = "tblib-3.1.0.tar.gz", hash = "sha256:06404c2c9f07f66fee2d7d6ad43accc46f9c3361714d9b8426e7f47e595cd652"}, + {file = "tblib-3.2.2-py3-none-any.whl", hash = "sha256:26bdccf339bcce6a88b2b5432c988b266ebbe63a4e593f6b578b1d2e723d2b76"}, + {file = "tblib-3.2.2.tar.gz", hash = "sha256:e9a652692d91bf4f743d4a15bc174c0b76afc750fe8c7b6d195cc1c1d6d2ccec"}, ] [[package]] @@ -3348,15 +3773,15 @@ files = [ [[package]] name = "tifffile" -version = "2025.5.10" -requires_python = ">=3.10" +version = "2025.12.12" +requires_python = ">=3.11" summary = "Read and write TIFF files" dependencies = [ "numpy", ] files = [ - {file = "tifffile-2025.5.10-py3-none-any.whl", hash = "sha256:e37147123c0542d67bc37ba5cdd67e12ea6fbe6e86c52bee037a9eb6a064e5ad"}, - {file = "tifffile-2025.5.10.tar.gz", hash = "sha256:018335d34283aa3fd8c263bae5c3c2b661ebc45548fde31504016fcae7bf1103"}, + {file = "tifffile-2025.12.12-py3-none-any.whl", hash = "sha256:e3e3f1290ec6741ca248a5b5a997125209b5c2962f6bd9aef01ea9352c25d0ee"}, + {file = "tifffile-2025.12.12.tar.gz", hash = "sha256:97e11fd6b1d8dc971896a098c841d9cd4e6eb958ac040dd6fb8b332c3f7288b6"}, ] [[package]] @@ -3374,32 +3799,32 @@ files = [ [[package]] name = "toolz" -version = "1.0.0" -requires_python = ">=3.8" +version = "1.1.0" +requires_python = ">=3.9" summary = "List processing tools and functional utilities" files = [ - {file = "toolz-1.0.0-py3-none-any.whl", hash = "sha256:292c8f1c4e7516bf9086f8850935c799a874039c8bcf959d47b600e4c44a6236"}, - {file = "toolz-1.0.0.tar.gz", hash = "sha256:2c86e3d9a04798ac556793bced838816296a2f085017664e4995cb40a1047a02"}, + {file = "toolz-1.1.0-py3-none-any.whl", hash = "sha256:15ccc861ac51c53696de0a5d6d4607f99c210739caf987b5d2054f3efed429d8"}, + {file = "toolz-1.1.0.tar.gz", hash = "sha256:27a5c770d068c110d9ed9323f24f1543e83b2f300a687b7891c1a6d56b697b5b"}, ] [[package]] name = "tornado" -version = "6.5" +version = "6.5.3" requires_python = ">=3.9" summary = "Tornado is a Python web framework and asynchronous networking library, originally developed at FriendFeed." files = [ - {file = "tornado-6.5-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:f81067dad2e4443b015368b24e802d0083fecada4f0a4572fdb72fc06e54a9a6"}, - {file = "tornado-6.5-cp39-abi3-macosx_10_9_x86_64.whl", hash = "sha256:9ac1cbe1db860b3cbb251e795c701c41d343f06a96049d6274e7c77559117e41"}, - {file = "tornado-6.5-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7c625b9d03f1fb4d64149c47d0135227f0434ebb803e2008040eb92906b0105a"}, - {file = "tornado-6.5-cp39-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9a0d8d2309faf015903080fb5bdd969ecf9aa5ff893290845cf3fd5b2dd101bc"}, - {file = "tornado-6.5-cp39-abi3-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:03576ab51e9b1677e4cdaae620d6700d9823568b7939277e4690fe4085886c55"}, - {file = "tornado-6.5-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:ab75fe43d0e1b3a5e3ceddb2a611cb40090dd116a84fc216a07a298d9e000471"}, - {file = "tornado-6.5-cp39-abi3-musllinux_1_2_i686.whl", hash = "sha256:119c03f440a832128820e87add8a175d211b7f36e7ee161c631780877c28f4fb"}, - {file = "tornado-6.5-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:231f2193bb4c28db2bdee9e57bc6ca0cd491f345cd307c57d79613b058e807e0"}, - {file = "tornado-6.5-cp39-abi3-win32.whl", hash = "sha256:fd20c816e31be1bbff1f7681f970bbbd0bb241c364220140228ba24242bcdc59"}, - {file = "tornado-6.5-cp39-abi3-win_amd64.whl", hash = "sha256:007f036f7b661e899bd9ef3fa5f87eb2cb4d1b2e7d67368e778e140a2f101a7a"}, - {file = "tornado-6.5-cp39-abi3-win_arm64.whl", hash = "sha256:542e380658dcec911215c4820654662810c06ad872eefe10def6a5e9b20e9633"}, - {file = "tornado-6.5.tar.gz", hash = "sha256:c70c0a26d5b2d85440e4debd14a8d0b463a0cf35d92d3af05f5f1ffa8675c826"}, + {file = "tornado-6.5.3-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:2dd7d7e8d3e4635447a8afd4987951e3d4e8d1fb9ad1908c54c4002aabab0520"}, + {file = "tornado-6.5.3-cp39-abi3-macosx_10_9_x86_64.whl", hash = "sha256:5977a396f83496657779f59a48c38096ef01edfe4f42f1c0634b791dde8165d0"}, + {file = "tornado-6.5.3-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f72ac800be2ac73ddc1504f7aa21069a4137e8d70c387172c063d363d04f2208"}, + {file = "tornado-6.5.3-cp39-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c43c4fc4f5419c6561cfb8b884a8f6db7b142787d47821e1a0e1296253458265"}, + {file = "tornado-6.5.3-cp39-abi3-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:de8b3fed4b3afb65d542d7702ac8767b567e240f6a43020be8eaef59328f117b"}, + {file = "tornado-6.5.3-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:dbc4b4c32245b952566e17a20d5c1648fbed0e16aec3fc7e19f3974b36e0e47c"}, + {file = "tornado-6.5.3-cp39-abi3-musllinux_1_2_i686.whl", hash = "sha256:db238e8a174b4bfd0d0238b8cfcff1c14aebb4e2fcdafbf0ea5da3b81caceb4c"}, + {file = "tornado-6.5.3-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:892595c100cd9b53a768cbfc109dfc55dec884afe2de5290611a566078d9692d"}, + {file = "tornado-6.5.3-cp39-abi3-win32.whl", hash = "sha256:88141456525fe291e47bbe1ba3ffb7982549329f09b4299a56813923af2bd197"}, + {file = "tornado-6.5.3-cp39-abi3-win_amd64.whl", hash = "sha256:ba4b513d221cc7f795a532c1e296f36bcf6a60e54b15efd3f092889458c69af1"}, + {file = "tornado-6.5.3-cp39-abi3-win_arm64.whl", hash = "sha256:278c54d262911365075dd45e0b6314308c74badd6ff9a54490e7daccdd5ed0ea"}, + {file = "tornado-6.5.3.tar.gz", hash = "sha256:16abdeb0211796ffc73765bc0a20119712d68afeeaf93d1a3f2edf6b3aee8d5a"}, ] [[package]] @@ -3426,33 +3851,46 @@ files = [ ] [[package]] -name = "types-python-dateutil" -version = "2.9.0.20250516" +name = "typing-extensions" +version = "4.15.0" requires_python = ">=3.9" -summary = "Typing stubs for python-dateutil" +summary = "Backported and Experimental Type Hints for Python 3.9+" files = [ - {file = "types_python_dateutil-2.9.0.20250516-py3-none-any.whl", hash = "sha256:2b2b3f57f9c6a61fba26a9c0ffb9ea5681c9b83e69cd897c6b5f668d9c0cab93"}, - {file = "types_python_dateutil-2.9.0.20250516.tar.gz", hash = "sha256:13e80d6c9c47df23ad773d54b2826bd52dbbb41be87c3f339381c1700ad21ee5"}, + {file = "typing_extensions-4.15.0-py3-none-any.whl", hash = "sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548"}, + {file = "typing_extensions-4.15.0.tar.gz", hash = "sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466"}, ] [[package]] -name = "typing-extensions" -version = "4.13.2" -requires_python = ">=3.8" -summary = "Backported and Experimental Type Hints for Python 3.8+" +name = "typing-inspection" +version = "0.4.2" +requires_python = ">=3.9" +summary = "Runtime typing introspection tools" +dependencies = [ + "typing-extensions>=4.12.0", +] files = [ - {file = "typing_extensions-4.13.2-py3-none-any.whl", hash = "sha256:a439e7c04b49fec3e5d3e2beaa21755cadbbdc391694e28ccdd36ca4a1408f8c"}, - {file = "typing_extensions-4.13.2.tar.gz", hash = "sha256:e6c81219bd689f51865d9e372991c540bda33a0379d5573cddb9a3a23f7caaef"}, + {file = "typing_inspection-0.4.2-py3-none-any.whl", hash = "sha256:4ed1cacbdc298c220f1bd249ed5287caa16f34d44ef4e9c3d0cbad5b521545e7"}, + {file = "typing_inspection-0.4.2.tar.gz", hash = "sha256:ba561c48a67c5958007083d386c3295464928b01faa735ab8547c5692e87f464"}, ] [[package]] name = "tzdata" -version = "2025.2" +version = "2025.3" requires_python = ">=2" summary = "Provider of IANA time zone data" files = [ - {file = "tzdata-2025.2-py2.py3-none-any.whl", hash = "sha256:1a403fada01ff9221ca8044d701868fa132215d84beb92242d9acd2147f667a8"}, - {file = "tzdata-2025.2.tar.gz", hash = "sha256:b60a638fcc0daffadf82fe0f57e53d06bdec2f36c4df66280ae79bce6bd6f2b9"}, + {file = "tzdata-2025.3-py2.py3-none-any.whl", hash = "sha256:06a47e5700f3081aab02b2e513160914ff0694bce9947d6b76ebd6bf57cfc5d1"}, + {file = "tzdata-2025.3.tar.gz", hash = "sha256:de39c2ca5dc7b0344f2eba86f49d614019d29f060fc4ebc8a417896a620b56a7"}, +] + +[[package]] +name = "ubelt" +version = "1.4.0" +requires_python = ">=3.8" +summary = "A Python utility belt containing simple tools, a stdlib like feel, and extra batteries" +files = [ + {file = "ubelt-1.4.0-py3-none-any.whl", hash = "sha256:1490f377ba3cd1d65d839fae4c1a0354c5d486f3cb19e0cb434712709fcf49df"}, + {file = "ubelt-1.4.0.tar.gz", hash = "sha256:84e146c1c3ba13a2425eea5d5748bf33ab3f9dbe7ce237eb11e130116ba17441"}, ] [[package]] @@ -3477,34 +3915,32 @@ files = [ [[package]] name = "urllib3" -version = "2.4.0" +version = "2.6.2" requires_python = ">=3.9" summary = "HTTP library with thread-safe connection pooling, file post, and more." files = [ - {file = "urllib3-2.4.0-py3-none-any.whl", hash = "sha256:4e16665048960a0900c702d4a66415956a584919c03361cac9f1df5c5dd7e813"}, - {file = "urllib3-2.4.0.tar.gz", hash = "sha256:414bc6535b787febd7567804cc015fee39daab8ad86268f1310a9250697de466"}, + {file = "urllib3-2.6.2-py3-none-any.whl", hash = "sha256:ec21cddfe7724fc7cb4ba4bea7aa8e2ef36f607a4bab81aa6ce42a13dc3f03dd"}, + {file = "urllib3-2.6.2.tar.gz", hash = "sha256:016f9c98bb7e98085cb2b4b17b87d2c702975664e4f060c6532e64d1c1a5e797"}, ] [[package]] name = "wcwidth" -version = "0.2.13" +version = "0.2.14" +requires_python = ">=3.6" summary = "Measures the displayed width of unicode strings in a terminal" -dependencies = [ - "backports-functools-lru-cache>=1.2.1; python_version < \"3.2\"", -] files = [ - {file = "wcwidth-0.2.13-py2.py3-none-any.whl", hash = "sha256:3da69048e4540d84af32131829ff948f1e022c1c6bdb8d6102117aac784f6859"}, - {file = "wcwidth-0.2.13.tar.gz", hash = "sha256:72ea0c06399eb286d978fdedb6923a9eb47e1c486ce63e9b4e64fc18303972b5"}, + {file = "wcwidth-0.2.14-py2.py3-none-any.whl", hash = "sha256:a7bb560c8aee30f9957e5f9895805edd20602f2d7f720186dfd906e82b4982e1"}, + {file = "wcwidth-0.2.14.tar.gz", hash = "sha256:4d478375d31bc5395a3c55c40ccdf3354688364cd61c4f6adacaa9215d0b3605"}, ] [[package]] name = "webcolors" -version = "24.11.1" -requires_python = ">=3.9" +version = "25.10.0" +requires_python = ">=3.10" summary = "A library for working with the color formats defined by HTML and CSS." files = [ - {file = "webcolors-24.11.1-py3-none-any.whl", hash = "sha256:515291393b4cdf0eb19c155749a096f779f7d909f7cceea072791cb9095b92e9"}, - {file = "webcolors-24.11.1.tar.gz", hash = "sha256:ecb3d768f32202af770477b8b65f318fa4f566c22948673a977b00d589dd80f6"}, + {file = "webcolors-25.10.0-py3-none-any.whl", hash = "sha256:032c727334856fc0b968f63daa252a1ac93d33db2f5267756623c210e57a4f1d"}, + {file = "webcolors-25.10.0.tar.gz", hash = "sha256:62abae86504f66d0f6364c2a8520de4a0c47b80c03fc3a5f1815fedbef7c19bf"}, ] [[package]] @@ -3518,52 +3954,99 @@ files = [ [[package]] name = "websocket-client" -version = "1.8.0" -requires_python = ">=3.8" +version = "1.9.0" +requires_python = ">=3.9" summary = "WebSocket client for Python with low level API options" files = [ - {file = "websocket_client-1.8.0-py3-none-any.whl", hash = "sha256:17b44cc997f5c498e809b22cdf2d9c7a9e71c02c8cc2b6c56e7c2d1239bfa526"}, - {file = "websocket_client-1.8.0.tar.gz", hash = "sha256:3239df9f44da632f96012472805d40a23281a991027ce11d2f45a6f24ac4c3da"}, + {file = "websocket_client-1.9.0-py3-none-any.whl", hash = "sha256:af248a825037ef591efbf6ed20cc5faa03d3b47b9e5a2230a529eeee1c1fc3ef"}, + {file = "websocket_client-1.9.0.tar.gz", hash = "sha256:9e813624b6eb619999a97dc7958469217c3176312b3a16a4bd1bc7e08a46ec98"}, +] + +[[package]] +name = "wheel" +version = "0.45.1" +requires_python = ">=3.8" +summary = "A built-package format for Python" +files = [ + {file = "wheel-0.45.1-py3-none-any.whl", hash = "sha256:708e7481cc80179af0e556bbf0cc00b8444c7321e2700b8d8580231d13017248"}, + {file = "wheel-0.45.1.tar.gz", hash = "sha256:661e1abd9198507b1409a20c02106d9670b2576e916d58f520316666abca6729"}, ] [[package]] name = "widgetsnbextension" -version = "4.0.14" +version = "4.0.15" requires_python = ">=3.7" summary = "Jupyter interactive widgets for Jupyter Notebook" files = [ - {file = "widgetsnbextension-4.0.14-py3-none-any.whl", hash = "sha256:4875a9eaf72fbf5079dc372a51a9f268fc38d46f767cbf85c43a36da5cb9b575"}, - {file = "widgetsnbextension-4.0.14.tar.gz", hash = "sha256:a3629b04e3edb893212df862038c7232f62973373869db5084aed739b437b5af"}, + {file = "widgetsnbextension-4.0.15-py3-none-any.whl", hash = "sha256:8156704e4346a571d9ce73b84bee86a29906c9abfd7223b7228a28899ccf3366"}, + {file = "widgetsnbextension-4.0.15.tar.gz", hash = "sha256:de8610639996f1567952d763a5a41af8af37f2575a41f9852a38f947eb82a3b9"}, ] [[package]] name = "xarray" -version = "2025.4.0" -requires_python = ">=3.10" +version = "2025.12.0" +requires_python = ">=3.11" summary = "N-D labeled arrays and datasets in Python" dependencies = [ - "numpy>=1.24", - "packaging>=23.2", - "pandas>=2.1", + "numpy>=1.26", + "packaging>=24.1", + "pandas>=2.2", ] files = [ - {file = "xarray-2025.4.0-py3-none-any.whl", hash = "sha256:b27defd082c5cb85d32c695708de6bb05c2838fb7caaf3f952982e602a35b9b8"}, - {file = "xarray-2025.4.0.tar.gz", hash = "sha256:2a89cd6a1dfd589aa90ac45f4e483246f31fc641836db45dd2790bb78bd333dc"}, + {file = "xarray-2025.12.0-py3-none-any.whl", hash = "sha256:9e77e820474dbbe4c6c2954d0da6342aa484e33adaa96ab916b15a786181e970"}, + {file = "xarray-2025.12.0.tar.gz", hash = "sha256:73f6a6fadccc69c4d45bdd70821a47c72de078a8a0313ff8b1e97cd54ac59fed"}, +] + +[[package]] +name = "xdoctest" +version = "1.3.0" +requires_python = ">=3.8" +summary = "A rewrite of the builtin doctest module" +files = [ + {file = "xdoctest-1.3.0-py3-none-any.whl", hash = "sha256:b546accaecae2fd0a14e8d8e125550832f3f11981629324519d057e218dd348f"}, + {file = "xdoctest-1.3.0.tar.gz", hash = "sha256:f92cb99a3be6011c57bb94613a26b09a268e0095e926b4559132d135d8f6c9d4"}, ] [[package]] name = "xyzservices" -version = "2025.4.0" +version = "2025.11.0" requires_python = ">=3.8" summary = "Source of XYZ tiles providers" files = [ - {file = "xyzservices-2025.4.0-py3-none-any.whl", hash = "sha256:8d4db9a59213ccb4ce1cf70210584f30b10795bff47627cdfb862b39ff6e10c9"}, - {file = "xyzservices-2025.4.0.tar.gz", hash = "sha256:6fe764713648fac53450fbc61a3c366cb6ae5335a1b2ae0c3796b495de3709d8"}, + {file = "xyzservices-2025.11.0-py3-none-any.whl", hash = "sha256:de66a7599a8d6dad63980b77defd1d8f5a5a9cb5fc8774ea1c6e89ca7c2a3d2f"}, + {file = "xyzservices-2025.11.0.tar.gz", hash = "sha256:2fc72b49502b25023fd71e8f532fb4beddbbf0aa124d90ea25dba44f545e17ce"}, +] + +[[package]] +name = "yappi" +version = "1.7.3" +requires_python = ">=3.6" +summary = "Yet Another Python Profiler" +files = [ + {file = "yappi-1.7.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4e34aff669d5f08811234d1ac3b1ecc494353b9a3659d046278fa9a91ff28815"}, + {file = "yappi-1.7.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4518fc47efeaef9fc5035482711156b69cc52fe7d79da0463f1b044d0f40249f"}, + {file = "yappi-1.7.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c8152f6a26ba04cbbf12e959784b5d2497f8f1a8462d30442ca4cef581f78a4c"}, + {file = "yappi-1.7.3-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:627c7c2e6752a8231712760819204f2fc13ab4ba24844fbfcb435fd2f0120c6a"}, + {file = "yappi-1.7.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:01328c4e5a48a0fe8d840a928cf9105a20060272cf635fc49cf9b7762f70e696"}, + {file = "yappi-1.7.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:c319427c220c35bc9a2719356d6de09acb855078bc93f4dc9da03c7ccda64915"}, + {file = "yappi-1.7.3-cp311-cp311-win32.whl", hash = "sha256:f2ee5a22d1cc2f665ecb0eb26f554a4dc0b9af09bed7d04b1de0f2a9e08ae45c"}, + {file = "yappi-1.7.3-cp311-cp311-win_amd64.whl", hash = "sha256:77dac9da5772e8fe6e0dcd116e2785682df6601e77d824436f3b41de8d4ce489"}, + {file = "yappi-1.7.3-cp311-cp311-win_arm64.whl", hash = "sha256:4ece7c47fb16b78b7ad8d7b143f74d2923ab2c76a8993b3dd32ef6df3e40dbef"}, + {file = "yappi-1.7.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:835ba8b6078aa480c185c43e70489d6f7730d3c3570a51451d1f9e29f0fdecf5"}, + {file = "yappi-1.7.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:a23419753961c523a4d98799e199b32e7102bc1b4bd2279199e63e9bc37c0874"}, + {file = "yappi-1.7.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2b26c062c072ee1831d77cf06f8a812dc0cbcac63ef2f5b4cc6b4e67718603b6"}, + {file = "yappi-1.7.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:54d17fb356f2cfbb4862901d05cf686bddd46d5e5d3b4bbcb3a0ead3d4fac77d"}, + {file = "yappi-1.7.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6c62600783a0cf659c46324264996489fc6348dfc113faaf31b7c9af8e747133"}, + {file = "yappi-1.7.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:0cb41e4243907368d24081a4acd45d9dfa0867c8cb372491bb00d774f03fb21f"}, + {file = "yappi-1.7.3-cp312-cp312-win32.whl", hash = "sha256:b93bbf4e6951c1ace9687ac6b027c4b14a581359f233b2dfb21108fe08650397"}, + {file = "yappi-1.7.3-cp312-cp312-win_amd64.whl", hash = "sha256:396c183dd0ab93532f2fe5c1742b96e136846d56c249b85e72b653af56d11352"}, + {file = "yappi-1.7.3-cp312-cp312-win_arm64.whl", hash = "sha256:0317c9bf8908437578cb7661d2d5786043d2817b0377bb1e493669a1f1dbad76"}, + {file = "yappi-1.7.3.tar.gz", hash = "sha256:bef71ad0595b600261668dcb1e18b935a7117a724c04d7be60d9d246e32d0928"}, ] [[package]] name = "yarl" -version = "1.20.0" +version = "1.22.0" requires_python = ">=3.9" summary = "Yet another URL library" dependencies = [ @@ -3572,42 +4055,40 @@ dependencies = [ "propcache>=0.2.1", ] files = [ - {file = "yarl-1.20.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:fdb5204d17cb32b2de2d1e21c7461cabfacf17f3645e4b9039f210c5d3378bf3"}, - {file = "yarl-1.20.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:eaddd7804d8e77d67c28d154ae5fab203163bd0998769569861258e525039d2a"}, - {file = "yarl-1.20.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:634b7ba6b4a85cf67e9df7c13a7fb2e44fa37b5d34501038d174a63eaac25ee2"}, - {file = "yarl-1.20.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6d409e321e4addf7d97ee84162538c7258e53792eb7c6defd0c33647d754172e"}, - {file = "yarl-1.20.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:ea52f7328a36960ba3231c6677380fa67811b414798a6e071c7085c57b6d20a9"}, - {file = "yarl-1.20.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c8703517b924463994c344dcdf99a2d5ce9eca2b6882bb640aa555fb5efc706a"}, - {file = "yarl-1.20.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:077989b09ffd2f48fb2d8f6a86c5fef02f63ffe6b1dd4824c76de7bb01e4f2e2"}, - {file = "yarl-1.20.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0acfaf1da020253f3533526e8b7dd212838fdc4109959a2c53cafc6db611bff2"}, - {file = "yarl-1.20.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b4230ac0b97ec5eeb91d96b324d66060a43fd0d2a9b603e3327ed65f084e41f8"}, - {file = "yarl-1.20.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:0a6a1e6ae21cdd84011c24c78d7a126425148b24d437b5702328e4ba640a8902"}, - {file = "yarl-1.20.0-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:86de313371ec04dd2531f30bc41a5a1a96f25a02823558ee0f2af0beaa7ca791"}, - {file = "yarl-1.20.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:dd59c9dd58ae16eaa0f48c3d0cbe6be8ab4dc7247c3ff7db678edecbaf59327f"}, - {file = "yarl-1.20.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:a0bc5e05f457b7c1994cc29e83b58f540b76234ba6b9648a4971ddc7f6aa52da"}, - {file = "yarl-1.20.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:c9471ca18e6aeb0e03276b5e9b27b14a54c052d370a9c0c04a68cefbd1455eb4"}, - {file = "yarl-1.20.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:40ed574b4df723583a26c04b298b283ff171bcc387bc34c2683235e2487a65a5"}, - {file = "yarl-1.20.0-cp311-cp311-win32.whl", hash = "sha256:db243357c6c2bf3cd7e17080034ade668d54ce304d820c2a58514a4e51d0cfd6"}, - {file = "yarl-1.20.0-cp311-cp311-win_amd64.whl", hash = "sha256:8c12cd754d9dbd14204c328915e23b0c361b88f3cffd124129955e60a4fbfcfb"}, - {file = "yarl-1.20.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:e06b9f6cdd772f9b665e5ba8161968e11e403774114420737f7884b5bd7bdf6f"}, - {file = "yarl-1.20.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:b9ae2fbe54d859b3ade40290f60fe40e7f969d83d482e84d2c31b9bff03e359e"}, - {file = "yarl-1.20.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6d12b8945250d80c67688602c891237994d203d42427cb14e36d1a732eda480e"}, - {file = "yarl-1.20.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:087e9731884621b162a3e06dc0d2d626e1542a617f65ba7cc7aeab279d55ad33"}, - {file = "yarl-1.20.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:69df35468b66c1a6e6556248e6443ef0ec5f11a7a4428cf1f6281f1879220f58"}, - {file = "yarl-1.20.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3b2992fe29002fd0d4cbaea9428b09af9b8686a9024c840b8a2b8f4ea4abc16f"}, - {file = "yarl-1.20.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4c903e0b42aab48abfbac668b5a9d7b6938e721a6341751331bcd7553de2dcae"}, - {file = "yarl-1.20.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bf099e2432131093cc611623e0b0bcc399b8cddd9a91eded8bfb50402ec35018"}, - {file = "yarl-1.20.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8a7f62f5dc70a6c763bec9ebf922be52aa22863d9496a9a30124d65b489ea672"}, - {file = "yarl-1.20.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:54ac15a8b60382b2bcefd9a289ee26dc0920cf59b05368c9b2b72450751c6eb8"}, - {file = "yarl-1.20.0-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:25b3bc0763a7aca16a0f1b5e8ef0f23829df11fb539a1b70476dcab28bd83da7"}, - {file = "yarl-1.20.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:b2586e36dc070fc8fad6270f93242124df68b379c3a251af534030a4a33ef594"}, - {file = "yarl-1.20.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:866349da9d8c5290cfefb7fcc47721e94de3f315433613e01b435473be63daa6"}, - {file = "yarl-1.20.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:33bb660b390a0554d41f8ebec5cd4475502d84104b27e9b42f5321c5192bfcd1"}, - {file = "yarl-1.20.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:737e9f171e5a07031cbee5e9180f6ce21a6c599b9d4b2c24d35df20a52fabf4b"}, - {file = "yarl-1.20.0-cp312-cp312-win32.whl", hash = "sha256:839de4c574169b6598d47ad61534e6981979ca2c820ccb77bf70f4311dd2cc64"}, - {file = "yarl-1.20.0-cp312-cp312-win_amd64.whl", hash = "sha256:3d7dbbe44b443b0c4aa0971cb07dcb2c2060e4a9bf8d1301140a33a93c98e18c"}, - {file = "yarl-1.20.0-py3-none-any.whl", hash = "sha256:5d0fe6af927a47a230f31e6004621fd0959eaa915fc62acfafa67ff7229a3124"}, - {file = "yarl-1.20.0.tar.gz", hash = "sha256:686d51e51ee5dfe62dec86e4866ee0e9ed66df700d55c828a615640adc885307"}, + {file = "yarl-1.22.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:1ab72135b1f2db3fed3997d7e7dc1b80573c67138023852b6efb336a5eae6511"}, + {file = "yarl-1.22.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:669930400e375570189492dc8d8341301578e8493aec04aebc20d4717f899dd6"}, + {file = "yarl-1.22.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:792a2af6d58177ef7c19cbf0097aba92ca1b9cb3ffdd9c7470e156c8f9b5e028"}, + {file = "yarl-1.22.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3ea66b1c11c9150f1372f69afb6b8116f2dd7286f38e14ea71a44eee9ec51b9d"}, + {file = "yarl-1.22.0-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:3e2daa88dc91870215961e96a039ec73e4937da13cf77ce17f9cad0c18df3503"}, + {file = "yarl-1.22.0-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:ba440ae430c00eee41509353628600212112cd5018d5def7e9b05ea7ac34eb65"}, + {file = "yarl-1.22.0-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:e6438cc8f23a9c1478633d216b16104a586b9761db62bfacb6425bac0a36679e"}, + {file = "yarl-1.22.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4c52a6e78aef5cf47a98ef8e934755abf53953379b7d53e68b15ff4420e6683d"}, + {file = "yarl-1.22.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:3b06bcadaac49c70f4c88af4ffcfbe3dc155aab3163e75777818092478bcbbe7"}, + {file = "yarl-1.22.0-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:6944b2dc72c4d7f7052683487e3677456050ff77fcf5e6204e98caf785ad1967"}, + {file = "yarl-1.22.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:d5372ca1df0f91a86b047d1277c2aaf1edb32d78bbcefffc81b40ffd18f027ed"}, + {file = "yarl-1.22.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:51af598701f5299012b8416486b40fceef8c26fc87dc6d7d1f6fc30609ea0aa6"}, + {file = "yarl-1.22.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:b266bd01fedeffeeac01a79ae181719ff848a5a13ce10075adbefc8f1daee70e"}, + {file = "yarl-1.22.0-cp311-cp311-win32.whl", hash = "sha256:a9b1ba5610a4e20f655258d5a1fdc7ebe3d837bb0e45b581398b99eb98b1f5ca"}, + {file = "yarl-1.22.0-cp311-cp311-win_amd64.whl", hash = "sha256:078278b9b0b11568937d9509b589ee83ef98ed6d561dfe2020e24a9fd08eaa2b"}, + {file = "yarl-1.22.0-cp311-cp311-win_arm64.whl", hash = "sha256:b6a6f620cfe13ccec221fa312139135166e47ae169f8253f72a0abc0dae94376"}, + {file = "yarl-1.22.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:e340382d1afa5d32b892b3ff062436d592ec3d692aeea3bef3a5cfe11bbf8c6f"}, + {file = "yarl-1.22.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:f1e09112a2c31ffe8d80be1b0988fa6a18c5d5cad92a9ffbb1c04c91bfe52ad2"}, + {file = "yarl-1.22.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:939fe60db294c786f6b7c2d2e121576628468f65453d86b0fe36cb52f987bd74"}, + {file = "yarl-1.22.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e1651bf8e0398574646744c1885a41198eba53dc8a9312b954073f845c90a8df"}, + {file = "yarl-1.22.0-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:b8a0588521a26bf92a57a1705b77b8b59044cdceccac7151bd8d229e66b8dedb"}, + {file = "yarl-1.22.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:42188e6a615c1a75bcaa6e150c3fe8f3e8680471a6b10150c5f7e83f47cc34d2"}, + {file = "yarl-1.22.0-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:f6d2cb59377d99718913ad9a151030d6f83ef420a2b8f521d94609ecc106ee82"}, + {file = "yarl-1.22.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:50678a3b71c751d58d7908edc96d332af328839eea883bb554a43f539101277a"}, + {file = "yarl-1.22.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:1e8fbaa7cec507aa24ea27a01456e8dd4b6fab829059b69844bd348f2d467124"}, + {file = "yarl-1.22.0-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:433885ab5431bc3d3d4f2f9bd15bfa1614c522b0f1405d62c4f926ccd69d04fa"}, + {file = "yarl-1.22.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:b790b39c7e9a4192dc2e201a282109ed2985a1ddbd5ac08dc56d0e121400a8f7"}, + {file = "yarl-1.22.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:31f0b53913220599446872d757257be5898019c85e7971599065bc55065dc99d"}, + {file = "yarl-1.22.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:a49370e8f711daec68d09b821a34e1167792ee2d24d405cbc2387be4f158b520"}, + {file = "yarl-1.22.0-cp312-cp312-win32.whl", hash = "sha256:70dfd4f241c04bd9239d53b17f11e6ab672b9f1420364af63e8531198e3f5fe8"}, + {file = "yarl-1.22.0-cp312-cp312-win_amd64.whl", hash = "sha256:8884d8b332a5e9b88e23f60bb166890009429391864c685e17bd73a9eda9105c"}, + {file = "yarl-1.22.0-cp312-cp312-win_arm64.whl", hash = "sha256:ea70f61a47f3cc93bdf8b2f368ed359ef02a01ca6393916bc8ff877427181e74"}, + {file = "yarl-1.22.0-py3-none-any.whl", hash = "sha256:1380560bdba02b6b6c90de54133c81c9f2a453dee9912fe58c1dcced1edb7cff"}, + {file = "yarl-1.22.0.tar.gz", hash = "sha256:bebf8557577d4401ba8bd9ff33906f1376c877aa78d1fe216ad01b4d6745af71"}, ] [[package]] @@ -3622,10 +4103,10 @@ files = [ [[package]] name = "zipp" -version = "3.21.0" +version = "3.23.0" requires_python = ">=3.9" summary = "Backport of pathlib-compatible object wrapper for zip files" files = [ - {file = "zipp-3.21.0-py3-none-any.whl", hash = "sha256:ac1bbe05fd2991f160ebce24ffbac5f6d11d83dc90891255885223d42b3cd931"}, - {file = "zipp-3.21.0.tar.gz", hash = "sha256:2c9958f6430a2040341a52eb608ed6dd93ef4392e02ffe219417c1b28b5dd1f4"}, + {file = "zipp-3.23.0-py3-none-any.whl", hash = "sha256:071652d6115ed432f5ce1d34c336c0adfd6a884660d1e9712a256d3d3bd4b14e"}, + {file = "zipp-3.23.0.tar.gz", hash = "sha256:a07157588a12518c9d4034df3fbbee09c814741a33ff63c05fa29d26a2404166"}, ] diff --git a/pyproject.toml b/pyproject.toml index ba6027a..822438f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -27,6 +27,8 @@ dependencies = [ "line-profiler>=4.1.3", "scikit-image>=0.25.2", "numba>=0.61.2", + "pydantic>=2.0", + "yappi>=1.6.0", ] requires-python = ">=3.11,<3.13" readme = "README.md" @@ -42,7 +44,7 @@ benchmark_bin = "python scripts/s01_benchmark_bin.py" plot_test = "python tests/plot_results.py" [tool.pdm.dev-dependencies] -dev = ["line-profiler[all]>=4.1.3", "jupyter>=1.1.1"] +dev = ["line-profiler[all]>=4.1.3", "jupyter>=1.1.1", "snakeviz>=2.2.0"] [tool.black] line-length = 88 diff --git a/src/indeca/core/AR_kernel.py b/src/indeca/core/AR_kernel.py index 60ea07d..7ef33bb 100644 --- a/src/indeca/core/AR_kernel.py +++ b/src/indeca/core/AR_kernel.py @@ -9,7 +9,7 @@ from scipy.optimize import curve_fit from statsmodels.tsa.stattools import acovf -from indeca.core.deconv.deconv import construct_G, construct_R +from indeca.core.deconv import construct_G, construct_R from indeca.core.simulation import AR2tau, ar_pulse, solve_p, tau2AR diff --git a/src/indeca/core/deconv/__init__.py b/src/indeca/core/deconv/__init__.py index da46a0c..0753809 100644 --- a/src/indeca/core/deconv/__init__.py +++ b/src/indeca/core/deconv/__init__.py @@ -1,3 +1,4 @@ -from .deconv import DeconvBin, construct_R, construct_G, max_thres, sum_downsample +from .deconv import DeconvBin +from .utils import construct_R, construct_G, max_thres, sum_downsample __all__ = ["DeconvBin", "construct_R", "construct_G", "max_thres", "sum_downsample"] diff --git a/src/indeca/core/deconv/config.py b/src/indeca/core/deconv/config.py new file mode 100644 index 0000000..bd4aff9 --- /dev/null +++ b/src/indeca/core/deconv/config.py @@ -0,0 +1,91 @@ +"""Configuration for deconv module.""" + +from typing import Literal, Optional, Union + +from pydantic import BaseModel, Field, model_validator + + +class DeconvConfig(BaseModel): + """Configuration for DeconvBin.""" + + model_config = {"frozen": True} + + coef_len: int = Field( + 100, description="Length of the coefficient kernel (e.g. calcium response)." + ) + scale: float = Field(1.0, description="Global scaling factor.") + penal: str | None = Field("l1", description="Penalty type ('l1', 'l0', etc.).") + use_base: bool = Field(False, description="Whether to include a baseline term.") + upsamp: int = Field(1, description="Upsampling factor.") + norm: Literal["l1", "l2", "huber"] = Field( + "l2", description="Norm for data fidelity ('l2', 'l1', 'huber')." + ) + mixin: bool = Field( + False, description="Whether to use mixed-integer programming (boolean spikes)." + ) + backend: Literal["osqp", "cvxpy", "cuosqp"] = Field( + "osqp", + description="Solver backend ('osqp', 'cvxpy', 'cuosqp'). Note: emosqp requires codegen and is not supported.", + ) + free_kernel: bool = Field( + False, + description="If True, use convolution constraint instead of AR constraint. Only supported with OSQP backends.", + ) + nthres: int = Field(1000, description="Number of thresholds for thresholding step.") + err_weighting: Optional[str] = Field( + None, description="Error weighting method ('fft', 'corr', 'adaptive', or None)." + ) + wt_trunc_thres: float = Field( + 1e-2, description="Threshold for truncating error weights." + ) + masking_radius: Optional[int] = Field( + None, description="Radius for masking around spikes." + ) + pks_polish: bool = Field(True, description="Whether to polish peaks after solving.") + th_min: float = Field(0.0, description="Minimum threshold.") + th_max: float = Field(1.0, description="Maximum threshold.") + density_thres: Optional[float] = Field( + None, description="Max spike density threshold." + ) + ncons_thres: Union[int, Literal["auto"], None] = Field( + None, description="Max consecutive spikes threshold. If 'auto', upsamp + 1." + ) + min_rel_scl: Union[float, Literal["auto"], None] = Field( + "auto", description="Minimum relative scale. Use None to disable." + ) + + max_iter_l0: int = 30 + max_iter_penal: int = 500 + max_iter_scal: int = 50 + delta_l0: float = 1e-4 + delta_penal: float = 1e-4 + atol: float = 1e-3 + rtol: float = 1e-3 + Hlim: Optional[int] = 1e5 + + @model_validator(mode="before") + @classmethod + def resolve_auto_fields(cls, data): + # Resolve "auto" values before constructing the (frozen) model to avoid + # returning a new instance from an "after" validator (pydantic warns). + if not isinstance(data, dict): + return data + upsamp = data.get("upsamp", 1) + if data.get("min_rel_scl") == "auto": + data["min_rel_scl"] = 0.5 / upsamp + if data.get("ncons_thres") == "auto": + data["ncons_thres"] = upsamp + 1 + return data + + @model_validator(mode="after") + def validate_penal(self): + allowed = {None, "l0", "l1"} + if self.penal not in allowed: + raise ValueError(f"Unsupported penal type: {self.penal}") + return self + + @model_validator(mode="after") + def validate_compat(self): + if self.free_kernel and self.backend == "cvxpy": + raise ValueError("free_kernel=True is not supported with backend='cvxpy'") + return self diff --git a/src/indeca/core/deconv/deconv.py b/src/indeca/core/deconv/deconv.py index 40fa2fc..ea39772 100644 --- a/src/indeca/core/deconv/deconv.py +++ b/src/indeca/core/deconv/deconv.py @@ -1,139 +1,46 @@ +"""Main deconvolution module.""" + import itertools as itt +import math +import os import warnings -from typing import Tuple +from typing import Tuple, Any, Optional -import cvxpy as cp import numpy as np -import osqp -import pandas as pd import scipy.sparse as sps -import xarray as xr -from numba import njit -from scipy.ndimage import label +import pandas as pd from scipy.optimize import direct -from scipy.signal import ShortTimeFFT, find_peaks -from scipy.special import huber +from scipy.signal import find_peaks +from scipy.ndimage import label from indeca.utils.logging_config import get_module_logger from indeca.core.simulation import AR2tau, ar_pulse, exp_pulse, solve_p, tau2AR from indeca.utils.utils import scal_lstsq +from .config import DeconvConfig +from .solver import DeconvSolver, CVXPYSolver, OSQPSolver +from .utils import max_thres, max_consecutive, sum_downsample # Initialize logger for this module logger = get_module_logger("deconv") logger.info("Deconv module initialized") -try: - import cuosqp -except ImportError: - logger.warning("No GPU solver support") - -def construct_R(T: int, up_factor: int): - if up_factor > 1: - return sps.csc_matrix( - ( - np.ones(T * up_factor), - (np.repeat(np.arange(T), up_factor), np.arange(T * up_factor)), - ), - shape=(T, T * up_factor), - ) - else: - return sps.eye(T, format="csc") - - -def sum_downsample(a, factor): - return np.convolve(a, np.ones(factor), mode="full")[factor - 1 :: factor] - - -def construct_G(fac: np.ndarray, T: int, fromTau=False): - fac = np.array(fac) - assert fac.shape == (2,) - if fromTau: - fac = np.array(tau2AR(*fac)) - return sps.dia_matrix( - ( - np.tile(np.concatenate(([1], -fac)), (T, 1)).T, - -np.arange(len(fac) + 1), - ), - shape=(T, T), - ).tocsc() - - -def max_thres( - a: xr.DataArray, - nthres: int, - th_min=0.1, - th_max=0.9, - ds=None, - return_thres=False, - th_amplitude=False, - delta=1e-6, - reverse_thres=False, - nz_only: bool = False, -): - amax = a.max() - if reverse_thres: - thres = np.linspace(th_max, th_min, nthres) - else: - thres = np.linspace(th_min, th_max, nthres) - if th_amplitude: - S_ls = [np.floor_divide(a, (amax * th).clip(delta, None)) for th in thres] - else: - S_ls = [(a > (amax * th).clip(delta, None)) for th in thres] - if ds is not None: - S_ls = [sum_downsample(s, ds) for s in S_ls] - if nz_only: - Snz = [ss.sum() > 0 for ss in S_ls] - S_ls = [ss for ss, nz in zip(S_ls, Snz) if nz] - thres = [th for th, nz in zip(thres, Snz) if nz] - if return_thres: - return S_ls, thres - else: - return S_ls - - -@njit(nopython=True, nogil=True, cache=True) -def bin_convolve( - coef: np.ndarray, s: np.ndarray, nzidx_s: np.ndarray = None, s_len: int = None -): - coef_len = len(coef) - if s_len is None: - s_len = len(s) - out = np.zeros(s_len) - nzidx = np.where(s)[0] - if nzidx_s is not None: - nzidx = nzidx_s[nzidx].astype( - np.int64 - ) # astype to fix numpa issues on GPU on Windows - for i0 in nzidx: - i1 = min(i0 + coef_len, s_len) - clen = i1 - i0 - out[i0:i1] += coef[:clen] - return out - - -@njit(nopython=True, nogil=True, cache=True) -def max_consecutive(arr): - max_count = 0 - current_count = 0 - for value in arr: - if value: - current_count += 1 - max_count = max(max_count, current_count) - else: - current_count = 0 - return max_count +class DeconvBin: + """Deconvolution main class. + This class wraps the solver backends and provides high-level methods + for spike inference including thresholding, penalty optimization, + and scale estimation. + """ -class DeconvBin: def __init__( self, - y: np.array = None, + y: np.ndarray = None, y_len: int = None, - theta: np.array = None, - tau: np.array = None, - ps: np.array = None, - coef: np.array = None, + theta: np.ndarray = None, + tau: np.ndarray = None, + ps: np.ndarray = None, + coef: np.ndarray = None, coef_len: int = 100, scale: float = 1, penal: str = "l1", @@ -142,6 +49,7 @@ def __init__( norm: str = "l2", mixin: bool = False, backend: str = "osqp", + free_kernel: bool = False, nthres: int = 1000, err_weighting: str = None, wt_trunc_thres: float = 1e-2, @@ -163,15 +71,25 @@ def __init__( dashboard=None, dashboard_uid=None, ) -> None: - # book-keeping + # Handle y input if y is not None: self.y_len = len(y) + self.y = y else: assert y_len is not None self.y_len = y_len + self.y = np.zeros(y_len) + if coef_len is not None and coef_len > self.y_len: warnings.warn("Coefficient length longer than data") coef_len = self.y_len + + # Store tau/theta/ps + self.theta = None + self.tau = None + self.ps = None + + # Compute coefficients from theta or tau if theta is not None: self.theta = np.array(theta) if tau is None: @@ -207,164 +125,146 @@ def __init__( if coef is None: assert coef_len is not None coef = np.ones(coef_len * upsamp) + + # `coef_len` (config) is the *base* kernel length; the stored `coef` is + # already upsampled to length `coef_len * upsamp`. self.coef_len = len(coef) - self.T = self.y_len * upsamp - l0_penal = 0 - l1_penal = 0 - self.free_kernel = False - self.penal = penal - self.use_base = use_base - self.l0_penal = l0_penal - self.w_org = np.ones(self.T) - self.w = np.ones(self.T) - self.upsamp = upsamp - self.norm = norm - self.backend = backend - self.nthres = nthres - self.th_min = th_min - self.th_max = th_max - self.max_iter_l0 = max_iter_l0 - self.max_iter_penal = max_iter_penal - self.max_iter_scal = max_iter_scal - self.delta_l0 = delta_l0 - self.delta_penal = delta_penal - self.atol = atol - self.rtol = rtol - self.Hlim = Hlim + + # Create config (note: frozen after creation) + self.cfg = DeconvConfig( + coef_len=coef_len, + scale=scale, + penal=penal, + use_base=use_base, + upsamp=upsamp, + norm=norm, + mixin=mixin, + backend=backend, + free_kernel=free_kernel, + nthres=nthres, + err_weighting=err_weighting, + wt_trunc_thres=wt_trunc_thres, + masking_radius=masking_radius, + pks_polish=pks_polish, + th_min=th_min, + th_max=th_max, + density_thres=density_thres, + # IMPORTANT: preserve old semantics: None disables consecutive constraint, + # and "auto" enables the (upsamp + 1) default. + ncons_thres=ncons_thres, + min_rel_scl=min_rel_scl, + max_iter_l0=max_iter_l0, + max_iter_penal=max_iter_penal, + max_iter_scal=max_iter_scal, + delta_l0=delta_l0, + delta_penal=delta_penal, + atol=atol, + rtol=rtol, + Hlim=Hlim, + ) + + # Dashboard for visualization self.dashboard = dashboard self.dashboard_uid = dashboard_uid - self.nzidx_s = np.arange(self.T, dtype=np.int64) - self.nzidx_c = np.arange(self.T, dtype=np.int64) - self.x_cache = None - self.err_weighting = err_weighting - self.masking_r = masking_radius - self.pks_polish = pks_polish - self.err_wt = np.ones(self.y_len) - self.density_thres = density_thres - self.wt_trunc_thres = wt_trunc_thres - if ncons_thres == "auto": - self.ncons_thres = upsamp + 1 - else: - self.ncons_thres = ncons_thres - if min_rel_scl == "auto": - self.min_rel_scl = ( - 0.5 / self.upsamp - ) # 2 x upsamp number of spikes should be more than enough to explain highest peak - else: - self.min_rel_scl = min_rel_scl - if err_weighting == "fft": - self.stft = ShortTimeFFT(win=np.ones(self.coef_len), hop=1, fs=1) - self.yspec = self._get_stft_spec(y) - if y is not None: - self.huber_k = 0.5 * np.std(y) - self.err_total = self._res_err(y) - else: - self.huber_k = 0 - self.err_total = 0 - self._update_R() - # setup cvxpy - if self.backend == "cvxpy": - self.R = cp.Constant(self.R, name="R") - self.c = cp.Variable((self.T, 1), nonneg=True, name="c") - self.s = cp.Variable((self.T, 1), nonneg=True, name="s", boolean=mixin) - self.y = cp.Parameter(shape=(self.y_len, 1), name="y") - self.coef = cp.Parameter(value=coef, shape=self.coef_len, name="coef") - self.scale = cp.Parameter(value=scale, name="scale", nonneg=True) - self.l1_penal = cp.Parameter(value=l1_penal, name="l1_penal", nonneg=True) - self.l0_w = cp.Parameter( - shape=self.T, value=self.l0_penal * self.w, nonneg=True, name="w_l0" - ) # product of l0_penal * w! - if y is not None: - self.y.value = y.reshape((-1, 1)) - if coef is not None: - self.coef.value = coef - if use_base: - self.b = cp.Variable(nonneg=True, name="b") - else: - self.b = cp.Constant(value=0, name="b") - if norm == "l1": - self.err_term = cp.sum( - cp.abs(self.y - self.scale * self.R @ self.c - self.b) - ) - elif norm == "l2": - self.err_term = cp.sum_squares( - self.y - self.scale * self.R @ self.c - self.b - ) - elif norm == "huber": - self.err_term = cp.sum( - cp.huber(self.y - self.scale * self.R @ self.c - self.b) + + # Penalty tracking - solver tracks scale, we track penalty locally + self._l0_penal = 0.0 + self._l1_penal = 0.0 + + # Create solver + if self.cfg.backend == "cvxpy": + if self.cfg.free_kernel: + raise NotImplementedError( + "CVXPY backend does not support free_kernel mode" ) - obj = cp.Minimize( - self.err_term - + self.l0_w.T @ cp.abs(self.s) - + self.l1_penal * cp.sum(cp.abs(self.s)) + self.solver = CVXPYSolver( + self.cfg, + self.y_len, + y=self.y, + coef=coef, + theta=self.theta, + tau=self.tau, + ps=self.ps, + ) + elif self.cfg.backend in ["osqp", "cuosqp"]: + self.solver = OSQPSolver( + self.cfg, + self.y_len, + y=self.y, + coef=coef, + theta=self.theta, + tau=self.tau, + ps=self.ps, ) - if self.free_kernel: - dcv_cons = [ - self.c[:, 0] == cp.convolve(self.coef, self.s[:, 0])[: self.T] - ] - else: - self.theta = cp.Parameter( - value=self.theta, shape=self.theta.shape, name="theta" - ) - G_diag = sps.eye(self.T - 1) + sum( - [ - cp.diag(cp.promote(-self.theta[i], (self.T - i - 2,)), -i - 1) - for i in range(self.theta.shape[0]) - ] - ) # diag part of unshifted G - G = cp.bmat( - [ - [np.zeros((self.T - 1, 1)), G_diag], - [np.zeros((1, 1)), np.zeros((1, self.T - 1))], - ] - ) - dcv_cons = [self.s == G @ self.c] - edge_cons = [self.c[0, 0] == 0, self.s[-1, 0] == 0] - amp_cons = [self.s <= 1] - self.prob_free = cp.Problem(obj, dcv_cons + edge_cons) - self.prob = cp.Problem(obj, dcv_cons + edge_cons + amp_cons) - self._update_HG() # self.H and self.G not used for cvxpy problems - elif self.backend in ["osqp", "emosqp", "cuosqp"]: - # book-keeping - if y is None: - self.y = np.ones(self.y_len) - else: - self.y = y - if coef is None: - self.coef = np.ones(self.coef_len) - else: - self.coef = coef - self.c = np.zeros(self.T * upsamp) - self.s = np.zeros(self.T * upsamp) - self.s_bin = None - self.b = 0 - self.l1_penal = l1_penal - self.scale = scale - self.H = None - self._update_Wt() - self._setup_prob_osqp() + else: + raise ValueError(f"Unknown backend: {self.cfg.backend}") + + # State + self.T = self.solver.T + self.s = np.zeros(self.T) + self.b = 0 + self.c_bin = None + self.s_bin = None + # NOTE: do not store an "err_total" here. `_res_err` expects a residual, + # not the raw `y`, and this value was misleading and unused. + + # Update dashboard with initial kernel if self.dashboard is not None: - self.dashboard.update( - h=self.coef.value if backend == "cvxpy" else self.coef, - uid=self.dashboard_uid, - ) - tr_exp, _, _ = exp_pulse( - self.tau[0], - self.tau[1], - p_d=self.ps[0], - p_r=self.ps[1], - nsamp=self.coef_len, - ) - theta = self.theta.value if self.backend == "cvxpy" else self.theta - tr_ar, _, _ = ar_pulse(theta[0], theta[1], nsamp=self.coef_len, shifted=True) - assert (~np.isnan(coef)).all() - assert np.isclose( - tr_exp, coef, atol=self.atol - ).all(), "exp time constant inconsistent" - assert np.isclose( - tr_ar, coef, atol=self.atol - ).all(), "ar coefficients inconsistent" + self.dashboard.update(h=coef, uid=self.dashboard_uid) + + # Validate coefficients + self.solver.validate_coefficients(atol=atol) + + @property + def scale(self) -> float: + """Current scale value (delegated to solver).""" + return self.solver.scale + + @property + def H(self): + """Convolution matrix H.""" + return self.solver.H + + @property + def R(self): + """Resampling matrix R.""" + return self.solver.R + + @property + def R_org(self): + """Original (full) resampling matrix.""" + return self.solver.R_org + + @property + def nzidx_s(self): + """Nonzero indices for s.""" + return self.solver.nzidx_s + + @property + def nzidx_c(self): + """Nonzero indices for c.""" + return self.solver.nzidx_c + + @property + def coef(self): + """Coefficient kernel.""" + return self.solver.coef + + @property + def err_wt(self): + """Error weighting vector.""" + return self.solver.err_wt + + @property + def wgt_len(self): + """Error weighting length.""" + return self.solver.wgt_len + + @err_wt.setter + def err_wt(self, value): + """Allow direct assignment (used by tests/demo code).""" + self.solver.err_wt = np.array(value) + self.solver.Wt = sps.diags(self.solver.err_wt) def update( self, @@ -380,178 +280,111 @@ def update( clear_weighting: bool = False, scale_coef: bool = False, ) -> None: - logger.debug( - f"Updating parameters - backend: {self.backend}, tau: {tau}, scale: {scale}, scale_mul: {scale_mul}, l0_penal: {l0_penal}, l1_penal: {l1_penal}" + """Update parameters.""" + logger.debug(f"Updating parameters - backend: {self.cfg.backend}") + + theta_new = None + if tau is not None: + theta_new = np.array(tau2AR(tau[0], tau[1])) + p = solve_p(tau[0], tau[1]) + coef_new, _, _ = exp_pulse( + tau[0], + tau[1], + p_d=p, + p_r=-p, + nsamp=self.cfg.coef_len * self.cfg.upsamp, + kn_len=self.cfg.coef_len * self.cfg.upsamp, + ) + coef = coef_new + self.tau = tau + self.theta = theta_new + self.ps = np.array([p, -p]) + + if coef is not None and scale_coef: + current_coef = ( + self.solver.coef if self.solver.coef is not None else np.ones_like(coef) + ) + scale_mul = scal_lstsq(coef, current_coef).item() + + if l0_penal is not None: + self._l0_penal = l0_penal + if l1_penal is not None: + self._l1_penal = l1_penal + + # Forward updates to solver (solver handles scale directly) + self.solver.update( + y=y, + coef=coef, + scale=scale, + scale_mul=scale_mul, + l1_penal=self._l1_penal if l1_penal is not None else None, + l0_penal=self._l0_penal if l0_penal is not None else None, + w=w, + theta=theta_new if theta_new is not None else self.theta, + update_weighting=update_weighting, + clear_weighting=clear_weighting, + scale_coef=scale_coef, ) - if self.backend == "cvxpy": - if y is not None: - self.y.value = y - if tau is not None: - theta_new = np.array(tau2AR(tau[0], tau[1])) - p = solve_p(tau[0], tau[1]) - coef, _, _ = exp_pulse( - tau[0], - tau[1], - p_d=p, - p_r=-p, - nsamp=self.coef_len, - kn_len=self.coef_len, - ) - self.coef.value = coef - self.theta.value = theta_new - self._update_HG() - self._update_wgt_len() - if coef is not None: - if scale_coef: - scale_mul = scal_lstsq(coef, self.coef).item() - self.coef.value = coef - self._update_HG() - self._update_wgt_len() - if scale is not None: - self.scale.value = scale - if scale_mul is not None: - self.scale.value = scale_mul * self.scale.value - if l1_penal is not None: - self.l1_penal.value = l1_penal - if l0_penal is not None: - self.l0_penal = l0_penal - if w is not None: - self._update_w(w) - if l0_penal is not None or w is not None: - self.l0_w.value = self.l0_penal * self.w - elif self.backend in ["osqp", "emosqp", "cuosqp"]: - # update input params - if y is not None: - self.y = y - if tau is not None: - theta_new = np.array(tau2AR(tau[0], tau[1])) - p = solve_p(tau[0], tau[1]) - coef, _, _ = exp_pulse( - tau[0], - tau[1], - p_d=p, - p_r=-p, - nsamp=self.coef_len, - kn_len=self.coef_len, - ) - self.tau = tau - self.ps = np.array([p, -p]) - self.theta = theta_new - if coef is not None: - if scale_coef: - scale_mul = scal_lstsq(coef, self.coef).item() - self.coef = coef - if scale is not None: - self.scale = scale - if scale_mul is not None: - self.scale = scale_mul * self.scale - if l1_penal is not None: - self.l1_penal = l1_penal - if l0_penal is not None: - self.l0_penal = l0_penal - if w is not None: - self._update_w(w) - # update internal variables - updt_HG, updt_P, updt_A, updt_q0, updt_q, updt_bounds, setup_prob = [ - False - ] * 7 - if coef is not None: - self._update_HG() - self._update_wgt_len() - updt_HG = True - if self.err_weighting is not None and update_weighting: - self._update_Wt(clear=clear_weighting) - if self.err_weighting == "adaptive": - setup_prob = True - else: - updt_P = True - updt_q0 = True - updt_q = True - if self.norm == "huber": - if any((scale is not None, scale_mul is not None, updt_HG)): - self._update_A() - updt_A = True - if any( - (w is not None, l0_penal is not None, l1_penal is not None, updt_HG) - ): - self._update_q() - updt_q = True - if y is not None: - self._update_bounds() - updt_bounds = True + + if y is not None: + self.y = y + + def _pad_s(self, s: np.ndarray = None) -> np.ndarray: + """Pad sparse s to full length.""" + return self.solver._pad_s(s) + + def _pad_c(self, c: np.ndarray = None) -> np.ndarray: + """Pad sparse c to full length.""" + return self.solver._pad_c(c) + + def _reset_cache(self) -> None: + """Reset solver cache.""" + self.solver.reset_cache() + + def _reset_mask(self) -> None: + """Reset solver mask to full range.""" + self.solver.reset_mask() + + def _update_mask(self, use_wt: bool = False, amp_constraint: bool = True) -> None: + """Update mask based on current solution.""" + # CVXPY doesn't support masking + if self.cfg.backend == "cvxpy": + return + + if self.cfg.backend in ["osqp", "cuosqp"]: + if use_wt: + nzidx_s = np.where(self.R.T @ self.err_wt)[0] else: - if any((updt_HG, updt_A)): - A_before = self.A.copy() - self._update_A() - assert self.A.shape == A_before.shape - assert (self.A.nonzero()[0] == A_before.nonzero()[0]).all() - assert (self.A.nonzero()[1] == A_before.nonzero()[1]).all() - updt_A = True - if any((scale is not None, scale_mul is not None, updt_HG, updt_P)): - P_before = self.P.copy() - self._update_P() - assert self.P.shape == P_before.shape - assert (self.P.nonzero()[0] == P_before.nonzero()[0]).all() - assert (self.P.nonzero()[1] == P_before.nonzero()[1]).all() - updt_P = True - if any( - ( - scale is not None, - scale_mul is not None, - y is not None, - updt_HG, - updt_q0, - ) - ): - q0_before = self.q0.copy() - self._update_q0() - assert self.q0.shape == q0_before.shape - updt_q0 = True - if any( - ( - w is not None, - l0_penal is not None, - l1_penal is not None, - updt_q0, - updt_q, - ) - ): - q_before = self.q.copy() - self._update_q() - assert self.q.shape == q_before.shape - updt_q = True - # update prob - logger.debug(f"Updating optimization problem with {self.backend}") - if self.backend == "emosqp": - if updt_P: - self.prob_free.update_P(self.P.data, None, 0) - self.prob.update_P(self.P.data, None, 0) - if updt_q: - self.prob_free.update_lin_cost(self.q) - self.prob.update_lin_cost(self.q) - elif self.backend in ["osqp", "cuosqp"] and any( - (updt_P, updt_q, updt_A, updt_bounds, setup_prob) - ): - if setup_prob: - self._setup_prob_osqp() + if self.cfg.masking_radius is not None: + mask = np.zeros(self.T) + for nzidx in np.where(self._pad_s(self.s_bin) > 0)[0]: + start = max(nzidx - self.cfg.masking_radius, 0) + end = min(nzidx + self.cfg.masking_radius, self.T) + mask[start:end] = 1 + nzidx_s = np.where(mask)[0] else: - self.prob_free.update( - Px=self.P.copy().data if updt_P else None, - q=self.q.copy() if updt_q else None, - Ax=self.A.copy().data if updt_A else None, - l=self.lb.copy() if updt_bounds else None, - u=self.ub_inf.copy() if updt_bounds else None, - ) - self.prob.update( - Px=self.P.copy().data if updt_P else None, - q=self.q.copy() if updt_q else None, - Ax=self.A.copy().data if updt_A else None, - l=self.lb.copy() if updt_bounds else None, - u=self.ub.copy() if updt_bounds else None, - ) - logger.debug("Optimization problem updated") + self._reset_mask() + opt_s, _ = self.solve(amp_constraint) + nzidx_s = np.where(opt_s > self.cfg.delta_penal)[0] + + if len(nzidx_s) == 0: + logger.warning("Empty mask, resetting") + self._reset_mask() + return + + self.solver.set_mask(nzidx_s) + + # Verify mask is valid + if not self.cfg.free_kernel and len(self.nzidx_c) < self.T: + res = self.solver.prob.solve() + if res.info.status == "primal infeasible": + logger.warning("Mask caused primal infeasibility, resetting") + self._reset_mask() + else: + raise NotImplementedError("Masking not supported for cvxpy backend") def _cut_pks_labs(self, s, labs, pks): + """Cut peak labels at valleys between peaks.""" pk_labs = np.full_like(labs, -1) lb = 0 for ilab in range(labs.max() + 1): @@ -574,6 +407,8 @@ def _cut_pks_labs(self, s, labs, pks): def _merge_sparse_regs( self, s, regs, err_rtol=0, max_len=9, constraint_sum: bool = True ): + """Merge sparse regions to minimize error.""" + max_combos = 10_000 s_ret = s.copy() for r in range(regs.max() + 1): ridx = np.where(regs == r)[0] @@ -593,6 +428,9 @@ def _merge_sparse_regs( else: ns_vals = list(range(ns_min, rlen + 1)) for ns in ns_vals: + # Defensive guard: avoid combinatorial explosion. + if math.comb(rlen, ns) > max_combos: + continue for idxs in itt.combinations(ridx, ns): idxs = np.array(idxs) s_test = s_new.copy() @@ -600,28 +438,15 @@ def _merge_sparse_regs( err_after = self._compute_err(s=s_test[self.nzidx_s]) err_ls.append(err_after) idx_ls.append(idxs) - err_min_idx = np.argmin(err_ls) - err_min = err_ls[err_min_idx] - if err_min - err_before < err_rtol * err_before: - idx_min = idx_ls[err_min_idx] - s_new[idx_min] = rsum / len(idx_min) - s_ret = s_new - return s_ret - - def _pad_s(self, s=None): - if s is None: - s = self.s - s_ret = np.zeros(self.T) - s_ret[self.nzidx_s] = s + if len(err_ls) > 0: + err_min_idx = np.argmin(err_ls) + err_min = err_ls[err_min_idx] + if err_min - err_before < err_rtol * err_before: + idx_min = idx_ls[err_min_idx] + s_new[idx_min] = rsum / len(idx_min) + s_ret = s_new return s_ret - def _pad_c(self, c=None): - if c is None: - c = self.s - c_ret = np.zeros(self.T) - c_ret[self.nzidx_c] = c - return c_ret - def solve( self, amp_constraint: bool = True, @@ -630,24 +455,31 @@ def solve( pks_delta: float = 1e-5, pks_err_rtol: float = 10, pks_cut: bool = False, - ) -> np.ndarray: - if self.l0_penal == 0: - opt_s, opt_b = self._solve( - amp_constraint=amp_constraint, update_cache=update_cache - ) + ) -> Tuple[np.ndarray, float]: + """Solve main routine (l0 heuristic wrapper).""" + if self._l0_penal == 0: + opt_s, opt_b, _ = self.solver.solve(amp_constraint=amp_constraint) else: + # L0 heuristic via reweighted L1 metric_df = None - for i in range(self.max_iter_l0): - cur_s, cur_obj = self._solve(amp_constraint, return_obj=True) + for i in range(self.cfg.max_iter_l0): + cur_s, cur_b, _ = self.solver.solve(amp_constraint=amp_constraint) + # Compute objective explicitly since solver returns 0 + cur_obj = self._compute_err(s=cur_s, b=cur_b) + if metric_df is None: obj_best = np.inf obj_last = np.inf else: - obj_best = metric_df["obj"][1:].min() + obj_best = ( + metric_df["obj"][1:].min() if len(metric_df) > 1 else np.inf + ) obj_last = np.array(metric_df["obj"])[-1] - opt_s = np.where(cur_s > self.delta_l0, cur_s, 0) + + opt_s = np.where(cur_s > self.cfg.delta_l0, cur_s, 0) obj_gap = np.abs(cur_obj - obj_best) obj_delta = np.abs(cur_obj - obj_last) + cur_met = pd.DataFrame( [ { @@ -660,27 +492,30 @@ def solve( ] ) metric_df = pd.concat([metric_df, cur_met], ignore_index=True) - if any((obj_gap < self.rtol * np.obj_best, obj_delta < self.atol)): + + if any([obj_gap < self.cfg.rtol * obj_best, obj_delta < self.cfg.atol]): break else: - self.update( - w=np.clip( - np.ones(self.T) / (self.delta_l0 * np.ones(self.T) + opt_s), - 0, - 1e5, - ) - ) # clip to avoid numerical issues + w_new = np.clip( + np.ones(self.T) / (self.cfg.delta_l0 * np.ones(self.T) + opt_s), + 0, + 1e5, + ) + self.update(w=w_new) else: warnings.warn( - "l0 heuristic did not converge in {} iterations".format( - self.max_iter_l0 - ) + f"l0 heuristic did not converge in {self.cfg.max_iter_l0} iterations" ) + + opt_s, opt_b, _ = self.solver.solve(amp_constraint=amp_constraint) + self.b = opt_b + + # Peak polishing if pks_polish is None: pks_polish = amp_constraint - if pks_polish and self.backend != "cvxpy": - s_pad = self._pad_s(s=opt_s) + if pks_polish and self.cfg.backend != "cvxpy": + s_pad = self._pad_s(opt_s) if len(opt_s) == len(self.nzidx_s) else opt_s s_ft = np.where(s_pad > pks_delta, s_pad, 0) labs, _ = label(s_ft) labs = labs - 1 @@ -688,37 +523,125 @@ def solve( pks_idx, _ = find_peaks(s_ft) labs = self._cut_pks_labs(s=s_ft, labs=labs, pks=pks_idx) opt_s = self._merge_sparse_regs(s=s_ft, regs=labs, err_rtol=pks_err_rtol) - opt_s = opt_s[self.nzidx_s] + if len(opt_s) == self.T: + opt_s = opt_s[self.nzidx_s] + self.s = np.abs(opt_s) return self.s, self.b + def _compute_c(self, s: np.ndarray = None) -> np.ndarray: + """Compute c from s via convolution.""" + if s is not None: + return self.solver.convolve(s) + else: + return self.solver.convolve(self.s) + + def _res_err(self, r: np.ndarray) -> float: + """Compute residual error.""" + if self.err_wt is not None: + r = self.err_wt * r + if self.cfg.norm == "l1": + return np.sum(np.abs(r)) + elif self.cfg.norm == "l2": + return np.sum(r**2) + elif self.cfg.norm == "huber": + # True Huber loss: + # 0.5*r^2 if |r| <= k + # k*(|r| - 0.5*k) otherwise + k = float(self.solver.huber_k) + ar = np.abs(r) + quad = 0.5 * (r**2) + lin = k * (ar - 0.5 * k) + return float(np.sum(np.where(ar <= k, quad, lin))) + + def _compute_err( + self, + y_fit: np.ndarray = None, + b: float = None, + c: np.ndarray = None, + s: np.ndarray = None, + res: np.ndarray = None, + obj_crit: str = None, + ) -> float: + """Compute error/objective value.""" + y = np.array(self.y) + if res is not None: + y = y - res + if b is None: + b = self.b + y = y - b + + if y_fit is None: + if c is None: + c = self._compute_c(s) + R = self.R + if sps.issparse(c): + y_fit = np.array((R @ c * self.scale).todense()).squeeze() + else: + y_fit = np.array(R @ c * self.scale).squeeze() + + r = y - y_fit + err = self._res_err(r) + + if obj_crit in [None, "spk_diff"]: + return float(err) + else: + nspk = (s > 0).sum() if s is not None else (self.s > 0).sum() + if obj_crit == "mean_spk": + err_total = self._res_err(y - y.mean()) + return float((err - err_total) / max(nspk, 1)) + elif obj_crit in ["aic", "bic"]: + T = len(r) + mu = r.mean() + sigma = max(((r - mu) ** 2).sum() / T, 1e-10) + logL = -0.5 * ( + T * np.log(2 * np.pi * sigma) + 1 / sigma * ((r - mu) ** 2).sum() + ) + if obj_crit == "aic": + return float(2 * (nspk - logL)) + elif obj_crit == "bic": + return float(nspk * np.log(T) - 2 * logL) + return float(err) + def _max_thres(self, s, nz_only=True): + """Apply max thresholding to solution.""" S_ls, thres = max_thres( - s, - nthres=self.nthres, - th_min=self.th_min, - th_max=self.th_max, + np.array(s), + nthres=self.cfg.nthres, + th_min=self.cfg.th_min, + th_max=self.cfg.th_max, reverse_thres=True, return_thres=True, nz_only=nz_only, ) - if self.density_thres is not None: + # Ensure we return numpy arrays (not xarray.DataArray) + S_ls = [np.array(ss) for ss in S_ls] + + # Apply density threshold + if self.cfg.density_thres is not None: Sden = [ss.sum() / self.T for ss in S_ls] - S_ls = [ss for ss, den in zip(S_ls, Sden) if den < self.density_thres] - thres = [th for th, den in zip(thres, Sden) if den < self.density_thres] - if self.ncons_thres is not None: + S_ls = [ss for ss, den in zip(S_ls, Sden) if den < self.cfg.density_thres] + thres = [th for th, den in zip(thres, Sden) if den < self.cfg.density_thres] + + # Apply consecutive threshold + if self.cfg.ncons_thres is not None: S_pad = [self._pad_s(ss) for ss in S_ls] - Sncons = [max_consecutive(ss) for ss in S_pad] - if min(Sncons) < self.ncons_thres: + Sncons = [max_consecutive(np.array(ss)) for ss in S_pad] + if len(Sncons) > 0 and min(Sncons) < self.cfg.ncons_thres: S_ls = [ - ss for ss, ncons in zip(S_ls, Sncons) if ncons <= self.ncons_thres + ss + for ss, ncons in zip(S_ls, Sncons) + if ncons <= self.cfg.ncons_thres ] thres = [ - th for th, ncons in zip(thres, Sncons) if ncons <= self.ncons_thres + th + for th, ncons in zip(thres, Sncons) + if ncons <= self.cfg.ncons_thres ] - else: + elif len(S_ls) > 0: S_ls = [S_ls[0]] thres = [thres[0]] + return S_ls, thres def solve_thres( @@ -729,17 +652,21 @@ def solve_thres( return_intm: bool = False, pks_polish: bool = None, obj_crit: str = None, - ) -> Tuple[np.ndarray]: - if self.backend == "cvxpy": - y = np.array(self.y.value.squeeze()) - elif self.backend in ["osqp", "emosqp", "cuosqp"]: - y = np.array(self.y) + ) -> Tuple[np.ndarray, ...]: + """Solve with thresholding.""" + y = np.array(self.y) opt_s, opt_b = self.solve(amp_constraint=amp_constraint, pks_polish=pks_polish) - R = self.R.value if self.backend == "cvxpy" else self.R + R = self.R + if ignore_res: - res = y - opt_b - self.scale * R @ self._compute_c(opt_s) + c = self._compute_c(opt_s) + if sps.issparse(c): + res = y - opt_b - self.scale * np.array((R @ c).todense()).squeeze() + else: + res = y - opt_b - self.scale * (R @ c).squeeze() else: res = np.zeros_like(y) + svals, thres = self._max_thres(opt_s) if not len(svals) > 0: if return_intm: @@ -751,31 +678,62 @@ def solve_thres( 0, np.inf, ) + cvals = [self._compute_c(s) for s in svals] - yfvals = [np.array((R @ c).todense()).squeeze() for c in cvals] + + def to_arr(m): + return ( + np.array(m.todense()).squeeze() + if sps.issparse(m) + else np.array(m).squeeze() + ) + + yfvals = [to_arr(R @ c) for c in cvals] + if scaling: scal_fit = [scal_lstsq(yf, y - res, fit_intercept=True) for yf in yfvals] scals = [sf[0] for sf in scal_fit] bs = [sf[1] for sf in scal_fit] - if self.min_rel_scl is not None: - scl_thres = np.max(y) * self.min_rel_scl - valid_idx = np.where(scals > scl_thres)[0] + + if self.cfg.min_rel_scl is not None: + scl_thres = np.max(y) * self.cfg.min_rel_scl + valid_idx = np.where(np.array(scals) > scl_thres)[0] if len(valid_idx) > 0: + # Optional legacy compatibility: reproduce old deconv behavior where + # scale filtering shrinks `scals/bs` but does NOT shrink `svals/yfvals`. + # This leads to zip() truncation later and can change which candidate is selected. + legacy_bug = ( + os.environ.get("INDECA_LEGACY_SCALE_FILTER_BUG", "0") == "1" + ) scals = [scals[i] for i in valid_idx] bs = [bs[i] for i in valid_idx] + if not legacy_bug: + svals = [svals[i] for i in valid_idx] + cvals = [cvals[i] for i in valid_idx] + yfvals = [yfvals[i] for i in valid_idx] else: max_idx = np.argmax(scals) + legacy_bug = ( + os.environ.get("INDECA_LEGACY_SCALE_FILTER_BUG", "0") == "1" + ) scals = [scals[max_idx]] bs = [bs[max_idx]] + if not legacy_bug: + svals = [svals[max_idx]] + cvals = [cvals[max_idx]] + yfvals = [yfvals[max_idx]] else: scals = [self.scale] * len(yfvals) bs = [(y - res - scl * yf).mean() for scl, yf in zip(scals, yfvals)] + objs = [ self._compute_err(s=ss, y_fit=scl * yf, res=res, b=bb, obj_crit=obj_crit) for ss, scl, yf, bb in zip(svals, scals, yfvals, bs) ] + scals = np.array(scals).clip(0, None) objs = np.where(scals > 0, objs, np.inf) + if obj_crit == "spk_diff": err_null = self._compute_err( s=np.zeros_like(opt_s), res=res, b=opt_b, obj_crit=obj_crit @@ -784,17 +742,24 @@ def solve_thres( nspk = np.array([0] + [(ss > 0).sum() for ss in svals]) objs_diff = np.diff(objs_pad) nspk_diff = np.diff(nspk) + nspk_diff = np.where(nspk_diff == 0, 1, nspk_diff) # Avoid division by zero merr_diff = objs_diff / nspk_diff - avg_err = (objs_pad.min() - err_null) / nspk.max() - opt_idx = np.max(np.where(merr_diff < avg_err)) + avg_err = (objs_pad.min() - err_null) / max(nspk.max(), 1) + opt_idx = ( + int(np.max(np.where(merr_diff < avg_err)[0])) + if np.any(merr_diff < avg_err) + else 0 + ) objs = merr_diff else: - opt_idx = np.argmin(objs) + opt_idx = int(np.argmin(objs)) + s_bin = svals[opt_idx] self.s_bin = s_bin - assert len(s_bin) == len(self.nzidx_s) - self.c_bin = np.array(cvals[opt_idx].todense()).squeeze() + self.c_bin = to_arr(cvals[opt_idx]) self.b = bs[opt_idx] + self.solver.s_bin = s_bin # Update solver's s_bin for adaptive weighting + if return_intm: return ( self.s_bin, @@ -808,86 +773,89 @@ def solve_thres( def solve_penal( self, masking=True, scaling=True, return_intm=False, pks_polish=None - ) -> Tuple[np.ndarray]: - if self.penal is None: + ) -> Tuple[np.ndarray, ...]: + """Solve with penalty optimization via DIRECT.""" + if self.cfg.penal is None: opt_s, opt_c, opt_scl, opt_obj = self.solve_thres( scaling=scaling, return_intm=return_intm, pks_polish=pks_polish ) opt_penal = 0 - elif self.penal in ["l0", "l1"]: - pn = "{}_penal".format(self.penal) - self.update(**{pn: 0}) - if masking: - self._reset_cache() - self._update_mask() - s_nopn, _, _, err_nopn, intm = self.solve_thres( - scaling=scaling, return_intm=True, pks_polish=pks_polish - ) - s_min = intm[0] - ymean = self.y.mean() - err_full = self._compute_err(s=np.zeros(len(self.nzidx_s)), b=ymean) - err_min = self._compute_err(s=s_min) - ub, ub_last = err_full, err_full - for _ in range(int(np.ceil(np.log2(ub)))): - self.update(**{pn: ub}) - s, b = self.solve(pks_polish=pks_polish) - cur_err = self._compute_err(s=s, b=b) - # DIRECT finds weird solutions with high penalty and baseline, - # so we want to eliminate those possibilities - if np.abs(cur_err - err_min) < 0.5 * np.abs(err_full - err_min): - ub = ub_last - break - else: - ub_last = ub - ub = ub / 2 - - def opt_fn(x): - self.update(**{pn: x.item()}) - _, _, _, obj = self.solve_thres(scaling=False, pks_polish=pks_polish) - if self.dashboard is not None: - self.dashboard.update( - uid=self.dashboard_uid, - penal_err={"penal": x.item(), "scale": self.scale, "err": obj}, - ) - if obj < err_full: - return obj - else: - return np.inf + if return_intm: + return opt_s, opt_c, opt_scl, opt_obj, opt_penal, None + return opt_s, opt_c, opt_scl, opt_obj, opt_penal + + pn = f"{self.cfg.penal}_penal" + self.update(**{pn: 0}) + + if masking: + self._reset_cache() + self._update_mask() + + s_nopn, _, _, err_nopn, intm = self.solve_thres( + scaling=scaling, return_intm=True, pks_polish=pks_polish + ) + s_min = intm[0] + ymean = self.y.mean() + err_full = self._compute_err(s=np.zeros(len(self.nzidx_s)), b=ymean) + err_min = self._compute_err(s=s_min) + + # Find upper bound for penalty + ub, ub_last = err_full, err_full + for _ in range(int(np.ceil(np.log2(ub + 1)))): + self.update(**{pn: ub}) + s, b = self.solve(pks_polish=pks_polish) + cur_err = self._compute_err(s=s, b=b) + if np.abs(cur_err - err_min) < 0.5 * np.abs(err_full - err_min): + ub = ub_last + break + else: + ub_last = ub + ub = ub / 2 + + def opt_fn(x): + self.update(**{pn: float(x)}) + _, _, _, obj = self.solve_thres(scaling=False, pks_polish=pks_polish) + if self.dashboard is not None: + self.dashboard.update( + uid=self.dashboard_uid, + penal_err={"penal": float(x), "scale": self.scale, "err": obj}, + ) + return obj if obj < err_full else np.inf + try: res = direct( opt_fn, - bounds=[(0, ub)], - maxfun=self.max_iter_penal, + bounds=[(0, max(ub, 1e-6))], + maxfun=self.cfg.max_iter_penal, locally_biased=False, vol_tol=1e-2, ) direct_pn = res.x if not res.success: logger.warning( - "could not find optimal penalty within {} iterations".format( - res.nfev - ) + f"Could not find optimal penalty within {res.nfev} iterations" ) opt_penal = 0 elif err_nopn <= opt_fn(direct_pn): - # DIRECT seem to mistakenly report high penalty when 0 penalty attains better error opt_penal = 0 else: - opt_penal = direct_pn.item() - self.update(**{pn: opt_penal}) - if return_intm: - opt_s, opt_c, opt_scl, opt_obj, intm = self.solve_thres( - scaling=scaling, return_intm=return_intm, pks_polish=pks_polish - ) - else: - opt_s, opt_c, opt_scl, opt_obj = self.solve_thres( - scaling=scaling, return_intm=return_intm, pks_polish=pks_polish - ) - if opt_scl == 0: - logger.warning("could not find non-zero solution") + opt_penal = float(direct_pn) + except Exception as e: + logger.warning(f"DIRECT optimization failed: {e}") + opt_penal = 0 + + self.update(**{pn: opt_penal}) if return_intm: + opt_s, opt_c, opt_scl, opt_obj, intm = self.solve_thres( + scaling=scaling, return_intm=True, pks_polish=pks_polish + ) return opt_s, opt_c, opt_scl, opt_obj, opt_penal, intm else: + opt_s, opt_c, opt_scl, opt_obj = self.solve_thres( + scaling=scaling, pks_polish=pks_polish + ) + if opt_scl == 0: + logger.warning("Could not find non-zero solution") return opt_s, opt_c, opt_scl, opt_obj, opt_penal def solve_scale( @@ -898,32 +866,35 @@ def solve_scale( obj_crit: str = None, early_stop: bool = True, masking: bool = True, - ) -> Tuple[np.ndarray]: - if self.penal in ["l0", "l1"]: - pn = "{}_penal".format(self.penal) + ) -> Tuple[np.ndarray, ...]: + """Solve with iterative scale estimation.""" + if self.cfg.penal in ["l0", "l1"]: + pn = f"{self.cfg.penal}_penal" self.update(**{pn: 0}) + self._reset_cache() self._reset_mask() + if reset_scale: self.update(scale=1) s_free, _ = self.solve(amp_constraint=False) self.update(scale=np.ptp(s_free)) - else: - s_free = np.zeros(len(self.nzidx_s)) + metric_df = None - for i in range(self.max_iter_scal): + for i in range(self.cfg.max_iter_scal): if concur_penal: cur_s, cur_c, cur_scl, cur_obj_raw, cur_penal = self.solve_penal( scaling=i > 0, - pks_polish=self.pks_polish and (i > 1 or not reset_scale), + pks_polish=self.cfg.pks_polish and (i > 1 or not reset_scale), ) else: cur_penal = 0 cur_s, cur_c, cur_scl, cur_obj_raw = self.solve_thres( scaling=i > 0, - pks_polish=self.pks_polish and (i > 1 or not reset_scale), + pks_polish=self.cfg.pks_polish and (i > 1 or not reset_scale), obj_crit=obj_crit, ) + if self.dashboard is not None: pad_s = np.zeros(self.T) pad_s[self.nzidx_s] = cur_s @@ -933,6 +904,7 @@ def solve_scale( s=self.R_org @ pad_s, scale=cur_scl, ) + if metric_df is None: prev_scals = np.array([np.inf]) opt_obj = np.inf @@ -941,14 +913,16 @@ def solve_scale( last_scal = np.inf else: opt_idx = metric_df["obj"].idxmin() - opt_obj = metric_df.loc[opt_idx, "obj"].item() - opt_scal = metric_df.loc[opt_idx, "scale"].item() + opt_obj = metric_df.loc[opt_idx, "obj"] + opt_scal = metric_df.loc[opt_idx, "scale"] prev_scals = np.array(metric_df["scale"]) last_scal = prev_scals[-1] last_obj = np.array(metric_df["obj"])[-1] + y_wt = np.array(self.y * self.err_wt) err_tt = self._res_err(y_wt - y_wt.mean()) - cur_obj = (cur_obj_raw - err_tt) / err_tt + cur_obj = (cur_obj_raw - err_tt) / max(err_tt, 1e-10) + cur_met = pd.DataFrame( [ { @@ -963,47 +937,59 @@ def solve_scale( ] ) metric_df = pd.concat([metric_df, cur_met], ignore_index=True) - if self.err_weighting == "adaptive" and i <= 1: + + if self.cfg.err_weighting == "adaptive" and i <= 1: self.update(update_weighting=True) if masking and i >= 1: self._update_mask() + if any( - ( - np.abs(cur_scl - opt_scal) < self.rtol * opt_scal, - np.abs(cur_obj - opt_obj) < self.rtol * opt_obj, - np.abs(cur_scl - last_scal) < self.atol, - np.abs(cur_obj - last_obj) < self.atol * 1e-3, + [ + np.abs(cur_scl - opt_scal) < self.cfg.rtol * opt_scal, + np.abs(cur_obj - opt_obj) < self.cfg.rtol * opt_obj, + np.abs(cur_scl - last_scal) < self.cfg.atol, + np.abs(cur_obj - last_obj) < self.cfg.atol * 1e-3, early_stop and cur_obj > last_obj, - ) + ] ): break elif cur_scl == 0: - warnings.warn("exit with zero solution") + warnings.warn("Exit with zero solution") break - elif np.abs(cur_scl - prev_scals).min() < self.atol: + elif np.abs(cur_scl - prev_scals).min() < self.cfg.atol: self.update(scale=(cur_scl + last_scal) / 2) else: self.update(scale=cur_scl) else: - warnings.warn("max scale iterations reached") + warnings.warn("Max scale iterations reached") + + # Final solve with optimal scale opt_idx = metric_df["obj"].idxmin() self.update(update_weighting=True, clear_weighting=True) self._reset_cache() self._reset_mask() - self.update(scale=metric_df.loc[opt_idx, "scale"]) + self.update(scale=float(metric_df.loc[opt_idx, "scale"])) + cur_s, cur_c, cur_scl, cur_obj, cur_penal = self.solve_penal( - scaling=False, masking=False, pks_polish=self.pks_polish + scaling=False, masking=False, pks_polish=self.cfg.pks_polish ) - opt_s, opt_c = np.zeros(self.T), np.zeros(self.T) + + opt_s = np.zeros(self.T) + opt_c = np.zeros(self.T) opt_s[self.nzidx_s] = cur_s - opt_c[self.nzidx_c] = cur_c + opt_c[self.nzidx_c] = ( + cur_c if not sps.issparse(cur_c) else cur_c.toarray().squeeze() + ) nnz = int(opt_s.sum()) + self.update(update_weighting=True) y_wt = np.array(self.y * self.err_wt) err_tt = self._res_err(y_wt - y_wt.mean()) err_cur = self._compute_err(s=opt_s) - err_rel = (err_cur - err_tt) / err_tt + err_rel = (err_cur - err_tt) / max(err_tt, 1e-10) + self.update(update_weighting=True, clear_weighting=True) + if self.dashboard is not None: self.dashboard.update( uid=self.dashboard_uid, @@ -1011,556 +997,11 @@ def solve_scale( s=self.R_org @ opt_s, scale=cur_scl, ) + self._reset_cache() self._reset_mask() + if return_met: return opt_s, opt_c, cur_scl, cur_obj, err_rel, nnz, cur_penal, metric_df else: return opt_s, opt_c, cur_scl, cur_obj, err_rel, nnz, cur_penal - - def _setup_prob_osqp(self) -> None: - logger.debug("Setting up OSQP problem") - self._update_HG() - self._update_wgt_len() - self._update_P() - self._update_q0() - self._update_q() - self._update_A() - self._update_bounds() - if self.backend == "emosqp": - m = osqp.OSQP() - m.setup( - P=self.P, - q=self.q, - A=self.A, - l=self.lb, - u=self.ub_inf, - check_termination=25, - eps_abs=self.atol * 1e-4, - eps_rel=1e-8, - ) - m.codegen( - "osqp-codegen-prob_free", - parameters="matrices", - python_ext_name="emosqp_free", - force_rewrite=True, - ) - m.update(u=self.ub) - m.codegen( - "osqp-codegen-prob", - parameters="matrices", - python_ext_name="emosqp", - force_rewrite=True, - ) - import emosqp - import emosqp_free - - self.prob_free = emosqp_free - self.prob = emosqp - elif self.backend in ["osqp", "cuosqp"]: - if self.backend == "osqp": - self.prob_free = osqp.OSQP() - self.prob = osqp.OSQP() - elif self.backend == "cuosqp": - self.prob_free = cuosqp.OSQP() - self.prob = cuosqp.OSQP() - P_copy = self.P.copy() - q_copy = self.q.copy() - A_copy = self.A.copy() - lb_copy = self.lb.copy() - ub_inf_copy = self.ub_inf.copy() - self.prob_free.setup( - P=P_copy, - q=q_copy, - A=A_copy, - l=lb_copy, - u=ub_inf_copy, - verbose=False, - polish=True, - warm_start=False, - # adaptive_rho=False, - eps_abs=1e-6, - eps_rel=1e-6, - eps_prim_inf=1e-7, - eps_dual_inf=1e-7, - # max_iter=int(1e5) if self.backend == "osqp" else None, - # eps_prim_inf=1e-8, - ) - P_copy = self.P.copy() - q_copy = self.q.copy() - A_copy = self.A.copy() - lb_copy = self.lb.copy() - ub_copy = self.ub.copy() - self.prob.setup( - P=P_copy, - q=q_copy, - A=A_copy, - l=lb_copy, - u=ub_copy, - verbose=False, - polish=True, - warm_start=False, - # adaptive_rho=False, - eps_abs=1e-6, - eps_rel=1e-6, - eps_prim_inf=1e-7, - eps_dual_inf=1e-7, - # max_iter=int(1e5) if self.backend == "osqp" else None, - # eps_prim_inf=1e-8, - ) - logger.debug(f"{self.backend} setup completed successfully") - - def _solve( - self, - amp_constraint: bool = True, - return_obj: bool = False, - update_cache: bool = False, - ) -> np.ndarray: - if amp_constraint: - prob = self.prob - else: - prob = self.prob_free - # if self.backend in ["osqp", "emosqp", "cuosqp"] and self.x_cache is not None: - # prob.warm_start(x=self.x_cache) - res = prob.solve() - if self.backend == "cvxpy": - opt_s = self.s.value.squeeze() - opt_b = 0 - elif self.backend in ["osqp", "emosqp", "cuosqp"]: - x = res[0] if self.backend == "emosqp" else res.x - if res.info.status not in ["solved", "solved inaccurate"]: - warnings.warn("Problem not solved. status: {}".format(res.info.status)) - # osqp mistakenly report primal infeasibility when using masks - # with high l1 penalty. manually set solution to zero in such cases - if res.info.status in [ - "primal infeasible", - "primal infeasible inaccurate", - ]: - x = np.zeros_like(x, dtype=float) - else: - x = x.astype(float) - # if update_cache: - # self.x_cache = x - # prob.warm_start(x=x) - if self.norm == "huber": - xlen = len(self.nzidx_s) if self.free_kernel else len(self.nzidx_c) - sol = x[:xlen] - else: - sol = x - opt_b = sol[0] - if self.free_kernel: - opt_s = sol[1:] - else: - opt_s = self.G @ sol[1:] - if return_obj: - if self.backend == "cvxpy": - opt_obj = res - elif self.backend in ["osqp", "emosqp", "cuosqp"]: - opt_obj = self._compute_err() - return opt_s, opt_b, opt_obj - else: - return opt_s, opt_b - - def _compute_c(self, s: np.ndarray = None) -> np.ndarray: - if s is not None: - return self._convolve_s(s) - else: - if self.backend == "cvxpy": - return self.c.value.squeeze() - elif self.backend in ["osqp", "emosqp", "cuosqp"]: - return self._convolve_s(self.s) - - def _convolve_s(self, s: np.ndarray) -> sps.csc_array: - if self.H is not None: - return self.H @ sps.csc_matrix(s.reshape(-1, 1)) - else: - if s.dtype == np.bool_: - return sps.csc_matrix( - bin_convolve( - self.coef, s=s, nzidx_s=self.nzidx_s, s_len=self.T - ).reshape(-1, 1) - ) - else: - return sps.csc_matrix( - np.convolve(self.coef, self._pad_s(s))[self.nzidx_c].reshape(-1, 1) - ) - - def _compute_err( - self, - y_fit: np.ndarray = None, - b: np.ndarray = None, - c: np.ndarray = None, - s: np.ndarray = None, - res: np.ndarray = None, - obj_crit: str = None, - ) -> float: - if self.backend == "cvxpy": - # TODO: add support - raise NotImplementedError - elif self.backend in ["osqp", "emosqp", "cuosqp"]: - y = np.array(self.y) - if res is not None: - y = y - res - if b is None: - b = self.b - y = y - b - if y_fit is None: - if c is None: - c = self._compute_c(s) - y_fit = np.array((self.R @ c * self.scale).todense()).squeeze() - r = y - y_fit - err = self._res_err(r) - if obj_crit in [None, "spk_diff"]: - return np.array(err).item() - else: - nspk = (s > 0).sum() - if obj_crit == "mean_spk": - err_total = self._res_err(y - y.mean()) - return np.array((err - err_total) / nspk).item() - elif obj_crit in ["aic", "bic"]: - noise_model = "normal" - T = len(r) - if noise_model == "normal": - mu = r.mean() - sigma = ((r - mu) ** 2).sum() / T - logL = -0.5 * ( - T * np.log(2 * np.pi * sigma) - + 1 / sigma * ((r - mu) ** 2).sum() - ) - elif noise_model == "lognormal": - ymin = y.min() - logy = np.log(y - ymin + 1) - logy_hat = np.log(y_fit - ymin + 1) - logr = logy - logy_hat - mu = np.mean(logr) - sigma = ((logr - mu) ** 2).sum() / T - logL = np.sum( - -logy - - (logr - mu) ** 2 / (2 * sigma) - - 0.5 * np.log(2 * np.pi * sigma) - ) - if obj_crit == "aic": - return np.array(2 * (nspk - logL)).item() - elif obj_crit == "bic": - return np.array(nspk * np.log(T) - 2 * logL).item() - else: - raise ValueError("invalid objective criterion: {}".format(obj_crit)) - - def _res_err(self, r: np.ndarray): - if self.err_wt is not None: - r = self.err_wt * r - if self.norm == "l1": - return np.sum(np.abs(r)) - elif self.norm == "l2": - return np.sum((r) ** 2) - elif self.norm == "huber": - err_hub = huber(self.huber_k, r) - err_qud = r**2 / 2 - return np.sum(np.where(r >= 0, err_hub, err_qud)) - - def _reset_cache(self) -> None: - self.x_cache = None - - def _reset_mask(self) -> None: - self.nzidx_s = np.arange(self.T) - self.nzidx_c = np.arange(self.T) - self._update_R() - self._update_w() - if self.backend in ["osqp", "emosqp", "cuosqp"]: - self._setup_prob_osqp() - - def _update_mask(self, use_wt: bool = False, amp_constraint: bool = True) -> None: - if self.backend in ["osqp", "emosqp", "cuosqp"]: - if use_wt: - nzidx_s = np.where(self.R.T @ self.err_wt)[0] - else: - if self.masking_r is not None: - mask = np.zeros(self.T) - for nzidx in np.where(self._pad_s(self.s_bin) > 0)[0]: - mask[ - max(nzidx - self.masking_r, 0) : min( - nzidx + self.masking_r, self.T - ) - ] = 1 - nzidx_s = np.where(mask)[0] - else: - self._reset_mask() - opt_s, _ = self.solve(amp_constraint) - nzidx_s = np.where(opt_s > self.delta_penal)[0] - if len(nzidx_s) == 0: - raise ValueError - self.nzidx_s = nzidx_s - self._update_R() - self._update_w() - self._setup_prob_osqp() - if not self.free_kernel and len(self.nzidx_c) < self.T: - res = self.prob.solve() - # osqp mistakenly report primal infeasible in some cases - # disable masking in such cases - # potentially related: https://github.com/osqp/osqp/issues/485 - if res.info.status == "primal infeasible": - self._reset_mask() - else: - # TODO: add support - raise NotImplementedError("masking not supported for cvxpy backend") - - def _update_w(self, w_new=None) -> None: - if w_new is not None: - self.w_org = w_new - self.w = self.w_org[self.nzidx_s] - - def _update_R(self) -> None: - self.R_org = construct_R(self.y_len, self.upsamp) - self.R = self.R_org[:, self.nzidx_c] - - def _update_Wt(self, clear=False) -> None: - coef = self.coef.value if self.backend == "cvxpy" else self.coef - if clear: - logger.debug("Clearing error weighting") - self.err_wt = np.ones(self.y_len) - elif self.err_weighting == "fft": - logger.debug("Updating error weighting with fft") - hspec = self._get_stft_spec(coef)[:, int(self.coef_len / 2)] - self.err_wt = ( - (hspec.reshape(-1, 1) * self.yspec).sum(axis=0) - / np.linalg.norm(hspec) - / np.linalg.norm(self.yspec, axis=0) - ) - elif self.err_weighting == "corr": - logger.debug("Updating error weighting with corr") - for i in range(self.y_len): - yseg = self.y[i : i + self.coef_len] - if len(yseg) <= 1: - continue - cseg = coef[: len(yseg)] - with np.errstate(all="ignore"): - self.err_wt[i] = np.corrcoef(yseg, cseg)[0, 1].clip(0, 1) - self.err_wt = np.nan_to_num(self.err_wt) - elif self.err_weighting == "adaptive": - if self.s_bin is not None: - self.err_wt = np.zeros(self.y_len) - s_bin_R = self.R @ self._pad_s(self.s_bin) - for nzidx in np.where(s_bin_R > 0)[0]: - self.err_wt[nzidx : nzidx + self.wgt_len] = 1 - else: - self.err_wt = np.ones(self.y_len) - self.Wt = sps.diags(self.err_wt) - - def _update_HG(self) -> None: - coef = self.coef.value if self.backend == "cvxpy" else self.coef - if self.Hlim is None or self.T * self.coef_len < self.Hlim: - self.H_org = sps.diags( - [np.repeat(coef[i], self.T - i) for i in range(len(coef))], - offsets=-np.arange(len(coef)), - format="csc", - ) - try: - H_shape, H_nnz = self.H.shape, self.H.nnz - except AttributeError: - H_shape, H_nnz = None, None - self.H = self.H_org[:, self.nzidx_s][self.nzidx_c, :] - logger.debug( - f"Updating H matrix - shape before: {H_shape}, shape new: {self.H.shape}, nnz before: {H_nnz}, nnz new: {self.H.nnz}" - ) - if not self.free_kernel: - theta = self.theta.value if self.backend == "cvxpy" else self.theta - G_diag = sps.diags( - [np.ones(self.T - 1)] - + [np.repeat(-theta[i], self.T - 2 - i) for i in range(theta.shape[0])], - offsets=np.arange(0, -theta.shape[0] - 1, -1), - format="csc", - ) - self.G_org = sps.bmat( - [[None, G_diag], [np.zeros((1, 1)), None]], format="csc" - ) - try: - G_shape, G_nnz = self.G.shape, self.G.nnz - except AttributeError: - G_shape, G_nnz = None, None - self.G = self.G_org[:, self.nzidx_c][self.nzidx_s, :] - logger.debug( - f"Updating G matrix - shape before: {G_shape}, shape new: {self.G.shape}, nnz before: {G_nnz}, nnz new: {self.G.nnz}" - ) - # assert np.isclose( - # np.linalg.pinv(self.H.todense()), self.G.todense(), atol=self.atol - # ).all() - - def _update_wgt_len(self) -> None: - coef = self.coef.value if self.backend == "cvxpy" else self.coef - if self.wt_trunc_thres is not None: - trunc_len = int( - np.around(np.where(coef > self.wt_trunc_thres)[0][-1] / self.upsamp) - ) - if trunc_len == 0: - trunc_len = int(np.around(np.where(coef > 0)[0][-1] / self.upsamp)) - self.wgt_len = max(min(self.coef_len, trunc_len), 1) - else: - self.wgt_len = self.coef_len - - def _get_stft_spec(self, x: np.ndarray) -> np.ndarray: - spec = np.abs(self.stft.stft(x)) ** 2 - t = self.stft.t(len(x)) - t_mask = np.logical_and(t >= 0, t < len(x)) - return spec[:, t_mask] - - def _get_M(self) -> sps.csc_matrix: - if self.free_kernel: - return sps.hstack( - [ - np.ones((self.R.shape[0], 1)), - self.scale * self.R @ self.H, - ], - format="csc", - ) - else: - return sps.hstack( - [np.ones((self.R.shape[0], 1)), self.scale * self.R], format="csc" - ) - - def _update_P(self) -> None: - if self.norm == "l1": - # TODO: add support - raise NotImplementedError( - "l1 norm not yet supported with backend {}".format(self.backend) - ) - elif self.norm == "l2": - M = self._get_M() - P = M.T @ self.Wt.T @ self.Wt @ M - elif self.norm == "huber": - lc, ls, ly = len(self.nzidx_c), len(self.nzidx_s), self.y_len - if self.free_kernel: - P = sps.bmat( - [ - [sps.csc_matrix((ls, ls)), None, None], - [None, sps.csc_matrix((ly, ly)), None], - [None, None, sps.eye(ly, format="csc")], - ] - ) - else: - P = sps.bmat( - [ - [sps.csc_matrix((lc, lc)), None, None], - [None, sps.csc_matrix((ly, ly)), None], - [None, None, sps.eye(ly, format="csc")], - ] - ) - try: - P_shape, P_nnz = self.P.shape, self.P.nnz - except AttributeError: - P_shape, P_nnz = None, None - logger.debug( - f"Updating P matrix - shape before: {P_shape}, shape new: {P.shape}, nnz before: {P_nnz}, nnz new: {P.nnz}" - ) - self.P = sps.triu(P).tocsc() - - def _update_q0(self) -> None: - if self.norm == "l1": - # TODO: add support - raise NotImplementedError( - "l1 norm not yet supported with backend {}".format(self.backend) - ) - elif self.norm == "l2": - M = self._get_M() - self.q0 = -M.T @ self.Wt.T @ self.Wt @ self.y - elif self.norm == "huber": - ly = self.y_len - lx = len(self.nzidx_s) if self.free_kernel else len(self.nzidx_c) - self.q0 = ( - np.concatenate([np.zeros(lx), np.ones(ly), np.ones(ly)]) * self.huber_k - ) - - def _update_q(self) -> None: - if self.norm == "l1": - # TODO: add support - raise NotImplementedError( - "l1 norm not yet supported with backend {}".format(self.backend) - ) - elif self.norm == "l2": - if self.free_kernel: - ww = np.concatenate([np.zeros(1), self.w]) - qq = np.concatenate([np.zeros(1), np.ones_like(self.w)]) - self.q = self.q0 + self.l0_penal * ww + self.l1_penal * qq - else: - G_p = sps.hstack([np.zeros((self.G.shape[0], 1)), self.G], format="csc") - self.q = ( - self.q0 - + self.l0_penal * self.w @ G_p - + self.l1_penal * np.ones(self.G.shape[0]) @ G_p - ) - elif self.norm == "huber": - pad_k = np.zeros(self.y_len) - if self.free_kernel: - self.q = ( - self.q0 - + self.l0_penal * np.concatenate([self.w, pad_k, pad_k]) - + self.l1_penal - * np.concatenate([np.ones(len(self.nzidx_s)), pad_k, pad_k]) - ) - else: - self.q = ( - self.q0 - + self.l0_penal * np.concatenate([self.w @ self.G, pad_k, pad_k]) - + self.l1_penal - * np.concatenate([np.ones(self.G.shape[0]) @ self.G, pad_k, pad_k]) - ) - - def _update_A(self) -> None: - if self.free_kernel: - Ax = sps.eye(len(self.nzidx_s), format="csc") - Ar = self.scale * self.R @ self.H - else: - Ax = sps.csc_matrix(self.G_org[:, self.nzidx_c]) - # record spike terms that requires constraint - self.nzidx_A = np.where((Ax != 0).sum(axis=1))[0] - Ax = Ax[self.nzidx_A, :] - Ar = self.scale * self.R - try: - A_shape, A_nnz = self.A.shape, self.A.nnz - except AttributeError: - A_shape, A_nnz = None, None - if self.norm == "huber": - e = sps.eye(self.y_len, format="csc") - self.A = sps.bmat( - [ - [Ax, None, None], - [None, e, None], - [None, None, -e], - [Ar, e, e], - ], - format="csc", - ) - else: - self.A = sps.bmat([[np.ones((1, 1)), None], [None, Ax]], format="csc") - logger.debug( - f"Updating A matrix - shape before: {A_shape}, shape new: {self.A.shape}, nnz before: {A_nnz}, nnz new: {self.A.nnz}" - ) - - def _update_bounds(self) -> None: - if self.norm == "huber": - xlen = len(self.nzidx_s) if self.free_kernel else self.T - self.lb = np.concatenate( - [np.zeros(xlen + self.y_len * 2), self.y - self.huber_k] - ) - self.ub = np.concatenate( - [np.ones(xlen), np.full(self.y_len * 2, np.inf), self.y - self.huber_k] - ) - self.ub_inf = np.concatenate( - [np.full(xlen + self.y_len * 2, np.inf), self.y - self.huber_k] - ) - else: - bb = np.clip(self.y.mean(), 0, None) if self.use_base else 0 - if self.free_kernel: - self.lb = np.zeros(len(self.nzidx_s) + 1) - self.ub = np.concatenate([np.full(1, bb), np.ones(len(self.nzidx_s))]) - self.ub_inf = np.concatenate( - [np.full(1, bb), np.full(len(self.nzidx_s), np.inf)] - ) - else: - ub_pad, ub_inf_pad = np.zeros(self.T), np.zeros(self.T) - ub_pad[self.nzidx_s] = 1 - ub_inf_pad[self.nzidx_s] = np.inf - self.lb = np.zeros(len(self.nzidx_A) + 1) - self.ub = np.concatenate([np.full(1, bb), ub_pad[self.nzidx_A]]) - self.ub_inf = np.concatenate([np.full(1, bb), ub_inf_pad[self.nzidx_A]]) - assert (self.ub >= self.lb).all() - assert (self.ub_inf >= self.lb).all() diff --git a/src/indeca/core/deconv/solver.py b/src/indeca/core/deconv/solver.py new file mode 100644 index 0000000..d40caa4 --- /dev/null +++ b/src/indeca/core/deconv/solver.py @@ -0,0 +1,913 @@ +"""Solver implementations for deconv.""" + +from abc import ABC, abstractmethod +from typing import Any, Tuple, Optional +import warnings + +import cvxpy as cp +import numpy as np +import osqp +import scipy.sparse as sps +from scipy.special import huber +from scipy.signal import ShortTimeFFT + +from indeca.utils.logging_config import get_module_logger +from indeca.core.simulation import tau2AR, solve_p, exp_pulse, ar_pulse +from indeca.utils.utils import scal_lstsq +from .config import DeconvConfig +from .utils import construct_R, bin_convolve, get_stft_spec + +logger = get_module_logger("deconv_solver") + +# Try to import GPU solver +try: + import cuosqp + + HAS_CUOSQP = True +except ImportError: + HAS_CUOSQP = False + logger.debug("cuosqp not available") + + +class DeconvSolver(ABC): + """Abstract base class for deconvolution solvers.""" + + def __init__( + self, + config: DeconvConfig, + y_len: int, + y: np.ndarray | None = None, + coef: np.ndarray | None = None, + theta: np.ndarray | None = None, + tau: np.ndarray | None = None, + ps: np.ndarray | None = None, + ): + self.cfg = config + self.y_len = y_len + self.T = y_len * self.cfg.upsamp + self.y = y if y is not None else np.zeros(y_len) + self.coef = coef + self.coef_len = ( + len(coef) if coef is not None else config.coef_len * config.upsamp + ) + self.theta = theta + self.tau = tau + self.ps = ps + + # Scale tracking (mutable, since config is frozen) + self.scale = config.scale + + # Penalty tracking + self.l0_penal = 0.0 + self.l1_penal = 0.0 + + # Weight vectors + self.w_org = np.ones(self.T) + self.w = np.ones(self.T) + + # Masking indices + self.nzidx_s = np.arange(self.T) + self.nzidx_c = np.arange(self.T) + + # Matrices + self.R_org = construct_R(self.y_len, self.cfg.upsamp) + self.R = self.R_org + self.H = None + self.H_org = None + self.G = None + self.G_org = None + + # Cache + self.x_cache = None + self.s_bin = None # Binary spike solution from thresholding + + # Error weighting + self.err_wt = np.ones(self.y_len) + self.wgt_len = self.coef_len + self.Wt = sps.diags(self.err_wt) + + # Huber parameter + self.huber_k = 0.5 * np.std(self.y) if y is not None else 0 + + @abstractmethod + def update(self, **kwargs): + """Update solver parameters.""" + pass + + @abstractmethod + def solve(self, amp_constraint: bool = True) -> Tuple[np.ndarray, float, Any]: + """Solve the optimization problem.""" + pass + + def reset_cache(self) -> None: + """Reset solution cache.""" + self.x_cache = None + + def reset_mask(self) -> None: + """Reset masks to full range.""" + self.nzidx_s = np.arange(self.T) + self.nzidx_c = np.arange(self.T) + self._update_R() + self._update_w() + + def set_mask(self, nzidx_s: np.ndarray, nzidx_c: np.ndarray = None): + """Set mask indices. Override in subclasses that don't support masking.""" + self.nzidx_s = nzidx_s + # Old behavior (from `old deconv.py`): masking is applied to spike indices (s) + # while keeping the calcium state indices (c) unmasked unless explicitly provided. + if nzidx_c is not None: + self.nzidx_c = nzidx_c + self._update_R() + self._update_w() + + def _update_R(self) -> None: + """Update R matrix based on mask.""" + self.R = self.R_org[:, self.nzidx_c] + + def _update_w(self, w_new: np.ndarray = None) -> None: + """Update weight vector.""" + if w_new is not None: + self.w_org = w_new + self.w = self.w_org[self.nzidx_s] + + def _pad_s(self, s: np.ndarray = None) -> np.ndarray: + """Pad sparse s to full length.""" + if s is None: + s = np.zeros(len(self.nzidx_s)) + s_ret = np.zeros(self.T) + s_ret[self.nzidx_s] = s + return s_ret + + def _pad_c(self, c: np.ndarray = None) -> np.ndarray: + """Pad sparse c to full length.""" + if c is None: + c = np.zeros(len(self.nzidx_c)) + c_ret = np.zeros(self.T) + c_ret[self.nzidx_c] = c + return c_ret + + def _update_HG(self) -> None: + """Update H (convolution) and G (AR inverse) matrices.""" + coef = self.coef + if coef is None: + return + + # H matrix: convolution matrix + # IMPORTANT: in free-kernel mode the optimization uses R @ H explicitly, + # so H must always be materialized (do not drop it based on Hlim). + if ( + self.cfg.free_kernel + or self.cfg.Hlim is None + or self.T * len(coef) < self.cfg.Hlim + ): + self.H_org = sps.diags( + [np.repeat(coef[i], self.T - i) for i in range(len(coef))], + offsets=-np.arange(len(coef)), + format="csc", + ) + self.H = self.H_org[:, self.nzidx_s][self.nzidx_c, :] + logger.debug(f"Updated H matrix - shape: {self.H.shape}, nnz: {self.H.nnz}") + else: + self.H = None + self.H_org = None + + # G matrix: AR inverse (only if theta provided and not free_kernel) + if not self.cfg.free_kernel and self.theta is not None: + theta = self.theta + G_diag = sps.diags( + [np.ones(self.T - 1)] + + [np.repeat(-theta[i], self.T - 2 - i) for i in range(theta.shape[0])], + offsets=np.arange(0, -theta.shape[0] - 1, -1), + format="csc", + ) + self.G_org = sps.bmat( + [[None, G_diag], [np.zeros((1, 1)), None]], format="csc" + ) + self.G = self.G_org[:, self.nzidx_c][self.nzidx_s, :] + logger.debug(f"Updated G matrix - shape: {self.G.shape}, nnz: {self.G.nnz}") + else: + self.G = None + self.G_org = None + + def _update_wgt_len(self) -> None: + """Update error weighting length based on coefficient truncation.""" + coef = self.coef + if coef is None: + return + if self.cfg.wt_trunc_thres is not None: + trunc_idx = np.where(coef > self.cfg.wt_trunc_thres)[0] + if len(trunc_idx) > 0: + trunc_len = int(np.around(trunc_idx[-1] / self.cfg.upsamp)) + else: + trunc_len = int(np.around(np.where(coef > 0)[0][-1] / self.cfg.upsamp)) + if trunc_len == 0: + trunc_len = 1 + self.wgt_len = max(min(self.coef_len, trunc_len), 1) + else: + self.wgt_len = self.coef_len + + def convolve(self, s: np.ndarray) -> sps.csc_matrix: + """Convolve signal s with kernel. Returns sparse column matrix.""" + if self.cfg.free_kernel: + assert ( + self.H is not None + ), "Invariant violated: free_kernel=True requires a materialized H matrix" + if self.H is not None: + # Check if s is masked length or full length + if len(s) == len(self.nzidx_s): + result = self.H @ sps.csc_matrix(s.reshape(-1, 1)) + elif len(s) == self.T: + result = self.H @ sps.csc_matrix(s[self.nzidx_s].reshape(-1, 1)) + else: + logger.warning( + f"Shape mismatch in convolve: s={len(s)}, nzidx_s={len(self.nzidx_s)}" + ) + result = sps.csc_matrix(np.zeros((len(self.nzidx_c), 1))) + return result + else: + # Use bin_convolve for efficiency when H is not stored + if s.dtype == np.bool_: + out = bin_convolve(self.coef, s, nzidx_s=self.nzidx_s, s_len=self.T) + else: + s_pad = self._pad_s(s) if len(s) == len(self.nzidx_s) else s + out = np.convolve(self.coef, s_pad)[: self.T] + return sps.csc_matrix(out[self.nzidx_c].reshape(-1, 1)) + + def validate_coefficients(self, atol: float = 1e-3) -> bool: + """Validate that AR and exponential coefficients are consistent.""" + if self.tau is None or self.ps is None or self.theta is None: + logger.debug("Skipping coefficient validation - missing tau/ps/theta") + return True + + try: + # Generate exponential pulse + tr_exp, _, _ = exp_pulse( + self.tau[0], + self.tau[1], + p_d=self.ps[0], + p_r=self.ps[1], + nsamp=self.coef_len, + ) + + # Generate AR pulse + theta = self.theta + tr_ar, _, _ = ar_pulse( + theta[0], theta[1], nsamp=self.coef_len, shifted=True + ) + + # Validate + if not (~np.isnan(self.coef)).all(): + logger.warning("Coefficient array contains NaN values") + return False + + if not np.isclose(tr_exp, self.coef[: len(tr_exp)], atol=atol).all(): + logger.warning("Exp time constant inconsistent with coefficients") + return False + + if not np.isclose(tr_ar, self.coef[: len(tr_ar)], atol=atol).all(): + logger.warning("AR coefficients inconsistent with coefficients") + return False + + logger.debug("Coefficient validation passed") + return True + except Exception as e: + logger.warning(f"Coefficient validation failed: {e}") + return False + + +class CVXPYSolver(DeconvSolver): + """CVXPY backend solver.""" + + def __init__(self, config: DeconvConfig, y_len: int, **kwargs): + super().__init__(config, y_len, **kwargs) + self._update_HG() + self._update_wgt_len() + self._setup_problem() + + def set_mask(self, nzidx_s: np.ndarray, nzidx_c: np.ndarray = None): + """CVXPY does not support masking - raise error.""" + if len(nzidx_s) != self.T: + raise NotImplementedError( + "CVXPY backend does not support masking. Use OSQP backend instead." + ) + super().set_mask(nzidx_s, nzidx_c) + + def reset_mask(self) -> None: + """CVXPY does not support masking - no-op since problem is already full.""" + # CVXPY builds the full problem once, no mask support + # Just reset indices without rebuilding + self.nzidx_s = np.arange(self.T) + self.nzidx_c = np.arange(self.T) + + def _setup_problem(self): + """Setup CVXPY optimization problem.""" + # NOTE: `free_kernel=True` is forbidden with CVXPY backend (see `DeconvConfig`). + self.cp_R = cp.Constant(self.R, name="R") + self.cp_c = cp.Variable((self.T, 1), nonneg=True, name="c") + self.cp_s = cp.Variable( + (self.T, 1), nonneg=True, name="s", boolean=self.cfg.mixin + ) + self.cp_y = cp.Parameter(shape=(self.y_len, 1), name="y") + self.cp_huber_k = cp.Parameter( + value=float(self.huber_k), nonneg=True, name="huber_k" + ) + + self.cp_scale = cp.Parameter(value=self.scale, name="scale", nonneg=True) + self.cp_l1_penal = cp.Parameter(value=0.0, name="l1_penal", nonneg=True) + self.cp_l0_w = cp.Parameter( + shape=self.T, value=np.zeros(self.T), nonneg=True, name="w_l0" + ) + + if self.y is not None: + self.cp_y.value = self.y.reshape((-1, 1)) + + if self.cfg.use_base: + self.cp_b = cp.Variable(nonneg=True, name="b") + else: + self.cp_b = cp.Constant(value=0, name="b") + + # Error term based on norm + term = self.cp_y - self.cp_scale * self.cp_R @ self.cp_c - self.cp_b + if self.cfg.norm == "l1": + self.err_term = cp.sum(cp.abs(term)) + elif self.cfg.norm == "l2": + self.err_term = cp.sum_squares(term) + elif self.cfg.norm == "huber": + # Keep huber parameter consistent with OSQP backend's `huber_k`. + self.err_term = cp.sum(cp.huber(term, M=self.cp_huber_k)) + + # Objective + obj_expr = ( + self.err_term + + self.cp_l0_w.T @ cp.abs(self.cp_s) + + self.cp_l1_penal * cp.sum(cp.abs(self.cp_s)) + ) + obj = cp.Minimize(obj_expr) + + # Constraints + # AR constraint via G matrix + self.cp_theta = cp.Parameter( + value=self.theta, shape=self.theta.shape, name="theta" + ) + G_diag = sps.eye(self.T - 1) + sum( + [ + cp.diag(cp.promote(-self.cp_theta[i], (self.T - i - 2,)), -i - 1) + for i in range(self.theta.shape[0]) + ] + ) + G = cp.bmat( + [ + [np.zeros((self.T - 1, 1)), G_diag], + [np.zeros((1, 1)), np.zeros((1, self.T - 1))], + ] + ) + dcv_cons = [self.cp_s == G @ self.cp_c] + + edge_cons = [self.cp_c[0, 0] == 0, self.cp_s[-1, 0] == 0] + amp_cons = [self.cp_s <= 1] + + self.prob_free = cp.Problem(obj, dcv_cons + edge_cons) + self.prob = cp.Problem(obj, dcv_cons + edge_cons + amp_cons) + + def update( + self, + y: np.ndarray = None, + coef: np.ndarray = None, + scale: float = None, + scale_mul: float = None, + l1_penal: float = None, + l0_penal: float = None, + w: np.ndarray = None, + theta: np.ndarray = None, + **kwargs, + ): + """Update CVXPY parameters.""" + if y is not None: + self.y = y + self.cp_y.value = y.reshape((-1, 1)) + # Keep huber_k consistent with OSQP backend / deconv objective. + self.huber_k = 0.5 * np.std(self.y) + self.cp_huber_k.value = float(self.huber_k) + if coef is not None: + self.coef = coef + self._update_HG() + self._update_wgt_len() + if scale is not None: + self.scale = scale + self.cp_scale.value = scale + if scale_mul is not None: + self.scale *= scale_mul + self.cp_scale.value = self.scale + if l1_penal is not None: + self.l1_penal = l1_penal + self.cp_l1_penal.value = l1_penal + if l0_penal is not None: + self.l0_penal = l0_penal + if w is not None: + self._update_w(w) + if l0_penal is not None or w is not None: + self.cp_l0_w.value = self.l0_penal * self.w + if theta is not None and hasattr(self, "cp_theta"): + self.theta = theta + self.cp_theta.value = theta + + def solve(self, amp_constraint: bool = True) -> Tuple[np.ndarray, float, Any]: + """Solve CVXPY problem.""" + prob = self.prob if amp_constraint else self.prob_free + try: + res = prob.solve() + except cp.error.SolverError as e: + logger.warning(f"CVXPY SolverError: {e}") + res = np.inf + + opt_s = ( + self.cp_s.value.squeeze() + if self.cp_s.value is not None + else np.zeros(self.T) + ) + opt_b = 0 + if ( + self.cfg.use_base + and hasattr(self.cp_b, "value") + and self.cp_b.value is not None + ): + opt_b = float(self.cp_b.value) + + return opt_s, opt_b, res + + +class OSQPSolver(DeconvSolver): + """OSQP backend solver (also handles cuosqp for GPU).""" + + def __init__(self, config: DeconvConfig, y_len: int, **kwargs): + super().__init__(config, y_len, **kwargs) + + # Additional state for OSQP + self.prob = None + self.prob_free = None + self.P = None + self.q = None + self.q0 = None + self.A = None + self.lb = None + self.ub = None + self.ub_inf = None + self.nzidx_A = None + + # STFT for FFT weighting + if self.cfg.err_weighting == "fft": + self.stft = ShortTimeFFT(win=np.ones(self.coef_len), hop=1, fs=1) + self.yspec = get_stft_spec(self.y, self.stft) + + # Initialize matrices and problem + self._update_HG() + self._update_wgt_len() + self._update_Wt() + self._setup_prob_osqp() + + def reset_mask(self) -> None: + """Reset masks to full range and rebuild OSQP problems.""" + super().reset_mask() + self._update_HG() + self._setup_prob_osqp() + + def set_mask(self, nzidx_s: np.ndarray, nzidx_c: np.ndarray = None): + """Set mask and rebuild problem.""" + super().set_mask(nzidx_s, nzidx_c) + self._update_HG() + self._setup_prob_osqp() + + def _update_Wt(self, clear: bool = False) -> None: + """Update error weighting matrix.""" + coef = self.coef + if clear: + logger.debug("Clearing error weighting") + self.err_wt = np.ones(self.y_len) + elif self.cfg.err_weighting == "fft" and hasattr(self, "stft"): + logger.debug("Updating error weighting with fft") + hspec = get_stft_spec(coef, self.stft)[:, int(len(coef) / 2)] + self.err_wt = ( + (hspec.reshape(-1, 1) * self.yspec).sum(axis=0) + / np.linalg.norm(hspec) + / np.linalg.norm(self.yspec, axis=0) + ) + elif self.cfg.err_weighting == "corr": + logger.debug("Updating error weighting with corr") + self.err_wt = np.ones(self.y_len) + for i in range(self.y_len): + yseg = self.y[i : i + len(coef)] + if len(yseg) <= 1: + continue + cseg = coef[: len(yseg)] + with np.errstate(all="ignore"): + self.err_wt[i] = np.corrcoef(yseg, cseg)[0, 1].clip(0, 1) + self.err_wt = np.nan_to_num(self.err_wt) + elif self.cfg.err_weighting == "adaptive": + if self.s_bin is not None: + self.err_wt = np.zeros(self.y_len) + s_bin_R = self.R @ self._pad_s(self.s_bin) + for nzidx in np.where(s_bin_R > 0)[0]: + self.err_wt[nzidx : nzidx + self.wgt_len] = 1 + else: + self.err_wt = np.ones(self.y_len) + + self.Wt = sps.diags(self.err_wt) + + def _get_M(self) -> sps.csc_matrix: + """Get the combined model matrix M = [1, scale*R] or [1, scale*R@H].""" + if self.cfg.free_kernel: + return sps.hstack( + [np.ones((self.R.shape[0], 1)), self.scale * self.R @ self.H], + format="csc", + ) + else: + return sps.hstack( + [np.ones((self.R.shape[0], 1)), self.scale * self.R], + format="csc", + ) + + def _update_P(self) -> None: + """Update quadratic cost matrix P.""" + if self.cfg.norm == "l1": + raise NotImplementedError("l1 norm not yet supported with OSQP backend") + elif self.cfg.norm == "l2": + M = self._get_M() + w = self.err_wt # shape (y_len,) + # Use row-scaling: M.T @ W^2 @ M == (W @ M).T @ (W @ M) + Mw = M.multiply(w[:, None]) # = diag(w) @ M + P = Mw.T @ Mw + + + elif self.cfg.norm == "huber": + lc = len(self.nzidx_c) + ls = len(self.nzidx_s) + ly = self.y_len + if self.cfg.free_kernel: + P = sps.bmat( + [ + [sps.csc_matrix((ls + 1, ls + 1)), None, None], + [None, sps.csc_matrix((ly, ly)), None], + [None, None, sps.eye(ly, format="csc")], + ] + ) + else: + P = sps.bmat( + [ + [sps.csc_matrix((lc + 1, lc + 1)), None, None], + [None, sps.csc_matrix((ly, ly)), None], + [None, None, sps.eye(ly, format="csc")], + ] + ) + + self.P = sps.triu(P).tocsc() + logger.debug(f"Updated P matrix - shape: {self.P.shape}, nnz: {self.P.nnz}") + + def _update_q0(self) -> None: + """Update linear cost base q0.""" + if self.cfg.norm == "l1": + raise NotImplementedError("l1 norm not yet supported with OSQP backend") + elif self.cfg.norm == "l2": + M = self._get_M() + w = self.err_wt + # Use row-scaling: M.T @ W^2 @ y == (W @ M).T @ (W @ y) + Mw = M.multiply(w[:, None]) # = diag(w) @ M + y = self.y.reshape(-1) # safe for (y_len,) or (y_len,1) + yw = w * y # elementwise + self.q0 = -(Mw.T @ yw) + elif self.cfg.norm == "huber": + ly = self.y_len + lx = ( + len(self.nzidx_s) + 1 if self.cfg.free_kernel else len(self.nzidx_c) + 1 + ) + self.q0 = ( + np.concatenate([np.zeros(lx), np.ones(ly), np.ones(ly)]) * self.huber_k + ) + + def _update_q(self) -> None: + """Update linear cost vector q (including penalties).""" + if self.cfg.norm == "l1": + raise NotImplementedError("l1 norm not yet supported with OSQP backend") + elif self.cfg.norm == "l2": + if self.cfg.free_kernel: + ww = np.concatenate([np.zeros(1), self.w]) + qq = np.concatenate([np.zeros(1), np.ones_like(self.w)]) + self.q = self.q0 + self.l0_penal * ww + self.l1_penal * qq + else: + G_p = sps.hstack([np.zeros((self.G.shape[0], 1)), self.G], format="csc") + self.q = ( + self.q0 + + self.l0_penal * self.w @ G_p + + self.l1_penal * np.ones(self.G.shape[0]) @ G_p + ) + elif self.cfg.norm == "huber": + pad_k = np.zeros(self.y_len) + if self.cfg.free_kernel: + self.q = ( + self.q0 + + self.l0_penal * np.concatenate([[0], self.w, pad_k, pad_k]) + + self.l1_penal + * np.concatenate([[0], np.ones(len(self.nzidx_s)), pad_k, pad_k]) + ) + else: + self.q = ( + self.q0 + + self.l0_penal + * np.concatenate([[0], self.w @ self.G, pad_k, pad_k]) + + self.l1_penal + * np.concatenate( + [[0], np.ones(self.G.shape[0]) @ self.G, pad_k, pad_k] + ) + ) + + def _update_A(self) -> None: + """Update constraint matrix A.""" + if self.cfg.free_kernel: + Ax = sps.eye(len(self.nzidx_s), format="csc") + Ar = self.scale * self.R @ self.H + else: + Ax = sps.csc_matrix(self.G_org[:, self.nzidx_c]) + # Record spike terms that require constraint + self.nzidx_A = np.where((Ax != 0).sum(axis=1))[0] + Ax = Ax[self.nzidx_A, :] + Ar = self.scale * self.R + + if self.cfg.norm == "huber": + e = sps.eye(self.y_len, format="csc") + self.A = sps.bmat( + [ + [sps.csc_matrix((Ax.shape[0], 1)), Ax, None, None], + [None, None, e, None], + [None, None, None, -e], + [np.ones((Ar.shape[0], 1)), Ar, e, e], + ], + format="csc", + ) + else: + self.A = sps.bmat([[np.ones((1, 1)), None], [None, Ax]], format="csc") + + logger.debug(f"Updated A matrix - shape: {self.A.shape}, nnz: {self.A.nnz}") + + def _update_bounds(self) -> None: + """Update constraint bounds.""" + if self.cfg.norm == "huber": + xlen = len(self.nzidx_s) if self.cfg.free_kernel else len(self.nzidx_A) + self.lb = np.concatenate( + [np.zeros(xlen + self.y_len * 2), self.y - self.huber_k] + ) + self.ub = np.concatenate( + [np.ones(xlen), np.full(self.y_len * 2, np.inf), self.y - self.huber_k] + ) + self.ub_inf = np.concatenate( + [np.full(xlen + self.y_len * 2, np.inf), self.y - self.huber_k] + ) + else: + bb = np.clip(self.y.mean(), 0, None) if self.cfg.use_base else 0 + if self.cfg.free_kernel: + self.lb = np.zeros(len(self.nzidx_s) + 1) + self.ub = np.concatenate([np.full(1, bb), np.ones(len(self.nzidx_s))]) + self.ub_inf = np.concatenate( + [np.full(1, bb), np.full(len(self.nzidx_s), np.inf)] + ) + else: + ub_pad = np.zeros(self.T) + ub_inf_pad = np.zeros(self.T) + ub_pad[self.nzidx_s] = 1 + ub_inf_pad[self.nzidx_s] = np.inf + self.lb = np.zeros(len(self.nzidx_A) + 1) + self.ub = np.concatenate([np.full(1, bb), ub_pad[self.nzidx_A]]) + self.ub_inf = np.concatenate([np.full(1, bb), ub_inf_pad[self.nzidx_A]]) + + assert (self.ub >= self.lb).all(), "Upper bounds must be >= lower bounds" + assert ( + self.ub_inf >= self.lb + ).all(), "Upper bounds (inf) must be >= lower bounds" + + def _setup_prob_osqp(self) -> None: + """Setup OSQP problem instances.""" + logger.debug("Setting up OSQP problem") + + self._update_P() + self._update_q0() + self._update_q() + self._update_A() + self._update_bounds() + + # Choose solver backend + if self.cfg.backend == "cuosqp": + if not HAS_CUOSQP: + logger.warning("cuosqp not available, falling back to osqp") + self.prob = osqp.OSQP() + self.prob_free = osqp.OSQP() + else: + self.prob = cuosqp.OSQP() + self.prob_free = cuosqp.OSQP() + elif self.cfg.backend == "emosqp": + # Stub: emosqp requires codegen, not supported in this refactor + logger.warning("emosqp requires codegen, using osqp instead") + self.prob = osqp.OSQP() + self.prob_free = osqp.OSQP() + else: + self.prob = osqp.OSQP() + self.prob_free = osqp.OSQP() + + # Setup constrained problem + self.prob.setup( + P=self.P.copy(), + q=self.q.copy(), + A=self.A.copy(), + l=self.lb.copy(), + u=self.ub.copy(), + verbose=False, + polish=True, + warm_start=False, + eps_abs=1e-6, + eps_rel=1e-6, + eps_prim_inf=1e-7, + eps_dual_inf=1e-7, + ) + + # Setup unconstrained (free) problem + self.prob_free.setup( + P=self.P.copy(), + q=self.q.copy(), + A=self.A.copy(), + l=self.lb.copy(), + u=self.ub_inf.copy(), + verbose=False, + polish=True, + warm_start=False, + eps_abs=1e-6, + eps_rel=1e-6, + eps_prim_inf=1e-7, + eps_dual_inf=1e-7, + ) + + logger.debug(f"{self.cfg.backend} setup completed successfully") + + def update( + self, + y: np.ndarray = None, + coef: np.ndarray = None, + tau: np.ndarray = None, + theta: np.ndarray = None, + scale: float = None, + scale_mul: float = None, + l1_penal: float = None, + l0_penal: float = None, + w: np.ndarray = None, + update_weighting: bool = False, + clear_weighting: bool = False, + scale_coef: bool = False, + **kwargs, + ): + """Update OSQP problem parameters.""" + logger.debug(f"Updating OSQP solver parameters") + + # Update input parameters + if y is not None: + self.y = y + # Match legacy behavior: huber_k tracks the current y (used in q0 and bounds) + self.huber_k = 0.5 * np.std(self.y) + if tau is not None: + theta_new = np.array(tau2AR(tau[0], tau[1])) + p = solve_p(tau[0], tau[1]) + coef_new, _, _ = exp_pulse( + tau[0], tau[1], p_d=p, p_r=-p, nsamp=self.coef_len, kn_len=self.coef_len + ) + self.tau = tau + self.ps = np.array([p, -p]) + self.theta = theta_new + coef = coef_new + if theta is not None: + self.theta = theta + if coef is not None: + if scale_coef and self.coef is not None: + scale_mul = scal_lstsq(coef, self.coef).item() + self.coef = coef + if scale is not None: + self.scale = scale + if scale_mul is not None: + self.scale *= scale_mul + if l1_penal is not None: + self.l1_penal = l1_penal + if l0_penal is not None: + self.l0_penal = l0_penal + if w is not None: + self._update_w(w) + + # Track what needs updating + updt_HG = coef is not None + updt_P = False + updt_q0 = False + updt_q = False + updt_A = False + updt_bounds = False + setup_prob = False + + if updt_HG: + self._update_HG() + self._update_wgt_len() + + if self.cfg.err_weighting is not None and update_weighting: + self._update_Wt(clear=clear_weighting) + if self.cfg.err_weighting == "adaptive": + setup_prob = True + else: + updt_P = True + updt_q0 = True + updt_q = True + + if self.cfg.norm == "huber": + # huber_k changes require recomputing q and bounds + if y is not None: + self._update_q0() + updt_q0 = True + if any([scale is not None, scale_mul is not None, updt_HG]): + self._update_A() + updt_A = True + if any( + [w is not None, l0_penal is not None, l1_penal is not None, updt_HG] + ): + self._update_q() + updt_q = True + if y is not None: + self._update_bounds() + updt_bounds = True + else: + if any([updt_HG, updt_A]): + self._update_A() + updt_A = True + if any([scale is not None, scale_mul is not None, updt_HG, updt_P]): + self._update_P() + updt_P = True + if any( + [ + scale is not None, + scale_mul is not None, + y is not None, + updt_HG, + updt_q0, + ] + ): + self._update_q0() + updt_q0 = True + if any( + [ + w is not None, + l0_penal is not None, + l1_penal is not None, + updt_q0, + updt_q, + ] + ): + self._update_q() + updt_q = True + + # Apply updates to OSQP - conservative approach: + # Only q can be updated in-place safely. For P, A, bounds, rebuild. + if setup_prob or any([updt_P, updt_A, updt_bounds]): + self._setup_prob_osqp() + elif updt_q: + self.prob.update(q=self.q) + self.prob_free.update(q=self.q) + + logger.debug("OSQP problem updated") + + def solve(self, amp_constraint: bool = True) -> Tuple[np.ndarray, float, Any]: + """Solve OSQP problem.""" + prob = self.prob if amp_constraint else self.prob_free + res = prob.solve() + + if res.info.status not in ["solved", "solved inaccurate"]: + logger.warning(f"OSQP not solved: {res.info.status}") + if res.info.status in ["primal infeasible", "primal infeasible inaccurate"]: + x = np.zeros(self.P.shape[0], dtype=float) + else: + x = ( + res.x.astype(float) + if res.x is not None + else np.zeros(self.P.shape[0], dtype=float) + ) + else: + x = res.x + + if self.cfg.norm == "huber": + xlen = ( + len(self.nzidx_s) + 1 if self.cfg.free_kernel else len(self.nzidx_c) + 1 + ) + sol = x[:xlen] + opt_b = sol[0] + if self.cfg.free_kernel: + opt_s = sol[1:] + else: + opt_s = self.G @ sol[1:] + else: + opt_b = x[0] + if self.cfg.free_kernel: + opt_s = x[1:] + else: + c_sol = x[1:] + opt_s = self.G @ c_sol + + # Return 0 for objective - caller should use _compute_err for correct objective + return opt_s, opt_b, 0 diff --git a/src/indeca/core/deconv/utils.py b/src/indeca/core/deconv/utils.py new file mode 100644 index 0000000..e806446 --- /dev/null +++ b/src/indeca/core/deconv/utils.py @@ -0,0 +1,121 @@ +"""Utility functions for deconv module.""" + +import numpy as np +import scipy.sparse as sps +from numba import njit +from scipy.signal import ShortTimeFFT +from indeca.core.simulation import tau2AR + + +def get_stft_spec(x: np.ndarray, stft: ShortTimeFFT) -> np.ndarray: + """Compute STFT spectrogram.""" + spec = np.abs(stft.stft(x)) ** 2 + t = stft.t(len(x)) + t_mask = np.logical_and(t >= 0, t < len(x)) + return spec[:, t_mask] + + +def construct_R(T: int, up_factor: int): + """Construct the resampling matrix R.""" + if up_factor > 1: + return sps.csc_matrix( + ( + np.ones(T * up_factor), + (np.repeat(np.arange(T), up_factor), np.arange(T * up_factor)), + ), + shape=(T, T * up_factor), + ) + else: + return sps.eye(T, format="csc") + + +def sum_downsample(a, factor): + """Sum downsample array a by factor.""" + return np.convolve(a, np.ones(factor), mode="full")[factor - 1 :: factor] + + +def construct_G(fac: np.ndarray, T: int, fromTau=False): + """Construct the generator matrix G.""" + # I think we should be able to remove fromTau argument since we don't use it anywhere. + fac = np.array(fac) + assert fac.shape == (2,) + if fromTau: + fac = np.array(tau2AR(*fac)) + return sps.dia_matrix( + ( + np.tile(np.concatenate(([1], -fac)), (T, 1)).T, + -np.arange(len(fac) + 1), + ), + shape=(T, T), + ).tocsc() + + +def max_thres( + a: np.ndarray, + nthres: int, + th_min=0.1, + th_max=0.9, + ds=None, + return_thres=False, + th_amplitude=False, + delta=1e-6, + reverse_thres=False, + nz_only: bool = False, +): + """Threshold array a with nthres levels.""" + # Accept any array-like; normalized to numpy. + a = np.asarray(a) + amax = a.max() + if reverse_thres: + thres = np.linspace(th_max, th_min, nthres) + else: + thres = np.linspace(th_min, th_max, nthres) + if th_amplitude: + S_ls = [np.floor_divide(a, (amax * th).clip(delta, None)) for th in thres] + else: + S_ls = [(a > (amax * th).clip(delta, None)) for th in thres] + if ds is not None: + S_ls = [sum_downsample(s, ds) for s in S_ls] + if nz_only: + Snz = [ss.sum() > 0 for ss in S_ls] + S_ls = [ss for ss, nz in zip(S_ls, Snz) if nz] + thres = [th for th, nz in zip(thres, Snz) if nz] + if return_thres: + return S_ls, thres + else: + return S_ls + + +@njit(nopython=True, nogil=True, cache=True) +def bin_convolve( + coef: np.ndarray, s: np.ndarray, nzidx_s: np.ndarray = None, s_len: int = None +): + """Binary convolution implemented in numba.""" + coef_len = len(coef) + if s_len is None: + s_len = len(s) + out = np.zeros(s_len) + nzidx = np.where(s)[0] + if nzidx_s is not None: + nzidx = nzidx_s[nzidx].astype( + np.int64 + ) # astype to fix numpa issues on GPU on Windows + for i0 in nzidx: + i1 = min(i0 + coef_len, s_len) + clen = i1 - i0 + out[i0:i1] += coef[:clen] + return out + + +@njit(nopython=True, nogil=True, cache=True) +def max_consecutive(arr): + """Find maximum consecutive ones.""" + max_count = 0 + current_count = 0 + for value in arr: + if value: + current_count += 1 + max_count = max(max_count, current_count) + else: + current_count = 0 + return max_count diff --git a/src/indeca/pipeline/__init__.py b/src/indeca/pipeline/__init__.py index 487e269..9af47cf 100644 --- a/src/indeca/pipeline/__init__.py +++ b/src/indeca/pipeline/__init__.py @@ -1,3 +1,69 @@ -from .pipeline import pipeline_bin +"""Binary pursuit deconvolution pipeline. -__all__ = ["pipeline_bin"] +This package provides the binary pursuit pipeline for spike inference +from calcium imaging traces. + +Usage (recommended, config-based API):: + + from indeca.pipeline import pipeline_bin, DeconvPipelineConfig + + config = DeconvPipelineConfig( + up_factor=2, + convergence=ConvergenceConfig(max_iters=20), + ) + opt_C, opt_S, metrics = pipeline_bin(Y, config=config) + +Usage (legacy, deprecated):: + + from indeca.pipeline import pipeline_bin + + opt_C, opt_S, metrics = pipeline_bin(Y, up_factor=2, max_iters=20) + +""" + +# New config-based API (recommended) +from .binary_pursuit import pipeline_bin as pipeline_bin_new +from .config import ( + ARUpdateConfig, + ConvergenceConfig, + DeconvPipelineConfig, + DeconvStageConfig, + InitConfig, + PreprocessConfig, +) + +# Legacy API (deprecated, for backward compatibility) +from .pipeline import pipeline_bin, pipeline_bin_legacy + +# Type definitions +from .types import ( + ARParams, + ARUpdateResult, + ConvergenceResult, + DeconvStepResult, + IterationState, + PipelineResult, +) + +__all__ = [ + # Main entry point (legacy for backward compat, emits deprecation warning) + "pipeline_bin", + # New config-based entry point + "pipeline_bin_new", + # Legacy explicit name + "pipeline_bin_legacy", + # Configuration classes + "DeconvPipelineConfig", + "PreprocessConfig", + "InitConfig", + "DeconvStageConfig", + "ARUpdateConfig", + "ConvergenceConfig", + # Type definitions + "ARParams", + "DeconvStepResult", + "ARUpdateResult", + "ConvergenceResult", + "IterationState", + "PipelineResult", +] diff --git a/src/indeca/pipeline/ar_update.py b/src/indeca/pipeline/ar_update.py new file mode 100644 index 0000000..e281946 --- /dev/null +++ b/src/indeca/pipeline/ar_update.py @@ -0,0 +1,301 @@ +"""AR parameter update functions. + +Handles spike selection, AR estimation, and parameter propagation. +""" + +from typing import Any, List, Optional, Tuple + +import numpy as np +import pandas as pd +from scipy.signal import find_peaks + +from indeca.core.AR_kernel import updateAR +from indeca.core.deconv import construct_R + +from .types import ARUpdateResult + + +def select_best_spikes( + S_ls: List[np.ndarray], + scal_ls: List[np.ndarray], + err_rel: np.ndarray, + metric_df: pd.DataFrame, + *, + n_best: Optional[int], + i_iter: int, + tau_init: Optional[Tuple[float, float]], +) -> Tuple[np.ndarray, np.ndarray, np.ndarray, pd.DataFrame]: + """Select best spikes based on n_best iterations. + + Parameters + ---------- + S_ls : list of np.ndarray + Spike trains from all iterations + scal_ls : list of np.ndarray + Scale factors from all iterations + err_rel : np.ndarray + Relative errors from current iteration + metric_df : pd.DataFrame + Accumulated metrics + n_best : int or None + Number of best iterations to use + i_iter : int + Current iteration index + tau_init : tuple or None + Initial tau values (affects metric selection) + + Returns + ------- + S_best : np.ndarray + Best spike trains, shape (ncell, T * up_factor) + scal_best : np.ndarray + Best scale factors, shape (ncell,) + err_wt : np.ndarray + Error weights (negative err_rel), shape (ncell,) + metric_df : pd.DataFrame + Updated metric DataFrame with best_idx column + """ + S = S_ls[-1] # Current iteration spikes + scale = scal_ls[-1] # Current iteration scales + + metric_df = metric_df.set_index(["iter", "cell"]) + + if n_best is not None and i_iter >= n_best: + ncell = S.shape[0] + S_best = np.empty_like(S) + scal_best = np.empty_like(scale) + err_wt = np.empty_like(err_rel) + + if tau_init is not None: + metric_best = metric_df + else: + metric_best = metric_df.loc[1:, :] + + for icell, cell_met in metric_best.groupby("cell", sort=True): + cell_met = cell_met.reset_index().sort_values("obj", ascending=True) + cur_idx = np.array(cell_met["iter"][:n_best]) + metric_df.loc[(i_iter, icell), "best_idx"] = ",".join(cur_idx.astype(str)) + S_best[icell, :] = np.sum( + np.stack([S_ls[i][icell, :] for i in cur_idx], axis=0), axis=0 + ) > (n_best / 2) + scal_best[icell] = np.mean([scal_ls[i][icell] for i in cur_idx]) + err_wt[icell] = -np.mean( + [metric_df.loc[(i, icell), "err_rel"] for i in cur_idx] + ) + else: + S_best = S + scal_best = scale + err_wt = -err_rel + + metric_df = metric_df.reset_index() + return S_best, scal_best, err_wt, metric_df + + +def make_S_ar( + S_best: np.ndarray, + *, + est_nevt: Optional[int], + T: int, + up_factor: int, + ar_kn_len: int, +) -> np.ndarray: + """Create spike train for AR estimation with optional peak masking. + + Parameters + ---------- + S_best : np.ndarray + Best spike trains, shape (ncell, T * up_factor) + est_nevt : int or None + Number of top events to use. None uses all spikes. + T : int + Original trace length + up_factor : int + Upsampling factor + ar_kn_len : int + AR kernel length + + Returns + ------- + np.ndarray + Spike train for AR estimation, shape (ncell, T * up_factor) + """ + if est_nevt is not None: + S_ar = [] + R = construct_R(T, up_factor) + + for s in S_best: + Rs = R @ s + s_pks, pk_prop = find_peaks(Rs, height=1, distance=ar_kn_len * up_factor) + pk_ht = pk_prop["peak_heights"] + top_idx = s_pks[np.argsort(pk_ht)[-est_nevt:]] + mask = np.zeros_like(Rs, dtype=bool) + mask[top_idx] = True + Rs_ma = Rs * mask + s_ma = np.zeros_like(s) + s_ma[::up_factor] = Rs_ma + S_ar.append(s_ma) + + S_ar = np.stack(S_ar, axis=0) + else: + S_ar = S_best + + return S_ar + + +def update_ar_parameters( + Y: np.ndarray, + S_ar: np.ndarray, + scal_best: np.ndarray, + err_wt: np.ndarray, + *, + ar_use_all: bool, + ar_kn_len: int, + ar_norm: str, + ar_prop_best: Optional[float], + up_factor: int, + p: int, + ncell: int, + dashboard: Any, +) -> Tuple[np.ndarray, np.ndarray, np.ndarray, np.ndarray]: + """Update AR parameters based on current spike estimates. + + Parameters + ---------- + Y : np.ndarray + Input traces, shape (ncell, T) + S_ar : np.ndarray + Spike trains for AR estimation, shape (ncell, T * up_factor) + scal_best : np.ndarray + Best scale factors, shape (ncell,) + err_wt : np.ndarray + Error weights, shape (ncell,) + ar_use_all : bool + Whether to use all cells for shared AR update + ar_kn_len : int + AR kernel length + ar_norm : str + Norm for AR fitting + ar_prop_best : float or None + Proportion of best cells to use + up_factor : int + Upsampling factor + p : int + AR model order + ncell : int + Number of cells + dashboard : Dashboard or None + Dashboard instance + + Returns + ------- + tau : np.ndarray + Updated time constants, shape (ncell, 2) + ps : np.ndarray + Updated peak coefficients + h : np.ndarray + Impulse response + h_fit : np.ndarray + Fitted impulse response + """ + if ar_use_all: + # Shared AR update across cells + if ar_prop_best is not None: + ar_nbest = max(int(np.round(ar_prop_best * ncell)), 1) + ar_best_idx = np.argsort(err_wt)[-ar_nbest:] + else: + ar_best_idx = slice(None) + + cur_tau, ps, ar_scal, h, h_fit = updateAR( + Y[ar_best_idx], + S_ar[ar_best_idx], + scal_best[ar_best_idx], + N=p, + h_len=ar_kn_len * up_factor, + norm=ar_norm, + up_factor=up_factor, + ) + + if dashboard is not None: + dashboard.update( + h=h[: ar_kn_len * up_factor], + h_fit=h_fit[: ar_kn_len * up_factor], + ) + + tau = np.tile(cur_tau, (ncell, 1)) + else: + # Per-cell AR update + tau = np.empty((ncell, p)) + + # NOTE: Original pipeline only retained the last cell's ps/h/h_fit + # when ar_use_all=False. We preserve this behavior explicitly. + ps = None + h = None + h_fit = None + + for icell, (y, s) in enumerate(zip(Y, S_ar)): + cur_tau, cur_ps, ar_scal, cur_h, cur_h_fit = updateAR( + y, + s, + scal_best[icell], + N=p, + h_len=ar_kn_len, + norm=ar_norm, + up_factor=up_factor, + ) + + if dashboard is not None: + dashboard.update(uid=icell, h=cur_h, h_fit=cur_h_fit) + + tau[icell, :] = cur_tau + + # Overwrite on each iteration; only last cell's values are kept + ps = cur_ps + h = cur_h + h_fit = cur_h_fit + + return tau, ps, h, h_fit + + +def propagate_ar_update( + deconvolvers: List[Any], + tau: np.ndarray, + scal_best: np.ndarray, + *, + ar_use_all: bool, + da_client: Any, +) -> None: + """Propagate AR parameter updates to deconvolvers. + + Parameters + ---------- + deconvolvers : list + List of DeconvBin instances + tau : np.ndarray + Updated time constants, shape (ncell, 2) + scal_best : np.ndarray + Best scale factors, shape (ncell,) + ar_use_all : bool + Whether using shared AR (affects which tau to use) + da_client : Client or None + Dask client for distributed execution + """ + if ar_use_all: + # All cells share the same tau (use tau[0]) + cur_tau = tau[0] + for idx, d in enumerate(deconvolvers): + if da_client is not None: + da_client.submit( + lambda dd: dd.update(tau=cur_tau, scale=scal_best[idx]), d + ) + else: + d.update(tau=cur_tau, scale=scal_best[idx]) + else: + # Per-cell tau + for idx, d in enumerate(deconvolvers): + if da_client is not None: + da_client.submit( + lambda dd: dd.update(tau=tau[idx], scale=scal_best[idx]), + deconvolvers[idx], + ) + else: + d.update(tau=tau[idx], scale=scal_best[idx]) diff --git a/src/indeca/pipeline/binary_pursuit.py b/src/indeca/pipeline/binary_pursuit.py new file mode 100644 index 0000000..902e2b7 --- /dev/null +++ b/src/indeca/pipeline/binary_pursuit.py @@ -0,0 +1,359 @@ +"""Binary pursuit deconvolution pipeline. + +This module contains the main pipeline_bin function that orchestrates +the entire deconvolution process in a readable, top-down manner. +""" + +from typing import Any, Optional, Tuple, Union + +import numpy as np +import pandas as pd +from line_profiler import profile +from tqdm.auto import trange + +from indeca.core.simulation import tau2AR +from indeca.dashboard.dashboard import Dashboard +from indeca.utils.logging_config import get_module_logger + +from .ar_update import ( + make_S_ar, + propagate_ar_update, + select_best_spikes, + update_ar_parameters, +) +from .config import DeconvPipelineConfig +from .convergence import check_convergence +from .init import initialize_ar_params, initialize_deconvolvers +from .iteration import run_deconv_step +from .metrics import append_metrics, make_cur_metric, update_dashboard +from .preprocess import preprocess_traces +from .types import IterationState + +logger = get_module_logger("pipeline") + + +@profile +def pipeline_bin( + Y: np.ndarray, + *, + config: DeconvPipelineConfig, + da_client: Any = None, + spawn_dashboard: bool = True, + return_iter: bool = False, +) -> Union[ + Tuple[np.ndarray, np.ndarray, pd.DataFrame], + Tuple[np.ndarray, np.ndarray, pd.DataFrame, list, list, list, list], +]: + """Binary pursuit pipeline for spike inference. + + This is the main entry point for the deconvolution pipeline. + It orchestrates preprocessing, initialization, iterative deconvolution, + AR updates, and convergence checking. + + Parameters + ---------- + Y : np.ndarray + Input fluorescence traces, shape (ncell, T) + config : DeconvPipelineConfig + Pipeline configuration + da_client : Client or None + Dask client for distributed execution. None for local execution. + spawn_dashboard : bool + Whether to spawn a real-time dashboard + return_iter : bool + Whether to return per-iteration results + + Returns + ------- + opt_C : np.ndarray + Optimal calcium traces, shape (ncell, T * up_factor) + opt_S : np.ndarray + Optimal spike trains, shape (ncell, T * up_factor) + metric_df : pd.DataFrame + Per-iteration metrics + C_ls : list (only if return_iter=True) + Calcium traces per iteration + S_ls : list (only if return_iter=True) + Spike trains per iteration + h_ls : list (only if return_iter=True) + Impulse responses per iteration + h_fit_ls : list (only if return_iter=True) + Fitted impulse responses per iteration + """ + logger.info("Starting binary pursuit pipeline") + + # Unpack config + up_factor = config.up_factor + p = config.p + preprocess_cfg = config.preprocess + init_cfg = config.init + deconv_cfg = config.deconv + ar_cfg = config.ar_update + conv_cfg = config.convergence + + # 0. Housekeeping + ncell, T = Y.shape + logger.debug( + f"Pipeline parameters: " + f"up_factor={up_factor}, p={p}, max_iters={conv_cfg.max_iters}, " + f"n_best={conv_cfg.n_best}, backend={deconv_cfg.backend}, " + f"ar_use_all={ar_cfg.use_all}, ar_kn_len={ar_cfg.kn_len}, " + f"{ncell} cells with {T} timepoints" + ) + + # 1. Preprocessing + Y = preprocess_traces( + Y, + med_wnd=preprocess_cfg.med_wnd, + dff=preprocess_cfg.dff, + ar_kn_len=ar_cfg.kn_len, + ) + + # 2. Dashboard setup + if spawn_dashboard: + if da_client is not None: + logger.debug("Using Dask client for distributed computation") + dashboard = da_client.submit( + Dashboard, Y=Y, kn_len=ar_cfg.kn_len, actor=True + ).result() + else: + logger.debug("Running in single-machine mode") + dashboard = Dashboard(Y=Y, kn_len=ar_cfg.kn_len) + else: + dashboard = None + + # 3. Initialize AR parameters + ar_params = initialize_ar_params( + Y, + tau_init=init_cfg.tau_init, + p=p, + up_factor=up_factor, + ar_kn_len=ar_cfg.kn_len, + est_noise_freq=init_cfg.est_noise_freq, + est_use_smooth=init_cfg.est_use_smooth, + est_add_lag=init_cfg.est_add_lag, + ) + theta = ar_params.theta + tau = ar_params.tau + + # 4. Initialize deconvolvers + dcv = initialize_deconvolvers( + Y, + ar_params, + ar_kn_len=ar_cfg.kn_len, + up_factor=up_factor, + nthres=deconv_cfg.nthres, + norm=deconv_cfg.norm, + penal=deconv_cfg.penal, + use_base=deconv_cfg.use_base, + err_weighting=deconv_cfg.err_weighting, + masking_radius=deconv_cfg.masking_radius, + pks_polish=deconv_cfg.pks_polish, + ncons_thres=deconv_cfg.ncons_thres, + min_rel_scl=deconv_cfg.min_rel_scl, + atol=deconv_cfg.atol, + backend=deconv_cfg.backend, + dashboard=dashboard, + da_client=da_client, + ) + + # 5. Initialize iteration state + state = IterationState.empty(T, up_factor) + scale = np.empty(ncell) + + # 6. Main iteration loop + for i_iter in trange(conv_cfg.max_iters, desc="iteration"): + logger.info(f"Starting iteration {i_iter}/{conv_cfg.max_iters}") + + # 6.1 Deconvolution step + deconv_result = run_deconv_step( + Y, + dcv, + i_iter=i_iter, + reset_scale=deconv_cfg.reset_scale, + da_client=da_client, + ) + scale = deconv_result.scale + + logger.debug( + f"Iteration {i_iter} stats - " + f"Mean error: {deconv_result.err.mean():.4f}, " + f"Mean scale: {scale.mean():.4f}" + ) + + # 6.2 Update metrics + cur_metric = make_cur_metric( + i_iter=i_iter, + ncell=ncell, + theta=theta, + tau=tau, + scale=scale, + deconv_result=deconv_result, + deconvolvers=dcv, + use_rel_err=conv_cfg.use_rel_err, + ) + update_dashboard(dashboard, cur_metric, i_iter, conv_cfg.max_iters) + state.metric_df = append_metrics(state.metric_df, cur_metric) + + # 6.3 Save iteration results + state.C_ls.append(deconv_result.C) + state.S_ls.append(deconv_result.S) + state.scal_ls.append(scale) + + # Handle h_ls / h_fit_ls (not available on first iteration) + if i_iter == 0: + state.h_ls.append(np.full(T * up_factor, np.nan)) + state.h_fit_ls.append(np.full(T * up_factor, np.nan)) + else: + state.h_ls.append(h) + state.h_fit_ls.append(h_fit) + + # 6.4 Select best spikes for AR update + S_best, scal_best, err_wt, state.metric_df = select_best_spikes( + state.S_ls, + state.scal_ls, + deconv_result.err_rel, + state.metric_df, + n_best=conv_cfg.n_best, + i_iter=i_iter, + tau_init=init_cfg.tau_init, + ) + + # 6.5 Create spike train for AR estimation + S_ar = make_S_ar( + S_best, + est_nevt=init_cfg.est_nevt, + T=T, + up_factor=up_factor, + ar_kn_len=ar_cfg.kn_len, + ) + + # 6.6 Update AR parameters + tau, ps, h, h_fit = update_ar_parameters( + Y, + S_ar, + scal_best, + err_wt, + ar_use_all=ar_cfg.use_all, + ar_kn_len=ar_cfg.kn_len, + ar_norm=ar_cfg.norm, + ar_prop_best=ar_cfg.prop_best, + up_factor=up_factor, + p=p, + ncell=ncell, + dashboard=dashboard, + ) + + # Update theta to match the new tau values + # (required for correct metric reporting in make_cur_metric) + theta = np.array([tau2AR(t[0], t[1]) for t in tau]) + + if ar_cfg.use_all: + logger.debug(f"Updating AR parameters for all cells: tau={tau[0]}") + else: + logger.debug(f"Updated AR parameters per-cell") + + # 6.7 Propagate AR update to deconvolvers + propagate_ar_update( + dcv, + tau, + scal_best, + ar_use_all=ar_cfg.use_all, + da_client=da_client, + ) + + # 6.8 Check convergence + conv_result = check_convergence( + state.metric_df, + cur_metric, + deconv_result.S, + state.S_ls, + i_iter=i_iter, + err_atol=conv_cfg.err_atol, + err_rtol=conv_cfg.err_rtol, + ) + + if conv_result.converged: + if "trapped" in conv_result.reason.lower(): + logger.warning(conv_result.reason) + else: + logger.info(conv_result.reason) + break + else: + logger.warning("Max iteration reached without convergence") + + # 7. Compute final results + opt_C, opt_S = _finalize_results(state, ncell, T, up_factor, ar_cfg.use_all) + + # 8. Cleanup + if dashboard is not None: + dashboard.stop() + + logger.info("Pipeline completed successfully") + + if return_iter: + return ( + opt_C, + opt_S, + state.metric_df, + state.C_ls, + state.S_ls, + state.h_ls, + state.h_fit_ls, + ) + else: + return opt_C, opt_S, state.metric_df + + +def _finalize_results( + state: IterationState, + ncell: int, + T: int, + up_factor: int, + ar_use_all: bool, +) -> Tuple[np.ndarray, np.ndarray]: + """Compute final optimal results from iteration history. + + Parameters + ---------- + state : IterationState + Accumulated iteration state + ncell : int + Number of cells + T : int + Original trace length + up_factor : int + Upsampling factor + ar_use_all : bool + Whether using shared AR + + Returns + ------- + opt_C : np.ndarray + Optimal calcium traces + opt_S : np.ndarray + Optimal spike trains + """ + metric_df = state.metric_df + C_ls = state.C_ls + S_ls = state.S_ls + + opt_C = np.empty((ncell, T * up_factor)) + opt_S = np.empty((ncell, T * up_factor)) + + # mobj = metric_df.groupby("iter")["obj"].median() + # opt_idx_all = mobj.idxmin() + # NOTE: Original pipeline always selected the last iteration (-1), + # regardless of metric-based selection. We preserve that behavior here. + # (The metric-based selection logic was present but unused in the original.) + opt_idx = -1 + + for icell in range(ncell): + opt_C[icell, :] = C_ls[opt_idx][icell, :] + opt_S[icell, :] = S_ls[opt_idx][icell, :] + + # Append optimal to lists (matching original behavior) + C_ls.append(opt_C) + S_ls.append(opt_S) + + return opt_C, opt_S diff --git a/src/indeca/pipeline/config.py b/src/indeca/pipeline/config.py new file mode 100644 index 0000000..f7682dd --- /dev/null +++ b/src/indeca/pipeline/config.py @@ -0,0 +1,280 @@ +"""Pydantic v2 configuration models for the binary pursuit pipeline. + +These configs make the pipeline self-documenting, enable validation, +and allow easy CLI / config-file usage in the future. +""" + +from typing import Literal, Optional, Tuple, Union + +from pydantic import BaseModel, Field + + +class PreprocessConfig(BaseModel): + """Configuration for preprocessing traces.""" + + model_config = {"frozen": True} + + med_wnd: Optional[Union[int, Literal["auto"]]] = Field( + None, + description="Window size for median filtering. Use 'auto' to set to ar_kn_len, or None to skip.", + ) + dff: bool = Field( + True, + description="Whether to compute dF/F normalization.", + ) + + +class InitConfig(BaseModel): + """Configuration for AR parameter initialization.""" + + model_config = {"frozen": True} + + tau_init: Optional[Tuple[float, float]] = Field( + None, + description="Initial tau values (tau_d, tau_r). If None, estimate from data.", + ) + est_noise_freq: Optional[float] = Field( + None, + description="Frequency for noise estimation. None uses default.", + ) + est_use_smooth: bool = Field( + False, + description="Whether to use smoothing during AR estimation.", + ) + est_add_lag: int = Field( + 20, + description="Additional lag samples for AR estimation.", + ) + est_nevt: Optional[int] = Field( + 10, + description="Number of top spike events for AR update. None uses all spikes.", + ) + + +class DeconvStageConfig(BaseModel): + """Configuration for the deconvolution stage.""" + + model_config = {"frozen": True} + + nthres: int = Field( + 1000, + description="Number of thresholds for thresholding step.", + ) + norm: Literal["l1", "l2", "huber"] = Field( + "l2", + description="Norm for data fidelity.", + ) + penal: Optional[Literal["l0", "l1"]] = Field( + None, + description="Penalty type for sparsity.", + ) + backend: Literal["osqp", "cvxpy", "cuosqp"] = Field( + "osqp", + description="Solver backend.", + ) + err_weighting: Optional[Literal["fft", "corr", "adaptive"]] = Field( + None, + description="Error weighting method.", + ) + use_base: bool = Field( + True, + description="Whether to include a baseline term.", + ) + reset_scale: bool = Field( + True, + description="Whether to reset scale at each iteration.", + ) + masking_radius: Optional[int] = Field( + None, + description="Radius for masking around spikes.", + ) + pks_polish: bool = Field( + True, + description="Whether to polish peaks after solving.", + ) + ncons_thres: Optional[Union[int, Literal["auto"]]] = Field( + None, + description="Max consecutive spikes threshold. 'auto' = upsamp + 1.", + ) + min_rel_scl: Optional[Union[float, Literal["auto"]]] = Field( + None, + description="Minimum relative scale. 'auto' = 0.5 / upsamp.", + ) + atol: float = Field( + 1e-3, + description="Absolute tolerance for solver.", + ) + + +class ARUpdateConfig(BaseModel): + """Configuration for AR parameter updates.""" + + model_config = {"frozen": True} + + use_all: bool = Field( + True, + description="Whether to use all cells for AR update (shared tau).", + ) + kn_len: int = Field( + 100, + description="Kernel length for AR fitting.", + ) + norm: Literal["l1", "l2"] = Field( + "l2", + description="Norm for AR fitting.", + ) + prop_best: Optional[float] = Field( + None, + description="Proportion of best cells to use for AR update. None uses all.", + ) + + +class ConvergenceConfig(BaseModel): + """Configuration for convergence criteria.""" + + model_config = {"frozen": True} + + max_iters: int = Field( + 50, + description="Maximum number of iterations.", + ) + err_atol: float = Field( + 1e-4, + description="Absolute error tolerance for convergence.", + ) + err_rtol: float = Field( + 5e-2, + description="Relative error tolerance for convergence.", + ) + use_rel_err: bool = Field( + True, + description="Whether to use relative error for objective.", + ) + n_best: Optional[int] = Field( + 3, + description="Number of best iterations to average for spike selection.", + ) + + +class DeconvPipelineConfig(BaseModel): + """Main configuration for the binary pursuit deconvolution pipeline. + + This is the top-level config that composes all sub-configs. + """ + + model_config = {"frozen": True} + + # Core parameters + up_factor: int = Field( + 1, + description="Upsampling factor for spike times.", + ) + p: int = Field( + 2, + description="Order of AR model (typically 2 for calcium imaging).", + ) + + # Sub-configs + preprocess: PreprocessConfig = Field( + default_factory=PreprocessConfig, + description="Preprocessing configuration.", + ) + init: InitConfig = Field( + default_factory=InitConfig, + description="Initialization configuration.", + ) + deconv: DeconvStageConfig = Field( + default_factory=DeconvStageConfig, + description="Deconvolution stage configuration.", + ) + ar_update: ARUpdateConfig = Field( + default_factory=ARUpdateConfig, + description="AR update configuration.", + ) + convergence: ConvergenceConfig = Field( + default_factory=ConvergenceConfig, + description="Convergence configuration.", + ) + + @classmethod + def from_legacy_kwargs( + cls, + *, + up_factor: int = 1, + p: int = 2, + tau_init: Optional[Tuple[float, float]] = None, + max_iters: int = 50, + n_best: Optional[int] = 3, + use_rel_err: bool = True, + err_atol: float = 1e-4, + err_rtol: float = 5e-2, + est_noise_freq: Optional[float] = None, + est_use_smooth: bool = False, + est_add_lag: int = 20, + est_nevt: Optional[int] = 10, + med_wnd: Optional[Union[int, Literal["auto"]]] = None, + dff: bool = True, + deconv_nthres: int = 1000, + deconv_norm: Literal["l1", "l2", "huber"] = "l2", + deconv_atol: float = 1e-3, + deconv_penal: Optional[Literal["l0", "l1"]] = None, + deconv_backend: Literal["osqp", "cvxpy", "cuosqp"] = "osqp", + deconv_err_weighting: Optional[Literal["fft", "corr", "adaptive"]] = None, + deconv_use_base: bool = True, + deconv_reset_scl: bool = True, + deconv_masking_radius: Optional[int] = None, + deconv_pks_polish: bool = True, + deconv_ncons_thres: Optional[Union[int, Literal["auto"]]] = None, + deconv_min_rel_scl: Optional[Union[float, Literal["auto"]]] = None, + ar_use_all: bool = True, + ar_kn_len: int = 100, + ar_norm: Literal["l1", "l2"] = "l2", + ar_prop_best: Optional[float] = None, + ) -> "DeconvPipelineConfig": + """Create a config from legacy keyword arguments. + + This factory method enables backward compatibility with the old + flat-kwargs API. + """ + return cls( + up_factor=up_factor, + p=p, + preprocess=PreprocessConfig( + med_wnd=med_wnd, + dff=dff, + ), + init=InitConfig( + tau_init=tau_init, + est_noise_freq=est_noise_freq, + est_use_smooth=est_use_smooth, + est_add_lag=est_add_lag, + est_nevt=est_nevt, + ), + deconv=DeconvStageConfig( + nthres=deconv_nthres, + norm=deconv_norm, + penal=deconv_penal, + backend=deconv_backend, + err_weighting=deconv_err_weighting, + use_base=deconv_use_base, + reset_scale=deconv_reset_scl, + masking_radius=deconv_masking_radius, + pks_polish=deconv_pks_polish, + ncons_thres=deconv_ncons_thres, + min_rel_scl=deconv_min_rel_scl, + atol=deconv_atol, + ), + ar_update=ARUpdateConfig( + use_all=ar_use_all, + kn_len=ar_kn_len, + norm=ar_norm, + prop_best=ar_prop_best, + ), + convergence=ConvergenceConfig( + max_iters=max_iters, + err_atol=err_atol, + err_rtol=err_rtol, + use_rel_err=use_rel_err, + n_best=n_best, + ), + ) diff --git a/src/indeca/pipeline/convergence.py b/src/indeca/pipeline/convergence.py new file mode 100644 index 0000000..75f79ad --- /dev/null +++ b/src/indeca/pipeline/convergence.py @@ -0,0 +1,109 @@ +"""Convergence checking functions. + +Handles all convergence and trapping detection logic. +""" + +from typing import List + +import numpy as np +import pandas as pd + +from .types import ConvergenceResult + + +def check_convergence( + metric_df: pd.DataFrame, + cur_metric: pd.DataFrame, + S: np.ndarray, + S_ls: List[np.ndarray], + *, + i_iter: int, + err_atol: float, + err_rtol: float, +) -> ConvergenceResult: + """Check if the pipeline has converged or is trapped. + + Checks multiple convergence criteria: + 1. Absolute error tolerance + 2. Relative error tolerance + 3. Spike pattern stabilization + 4. Trapped in local optimum (error) + 5. Trapped in local optimum (spike pattern) + + Parameters + ---------- + metric_df : pd.DataFrame + Accumulated metrics from previous iterations + cur_metric : pd.DataFrame + Metrics from current iteration + S : np.ndarray + Current spike trains, shape (ncell, T * up_factor) + S_ls : list of np.ndarray + Spike trains from all iterations + i_iter : int + Current iteration index + err_atol : float + Absolute error tolerance + err_rtol : float + Relative error tolerance + + Returns + ------- + ConvergenceResult + Result indicating if converged and why + """ + # Need at least one previous iteration + metric_prev = metric_df[metric_df["iter"] < i_iter].dropna(subset=["obj", "scale"]) + metric_last = metric_df[metric_df["iter"] == i_iter - 1].dropna( + subset=["obj", "scale"] + ) + + if len(metric_prev) == 0: + return ConvergenceResult(converged=False, reason="") + + err_cur = cur_metric.set_index("cell")["obj"] + err_last = metric_last.set_index("cell")["obj"] + err_best = metric_prev.groupby("cell")["obj"].min() + ncell = S.shape[0] + + # Check 1: Converged by absolute error + if (np.abs(err_cur - err_last) < err_atol).all(): + return ConvergenceResult( + converged=True, reason="Converged: absolute error tolerance reached" + ) + + # Check 2: Converged by relative error + if (np.abs(err_cur - err_last) < err_rtol * err_best).all(): + return ConvergenceResult( + converged=True, reason="Converged: relative error tolerance reached" + ) + + # Check 3: Converged by spike pattern stabilization + T_up = S.shape[1] + S_best = np.empty((ncell, T_up)) + for uid, udf in metric_prev.groupby("cell"): + best_iter = udf.set_index("iter")["obj"].idxmin() + S_best[uid, :] = S_ls[best_iter][uid, :] + + if np.abs(S - S_best).sum() < 1: + return ConvergenceResult( + converged=True, reason="Converged: spike pattern stabilized" + ) + + # Check 4: Trapped by error (current error very close to some past error) + err_all = metric_prev.pivot(columns="iter", index="cell", values="obj") + diff_all = np.abs(err_cur.values.reshape((-1, 1)) - err_all.values) + if (diff_all.min(axis=1) < err_atol).all(): + return ConvergenceResult( + converged=True, reason="Solution trapped in local optimal err" + ) + + # Check 5: Trapped by spike pattern (current pattern matches > 1 past pattern) + if len(S_ls) > 1: + diff_all = np.array([np.abs(S - prev_s).sum() for prev_s in S_ls[:-1]]) + if (diff_all < 1).sum() > 1: + return ConvergenceResult( + converged=True, reason="Solution trapped in local optimal s" + ) + + return ConvergenceResult(converged=False, reason="") diff --git a/src/indeca/pipeline/init.py b/src/indeca/pipeline/init.py new file mode 100644 index 0000000..abfb06a --- /dev/null +++ b/src/indeca/pipeline/init.py @@ -0,0 +1,219 @@ +"""Initialization functions for the binary pursuit pipeline. + +Handles AR parameter estimation and DeconvBin instance creation. +""" + +from typing import List, Optional, Tuple, Any + +import numpy as np + +from indeca.core.AR_kernel import AR_upsamp_real, estimate_coefs +from indeca.core.deconv import DeconvBin +from indeca.core.simulation import AR2tau, tau2AR + +from .types import ARParams + + +def initialize_ar_params( + Y: np.ndarray, + *, + tau_init: Optional[Tuple[float, float]], + p: int, + up_factor: int, + ar_kn_len: int, + est_noise_freq: Optional[float], + est_use_smooth: bool, + est_add_lag: int, +) -> ARParams: + """Initialize AR model parameters. + + If tau_init is provided, uses those values for all cells. + Otherwise, estimates AR parameters from the data for each cell. + + Parameters + ---------- + Y : np.ndarray + Input traces, shape (ncell, T) + tau_init : tuple or None + Initial (tau_d, tau_r) values. If None, estimate from data. + p : int + AR model order (typically 2) + up_factor : int + Upsampling factor + ar_kn_len : int + AR kernel length for fitting + est_noise_freq : float or None + Noise frequency for estimation + est_use_smooth : bool + Whether to use smoothing during estimation + est_add_lag : int + Additional lag for estimation + + Returns + ------- + ARParams + Initialized AR parameters (theta, tau, ps) + """ + ncell = Y.shape[0] + + if tau_init is not None: + # Use provided tau values for all cells + theta = tau2AR(tau_init[0], tau_init[1]) + _, _, pp = AR2tau(theta[0], theta[1], solve_amp=True) + ps = np.array([pp, -pp]) + + theta = np.tile(tau2AR(tau_init[0], tau_init[1]), (ncell, 1)) + tau = np.tile(tau_init, (ncell, 1)) + ps = np.tile(ps, (ncell, 1)) + else: + # Estimate AR parameters from data + theta = np.empty((ncell, p)) + tau = np.empty((ncell, p)) + ps = np.empty((ncell, p)) + + for icell, y in enumerate(Y): + cur_theta, _ = estimate_coefs( + y, + p=p, + noise_freq=est_noise_freq, + use_smooth=est_use_smooth, + add_lag=est_add_lag, + ) + cur_theta, cur_tau, cur_p = AR_upsamp_real( + cur_theta, upsamp=up_factor, fit_nsamp=ar_kn_len + ) + tau[icell, :] = cur_tau + theta[icell, :] = cur_theta + ps[icell, :] = cur_p + + return ARParams(theta=theta, tau=tau, ps=ps) + + +def initialize_deconvolvers( + Y: np.ndarray, + ar_params: ARParams, + *, + ar_kn_len: int, + up_factor: int, + nthres: int, + norm: str, + penal: Optional[str], + use_base: bool, + err_weighting: Optional[str], + masking_radius: Optional[int], + pks_polish: bool, + ncons_thres: Optional[int], + min_rel_scl: Optional[float], + atol: float, + backend: str, + dashboard: Any, + da_client: Any, +) -> List[Any]: + """Create DeconvBin instances for all cells. + + Parameters + ---------- + Y : np.ndarray + Input traces, shape (ncell, T) + ar_params : ARParams + Initialized AR parameters + ar_kn_len : int + AR kernel length + up_factor : int + Upsampling factor + nthres : int + Number of thresholds + norm : str + Norm type ("l1", "l2", "huber") + penal : str or None + Penalty type + use_base : bool + Whether to use baseline + err_weighting : str or None + Error weighting method + masking_radius : int or None + Masking radius + pks_polish : bool + Whether to polish peaks + ncons_thres : int or None + Consecutive spikes threshold + min_rel_scl : float or None + Minimum relative scale + atol : float + Absolute tolerance + backend : str + Solver backend + dashboard : Dashboard or None + Dashboard instance + da_client : Client or None + Dask client for distributed execution + + Returns + ------- + list + List of DeconvBin instances (or futures if using Dask) + """ + theta = ar_params.theta + tau = ar_params.tau + ps = ar_params.ps + + if da_client is not None: + # Distributed execution + dcv = [ + da_client.submit( + lambda yy, th, tau_i, ps_i: DeconvBin( + y=yy, + theta=th, + tau=tau_i, + ps=ps_i, + coef_len=ar_kn_len, + upsamp=up_factor, + nthres=nthres, + norm=norm, + penal=penal, + use_base=use_base, + err_weighting=err_weighting, + masking_radius=masking_radius, + pks_polish=pks_polish, + ncons_thres=ncons_thres, + min_rel_scl=min_rel_scl, + atol=atol, + backend=backend, + dashboard=dashboard, + dashboard_uid=i, + ), + y, + theta[i], + tau[i], + ps[i], + ) + for i, y in enumerate(Y) + ] + else: + # Local execution + dcv = [ + DeconvBin( + y=y, + theta=theta[i], + tau=tau[i], + ps=ps[i], + coef_len=ar_kn_len, + upsamp=up_factor, + nthres=nthres, + norm=norm, + penal=penal, + use_base=use_base, + err_weighting=err_weighting, + masking_radius=masking_radius, + pks_polish=pks_polish, + ncons_thres=ncons_thres, + min_rel_scl=min_rel_scl, + atol=atol, + backend=backend, + dashboard=dashboard, + dashboard_uid=i, + ) + for i, y in enumerate(Y) + ] + + return dcv diff --git a/src/indeca/pipeline/iteration.py b/src/indeca/pipeline/iteration.py new file mode 100644 index 0000000..78d52e0 --- /dev/null +++ b/src/indeca/pipeline/iteration.py @@ -0,0 +1,74 @@ +"""Per-iteration deconvolution step functions. + +Handles running solve_scale on all cells and collecting results. +""" + +from typing import Any, List + +import numpy as np +from tqdm.auto import tqdm + +from .types import DeconvStepResult + + +def run_deconv_step( + Y: np.ndarray, + deconvolvers: List[Any], + *, + i_iter: int, + reset_scale: bool, + da_client: Any, +) -> DeconvStepResult: + """Run one deconvolution iteration across all cells. + + Parameters + ---------- + Y : np.ndarray + Input traces, shape (ncell, T) + deconvolvers : list + List of DeconvBin instances (or futures) + i_iter : int + Current iteration index + reset_scale : bool + Whether to reset scale this iteration + da_client : Client or None + Dask client for distributed execution + + Returns + ------- + DeconvStepResult + Results from this deconvolution step + """ + res = [] + + for icell, _ in tqdm(enumerate(Y), total=Y.shape[0], desc="deconv", leave=False): + if da_client is not None: + r = da_client.submit( + lambda d: d.solve_scale(reset_scale=i_iter <= 1 or reset_scale), + deconvolvers[icell], + ) + else: + r = deconvolvers[icell].solve_scale(reset_scale=i_iter <= 1 or reset_scale) + res.append(r) + + if da_client is not None: + res = da_client.gather(res) + + # Unpack results + S = np.stack([r[0].squeeze() for r in res], axis=0, dtype=float) + C = np.stack([r[1].squeeze() for r in res], axis=0) + scale = np.array([r[2] for r in res]) + err = np.array([r[3] for r in res]) + err_rel = np.array([r[4] for r in res]) + nnz = np.array([r[5] for r in res]) + penal = np.array([r[6] for r in res]) + + return DeconvStepResult( + S=S, + C=C, + scale=scale, + err=err, + err_rel=err_rel, + nnz=nnz, + penal=penal, + ) diff --git a/src/indeca/pipeline/metrics.py b/src/indeca/pipeline/metrics.py new file mode 100644 index 0000000..f022abd --- /dev/null +++ b/src/indeca/pipeline/metrics.py @@ -0,0 +1,131 @@ +"""Metrics construction and update functions. + +Handles building the per-iteration metrics DataFrame. +""" + +from typing import Any, List + +import numpy as np +import pandas as pd + +from indeca.core.simulation import find_dhm + +from .types import DeconvStepResult + + +def make_cur_metric( + i_iter: int, + ncell: int, + theta: np.ndarray, + tau: np.ndarray, + scale: np.ndarray, + deconv_result: DeconvStepResult, + deconvolvers: List[Any], + use_rel_err: bool, +) -> pd.DataFrame: + """Construct the metrics DataFrame for the current iteration. + + Parameters + ---------- + i_iter : int + Current iteration index + ncell : int + Number of cells + theta : np.ndarray + AR coefficients, shape (ncell, p) + tau : np.ndarray + Time constants, shape (ncell, 2) + scale : np.ndarray + Scale factors, shape (ncell,) + deconv_result : DeconvStepResult + Results from deconvolution step + deconvolvers : list + List of DeconvBin instances + use_rel_err : bool + Whether to use relative error for objective + + Returns + ------- + pd.DataFrame + Metrics for the current iteration + """ + # Compute half-max durations + dhm = np.stack( + [ + np.array(find_dhm(True, (t0, t1), (s, -s))[0], dtype=float) + for t0, t1, s in zip(tau.T[0], tau.T[1], scale) + ], + axis=0, + ) + + cur_metric = pd.DataFrame( + { + "iter": i_iter, + "cell": np.arange(ncell), + "g0": theta.T[0], + "g1": theta.T[1], + "tau_d": tau.T[0], + "tau_r": tau.T[1], + "dhm0": dhm.T[0], + "dhm1": dhm.T[1], + "err": deconv_result.err, + "err_rel": deconv_result.err_rel, + "scale": scale, + "penal": deconv_result.penal, + "nnz": deconv_result.nnz, + "obj": deconv_result.err_rel if use_rel_err else deconv_result.err, + "wgt_len": [d.wgt_len for d in deconvolvers], + } + ) + + return cur_metric + + +def append_metrics( + metric_df: pd.DataFrame, + cur_metric: pd.DataFrame, +) -> pd.DataFrame: + """Append current iteration metrics to the accumulated DataFrame. + + Parameters + ---------- + metric_df : pd.DataFrame + Accumulated metrics from previous iterations + cur_metric : pd.DataFrame + Metrics from current iteration + + Returns + ------- + pd.DataFrame + Updated metrics DataFrame + """ + return pd.concat([metric_df, cur_metric], ignore_index=True) + + +def update_dashboard( + dashboard: Any, + cur_metric: pd.DataFrame, + i_iter: int, + max_iters: int, +) -> None: + """Update the dashboard with current iteration metrics. + + Parameters + ---------- + dashboard : Dashboard or None + Dashboard instance + cur_metric : pd.DataFrame + Current iteration metrics + i_iter : int + Current iteration index + max_iters : int + Maximum number of iterations + """ + if dashboard is not None: + dashboard.update( + tau_d=cur_metric["tau_d"].squeeze(), + tau_r=cur_metric["tau_r"].squeeze(), + err=cur_metric["obj"].squeeze(), + scale=cur_metric["scale"].squeeze(), + ) + dashboard.set_iter(min(i_iter + 1, max_iters - 1)) diff --git a/src/indeca/pipeline/pipeline.py b/src/indeca/pipeline/pipeline.py index 5c463d6..446578f 100644 --- a/src/indeca/pipeline/pipeline.py +++ b/src/indeca/pipeline/pipeline.py @@ -1,446 +1,220 @@ +"""Legacy interface for the binary pursuit pipeline. + +This module provides backward compatibility with the old flat-kwargs API. +New code should use the config-based API from binary_pursuit.py. + +.. deprecated:: + Use `pipeline_bin` from `indeca.pipeline.binary_pursuit` with + `DeconvPipelineConfig` instead. +""" + import warnings +from typing import Literal, Optional, Tuple, Union import numpy as np import pandas as pd from line_profiler import profile -from scipy.signal import find_peaks, medfilt -from tqdm.auto import tqdm, trange -from indeca.core.AR_kernel import AR_upsamp_real, estimate_coefs, updateAR -from indeca.dashboard.dashboard import Dashboard -from indeca.core.deconv.deconv import DeconvBin, construct_R from indeca.utils.logging_config import get_module_logger -from indeca.core.simulation import AR2tau, find_dhm, tau2AR -from indeca.utils.utils import compute_dff -# Initialize logger for this module +from .binary_pursuit import pipeline_bin as _pipeline_bin_new +from .config import DeconvPipelineConfig + logger = get_module_logger("pipeline") -logger.info("Pipeline module initialized") # Test message on import +logger.info("Pipeline module initialized") @profile def pipeline_bin( - Y, - up_factor=1, - p=2, - tau_init=None, - return_iter=False, - max_iters=50, - n_best=3, - use_rel_err=True, - err_atol=1e-4, - err_rtol=5e-2, - est_noise_freq=None, - est_use_smooth=False, - est_add_lag=20, - est_nevt=10, - med_wnd=None, - dff=True, - deconv_nthres=1000, - deconv_norm="l2", - deconv_atol=1e-3, - deconv_penal=None, - deconv_backend="osqp", - deconv_err_weighting=None, - deconv_use_base=True, - deconv_reset_scl=True, - deconv_masking_radius=None, - deconv_pks_polish=None, - deconv_ncons_thres=None, - deconv_min_rel_scl=None, - ar_use_all=True, - ar_kn_len=100, - ar_norm="l2", - ar_prop_best=None, + Y: np.ndarray, + up_factor: int = 1, + p: int = 2, + tau_init: Optional[Tuple[float, float]] = None, + return_iter: bool = False, + max_iters: int = 50, + n_best: Optional[int] = 3, + use_rel_err: bool = True, + err_atol: float = 1e-4, + err_rtol: float = 5e-2, + est_noise_freq: Optional[float] = None, + est_use_smooth: bool = False, + est_add_lag: int = 20, + est_nevt: Optional[int] = 10, + med_wnd: Optional[Union[int, Literal["auto"]]] = None, + dff: bool = True, + deconv_nthres: int = 1000, + deconv_norm: Literal["l1", "l2", "huber"] = "l2", + deconv_atol: float = 1e-3, + deconv_penal: Optional[Literal["l0", "l1"]] = None, + deconv_backend: Literal["osqp", "cvxpy", "cuosqp"] = "osqp", + deconv_err_weighting: Optional[Literal["fft", "corr", "adaptive"]] = None, + deconv_use_base: bool = True, + deconv_reset_scl: bool = True, + deconv_masking_radius: Optional[int] = None, + deconv_pks_polish: bool = True, + deconv_ncons_thres: Optional[Union[int, Literal["auto"]]] = None, + deconv_min_rel_scl: Optional[Union[float, Literal["auto"]]] = None, + ar_use_all: bool = True, + ar_kn_len: int = 100, + ar_norm: Literal["l1", "l2"] = "l2", + ar_prop_best: Optional[float] = None, da_client=None, - spawn_dashboard=True, -): - """Binary pursuit pipeline for spike inference. + spawn_dashboard: bool = True, +) -> Union[ + Tuple[np.ndarray, np.ndarray, pd.DataFrame], + Tuple[np.ndarray, np.ndarray, pd.DataFrame, list, list, list, list], +]: + """Binary pursuit pipeline for spike inference (legacy interface). + + .. deprecated:: + This function signature is deprecated. Use the config-based API: + + >>> from indeca.pipeline import pipeline_bin, DeconvPipelineConfig + >>> config = DeconvPipelineConfig(up_factor=2, ...) + >>> opt_C, opt_S, metrics = pipeline_bin(Y, config=config) Parameters ---------- Y : array-like - Input fluorescence trace - ... + Input fluorescence trace, shape (ncell, T) + up_factor : int + Upsampling factor for spike times + p : int + AR model order + tau_init : tuple or None + Initial (tau_d, tau_r) values. If None, estimate from data. + return_iter : bool + Whether to return per-iteration results + max_iters : int + Maximum number of iterations + n_best : int or None + Number of best iterations to average for spike selection + use_rel_err : bool + Whether to use relative error for objective + err_atol : float + Absolute error tolerance for convergence + err_rtol : float + Relative error tolerance for convergence + est_noise_freq : float or None + Frequency for noise estimation + est_use_smooth : bool + Whether to use smoothing during AR estimation + est_add_lag : int + Additional lag samples for AR estimation + est_nevt : int or None + Number of top spike events for AR update + med_wnd : int, "auto", or None + Window size for median filtering + dff : bool + Whether to compute dF/F normalization + deconv_nthres : int + Number of thresholds for thresholding step + deconv_norm : str + Norm for data fidelity + deconv_atol : float + Absolute tolerance for solver + deconv_penal : str or None + Penalty type for sparsity + deconv_backend : str + Solver backend + deconv_err_weighting : str or None + Error weighting method + deconv_use_base : bool + Whether to include a baseline term + deconv_reset_scl : bool + Whether to reset scale at each iteration + deconv_masking_radius : int or None + Radius for masking around spikes + deconv_pks_polish : bool + Whether to polish peaks after solving + deconv_ncons_thres : int, "auto", or None + Max consecutive spikes threshold + deconv_min_rel_scl : float, "auto", or None + Minimum relative scale + ar_use_all : bool + Whether to use all cells for AR update (shared tau) + ar_kn_len : int + Kernel length for AR fitting + ar_norm : str + Norm for AR fitting + ar_prop_best : float or None + Proportion of best cells to use for AR update + da_client : Client or None + Dask client for distributed execution + spawn_dashboard : bool + Whether to spawn a real-time dashboard Returns ------- - dict - Dictionary containing results of the pipeline + opt_C : np.ndarray + Optimal calcium traces + opt_S : np.ndarray + Optimal spike trains + metric_df : pd.DataFrame + Per-iteration metrics + C_ls : list (only if return_iter=True) + Calcium traces per iteration + S_ls : list (only if return_iter=True) + Spike trains per iteration + h_ls : list (only if return_iter=True) + Impulse responses per iteration + h_fit_ls : list (only if return_iter=True) + Fitted impulse responses per iteration """ - logger.info("Starting binary pursuit pipeline") - # 0. housekeeping - ncell, T = Y.shape - logger.debug( - "Pipeline parameters: " - f"up_factor={up_factor}, p={p}, max_iters={max_iters}, " - f"n_best={n_best}, deconv_backend={deconv_backend}, " - f"ar_use_all={ar_use_all}, ar_kn_len={ar_kn_len}" - f"{ncell} cells with {T} timepoints" + # Emit deprecation warning + warnings.warn( + "The flat-kwargs signature of pipeline_bin() is deprecated. " + "Use the config-based API instead:\n" + " from indeca.pipeline import pipeline_bin, DeconvPipelineConfig\n" + " config = DeconvPipelineConfig.from_legacy_kwargs(...)\n" + " result = pipeline_bin(Y, config=config)", + DeprecationWarning, + stacklevel=2, ) - if med_wnd is not None: - if med_wnd == "auto": - med_wnd = ar_kn_len - for iy, y in enumerate(Y): - Y[iy, :] = y - medfilt(y, med_wnd * 2 + 1) - if dff: - for iy, y in enumerate(Y): - Y[iy, :] = compute_dff(y, window_size=ar_kn_len * 5, q=0.2) - if spawn_dashboard: - if da_client is not None: - logger.debug("Using Dask client for distributed computation") - dashboard = da_client.submit( - Dashboard, Y=Y, kn_len=ar_kn_len, actor=True - ).result() - else: - logger.debug("Running in single-machine mode") - dashboard = Dashboard(Y=Y, kn_len=ar_kn_len) - else: - dashboard = None - # 1. estimate initial guess at convolution kernel - if tau_init is not None: - logger.debug(f"Using provided tau_init: {tau_init}") - theta = tau2AR(tau_init[0], tau_init[1]) - _, _, pp = AR2tau(theta[0], theta[1], solve_amp=True) - ps = np.array([pp, -pp]) - theta = np.tile(tau2AR(tau_init[0], tau_init[1]), (ncell, 1)) - tau = np.tile(tau_init, (ncell, 1)) - ps = np.tile(ps, (ncell, 1)) - else: - logger.debug("Computing initial tau values") - theta = np.empty((ncell, p)) - tau = np.empty((ncell, p)) - ps = np.empty((ncell, p)) - for icell, y in enumerate(Y): - cur_theta, _ = estimate_coefs( - y, - p=p, - noise_freq=est_noise_freq, - use_smooth=est_use_smooth, - add_lag=est_add_lag, - ) - cur_theta, cur_tau, cur_p = AR_upsamp_real( - cur_theta, upsamp=up_factor, fit_nsamp=ar_kn_len - ) - tau[icell, :] = cur_tau - theta[icell, :] = cur_theta - ps[icell, :] = cur_p - scale = np.empty(ncell) - # 2. iteration loop - C_ls = [] - S_ls = [] - scal_ls = [] - h_ls = [] - h_fit_ls = [] - metric_df = pd.DataFrame( - columns=[ - "iter", - "cell", - "g0", - "g1", - "tau_d", - "tau_r", - "err", - "err_rel", - "nnz", - "scale", - "best_idx", - "obj", - "wgt_len", - ] + + # Build config from legacy kwargs + config = DeconvPipelineConfig.from_legacy_kwargs( + up_factor=up_factor, + p=p, + tau_init=tau_init, + max_iters=max_iters, + n_best=n_best, + use_rel_err=use_rel_err, + err_atol=err_atol, + err_rtol=err_rtol, + est_noise_freq=est_noise_freq, + est_use_smooth=est_use_smooth, + est_add_lag=est_add_lag, + est_nevt=est_nevt, + med_wnd=med_wnd, + dff=dff, + deconv_nthres=deconv_nthres, + deconv_norm=deconv_norm, + deconv_atol=deconv_atol, + deconv_penal=deconv_penal, + deconv_backend=deconv_backend, + deconv_err_weighting=deconv_err_weighting, + deconv_use_base=deconv_use_base, + deconv_reset_scl=deconv_reset_scl, + deconv_masking_radius=deconv_masking_radius, + deconv_pks_polish=deconv_pks_polish, + deconv_ncons_thres=deconv_ncons_thres, + deconv_min_rel_scl=deconv_min_rel_scl, + ar_use_all=ar_use_all, + ar_kn_len=ar_kn_len, + ar_norm=ar_norm, + ar_prop_best=ar_prop_best, + ) + + # Delegate to new implementation + return _pipeline_bin_new( + Y, + config=config, + da_client=da_client, + spawn_dashboard=spawn_dashboard, + return_iter=return_iter, ) - if da_client is not None: - dcv = [ - da_client.submit( - lambda yy, th, tau, ps: DeconvBin( - y=yy, - theta=th, - tau=tau, - ps=ps, - coef_len=ar_kn_len, - upsamp=up_factor, - nthres=deconv_nthres, - norm=deconv_norm, - penal=deconv_penal, - use_base=deconv_use_base, - err_weighting=deconv_err_weighting, - masking_radius=deconv_masking_radius, - pks_polish=deconv_pks_polish, - ncons_thres=deconv_ncons_thres, - min_rel_scl=deconv_min_rel_scl, - atol=deconv_atol, - backend=deconv_backend, - dashboard=dashboard, - dashboard_uid=i, - ), - y, - theta[i], - tau[i], - ps[i], - ) - for i, y in enumerate(Y) - ] - else: - dcv = [ - DeconvBin( - y=y, - theta=theta[i], - tau=tau[i], - ps=ps[i], - coef_len=ar_kn_len, - upsamp=up_factor, - nthres=deconv_nthres, - norm=deconv_norm, - penal=deconv_penal, - use_base=deconv_use_base, - err_weighting=deconv_err_weighting, - masking_radius=deconv_masking_radius, - pks_polish=deconv_pks_polish, - ncons_thres=deconv_ncons_thres, - min_rel_scl=deconv_min_rel_scl, - atol=deconv_atol, - backend=deconv_backend, - dashboard=dashboard, - dashboard_uid=i, - ) - for i, y in enumerate(Y) - ] - for i_iter in trange(max_iters, desc="iteration"): - logger.info(f"Starting iteration {i_iter}/{max_iters}") - # 2.1 deconvolution - res = [] - for icell, y in tqdm( - enumerate(Y), total=Y.shape[0], desc="deconv", leave=False - ): - if da_client is not None: - r = da_client.submit( - lambda d: d.solve_scale( - reset_scale=i_iter <= 1 or deconv_reset_scl - ), - dcv[icell], - ) - else: - r = dcv[icell].solve_scale(reset_scale=i_iter <= 1 or deconv_reset_scl) - res.append(r) - if da_client is not None: - res = da_client.gather(res) - S = np.stack([r[0].squeeze() for r in res], axis=0, dtype=float) - C = np.stack([r[1].squeeze() for r in res], axis=0) - scale = np.array([r[2] for r in res]) - err = np.array([r[3] for r in res]) - err_rel = np.array([r[4] for r in res]) - nnz = np.array([r[5] for r in res]) - penal = np.array([r[6] for r in res]) - logger.debug( - f"Iteration {i_iter} stats - Mean error: {err.mean():.4f}, Mean scale: {scale.mean():.4f}" - ) - # 2.2 save iteration results - dhm = np.stack( - [ - find_dhm(True, (t0, t1), (s, -s))[0] - for t0, t1, s in zip(tau.T[0], tau.T[1], scale) - ] - ) - cur_metric = pd.DataFrame( - { - "iter": i_iter, - "cell": np.arange(ncell), - "g0": theta.T[0], - "g1": theta.T[1], - "tau_d": tau.T[0], - "tau_r": tau.T[1], - "dhm0": dhm.T[0], - "dhm1": dhm.T[1], - "err": err, - "err_rel": err_rel, - "scale": scale, - "penal": penal, - "nnz": nnz, - "obj": err_rel if use_rel_err else err, - "wgt_len": [d.wgt_len for d in dcv], - } - ) - if dashboard is not None: - dashboard.update( - tau_d=cur_metric["tau_d"].squeeze(), - tau_r=cur_metric["tau_r"].squeeze(), - err=cur_metric["obj"].squeeze(), - scale=cur_metric["scale"].squeeze(), - ) - dashboard.set_iter(min(i_iter + 1, max_iters - 1)) - metric_df = pd.concat([metric_df, cur_metric], ignore_index=True) - C_ls.append(C) - S_ls.append(S) - scal_ls.append(scale) - try: - h_ls.append(h) - h_fit_ls.append(h_fit) - except UnboundLocalError: - h_ls.append(np.full(T * up_factor, np.nan)) - h_fit_ls.append(np.full(T * up_factor, np.nan)) - # 2.3 update AR - metric_df = metric_df.set_index(["iter", "cell"]) - if n_best is not None and i_iter >= n_best: - S_best = np.empty_like(S) - scal_best = np.empty_like(scale) - err_wt = np.empty_like(err_rel) - if tau_init is not None: - metric_best = metric_df - else: - metric_best = metric_df.loc[1:, :] - for icell, cell_met in metric_best.groupby("cell", sort=True): - cell_met = cell_met.reset_index().sort_values("obj", ascending=True) - cur_idx = np.array(cell_met["iter"][:n_best]) - metric_df.loc[(i_iter, icell), "best_idx"] = ",".join( - cur_idx.astype(str) - ) - S_best[icell, :] = np.sum( - np.stack([S_ls[i][icell, :] for i in cur_idx], axis=0), axis=0 - ) > (n_best / 2) - scal_best[icell] = np.mean([scal_ls[i][icell] for i in cur_idx]) - err_wt[icell] = -np.mean( - [metric_df.loc[(i, icell), "err_rel"] for i in cur_idx] - ) - else: - S_best = S - scal_best = scale - err_wt = -err_rel - metric_df = metric_df.reset_index() - if est_nevt is not None: - S_ar = [] - R = construct_R(T, up_factor) - for s in S_best: - Rs = R @ s - s_pks, pk_prop = find_peaks( - Rs, height=1, distance=ar_kn_len * up_factor - ) - pk_ht = pk_prop["peak_heights"] - top_idx = s_pks[np.argsort(pk_ht)[-est_nevt:]] - mask = np.zeros_like(Rs, dtype=bool) - mask[top_idx] = True - Rs_ma = Rs * mask - s_ma = np.zeros_like(s) - s_ma[::up_factor] = Rs_ma - S_ar.append(s_ma) - S_ar = np.stack(S_ar, axis=0) - else: - S_ar = S_best - if ar_use_all: - if ar_prop_best is not None: - ar_nbest = max(int(np.round(ar_prop_best * ncell)), 1) - ar_best_idx = np.argsort(err_wt)[-ar_nbest:] - else: - ar_best_idx = slice(None) - cur_tau, ps, ar_scal, h, h_fit = updateAR( - Y[ar_best_idx], - S_ar[ar_best_idx], - scal_best[ar_best_idx], - N=p, - h_len=ar_kn_len * up_factor, - norm=ar_norm, - up_factor=up_factor, - ) - if dashboard is not None: - dashboard.update( - h=h[: ar_kn_len * up_factor], h_fit=h_fit[: ar_kn_len * up_factor] - ) - tau = np.tile(cur_tau, (ncell, 1)) - for idx, d in enumerate(dcv): - if da_client is not None: - da_client.submit( - lambda dd: dd.update(tau=cur_tau, scale=scal_best[idx]), d - ) - else: - d.update(tau=cur_tau, scale=scal_best[idx]) - logger.debug( - f"Updating AR parameters for all cells: tau:{tau}, ar_scal: {ar_scal}" - ) - else: - theta = np.empty((ncell, p)) - tau = np.empty((ncell, p)) - for icell, (y, s) in enumerate(zip(Y, S_ar)): - cur_tau, ps, ar_scal, h, h_fit = updateAR( - y, - s, - scal_best[icell], - N=p, - h_len=ar_kn_len, - norm=ar_norm, - up_factor=up_factor, - ) - if dashboard is not None: - dashboard.update(uid=icell, h=h, h_fit=h_fit) - tau[icell, :] = cur_tau - if da_client is not None: - da_client.submit( - lambda dd: dd.update(tau=cur_tau, scale=scal_best[icell]), - dcv[icell], - ) - else: - dcv[icell].update(tau=cur_tau, scale=scal_best[icell]) - logger.debug( - f"Updating AR parameters for cell {icell}: tau:{tau}, ar_scal: {ar_scal}" - ) - # 2.4 check convergence - metric_prev = metric_df[metric_df["iter"] < i_iter].dropna( - subset=["obj", "scale"] - ) - metric_last = metric_df[metric_df["iter"] == i_iter - 1].dropna( - subset=["obj", "scale"] - ) - if len(metric_prev) > 0: - err_cur = cur_metric.set_index("cell")["obj"] - err_last = metric_last.set_index("cell")["obj"] - err_best = metric_prev.groupby("cell")["obj"].min() - # converged by err - if (np.abs(err_cur - err_last) < err_atol).all(): - logger.info("Converged: absolute error tolerance reached") - break - # converged by relative err - if (np.abs(err_cur - err_last) < err_rtol * err_best).all(): - logger.info("Converged: relative error tolerance reached") - break - # converged by s - S_best = np.empty((ncell, T * up_factor)) - for uid, udf in metric_prev.groupby("cell"): - best_iter = udf.set_index("iter")["obj"].idxmin() - S_best[uid, :] = S_ls[best_iter][uid, :] - if np.abs(S - S_best).sum() < 1: - logger.info("Converged: spike pattern stabilized") - break - # trapped - err_all = metric_prev.pivot(columns="iter", index="cell", values="obj") - diff_all = np.abs(err_cur.values.reshape((-1, 1)) - err_all.values) - if (diff_all.min(axis=1) < err_atol).all(): - logger.warning("Solution trapped in local optimal err") - break - # trapped by s - diff_all = np.array([np.abs(S - prev_s).sum() for prev_s in S_ls[:-1]]) - if (diff_all < 1).sum() > 1: - logger.warning("Solution trapped in local optimal s") - break - else: - logger.warning("Max iteration reached without convergence") - # Compute final results - opt_C, opt_S = np.empty((ncell, T * up_factor)), np.empty((ncell, T * up_factor)) - mobj = metric_df.groupby("iter")["obj"].median() - opt_idx_all = mobj.idxmin() - for icell in range(ncell): - if ar_use_all: - opt_idx = opt_idx_all - else: - opt_idx = metric_df.loc[ - metric_df[metric_df["cell"] == icell]["obj"].idxmin(), "iter" - ] - opt_idx = -1 - opt_C[icell, :] = C_ls[opt_idx][icell, :] - opt_S[icell, :] = S_ls[opt_idx][icell, :] - C_ls.append(opt_C) - S_ls.append(opt_S) - if dashboard is not None: - dashboard.stop() - logger.info("Pipeline completed successfully") - if return_iter: - return opt_C, opt_S, metric_df, C_ls, S_ls, h_ls, h_fit_ls - else: - return opt_C, opt_S, metric_df + + +# Keep legacy name available for explicit imports +pipeline_bin_legacy = pipeline_bin diff --git a/src/indeca/pipeline/preprocess.py b/src/indeca/pipeline/preprocess.py new file mode 100644 index 0000000..a088a5c --- /dev/null +++ b/src/indeca/pipeline/preprocess.py @@ -0,0 +1,56 @@ +"""Preprocessing functions for the binary pursuit pipeline. + +These are pure functions that transform input traces before deconvolution. +""" + +from typing import Optional, Union, Literal + +import numpy as np +from scipy.signal import medfilt + +from indeca.utils.utils import compute_dff + + +def preprocess_traces( + Y: np.ndarray, + *, + med_wnd: Optional[Union[int, Literal["auto"]]] = None, + dff: bool = True, + ar_kn_len: int = 100, +) -> np.ndarray: + """Preprocess fluorescence traces. + + This function applies median filtering and/or dF/F normalization + to the input traces. The input array is modified in place for + efficiency (matching the original pipeline behavior). + + Parameters + ---------- + Y : np.ndarray + Input fluorescence traces, shape (ncell, T) + med_wnd : int, "auto", or None + Window size for median filtering. If "auto", uses ar_kn_len. + If None, skips median filtering. + dff : bool + Whether to apply dF/F normalization. + ar_kn_len : int + AR kernel length, used for window sizing. + + Returns + ------- + np.ndarray + Preprocessed traces, shape (ncell, T). + Note: This may be the same array as Y (modified in place). + """ + # Median filtering + if med_wnd is not None: + actual_wnd = ar_kn_len if med_wnd == "auto" else med_wnd + for iy, y in enumerate(Y): + Y[iy, :] = y - medfilt(y, actual_wnd * 2 + 1) + + # dF/F normalization + if dff: + for iy, y in enumerate(Y): + Y[iy, :] = compute_dff(y, window_size=ar_kn_len * 5, q=0.2) + + return Y diff --git a/src/indeca/pipeline/types.py b/src/indeca/pipeline/types.py new file mode 100644 index 0000000..a3e07ec --- /dev/null +++ b/src/indeca/pipeline/types.py @@ -0,0 +1,153 @@ +"""Shared type definitions for the binary pursuit pipeline. + +These types define the data structures passed between pipeline steps, +making the data flow explicit and typed. +""" + +from dataclasses import dataclass +from typing import List, Optional + +import numpy as np +import pandas as pd + + +@dataclass +class ARParams: + """AR model parameters for all cells. + + Attributes: + theta: AR coefficients, shape (ncell, p) + tau: Time constants (tau_d, tau_r), shape (ncell, 2) + ps: Peak coefficients, shape (ncell, p) + """ + + theta: np.ndarray + tau: np.ndarray + ps: np.ndarray + + +@dataclass +class DeconvStepResult: + """Result of a single deconvolution step. + + Attributes: + S: Spike train, shape (ncell, T * up_factor) + C: Calcium trace, shape (ncell, T * up_factor) + scale: Scale factors, shape (ncell,) + err: Absolute errors, shape (ncell,) + err_rel: Relative errors, shape (ncell,) + nnz: Non-zero counts, shape (ncell,) + penal: Penalty values, shape (ncell,) + """ + + S: np.ndarray + C: np.ndarray + scale: np.ndarray + err: np.ndarray + err_rel: np.ndarray + nnz: np.ndarray + penal: np.ndarray + + +@dataclass +class ARUpdateResult: + """Result of AR parameter update step. + + Attributes: + tau: Updated time constants, shape (ncell, 2) or (1, 2) if use_all + ps: Updated peak coefficients + ar_scal: AR scale factor + h: Estimated impulse response + h_fit: Fitted impulse response + """ + + tau: np.ndarray + ps: np.ndarray + ar_scal: float + h: np.ndarray + h_fit: np.ndarray + + +@dataclass +class ConvergenceResult: + """Result of convergence check. + + Attributes: + converged: Whether convergence criteria are met + reason: Human-readable reason for convergence/non-convergence + """ + + converged: bool + reason: str + + +@dataclass +class IterationState: + """State accumulated across iterations. + + Attributes: + C_ls: List of calcium traces per iteration + S_ls: List of spike trains per iteration + scal_ls: List of scale factors per iteration + h_ls: List of impulse responses per iteration + h_fit_ls: List of fitted impulse responses per iteration + metric_df: DataFrame with per-iteration metrics + """ + + C_ls: List[np.ndarray] + S_ls: List[np.ndarray] + scal_ls: List[np.ndarray] + h_ls: List[np.ndarray] + h_fit_ls: List[np.ndarray] + metric_df: pd.DataFrame + + @classmethod + def empty(cls, T: int, up_factor: int) -> "IterationState": + """Create an empty iteration state.""" + return cls( + C_ls=[], + S_ls=[], + scal_ls=[], + h_ls=[], + h_fit_ls=[], + metric_df=pd.DataFrame( + columns=[ + "iter", + "cell", + "g0", + "g1", + "tau_d", + "tau_r", + "err", + "err_rel", + "nnz", + "scale", + "best_idx", + "obj", + "wgt_len", + ] + ), + ) + + +@dataclass +class PipelineResult: + """Final result of the pipeline. + + Attributes: + opt_C: Optimal calcium traces, shape (ncell, T * up_factor) + opt_S: Optimal spike trains, shape (ncell, T * up_factor) + metric_df: DataFrame with all iteration metrics + C_ls: List of calcium traces per iteration (if return_iter=True) + S_ls: List of spike trains per iteration (if return_iter=True) + h_ls: List of impulse responses per iteration (if return_iter=True) + h_fit_ls: List of fitted impulse responses per iteration (if return_iter=True) + """ + + opt_C: np.ndarray + opt_S: np.ndarray + metric_df: pd.DataFrame + C_ls: Optional[List[np.ndarray]] = None + S_ls: Optional[List[np.ndarray]] = None + h_ls: Optional[List[np.ndarray]] = None + h_fit_ls: Optional[List[np.ndarray]] = None diff --git a/src/indeca/utils/__init__.py b/src/indeca/utils/__init__.py index f737eaa..907e6c7 100644 --- a/src/indeca/utils/__init__.py +++ b/src/indeca/utils/__init__.py @@ -1 +1,2 @@ from .utils import scal_lstsq, scal_like, norm, enumerated_product +from .profiling import yappi_profile diff --git a/src/indeca/utils/profiling.py b/src/indeca/utils/profiling.py new file mode 100644 index 0000000..1eea95b --- /dev/null +++ b/src/indeca/utils/profiling.py @@ -0,0 +1,74 @@ +"""Yappi profiling utilities for pipeline-level performance analysis. + +This module provides a minimal context manager for yappi profiling, +outputting pstat-format files compatible with snakeviz visualization. + +Usage +----- +>>> from indeca.utils.profiling import yappi_profile +>>> from indeca.pipeline import pipeline_bin, DeconvPipelineConfig +>>> +>>> with yappi_profile("pipeline.prof"): +... pipeline_bin(Y, config=config, spawn_dashboard=False) +>>> +>>> # View results: snakeviz pipeline.prof +""" + +from contextlib import contextmanager +from typing import Generator + +import yappi + + +@contextmanager +def yappi_profile(outfile: str, clock: str = "wall") -> Generator[None, None, None]: + """Context manager for yappi profiling. + + Wraps code execution with yappi profiling and saves results + in pstat format for visualization with snakeviz or other tools. + + Parameters + ---------- + outfile : str + Output filename for profile stats (e.g., "pipeline.prof"). + The file will be saved in pstat format. + clock : str, optional + Clock type for timing measurements: + - "wall": Wall-clock time (real elapsed time, includes I/O and waiting) + - "cpu": CPU time (actual computation time, excludes I/O and waiting) + Default is "wall". + + Yields + ------ + None + The context manager yields nothing; profiling is automatic. + + Examples + -------- + Basic usage with wall-clock timing: + + >>> with yappi_profile("pipeline.prof"): + ... result = expensive_function() + + Using CPU time instead: + + >>> with yappi_profile("cpu_profile.prof", clock="cpu"): + ... result = expensive_function() + + Notes + ----- + View the resulting profile with: + snakeviz pipeline.prof + + The pstat format is compatible with Python's standard pstats module + and various visualization tools like snakeviz, gprof2dot, and pyprof2calltree. + """ + yappi.set_clock_type(clock) + yappi.clear_stats() + yappi.start() + try: + yield + finally: + yappi.stop() + yappi.get_func_stats().save(outfile, type="pstat") + diff --git a/tests/integration/test_deconv_masking.py b/tests/integration/test_deconv_masking.py index 5ec9cbd..ed55c57 100644 --- a/tests/integration/test_deconv_masking.py +++ b/tests/integration/test_deconv_masking.py @@ -18,10 +18,10 @@ def test_masking(self, taus, rand_seed, upsamp, eq_atol, test_fig_path_html): deconv, y, c, c_org, s, s_org, scale = fixt_deconv( taus=taus, rand_seed=rand_seed, upsamp=upsamp, deconv_kws={"Hlim": None} ) - s_nomsk, b_nomsk = deconv._solve(amp_constraint=False) + s_nomsk, b_nomsk = deconv.solve(amp_constraint=False, pks_polish=False) c_nomsk = deconv.H @ s_nomsk deconv._update_mask() - s_msk, b_msk = deconv._solve(amp_constraint=False) + s_msk, b_msk = deconv.solve(amp_constraint=False, pks_polish=False) c_msk = deconv.H @ s_msk s_msk = deconv._pad_s(s_msk) c_msk = deconv._pad_c(c_msk) diff --git a/tests/integration/test_deconv_solve.py b/tests/integration/test_deconv_solve.py index 1e50dea..47e799b 100644 --- a/tests/integration/test_deconv_solve.py +++ b/tests/integration/test_deconv_solve.py @@ -24,7 +24,7 @@ def test_solve(self, taus, rand_seed, backend, upsamp, eq_atol, test_fig_path_ht upsamp=upsamp, deconv_kws={"Hlim": None}, ) - R = deconv.R.value if backend == "cvxpy" else deconv.R + R = deconv.R s_solve, b_solve = deconv.solve(amp_constraint=False, pks_polish=True) c_solve = deconv.H @ s_solve c_solve_R = R @ c_solve diff --git a/tests/unit/test_deconv_G_matrix.py b/tests/unit/test_deconv_G_matrix.py new file mode 100644 index 0000000..08d3b7e --- /dev/null +++ b/tests/unit/test_deconv_G_matrix.py @@ -0,0 +1,57 @@ +import numpy as np + +from indeca.core.deconv import DeconvBin +from indeca.core.simulation import tau2AR + + +def test_G_matrix_matches_shifted_ar_difference_equation(): + """ + The legacy implementation constructs a (T x T) "G" operator such that: + - s = G @ c + - s[-1] == 0 (last row is zeros) + - for t >= 2: s[t] = c[t+1] - theta0*c[t] - theta1*c[t-1] + - for t == 1: s[1] = c[2] - theta0*c[1] + - for t == 0: s[0] = c[1] + + This test guards against accidental dimensional/shift regressions in `G_org`. + """ + T = 5 + theta = np.array(tau2AR(10.0, 3.0)) + + deconv = DeconvBin( + y_len=T, + theta=theta, + coef_len=3, + backend="osqp", + free_kernel=False, + use_base=False, + norm="l2", + penal=None, + ) + + # Use the full, unmasked operator for determinism. + deconv._reset_mask() + G = deconv.solver.G_org + assert G.shape == (T, T) + + # Build a c vector with the same boundary condition as the solver (c[0] == 0). + rng = np.random.default_rng(0) + c = rng.normal(size=T) + c[0] = 0.0 + + # `scipy.sparse_matrix @ np.ndarray` returns a dense np.ndarray (no `.todense()`). + s = np.asarray(G @ c.reshape(-1, 1)).squeeze() + + # Last element must be exactly 0 due to bottom row of zeros. + assert np.isclose(s[-1], 0.0) + + # Check the shifted AR-difference mapping on the first T-1 entries. + th0, th1 = float(theta[0]), float(theta[1]) + expected = np.zeros(T) + expected[0] = c[1] + expected[1] = c[2] - th0 * c[1] + expected[2] = c[3] - th0 * c[2] - th1 * c[1] + expected[3] = c[4] - th0 * c[3] - th1 * c[2] + expected[4] = 0.0 + + assert np.allclose(s, expected)